1 /*
2 * Copyright (c) 2022-2023 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 <inttypes.h>
17 #include <stdbool.h>
18
19 #include "client_trans_pending.h"
20
21 #include "common_list.h"
22 #include "softbus_adapter_mem.h"
23 #include "softbus_def.h"
24 #include "softbus_errcode.h"
25 #include "trans_log.h"
26
27 typedef struct {
28 ListNode node;
29 uint32_t id;
30 uint64_t seq;
31 bool finded;
32 SoftBusCond cond;
33 SoftBusMutex lock;
34 TransPendData data;
35 } PendingPacket;
36
37 static SoftBusMutex g_pendingLock;
38 static LIST_HEAD(g_pendingList);
39
40 #define USECTONSEC 1000LL
41
InitPendingPacket(void)42 int32_t InitPendingPacket(void)
43 {
44 if (SoftBusMutexInit(&g_pendingLock, NULL) != SOFTBUS_OK) {
45 return SOFTBUS_LOCK_ERR;
46 }
47 return SOFTBUS_OK;
48 }
49
DestroyPendingPacket(void)50 void DestroyPendingPacket(void)
51 {
52 (void)SoftBusMutexDestroy(&g_pendingLock);
53 }
54
CheckPendingPacketExisted(uint32_t id,uint64_t seq)55 static int32_t CheckPendingPacketExisted(uint32_t id, uint64_t seq)
56 {
57 if (SoftBusMutexLock(&g_pendingLock) != SOFTBUS_OK) {
58 TRANS_LOGE(TRANS_SDK, "Check pending packet is exist, lock error.");
59 return SOFTBUS_LOCK_ERR;
60 }
61 PendingPacket *pending = NULL;
62 LIST_FOR_EACH_ENTRY(pending, &g_pendingList, PendingPacket, node) {
63 if (pending->id == id && pending->seq == seq) {
64 TRANS_LOGE(TRANS_SDK, "PendingPacket existed. pendingId=%{public}u, pendingSeq=%{public}" PRIu64, id, seq);
65 (void)SoftBusMutexUnlock(&g_pendingLock);
66 return SOFTBUS_ALREADY_EXISTED;
67 }
68 }
69 (void)SoftBusMutexUnlock(&g_pendingLock);
70 return SOFTBUS_OK;
71 }
72
CreatePendingPacket(uint32_t id,uint64_t seq)73 int32_t CreatePendingPacket(uint32_t id, uint64_t seq)
74 {
75 int32_t ret = CheckPendingPacketExisted(id, seq);
76 if (ret != SOFTBUS_OK) {
77 TRANS_LOGE(TRANS_SDK, "Check pending packet is exist, ret=%{public}d.", ret);
78 return ret;
79 }
80
81 PendingPacket *pending = (PendingPacket *)SoftBusCalloc(sizeof(PendingPacket));
82 if (pending == NULL) {
83 TRANS_LOGE(TRANS_SDK, "SoftBusCalloc fail");
84 return SOFTBUS_MALLOC_ERR;
85 }
86 ListInit(&pending->node);
87 pending->id = id;
88 pending->seq = seq;
89 pending->data.data = NULL;
90 pending->data.len = 0;
91 pending->finded = false;
92 if (SoftBusMutexInit(&pending->lock, NULL) != SOFTBUS_OK) {
93 SoftBusFree(pending);
94 TRANS_LOGE(TRANS_SDK, "init lock fail");
95 return SOFTBUS_LOCK_ERR;
96 }
97 if (SoftBusCondInit(&pending->cond) != SOFTBUS_OK) {
98 TRANS_LOGE(TRANS_SDK, "condInit fail");
99 goto EXIT;
100 }
101 if (SoftBusMutexLock(&g_pendingLock) != SOFTBUS_OK) {
102 TRANS_LOGE(TRANS_SDK, "lock fail");
103 goto EXIT;
104 }
105 ListTailInsert(&g_pendingList, &(pending->node));
106 (void)SoftBusMutexUnlock(&g_pendingLock);
107 return SOFTBUS_OK;
108 EXIT:
109 SoftBusMutexDestroy(&pending->lock);
110 SoftBusFree(pending);
111 return SOFTBUS_NO_INIT;
112 }
113
DeletePendingPacket(uint32_t id,uint64_t seq)114 void DeletePendingPacket(uint32_t id, uint64_t seq)
115 {
116 if (SoftBusMutexLock(&g_pendingLock) != SOFTBUS_OK) {
117 TRANS_LOGE(TRANS_SDK, "mutex lock fail");
118 return;
119 }
120 PendingPacket *pending = NULL;
121 LIST_FOR_EACH_ENTRY(pending, &g_pendingList, PendingPacket, node) {
122 if (pending->id == id && pending->seq == seq) {
123 ListDelete(&pending->node);
124 SoftBusCondSignal(&pending->cond);
125 SoftBusMutexDestroy(&pending->lock);
126 SoftBusCondDestroy(&pending->cond);
127 SoftBusFree(pending);
128 break;
129 }
130 }
131 (void)SoftBusMutexUnlock(&g_pendingLock);
132 }
133
ComputeWaitPendTime(uint32_t waitMillis,SoftBusSysTime * outtime)134 static void ComputeWaitPendTime(uint32_t waitMillis, SoftBusSysTime *outtime)
135 {
136 SoftBusSysTime now;
137 (void)SoftBusGetTime(&now);
138 int64_t time = now.sec * USECTONSEC * USECTONSEC + now.usec + (int64_t)waitMillis * USECTONSEC;
139 outtime->sec = time / USECTONSEC / USECTONSEC;
140 outtime->usec = time % (USECTONSEC * USECTONSEC);
141 }
142
TransPendWaitTime(const PendingPacket * pending,TransPendData * data,uint32_t waitMillis)143 static int32_t TransPendWaitTime(const PendingPacket *pending, TransPendData *data, uint32_t waitMillis)
144 {
145 if (pending->finded) {
146 data->data = pending->data.data;
147 data->len = pending->data.len;
148 return SOFTBUS_ALREADY_TRIGGERED;
149 }
150 SoftBusSysTime outtime;
151 ComputeWaitPendTime(waitMillis, &outtime);
152 while (1) {
153 (void)SoftBusCondWait((SoftBusCond *)(&pending->cond), (SoftBusMutex *)(&pending->lock), &outtime);
154 if (pending->finded) {
155 data->data = pending->data.data;
156 data->len = pending->data.len;
157 return SOFTBUS_OK;
158 }
159 SoftBusSysTime now;
160 ComputeWaitPendTime(0, &now);
161 if (now.sec > outtime.sec || (now.sec == outtime.sec && now.usec >= outtime.usec)) {
162 break;
163 }
164 }
165 return SOFTBUS_TIMOUT;
166 }
167
GetPendingPacketData(uint32_t id,uint64_t seq,uint32_t waitMillis,bool isDelete,TransPendData * data)168 int32_t GetPendingPacketData(uint32_t id, uint64_t seq, uint32_t waitMillis, bool isDelete, TransPendData *data)
169 {
170 if (data == NULL) {
171 TRANS_LOGE(TRANS_SDK, "invalid param");
172 return SOFTBUS_INVALID_PARAM;
173 }
174 if (SoftBusMutexLock(&g_pendingLock) != SOFTBUS_OK) {
175 TRANS_LOGE(TRANS_SDK, "mutex lock fail");
176 return SOFTBUS_LOCK_ERR;
177 }
178 PendingPacket *pending = NULL;
179 PendingPacket *item = NULL;
180 LIST_FOR_EACH_ENTRY(item, &g_pendingList, PendingPacket, node) {
181 if (item->id == id && item->seq == seq) {
182 pending = item;
183 }
184 }
185 if (pending == NULL) {
186 (void)SoftBusMutexUnlock(&g_pendingLock);
187 return SOFTBUS_NOT_FIND;
188 }
189 (void)SoftBusMutexUnlock(&g_pendingLock);
190
191 int32_t ret;
192 if (SoftBusMutexLock(&pending->lock) != SOFTBUS_OK) {
193 ret = SOFTBUS_LOCK_ERR;
194 goto EXIT;
195 }
196 ret = TransPendWaitTime(pending, data, waitMillis);
197 (void)SoftBusMutexUnlock(&pending->lock);
198 EXIT:
199 (void)SoftBusMutexLock(&g_pendingLock);
200 if (isDelete || ret != SOFTBUS_TIMOUT) {
201 ListDelete(&pending->node);
202 SoftBusMutexDestroy(&pending->lock);
203 SoftBusCondDestroy(&pending->cond);
204 SoftBusFree(pending);
205 }
206 (void)SoftBusMutexUnlock(&g_pendingLock);
207 return ret;
208 }
209
SetPendingPacketData(uint32_t id,uint64_t seq,const TransPendData * data)210 int32_t SetPendingPacketData(uint32_t id, uint64_t seq, const TransPendData *data)
211 {
212 if (SoftBusMutexLock(&g_pendingLock) != SOFTBUS_OK) {
213 TRANS_LOGE(TRANS_SDK, "mutex lock fail");
214 return SOFTBUS_LOCK_ERR;
215 }
216 PendingPacket *item = NULL;
217 LIST_FOR_EACH_ENTRY(item, &g_pendingList, PendingPacket, node) {
218 if (item->seq == seq && item->id == id) {
219 if (SoftBusMutexLock(&item->lock) != SOFTBUS_OK) {
220 TRANS_LOGE(TRANS_SDK, "mutex lock fail");
221 (void)SoftBusMutexUnlock(&g_pendingLock);
222 return SOFTBUS_LOCK_ERR;
223 }
224 item->finded = true;
225 if (data != NULL) {
226 item->data.data = data->data;
227 item->data.len = data->len;
228 }
229 SoftBusCondSignal(&item->cond);
230 (void)SoftBusMutexUnlock(&item->lock);
231 (void)SoftBusMutexUnlock(&g_pendingLock);
232 return SOFTBUS_OK;
233 }
234 }
235 (void)SoftBusMutexUnlock(&g_pendingLock);
236 return SOFTBUS_NOT_FIND;
237 }