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