xref: /developtools/hdc/hdc_rust/src/cffi/bridge.cpp (revision cc290419)
1/*
2 * Copyright (C) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "bridge.h"
17#include "log.h"
18#include "sys_para.h"
19#include "base.h"
20
21#include <unistd.h>
22#include <fcntl.h>
23namespace Hdc {
24static uint8_t *g_bridgeReadBuf = nullptr;
25static constexpr char BRIDGE_FILE_PATH[20] = "/dev/express_bridge";
26
27HdcBridge::HdcBridge()
28{
29    string strBridgePort;
30    GetDevItem("persist.hdc.port", strBridgePort);
31    WRITE_LOG(LOG_INFO, "strBridgePort:%s", strBridgePort.c_str());
32    bridgeListenPort = atoi(strBridgePort.c_str());
33    if (bridgeListenPort <= 0) {
34        bridgeListenPort = 0;
35    }
36    WRITE_LOG(LOG_INFO, "bridgeListenPort:%d", bridgeListenPort);
37}
38
39HdcBridge::~HdcBridge()
40{
41}
42
43int HdcBridge::StartListen()
44{
45    bridgeFd = open(BRIDGE_FILE_PATH, O_RDWR);
46    WRITE_LOG(LOG_INFO, "StartListen bridgeFd:%d", bridgeFd);
47    if (bridgeFd <= 0) {
48        WRITE_LOG(LOG_FATAL, "SetBridgeListen open failed");
49        return -1;
50    }
51    int ret = ioctl(bridgeFd, IOC_BIND, static_cast<unsigned long>(bridgeListenPort));
52    WRITE_LOG(LOG_INFO, "StartListen ioctl ret:%d", ret);
53    if (ret < 0) {
54        WRITE_LOG(LOG_FATAL, "SetBridgeListen IOC_BIND failed");
55        return -1;
56    }
57    return bridgeFd;
58}
59
60int HdcBridge::HandleClient(int socketFd)
61{
62    int newClientFd = open(BRIDGE_FILE_PATH, O_RDWR);
63    WRITE_LOG(LOG_INFO, "HandleClient newClientFd:%d", newClientFd);
64    if (newClientFd < 0) {
65        WRITE_LOG(LOG_FATAL, "Unable to open new bridge connection err %d", errno);
66        return -1;
67    }
68    errno = 0;
69    int ret = ioctl(newClientFd, IOC_CONNECT, static_cast<unsigned long>(socketFd));
70    if (ret < 0) {
71        WRITE_LOG(LOG_FATAL, "Unable to ioctl new bridge err %d", errno);
72        close(newClientFd);
73        return -1;
74    }
75    return newClientFd;
76}
77
78int HdcBridge::ReadPipeFd(int fd, char* buf, int size)
79{
80    WRITE_LOG(LOG_INFO, "ReadPipeFd start");
81    return read(fd, buf, size);
82}
83
84PersistBuffer HdcBridge::ReadClient(int fd, int size)
85{
86    if (g_bridgeReadBuf == nullptr) {
87        WRITE_LOG(LOG_DEBUG, "remalloc g_bridgeReadBuf");
88        g_bridgeReadBuf = new uint8_t[MAX_SIZE_IOBUF];
89    }
90    int readSize = read(fd, g_bridgeReadBuf, size);
91    return PersistBuffer{reinterpret_cast<char *>(g_bridgeReadBuf), static_cast<uint64_t>(readSize)};
92}
93
94int HdcBridge::WriteClient(int fd, SerializedBuffer buf)
95{
96    uint8_t* ptr = reinterpret_cast<uint8_t *>(buf.ptr);
97    size_t size = static_cast<size_t>(buf.size);
98    int cnt = static_cast<int>(size);
99    constexpr int intrmax = 1000;
100    int intrcnt = 0;
101    while (cnt > 0) {
102        int rc = write(fd, ptr, cnt);
103        if (rc < 0) {
104            int err = errno;
105            if (err != EINTR && err != EAGAIN) {
106                WRITE_LOG(LOG_FATAL, "WriteClient fd:%d send rc:%d err:%d", fd, rc, err);
107                cnt = -1;
108                break;
109            }
110            if (++intrcnt > intrmax) {
111                WRITE_LOG(LOG_WARN, "WriteClient fd:%d send interrupt err:%d", fd, err);
112                intrcnt = 0;
113            }
114            continue;
115        }
116        ptr += rc;
117        cnt -= rc;
118    }
119    return cnt == 0 ? static_cast<int>(size) : cnt;
120}
121
122void HdcBridge::Stop()
123{
124    if (bridgeFd > 0) {
125        close(bridgeFd);
126        bridgeFd = -1;
127    }
128
129    if (g_bridgeReadBuf != nullptr) {
130        delete[] g_bridgeReadBuf;
131        g_bridgeReadBuf = nullptr;
132    }
133}
134
135extern "C" void* InitBridge()
136{
137    HdcBridge* instance = new HdcBridge();
138    return instance;
139}
140
141extern "C" int StartListen(void* ptr)
142{
143    HdcBridge* bridge = (HdcBridge*)ptr;
144    if (bridge == nullptr) {
145        return -1;
146    }
147    return bridge->StartListen();
148}
149
150extern "C" int AcceptServerSocketFd(void* ptr, int pipeFd)
151{
152    WRITE_LOG(LOG_INFO, "AcceptServerSocketFd start, pipeFd:%d", pipeFd);
153    HdcBridge* bridge = (HdcBridge*)ptr;
154    if (bridge == nullptr) {
155        return -1;
156    }
157    char socketFdBuf[4] = { 0 };
158    int ret = bridge->ReadPipeFd(pipeFd, socketFdBuf, 4);
159    WRITE_LOG(LOG_INFO, "AcceptServerSocketFd get socketfd buf size:%d", ret);
160    if (ret < 0) {
161        WRITE_LOG(LOG_INFO, "AcceptServerSocketFd get socket fd fail");
162        return -1;
163    }
164    int socketFd = *reinterpret_cast<int*>(socketFdBuf);
165    WRITE_LOG(LOG_INFO, "AcceptServerSocketFd get socketfd:%d", socketFd);
166    return socketFd;
167}
168
169extern "C" int InitClientFd(void* ptr, int socketFd)
170{
171    HdcBridge* bridge = (HdcBridge*)ptr;
172    if (bridge == nullptr) {
173        return -1;
174    }
175    return bridge->HandleClient(socketFd);
176}
177
178extern "C" PersistBuffer ReadClient(void* ptr, int fd, int size)
179{
180    HdcBridge* bridge = (HdcBridge*)ptr;
181    if (bridge == nullptr) {
182        return PersistBuffer{reinterpret_cast<char *>(0), static_cast<uint64_t>(0)};
183    }
184    return bridge->ReadClient(fd, size);
185}
186
187extern "C" int WriteClient(void* ptr, int fd, SerializedBuffer buf)
188{
189    HdcBridge* bridge = (HdcBridge*)ptr;
190    if (bridge == nullptr) {
191        return -1;
192    }
193    return bridge->WriteClient(fd, buf);
194}
195
196extern "C" int Stop(void* ptr)
197{
198    HdcBridge* bridge = (HdcBridge*)ptr;
199    if (bridge == nullptr) {
200        return -1;
201    }
202    bridge->Stop();
203    return 0;
204}
205}
206
207