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 CALLSTAT_GUARD(ptrConnect->loopMainStatus, uvpipe->loop, "HdcDaemonBridge::AcceptClient"); 68 const uint16_t maxWaitTime = UV_DEFAULT_INTERVAL; 69 int newPort = *(int *)buf->base; 70 int newClientFd; 71 int ret = 0; 72 if (nread != SOCKET_FD_LEN) { 73 WRITE_LOG(LOG_FATAL, "AcceptClient err nread %d", nread); 74 return; 75 } 76 auto ctrl = ptrConnect->BuildCtrlString(SP_START_SESSION, 0, nullptr, 0); 77 HSession hSession = ptrConnect->MallocSession(false, CONN_TCP, thisClass); 78 if (!hSession) { 79 goto freeBuf; 80 } 81 82 newClientFd = open("/dev/express_bridge", O_RDWR | O_NONBLOCK); 83 if (newClientFd < 0) { 84 WRITE_LOG(LOG_FATAL, "Unable to open new bridge connection err %d", errno); 85 goto freeSession; 86 } 87 ret = ioctl(newClientFd, IOC_CONNECT, static_cast<unsigned long>(newPort)); 88 if (ret < 0) { 89 WRITE_LOG(LOG_FATAL, "Unable to ioctl new bridge err %d", errno); 90 goto freeFd; 91 } 92 hSession->fdChildWorkTCP = (uv_os_sock_t)newClientFd; 93 Base::StartWorkThread(ptrLoop, ptrConnect->SessionWorkThread, Base::FinishWorkThread, hSession); 94 // wait for thread up 95 while (hSession->childLoop.active_handles == 0) { 96 WRITE_LOG(LOG_DEBUG, "wait for thread up"); 97 usleep(maxWaitTime); 98 } 99 Base::SendToPollFd(hSession->ctrlFd[STREAM_MAIN], ctrl.data(), ctrl.size()); 100 goto freeBuf; 101 102 freeFd: 103 close(newClientFd); 104 freeSession: 105 ptrConnect->FreeSession(hSession->sessionId); 106 freeBuf: 107 delete[] buf->base; 108 return; 109 } 110 111 // Set the daemon-side TCP listening SetBridgeListen()112 int HdcDaemonBridge::SetBridgeListen() 113 { 114 // tcp listen 115 HdcSessionBase *ptrConnect = (HdcSessionBase *)clsMainBase; 116 servPipe.data = this; 117 int bridgeFd = open("/dev/express_bridge", O_RDWR | O_NONBLOCK); 118 if (bridgeFd <= 0) { 119 WRITE_LOG(LOG_FATAL, "SetBridgeListen open failed"); 120 return ERR_FILE_OPEN; 121 } 122 int ret = ioctl(bridgeFd, IOC_BIND, (unsigned long)bridgeListenPort); 123 if (ret < 0) { 124 WRITE_LOG(LOG_FATAL, "SetBridgeListen IOC_BIND failed"); 125 close(bridgeFd); 126 return ERR_API_FAIL; 127 } 128 129 uv_pipe_init(&ptrConnect->loopMain, &servPipe, 0); 130 uv_pipe_open(&servPipe, (uv_file)bridgeFd); 131 uv_read_start((uv_stream_t *)&servPipe, HdcDaemonBridge::AllocBufferCallback, HdcDaemonBridge::AcceptClient); 132 133 return RET_SUCCESS; 134 } 135 Initial()136 int HdcDaemonBridge::Initial() 137 { 138 WRITE_LOG(LOG_DEBUG, "HdcDaemonBridge init"); 139 if (SetBridgeListen() != RET_SUCCESS) { 140 WRITE_LOG(LOG_FATAL, "Bridge listen failed"); 141 return ERR_GENERIC; 142 } 143 #ifndef UNIT_TEST 144 WRITE_LOG(LOG_INFO, "Bridge listen on port:[%d]", bridgeListenPort); 145 #endif 146 return RET_SUCCESS; 147 } 148 } // namespace Hdc 149