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