1 /*
2 * Copyright (C) 2021-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 "coap_adapter.h"
17 #include "nstackx_dfinder_log.h"
18 #include "securec.h"
19 #include "nstackx_statistics.h"
20
21 #define COAP_MAX_ENDPOINTS_NUM 64
22 #define COAP_LOW_DELTA_NUM 13
23 #define COAP_MID_DELTA_NUM 256
24 #define COAP_EXTEND_DELTA_VALUE_UINT8 13
25 #define COAP_EXTEND_DELTA_VALUE_UINT16 14
26 #define COAP_EXTEND_DELTA_VALUE_INVALID 15
27 #define COAP_OPTION_MAX_LEN 64
28 #define COAP_OPTION_EXTENSION_LEN 2
29 #define COAP_SHIFT_BIT8 8
30 #define COAP_SHIFT_BIT6 6
31 #define COAP_SHIFT_BIT4 4
32 #define BUF_OFFSET_BYTE2 2
33 #define BUF_OFFSET_BYTE3 3
34 #define BUF_OFFSET_BYTE4 4
35 #define MSGID_HIGHT_BYTE 2
36 #define RAND_DIVISOR 0
37
38 #define TAG "nStackXCoAP"
39
40 typedef struct {
41 CoapPacket *pkt;
42 CoapPacketParam *param;
43 const uint8_t *payload;
44 unsigned long payloadLen;
45 } CoapResponseInfo;
46
47 static uint16_t g_msgId = 0;
48
CoapParseOptionExtension(uint16_t * value,const uint8_t ** dataPos,uint8_t * headerLen,uint32_t bufLen)49 static int32_t CoapParseOptionExtension(uint16_t *value, const uint8_t **dataPos, uint8_t *headerLen, uint32_t bufLen)
50 {
51 if (*value == COAP_EXTEND_DELTA_VALUE_UINT8) {
52 (*headerLen)++;
53 if (bufLen < *headerLen) {
54 DFINDER_LOGE(TAG, "opt invalid cause short for header");
55 return DISCOVERY_ERR_OPT_INVALID_SHORT_FOR_HEADER;
56 }
57
58 *value = (uint16_t)((*dataPos)[1] + COAP_LOW_DELTA_NUM);
59 (*dataPos)++;
60 return DISCOVERY_ERR_SUCCESS;
61 }
62
63 if (*value == COAP_EXTEND_DELTA_VALUE_UINT16) {
64 *headerLen = (uint8_t)(*headerLen + COAP_OPTION_EXTENSION_LEN);
65 if (bufLen < *headerLen) {
66 DFINDER_LOGE(TAG, "opt invalid cause short for header");
67 return DISCOVERY_ERR_OPT_INVALID_SHORT_FOR_HEADER;
68 }
69
70 uint16_t optionDeltaValue = (uint16_t)((*dataPos)[1] << COAP_SHIFT_BIT8) |
71 (*dataPos)[COAP_OPTION_EXTENSION_LEN];
72 if (optionDeltaValue > (0xFFFF - COAP_LOW_DELTA_NUM - COAP_MID_DELTA_NUM)) {
73 DFINDER_LOGE(TAG, "CoapParseOptionExtension bad req");
74 return DISCOVERY_ERR_BAD_REQ;
75 }
76
77 *value = (uint16_t)(optionDeltaValue + COAP_LOW_DELTA_NUM + COAP_MID_DELTA_NUM);
78 (*dataPos) += COAP_OPTION_EXTENSION_LEN;
79 return DISCOVERY_ERR_SUCCESS;
80 }
81
82 if (*value == COAP_EXTEND_DELTA_VALUE_INVALID) {
83 DFINDER_LOGE(TAG, "CoapParseOptionExtension opt invalid delta");
84 return DISCOVERY_ERR_OPT_INVALID_DELTA;
85 }
86
87 return DISCOVERY_ERR_SUCCESS;
88 }
89
CoapParseOption(CoapOption * option,uint16_t * runningDelta,const uint8_t ** buf,uint32_t bufLen)90 static int32_t CoapParseOption(CoapOption *option, uint16_t *runningDelta, const uint8_t **buf, uint32_t bufLen)
91 {
92 const uint8_t *dataPos = NULL;
93 uint8_t headLen;
94 uint16_t len;
95 uint16_t delta;
96 int32_t ret;
97
98 if (bufLen < 1) {
99 DFINDER_LOGE(TAG, "CoapParseOption buf too short");
100 return DISCOVERY_ERR_OPT_INVALID_SHORT_FOR_HEADER;
101 }
102 dataPos = *buf;
103 delta = (dataPos[0] & 0xF0) >> COAP_SHIFT_BIT4;
104 len = dataPos[0] & 0x0F;
105 headLen = 1;
106 ret = CoapParseOptionExtension(&delta, &dataPos, &headLen, bufLen);
107 if (ret != DISCOVERY_ERR_SUCCESS) {
108 return ret;
109 }
110
111 ret = CoapParseOptionExtension(&len, &dataPos, &headLen, bufLen);
112 if (ret != DISCOVERY_ERR_SUCCESS) {
113 return ret;
114 }
115
116 if ((dataPos + 1 + len) > (*buf + bufLen)) {
117 DFINDER_LOGE(TAG, "CoapParseOption dataPos too big");
118 return DISCOVERY_ERR_OPT_INVALID_BIG;
119 }
120
121 option->num = (uint16_t)(delta + *runningDelta);
122 option->optionBuf = dataPos + 1;
123 option->len = len;
124
125 *buf = dataPos + 1 + len;
126 *runningDelta = (uint16_t)(*runningDelta + delta);
127 return DISCOVERY_ERR_SUCCESS;
128 }
129
CoapParseOptionsAndPayloadEx(CoapPacket * pkt,const uint8_t * buf,uint32_t buflen)130 static int32_t CoapParseOptionsAndPayloadEx(CoapPacket *pkt, const uint8_t *buf, uint32_t buflen)
131 {
132 uint8_t optionIndex = 0;
133 uint16_t delta = 0;
134 const uint8_t *dataPos = buf + HEADER_LEN + pkt->header.tokenLen;
135 const uint8_t *end = buf + buflen;
136
137 if (dataPos > end) {
138 DFINDER_LOGE(TAG, "CoapParseOptionsAndPayload overruns pkt");
139 return DISCOVERY_ERR_OPT_OVERRUNS_PKT;
140 }
141
142 while ((dataPos < end) && (*dataPos != 0xFF) && (optionIndex < COAP_MAX_OPTION)) {
143 int32_t ret = CoapParseOption(&((pkt->options)[optionIndex]), &delta, &dataPos, end - dataPos);
144 if (ret != DISCOVERY_ERR_SUCCESS) {
145 return ret;
146 }
147 optionIndex++;
148 }
149
150 if ((dataPos < end) && (*dataPos != 0xFF) && (optionIndex >= COAP_MAX_OPTION)) {
151 DFINDER_LOGE(TAG, "CoapParseOptionsAndPayload server error");
152 return DISCOVERY_ERR_SERVER_ERR;
153 }
154 pkt->optionsNum = optionIndex;
155 if ((dataPos < end) && (*dataPos != 0xFF)) {
156 pkt->payload.buffer = NULL;
157 pkt->payload.len = 0;
158 return DISCOVERY_ERR_SUCCESS;
159 }
160
161 if (dataPos + 1 >= end) {
162 DFINDER_LOGE(TAG, "CoapParseOptionsAndPayload invalid pkt");
163 return DISCOVERY_ERR_INVALID_PKT;
164 }
165
166 pkt->payload.buffer = dataPos + 1;
167 pkt->payload.len = (uint32_t)(end - (dataPos + 1));
168 return DISCOVERY_ERR_SUCCESS;
169 }
170
CoapParseOptionsAndPayload(CoapPacket * pkt,const uint8_t * buf,uint32_t buflen)171 static int32_t CoapParseOptionsAndPayload(CoapPacket *pkt, const uint8_t *buf, uint32_t buflen)
172 {
173 int32_t ret = CoapParseOptionsAndPayloadEx(pkt, buf, buflen);
174 if (ret != DISCOVERY_ERR_SUCCESS) {
175 IncStatistics(STATS_INVALID_OPT_AND_PAYLOAD);
176 }
177 return ret;
178 }
179
CoapParseHeader(CoapPacket * pkt,const uint8_t * buf,uint32_t bufLen)180 static int32_t CoapParseHeader(CoapPacket *pkt, const uint8_t *buf, uint32_t bufLen)
181 {
182 if (bufLen < HEADER_LEN) {
183 DFINDER_LOGE(TAG, "CoapParseHeader header invalid short");
184 return DISCOVERY_ERR_HEADER_INVALID_SHORT;
185 }
186
187 pkt->header.ver = (((uint32_t)buf[0] >> COAP_SHIFT_BIT6) & 0x03);
188 pkt->header.type = ((((uint32_t)buf[0] & 0x30) >> COAP_SHIFT_BIT4) & 0x03);
189 pkt->header.tokenLen = (((uint32_t)buf[0] & 0x0F));
190 pkt->header.code = buf[1];
191 pkt->header.varSection.msgId = (uint16_t)((uint16_t)(buf[MSGID_HIGHT_BYTE] << COAP_SHIFT_BIT8)
192 | buf[BUF_OFFSET_BYTE3]);
193 return DISCOVERY_ERR_SUCCESS;
194 }
195
CoapSoftBusDecodeEx(CoapPacket * pkt,const uint8_t * buf,uint32_t bufLen)196 static int32_t CoapSoftBusDecodeEx(CoapPacket *pkt, const uint8_t *buf, uint32_t bufLen)
197 {
198 int32_t ret;
199 if (pkt == NULL || buf == NULL) {
200 DFINDER_LOGE(TAG, "CoapSoftBusDecode pkt or buf invalid");
201 return -1;
202 }
203
204 if (bufLen == 0) {
205 DFINDER_LOGE(TAG, "CoapSoftBusDecode buflen invalid");
206 return -1;
207 }
208
209 if (pkt->protocol != COAP_UDP) {
210 DFINDER_LOGE(TAG, "CoapSoftBusDecode protocol not coap_udp");
211 return -1;
212 }
213
214 ret = CoapParseHeader(pkt, buf, bufLen);
215 if (ret != DISCOVERY_ERR_SUCCESS) {
216 return ret;
217 }
218
219 if (pkt->header.ver != COAP_VERSION) {
220 DFINDER_LOGE(TAG, "CoapSoftBusDecode protocol header version invalid");
221 return DISCOVERY_ERR_VER_INVALID;
222 }
223
224 if (pkt->header.tokenLen > MAX_TOK_LEN) {
225 DFINDER_LOGE(TAG, "CoapSoftBusDecode protocol header tokenlen invalid");
226 return DISCOVERY_ERR_INVALID_TOKEN_LEN;
227 }
228
229 if ((bufLen > HEADER_LEN) && (pkt->header.code == 0)) {
230 DFINDER_LOGE(TAG, "CoapSoftBusDecode empty msg");
231 return DISCOVERY_ERR_INVALID_EMPTY_MSG;
232 }
233
234 if (pkt->header.tokenLen == 0) {
235 pkt->token.buffer = NULL;
236 pkt->token.len = 0;
237 } else if ((uint32_t)(pkt->header.tokenLen + HEADER_LEN) > bufLen) {
238 DFINDER_LOGE(TAG, "CoapSoftBusDecode token too short");
239 return DISCOVERY_ERR_TOKEN_INVALID_SHORT;
240 } else {
241 pkt->token.buffer = &buf[BUF_OFFSET_BYTE4];
242 pkt->token.len = pkt->header.tokenLen;
243 }
244
245 ret = CoapParseOptionsAndPayload(pkt, buf, bufLen);
246 if (ret != DISCOVERY_ERR_SUCCESS) {
247 return ret;
248 }
249
250 pkt->len = bufLen;
251 return DISCOVERY_ERR_SUCCESS;
252 }
253
CoapSoftBusDecode(CoapPacket * pkt,const uint8_t * buf,uint32_t bufLen)254 int32_t CoapSoftBusDecode(CoapPacket *pkt, const uint8_t *buf, uint32_t bufLen)
255 {
256 int32_t ret = CoapSoftBusDecodeEx(pkt, buf, bufLen);
257 if (ret != DISCOVERY_ERR_SUCCESS) {
258 IncStatistics(STATS_DECODE_FAILED);
259 }
260 return ret;
261 }
262
CoapCreateHeaderEx(CoapPacket * pkt,const CoapPacketParam * pktParam,CoapReadWriteBuffer * buf)263 static int32_t CoapCreateHeaderEx(CoapPacket *pkt, const CoapPacketParam *pktParam, CoapReadWriteBuffer *buf)
264 {
265 if (buf->len != 0) {
266 DFINDER_LOGE(TAG, "CoapCreateHeader invalid argument");
267 return DISCOVERY_ERR_INVALID_ARGUMENT;
268 }
269
270 if ((pktParam->protocol != COAP_UDP) && (pktParam->protocol != COAP_TCP)) {
271 DFINDER_LOGE(TAG, "CoapCreateHeader protocol not udp or tcp");
272 return DISCOVERY_ERR_TRANSPORT_NOT_UDP_OR_TCP;
273 }
274 pkt->protocol = pktParam->protocol;
275
276 if (pktParam->type > COAP_TYPE_RESET) {
277 DFINDER_LOGE(TAG, "CoapCreateHeader unknown msg type");
278 return DISCOVERY_ERR_UNKNOWN_MSG_TYPE;
279 }
280
281 if (buf->size < HEADER_LEN) {
282 DFINDER_LOGE(TAG, "CoapCreateHeader exceed max pdu");
283 return DISCOVERY_ERR_PKT_EXCEED_MAX_PDU;
284 }
285
286 pkt->header.type = (uint32_t)pktParam->type & 0x03;
287 pkt->header.ver = COAP_VERSION;
288 pkt->header.code = COAP_RESPONSE_CODE(pktParam->code);
289
290 if (pkt->protocol == COAP_UDP) {
291 pkt->header.varSection.msgId = pktParam->msgId;
292 buf->readWriteBuf[0] = (char)(pkt->header.ver << COAP_SHIFT_BIT6);
293 buf->readWriteBuf[0] = (char)((uint8_t)buf->readWriteBuf[0] |
294 (uint8_t)(pkt->header.type << COAP_SHIFT_BIT4));
295 buf->readWriteBuf[1] = (char)pkt->header.code;
296 buf->readWriteBuf[BUF_OFFSET_BYTE2] = (char)((pkt->header.varSection.msgId & 0xFF00) >> COAP_SHIFT_BIT8);
297 buf->readWriteBuf[BUF_OFFSET_BYTE3] = (char)(pkt->header.varSection.msgId & 0x00FF);
298 } else {
299 DFINDER_LOGE(TAG, "CoapCreateHeader not supported");
300 return DISCOVERY_ERR_NOT_SUPPORTED;
301 }
302 pkt->len = buf->len = HEADER_LEN;
303 return DISCOVERY_ERR_SUCCESS;
304 }
305
CoapCreateHeader(CoapPacket * pkt,const CoapPacketParam * pktParam,CoapReadWriteBuffer * buf)306 static int32_t CoapCreateHeader(CoapPacket *pkt, const CoapPacketParam *pktParam, CoapReadWriteBuffer *buf)
307 {
308 int32_t ret = CoapCreateHeaderEx(pkt, pktParam, buf);
309 if (ret != DISCOVERY_ERR_SUCCESS) {
310 IncStatistics(STATS_CREATE_HEADER_FAILED);
311 }
312 return ret;
313 }
314
CoapAddData(CoapPacket * pkt,const CoapBuffer * payload,CoapReadWriteBuffer * buf)315 static int32_t CoapAddData(CoapPacket *pkt, const CoapBuffer *payload, CoapReadWriteBuffer *buf)
316 {
317 if ((payload->len == 0) && (payload->buffer == NULL)) {
318 DFINDER_LOGE(TAG, "CoapAddData invalid argument");
319 return DISCOVERY_ERR_INVALID_ARGUMENT;
320 }
321
322 if (buf->len < HEADER_LEN) {
323 DFINDER_LOGE(TAG, "CoapAddData buf invalid argument");
324 return DISCOVERY_ERR_INVALID_ARGUMENT;
325 }
326
327 if ((payload->len > 0xFFFF) || (buf->len + payload->len + 1) > buf->size) {
328 DFINDER_LOGE(TAG, "CoapAddData exceed max pdu");
329 return DISCOVERY_ERR_PKT_EXCEED_MAX_PDU;
330 }
331
332 pkt->payload.len = payload->len;
333 if (payload->len != 0) {
334 pkt->payload.len = payload->len;
335 buf->readWriteBuf[buf->len] = 0xFF;
336 (buf->len)++;
337 pkt->payload.buffer = (const uint8_t *)&buf->readWriteBuf[buf->len];
338 if (memcpy_s(&buf->readWriteBuf[buf->len], buf->size - buf->len, payload->buffer, payload->len) != EOK) {
339 DFINDER_LOGE(TAG, "CoapAddData memcpy fail");
340 return DISCOVERY_ERR_INVALID_ARGUMENT;
341 }
342 }
343
344 buf->len += payload->len;
345 pkt->len = buf->len;
346
347 return DISCOVERY_ERR_SUCCESS;
348 }
349
CoapGetOptionParam(uint16_t value,uint8_t * param)350 static void CoapGetOptionParam(uint16_t value, uint8_t *param)
351 {
352 if (value < COAP_LOW_DELTA_NUM) {
353 *param = (uint8_t)(value & 0xFF);
354 return;
355 }
356
357 if (value < (COAP_LOW_DELTA_NUM + COAP_MID_DELTA_NUM)) {
358 *param = COAP_EXTEND_DELTA_VALUE_UINT8;
359 return;
360 }
361
362 *param = COAP_EXTEND_DELTA_VALUE_UINT16;
363 return;
364 }
365
CoapGetOptionLength(const CoapOption * opt,uint16_t runningDelta)366 static uint16_t CoapGetOptionLength(const CoapOption *opt, uint16_t runningDelta)
367 {
368 uint16_t optionLen = 1;
369 uint8_t delta = 0;
370 uint8_t len = 0;
371
372 CoapGetOptionParam((uint16_t)(opt->num - runningDelta), &delta);
373 if (delta == COAP_EXTEND_DELTA_VALUE_UINT8) {
374 optionLen += 1;
375 } else if (delta == COAP_EXTEND_DELTA_VALUE_UINT16) {
376 optionLen += BUF_OFFSET_BYTE2;
377 }
378
379 CoapGetOptionParam((uint16_t)opt->len, &len);
380 if (len == COAP_EXTEND_DELTA_VALUE_UINT8) {
381 optionLen += 1;
382 } else if (len == COAP_EXTEND_DELTA_VALUE_UINT16) {
383 optionLen += BUF_OFFSET_BYTE2;
384 }
385
386 return optionLen + opt->len;
387 }
388
CoapCheckOption(const CoapPacket * pkt,const CoapOption * option,const CoapReadWriteBuffer * buf)389 static int32_t CoapCheckOption(const CoapPacket *pkt, const CoapOption *option, const CoapReadWriteBuffer *buf)
390 {
391 uint16_t optionLen;
392 uint16_t runningDelta = 0;
393
394 if (buf->len < HEADER_LEN) {
395 DFINDER_LOGE(TAG, "CoapCheckOption buf invalid argument");
396 return DISCOVERY_ERR_INVALID_ARGUMENT;
397 }
398
399 if ((option->optionBuf == NULL) && (option->len != 0)) {
400 DFINDER_LOGE(TAG, "CoapCheckOption invalid argument");
401 return DISCOVERY_ERR_INVALID_ARGUMENT;
402 }
403
404 if ((option->len > 0xFFFF) || (pkt->optionsNum >= COAP_MAX_OPTION)) {
405 DFINDER_LOGE(TAG, "CoapCheckOption bad req");
406 return DISCOVERY_ERR_BAD_REQ;
407 }
408
409 if (pkt->optionsNum != 0) {
410 runningDelta = pkt->options[pkt->optionsNum - 1].num;
411 }
412
413 optionLen = CoapGetOptionLength(option, runningDelta);
414 if ((buf->len + optionLen) > buf->size) {
415 DFINDER_LOGE(TAG, "CoapCheckOption exceed max pdu");
416 return DISCOVERY_ERR_PKT_EXCEED_MAX_PDU;
417 }
418
419 return DISCOVERY_ERR_SUCCESS;
420 }
421
CoapAddOption(CoapPacket * pkt,const CoapOption * option,CoapReadWriteBuffer * buf)422 static int32_t CoapAddOption(CoapPacket *pkt, const CoapOption *option, CoapReadWriteBuffer *buf)
423 {
424 uint8_t delta;
425 uint8_t len;
426 uint16_t optionDelta;
427 uint16_t prevOptionNum;
428
429 if (CoapCheckOption(pkt, option, buf) != DISCOVERY_ERR_SUCCESS) {
430 DFINDER_LOGE(TAG, "CoapAddOption invalid argument");
431 return DISCOVERY_ERR_INVALID_ARGUMENT;
432 }
433
434 prevOptionNum = 0;
435 if (pkt->optionsNum != 0) {
436 prevOptionNum = pkt->options[pkt->optionsNum - 1].num;
437 }
438 optionDelta = option->num - prevOptionNum;
439 CoapGetOptionParam(optionDelta, &delta);
440 CoapGetOptionParam(option->len, &len);
441
442 buf->readWriteBuf[buf->len++] = (char)(((delta << COAP_SHIFT_BIT4) | len) & 0xFF);
443 if (delta == COAP_EXTEND_DELTA_VALUE_UINT8) {
444 buf->readWriteBuf[buf->len++] = (char)(optionDelta - COAP_LOW_DELTA_NUM);
445 } else if (delta == COAP_EXTEND_DELTA_VALUE_UINT16) {
446 buf->readWriteBuf[buf->len++] = (char)((optionDelta - (COAP_LOW_DELTA_NUM + COAP_MID_DELTA_NUM))
447 >> COAP_SHIFT_BIT8);
448 buf->readWriteBuf[buf->len++] = (char)((optionDelta - (COAP_LOW_DELTA_NUM + COAP_MID_DELTA_NUM)) & 0xFF);
449 }
450
451 if (len == COAP_EXTEND_DELTA_VALUE_UINT8) {
452 buf->readWriteBuf[buf->len++] = (char)(option->len - COAP_LOW_DELTA_NUM);
453 } else if (len == COAP_EXTEND_DELTA_VALUE_UINT16) {
454 buf->readWriteBuf[buf->len++] = (char)((option->len - (COAP_LOW_DELTA_NUM + COAP_MID_DELTA_NUM))
455 >> COAP_SHIFT_BIT8);
456 buf->readWriteBuf[buf->len++] = (char)((option->len - (COAP_LOW_DELTA_NUM + COAP_MID_DELTA_NUM)) & 0xFF);
457 }
458
459 if (option->len != 0) {
460 if (memcpy_s(&buf->readWriteBuf[buf->len], buf->size - buf->len, option->optionBuf, option->len) != EOK) {
461 DFINDER_LOGE(TAG, "CoapAddOption memcpy fail");
462 return DISCOVERY_ERR_OPT_INVALID_BIG;
463 }
464 }
465
466 pkt->options[pkt->optionsNum].optionBuf = (const uint8_t *)&buf->readWriteBuf[buf->len];
467 pkt->options[pkt->optionsNum].num = option->num;
468 pkt->options[pkt->optionsNum].len = option->len;
469
470 buf->len += option->len;
471 pkt->len = buf->len;
472 pkt->optionsNum++;
473
474 return DISCOVERY_ERR_SUCCESS;
475 }
476
CoapAddToken(CoapPacket * pkt,const CoapBuffer * token,CoapReadWriteBuffer * buf)477 static int32_t CoapAddToken(CoapPacket *pkt, const CoapBuffer *token, CoapReadWriteBuffer *buf)
478 {
479 if ((token->len != 0) && (token->buffer == NULL)) {
480 DFINDER_LOGE(TAG, "CoapAddToken token invalid argument");
481 return DISCOVERY_ERR_INVALID_ARGUMENT;
482 }
483
484 if (buf->len != HEADER_LEN) {
485 DFINDER_LOGE(TAG, "CoapAddToken buf invalid argument");
486 return DISCOVERY_ERR_INVALID_ARGUMENT;
487 }
488
489 if (token->len > MAX_TOK_LEN) {
490 DFINDER_LOGE(TAG, "CoapAddToken token too long");
491 return DISCOVERY_ERR_INVALID_TOKEN_LEN;
492 }
493
494 if ((buf->len + token->len) > buf->size) {
495 DFINDER_LOGE(TAG, "CoapAddToken exceed max pdu");
496 return DISCOVERY_ERR_PKT_EXCEED_MAX_PDU;
497 }
498
499 pkt->token.len = token->len;
500 pkt->header.tokenLen = pkt->token.len & 0x0F;
501 pkt->token.buffer = (const uint8_t *)&buf->readWriteBuf[buf->len];
502 if (token->len != 0) {
503 if (pkt->protocol == COAP_UDP) {
504 buf->readWriteBuf[0] = (char)((uint8_t)buf->readWriteBuf[0] | token->len);
505 } else {
506 buf->readWriteBuf[BUF_OFFSET_BYTE2] = (char)((uint8_t)buf->readWriteBuf[BUF_OFFSET_BYTE2] | token->len);
507 }
508
509 if (memcpy_s(&buf->readWriteBuf[buf->len], buf->size - buf->len, token->buffer, pkt->header.tokenLen) != EOK) {
510 DFINDER_LOGE(TAG, "CoapAddToken memcpy fail");
511 return DISCOVERY_ERR_INVALID_ARGUMENT;
512 }
513 }
514 buf->len += token->len;
515 pkt->len = buf->len;
516
517 return DISCOVERY_ERR_SUCCESS;
518 }
519
CoapCreateBody(CoapPacket * pkt,const CoapPacketParam * param,const CoapBuffer * token,const CoapBuffer * payload,CoapReadWriteBuffer * buf)520 static int32_t CoapCreateBody(CoapPacket *pkt, const CoapPacketParam *param, const CoapBuffer *token,
521 const CoapBuffer *payload, CoapReadWriteBuffer *buf)
522 {
523 int32_t i;
524 int32_t ret;
525
526 if (token != NULL) {
527 ret = CoapAddToken(pkt, token, buf);
528 if (ret != DISCOVERY_ERR_SUCCESS) {
529 return ret;
530 }
531 }
532
533 if (param->options != 0) {
534 if (param->optionsNum > COAP_MAX_OPTION) {
535 DFINDER_LOGE(TAG, "CoapCreateBody server error");
536 return DISCOVERY_ERR_SERVER_ERR;
537 }
538
539 for (i = 0; i < param->optionsNum; i++) {
540 ret = CoapAddOption(pkt, ¶m->options[i], buf);
541 if (ret != DISCOVERY_ERR_SUCCESS) {
542 return ret;
543 }
544 }
545 }
546
547 if (payload != NULL) {
548 ret = CoapAddData(pkt, payload, buf);
549 if (ret != DISCOVERY_ERR_SUCCESS) {
550 return ret;
551 }
552 }
553
554 return DISCOVERY_ERR_SUCCESS;
555 }
556
CoapSoftBusEncodeEx(CoapPacket * pkt,const CoapPacketParam * param,const CoapBuffer * payload,CoapReadWriteBuffer * buf)557 static int32_t CoapSoftBusEncodeEx(CoapPacket *pkt, const CoapPacketParam *param, const CoapBuffer *payload,
558 CoapReadWriteBuffer *buf)
559 {
560 int32_t ret;
561
562 if (pkt == NULL || param == NULL || buf == NULL || buf->readWriteBuf == NULL) {
563 DFINDER_LOGE(TAG, "CoapSoftBusEncode invalid");
564 return DISCOVERY_ERR_INVALID_EMPTY_MSG;
565 }
566
567 ret = CoapCreateHeader(pkt, param, buf);
568 if (ret != DISCOVERY_ERR_SUCCESS) {
569 return ret;
570 }
571
572 if ((param->code == 0) && ((param->options != NULL) || (payload != NULL))) {
573 DFINDER_LOGE(TAG, "CoapSoftBusEncode empty msg");
574 return DISCOVERY_ERR_INVALID_EMPTY_MSG;
575 }
576
577 ret = CoapCreateBody(pkt, param, NULL, payload, buf);
578 if (ret != DISCOVERY_ERR_SUCCESS) {
579 return ret;
580 }
581
582 return DISCOVERY_ERR_SUCCESS;
583 }
584
CoapSoftBusEncode(CoapPacket * pkt,const CoapPacketParam * param,const CoapBuffer * payload,CoapReadWriteBuffer * buf)585 static int32_t CoapSoftBusEncode(CoapPacket *pkt, const CoapPacketParam *param, const CoapBuffer *payload,
586 CoapReadWriteBuffer *buf)
587 {
588 int32_t ret = CoapSoftBusEncodeEx(pkt, param, payload, buf);
589 if (ret != DISCOVERY_ERR_SUCCESS) {
590 IncStatistics(STATS_ENCODE_FAILED);
591 }
592 return ret;
593 }
594
CoapSoftBusInitMsgId(void)595 void CoapSoftBusInitMsgId(void)
596 {
597 g_msgId = (uint16_t)(RAND_DIVISOR);
598 }
599
CoapSoftBusMsgId(void)600 uint16_t CoapSoftBusMsgId(void)
601 {
602 if (++g_msgId == 0) {
603 g_msgId++;
604 }
605 return g_msgId;
606 }
607
CoapSoftBusBuildMessage(const CoapResponseInfo * resqInfo,CoapReadWriteBuffer * sndPktBuff)608 static int32_t CoapSoftBusBuildMessage(const CoapResponseInfo *resqInfo, CoapReadWriteBuffer *sndPktBuff)
609 {
610 if (resqInfo == NULL || resqInfo->pkt == NULL || resqInfo->param == NULL || sndPktBuff->readWriteBuf == NULL ||
611 resqInfo->payloadLen >= sndPktBuff->size) {
612 return DISCOVERY_ERR_BAD_REQ;
613 }
614
615 int32_t ret;
616 CoapReadWriteBuffer outBuf;
617 CoapBuffer inPayload;
618 (void)memset_s(&outBuf, sizeof(CoapReadWriteBuffer), 0, sizeof(CoapReadWriteBuffer));
619 (void)memset_s(&inPayload, sizeof(CoapBuffer), 0, sizeof(CoapBuffer));
620 outBuf.readWriteBuf = sndPktBuff->readWriteBuf;
621 outBuf.size = sndPktBuff->size;
622 inPayload.buffer = resqInfo->payload;
623 inPayload.len = resqInfo->payloadLen;
624
625 if ((resqInfo->payload == NULL) || (resqInfo->payloadLen == 0)) {
626 ret = CoapSoftBusEncode(resqInfo->pkt, resqInfo->param, NULL, &outBuf);
627 } else {
628 ret = CoapSoftBusEncode(resqInfo->pkt, resqInfo->param, &inPayload, &outBuf);
629 }
630
631 if (ret != DISCOVERY_ERR_SUCCESS) {
632 return DISCOVERY_ERR_BAD_REQ;
633 }
634
635 sndPktBuff->len = outBuf.len;
636 return ret;
637 }
638
BuildCoapPktParam(const CoapBuildParam * buildParam,CoapPacketParam * outParam)639 static void BuildCoapPktParam(const CoapBuildParam *buildParam, CoapPacketParam *outParam)
640 {
641 outParam->protocol = COAP_UDP;
642 outParam->options[outParam->optionsNum].num = DISCOVERY_MSG_URI_HOST;
643 outParam->options[outParam->optionsNum].optionBuf = (uint8_t *)(buildParam->remoteIp);
644 outParam->options[outParam->optionsNum].len = strlen(buildParam->remoteIp);
645 outParam->optionsNum++;
646
647 outParam->options[outParam->optionsNum].num = DISCOVERY_MSG_URI_PATH;
648 outParam->options[outParam->optionsNum].optionBuf = (uint8_t *)(buildParam->uriPath);
649 outParam->options[outParam->optionsNum].len = strlen(buildParam->uriPath);
650 outParam->optionsNum++;
651
652 outParam->type = buildParam->msgType;
653 outParam->code = buildParam->methodType;
654 outParam->msgId = buildParam->msgId;
655 }
656
BuildCoapPktEx(const CoapBuildParam * param,const char * pktPayload,CoapReadWriteBuffer * sndPktBuff,bool isAck)657 static int32_t BuildCoapPktEx(const CoapBuildParam *param, const char *pktPayload,
658 CoapReadWriteBuffer *sndPktBuff, bool isAck)
659 {
660 if (param == NULL || sndPktBuff == NULL || sndPktBuff->readWriteBuf == NULL) {
661 DFINDER_LOGE(TAG, "BuildCoapPkt invalid");
662 return DISCOVERY_ERR_BAD_REQ;
663 }
664
665 if (!isAck && (pktPayload == NULL)) {
666 DFINDER_LOGE(TAG, "BuildCoapPkt bad req");
667 return DISCOVERY_ERR_BAD_REQ;
668 }
669
670 CoapOption options[COAP_MAX_OPTION] = {0};
671 CoapPacketParam outParam = {0};
672 outParam.options = options;
673 BuildCoapPktParam(param, &outParam);
674
675 CoapPacket respPkt = {0};
676 if (isAck) {
677 if (CoapCreateHeader(&respPkt, &outParam, sndPktBuff) != DISCOVERY_ERR_SUCCESS) {
678 return DISCOVERY_ERR_BAD_REQ;
679 }
680 } else {
681 CoapResponseInfo respInfo = {0};
682 respInfo.pkt = &respPkt;
683 respInfo.param = &outParam;
684 respInfo.payload = (uint8_t *)pktPayload;
685 respInfo.payloadLen = strlen(pktPayload) + 1;
686
687 if (CoapSoftBusBuildMessage(&respInfo, sndPktBuff) != DISCOVERY_ERR_SUCCESS) {
688 return DISCOVERY_ERR_BAD_REQ;
689 }
690 }
691
692 if (sndPktBuff->len >= sndPktBuff->size) {
693 DFINDER_LOGE(TAG, "BuildCoapPkt snd pkt buff too long");
694 return DISCOVERY_ERR_BAD_REQ;
695 }
696
697 return DISCOVERY_ERR_SUCCESS;
698 }
699
BuildCoapPkt(const CoapBuildParam * param,const char * pktPayload,CoapReadWriteBuffer * sndPktBuff,bool isAck)700 int32_t BuildCoapPkt(const CoapBuildParam *param, const char *pktPayload, CoapReadWriteBuffer *sndPktBuff, bool isAck)
701 {
702 int32_t ret = BuildCoapPktEx(param, pktPayload, sndPktBuff, isAck);
703 if (ret != DISCOVERY_ERR_SUCCESS) {
704 IncStatistics(STATS_BUILD_PKT_FAILED);
705 }
706 return ret;
707 }
708