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, &param->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