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 #ifndef HDC_SESSION_H 16 #define HDC_SESSION_H 17 #include <shared_mutex> 18 #include <sstream> 19 #include "common.h" 20 #include "uv_status.h" 21 22 namespace Hdc { 23 enum TaskType { TYPE_UNITY, TYPE_SHELL, TASK_FILE, TASK_FORWARD, TASK_APP, TASK_FLASHD }; 24 25 class HdcSessionBase { 26 public: 27 enum AuthType { AUTH_NONE, AUTH_TOKEN, AUTH_SIGNATURE, AUTH_PUBLICKEY, AUTH_OK, AUTH_FAIL, AUTH_SSL_TLS_PSK }; 28 struct SessionHandShake { 29 string banner; // must first index 30 // auth none 31 uint8_t authType; 32 uint32_t sessionId; 33 string connectKey; 34 string buf; 35 string version; ToDebugStringSessionHandShake36 std::string ToDebugString() 37 { 38 std::ostringstream oss; 39 oss << "SessionHandShake ["; 40 oss << " banner:" << banner; 41 oss << " sessionId:" << sessionId; 42 oss << " authType:" << unsigned(authType); 43 oss << " connectKey:" << Hdc::MaskString(connectKey); 44 oss << " version:" << version; 45 oss << "]"; 46 return oss.str(); 47 } 48 }; 49 50 struct CtrlStruct { 51 InnerCtrlCommand command; 52 uint32_t channelId; 53 uint8_t dataSize; 54 uint8_t data[BUF_SIZE_MICRO]; 55 }; 56 struct PayloadProtect { // reserve for encrypt and decrypt 57 uint32_t channelId; 58 uint32_t commandFlag; 59 uint8_t checkSum; // enable it will be lose about 20% speed 60 uint8_t vCode; 61 }; 62 struct HeartbeatMsg { 63 uint64_t heartbeatCount; 64 string reserved; 65 }; 66 67 HdcSessionBase(bool serverOrDaemonIn, size_t uvThreadSize = SIZE_THREAD_POOL); 68 virtual ~HdcSessionBase(); AttachChannel(HSession hSession,const uint32_t channelId)69 virtual void AttachChannel(HSession hSession, const uint32_t channelId) 70 { 71 } DeatchChannel(HSession hSession,const uint32_t channelId)72 virtual void DeatchChannel(HSession hSession, const uint32_t channelId) 73 { 74 } NotifyInstanceSessionFree(HSession hSession,bool freeOrClear)75 virtual void NotifyInstanceSessionFree(HSession hSession, bool freeOrClear) 76 { 77 } RedirectToTask(HTaskInfo hTaskInfo,HSession hSession,const uint32_t channelId,const uint16_t command,uint8_t * payload,const int payloadSize)78 virtual bool RedirectToTask(HTaskInfo hTaskInfo, HSession hSession, const uint32_t channelId, 79 const uint16_t command, uint8_t *payload, const int payloadSize) 80 { 81 return true; 82 } 83 // Thread security interface for global stop programs 84 void PostStopInstanceMessage(bool restart = false); 85 void ReMainLoopForInstanceClear(); 86 // server, Two parameters in front of call can be empty 87 void LogMsg(const uint32_t sessionId, const uint32_t channelId, MessageLevel level, const char *msg, ...); 88 static void AllocCallback(uv_handle_t *handle, size_t sizeWanted, uv_buf_t *buf); 89 static void MainAsyncCallback(uv_async_t *handle); 90 static void FinishWriteSessionTCP(uv_write_t *req, int status); 91 static void SessionWorkThread(uv_work_t *arg); 92 static void ReadCtrlFromSession(uv_poll_t *poll, int status, int events); 93 static void ReadCtrlFromMain(uv_poll_t *poll, int status, int events); 94 static void ParsePeerSupportFeatures(HSession &hSession, std::map<std::string, std::string> &tlvMap); 95 HSession QueryUSBDeviceRegister(void *pDev, uint8_t busIDIn, uint8_t devIDIn); 96 virtual HSession MallocSession(bool serverOrDaemon, const ConnType connType, void *classModule, 97 uint32_t sessionId = 0); 98 virtual void FreeSession(const uint32_t sessionId); 99 #ifdef HDC_HOST 100 void PrintAllSessionConnection(const uint32_t sessionId); 101 #endif 102 void WorkerPendding(); 103 int OnRead(HSession hSession, uint8_t *bufPtr, const int bufLen); 104 int Send(const uint32_t sessionId, const uint32_t channelId, const uint16_t commandFlag, const uint8_t *data, 105 const int dataSize); 106 int SendByProtocol(HSession hSession, uint8_t *bufPtr, const int bufLen, bool echo = false); 107 virtual HSession AdminSession(const uint8_t op, const uint32_t sessionId, HSession hInput); 108 virtual int FetchIOBuf(HSession hSession, uint8_t *ioBuf, int read); 109 #ifdef HDC_SUPPORT_ENCRYPT_TCP 110 virtual int FetchIOBuf(HSession hSession, uint8_t *ioBuf, int read, bool isEncrypted); 111 #endif 112 virtual void PushAsyncMessage(const uint32_t sessionId, const uint8_t method, const void *data, const int dataSize); 113 HTaskInfo AdminTask(const uint8_t op, HSession hSession, const uint32_t channelId, HTaskInfo hInput); 114 bool DispatchTaskData(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload, 115 int payloadSize); 116 void EnumUSBDeviceRegister(void (*pCallBack)(HSession hSession)); 117 #ifdef HDC_SUPPORT_UART 118 using UartKickoutZombie = const std::function<void(HSession hSession)>; 119 virtual void EnumUARTDeviceRegister(UartKickoutZombie); 120 #endif 121 void ClearOwnTasks(HSession hSession, const uint32_t channelIDInput); FetchCommand(HSession hSession,const uint32_t channelId,const uint16_t command,uint8_t * payload,int payloadSize)122 virtual bool FetchCommand(HSession hSession, const uint32_t channelId, const uint16_t command, uint8_t *payload, 123 int payloadSize) 124 { 125 return true; 126 } ServerCommand(const uint32_t sessionId,const uint32_t channelId,const uint16_t command,uint8_t * bufPtr,const int size)127 virtual bool ServerCommand(const uint32_t sessionId, const uint32_t channelId, const uint16_t command, 128 uint8_t *bufPtr, const int size) 129 { 130 return true; 131 } RemoveInstanceTask(const uint8_t op,HTaskInfo hTask)132 virtual bool RemoveInstanceTask(const uint8_t op, HTaskInfo hTask) 133 { 134 return true; 135 } WantRestart()136 bool WantRestart() 137 { 138 return wantRestart; 139 } 140 static vector<uint8_t> BuildCtrlString(InnerCtrlCommand command, uint32_t channelId, uint8_t *data, int dataSize); 141 uv_loop_t loopMain; 142 LoopStatus loopMainStatus; 143 bool serverOrDaemon; 144 uv_async_t asyncMainLoop; 145 uv_rwlock_t mainAsync; 146 list<void *> lstMainThreadOP; 147 void *ctxUSB; 148 149 protected: 150 struct PayloadHead { 151 uint8_t flag[2]; 152 uint8_t reserve[2]; // encrypt'flag or others options 153 uint8_t protocolVer; 154 uint16_t headSize; 155 uint32_t dataSize; 156 } __attribute__((packed)); 157 void ClearSessions(); 158 #ifdef HDC_HOST 159 void PrintSession(const uint32_t sessionId); 160 #endif 161 HSession VoteReset(const uint32_t sessionId); JdwpNewFileDescriptor(const uint8_t * buf,const int bytesIO)162 virtual void JdwpNewFileDescriptor(const uint8_t *buf, const int bytesIO) 163 { 164 } 165 // must be define in haderfile, cannot in cpp file 166 template<class T> TaskCommandDispatch(HTaskInfo hTaskInfo,uint8_t taskType,const uint16_t command,uint8_t * payload,const int payloadSize)167 bool TaskCommandDispatch(HTaskInfo hTaskInfo, uint8_t taskType, const uint16_t command, uint8_t *payload, 168 const int payloadSize) 169 { 170 StartTraceScope("HdcSessionBase::TaskCommandDispatch"); 171 bool ret = true; 172 T *ptrTask = nullptr; 173 if (!hTaskInfo->hasInitial) { 174 hTaskInfo->taskType = taskType; 175 ptrTask = new(std::nothrow) T(hTaskInfo); 176 if (ptrTask == nullptr) { 177 return false; 178 } 179 hTaskInfo->hasInitial = true; 180 hTaskInfo->taskClass = ptrTask; 181 } else { 182 ptrTask = static_cast<T *>(hTaskInfo->taskClass); 183 } 184 if (!ptrTask->CommandDispatch(command, payload, payloadSize)) { 185 ptrTask->TaskFinish(); 186 } 187 return ret; 188 } DoTaskRemove(HTaskInfo hTaskInfo,const uint8_t op)189 template<class T> bool DoTaskRemove(HTaskInfo hTaskInfo, const uint8_t op) 190 { 191 T *ptrTask = static_cast<T *>(hTaskInfo->taskClass); 192 if (ptrTask == nullptr) { 193 return true; 194 } 195 if (op == OP_CLEAR) { 196 ptrTask->StopTask(); 197 } else if (op == OP_REMOVE) { 198 if (!ptrTask->ReadyForRelease()) { 199 return false; 200 } 201 delete ptrTask; 202 } 203 return true; 204 } 205 bool wantRestart; 206 207 private: ClearInstanceResource()208 virtual void ClearInstanceResource() 209 { 210 } 211 int DecryptPayload(HSession hSession, PayloadHead *payloadHeadBe, uint8_t *encBuf); 212 bool DispatchMainThreadCommand(HSession hSession, const CtrlStruct *ctrl); 213 bool DispatchSessionThreadCommand(HSession hSession, const uint8_t *baseBuf, 214 const int bytesIO); 215 void BeginRemoveTask(HTaskInfo hTask); 216 bool TryRemoveTask(HTaskInfo hTask); 217 void ReChildLoopForSessionClear(HSession hSession); 218 void FreeSessionContinue(HSession hSession); 219 static void FreeSessionFinally(uv_idle_t *handle); 220 static void AsyncMainLoopTask(uv_idle_t *handle); 221 static void FreeSessionOpeate(uv_timer_t *handle); 222 static void SendHeartbeatMsg(uv_timer_t *handle); 223 int MallocSessionByConnectType(HSession hSession); 224 void FreeSessionByConnectType(HSession hSession); 225 bool WorkThreadStartSession(HSession hSession); 226 void WorkThreadInitSession(HSession hSession, SessionHandShake &handshake); 227 uint32_t GetSessionPseudoUid(); 228 bool NeedNewTaskInfo(const uint16_t command, bool &masterTask); 229 void DumpTasksInfo(map<uint32_t, HTaskInfo> &mapTask); 230 void StartHeartbeatWork(HSession hSession); 231 void SetFeature(SessionHandShake &handshake); 232 void StopHeartbeatWork(HSession hSession); 233 234 map<uint32_t, HSession> mapSession; 235 uv_rwlock_t lockMapSession; 236 std::atomic<uint32_t> sessionRef = 0; 237 const uint8_t payloadProtectStaticVcode = 0x09; 238 uv_thread_t threadSessionMain; 239 size_t threadPoolCount; 240 std::atomic<uint32_t> taskCount = 0; 241 }; 242 } // namespace Hdc 243 #endif 244