1 /*
2 * Copyright (c) 2021 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_log.h"
22 #include "softbus_utils.h"
23
24 #define TIME_OUT 2
25
26 typedef struct {
27 ListNode node;
28 SoftBusCond cond;
29 SoftBusMutex lock;
30 int32_t channelId;
31 int32_t seq;
32 uint8_t status;
33 } PendingPktInfo;
34
35 enum PackageStatus {
36 PACKAGE_STATUS_PENDING = 0,
37 PACKAGE_STATUS_FINISHED,
38 PACKAGE_STATUS_CANCELED
39 };
40
41 static SoftBusList *g_pendingList[PENDING_TYPE_BUTT] = {NULL, NULL};
42
PendingInit(int type)43 int32_t PendingInit(int type)
44 {
45 if (type < PENDING_TYPE_PROXY || type >= PENDING_TYPE_BUTT) {
46 return SOFTBUS_ERR;
47 }
48
49 g_pendingList[type] = CreateSoftBusList();
50 if (g_pendingList[type] == NULL) {
51 return SOFTBUS_ERR;
52 }
53 return SOFTBUS_OK;
54 }
55
PendingDeinit(int type)56 void PendingDeinit(int type)
57 {
58 if (type < PENDING_TYPE_PROXY || type >= PENDING_TYPE_BUTT) {
59 return;
60 }
61
62 if (g_pendingList[type] != NULL) {
63 DestroySoftBusList(g_pendingList[type]);
64 g_pendingList[type] = NULL;
65 }
66 SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_INFO, "PendigPackManagerDeinit init ok");
67 }
68
TimeBefore(const SoftBusSysTime * inputTime)69 static inline bool TimeBefore(const SoftBusSysTime *inputTime)
70 {
71 SoftBusSysTime now;
72 SoftBusGetTime(&now);
73 return (now.sec < inputTime->sec || (now.sec == inputTime->sec && now.usec < inputTime->usec));
74 }
75
CreatePendingItem(int32_t channelId,int32_t seqNum)76 static PendingPktInfo *CreatePendingItem(int32_t channelId, int32_t seqNum)
77 {
78 PendingPktInfo *item = (PendingPktInfo *)SoftBusCalloc(sizeof(PendingPktInfo));
79 if (item == NULL) {
80 return NULL;
81 }
82
83 SoftBusMutexInit(&item->lock, NULL);
84 SoftBusCondInit(&item->cond);
85 item->channelId = channelId;
86 item->seq = seqNum;
87 item->status = PACKAGE_STATUS_PENDING;
88 return item;
89 }
90
ReleasePendingItem(PendingPktInfo * item)91 static void ReleasePendingItem(PendingPktInfo *item)
92 {
93 if (item == NULL) {
94 return;
95 }
96 (void)SoftBusMutexDestroy(&item->lock);
97 (void)SoftBusCondDestroy(&item->cond);
98 SoftBusFree(item);
99 }
100
ProcPendingPacket(int32_t channelId,int32_t seqNum,int type)101 int32_t ProcPendingPacket(int32_t channelId, int32_t seqNum, int type)
102 {
103 if (type < PENDING_TYPE_PROXY || type >= PENDING_TYPE_BUTT) {
104 return SOFTBUS_ERR;
105 }
106
107 PendingPktInfo *item = NULL;
108 SoftBusList *pendingList = g_pendingList[type];
109 if (pendingList == NULL) {
110 SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_ERROR, "pending[%d] list not inited.", type);
111 return SOFTBUS_TRANS_TDC_PENDINGLIST_NOT_FOUND;
112 }
113
114 SoftBusMutexLock(&pendingList->lock);
115 LIST_FOR_EACH_ENTRY(item, &pendingList->list, PendingPktInfo, node)
116 {
117 if (item->seq == seqNum && item->channelId == channelId) {
118 SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_ERROR, "PendingPacket already Created");
119 SoftBusMutexUnlock(&pendingList->lock);
120 return SOFTBUS_TRANS_TDC_CHANNEL_ALREADY_PENDING;
121 }
122 }
123
124 item = CreatePendingItem(channelId, seqNum);
125 if (item == NULL) {
126 SoftBusMutexUnlock(&pendingList->lock);
127 return SOFTBUS_MALLOC_ERR;
128 }
129 ListAdd(&pendingList->list, &item->node);
130 pendingList->cnt++;
131 SoftBusMutexUnlock(&pendingList->lock);
132
133 SoftBusSysTime outtime;
134 SoftBusSysTime now;
135 SoftBusGetTime(&now);
136 outtime.sec = now.sec + TIME_OUT;
137 outtime.usec = now.usec;
138 SoftBusMutexLock(&item->lock);
139 while (item->status == PACKAGE_STATUS_PENDING && TimeBefore(&outtime)) {
140 SoftBusCondWait(&item->cond, &item->lock, &outtime);
141 }
142
143 int32_t ret = SOFTBUS_OK;
144 if (item->status != PACKAGE_STATUS_FINISHED) {
145 ret = SOFTBUS_TIMOUT;
146 }
147 SoftBusMutexUnlock(&item->lock);
148
149 SoftBusMutexLock(&pendingList->lock);
150 ListDelete(&item->node);
151 pendingList->cnt--;
152 SoftBusMutexUnlock(&pendingList->lock);
153 ReleasePendingItem(item);
154 return ret;
155 }
156
SetPendingPacket(int32_t channelId,int32_t seqNum,int type)157 int32_t SetPendingPacket(int32_t channelId, int32_t seqNum, int type)
158 {
159 if (type < PENDING_TYPE_PROXY || type >= PENDING_TYPE_BUTT) {
160 SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_ERROR, "type[%d] illegal.", type);
161 return SOFTBUS_ERR;
162 }
163
164 SoftBusList *pendingList = g_pendingList[type];
165 if (pendingList == NULL) {
166 SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_ERROR, "pendind list not exist");
167 return SOFTBUS_ERR;
168 }
169 if (SoftBusMutexLock(&pendingList->lock) != SOFTBUS_OK) {
170 SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_ERROR, "set pendind lock failed.");
171 return SOFTBUS_ERR;
172 }
173 PendingPktInfo *item = NULL;
174 LIST_FOR_EACH_ENTRY(item, &pendingList->list, PendingPktInfo, node) {
175 if (item->seq == seqNum && item->channelId == channelId) {
176 item->status = PACKAGE_STATUS_FINISHED;
177 SoftBusCondSignal(&item->cond);
178 SoftBusMutexUnlock(&pendingList->lock);
179 return SOFTBUS_OK;
180 }
181 }
182 SoftBusMutexUnlock(&pendingList->lock);
183 return SOFTBUS_ERR;
184 }
185
DelPendingPacket(int32_t channelId,int type)186 NO_SANITIZE("cfi") int32_t DelPendingPacket(int32_t channelId, int type)
187 {
188 if (type < PENDING_TYPE_PROXY || type >= PENDING_TYPE_BUTT) {
189 return SOFTBUS_ERR;
190 }
191
192 SoftBusList *pendingList = g_pendingList[type];
193 if (pendingList == NULL) {
194 return SOFTBUS_ERR;
195 }
196 if (SoftBusMutexLock(&pendingList->lock) != SOFTBUS_OK) {
197 SoftBusLog(SOFTBUS_LOG_TRAN, SOFTBUS_LOG_ERROR, "del pendind lock failed.");
198 return SOFTBUS_ERR;
199 }
200 PendingPktInfo *item = NULL;
201 LIST_FOR_EACH_ENTRY(item, &pendingList->list, PendingPktInfo, node) {
202 if (item->channelId == channelId) {
203 item->status = PACKAGE_STATUS_CANCELED;
204 SoftBusCondSignal(&item->cond);
205 SoftBusMutexUnlock(&pendingList->lock);
206 return SOFTBUS_OK;
207 }
208 }
209 SoftBusMutexUnlock(&pendingList->lock);
210 return SOFTBUS_OK;
211 }
212
213