1 /*
2 * Copyright (C) 2022 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
16 #include "nstackx_dfinder_hidump.h"
17 #include <inttypes.h>
18 #include "nstackx_dfinder_log.h"
19 #include "nstackx_dfinder_mgt_msg_log.h"
20 #include "nstackx_util.h"
21 #include "nstackx_getopt.h"
22 #include "nstackx_statistics.h"
23 #include "nstackx_common.h"
24 #include "nstackx_event.h"
25 #include "nstackx_error.h"
26 #include "securec.h"
27
28 #ifdef NSTACKX_DFINDER_HIDUMP
29
30 #define TAG "nStackXDFinder"
31 #define CRLF "\r\n"
32
33 #define DUMP_BUF_LEN (2048U)
34
35 typedef struct {
36 char *buf;
37 uint32_t size;
38 int err;
39 sem_t wait;
40 } DumpMsg;
41
CreateDumpMsg(char * buf,uint32_t size)42 static DumpMsg *CreateDumpMsg(char *buf, uint32_t size)
43 {
44 DumpMsg *msg = (DumpMsg *)malloc(sizeof(DumpMsg));
45 if (msg == NULL) {
46 return NULL;
47 }
48
49 if (SemInit(&(msg->wait), 0, 0)) {
50 free(msg);
51 return NULL;
52 }
53
54 msg->err = NSTACKX_EOK;
55 msg->buf = buf;
56 msg->size = size;
57 return msg;
58 }
59
DestroyDumpMsg(DumpMsg * msg)60 static void DestroyDumpMsg(DumpMsg *msg)
61 {
62 SemDestroy(&(msg->wait));
63 free(msg);
64 }
65
PostDumpMsg(char * buf,uint32_t size,EventHandle handle)66 static int PostDumpMsg(char *buf, uint32_t size, EventHandle handle)
67 {
68 int ret = NSTACKX_EFAILED;
69 DumpMsg *msg = CreateDumpMsg(buf, size);
70 if (msg == NULL) {
71 return ret;
72 }
73
74 if (PostEvent(GetEventNodeChain(), GetEpollFD(), handle, msg) != NSTACKX_EOK) {
75 DestroyDumpMsg(msg);
76 return ret;
77 }
78
79 SemWait(&(msg->wait));
80 ret = msg->err;
81 DestroyDumpMsg(msg);
82 return ret;
83 }
84
85 typedef int (*DumpFunc)(char *buf, uint32_t size);
Dump(void * softObj,DFinderDumpFunc dump,DumpFunc func)86 static int Dump(void *softObj, DFinderDumpFunc dump, DumpFunc func)
87 {
88 char *buf = (char *)calloc(DUMP_BUF_LEN, sizeof(char));
89 if (buf == NULL) {
90 return NSTACKX_EFAILED;
91 }
92
93 if (func(buf, DUMP_BUF_LEN) != NSTACKX_EOK) {
94 free(buf);
95 return NSTACKX_EFAILED;
96 }
97
98 dump(softObj, buf, strlen(buf) + 1);
99 free(buf);
100 return NSTACKX_EOK;
101 }
102
DumpStatisticsInfo(char * buf,uint32_t size)103 static int DumpStatisticsInfo(char *buf, uint32_t size)
104 {
105 int ret;
106 uint32_t index = 0;
107 const uint64_t *stat = GetStatistics();
108 DUMP_MSG_ADD_CHECK(ret, buf, index, size, CRLF"DFinder statistics:"CRLF);
109 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_INVALID_OPT_AND_PAYLOAD: %" PRIu64 CRLF,
110 stat[STATS_INVALID_OPT_AND_PAYLOAD]);
111 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_DECODE_FAILED: %" PRIu64 CRLF, stat[STATS_DECODE_FAILED]);
112 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_ENCODE_FAILED: %" PRIu64 CRLF, stat[STATS_ENCODE_FAILED]);
113 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_CREATE_HEADER_FAILED: %" PRIu64 CRLF,
114 stat[STATS_CREATE_HEADER_FAILED]);
115 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_BUILD_PKT_FAILED: %" PRIu64 CRLF, stat[STATS_BUILD_PKT_FAILED]);
116 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_SOCKET_ERROR: %" PRIu64 CRLF, stat[STATS_SOCKET_ERROR]);
117 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_EPOLL_ERROR: %" PRIu64 CRLF, stat[STATS_EPOLL_ERROR]);
118 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_CREATE_SERVER_FAILED: %" PRIu64 CRLF,
119 stat[STATS_CREATE_SERVER_FAILED]);
120 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_CREATE_CLIENT_FAILED: %" PRIu64 CRLF,
121 stat[STATS_CREATE_CLIENT_FAILED]);
122 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_DROP_LOOPBACK_PKT: %" PRIu64 CRLF, stat[STATS_DROP_LOOPBACK_PKT]);
123 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_SEND_MSG_FAILED: %" PRIu64 CRLF, stat[STATS_SEND_MSG_FAILED]);
124 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_SEND_REQUEST_FAILED: %" PRIu64 CRLF,
125 stat[STATS_SEND_REQUEST_FAILED]);
126 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_DROP_MSG_ID: %" PRIu64 CRLF, stat[STATS_DROP_MSG_ID]);
127 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_HANDLE_SERVICE_MSG_FAILED: %" PRIu64 CRLF,
128 stat[STATS_HANDLE_SERVICE_MSG_FAILED]);
129 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_HANDLE_DEVICE_DISCOVER_MSG_FAILED: %" PRIu64 CRLF,
130 stat[STATS_HANDLE_DEVICE_DISCOVER_MSG_FAILED]);
131 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_INVALID_RESPONSE_MSG: %" PRIu64 CRLF,
132 stat[STATS_INVALID_RESPONSE_MSG]);
133 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_POST_SD_REQUEST_FAILED: %" PRIu64 CRLF,
134 stat[STATS_POST_SD_REQUEST_FAILED]);
135 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_ABORT_SD: %" PRIu64 CRLF, stat[STATS_ABORT_SD]);
136 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_START_SD_FAILED: %" PRIu64 CRLF, stat[STATS_START_SD_FAILED]);
137 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_CREATE_SERVICE_MSG_FAILED: %" PRIu64 CRLF,
138 stat[STATS_CREATE_SERVICE_MSG_FAILED]);
139 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_SEND_SD_RESPONSE_FAILED: %" PRIu64 CRLF,
140 stat[STATS_SEND_SD_RESPONSE_FAILED]);
141 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_BACKUP_DEVICE_DB_FAILED: %" PRIu64 CRLF,
142 stat[STATS_BACKUP_DEVICE_DB_FAILED]);
143 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_UPDATE_DEVICE_DB_FAILED: %" PRIu64 CRLF,
144 stat[STATS_UPDATE_DEVICE_DB_FAILED]);
145 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_CREATE_CONTEX_FAILED: %" PRIu64 CRLF,
146 stat[STATS_CREATE_CONTEX_FAILED]);
147 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_CREATE_SESSION_FAILED: %" PRIu64 CRLF,
148 stat[STATS_CREATE_SESSION_FAILED]);
149 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_PREPARE_SD_MSG_FAILED: %" PRIu64 CRLF,
150 stat[STATS_PREPARE_SD_MSG_FAILED]);
151 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_PARSE_SD_MSG_FAILED: %" PRIu64 CRLF,
152 stat[STATS_PARSE_SD_MSG_FAILED]);
153 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_ALLOC_RECORD_FAILED: %" PRIu64 CRLF,
154 stat[STATS_ALLOC_RECORD_FAILED]);
155 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_FREE_RECORD_FAILED: %" PRIu64 CRLF,
156 stat[STATS_FREE_RECORD_FAILED]);
157 DUMP_MSG_ADD_CHECK(ret, buf, index, size, "STATS_OVER_DEVICE_LIMIT: %" PRIu64 CRLF, stat[STATS_OVER_DEVICE_LIMIT]);
158 return NSTACKX_EOK;
159 }
160
DumpStatisticsInner(void * arg)161 static void DumpStatisticsInner(void *arg)
162 {
163 DumpMsg *msg = (DumpMsg *)arg;
164 msg->err = DumpStatisticsInfo(msg->buf, msg->size);
165 SemPost(&(msg->wait));
166 }
167
DumpStatistics(char * buf,uint32_t size)168 int DumpStatistics(char *buf, uint32_t size)
169 {
170 return PostDumpMsg(buf, size, DumpStatisticsInner);
171 }
172
DumpHelp(char * buf,uint32_t size)173 static int DumpHelp(char *buf, uint32_t size)
174 {
175 int ret;
176 int index = 0;
177 DUMP_MSG_ADD_CHECK(ret, buf, index, size, CRLF"Usage: dfinder <opt>"CRLF);
178 DUMP_MSG_ADD_CHECK(ret, buf, index, size, " -h show this help"CRLF);
179 DUMP_MSG_ADD_CHECK(ret, buf, index, size, " -s show statistics info"CRLF);
180 DUMP_MSG_ADD_CHECK(ret, buf, index, size, " -m <0/1> enable control message log"CRLF);
181 return NSTACKX_EOK;
182 }
183
184 #define DFINDER_DUMP_STRTOL_BASE 10
185 static const char *g_dfinderDumpOpts = "hsm:";
DFinderDump(const char ** argv,uint32_t argc,void * softObj,DFinderDumpFunc dump)186 int DFinderDump(const char **argv, uint32_t argc, void *softObj, DFinderDumpFunc dump)
187 {
188 int32_t opt;
189 NstackGetOptMsg optMsg;
190 int32_t ret = NstackInitGetOptMsg(&optMsg);
191 if (ret != NSTACKX_EOK) {
192 return ret;
193 }
194
195 while ((opt = NstackGetOpt(&optMsg, argc, argv, g_dfinderDumpOpts)) != NSTACK_GETOPT_END_OF_STR) {
196 switch (opt) {
197 case 'h':
198 ret = Dump(softObj, dump, DumpHelp);
199 break;
200 case 's':
201 ret = Dump(softObj, dump, DumpStatistics);
202 break;
203 case 'm':
204 #ifdef DFINDER_MGT_MSG_LOG
205 (void)DFinderSetMgtMsgLog((int32_t)strtol(NstackGetOptArgs(&optMsg), NULL, DFINDER_DUMP_STRTOL_BASE));
206 #endif
207 break;
208 default:
209 ret = NSTACKX_EFAILED;
210 DFINDER_LOGE(TAG, "Unknown option");
211 break;
212 }
213
214 if (ret != NSTACKX_EOK) {
215 break;
216 }
217 }
218
219 return ret;
220 }
221
222 #endif /* NSTACKX_DFINDER_HIDUMP */
223