6d95450f创建于 2024年5月23日历史提交
/*

 * Copyright (C) 2024 Huawei Device Co., Ltd.

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 *     http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */



#include "bridge.h"

#include "log.h"

#include "sys_para.h"

#include "base.h"



#include <unistd.h>

#include <fcntl.h>

namespace Hdc {

static uint8_t *g_bridgeReadBuf = nullptr;

static constexpr char BRIDGE_FILE_PATH[20] = "/dev/express_bridge";



HdcBridge::HdcBridge()

{

    string strBridgePort;

    GetDevItem("persist.hdc.port", strBridgePort);

    WRITE_LOG(LOG_INFO, "strBridgePort:%s", strBridgePort.c_str());

    bridgeListenPort = atoi(strBridgePort.c_str());

    if (bridgeListenPort <= 0) {

        bridgeListenPort = 0;

    }

    WRITE_LOG(LOG_INFO, "bridgeListenPort:%d", bridgeListenPort);

}



HdcBridge::~HdcBridge()

{

}



int HdcBridge::StartListen()

{

    bridgeFd = open(BRIDGE_FILE_PATH, O_RDWR);

    WRITE_LOG(LOG_INFO, "StartListen bridgeFd:%d", bridgeFd);

    if (bridgeFd <= 0) {

        WRITE_LOG(LOG_FATAL, "SetBridgeListen open failed");

        return -1;

    }

    int ret = ioctl(bridgeFd, IOC_BIND, static_cast<unsigned long>(bridgeListenPort));

    WRITE_LOG(LOG_INFO, "StartListen ioctl ret:%d", ret);

    if (ret < 0) {

        WRITE_LOG(LOG_FATAL, "SetBridgeListen IOC_BIND failed");

        return -1;

    }

    return bridgeFd;

}



int HdcBridge::HandleClient(int socketFd)

{

    int newClientFd = open(BRIDGE_FILE_PATH, O_RDWR);

    WRITE_LOG(LOG_INFO, "HandleClient newClientFd:%d", newClientFd);

    if (newClientFd < 0) {

        WRITE_LOG(LOG_FATAL, "Unable to open new bridge connection err %d", errno);

        return -1;

    }

    errno = 0;

    int ret = ioctl(newClientFd, IOC_CONNECT, static_cast<unsigned long>(socketFd));

    if (ret < 0) {

        WRITE_LOG(LOG_FATAL, "Unable to ioctl new bridge err %d", errno);

        close(newClientFd);

        return -1;

    }

    return newClientFd;

}



int HdcBridge::ReadPipeFd(int fd, char* buf, int size)

{

    WRITE_LOG(LOG_INFO, "ReadPipeFd start");

    return read(fd, buf, size);

}



PersistBuffer HdcBridge::ReadClient(int fd, int size)

{

    if (g_bridgeReadBuf == nullptr) {

        WRITE_LOG(LOG_DEBUG, "remalloc g_bridgeReadBuf");

        g_bridgeReadBuf = new uint8_t[MAX_SIZE_IOBUF];

    }

    int readSize = read(fd, g_bridgeReadBuf, size);

    return PersistBuffer{reinterpret_cast<char *>(g_bridgeReadBuf), static_cast<uint64_t>(readSize)};

}



int HdcBridge::WriteClient(int fd, SerializedBuffer buf)

{

    uint8_t* ptr = reinterpret_cast<uint8_t *>(buf.ptr);

    size_t size = static_cast<size_t>(buf.size);

    int cnt = static_cast<int>(size);

    constexpr int intrmax = 1000;

    int intrcnt = 0;

    while (cnt > 0) {

        int rc = write(fd, ptr, cnt);

        if (rc < 0) {

            int err = errno;

            if (err != EINTR && err != EAGAIN) {

                WRITE_LOG(LOG_FATAL, "WriteClient fd:%d send rc:%d err:%d", fd, rc, err);

                cnt = -1;

                break;

            }

            if (++intrcnt > intrmax) {

                WRITE_LOG(LOG_WARN, "WriteClient fd:%d send interrupt err:%d", fd, err);

                intrcnt = 0;

            }

            continue;

        }

        ptr += rc;

        cnt -= rc;

    }

    return cnt == 0 ? static_cast<int>(size) : cnt;

}



void HdcBridge::Stop()

{

    if (bridgeFd > 0) {

        close(bridgeFd);

        bridgeFd = -1;

    }



    if (g_bridgeReadBuf != nullptr) {

        delete[] g_bridgeReadBuf;

        g_bridgeReadBuf = nullptr;

    }

}



extern "C" void* InitBridge()

{

    HdcBridge* instance = new HdcBridge();

    return instance;

}



extern "C" int StartListen(void* ptr)

{

    HdcBridge* bridge = (HdcBridge*)ptr;

    if (bridge == nullptr) {

        return -1;

    }

    return bridge->StartListen();

}



extern "C" int AcceptServerSocketFd(void* ptr, int pipeFd)

{

    WRITE_LOG(LOG_INFO, "AcceptServerSocketFd start, pipeFd:%d", pipeFd);

    HdcBridge* bridge = (HdcBridge*)ptr;

    if (bridge == nullptr) {

        return -1;

    }

    char socketFdBuf[4] = { 0 };

    int ret = bridge->ReadPipeFd(pipeFd, socketFdBuf, 4);

    WRITE_LOG(LOG_INFO, "AcceptServerSocketFd get socketfd buf size:%d", ret);

    if (ret < 0) {

        WRITE_LOG(LOG_INFO, "AcceptServerSocketFd get socket fd fail");

        return -1;

    }

    int socketFd = *reinterpret_cast<int*>(socketFdBuf);

    WRITE_LOG(LOG_INFO, "AcceptServerSocketFd get socketfd:%d", socketFd);

    return socketFd;

}



extern "C" int InitClientFd(void* ptr, int socketFd)

{

    HdcBridge* bridge = (HdcBridge*)ptr;

    if (bridge == nullptr) {

        return -1;

    }

    return bridge->HandleClient(socketFd);

}



extern "C" PersistBuffer ReadClient(void* ptr, int fd, int size)

{

    HdcBridge* bridge = (HdcBridge*)ptr;

    if (bridge == nullptr) {

        return PersistBuffer{reinterpret_cast<char *>(0), static_cast<uint64_t>(0)};

    }

    return bridge->ReadClient(fd, size);

}



extern "C" int WriteClient(void* ptr, int fd, SerializedBuffer buf)

{

    HdcBridge* bridge = (HdcBridge*)ptr;

    if (bridge == nullptr) {

        return -1;

    }

    return bridge->WriteClient(fd, buf);

}



extern "C" int Stop(void* ptr)

{

    HdcBridge* bridge = (HdcBridge*)ptr;

    if (bridge == nullptr) {

        return -1;

    }

    bridge->Stop();

    return 0;

}

}