• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }