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