/* * 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 #include 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(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(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(g_bridgeReadBuf), static_cast(readSize)}; } int HdcBridge::WriteClient(int fd, SerializedBuffer buf) { uint8_t* ptr = reinterpret_cast(buf.ptr); size_t size = static_cast(buf.size); int cnt = static_cast(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(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(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(0), static_cast(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; } }