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