1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23 #include "message_server.h"
24
25 #include <fstream>
26 #include <functional>
27 #include <iostream>
28 #include <list>
29 #include <map>
30 #include <string>
31 #include <sys/socket.h>
32 #include <sys/types.h>
33 #include <sys/un.h>
34 #include <unistd.h>
35
36 #include "debugger.h"
37 #include "securec.h"
38
39 static std::mutex g_mtx;
40 static std::map<int, std::list<std::string>> g_readMsgQueues;
41 static constexpr int MSG_LEN = 9;
42 static constexpr int MAX_CONNECT_CLIENT_NUM = 1;
43
DBG_CopyComponentNameFromAce(const char * srcStr,char * destStr,int maxLen)44 bool DBG_CopyComponentNameFromAce(const char *srcStr, char *destStr, int maxLen)
45 {
46 if (strcpy_s(destStr, maxLen, srcStr) != 0) {
47 DEBUGGER_LOGE("GetInstanceName strcpy_s fail");
48 return false;
49 }
50 return true;
51 }
52
QueueFront(int client)53 const char* QueueFront(int client)
54 {
55 g_mtx.lock();
56 const char* res = g_readMsgQueues[client].front().c_str();
57 g_mtx.unlock();
58 return res;
59 }
60
QueuePop(int client)61 void QueuePop(int client)
62 {
63 g_mtx.lock();
64 g_readMsgQueues[client].pop_front();
65 g_mtx.unlock();
66 }
67
QueueIsEmpty(int client)68 int QueueIsEmpty(int client)
69 {
70 g_mtx.lock();
71 int ret = g_readMsgQueues[client].empty();
72 g_mtx.unlock();
73 return ret;
74 }
75
DBG_SocketRead(int client,char * buf,int len)76 static int DBG_SocketRead(int client, char *buf, int len)
77 {
78 if (client <= 0 || len == 0 || buf == nullptr) {
79 DEBUGGER_LOGE("DBG_SocketRead fail client=%d, len=%d, buf=%s", client, len, buf);
80 return 0;
81 }
82
83 int loc = 0;
84 while (loc < len) {
85 int ret = TEMP_FAILURE_RETRY(read(client, reinterpret_cast<void*>(buf + loc), len - loc));
86 if (ret <= 0 || ret > (len - loc)) {
87 return 0;
88 }
89 loc = loc + ret;
90 }
91
92 return 1;
93 }
94
DBG_ReadMsgLen(int client)95 static int DBG_ReadMsgLen(int client)
96 {
97 char msgLenChar[MSG_LEN] = {0};
98 int readRet = DBG_SocketRead(client, msgLenChar, MSG_LEN);
99 if (readRet != 1) {
100 return 0;
101 }
102 msgLenChar[MSG_LEN - 1] = '\0';
103 // turn str to hex
104 const int base = 16;
105 int msgLen = strtol(msgLenChar, nullptr, base);
106 if (msgLen <= 0) {
107 DEBUGGER_LOGE("DBG_ReadMsgLen fail msgLen=%d", msgLen);
108 return 0;
109 }
110
111 return msgLen;
112 }
113
ReadMsg(int client)114 static void ReadMsg(int client)
115 {
116 int msgLen = DBG_ReadMsgLen(client);
117 if (msgLen <= 0) {
118 return;
119 }
120 std::unique_ptr<char[]> msgBuf = std::make_unique<char[]>(msgLen + 1);
121 if (msgBuf == nullptr) {
122 DEBUGGER_LOGE("DBG_ReadMsg fail msgBuf=nullptr");
123 return;
124 }
125
126 int readRet = DBG_SocketRead(client, msgBuf.get(), msgLen);
127 if (!readRet) {
128 DEBUGGER_LOGE("DBG_ReadMsg fail readRet=%d", readRet);
129 return;
130 }
131
132 g_mtx.lock();
133 msgBuf.get()[msgLen] = '\0';
134 DEBUGGER_LOGI("dbg msg %s", msgBuf.get());
135 std::string message(msgBuf.get());
136 g_readMsgQueues[client].push_back(message);
137 g_mtx.unlock();
138
139 return;
140 }
141
142
143 static std::string g_componentName;
144 static int g_instanceId;
145
DBG_SetComponentNameAndInstanceId(const char * name,int size,int instanceId)146 void DBG_SetComponentNameAndInstanceId(const char *name, int size, int instanceId)
147 {
148 if (size <= 0) {
149 DEBUGGER_LOGE("DBG_SetComponentName fail");
150 return;
151 }
152 g_componentName = name;
153 g_instanceId = instanceId;
154 }
155
DBG_SetNeedDebugBreakPoint(bool needDebugBreakPoint)156 void DBG_SetNeedDebugBreakPoint(bool needDebugBreakPoint)
157 {
158 DEBUGGER_LOGI("NeedDebugBreakPoint: %d", needDebugBreakPoint);
159 DBG_SetDebugMode(!needDebugBreakPoint);
160 }
161
DBG_GetComponentName()162 static std::string DBG_GetComponentName()
163 {
164 if (g_componentName.empty()) {
165 DEBUGGER_LOGE("DBG_GetComponentName fail");
166 }
167 return g_componentName;
168 }
169
DBG_StartServer()170 static int DBG_StartServer()
171 {
172 DEBUGGER_LOGI("DBG_StartServer");
173 int fd = socket(AF_UNIX, SOCK_STREAM, 0);
174 if (fd < 0) {
175 return FAIL_CAUSE_SOCKET_COMMON_FAIL;
176 }
177
178 std::string instanceIdStr = std::to_string(g_instanceId);
179 std::string component = DBG_GetComponentName();
180 std::string sockName = instanceIdStr + component;
181 struct sockaddr_un un;
182 if (memset_s(&un, sizeof(un), 0, sizeof(un)) != EOK) {
183 DEBUGGER_LOGE("DBG_StartServer memset_s fail");
184 close(fd);
185 return FAIL_CAUSE_SOCKET_COMMON_FAIL;
186 }
187 un.sun_family = AF_UNIX;
188 if (strcpy_s(un.sun_path + 1, sizeof(un.sun_path) - 1, sockName.c_str()) != EOK) {
189 DEBUGGER_LOGE("DBG_StartServer strcpy_s fail");
190 close(fd);
191 return FAIL_CAUSE_SOCKET_COMMON_FAIL;
192 }
193 un.sun_path[0] = '\0';
194 int len = offsetof(struct sockaddr_un, sun_path) + strlen(sockName.c_str()) + 1;
195 if (bind(fd, reinterpret_cast<struct sockaddr*>(&un), len) < 0) {
196 close(fd);
197 return FAIL_CAUSE_SOCKET_COMMON_FAIL;
198 }
199 if (listen(fd, MAX_CONNECT_CLIENT_NUM) < 0) {
200 close(fd);
201 return FAIL_CAUSE_SOCKET_COMMON_FAIL;
202 }
203 int client = 0;
204 if ((client = accept(fd, nullptr, nullptr)) < 0) {
205 close(fd);
206 return FAIL_CAUSE_SOCKET_COMMON_FAIL;
207 }
208 return client;
209 }
210
DBG_StartAgent(void * args)211 void *DBG_StartAgent(void *args)
212 {
213 int client = DBG_StartServer();
214 if (client < 0) {
215 DEBUGGER_LOGE("DBG_StartAgent fail");
216 return nullptr;
217 }
218
219 auto debugger_info = (DebuggerInfo*)args;
220 g_mtx.lock();
221 debugger_info->client = client;
222 debugger_info->isConnected = 1;
223 g_mtx.unlock();
224
225 std::list<std::string> messageList;
226 g_readMsgQueues[client] = messageList;
227 DEBUGGER_LOGI("DBG_StartAgent client = %d", client);
228
229 while (true) {
230 ReadMsg(client);
231 }
232 }
233