1cc290419Sopenharmony_ci/*
2cc290419Sopenharmony_ci * Copyright (C) 2021 Huawei Device Co., Ltd.
3cc290419Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4cc290419Sopenharmony_ci * you may not use this file except in compliance with the License.
5cc290419Sopenharmony_ci * You may obtain a copy of the License at
6cc290419Sopenharmony_ci *
7cc290419Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8cc290419Sopenharmony_ci *
9cc290419Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10cc290419Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11cc290419Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12cc290419Sopenharmony_ci * See the License for the specific language governing permissions and
13cc290419Sopenharmony_ci * limitations under the License.
14cc290419Sopenharmony_ci */
15cc290419Sopenharmony_ci#include "daemon_bridge.h"
16cc290419Sopenharmony_ci#include <cstdlib>
17cc290419Sopenharmony_ci#include "arpa/inet.h"
18cc290419Sopenharmony_ci#include "netinet/in.h"
19cc290419Sopenharmony_ci#include "new"
20cc290419Sopenharmony_ci#include "sys/socket.h"
21cc290419Sopenharmony_ci#include "system_depend.h"
22cc290419Sopenharmony_ci#include "unistd.h"
23cc290419Sopenharmony_ci#include "common.h"
24cc290419Sopenharmony_ci#include "session.h"
25cc290419Sopenharmony_ci#include "uv-common.h"
26cc290419Sopenharmony_ci
27cc290419Sopenharmony_cinamespace Hdc {
28cc290419Sopenharmony_ci    HdcDaemonBridge::HdcDaemonBridge(const bool serverOrDaemonIn, void *ptrMainBase)
29cc290419Sopenharmony_ci        : HdcTCPBase(serverOrDaemonIn, ptrMainBase)
30cc290419Sopenharmony_ci    {
31cc290419Sopenharmony_ci        // If the listening value for the property setting is obtained, it will be 0 randomly assigned.
32cc290419Sopenharmony_ci        string strBridgePort;
33cc290419Sopenharmony_ci        SystemDepend::GetDevItem("persist.hdc.port", strBridgePort);
34cc290419Sopenharmony_ci        bridgeListenPort = atoi(strBridgePort.c_str());
35cc290419Sopenharmony_ci        if (bridgeListenPort <= 0) {
36cc290419Sopenharmony_ci            bridgeListenPort = 0;
37cc290419Sopenharmony_ci        }
38cc290419Sopenharmony_ci#ifdef HDC_DEBUG
39cc290419Sopenharmony_ci        const uint16_t DEBUG_TCP_PORT = 10178;
40cc290419Sopenharmony_ci        bridgeListenPort = DEBUG_TCP_PORT;
41cc290419Sopenharmony_ci#endif
42cc290419Sopenharmony_ci    }
43cc290419Sopenharmony_ci
44cc290419Sopenharmony_ci    HdcDaemonBridge::~HdcDaemonBridge()
45cc290419Sopenharmony_ci    {
46cc290419Sopenharmony_ci    }
47cc290419Sopenharmony_ci
48cc290419Sopenharmony_ci    void HdcDaemonBridge::Stop()
49cc290419Sopenharmony_ci    {
50cc290419Sopenharmony_ci        Base::TryCloseHandle((const uv_handle_t *)&servPipe);
51cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "~HdcDaemonBridge");
52cc290419Sopenharmony_ci    }
53cc290419Sopenharmony_ci
54cc290419Sopenharmony_ci    void HdcDaemonBridge::AllocBufferCallback(uv_handle_t *handle, size_t sizeSuggested, uv_buf_t *buf)
55cc290419Sopenharmony_ci    {
56cc290419Sopenharmony_ci        buf->base = (char *)new int[1];
57cc290419Sopenharmony_ci        buf->len = SOCKET_FD_LEN;
58cc290419Sopenharmony_ci    }
59cc290419Sopenharmony_ci
60cc290419Sopenharmony_ci    void HdcDaemonBridge::AcceptClient(uv_stream_t *uvpipe, ssize_t nread, const uv_buf_t *buf)
61cc290419Sopenharmony_ci    {
62cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "Accept New Client");
63cc290419Sopenharmony_ci        uv_loop_t *ptrLoop = uvpipe->loop;
64cc290419Sopenharmony_ci        uv_tcp_t *pServBridge = (uv_tcp_t *)uvpipe;
65cc290419Sopenharmony_ci        HdcDaemonBridge *thisClass = (HdcDaemonBridge *)pServBridge->data;
66cc290419Sopenharmony_ci        HdcSessionBase *ptrConnect = reinterpret_cast<HdcSessionBase *>(thisClass->clsMainBase);
67cc290419Sopenharmony_ci        const uint16_t maxWaitTime = UV_DEFAULT_INTERVAL;
68cc290419Sopenharmony_ci        int newPort = *(int *)buf->base;
69cc290419Sopenharmony_ci        int newClientFd;
70cc290419Sopenharmony_ci        int ret = 0;
71cc290419Sopenharmony_ci        if (nread != SOCKET_FD_LEN) {
72cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "AcceptClient err nread %d", nread);
73cc290419Sopenharmony_ci            return;
74cc290419Sopenharmony_ci        }
75cc290419Sopenharmony_ci        auto ctrl = ptrConnect->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0);
76cc290419Sopenharmony_ci        HSession hSession = ptrConnect->MallocSession(false, CONN_TCP, thisClass);
77cc290419Sopenharmony_ci        if (!hSession) {
78cc290419Sopenharmony_ci            goto freeBuf;
79cc290419Sopenharmony_ci        }
80cc290419Sopenharmony_ci
81cc290419Sopenharmony_ci        newClientFd = open("/dev/express_bridge", O_RDWR | O_NONBLOCK);
82cc290419Sopenharmony_ci        if (newClientFd < 0) {
83cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "Unable to open new bridge connection err %d", errno);
84cc290419Sopenharmony_ci            goto freeSession;
85cc290419Sopenharmony_ci        }
86cc290419Sopenharmony_ci        ret = ioctl(newClientFd, IOC_CONNECT, static_cast<unsigned long>(newPort));
87cc290419Sopenharmony_ci        if (ret < 0) {
88cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "Unable to ioctl new bridge err %d", errno);
89cc290419Sopenharmony_ci            goto freeFd;
90cc290419Sopenharmony_ci        }
91cc290419Sopenharmony_ci        hSession->fdChildWorkTCP = (uv_os_sock_t)newClientFd;
92cc290419Sopenharmony_ci        Base::StartWorkThread(ptrLoop, ptrConnect->SessionWorkThread, Base::FinishWorkThread, hSession);
93cc290419Sopenharmony_ci        // wait for thread up
94cc290419Sopenharmony_ci        while (hSession->childLoop.active_handles == 0) {
95cc290419Sopenharmony_ci            WRITE_LOG(LOG_DEBUG, "wait for thread up");
96cc290419Sopenharmony_ci            usleep(maxWaitTime);
97cc290419Sopenharmony_ci        }
98cc290419Sopenharmony_ci        Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrl.data(), ctrl.size());
99cc290419Sopenharmony_ci        goto freeBuf;
100cc290419Sopenharmony_ci
101cc290419Sopenharmony_ci    freeFd:
102cc290419Sopenharmony_ci        close(newClientFd);
103cc290419Sopenharmony_ci    freeSession:
104cc290419Sopenharmony_ci        ptrConnect->FreeSession(hSession->sessionId);
105cc290419Sopenharmony_ci    freeBuf:
106cc290419Sopenharmony_ci        delete[] buf->base;
107cc290419Sopenharmony_ci        return;
108cc290419Sopenharmony_ci    }
109cc290419Sopenharmony_ci
110cc290419Sopenharmony_ci    // Set the daemon-side TCP listening
111cc290419Sopenharmony_ci    int HdcDaemonBridge::SetBridgeListen()
112cc290419Sopenharmony_ci    {
113cc290419Sopenharmony_ci        // tcp listen
114cc290419Sopenharmony_ci        HdcSessionBase *ptrConnect = (HdcSessionBase *)clsMainBase;
115cc290419Sopenharmony_ci        servPipe.data = this;
116cc290419Sopenharmony_ci        int bridgeFd = open("/dev/express_bridge", O_RDWR | O_NONBLOCK);
117cc290419Sopenharmony_ci        if (bridgeFd <= 0) {
118cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "SetBridgeListen open failed");
119cc290419Sopenharmony_ci            return ERR_FILE_OPEN;
120cc290419Sopenharmony_ci        }
121cc290419Sopenharmony_ci        int ret = ioctl(bridgeFd, IOC_BIND, (unsigned long)bridgeListenPort);
122cc290419Sopenharmony_ci        if (ret < 0) {
123cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "SetBridgeListen IOC_BIND failed");
124cc290419Sopenharmony_ci            close(bridgeFd);
125cc290419Sopenharmony_ci            return ERR_API_FAIL;
126cc290419Sopenharmony_ci        }
127cc290419Sopenharmony_ci
128cc290419Sopenharmony_ci        uv_pipe_init(&ptrConnect->loopMain, &servPipe, 0);
129cc290419Sopenharmony_ci        uv_pipe_open(&servPipe, (uv_file)bridgeFd);
130cc290419Sopenharmony_ci        uv_read_start((uv_stream_t *)&servPipe, HdcDaemonBridge::AllocBufferCallback, HdcDaemonBridge::AcceptClient);
131cc290419Sopenharmony_ci
132cc290419Sopenharmony_ci        return RET_SUCCESS;
133cc290419Sopenharmony_ci    }
134cc290419Sopenharmony_ci
135cc290419Sopenharmony_ci    int HdcDaemonBridge::Initial()
136cc290419Sopenharmony_ci    {
137cc290419Sopenharmony_ci        WRITE_LOG(LOG_DEBUG, "HdcDaemonBridge init");
138cc290419Sopenharmony_ci        if (SetBridgeListen() != RET_SUCCESS) {
139cc290419Sopenharmony_ci            WRITE_LOG(LOG_FATAL, "Bridge listen failed");
140cc290419Sopenharmony_ci            return ERR_GENERIC;
141cc290419Sopenharmony_ci        }
142cc290419Sopenharmony_ci#ifndef UNIT_TEST
143cc290419Sopenharmony_ci        WRITE_LOG(LOG_INFO, "Bridge listen on port:[%d]", bridgeListenPort);
144cc290419Sopenharmony_ci#endif
145cc290419Sopenharmony_ci        return RET_SUCCESS;
146cc290419Sopenharmony_ci    }
147cc290419Sopenharmony_ci} // namespace Hdc
148