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