1 /*
2 * Copyright (c) 2021-2024 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 "trans_pending_pkt.h"
17
18 #include "softbus_adapter_mem.h"
19 #include "softbus_adapter_thread.h"
20 #include "softbus_errcode.h"
21 #include "softbus_utils.h"
22 #include "trans_log.h"
23
24 #define MSG_TIMEOUT_S 20
25 #define UDP_TIMEOUT_US (150 * 1000)
26 #define MAX_US (1 * 1000 * 1000)
27
28 typedef struct {
29 ListNode node;
30 SoftBusCond cond;
31 SoftBusMutex lock;
32 int32_t channelId;
33 int32_t seq;
34 uint8_t status;
35 } PendingPktInfo;
36
37 enum PackageStatus {
38 PACKAGE_STATUS_PENDING = 0,
39 PACKAGE_STATUS_FINISHED,
40 PACKAGE_STATUS_CANCELED
41 };
42
43 static SoftBusList *g_pendingList[PENDING_TYPE_BUTT] = {NULL, NULL};
44
IsPendingListTypeLegal(int type)45 static int32_t IsPendingListTypeLegal(int type)
46 {
47 if (type < PENDING_TYPE_PROXY || type >= PENDING_TYPE_BUTT) {
48 return SOFTBUS_INVALID_PARAM;
49 }
50 return SOFTBUS_OK;
51 }
52
PendingInit(int32_t type)53 int32_t PendingInit(int32_t type)
54 {
55 int32_t ret = IsPendingListTypeLegal(type);
56 if (ret != SOFTBUS_OK) {
57 TRANS_LOGE(TRANS_SVC, "type illegal. type=%{public}d ", type);
58 return ret;
59 }
60
61 g_pendingList[type] = CreateSoftBusList();
62 if (g_pendingList[type] == NULL) {
63 TRANS_LOGE(TRANS_SVC, "pending init fail");
64 return SOFTBUS_MALLOC_ERR;
65 }
66 return SOFTBUS_OK;
67 }
68
PendingDeinit(int32_t type)69 void PendingDeinit(int32_t type)
70 {
71 int32_t ret = IsPendingListTypeLegal(type);
72 if (ret != SOFTBUS_OK) {
73 TRANS_LOGE(TRANS_SVC, "type illegal. type=%{public}d", type);
74 return;
75 }
76
77 if (g_pendingList[type] != NULL) {
78 DestroySoftBusList(g_pendingList[type]);
79 g_pendingList[type] = NULL;
80 }
81 TRANS_LOGI(TRANS_INIT, "PendigPackManagerDeinit init ok");
82 }
83
TimeBefore(const SoftBusSysTime * inputTime)84 static inline bool TimeBefore(const SoftBusSysTime *inputTime)
85 {
86 SoftBusSysTime now;
87 SoftBusGetTime(&now);
88 return (now.sec < inputTime->sec || (now.sec == inputTime->sec && now.usec < inputTime->usec));
89 }
90
CreatePendingItem(int32_t channelId,int32_t seqNum)91 static PendingPktInfo *CreatePendingItem(int32_t channelId, int32_t seqNum)
92 {
93 PendingPktInfo *item = (PendingPktInfo *)SoftBusCalloc(sizeof(PendingPktInfo));
94 if (item == NULL) {
95 return NULL;
96 }
97
98 SoftBusMutexInit(&item->lock, NULL);
99 SoftBusCondInit(&item->cond);
100 item->channelId = channelId;
101 item->seq = seqNum;
102 item->status = PACKAGE_STATUS_PENDING;
103 return item;
104 }
105
ReleasePendingItem(PendingPktInfo * item)106 static void ReleasePendingItem(PendingPktInfo *item)
107 {
108 if (item == NULL) {
109 return;
110 }
111 (void)SoftBusMutexDestroy(&item->lock);
112 (void)SoftBusCondDestroy(&item->cond);
113 SoftBusFree(item);
114 }
115
FormalizeTimeFormat(SoftBusSysTime * outTime,int32_t type)116 static void FormalizeTimeFormat(SoftBusSysTime *outTime, int32_t type)
117 {
118 SoftBusSysTime now;
119 SoftBusGetTime(&now);
120 outTime->sec = (type == PENDING_TYPE_UDP) ? now.sec : now.sec + MSG_TIMEOUT_S;
121 outTime->usec = (type == PENDING_TYPE_UDP) ? now.usec + UDP_TIMEOUT_US : now.usec;
122
123 while (outTime->usec >= MAX_US) {
124 outTime->usec -= MAX_US;
125 outTime->sec += 1;
126 TRANS_LOGI(TRANS_SVC,
127 "us over limit, after formalize, us=%{public}" PRId64 "sec=%{public}" PRId64, outTime->usec, outTime->sec);
128 }
129 }
130
AddPendingPacket(int32_t channelId,int32_t seqNum,int32_t type)131 int32_t AddPendingPacket(int32_t channelId, int32_t seqNum, int32_t type)
132 {
133 int32_t ret = IsPendingListTypeLegal(type);
134 TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_SVC, "type=%{public}d illegal", type);
135
136 SoftBusList *pendingList = g_pendingList[type];
137 TRANS_CHECK_AND_RETURN_RET_LOGE(pendingList != NULL, SOFTBUS_TRANS_TDC_PENDINGLIST_NOT_FOUND, TRANS_SVC,
138 "type=%{public}d pending list not init", type);
139
140 ret = SoftBusMutexLock(&pendingList->lock);
141 TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, SOFTBUS_LOCK_ERR, TRANS_SVC, "pending list lock failed");
142 PendingPktInfo *item = NULL;
143 LIST_FOR_EACH_ENTRY(item, &pendingList->list, PendingPktInfo, node) {
144 if (item->seq == seqNum && item->channelId == channelId) {
145 TRANS_LOGW(TRANS_SVC, "PendingPacket already Created");
146 (void)SoftBusMutexUnlock(&pendingList->lock);
147 return SOFTBUS_TRANS_TDC_CHANNEL_ALREADY_PENDING;
148 }
149 }
150
151 item = CreatePendingItem(channelId, seqNum);
152 if (item == NULL) {
153 (void)SoftBusMutexUnlock(&pendingList->lock);
154 return SOFTBUS_MALLOC_ERR;
155 }
156 ListAdd(&pendingList->list, &item->node);
157 TRANS_LOGI(TRANS_SVC, "add channelId=%{public}d", item->channelId);
158 pendingList->cnt++;
159 (void)SoftBusMutexUnlock(&pendingList->lock);
160 return SOFTBUS_OK;
161 }
162
GetPendingPacket(int32_t channelId,int32_t seqNum,int32_t type)163 static PendingPktInfo *GetPendingPacket(int32_t channelId, int32_t seqNum, int32_t type)
164 {
165 int32_t ret = IsPendingListTypeLegal(type);
166 if (ret != SOFTBUS_OK) {
167 TRANS_LOGE(TRANS_SVC, "type illegal. type=%{public}d", type);
168 return NULL;
169 }
170
171 SoftBusList *pendingList = g_pendingList[type];
172 if (pendingList == NULL) {
173 TRANS_LOGE(TRANS_INIT, "pending type list not init. type=%{public}d", type);
174 return NULL;
175 }
176 if (SoftBusMutexLock(&pendingList->lock) != SOFTBUS_OK) {
177 TRANS_LOGE(TRANS_SVC, "set pending lock failed.");
178 return NULL;
179 }
180 PendingPktInfo *item = NULL;
181 LIST_FOR_EACH_ENTRY(item, &pendingList->list, PendingPktInfo, node) {
182 if (item->seq == seqNum && item->channelId == channelId) {
183 (void)SoftBusMutexUnlock(&pendingList->lock);
184 return item;
185 }
186 }
187 TRANS_LOGI(TRANS_SVC, "not found channelId=%{public}d", channelId);
188 (void)SoftBusMutexUnlock(&pendingList->lock);
189 return NULL;
190 }
191
DelPendingPacketbyChannelId(int32_t channelId,int32_t seqNum,int32_t type)192 void DelPendingPacketbyChannelId(int32_t channelId, int32_t seqNum, int32_t type)
193 {
194 int32_t ret = IsPendingListTypeLegal(type);
195 if (ret != SOFTBUS_OK) {
196 TRANS_LOGE(TRANS_SVC, "type illegal. type=%{public}d", type);
197 return;
198 }
199
200 SoftBusList *pendingList = g_pendingList[type];
201 if (pendingList == NULL) {
202 TRANS_LOGE(TRANS_INIT, "pending type list not init. type=%{public}d", type);
203 return;
204 }
205 if (SoftBusMutexLock(&pendingList->lock) != SOFTBUS_OK) {
206 TRANS_LOGE(TRANS_SVC, "set pending lock failed.");
207 return;
208 }
209 PendingPktInfo *item = NULL;
210 PendingPktInfo *next = NULL;
211 LIST_FOR_EACH_ENTRY_SAFE(item, next, &pendingList->list, PendingPktInfo, node) {
212 if (item->seq == seqNum && item->channelId == channelId) {
213 ListDelete(&item->node);
214 TRANS_LOGI(TRANS_SVC, "delete channelId=%{public}d", item->channelId);
215 pendingList->cnt--;
216 (void)SoftBusMutexUnlock(&pendingList->lock);
217 ReleasePendingItem(item);
218 return;
219 }
220 }
221 TRANS_LOGI(TRANS_SVC, "not found channelId=%{public}d", channelId);
222 (void)SoftBusMutexUnlock(&pendingList->lock);
223 }
224
ProcPendingPacket(int32_t channelId,int32_t seqNum,int32_t type)225 int32_t ProcPendingPacket(int32_t channelId, int32_t seqNum, int32_t type)
226 {
227 int32_t ret = IsPendingListTypeLegal(type);
228 TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, TRANS_SVC, "type=%{public}d illegal", type);
229
230 SoftBusList *pendingList = g_pendingList[type];
231 TRANS_CHECK_AND_RETURN_RET_LOGE(pendingList != NULL, SOFTBUS_TRANS_TDC_PENDINGLIST_NOT_FOUND, TRANS_SVC,
232 "type=%{public}d pending list not init", type);
233
234 SoftBusSysTime outTime;
235 FormalizeTimeFormat(&outTime, type);
236
237 PendingPktInfo *item = GetPendingPacket(channelId, seqNum, type);
238 TRANS_CHECK_AND_RETURN_RET_LOGE(item != NULL, SOFTBUS_NOT_FIND, TRANS_SVC, "pending item not found");
239 ret = SoftBusMutexLock(&item->lock);
240 TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, SOFTBUS_LOCK_ERR, TRANS_SVC, "pending item lock failed");
241 while (item->status == PACKAGE_STATUS_PENDING && TimeBefore(&outTime)) {
242 SoftBusCondWait(&item->cond, &item->lock, &outTime);
243 }
244 int32_t errCode = (item->status == PACKAGE_STATUS_FINISHED) ? SOFTBUS_OK : SOFTBUS_TIMOUT;
245 (void)SoftBusMutexUnlock(&item->lock);
246
247 ret = SoftBusMutexLock(&pendingList->lock);
248 TRANS_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, SOFTBUS_LOCK_ERR, TRANS_SVC, "pending list lock failed");
249 ListDelete(&item->node);
250 TRANS_LOGI(TRANS_SVC, "delete channelId=%{public}d", item->channelId);
251 pendingList->cnt--;
252 (void)SoftBusMutexUnlock(&pendingList->lock);
253 ReleasePendingItem(item);
254 return errCode;
255 }
256
SetPendingPacket(int32_t channelId,int32_t seqNum,int32_t type)257 int32_t SetPendingPacket(int32_t channelId, int32_t seqNum, int32_t type)
258 {
259 int32_t ret = IsPendingListTypeLegal(type);
260 if (ret != SOFTBUS_OK) {
261 TRANS_LOGE(TRANS_SVC, "type illegal. type=%{public}d", type);
262 return ret;
263 }
264
265 SoftBusList *pendingList = g_pendingList[type];
266 if (pendingList == NULL) {
267 TRANS_LOGE(TRANS_INIT, "pending type list not init. type=%{public}d", type);
268 return SOFTBUS_TRANS_TDC_PENDINGLIST_NOT_FOUND;
269 }
270 if (SoftBusMutexLock(&pendingList->lock) != SOFTBUS_OK) {
271 TRANS_LOGE(TRANS_SVC, "set pending lock failed.");
272 return SOFTBUS_LOCK_ERR;
273 }
274 PendingPktInfo *item = NULL;
275 LIST_FOR_EACH_ENTRY(item, &pendingList->list, PendingPktInfo, node) {
276 if (item->seq == seqNum && item->channelId == channelId) {
277 item->status = PACKAGE_STATUS_FINISHED;
278 SoftBusCondSignal(&item->cond);
279 (void)SoftBusMutexUnlock(&pendingList->lock);
280 return SOFTBUS_OK;
281 }
282 }
283 (void)SoftBusMutexUnlock(&pendingList->lock);
284 return SOFTBUS_TRANS_NODE_NOT_FOUND;
285 }
286
DelPendingPacket(int32_t channelId,int32_t type)287 int32_t DelPendingPacket(int32_t channelId, int32_t type)
288 {
289 int32_t ret = IsPendingListTypeLegal(type);
290 if (ret != SOFTBUS_OK) {
291 TRANS_LOGE(TRANS_SVC, "type illegal. type=%{public}d", type);
292 return ret;
293 }
294
295 SoftBusList *pendingList = g_pendingList[type];
296 if (pendingList == NULL) {
297 TRANS_LOGE(TRANS_INIT, "pending type list not init. type=%{public}d", type);
298 return SOFTBUS_TRANS_TDC_PENDINGLIST_NOT_FOUND;
299 }
300 if (SoftBusMutexLock(&pendingList->lock) != SOFTBUS_OK) {
301 TRANS_LOGE(TRANS_SVC, "del pending lock failed.");
302 return SOFTBUS_LOCK_ERR;
303 }
304 PendingPktInfo *item = NULL;
305 LIST_FOR_EACH_ENTRY(item, &pendingList->list, PendingPktInfo, node) {
306 if (item->channelId == channelId) {
307 item->status = PACKAGE_STATUS_CANCELED;
308 SoftBusCondSignal(&item->cond);
309 (void)SoftBusMutexUnlock(&pendingList->lock);
310 return SOFTBUS_OK;
311 }
312 }
313 (void)SoftBusMutexUnlock(&pendingList->lock);
314 return SOFTBUS_OK;
315 }
316
317