• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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) != 0) {
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_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_ERR;
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 + 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 || SoftBusMutexLock(&g_pendingLock) != SOFTBUS_OK) {
171         return SOFTBUS_ERR;
172     }
173     PendingPacket *pending = NULL;
174     PendingPacket *item = NULL;
175     LIST_FOR_EACH_ENTRY(item, &g_pendingList, PendingPacket, node) {
176         if (item->id == id && item->seq == seq) {
177             pending = item;
178         }
179     }
180     if (pending == NULL) {
181         (void)SoftBusMutexUnlock(&g_pendingLock);
182         return SOFTBUS_NOT_FIND;
183     }
184     (void)SoftBusMutexUnlock(&g_pendingLock);
185 
186     int32_t ret;
187     if (SoftBusMutexLock(&pending->lock) != SOFTBUS_OK) {
188         ret = SOFTBUS_LOCK_ERR;
189         goto EXIT;
190     }
191     ret = TransPendWaitTime(pending, data, waitMillis);
192     (void)SoftBusMutexUnlock(&pending->lock);
193 EXIT:
194     (void)SoftBusMutexLock(&g_pendingLock);
195     if (isDelete || ret != SOFTBUS_TIMOUT) {
196         ListDelete(&pending->node);
197         SoftBusMutexDestroy(&pending->lock);
198         SoftBusCondDestroy(&pending->cond);
199         SoftBusFree(pending);
200     }
201     (void)SoftBusMutexUnlock(&g_pendingLock);
202     return ret;
203 }
204 
SetPendingPacketData(uint32_t id,uint64_t seq,const TransPendData * data)205 int32_t SetPendingPacketData(uint32_t id, uint64_t seq, const TransPendData *data)
206 {
207     if (SoftBusMutexLock(&g_pendingLock) != SOFTBUS_OK) {
208         TRANS_LOGE(TRANS_SDK, "mutex lock fail");
209         return SOFTBUS_LOCK_ERR;
210     }
211     PendingPacket *item = NULL;
212     LIST_FOR_EACH_ENTRY(item, &g_pendingList, PendingPacket, node) {
213         if (item->seq == seq && item->id == id) {
214             if (SoftBusMutexLock(&item->lock) != SOFTBUS_OK) {
215                 TRANS_LOGE(TRANS_SDK, "mutex lock fail");
216                 (void)SoftBusMutexUnlock(&g_pendingLock);
217                 return SOFTBUS_LOCK_ERR;
218             }
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             (void)SoftBusMutexUnlock(&item->lock);
226             (void)SoftBusMutexUnlock(&g_pendingLock);
227             return SOFTBUS_OK;
228         }
229     }
230     (void)SoftBusMutexUnlock(&g_pendingLock);
231     return SOFTBUS_ERR;
232 }