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 <stdbool.h>
17
18 #include "softbus_conn_br_pending_packet.h"
19
20 #include "common_list.h"
21 #include "conn_log.h"
22 #include "softbus_adapter_mem.h"
23 #include "softbus_conn_br_connection.h"
24 #include "softbus_conn_br_trans.h"
25 #include "softbus_def.h"
26
27 typedef struct {
28 ListNode node;
29 uint32_t id;
30 int64_t seq;
31 void *data;
32 bool finded;
33 SoftBusCond cond;
34 SoftBusMutex lock;
35 } PendingPacket;
36
37 static SoftBusMutex g_pendingLock;
38 static LIST_HEAD(g_pendingList);
39
ConnBrInitBrPendingPacket(void)40 int32_t ConnBrInitBrPendingPacket(void)
41 {
42 if (SoftBusMutexInit(&g_pendingLock, NULL) != 0) {
43 return SOFTBUS_LOCK_ERR;
44 }
45 return SOFTBUS_OK;
46 }
47
ConnBrCreateBrPendingPacket(uint32_t id,int64_t seq)48 int32_t ConnBrCreateBrPendingPacket(uint32_t id, int64_t seq)
49 {
50 if (SoftBusMutexLock(&g_pendingLock) != SOFTBUS_OK) {
51 return SOFTBUS_LOCK_ERR;
52 }
53 PendingPacket *pending = NULL;
54 LIST_FOR_EACH_ENTRY(pending, &g_pendingList, PendingPacket, node) {
55 if (pending->id == id && pending->seq == seq) {
56 CONN_LOGW(CONN_BR, "PendingPacket exist, id=%{public}u, seq=%{public}" PRId64, id, seq);
57 (void)SoftBusMutexUnlock(&g_pendingLock);
58 return SOFTBUS_ALREADY_EXISTED;
59 }
60 }
61 pending = (PendingPacket *)SoftBusCalloc(sizeof(PendingPacket));
62 if (pending == NULL) {
63 CONN_LOGE(CONN_BR, "calloc failed, id=%{public}u, seq=%{public}" PRId64, id, seq);
64 (void)SoftBusMutexUnlock(&g_pendingLock);
65 return SOFTBUS_MALLOC_ERR;
66 }
67 ListInit(&pending->node);
68 pending->id = id;
69 pending->seq = seq;
70 pending->data = NULL;
71 pending->finded = false;
72 if (SoftBusMutexInit(&pending->lock, NULL) != SOFTBUS_OK) {
73 SoftBusFree(pending);
74 (void)SoftBusMutexUnlock(&g_pendingLock);
75 return SOFTBUS_LOCK_ERR;
76 }
77 if (SoftBusCondInit(&pending->cond) != SOFTBUS_OK) {
78 SoftBusMutexDestroy(&pending->lock);
79 SoftBusFree(pending);
80 (void)SoftBusMutexUnlock(&g_pendingLock);
81 return SOFTBUS_NO_INIT;
82 }
83 ListTailInsert(&g_pendingList, &(pending->node));
84 (void)SoftBusMutexUnlock(&g_pendingLock);
85 return SOFTBUS_OK;
86 }
87
ConnBrDelBrPendingPacket(uint32_t id,int64_t seq)88 void ConnBrDelBrPendingPacket(uint32_t id, int64_t seq)
89 {
90 if (SoftBusMutexLock(&g_pendingLock) != SOFTBUS_OK) {
91 return;
92 }
93 PendingPacket *pending = NULL;
94 LIST_FOR_EACH_ENTRY(pending, &g_pendingList, PendingPacket, node) {
95 if (pending->id == id && pending->seq == seq) {
96 ListDelete(&pending->node);
97 SoftBusCondSignal(&pending->cond);
98 SoftBusMutexDestroy(&pending->lock);
99 SoftBusCondDestroy(&pending->cond);
100 SoftBusFree(pending);
101 break;
102 }
103 }
104 (void)SoftBusMutexUnlock(&g_pendingLock);
105 }
106
ConnBrGetBrPendingPacket(uint32_t id,int64_t seq,uint32_t waitMillis,void ** data)107 int32_t ConnBrGetBrPendingPacket(uint32_t id, int64_t seq, uint32_t waitMillis, void **data)
108 {
109 #define USECTONSEC 1000LL
110 CONN_CHECK_AND_RETURN_RET_LOGW(data != NULL, SOFTBUS_INVALID_PARAM, CONN_BR, "invalid param");
111 CONN_CHECK_AND_RETURN_RET_LOGW(SoftBusMutexLock(&g_pendingLock) == SOFTBUS_OK, SOFTBUS_LOCK_ERR,
112 CONN_BR, "lock failed");
113 PendingPacket *pending = NULL;
114 PendingPacket *item = NULL;
115 LIST_FOR_EACH_ENTRY(item, &g_pendingList, PendingPacket, node) {
116 if (item->id == id && item->seq == seq) {
117 pending = item;
118 }
119 }
120 if (pending == NULL) {
121 (void)SoftBusMutexUnlock(&g_pendingLock);
122 return SOFTBUS_NOT_FIND;
123 }
124 (void)SoftBusMutexUnlock(&g_pendingLock);
125
126 int32_t ret = SOFTBUS_OK;
127 if (SoftBusMutexLock(&pending->lock) != SOFTBUS_OK) {
128 ret = SOFTBUS_LOCK_ERR;
129 goto EXIT;
130 }
131 if (pending->finded) {
132 *data = pending->data;
133 ret = SOFTBUS_ALREADY_TRIGGERED;
134 } else {
135 SoftBusSysTime outtime;
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 (void)SoftBusCondWait(&pending->cond, &pending->lock, &outtime);
142 if (pending->finded) {
143 *data = pending->data;
144 } else {
145 ret = SOFTBUS_TIMOUT;
146 }
147 }
148 (void)SoftBusMutexUnlock(&pending->lock);
149 EXIT:
150 (void)SoftBusMutexLock(&g_pendingLock);
151 ListDelete(&pending->node);
152 SoftBusMutexDestroy(&pending->lock);
153 SoftBusCondDestroy(&pending->cond);
154 SoftBusFree(pending);
155 (void)SoftBusMutexUnlock(&g_pendingLock);
156 return ret;
157 }
158
ConnBrSetBrPendingPacket(uint32_t id,int64_t seq,void * data)159 int32_t ConnBrSetBrPendingPacket(uint32_t id, int64_t seq, void *data)
160 {
161 PendingPacket *item = NULL;
162 if (SoftBusMutexLock(&g_pendingLock) != SOFTBUS_OK) {
163 CONN_LOGE(CONN_BR, "lock failed");
164 return SOFTBUS_LOCK_ERR;
165 }
166 LIST_FOR_EACH_ENTRY(item, &g_pendingList, PendingPacket, node) {
167 if (item->seq == seq && item->id == id) {
168 if (SoftBusMutexLock(&item->lock) != SOFTBUS_OK) {
169 SoftBusMutexUnlock(&g_pendingLock);
170 return SOFTBUS_LOCK_ERR;
171 }
172 item->finded = true;
173 item->data = data;
174 SoftBusCondSignal(&item->cond);
175 SoftBusMutexUnlock(&item->lock);
176 SoftBusMutexUnlock(&g_pendingLock);
177 return SOFTBUS_OK;
178 }
179 }
180 SoftBusMutexUnlock(&g_pendingLock);
181 return SOFTBUS_CONN_BR_SET_PENDING_PACKET_ERR;
182 }
183
ConnBrOnAckRequest(ConnBrConnection * connection,const cJSON * json)184 int32_t ConnBrOnAckRequest(ConnBrConnection *connection, const cJSON *json)
185 {
186 CONN_CHECK_AND_RETURN_RET_LOGW(connection != NULL, SOFTBUS_INVALID_PARAM, CONN_BR, "invalid param");
187 int32_t peerWindows = 0;
188 int64_t peerSeq = 0;
189 if (!GetJsonObjectSignedNumberItem(json, KEY_WINDOWS, &peerWindows) ||
190 !GetJsonObjectNumber64Item(json, KEY_ACK_SEQ_NUM, &peerSeq)) {
191 CONN_LOGE(CONN_BR, "parse window or seq failed, connId=%{public}u", connection->connectionId);
192 return SOFTBUS_PARSE_JSON_ERR;
193 }
194
195 int32_t status = SoftBusMutexLock(&connection->lock);
196 if (status != SOFTBUS_OK) {
197 CONN_LOGE(CONN_BR, "lock failed, connId=%{public}u, error=%{public}d", connection->connectionId, status);
198 return SOFTBUS_LOCK_ERR;
199 }
200
201 int32_t localWindows = connection->window;
202 (void)SoftBusMutexUnlock(&connection->lock);
203
204 CONN_LOGD(CONN_BR,
205 "ack request message: connId=%{public}u, localWindow=%{public}d, peerWindow=%{public}d, "
206 "peerSeq=%{public}" PRId64,
207 connection->connectionId, localWindows, peerWindows, peerSeq);
208
209 int32_t flag = CONN_HIGH;
210 BrCtlMessageSerializationContext ctx = {
211 .connectionId = connection->connectionId,
212 .flag = flag,
213 .method = BR_METHOD_ACK_RESPONSE,
214 .ackRequestResponse = {
215 .window = localWindows,
216 .seq = peerSeq,
217 },
218 };
219 uint8_t *data = NULL;
220 uint32_t dataLen = 0;
221 int64_t seq = ConnBrPackCtlMessage(ctx, &data, &dataLen);
222 if (seq < 0) {
223 CONN_LOGE(CONN_BR,
224 "pack msg failed: connId=%{public}u, localWindow=%{public}d, peeWindow=%{public}d, "
225 "peerSeq=%{public}" PRId64 ", error=%{public}d",
226 connection->connectionId, localWindows, peerWindows, peerSeq, (int32_t)seq);
227 return (int32_t)seq;
228 }
229 return ConnBrPostBytes(connection->connectionId, data, dataLen, 0, flag, MODULE_CONNECTION, seq);
230 }
231
ConnBrOnAckResponse(ConnBrConnection * connection,const cJSON * json)232 int32_t ConnBrOnAckResponse(ConnBrConnection *connection, const cJSON *json)
233 {
234 int32_t peerWindows = 0;
235 uint64_t seq = 0;
236 if (!GetJsonObjectSignedNumberItem(json, KEY_WINDOWS, &peerWindows) ||
237 !GetJsonObjectNumber64Item(json, KEY_ACK_SEQ_NUM, (int64_t *)&seq)) {
238 CONN_LOGE(CONN_BR, "parse window or seq fields failed, connId=%{public}u", connection->connectionId);
239 return SOFTBUS_PARSE_JSON_ERR;
240 }
241 CONN_LOGD(CONN_BR, "connId=%{public}u, peerWindow=%{public}d, seq=%{public}" PRId64, connection->connectionId,
242 peerWindows, seq);
243 int32_t status = ConnBrSetBrPendingPacket(connection->connectionId, (int64_t)seq, NULL);
244 if (status != SOFTBUS_OK) {
245 CONN_LOGE(CONN_BR,
246 "set br pending packet failed, connId=%{public}u, error=%{public}d", connection->connectionId, status);
247 }
248 return status;
249 }
250