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