1 /*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(net_test, LOG_LEVEL_DBG);
9
10 #include <errno.h>
11 #include <zephyr/types.h>
12 #include <stdbool.h>
13 #include <stddef.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <zephyr/sys/printk.h>
17 #include <zephyr/kernel.h>
18 #include <zephyr/sys/util.h>
19 #include <zephyr/net/coap.h>
20
21 #include <zephyr/tc_util.h>
22 #include <zephyr/ztest.h>
23
24 #include "net_private.h"
25
26 #define COAP_BUF_SIZE 128
27 #define COAP_FIXED_HEADER_SIZE 4
28
29 #define NUM_PENDINGS 3
30 #define NUM_OBSERVERS 3
31 #define NUM_REPLIES 3
32
33 static struct coap_pending pendings[NUM_PENDINGS];
34 static struct coap_observer observers[NUM_OBSERVERS];
35 static struct coap_reply replies[NUM_REPLIES];
36
37 /* This is exposed for this test in subsys/net/lib/coap/coap_link_format.c */
38 bool _coap_match_path_uri(const char * const *path,
39 const char *uri, uint16_t len);
40
41 /* Some forward declarations */
42 static void server_resource_1_callback(struct coap_resource *resource,
43 struct coap_observer *observer);
44
45 static void server_resource_2_callback(struct coap_resource *resource,
46 struct coap_observer *observer);
47
48 static int server_resource_1_get(struct coap_resource *resource,
49 struct coap_packet *request,
50 struct sockaddr *addr, socklen_t addr_len);
51
52 static const char * const server_resource_1_path[] = { "s", "1", NULL };
53 static const char *const server_resource_2_path[] = { "s", "2", NULL };
54 static struct coap_resource server_resources[] = {
55 { .path = server_resource_1_path,
56 .get = server_resource_1_get,
57 .notify = server_resource_1_callback },
58 { .path = server_resource_2_path,
59 .get = server_resource_1_get, /* Get can be shared with the first resource */
60 .notify = server_resource_2_callback },
61 { },
62 };
63
64 #define MY_PORT 12345
65 #define peer_addr { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, \
66 0, 0, 0, 0, 0, 0, 0, 0x2 } } }
67 static struct sockaddr_in6 dummy_addr = {
68 .sin6_family = AF_INET6,
69 .sin6_addr = peer_addr };
70
71 static uint8_t data_buf[2][COAP_BUF_SIZE];
72
73 #define COAP_ROLLOVER_AGE (1 << 23)
74 #define COAP_MAX_AGE 0xffffff
75 #define COAP_FIRST_AGE 2
76
77 extern bool coap_age_is_newer(int v1, int v2);
78
ZTEST(coap,test_build_empty_pdu)79 ZTEST(coap, test_build_empty_pdu)
80 {
81 uint8_t result_pdu[] = { 0x40, 0x01, 0x0, 0x0 };
82 struct coap_packet cpkt;
83 uint8_t *data = data_buf[0];
84 int r;
85
86 r = coap_packet_init(&cpkt, data, COAP_BUF_SIZE,
87 COAP_VERSION_1, COAP_TYPE_CON, 0, NULL,
88 COAP_METHOD_GET, 0);
89
90 zassert_equal(r, 0, "Could not initialize packet");
91 zassert_equal(cpkt.offset, sizeof(result_pdu),
92 "Different size from the reference packet");
93 zassert_equal(cpkt.hdr_len, COAP_FIXED_HEADER_SIZE,
94 "Invalid header length");
95 zassert_equal(cpkt.opt_len, 0, "Invalid options length");
96 zassert_mem_equal(result_pdu, cpkt.data, cpkt.offset,
97 "Built packet doesn't match reference packet");
98 }
99
ZTEST(coap,test_build_simple_pdu)100 ZTEST(coap, test_build_simple_pdu)
101 {
102 uint8_t result_pdu[] = { 0x55, 0xA5, 0x12, 0x34, 't', 'o', 'k', 'e',
103 'n', 0xC0, 0xFF, 'p', 'a', 'y', 'l',
104 'o', 'a', 'd', 0x00 };
105 struct coap_packet cpkt;
106 const char token[] = "token";
107 static const char payload[] = "payload";
108 uint8_t *data = data_buf[0];
109 const uint8_t *payload_start;
110 uint16_t payload_len;
111 int r;
112
113 r = coap_packet_init(&cpkt, data, COAP_BUF_SIZE,
114 COAP_VERSION_1, COAP_TYPE_NON_CON,
115 strlen(token), token,
116 COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED,
117 0x1234);
118 zassert_equal(r, 0, "Could not initialize packet");
119
120 r = coap_append_option_int(&cpkt, COAP_OPTION_CONTENT_FORMAT,
121 COAP_CONTENT_FORMAT_TEXT_PLAIN);
122 zassert_equal(r, 0, "Could not append option");
123
124 r = coap_packet_append_payload_marker(&cpkt);
125 zassert_equal(r, 0, "Failed to set the payload marker");
126
127 r = coap_packet_append_payload(&cpkt, payload, sizeof(payload));
128 zassert_equal(r, 0, "Failed to set the payload");
129
130 zassert_equal(cpkt.offset, sizeof(result_pdu),
131 "Different size from the reference packet");
132 zassert_equal(cpkt.hdr_len, COAP_FIXED_HEADER_SIZE + strlen(token),
133 "Invalid header length");
134 zassert_equal(cpkt.opt_len, 1, "Invalid options length");
135 zassert_mem_equal(result_pdu, cpkt.data, cpkt.offset,
136 "Built packet doesn't match reference packet");
137
138 payload_start = coap_packet_get_payload(&cpkt, &payload_len);
139
140 zassert_equal(payload_len, sizeof(payload), "Invalid payload length");
141 zassert_equal_ptr(payload_start, cpkt.data + cpkt.offset - payload_len,
142 "Invalid payload pointer");
143 }
144
145 /* No options, No payload */
ZTEST(coap,test_parse_empty_pdu)146 ZTEST(coap, test_parse_empty_pdu)
147 {
148 uint8_t pdu[] = { 0x40, 0x01, 0, 0 };
149 struct coap_packet cpkt;
150 uint8_t *data = data_buf[0];
151 uint8_t ver;
152 uint8_t type;
153 uint8_t code;
154 uint16_t id;
155 int r;
156
157 memcpy(data, pdu, sizeof(pdu));
158
159 r = coap_packet_parse(&cpkt, data, sizeof(pdu), NULL, 0);
160 zassert_equal(r, 0, "Could not parse packet");
161
162 zassert_equal(cpkt.offset, sizeof(pdu),
163 "Different size from the reference packet");
164 zassert_equal(cpkt.hdr_len, COAP_FIXED_HEADER_SIZE,
165 "Invalid header length");
166 zassert_equal(cpkt.opt_len, 0, "Invalid options length");
167
168 ver = coap_header_get_version(&cpkt);
169 type = coap_header_get_type(&cpkt);
170 code = coap_header_get_code(&cpkt);
171 id = coap_header_get_id(&cpkt);
172
173 zassert_equal(ver, 1U, "Invalid version for parsed packet");
174 zassert_equal(type, COAP_TYPE_CON,
175 "Packet type doesn't match reference");
176 zassert_equal(code, COAP_METHOD_GET,
177 "Packet code doesn't match reference");
178 zassert_equal(id, 0U, "Packet id doesn't match reference");
179 }
180
181 /* 1 option, No payload (No payload marker) */
ZTEST(coap,test_parse_empty_pdu_1)182 ZTEST(coap, test_parse_empty_pdu_1)
183 {
184 uint8_t pdu[] = { 0x40, 0x01, 0, 0, 0x40};
185 struct coap_packet cpkt;
186 uint8_t *data = data_buf[0];
187 uint8_t ver;
188 uint8_t type;
189 uint8_t code;
190 uint16_t id;
191 int r;
192
193 memcpy(data, pdu, sizeof(pdu));
194
195 r = coap_packet_parse(&cpkt, data, sizeof(pdu), NULL, 0);
196 zassert_equal(r, 0, "Could not parse packet");
197
198 zassert_equal(cpkt.offset, sizeof(pdu),
199 "Different size from the reference packet");
200 zassert_equal(cpkt.hdr_len, COAP_FIXED_HEADER_SIZE,
201 "Invalid header length");
202 zassert_equal(cpkt.opt_len, 1, "Invalid options length");
203
204 ver = coap_header_get_version(&cpkt);
205 type = coap_header_get_type(&cpkt);
206 code = coap_header_get_code(&cpkt);
207 id = coap_header_get_id(&cpkt);
208
209 zassert_equal(ver, 1U, "Invalid version for parsed packet");
210 zassert_equal(type, COAP_TYPE_CON,
211 "Packet type doesn't match reference");
212 zassert_equal(code, COAP_METHOD_GET,
213 "Packet code doesn't match reference");
214 zassert_equal(id, 0U, "Packet id doesn't match reference");
215 }
216
ZTEST(coap,test_parse_simple_pdu)217 ZTEST(coap, test_parse_simple_pdu)
218 {
219 uint8_t pdu[] = { 0x55, 0xA5, 0x12, 0x34, 't', 'o', 'k', 'e', 'n',
220 0x00, 0xc1, 0x00, 0xff, 'p', 'a', 'y', 'l', 'o',
221 'a', 'd', 0x00 };
222 struct coap_packet cpkt;
223 struct coap_option options[16] = {};
224 const uint8_t token[8];
225 const uint8_t payload[] = "payload";
226 uint8_t *data = data_buf[0];
227 uint8_t ver;
228 uint8_t type;
229 uint8_t code;
230 uint8_t tkl;
231 uint16_t id;
232 const uint8_t *payload_start;
233 uint16_t payload_len;
234 int r, count = ARRAY_SIZE(options) - 1;
235
236 memcpy(data, pdu, sizeof(pdu));
237
238 r = coap_packet_parse(&cpkt, data, sizeof(pdu), NULL, 0);
239 zassert_equal(r, 0, "Could not parse packet");
240
241 zassert_equal(cpkt.offset, sizeof(pdu),
242 "Different size from the reference packet");
243 zassert_equal(cpkt.hdr_len, COAP_FIXED_HEADER_SIZE + strlen("token"),
244 "Invalid header length");
245 zassert_equal(cpkt.opt_len, 3, "Invalid options length");
246
247 payload_start = coap_packet_get_payload(&cpkt, &payload_len);
248
249 zassert_equal(payload_len, sizeof(payload), "Invalid payload length");
250 zassert_equal_ptr(payload_start, cpkt.data + cpkt.offset - payload_len,
251 "Invalid payload pointer");
252
253 ver = coap_header_get_version(&cpkt);
254 type = coap_header_get_type(&cpkt);
255 code = coap_header_get_code(&cpkt);
256 id = coap_header_get_id(&cpkt);
257
258 zassert_equal(ver, 1U, "Invalid version for parsed packet");
259 zassert_equal(type, COAP_TYPE_NON_CON,
260 "Packet type doesn't match reference");
261 zassert_equal(code, COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED,
262 "Packet code doesn't match reference");
263 zassert_equal(id, 0x1234, "Packet id doesn't match reference");
264
265 tkl = coap_header_get_token(&cpkt, (uint8_t *)token);
266
267 zassert_equal(tkl, 5U, "Token length doesn't match reference");
268 zassert_mem_equal(token, "token", tkl,
269 "Token value doesn't match the reference");
270
271 count = coap_find_options(&cpkt, COAP_OPTION_CONTENT_FORMAT,
272 options, count);
273
274 zassert_equal(count, 1, "Unexpected number of options in the packet");
275 zassert_equal(options[0].len, 1U,
276 "Option length doesn't match the reference");
277 zassert_equal(((uint8_t *)options[0].value)[0],
278 COAP_CONTENT_FORMAT_TEXT_PLAIN,
279 "Option value doesn't match the reference");
280
281 /* Not existent */
282 count = coap_find_options(&cpkt, COAP_OPTION_ETAG, options, count);
283
284 zassert_equal(count, 0,
285 "There shouldn't be any ETAG option in the packet");
286 }
287
ZTEST(coap,test_parse_malformed_pkt)288 ZTEST(coap, test_parse_malformed_pkt)
289 {
290 uint8_t opt[] = { 0x55, 0xA5, 0x12 };
291
292 struct coap_packet cpkt;
293 uint8_t *data = data_buf[0];
294 int r;
295
296 r = coap_packet_parse(&cpkt, NULL, sizeof(opt), NULL, 0);
297 zassert_equal(r, -EINVAL, "Should've failed to parse a packet");
298
299 r = coap_packet_parse(&cpkt, data, 0, NULL, 0);
300 zassert_equal(r, -EINVAL, "Should've failed to parse a packet");
301
302 memcpy(data, opt, sizeof(opt));
303 r = coap_packet_parse(&cpkt, data, sizeof(opt), NULL, 0);
304 zassert_equal(r, -EINVAL, "Should've failed to parse a packet");
305 }
306
ZTEST(coap,test_parse_malformed_coap_hdr)307 ZTEST(coap, test_parse_malformed_coap_hdr)
308 {
309 uint8_t opt[] = { 0x55, 0x24, 0x49, 0x55, 0xff, 0x66, 0x77, 0x99};
310
311 struct coap_packet cpkt;
312 uint8_t *data = data_buf[0];
313 int r;
314
315 memcpy(data, opt, sizeof(opt));
316 r = coap_packet_parse(&cpkt, data, sizeof(opt), NULL, 0);
317 zassert_equal(r, -EBADMSG, "Should've failed to parse a packet");
318 }
319
ZTEST(coap,test_parse_malformed_opt)320 ZTEST(coap, test_parse_malformed_opt)
321 {
322 uint8_t opt[] = { 0x55, 0xA5, 0x12, 0x34, 't', 'o', 'k', 'e', 'n',
323 0xD0 };
324 struct coap_packet cpkt;
325 uint8_t *data = data_buf[0];
326 int r;
327
328 memcpy(data, opt, sizeof(opt));
329
330 r = coap_packet_parse(&cpkt, data, sizeof(opt), NULL, 0);
331 zassert_equal(r, -EILSEQ, "Should've failed to parse a packet");
332 }
333
ZTEST(coap,test_parse_malformed_opt_len)334 ZTEST(coap, test_parse_malformed_opt_len)
335 {
336 uint8_t opt[] = { 0x55, 0xA5, 0x12, 0x34, 't', 'o', 'k', 'e', 'n',
337 0xC1 };
338 struct coap_packet cpkt;
339 uint8_t *data = data_buf[0];
340 int r;
341
342 memcpy(data, opt, sizeof(opt));
343
344 r = coap_packet_parse(&cpkt, data, sizeof(opt), NULL, 0);
345 zassert_equal(r, -EILSEQ, "Should've failed to parse a packet");
346 }
347
ZTEST(coap,test_parse_malformed_opt_ext)348 ZTEST(coap, test_parse_malformed_opt_ext)
349 {
350 uint8_t opt[] = { 0x55, 0xA5, 0x12, 0x34, 't', 'o', 'k', 'e', 'n',
351 0xE0, 0x01 };
352 struct coap_packet cpkt;
353 uint8_t *data = data_buf[0];
354 int r;
355
356 memcpy(data, opt, sizeof(opt));
357
358 r = coap_packet_parse(&cpkt, data, sizeof(opt), NULL, 0);
359 zassert_equal(r, -EILSEQ, "Should've failed to parse a packet");
360 }
361
ZTEST(coap,test_parse_malformed_opt_len_ext)362 ZTEST(coap, test_parse_malformed_opt_len_ext)
363 {
364 uint8_t opt[] = { 0x55, 0xA5, 0x12, 0x34, 't', 'o', 'k', 'e', 'n',
365 0xEE, 0x01, 0x02, 0x01};
366 struct coap_packet cpkt;
367 uint8_t *data = data_buf[0];
368 int r;
369
370 memcpy(data, opt, sizeof(opt));
371
372 r = coap_packet_parse(&cpkt, data, sizeof(opt), NULL, 0);
373 zassert_equal(r, -EILSEQ, "Should've failed to parse a packet");
374 }
375
376 /* 1 option, No payload (with payload marker) */
ZTEST(coap,test_parse_malformed_marker)377 ZTEST(coap, test_parse_malformed_marker)
378 {
379 uint8_t pdu[] = { 0x40, 0x01, 0, 0, 0x40, 0xFF};
380 struct coap_packet cpkt;
381 uint8_t *data = data_buf[0];
382 int r;
383
384 memcpy(data, pdu, sizeof(pdu));
385
386 r = coap_packet_parse(&cpkt, data, sizeof(pdu), NULL, 0);
387 zassert_not_equal(r, 0, "Should've failed to parse a packet");
388 }
389
ZTEST(coap,test_parse_req_build_ack)390 ZTEST(coap, test_parse_req_build_ack)
391 {
392 uint8_t pdu[] = { 0x45, 0xA5, 0x12, 0x34, 't', 'o', 'k', 'e', 'n',
393 0x00, 0xc1, 0x00, 0xff, 'p', 'a', 'y', 'l', 'o',
394 'a', 'd', 0x00 };
395 uint8_t ack_pdu[] = { 0x65, 0x80, 0x12, 0x34, 't', 'o', 'k', 'e', 'n' };
396 struct coap_packet cpkt;
397 struct coap_packet ack_cpkt;
398 uint8_t *data = data_buf[0];
399 uint8_t *ack_data = data_buf[1];
400 int r;
401
402 memcpy(data, pdu, sizeof(pdu));
403
404 r = coap_packet_parse(&cpkt, data, sizeof(pdu), NULL, 0);
405 zassert_equal(r, 0, "Could not parse packet");
406
407 r = coap_ack_init(&ack_cpkt, &cpkt, ack_data, COAP_BUF_SIZE,
408 COAP_RESPONSE_CODE_BAD_REQUEST);
409 zassert_equal(r, 0, "Could not initialize ACK packet");
410
411 zassert_equal(ack_cpkt.offset, sizeof(ack_pdu),
412 "Different size from the reference packet");
413 zassert_mem_equal(ack_pdu, ack_cpkt.data, ack_cpkt.offset,
414 "Built packet doesn't match reference packet");
415 }
416
ZTEST(coap,test_parse_req_build_empty_ack)417 ZTEST(coap, test_parse_req_build_empty_ack)
418 {
419 uint8_t pdu[] = { 0x45, 0xA5, 0xDE, 0xAD, 't', 'o', 'k', 'e', 'n',
420 0x00, 0xc1, 0x00, 0xff, 'p', 'a', 'y', 'l', 'o',
421 'a', 'd', 0x00 };
422 uint8_t ack_pdu[] = { 0x60, 0x00, 0xDE, 0xAD };
423 struct coap_packet cpkt;
424 struct coap_packet ack_cpkt;
425 uint8_t *data = data_buf[0];
426 uint8_t *ack_data = data_buf[1];
427 int r;
428
429 memcpy(data, pdu, sizeof(pdu));
430
431 r = coap_packet_parse(&cpkt, data, sizeof(pdu), NULL, 0);
432 zassert_equal(r, 0, "Could not parse packet");
433
434 r = coap_ack_init(&ack_cpkt, &cpkt, ack_data, COAP_BUF_SIZE,
435 COAP_CODE_EMPTY);
436 zassert_equal(r, 0, "Could not initialize ACK packet");
437
438 zassert_equal(ack_cpkt.offset, sizeof(ack_pdu),
439 "Different size from the reference packet");
440 zassert_mem_equal(ack_pdu, ack_cpkt.data, ack_cpkt.offset,
441 "Built packet doesn't match reference packet");
442 }
443
ZTEST(coap,test_match_path_uri)444 ZTEST(coap, test_match_path_uri)
445 {
446 const char * const resource_path[] = {
447 "s",
448 "1",
449 "foobar",
450 "foobar3a",
451 "foobar3",
452 "devnull",
453 NULL
454 };
455 const char *uri;
456 int r;
457
458 uri = "/k";
459 r = _coap_match_path_uri(resource_path, uri, strlen(uri));
460 zassert_false(r, "Matching %s failed", uri);
461
462 uri = "/s";
463 r = _coap_match_path_uri(resource_path, uri, strlen(uri));
464 zassert_true(r, "Matching %s failed", uri);
465
466 uri = "/foobar";
467 r = _coap_match_path_uri(resource_path, uri, strlen(uri));
468 zassert_true(r, "Matching %s failed", uri);
469
470 uri = "/foobar2";
471 r = _coap_match_path_uri(resource_path, uri, strlen(uri));
472 zassert_false(r, "Matching %s failed", uri);
473
474 uri = "/foobar*";
475 r = _coap_match_path_uri(resource_path, uri, strlen(uri));
476 zassert_true(r, "Matching %s failed", uri);
477
478 uri = "/foobar3*";
479 r = _coap_match_path_uri(resource_path, uri, strlen(uri));
480 zassert_true(r, "Matching %s failed", uri);
481
482 uri = "/devnull*";
483 r = _coap_match_path_uri(resource_path, uri, strlen(uri));
484 zassert_false(r, "Matching %s failed", uri);
485 }
486
487 #define BLOCK_WISE_TRANSFER_SIZE_GET 150
488
prepare_block1_request(struct coap_packet * req,struct coap_block_context * req_ctx,int * more)489 static void prepare_block1_request(struct coap_packet *req,
490 struct coap_block_context *req_ctx,
491 int *more)
492 {
493 const char token[] = "token";
494 uint8_t payload[32] = { 0 };
495 uint8_t *data = data_buf[0];
496 bool first;
497 int r;
498 int block_size = coap_block_size_to_bytes(COAP_BLOCK_32);
499 int payload_len;
500
501 /* Request Context */
502 if (req_ctx->total_size == 0) {
503 first = true;
504 coap_block_transfer_init(req_ctx, COAP_BLOCK_32,
505 BLOCK_WISE_TRANSFER_SIZE_GET);
506 } else {
507 first = false;
508 }
509
510 r = coap_packet_init(req, data, COAP_BUF_SIZE, COAP_VERSION_1,
511 COAP_TYPE_CON, strlen(token),
512 token, COAP_METHOD_POST,
513 coap_next_id());
514 zassert_equal(r, 0, "Unable to initialize request");
515
516 r = coap_append_block1_option(req, req_ctx);
517 zassert_equal(r, 0, "Unable to append block1 option");
518
519 if (first) {
520 r = coap_append_size1_option(req, req_ctx);
521 zassert_equal(r, 0, "Unable to append size1 option");
522 }
523
524 r = coap_packet_append_payload_marker(req);
525 zassert_equal(r, 0, "Unable to append payload marker");
526
527 payload_len = req_ctx->total_size - req_ctx->current;
528 if (payload_len > block_size) {
529 payload_len = block_size;
530 }
531
532 r = coap_packet_append_payload(req, payload, payload_len);
533 zassert_equal(r, 0, "Unable to append payload");
534
535 *more = coap_next_block(req, req_ctx);
536 }
537
prepare_block1_response(struct coap_packet * rsp,struct coap_block_context * rsp_ctx,struct coap_packet * req)538 static void prepare_block1_response(struct coap_packet *rsp,
539 struct coap_block_context *rsp_ctx,
540 struct coap_packet *req)
541 {
542 uint8_t token[8];
543 uint8_t *data = data_buf[1];
544 uint16_t id;
545 uint8_t tkl;
546 int r;
547
548 if (rsp_ctx->total_size == 0) {
549 coap_block_transfer_init(rsp_ctx, COAP_BLOCK_32,
550 BLOCK_WISE_TRANSFER_SIZE_GET);
551 }
552
553 r = coap_update_from_block(req, rsp_ctx);
554 zassert_equal(r, 0, "Failed to read block option");
555
556 id = coap_header_get_id(req);
557 tkl = coap_header_get_token(req, token);
558
559 r = coap_packet_init(rsp, data, COAP_BUF_SIZE, COAP_VERSION_1,
560 COAP_TYPE_ACK, tkl, token,
561 COAP_RESPONSE_CODE_CREATED, id);
562 zassert_equal(r, 0, "Unable to initialize request");
563
564 r = coap_append_block1_option(rsp, rsp_ctx);
565 zassert_equal(r, 0, "Unable to append block1 option");
566 }
567
568 #define ITER_COUNT(len, block_len) DIV_ROUND_UP(len, block_len)
569
verify_block1_request(struct coap_block_context * req_ctx,uint8_t iter)570 static void verify_block1_request(struct coap_block_context *req_ctx,
571 uint8_t iter)
572 {
573 int block_size = coap_block_size_to_bytes(COAP_BLOCK_32);
574 int iter_max = ITER_COUNT(BLOCK_WISE_TRANSFER_SIZE_GET, block_size);
575
576 zassert_equal(req_ctx->block_size, COAP_BLOCK_32,
577 "req:%d,Couldn't get block size", iter);
578
579 /* In last iteration "current" must match "total_size" */
580 if (iter < iter_max) {
581 zassert_equal(
582 req_ctx->current, block_size * iter,
583 "req:%d,Couldn't get the current block position", iter);
584 } else {
585 zassert_equal(
586 req_ctx->current, req_ctx->total_size,
587 "req:%d,Couldn't get the current block position", iter);
588 }
589
590 zassert_equal(req_ctx->total_size, BLOCK_WISE_TRANSFER_SIZE_GET,
591 "req:%d,Couldn't packet total size", iter);
592 }
593
verify_block1_response(struct coap_block_context * rsp_ctx,uint8_t iter)594 static void verify_block1_response(struct coap_block_context *rsp_ctx,
595 uint8_t iter)
596 {
597 zassert_equal(rsp_ctx->block_size, COAP_BLOCK_32,
598 "rsp:%d,Couldn't get block size", iter);
599 zassert_equal(rsp_ctx->current,
600 coap_block_size_to_bytes(COAP_BLOCK_32) * (iter - 1U),
601 "rsp:%d, Couldn't get the current block position", iter);
602 zassert_equal(rsp_ctx->total_size, BLOCK_WISE_TRANSFER_SIZE_GET,
603 "rsp:%d, Couldn't packet total size", iter);
604 }
605
ZTEST(coap,test_block1_size)606 ZTEST(coap, test_block1_size)
607 {
608 struct coap_block_context req_ctx;
609 struct coap_block_context rsp_ctx;
610 struct coap_packet req;
611 struct coap_packet rsp;
612 int more;
613 uint8_t i;
614
615 i = 0U;
616 more = 1;
617 memset(&req_ctx, 0, sizeof(req_ctx));
618 memset(&rsp_ctx, 0, sizeof(rsp_ctx));
619
620 while (more) {
621 prepare_block1_request(&req, &req_ctx, &more);
622 prepare_block1_response(&rsp, &rsp_ctx, &req);
623
624 i++;
625
626 verify_block1_request(&req_ctx, i);
627 verify_block1_response(&rsp_ctx, i);
628 }
629 }
630
631 #define BLOCK2_WISE_TRANSFER_SIZE_GET 300
632
prepare_block2_request(struct coap_packet * req,struct coap_block_context * req_ctx,struct coap_packet * rsp)633 static void prepare_block2_request(struct coap_packet *req,
634 struct coap_block_context *req_ctx,
635 struct coap_packet *rsp)
636 {
637 const char token[] = "token";
638 uint8_t *data = data_buf[0];
639 int r;
640
641 /* Request Context */
642 if (req_ctx->total_size == 0) {
643 coap_block_transfer_init(req_ctx, COAP_BLOCK_64,
644 BLOCK2_WISE_TRANSFER_SIZE_GET);
645 } else {
646 coap_next_block(rsp, req_ctx);
647 }
648
649 r = coap_packet_init(req, data, COAP_BUF_SIZE, COAP_VERSION_1,
650 COAP_TYPE_CON, strlen(token),
651 token, COAP_METHOD_GET,
652 coap_next_id());
653 zassert_equal(r, 0, "Unable to initialize request");
654
655 r = coap_append_block2_option(req, req_ctx);
656 zassert_equal(r, 0, "Unable to append block2 option");
657 }
658
prepare_block2_response(struct coap_packet * rsp,struct coap_block_context * rsp_ctx,struct coap_packet * req,int * more)659 static void prepare_block2_response(struct coap_packet *rsp,
660 struct coap_block_context *rsp_ctx,
661 struct coap_packet *req,
662 int *more)
663 {
664 uint8_t payload[64];
665 uint8_t token[8];
666 uint8_t *data = data_buf[1];
667 uint16_t id;
668 uint8_t tkl;
669 bool first;
670 int r;
671 int block_size = coap_block_size_to_bytes(COAP_BLOCK_64);
672 int payload_len;
673
674 if (rsp_ctx->total_size == 0) {
675 first = true;
676 coap_block_transfer_init(rsp_ctx, COAP_BLOCK_64,
677 BLOCK2_WISE_TRANSFER_SIZE_GET);
678 } else {
679 first = false;
680 }
681
682 id = coap_header_get_id(req);
683 tkl = coap_header_get_token(req, token);
684
685 r = coap_packet_init(rsp, data, COAP_BUF_SIZE, COAP_VERSION_1,
686 COAP_TYPE_ACK, tkl, token,
687 COAP_RESPONSE_CODE_CONTENT, id);
688 zassert_equal(r, 0, "Unable to initialize request");
689
690 r = coap_append_block2_option(rsp, rsp_ctx);
691 zassert_equal(r, 0, "Unable to append block2 option");
692
693 if (first) {
694 r = coap_append_size2_option(rsp, rsp_ctx);
695 zassert_equal(r, 0, "Unable to append size2 option");
696 }
697
698 r = coap_packet_append_payload_marker(rsp);
699 zassert_equal(r, 0, "Unable to append payload marker");
700
701 payload_len = rsp_ctx->total_size - rsp_ctx->current;
702 if (payload_len > block_size) {
703 payload_len = block_size;
704 }
705
706 r = coap_packet_append_payload(rsp, payload, payload_len);
707 zassert_equal(r, 0, "Unable to append payload");
708
709 *more = coap_next_block(rsp, rsp_ctx);
710 }
711
verify_block2_request(struct coap_block_context * req_ctx,uint8_t iter)712 static void verify_block2_request(struct coap_block_context *req_ctx,
713 uint8_t iter)
714 {
715 zassert_equal(req_ctx->block_size, COAP_BLOCK_64,
716 "req:%d,Couldn't get block size", iter);
717 zassert_equal(req_ctx->current,
718 coap_block_size_to_bytes(COAP_BLOCK_64) * (iter - 1U),
719 "req:%d, Couldn't get the current block position", iter);
720 zassert_equal(req_ctx->total_size, BLOCK2_WISE_TRANSFER_SIZE_GET,
721 "req:%d,Couldn't packet total size", iter);
722 }
723
verify_block2_response(struct coap_block_context * rsp_ctx,uint8_t iter)724 static void verify_block2_response(struct coap_block_context *rsp_ctx,
725 uint8_t iter)
726 {
727 int block_size = coap_block_size_to_bytes(COAP_BLOCK_64);
728 int iter_max = ITER_COUNT(BLOCK2_WISE_TRANSFER_SIZE_GET, block_size);
729
730 zassert_equal(rsp_ctx->block_size, COAP_BLOCK_64,
731 "rsp:%d,Couldn't get block size", iter);
732
733 /* In last iteration "current" must match "total_size" */
734 if (iter < iter_max) {
735 zassert_equal(
736 rsp_ctx->current, block_size * iter,
737 "req:%d,Couldn't get the current block position", iter);
738 } else {
739 zassert_equal(
740 rsp_ctx->current, rsp_ctx->total_size,
741 "req:%d,Current block position does not match total size", iter);
742 }
743
744 zassert_equal(rsp_ctx->total_size, BLOCK2_WISE_TRANSFER_SIZE_GET,
745 "rsp:%d, Couldn't packet total size", iter);
746 }
747
ZTEST(coap,test_block2_size)748 ZTEST(coap, test_block2_size)
749 {
750 struct coap_block_context req_ctx;
751 struct coap_block_context rsp_ctx;
752 struct coap_packet req;
753 struct coap_packet rsp;
754 int more;
755 uint8_t i;
756
757 i = 0U;
758 more = 1;
759 memset(&req_ctx, 0, sizeof(req_ctx));
760 memset(&rsp_ctx, 0, sizeof(rsp_ctx));
761
762 while (more) {
763 prepare_block2_request(&req, &req_ctx, &rsp);
764 prepare_block2_response(&rsp, &rsp_ctx, &req, &more);
765
766 i++;
767
768 verify_block2_request(&req_ctx, i);
769 verify_block2_response(&rsp_ctx, i);
770 }
771 }
772
ZTEST(coap,test_retransmit_second_round)773 ZTEST(coap, test_retransmit_second_round)
774 {
775 struct coap_packet cpkt;
776 struct coap_packet rsp;
777 struct coap_pending *pending;
778 struct coap_pending *rsp_pending;
779 uint8_t *data = data_buf[0];
780 uint8_t *rsp_data = data_buf[1];
781 int r;
782 uint16_t id;
783
784 id = coap_next_id();
785
786 r = coap_packet_init(&cpkt, data, COAP_BUF_SIZE, COAP_VERSION_1,
787 COAP_TYPE_CON, 0, coap_next_token(),
788 COAP_METHOD_GET, id);
789 zassert_equal(r, 0, "Could not initialize packet");
790
791 pending = coap_pending_next_unused(pendings, NUM_PENDINGS);
792 zassert_not_null(pending, "No free pending");
793
794 r = coap_pending_init(pending, &cpkt, (struct sockaddr *) &dummy_addr,
795 NULL);
796 zassert_equal(r, 0, "Could not initialize packet");
797
798 /* We "send" the packet the first time here */
799 zassert_true(coap_pending_cycle(pending), "Pending expired too early");
800
801 /* We simulate that the first transmission got lost */
802 zassert_true(coap_pending_cycle(pending), "Pending expired too early");
803
804 r = coap_packet_init(&rsp, rsp_data, COAP_BUF_SIZE,
805 COAP_VERSION_1, COAP_TYPE_ACK, 0, NULL,
806 COAP_METHOD_GET, id);
807 zassert_equal(r, 0, "Could not initialize packet");
808
809 /* Now we get the ack from the remote side */
810 rsp_pending = coap_pending_received(&rsp, pendings, NUM_PENDINGS);
811 zassert_equal_ptr(pending, rsp_pending,
812 "Invalid pending %p should be %p",
813 rsp_pending, pending);
814
815 coap_pending_clear(rsp_pending);
816
817 rsp_pending = coap_pending_next_to_expire(pendings, NUM_PENDINGS);
818 zassert_is_null(rsp_pending, "There should be no active pendings");
819 }
820
ipaddr_cmp(const struct sockaddr * a,const struct sockaddr * b)821 static bool ipaddr_cmp(const struct sockaddr *a, const struct sockaddr *b)
822 {
823 if (a->sa_family != b->sa_family) {
824 return false;
825 }
826
827 if (a->sa_family == AF_INET6) {
828 return net_ipv6_addr_cmp(&net_sin6(a)->sin6_addr,
829 &net_sin6(b)->sin6_addr);
830 } else if (a->sa_family == AF_INET) {
831 return net_ipv4_addr_cmp(&net_sin(a)->sin_addr,
832 &net_sin(b)->sin_addr);
833 }
834
835 return false;
836 }
837
server_resource_1_callback(struct coap_resource * resource,struct coap_observer * observer)838 static void server_resource_1_callback(struct coap_resource *resource,
839 struct coap_observer *observer)
840 {
841 bool r;
842
843 r = ipaddr_cmp(&observer->addr, (const struct sockaddr *)&dummy_addr);
844 zassert_true(r, "The address of the observer doesn't match");
845
846 coap_remove_observer(resource, observer);
847 }
server_resource_2_callback(struct coap_resource * resource,struct coap_observer * observer)848 static void server_resource_2_callback(struct coap_resource *resource,
849 struct coap_observer *observer)
850 {
851 bool r;
852
853 r = ipaddr_cmp(&observer->addr, (const struct sockaddr *)&dummy_addr);
854 zassert_true(r, "The address of the observer doesn't match");
855 }
856
server_resource_1_get(struct coap_resource * resource,struct coap_packet * request,struct sockaddr * addr,socklen_t addr_len)857 static int server_resource_1_get(struct coap_resource *resource,
858 struct coap_packet *request,
859 struct sockaddr *addr, socklen_t addr_len)
860 {
861 struct coap_packet response;
862 struct coap_observer *observer;
863 uint8_t *data = data_buf[1];
864 char payload[] = "This is the payload";
865 uint8_t token[8];
866 uint8_t tkl;
867 uint16_t id;
868 int r;
869
870 zassert_true(coap_request_is_observe(request),
871 "The request should enable observing");
872
873 observer = coap_observer_next_unused(observers, NUM_OBSERVERS);
874 zassert_not_null(observer, "There should be an available observer");
875
876 tkl = coap_header_get_token(request, (uint8_t *) token);
877 id = coap_header_get_id(request);
878
879 coap_observer_init(observer, request, addr);
880 coap_register_observer(resource, observer);
881
882 r = coap_packet_init(&response, data, COAP_BUF_SIZE,
883 COAP_VERSION_1, COAP_TYPE_ACK, tkl, token,
884 COAP_RESPONSE_CODE_OK, id);
885 zassert_equal(r, 0, "Unable to initialize packet");
886
887 r = coap_append_option_int(&response, COAP_OPTION_OBSERVE,
888 resource->age);
889 zassert_equal(r, 0, "Failed to append observe option");
890
891 r = coap_packet_append_payload_marker(&response);
892 zassert_equal(r, 0, "Failed to set the payload marker");
893
894 r = coap_packet_append_payload(&response, (uint8_t *)payload,
895 strlen(payload));
896 zassert_equal(r, 0, "Unable to append payload");
897
898 resource->user_data = data;
899
900 return 0;
901 }
902
ZTEST(coap,test_observer_server)903 ZTEST(coap, test_observer_server)
904 {
905 uint8_t valid_request_pdu[] = {
906 0x45, 0x01, 0x12, 0x34,
907 't', 'o', 'k', 'e', 'n',
908 0x60, /* enable observe option */
909 0x51, 's', 0x01, '1', /* path */
910 };
911 uint8_t not_found_request_pdu[] = {
912 0x45, 0x01, 0x12, 0x34,
913 't', 'o', 'k', 'e', 'n',
914 0x60, /* enable observe option */
915 0x51, 's', 0x01, '3', /* path */
916 };
917 struct coap_packet req;
918 struct coap_option options[4] = {};
919 uint8_t *data = data_buf[0];
920 uint8_t opt_num = ARRAY_SIZE(options) - 1;
921 int r;
922
923 memcpy(data, valid_request_pdu, sizeof(valid_request_pdu));
924
925 r = coap_packet_parse(&req, data, sizeof(valid_request_pdu),
926 options, opt_num);
927 zassert_equal(r, 0, "Could not initialize packet");
928
929 r = coap_handle_request(&req, server_resources, options, opt_num,
930 (struct sockaddr *) &dummy_addr,
931 sizeof(dummy_addr));
932 zassert_equal(r, 0, "Could not handle packet");
933
934 /* Suppose some time passes */
935 r = coap_resource_notify(&server_resources[0]);
936 zassert_equal(r, 0, "Could not notify resource");
937
938 memcpy(data, not_found_request_pdu, sizeof(not_found_request_pdu));
939
940 r = coap_packet_parse(&req, data, sizeof(not_found_request_pdu),
941 options, opt_num);
942 zassert_equal(r, 0, "Could not initialize packet");
943
944 r = coap_handle_request(&req, server_resources, options, opt_num,
945 (struct sockaddr *) &dummy_addr,
946 sizeof(dummy_addr));
947 zassert_equal(r, -ENOENT,
948 "There should be no handler for this resource");
949 }
950
resource_reply_cb(const struct coap_packet * response,struct coap_reply * reply,const struct sockaddr * from)951 static int resource_reply_cb(const struct coap_packet *response,
952 struct coap_reply *reply,
953 const struct sockaddr *from)
954 {
955 TC_PRINT("You should see this");
956
957 return 0;
958 }
959
ZTEST(coap,test_observer_client)960 ZTEST(coap, test_observer_client)
961 {
962 struct coap_packet req;
963 struct coap_packet rsp;
964 struct coap_reply *reply;
965 struct coap_option options[4] = {};
966 const char token[] = "token";
967 const char * const *p;
968 uint8_t *data = data_buf[0];
969 uint8_t *rsp_data = data_buf[1];
970 uint8_t opt_num = ARRAY_SIZE(options) - 1;
971 int observe = 0;
972 int r;
973
974 r = coap_packet_init(&req, data, COAP_BUF_SIZE,
975 COAP_VERSION_1, COAP_TYPE_CON,
976 strlen(token), token,
977 COAP_METHOD_GET, coap_next_id());
978 zassert_equal(r, 0, "Unable to initialize request");
979
980 /* Enable observing the resource. */
981 r = coap_append_option_int(&req, COAP_OPTION_OBSERVE, observe);
982 zassert_equal(r, 0, "Unable to add option to request int");
983
984 for (p = server_resource_1_path; p && *p; p++) {
985 r = coap_packet_append_option(&req, COAP_OPTION_URI_PATH,
986 *p, strlen(*p));
987 zassert_equal(r, 0, "Unable to add option to request");
988 }
989
990 reply = coap_reply_next_unused(replies, NUM_REPLIES);
991 zassert_not_null(reply, "No resources for waiting for replies");
992
993 coap_reply_init(reply, &req);
994 reply->reply = resource_reply_cb;
995
996 /* Server side, not interesting for this test */
997 r = coap_packet_parse(&req, data, req.offset, options, opt_num);
998 zassert_equal(r, 0, "Could not parse req packet");
999
1000 r = coap_handle_request(&req, server_resources, options, opt_num,
1001 (struct sockaddr *) &dummy_addr,
1002 sizeof(dummy_addr));
1003 zassert_equal(r, 0, "Could not handle packet");
1004
1005 /* We cheat, and communicate using the resource's user_data */
1006 rsp_data = server_resources[0].user_data;
1007
1008 /* 'rsp_pkt' contains the response now */
1009
1010 r = coap_packet_parse(&rsp, rsp_data, req.offset, options, opt_num);
1011 zassert_equal(r, 0, "Could not parse rsp packet");
1012
1013 reply = coap_response_received(&rsp,
1014 (const struct sockaddr *) &dummy_addr,
1015 replies, NUM_REPLIES);
1016 zassert_not_null(reply, "Couldn't find a matching waiting reply");
1017 }
1018
ZTEST(coap,test_handle_invalid_coap_req)1019 ZTEST(coap, test_handle_invalid_coap_req)
1020 {
1021 struct coap_packet pkt;
1022 uint8_t *data = data_buf[0];
1023 struct coap_option options[4] = {};
1024 uint8_t opt_num = 4;
1025 int r;
1026 const char *const *p;
1027
1028 r = coap_packet_init(&pkt, data, COAP_BUF_SIZE, COAP_VERSION_1,
1029 COAP_TYPE_CON, 0, NULL, 0xFF, coap_next_id());
1030
1031 zassert_equal(r, 0, "Unable to init req");
1032
1033 for (p = server_resource_1_path; p && *p; p++) {
1034 r = coap_packet_append_option(&pkt, COAP_OPTION_URI_PATH,
1035 *p, strlen(*p));
1036 zassert_equal(r, 0, "Unable to append option");
1037 }
1038
1039 r = coap_packet_parse(&pkt, data, pkt.offset, options, opt_num);
1040 zassert_equal(r, 0, "Could not parse req packet");
1041
1042 r = coap_handle_request(&pkt, server_resources, options, opt_num,
1043 (struct sockaddr *) &dummy_addr, sizeof(dummy_addr));
1044 zassert_equal(r, -ENOTSUP, "Request handling should fail with -ENOTSUP");
1045 }
1046
ZTEST(coap,test_build_options_out_of_order_0)1047 ZTEST(coap, test_build_options_out_of_order_0)
1048 {
1049 uint8_t result[] = {0x45, 0x02, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0xC0, 0xB1, 0x19,
1050 0xC5, 'p', 'r', 'o', 'x', 'y', 0x44, 'c', 'o', 'a', 'p'};
1051 struct coap_packet cpkt;
1052 static const char token[] = "token";
1053 uint8_t *data = data_buf[0];
1054 int r;
1055
1056 r = coap_packet_init(&cpkt, data, COAP_BUF_SIZE, COAP_VERSION_1, COAP_TYPE_CON,
1057 strlen(token), token, COAP_METHOD_POST, 0x1234);
1058 zassert_equal(r, 0, "Could not initialize packet");
1059
1060 r = coap_append_option_int(&cpkt, COAP_OPTION_CONTENT_FORMAT,
1061 COAP_CONTENT_FORMAT_TEXT_PLAIN);
1062 zassert_equal(r, 0, "Could not append option");
1063
1064 static const uint8_t expected_options_0 = 0xc0; /* content format */
1065
1066 zassert_mem_equal(&expected_options_0, &cpkt.data[cpkt.hdr_len], cpkt.opt_len);
1067
1068 const char *proxy_uri = "proxy";
1069
1070 r = coap_packet_append_option(&cpkt, COAP_OPTION_PROXY_URI, proxy_uri, strlen(proxy_uri));
1071 zassert_equal(r, 0, "Could not append option");
1072 static const uint8_t expected_options_1[] = {
1073 0xc0, /* content format */
1074 0xd5, 0x0a, 'p', 'r', 'o', 'x', 'y' /* proxy url */
1075 };
1076 zassert_mem_equal(expected_options_1, &cpkt.data[cpkt.hdr_len], cpkt.opt_len);
1077
1078 const char *proxy_scheme = "coap";
1079
1080 r = coap_packet_append_option(&cpkt, COAP_OPTION_PROXY_SCHEME, proxy_scheme,
1081 strlen(proxy_scheme));
1082 zassert_equal(r, 0, "Could not append option");
1083 static const uint8_t expected_options_2[] = {
1084 0xc0, /* content format */
1085 0xd5, 0x0a, 'p', 'r', 'o', 'x', 'y', /* proxy url */
1086 0x44, 'c', 'o', 'a', 'p' /* proxy scheme */
1087 };
1088 zassert_mem_equal(expected_options_2, &cpkt.data[cpkt.hdr_len], cpkt.opt_len);
1089
1090 /* option out of order */
1091 const uint8_t block_option = 0b11001;
1092
1093 r = coap_append_option_int(&cpkt, COAP_OPTION_BLOCK2, block_option);
1094 zassert_equal(r, 0, "Could not append option");
1095 static const uint8_t expected_options_3[] = {
1096 0xc0, /* content format */
1097 0xb1, 0x19, /* block2 */
1098 0xc5, 'p', 'r', 'o', 'x', 'y', /* proxy url */
1099 0x44, 'c', 'o', 'a', 'p' /* proxy scheme */
1100 };
1101 zassert_mem_equal(expected_options_3, &cpkt.data[cpkt.hdr_len], cpkt.opt_len);
1102
1103 /* look for options */
1104 struct coap_option opt;
1105
1106 r = coap_find_options(&cpkt, COAP_OPTION_CONTENT_FORMAT, &opt, 1);
1107 zassert_equal(r, 1, "Could not find option");
1108
1109 r = coap_find_options(&cpkt, COAP_OPTION_PROXY_URI, &opt, 1);
1110 zassert_equal(r, 1, "Could not find option");
1111 zassert_equal(opt.len, strlen(proxy_uri), "Wrong option len");
1112 zassert_mem_equal(opt.value, proxy_uri, strlen(proxy_uri), "Wrong option content");
1113
1114 r = coap_find_options(&cpkt, COAP_OPTION_PROXY_SCHEME, &opt, 1);
1115 zassert_equal(r, 1, "Could not find option");
1116 zassert_equal(opt.len, strlen(proxy_scheme), "Wrong option len");
1117 zassert_mem_equal(opt.value, proxy_scheme, strlen(proxy_scheme), "Wrong option content");
1118
1119 r = coap_find_options(&cpkt, COAP_OPTION_BLOCK2, &opt, 1);
1120 zassert_equal(r, 1, "Could not find option");
1121 zassert_equal(opt.len, 1, "Wrong option len");
1122 zassert_equal(*opt.value, block_option, "Wrong option content");
1123
1124 zassert_equal(cpkt.hdr_len, 9, "Wrong header len");
1125 zassert_equal(cpkt.opt_len, 14, "Wrong options size");
1126 zassert_equal(cpkt.delta, 39, "Wrong delta");
1127
1128 zassert_equal(cpkt.offset, 23, "Wrong data size");
1129
1130 zassert_mem_equal(result, cpkt.data, cpkt.offset,
1131 "Built packet doesn't match reference packet");
1132 }
1133
1134 #define ASSERT_OPTIONS(cpkt, expected_opt_len, expected_data, expected_data_len) \
1135 do { \
1136 static const uint8_t expected_hdr_len = 9; \
1137 zassert_equal(expected_hdr_len, cpkt.hdr_len, "Wrong header length"); \
1138 zassert_equal(expected_opt_len, cpkt.opt_len, "Wrong option length"); \
1139 zassert_equal(expected_hdr_len + expected_opt_len, cpkt.offset, "Wrong offset"); \
1140 zassert_equal(expected_data_len, cpkt.offset, "Wrong offset"); \
1141 zassert_mem_equal(expected_data, cpkt.data, expected_data_len, "Wrong data"); \
1142 } while (0)
1143
ZTEST(coap,test_build_options_out_of_order_1)1144 ZTEST(coap, test_build_options_out_of_order_1)
1145 {
1146 struct coap_packet cpkt;
1147
1148 static const char token[] = "token";
1149
1150 uint8_t *data = data_buf[0];
1151
1152 memset(data_buf[0], 0, ARRAY_SIZE(data_buf[0]));
1153
1154 int r;
1155
1156 r = coap_packet_init(&cpkt, data, COAP_BUF_SIZE, COAP_VERSION_1, COAP_TYPE_CON,
1157 strlen(token), token, COAP_METHOD_POST, 0x1234);
1158 zassert_equal(r, 0, "Could not initialize packet");
1159
1160 r = coap_append_option_int(&cpkt, COAP_OPTION_SIZE2,
1161 coap_block_size_to_bytes(COAP_BLOCK_128));
1162 zassert_equal(r, 0, "Could not append option");
1163 static const uint8_t expected_0[] = {0x45, 0x02, 0x12, 0x34, 't', 'o',
1164 'k', 'e', 'n', 0xd1, 0x0f, 0x80};
1165 ASSERT_OPTIONS(cpkt, 3, expected_0, 12);
1166
1167 const char *uri_path = "path";
1168
1169 r = coap_packet_append_option(&cpkt, COAP_OPTION_URI_PATH, uri_path, strlen(uri_path));
1170 zassert_equal(r, 0, "Could not append option");
1171
1172 static const uint8_t expected_1[] = {
1173 0x45, 0x02, 0x12, 0x34, 't', 'o', 'k', 'e', 'n',
1174 0xb4, 'p', 'a', 't', 'h', 0xd1, 0x04, 0x80,
1175 };
1176
1177 ASSERT_OPTIONS(cpkt, 8, expected_1, 17);
1178
1179 r = coap_append_option_int(&cpkt, COAP_OPTION_CONTENT_FORMAT, COAP_CONTENT_FORMAT_APP_JSON);
1180 zassert_equal(r, 0, "Could not append option");
1181
1182 static const uint8_t expected_2[] = {
1183 0x45, 0x02, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0xb4,
1184 'p', 'a', 't', 'h', 0x11, 0x32, 0xd1, 0x03, 0x80,
1185 };
1186
1187 ASSERT_OPTIONS(cpkt, 10, expected_2, 19);
1188
1189 const char *uri_host = "hostname";
1190
1191 r = coap_packet_append_option(&cpkt, COAP_OPTION_URI_HOST, uri_host, strlen(uri_host));
1192 zassert_equal(r, 0, "Could not append option");
1193
1194 static const uint8_t expected_3[] = {
1195 0x45, 0x02, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x38, 'h', 'o', 's', 't',
1196 'n', 'a', 'm', 'e', 0x84, 'p', 'a', 't', 'h', 0x11, 0x32, 0xd1, 0x03, 0x80,
1197 };
1198
1199 ASSERT_OPTIONS(cpkt, 19, expected_3, 28);
1200
1201 r = coap_append_option_int(&cpkt, COAP_OPTION_URI_PORT, 5638);
1202 zassert_equal(r, 0, "Could not append option");
1203
1204 static const uint8_t expected_4[] = {
1205 0x45, 0x02, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x38, 'h',
1206 'o', 's', 't', 'n', 'a', 'm', 'e', 'B', 0x16, 0x06, 'D',
1207 'p', 'a', 't', 'h', 0x11, 0x32, 0xd1, 0x03, 0x80,
1208 };
1209
1210 ASSERT_OPTIONS(cpkt, 22, expected_4, 31);
1211
1212 const char *uri_query0 = "query0";
1213
1214 r = coap_packet_append_option(&cpkt, COAP_OPTION_URI_QUERY, uri_query0, strlen(uri_query0));
1215 zassert_equal(r, 0, "Could not append option");
1216
1217 const char *uri_query1 = "query1";
1218
1219 r = coap_packet_append_option(&cpkt, COAP_OPTION_URI_QUERY, uri_query1, strlen(uri_query1));
1220 zassert_equal(r, 0, "Could not append option");
1221
1222 static const uint8_t expected_5[] = {
1223 0x45, 0x02, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x38, 'h', 'o',
1224 's', 't', 'n', 'a', 'm', 'e', 'B', 0x16, 0x06, 'D', 'p', 'a',
1225 't', 'h', 0x11, 0x32, 0x36, 'q', 'u', 'e', 'r', 'y', 0x30, 0x06,
1226 'q', 'u', 'e', 'r', 'y', 0x31, 0xd1, 0x00, 0x80,
1227 };
1228
1229 ASSERT_OPTIONS(cpkt, 36, expected_5, 45);
1230
1231 r = coap_append_option_int(&cpkt, COAP_OPTION_ACCEPT, COAP_CONTENT_FORMAT_APP_CBOR);
1232 zassert_equal(r, 0, "Could not append option");
1233
1234 static const uint8_t expected_6[] = {
1235 0x45, 0x02, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x38, 'h', 'o',
1236 's', 't', 'n', 'a', 'm', 'e', 'B', 0x16, 0x06, 'D', 'p', 'a',
1237 't', 'h', 0x11, 0x32, 0x36, 'q', 'u', 'e', 'r', 'y', 0x30, 0x06,
1238 'q', 'u', 'e', 'r', 'y', 0x31, 0x21, 0x3c, 0xb1, 0x80,
1239 };
1240
1241 ASSERT_OPTIONS(cpkt, 37, expected_6, 46);
1242
1243 r = coap_append_option_int(&cpkt, COAP_OPTION_OBSERVE, 0);
1244 zassert_equal(r, 0, "Could not append option");
1245
1246 static const uint8_t expected_7[] = {
1247 0x45, 0x02, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x38, 'h', 'o',
1248 's', 't', 'n', 'a', 'm', 'e', 0x30, 0x12, 0x16, 0x06, 'D', 'p',
1249 'a', 't', 'h', 0x11, 0x32, 0x36, 'q', 'u', 'e', 'r', 'y', 0x30,
1250 0x06, 'q', 'u', 'e', 'r', 'y', 0x31, 0x21, 0x3c, 0xb1, 0x80,
1251 };
1252
1253 ASSERT_OPTIONS(cpkt, 38, expected_7, 47);
1254
1255 r = coap_append_option_int(&cpkt, COAP_OPTION_MAX_AGE, 3);
1256 zassert_equal(r, 0, "Could not append option");
1257
1258 static const uint8_t expected_8[] = {
1259 0x45, 0x02, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x38, 'h', 'o', 's',
1260 't', 'n', 'a', 'm', 'e', 0x30, 0x12, 0x16, 0x06, 'D', 'p', 'a', 't',
1261 'h', 0x11, 0x32, 0x21, 0x03, 0x16, 'q', 'u', 'e', 'r', 'y', 0x30, 0x06,
1262 'q', 'u', 'e', 'r', 'y', 0x31, 0x21, 0x3c, 0xb1, 0x80,
1263 };
1264
1265 ASSERT_OPTIONS(cpkt, 40, expected_8, 49);
1266
1267 r = coap_append_option_int(&cpkt, COAP_OPTION_SIZE1, 64);
1268 zassert_equal(r, 0, "Could not append option");
1269
1270 static const uint8_t expected_9[] = {
1271 0x45, 0x02, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x38, 'h', 'o', 's',
1272 't', 'n', 'a', 'm', 'e', 0x30, 0x12, 0x16, 0x06, 'D', 'p', 'a', 't',
1273 'h', 0x11, 0x32, 0x21, 0x03, 0x16, 'q', 'u', 'e', 'r', 'y', 0x30, 0x06,
1274 'q', 'u', 'e', 'r', 'y', 0x31, 0x21, 0x3c, 0xb1, 0x80, 0xd1, 0x13, 0x40,
1275 };
1276
1277 ASSERT_OPTIONS(cpkt, 43, expected_9, 52);
1278
1279 zassert_equal(cpkt.hdr_len, 9, "Wrong header len");
1280 zassert_equal(cpkt.opt_len, 43, "Wrong options size");
1281 zassert_equal(cpkt.delta, 60, "Wrong delta");
1282 zassert_equal(cpkt.offset, 52, "Wrong data size");
1283 }
1284
1285 #define ASSERT_OPTIONS_AND_PAYLOAD(cpkt, expected_opt_len, expected_data, expected_offset, \
1286 expected_delta) \
1287 do { \
1288 size_t expected_data_l = ARRAY_SIZE(expected_data); \
1289 zassert_equal(expected_offset, expected_data_l); \
1290 static const uint8_t expected_hdr_len = 9; \
1291 zassert_equal(expected_hdr_len, cpkt.hdr_len, "Wrong header length"); \
1292 zassert_equal(expected_opt_len, cpkt.opt_len, "Wrong option length"); \
1293 zassert_equal(expected_offset, cpkt.offset, "Wrong offset"); \
1294 zassert_mem_equal(expected_data, cpkt.data, expected_offset, "Wrong data"); \
1295 zassert_equal(expected_delta, cpkt.delta, "Wrong delta"); \
1296 } while (0)
1297
init_basic_test_msg(struct coap_packet * cpkt,uint8_t * data)1298 static void init_basic_test_msg(struct coap_packet *cpkt, uint8_t *data)
1299 {
1300 static const char token[] = "token";
1301 const char *uri_path = "path";
1302 const char *uri_host = "hostname";
1303 const char *uri_query0 = "query0";
1304 const char *uri_query1 = "query1";
1305
1306 memset(data_buf[0], 0, ARRAY_SIZE(data_buf[0]));
1307
1308 int r;
1309
1310 r = coap_packet_init(cpkt, data, COAP_BUF_SIZE, COAP_VERSION_1, COAP_TYPE_CON,
1311 strlen(token), token, COAP_METHOD_POST, 0x1234);
1312 zassert_equal(r, 0, "Could not initialize packet");
1313
1314 r = coap_append_option_int(cpkt, COAP_OPTION_SIZE2,
1315 coap_block_size_to_bytes(COAP_BLOCK_128));
1316 zassert_equal(r, 0, "Could not append option");
1317
1318 r = coap_packet_append_option(cpkt, COAP_OPTION_URI_PATH, uri_path, strlen(uri_path));
1319 zassert_equal(r, 0, "Could not append option");
1320
1321 r = coap_append_option_int(cpkt, COAP_OPTION_CONTENT_FORMAT, COAP_CONTENT_FORMAT_APP_JSON);
1322 zassert_equal(r, 0, "Could not append option");
1323
1324 r = coap_packet_append_option(cpkt, COAP_OPTION_URI_HOST, uri_host, strlen(uri_host));
1325 zassert_equal(r, 0, "Could not append option");
1326
1327 r = coap_append_option_int(cpkt, COAP_OPTION_URI_PORT, 5638);
1328 zassert_equal(r, 0, "Could not append option");
1329
1330 r = coap_packet_append_option(cpkt, COAP_OPTION_URI_QUERY, uri_query0, strlen(uri_query0));
1331 zassert_equal(r, 0, "Could not append option");
1332
1333 r = coap_packet_append_option(cpkt, COAP_OPTION_URI_QUERY, uri_query1, strlen(uri_query1));
1334 zassert_equal(r, 0, "Could not append option");
1335
1336 r = coap_append_option_int(cpkt, COAP_OPTION_ACCEPT, COAP_CONTENT_FORMAT_APP_CBOR);
1337 zassert_equal(r, 0, "Could not append option");
1338
1339 r = coap_append_option_int(cpkt, COAP_OPTION_OBSERVE, 0);
1340 zassert_equal(r, 0, "Could not append option");
1341
1342 r = coap_append_option_int(cpkt, COAP_OPTION_MAX_AGE, 3);
1343 zassert_equal(r, 0, "Could not append option");
1344
1345 r = coap_append_option_int(cpkt, COAP_OPTION_SIZE1, 64);
1346 zassert_equal(r, 0, "Could not append option");
1347
1348 static const uint8_t expected_9[] = {
1349 0x45, 0x02, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x38, 'h', 'o', 's',
1350 't', 'n', 'a', 'm', 'e', 0x30, 0x12, 0x16, 0x06, 'D', 'p', 'a', 't',
1351 'h', 0x11, 0x32, 0x21, 0x03, 0x16, 'q', 'u', 'e', 'r', 'y', 0x30, 0x06,
1352 'q', 'u', 'e', 'r', 'y', 0x31, 0x21, 0x3c, 0xb1, 0x80, 0xd1, 0x13, 0x40,
1353 };
1354
1355 ASSERT_OPTIONS((*cpkt), 43, expected_9, 52);
1356
1357 r = coap_packet_append_payload_marker(cpkt);
1358 zassert_equal(r, 0, "Could not append payload marker");
1359
1360 static const uint8_t test_payload[] = {0xde, 0xad, 0xbe, 0xef};
1361
1362 r = coap_packet_append_payload(cpkt, test_payload, ARRAY_SIZE(test_payload));
1363 zassert_equal(r, 0, "Could not append test payload");
1364
1365 zassert_equal((*cpkt).hdr_len, 9, "Wrong header len");
1366 zassert_equal((*cpkt).opt_len, 43, "Wrong options size");
1367 zassert_equal((*cpkt).delta, 60, "Wrong delta");
1368 zassert_equal((*cpkt).offset, 57, "Wrong data size");
1369 }
1370
ZTEST(coap,test_remove_first_coap_option)1371 ZTEST(coap, test_remove_first_coap_option)
1372 {
1373 int r;
1374 struct coap_packet cpkt;
1375 uint8_t *data = data_buf[0];
1376
1377 init_basic_test_msg(&cpkt, data);
1378
1379 r = coap_packet_remove_option(&cpkt, COAP_OPTION_URI_HOST);
1380 zassert_equal(r, 0, "Could not remove option");
1381
1382 static const uint8_t expected_0[] = {
1383 0x45, 0x02, 0x12, 0x34, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x60, 0x12, 0x16,
1384 0x06, 0x44, 0x70, 0x61, 0x74, 0x68, 0x11, 0x32, 0x21, 0x03, 0x16, 0x71,
1385 0x75, 0x65, 0x72, 0x79, 0x30, 0x06, 0x71, 0x75, 0x65, 0x72, 0x79, 0x31,
1386 0x21, 0x3c, 0xb1, 0x80, 0xd1, 0x13, 0x40, 0xff, 0xde, 0xad, 0xbe, 0xef};
1387
1388 ASSERT_OPTIONS_AND_PAYLOAD(cpkt, 34, expected_0, 48, 60);
1389 }
1390
ZTEST(coap,test_remove_middle_coap_option)1391 ZTEST(coap, test_remove_middle_coap_option)
1392 {
1393 int r;
1394 struct coap_packet cpkt;
1395 uint8_t *data = data_buf[0];
1396
1397 init_basic_test_msg(&cpkt, data);
1398
1399 r = coap_packet_remove_option(&cpkt, COAP_OPTION_OBSERVE);
1400 zassert_equal(r, 0, "Could not remove option");
1401
1402 static const uint8_t expected_0[] = {
1403 0x45, 0x02, 0x12, 0x34, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x38, 0x68, 0x6f, 0x73, 0x74,
1404 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x16, 0x06, 0x44, 0x70, 0x61, 0x74, 0x68, 0x11, 0x32,
1405 0x21, 0x03, 0x16, 0x71, 0x75, 0x65, 0x72, 0x79, 0x30, 0x06, 0x71, 0x75, 0x65, 0x72,
1406 0x79, 0x31, 0x21, 0x3c, 0xb1, 0x80, 0xd1, 0x13, 0x40, 0xff, 0xde, 0xad, 0xbe, 0xef};
1407
1408 ASSERT_OPTIONS_AND_PAYLOAD(cpkt, 42, expected_0, 56, 60);
1409 }
1410
ZTEST(coap,test_remove_last_coap_option)1411 ZTEST(coap, test_remove_last_coap_option)
1412 {
1413 int r;
1414 struct coap_packet cpkt;
1415 uint8_t *data = data_buf[0];
1416
1417 init_basic_test_msg(&cpkt, data);
1418
1419 r = coap_packet_remove_option(&cpkt, COAP_OPTION_SIZE1);
1420 zassert_equal(r, 0, "Could not remove option");
1421
1422 static const uint8_t expected_0[] = {
1423 0x45, 0x02, 0x12, 0x34, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x38, 0x68, 0x6f, 0x73, 0x74,
1424 0x6e, 0x61, 0x6d, 0x65, 0x30, 0x12, 0x16, 0x06, 0x44, 0x70, 0x61, 0x74, 0x68, 0x11,
1425 0x32, 0x21, 0x03, 0x16, 0x71, 0x75, 0x65, 0x72, 0x79, 0x30, 0x06, 0x71, 0x75, 0x65,
1426 0x72, 0x79, 0x31, 0x21, 0x3c, 0xb1, 0x80, 0xff, 0xde, 0xad, 0xbe, 0xef};
1427
1428 ASSERT_OPTIONS_AND_PAYLOAD(cpkt, 40, expected_0, 54, 28);
1429
1430 r = coap_append_option_int(&cpkt, COAP_OPTION_SIZE1, 65);
1431 zassert_equal(r, 0, "Could not add option at end");
1432
1433 static const uint8_t expected_1[] = {
1434 0x45, 0x02, 0x12, 0x34, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x38, 0x68, 0x6f,
1435 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x30, 0x12, 0x16, 0x06, 0x44, 0x70,
1436 0x61, 0x74, 0x68, 0x11, 0x32, 0x21, 0x03, 0x16, 0x71, 0x75, 0x65, 0x72,
1437 0x79, 0x30, 0x06, 0x71, 0x75, 0x65, 0x72, 0x79, 0x31, 0x21, 0x3c, 0xb1,
1438 0x80, 0xd1, 0x13, 0x41, 0xff, 0xde, 0xad, 0xbe, 0xef};
1439
1440 ASSERT_OPTIONS_AND_PAYLOAD(cpkt, 43, expected_1, 57, 60);
1441 }
1442
ZTEST(coap,test_remove_single_coap_option)1443 ZTEST(coap, test_remove_single_coap_option)
1444 {
1445 struct coap_packet cpkt;
1446 uint8_t *data = data_buf[0];
1447
1448 static const char token[] = "token";
1449 const char *uri_path = "path";
1450
1451 memset(data_buf[0], 0, ARRAY_SIZE(data_buf[0]));
1452
1453 int r1;
1454
1455 r1 = coap_packet_init(&cpkt, data, COAP_BUF_SIZE, COAP_VERSION_1, COAP_TYPE_CON,
1456 strlen(token), token, COAP_METHOD_POST, 0x1234);
1457 zassert_equal(r1, 0, "Could not initialize packet");
1458
1459 r1 = coap_packet_append_option(&cpkt, COAP_OPTION_URI_PATH, uri_path, strlen(uri_path));
1460 zassert_equal(r1, 0, "Could not append option");
1461
1462 r1 = coap_packet_append_payload_marker(&cpkt);
1463 zassert_equal(r1, 0, "Could not append payload marker");
1464
1465 static const uint8_t test_payload[] = {0xde, 0xad, 0xbe, 0xef};
1466
1467 r1 = coap_packet_append_payload(&cpkt, test_payload, ARRAY_SIZE(test_payload));
1468 zassert_equal(r1, 0, "Could not append test payload");
1469
1470 static const uint8_t expected_0[] = {0x45, 0x02, 0x12, 0x34, 0x74, 0x6f, 0x6b,
1471 0x65, 0x6e, 0xb4, 0x70, 0x61, 0x74, 0x68,
1472 0xff, 0xde, 0xad, 0xbe, 0xef};
1473
1474 ASSERT_OPTIONS_AND_PAYLOAD(cpkt, 5, expected_0, 19, 11);
1475
1476 /* remove the one and only option */
1477 r1 = coap_packet_remove_option(&cpkt, COAP_OPTION_URI_PATH);
1478 zassert_equal(r1, 0, "Could not remove option");
1479
1480 static const uint8_t expected_1[] = {0x45, 0x02, 0x12, 0x34, 0x74, 0x6f, 0x6b,
1481 0x65, 0x6e, 0xff, 0xde, 0xad, 0xbe, 0xef};
1482
1483 ASSERT_OPTIONS_AND_PAYLOAD(cpkt, 0, expected_1, 14, 0);
1484 }
1485
ZTEST(coap,test_remove_repeatable_coap_option)1486 ZTEST(coap, test_remove_repeatable_coap_option)
1487 {
1488 int r;
1489 struct coap_packet cpkt;
1490 uint8_t *data = data_buf[0];
1491
1492 init_basic_test_msg(&cpkt, data);
1493
1494 r = coap_packet_remove_option(&cpkt, COAP_OPTION_URI_QUERY);
1495 zassert_equal(r, 0, "Could not remove option");
1496
1497 static const uint8_t expected_0[] = {
1498 0x45, 0x02, 0x12, 0x34, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x38, 0x68, 0x6f, 0x73,
1499 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x30, 0x12, 0x16, 0x06, 0x44, 0x70, 0x61, 0x74,
1500 0x68, 0x11, 0x32, 0x21, 0x03, 0x16, 0x71, 0x75, 0x65, 0x72, 0x79, 0x31, 0x21,
1501 0x3c, 0xb1, 0x80, 0xd1, 0x13, 0x40, 0xff, 0xde, 0xad, 0xbe, 0xef};
1502
1503 ASSERT_OPTIONS_AND_PAYLOAD(cpkt, 36, expected_0, 50, 60);
1504 }
1505
ZTEST(coap,test_remove_all_coap_options)1506 ZTEST(coap, test_remove_all_coap_options)
1507 {
1508 int r;
1509 struct coap_packet cpkt;
1510 uint8_t *data = data_buf[0];
1511
1512 init_basic_test_msg(&cpkt, data);
1513
1514 r = coap_packet_remove_option(&cpkt, COAP_OPTION_URI_PORT);
1515 zassert_equal(r, 0, "Could not remove option");
1516
1517 r = coap_packet_remove_option(&cpkt, COAP_OPTION_OBSERVE);
1518 zassert_equal(r, 0, "Could not remove option");
1519
1520 r = coap_packet_remove_option(&cpkt, COAP_OPTION_SIZE1);
1521 zassert_equal(r, 0, "Could not remove option");
1522
1523 static const uint8_t expected_0[] = {
1524 0x45, 0x02, 0x12, 0x34, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x38, 0x68, 0x6f, 0x73,
1525 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x84, 0x70, 0x61, 0x74, 0x68, 0x11, 0x32, 0x21,
1526 0x03, 0x16, 0x71, 0x75, 0x65, 0x72, 0x79, 0x30, 0x06, 0x71, 0x75, 0x65, 0x72,
1527 0x79, 0x31, 0x21, 0x3c, 0xb1, 0x80, 0xff, 0xde, 0xad, 0xbe, 0xef};
1528
1529 ASSERT_OPTIONS_AND_PAYLOAD(cpkt, 36, expected_0, 50, 28);
1530
1531 r = coap_packet_remove_option(&cpkt, COAP_OPTION_URI_HOST);
1532 zassert_equal(r, 0, "Could not remove option");
1533
1534 r = coap_packet_remove_option(&cpkt, COAP_OPTION_SIZE2);
1535 zassert_equal(r, 0, "Could not remove option");
1536
1537 r = coap_packet_remove_option(&cpkt, COAP_OPTION_CONTENT_FORMAT);
1538 zassert_equal(r, 0, "Could not remove option");
1539
1540 static const uint8_t expected_1[] = {
1541 0x45, 0x02, 0x12, 0x34, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0xb4, 0x70, 0x61, 0x74,
1542 0x68, 0x31, 0x03, 0x16, 0x71, 0x75, 0x65, 0x72, 0x79, 0x30, 0x06, 0x71, 0x75,
1543 0x65, 0x72, 0x79, 0x31, 0x21, 0x3c, 0xff, 0xde, 0xad, 0xbe, 0xef};
1544
1545 ASSERT_OPTIONS_AND_PAYLOAD(cpkt, 23, expected_1, 37, 17);
1546
1547 r = coap_packet_remove_option(&cpkt, COAP_OPTION_ACCEPT);
1548 zassert_equal(r, 0, "Could not remove option");
1549
1550 r = coap_packet_remove_option(&cpkt, COAP_OPTION_URI_PATH);
1551 zassert_equal(r, 0, "Could not remove option");
1552
1553 r = coap_packet_remove_option(&cpkt, COAP_OPTION_URI_QUERY);
1554 zassert_equal(r, 0, "Could not remove option");
1555
1556 static const uint8_t expected_2[] = {0x45, 0x02, 0x12, 0x34, 0x74, 0x6f, 0x6b, 0x65,
1557 0x6e, 0xd1, 0x01, 0x03, 0x16, 0x71, 0x75, 0x65,
1558 0x72, 0x79, 0x31, 0xff, 0xde, 0xad, 0xbe, 0xef};
1559
1560 ASSERT_OPTIONS_AND_PAYLOAD(cpkt, 10, expected_2, 24, 15);
1561
1562 r = coap_packet_remove_option(&cpkt, COAP_OPTION_MAX_AGE);
1563 zassert_equal(r, 0, "Could not remove option");
1564
1565 r = coap_packet_remove_option(&cpkt, COAP_OPTION_URI_QUERY);
1566 zassert_equal(r, 0, "Could not remove option");
1567
1568 static const uint8_t expected_3[] = {0x45, 0x02, 0x12, 0x34, 0x74, 0x6f, 0x6b,
1569 0x65, 0x6e, 0xff, 0xde, 0xad, 0xbe, 0xef};
1570
1571 ASSERT_OPTIONS_AND_PAYLOAD(cpkt, 0, expected_3, 14, 0);
1572
1573 /* remove option that is not there anymore */
1574 r = coap_packet_remove_option(&cpkt, COAP_OPTION_MAX_AGE);
1575 zassert_equal(r, 0, "Could not remove option");
1576
1577 ASSERT_OPTIONS_AND_PAYLOAD(cpkt, 0, expected_3, 14, 0);
1578 }
1579
ZTEST(coap,test_remove_non_existent_coap_option)1580 ZTEST(coap, test_remove_non_existent_coap_option)
1581 {
1582 int r;
1583 struct coap_packet cpkt;
1584 uint8_t *data = data_buf[0];
1585 static const char token[] = "token";
1586
1587 memset(data_buf[0], 0, ARRAY_SIZE(data_buf[0]));
1588
1589 r = coap_packet_init(&cpkt, data, COAP_BUF_SIZE, COAP_VERSION_1, COAP_TYPE_CON,
1590 strlen(token), token, COAP_METHOD_POST, 0x1234);
1591 zassert_equal(r, 0, "Could not initialize packet");
1592
1593 r = coap_append_option_int(&cpkt, COAP_OPTION_CONTENT_FORMAT, COAP_CONTENT_FORMAT_APP_CBOR);
1594 zassert_equal(r, 0, "Could not append option");
1595
1596 r = coap_append_option_int(&cpkt, COAP_OPTION_ACCEPT, COAP_CONTENT_FORMAT_APP_OCTET_STREAM);
1597 zassert_equal(r, 0, "Could not append option");
1598
1599 r = coap_packet_append_payload_marker(&cpkt);
1600 zassert_equal(r, 0, "Could not append payload marker");
1601
1602 static const uint8_t test_payload[] = {0xde, 0xad, 0xbe, 0xef};
1603
1604 r = coap_packet_append_payload(&cpkt, test_payload, ARRAY_SIZE(test_payload));
1605
1606 static const uint8_t expected_original_msg[] = {0x45, 0x02, 0x12, 0x34, 0x74, 0x6f,
1607 0x6b, 0x65, 0x6e, 0xc1, 0x3c, 0x51,
1608 0x2a, 0xff, 0xde, 0xad, 0xbe, 0xef};
1609
1610 ASSERT_OPTIONS_AND_PAYLOAD(cpkt, 4, expected_original_msg, 18, 17);
1611
1612 /* remove option that is not there but would be before existing options */
1613 r = coap_packet_remove_option(&cpkt, COAP_OPTION_URI_PATH);
1614 zassert_equal(r, 0, "Could not remove option");
1615
1616 ASSERT_OPTIONS_AND_PAYLOAD(cpkt, 4, expected_original_msg, 18, 17);
1617
1618 /* remove option that is not there but would be between existing options */
1619 r = coap_packet_remove_option(&cpkt, COAP_OPTION_MAX_AGE);
1620 zassert_equal(r, 0, "Could not remove option");
1621
1622 ASSERT_OPTIONS_AND_PAYLOAD(cpkt, 4, expected_original_msg, 18, 17);
1623
1624 /* remove option that is not there but would be after existing options */
1625 r = coap_packet_remove_option(&cpkt, COAP_OPTION_LOCATION_QUERY);
1626 zassert_equal(r, 0, "Could not remove option");
1627
1628 ASSERT_OPTIONS_AND_PAYLOAD(cpkt, 4, expected_original_msg, 18, 17);
1629 }
1630
assert_coap_packet_set_path_query_options(const char * path,const char * const * expected,size_t expected_len,uint16_t code)1631 static void assert_coap_packet_set_path_query_options(const char *path,
1632 const char * const *expected,
1633 size_t expected_len, uint16_t code)
1634 {
1635 struct coap_packet cpkt;
1636 uint8_t *data = data_buf[0];
1637 struct coap_option options[16] = {0};
1638 int res;
1639
1640 memset(data_buf[0], 0, ARRAY_SIZE(data_buf[0]));
1641 TC_PRINT("Assert path: %s\n", path);
1642
1643 res = coap_packet_init(&cpkt, data, COAP_BUF_SIZE, COAP_VERSION_1, COAP_TYPE_CON,
1644 COAP_TOKEN_MAX_LEN, coap_next_token(),
1645 COAP_METHOD_GET, 0x1234);
1646 zassert_equal(res, 0, "Could not initialize packet");
1647
1648 res = coap_packet_set_path(&cpkt, path);
1649 zassert_equal(res, 0, "Could not set path/query, path: %s", path);
1650
1651 res = coap_find_options(&cpkt, code, options, ARRAY_SIZE(options));
1652 if (res <= 0) {
1653 /* fail if we expect options */
1654 zassert_true(((expected == NULL) && (expected_len == 0U)),
1655 "Expected options but found none, path: %s", path);
1656 }
1657
1658 for (unsigned int i = 0U; i < expected_len; ++i) {
1659 /* validate expected options, the rest shall be 0 */
1660 if (i < expected_len) {
1661 zassert_true((options[i].len == strlen(expected[i])),
1662 "Expected and parsed option lengths don't match"
1663 ", path: %s",
1664 path);
1665
1666 zassert_mem_equal(options[i].value, expected[i], options[i].len,
1667 "Expected and parsed option values don't match"
1668 ", path: %s",
1669 path);
1670 } else {
1671 zassert_true((options[i].len == 0U),
1672 "Unexpected options shall be empty"
1673 ", path: %s",
1674 path);
1675 }
1676 }
1677 }
1678
ZTEST(coap,test_coap_packet_set_path)1679 ZTEST(coap, test_coap_packet_set_path)
1680 {
1681 assert_coap_packet_set_path_query_options(" ", NULL, 0U, COAP_OPTION_URI_PATH);
1682 assert_coap_packet_set_path_query_options("", NULL, 0U, COAP_OPTION_URI_PATH);
1683 assert_coap_packet_set_path_query_options("/", NULL, 0U, COAP_OPTION_URI_PATH);
1684 assert_coap_packet_set_path_query_options("?", NULL, 0U, COAP_OPTION_URI_QUERY);
1685
1686 assert_coap_packet_set_path_query_options("?a",
1687 (const char *const[]){"a"}, 1U,
1688 COAP_OPTION_URI_QUERY);
1689 assert_coap_packet_set_path_query_options("?a&b",
1690 (const char *const[]){"a", "b"}, 2U,
1691 COAP_OPTION_URI_QUERY);
1692
1693 assert_coap_packet_set_path_query_options("a",
1694 (const char *const[]){"a"}, 1U,
1695 COAP_OPTION_URI_PATH);
1696 assert_coap_packet_set_path_query_options("a", NULL, 0, COAP_OPTION_URI_QUERY);
1697 assert_coap_packet_set_path_query_options("a/",
1698 (const char *const[]){"a"}, 1U,
1699 COAP_OPTION_URI_PATH);
1700
1701 assert_coap_packet_set_path_query_options("a?b=t&a",
1702 (const char *const[]){"a"}, 1U,
1703 COAP_OPTION_URI_PATH);
1704 assert_coap_packet_set_path_query_options("a?b=t&a",
1705 (const char *const[]){"b=t", "a"}, 2U,
1706 COAP_OPTION_URI_QUERY);
1707 assert_coap_packet_set_path_query_options("a?b=t&aa",
1708 (const char *const[]){"b=t", "aa"},
1709 2U, COAP_OPTION_URI_QUERY);
1710
1711 assert_coap_packet_set_path_query_options("a?b&a",
1712 (const char *const[]){"a"}, 1U,
1713 COAP_OPTION_URI_PATH);
1714 assert_coap_packet_set_path_query_options("a?b&a",
1715 (const char *const[]){"b", "a"}, 2U,
1716 COAP_OPTION_URI_QUERY);
1717 assert_coap_packet_set_path_query_options("a?b&aa",
1718 (const char *const[]){"b", "aa"}, 2U,
1719 COAP_OPTION_URI_QUERY);
1720
1721 assert_coap_packet_set_path_query_options("a/b",
1722 (const char *const[]){"a", "b"}, 2U,
1723 COAP_OPTION_URI_PATH);
1724 assert_coap_packet_set_path_query_options("a/b/",
1725 (const char *const[]){"a", "b"}, 2U,
1726 COAP_OPTION_URI_PATH);
1727 assert_coap_packet_set_path_query_options("a/b?b&a",
1728 (const char *const[]){"b", "a"}, 2U,
1729 COAP_OPTION_URI_QUERY);
1730 assert_coap_packet_set_path_query_options("a/b?b&aa",
1731 (const char *const[]){"b", "aa"}, 2U,
1732 COAP_OPTION_URI_QUERY);
1733
1734 assert_coap_packet_set_path_query_options("a/bb",
1735 (const char *const[]){"a", "bb"}, 2U,
1736 COAP_OPTION_URI_PATH);
1737 assert_coap_packet_set_path_query_options("a/bb/",
1738 (const char *const[]){"a", "bb"}, 2U,
1739 COAP_OPTION_URI_PATH);
1740 }
1741
ZTEST(coap,test_transmission_parameters)1742 ZTEST(coap, test_transmission_parameters)
1743 {
1744 struct coap_packet cpkt;
1745 struct coap_pending *pending;
1746 struct coap_transmission_parameters params;
1747 uint8_t *data = data_buf[0];
1748 int r;
1749 uint16_t id;
1750
1751 params = coap_get_transmission_parameters();
1752 zassert_equal(params.ack_timeout, CONFIG_COAP_INIT_ACK_TIMEOUT_MS, "Wrong ACK timeout");
1753 zassert_equal(params.ack_random_percent, CONFIG_COAP_ACK_RANDOM_PERCENT,
1754 "Wrong ACK random percent");
1755 zassert_equal(params.coap_backoff_percent, CONFIG_COAP_BACKOFF_PERCENT,
1756 "Wrong backoff percent");
1757 zassert_equal(params.max_retransmission, CONFIG_COAP_MAX_RETRANSMIT,
1758 "Wrong max retransmission value");
1759
1760 params.ack_timeout = 1000;
1761 params.ack_random_percent = 110;
1762 params.coap_backoff_percent = 150;
1763 params.max_retransmission = 2;
1764
1765 coap_set_transmission_parameters(¶ms);
1766
1767 id = coap_next_id();
1768
1769 r = coap_packet_init(&cpkt, data, COAP_BUF_SIZE, COAP_VERSION_1,
1770 COAP_TYPE_CON, 0, coap_next_token(),
1771 COAP_METHOD_GET, id);
1772 zassert_equal(r, 0, "Could not initialize packet");
1773
1774 pending = coap_pending_next_unused(pendings, NUM_PENDINGS);
1775 zassert_not_null(pending, "No free pending");
1776
1777 params.ack_timeout = 3000;
1778 params.ack_random_percent = 130;
1779 params.coap_backoff_percent = 250;
1780 params.max_retransmission = 3;
1781
1782 r = coap_pending_init(pending, &cpkt, (struct sockaddr *) &dummy_addr,
1783 ¶ms);
1784 zassert_equal(r, 0, "Could not initialize packet");
1785
1786 zassert_equal(pending->params.ack_timeout, 3000, "Wrong ACK timeout");
1787 zassert_equal(pending->params.ack_random_percent, 130, "Wrong ACK random percent");
1788 zassert_equal(pending->params.coap_backoff_percent, 250, "Wrong backoff percent");
1789 zassert_equal(pending->params.max_retransmission, 3, "Wrong max retransmission value");
1790
1791 r = coap_pending_init(pending, &cpkt, (struct sockaddr *) &dummy_addr,
1792 NULL);
1793 zassert_equal(r, 0, "Could not initialize packet");
1794
1795 zassert_equal(pending->params.ack_timeout, 1000, "Wrong ACK timeout");
1796 zassert_equal(pending->params.ack_random_percent, 110, "Wrong ACK random percent");
1797 zassert_equal(pending->params.coap_backoff_percent, 150, "Wrong backoff percent");
1798 zassert_equal(pending->params.max_retransmission, 2, "Wrong max retransmission value");
1799 }
1800
ZTEST(coap,test_notify_age)1801 ZTEST(coap, test_notify_age)
1802 {
1803 uint8_t valid_request_pdu[] = {
1804 0x45, 0x01, 0x12, 0x34, 't', 'o', 'k', 'e', 'n', 0x60, /* enable observe option */
1805 0x51, 's', 0x01, '2', /* path */
1806 };
1807
1808 struct coap_packet req;
1809 struct coap_option options[4] = {};
1810 uint8_t *data = data_buf[0];
1811 uint8_t opt_num = ARRAY_SIZE(options) - 1;
1812 struct coap_resource *resource = &server_resources[1];
1813 int r;
1814 struct coap_observer *observer;
1815 int last_age;
1816
1817 memcpy(data, valid_request_pdu, sizeof(valid_request_pdu));
1818
1819 r = coap_packet_parse(&req, data, sizeof(valid_request_pdu), options, opt_num);
1820 zassert_equal(r, 0, "Could not initialize packet");
1821
1822 r = coap_handle_request(&req, server_resources, options, opt_num,
1823 (struct sockaddr *)&dummy_addr, sizeof(dummy_addr));
1824 zassert_equal(r, 0, "Could not handle packet");
1825
1826 /* Forward time a bit, as not to run this 8 million time */
1827 resource->age = COAP_OBSERVE_MAX_AGE - 10;
1828
1829 last_age = resource->age;
1830
1831 for (int i = 0; i < 15; i++) {
1832 r = coap_resource_notify(resource);
1833 zassert_true(coap_age_is_newer(last_age, resource->age),
1834 "Resource age expected to be newer");
1835 last_age = resource->age;
1836 }
1837
1838 observer =
1839 CONTAINER_OF(sys_slist_peek_head(&resource->observers), struct coap_observer, list);
1840 coap_remove_observer(resource, observer);
1841 }
1842
ZTEST(coap,test_age_is_newer)1843 ZTEST(coap, test_age_is_newer)
1844 {
1845 for (int i = COAP_FIRST_AGE; i < COAP_MAX_AGE; ++i) {
1846 zassert_true(coap_age_is_newer(i, i + 1),
1847 "Resource age expected to be marked as newer");
1848 }
1849
1850 zassert_true(coap_age_is_newer(COAP_MAX_AGE, COAP_FIRST_AGE),
1851 "First age should be marked as newer");
1852 zassert_true(coap_age_is_newer(COAP_FIRST_AGE, COAP_ROLLOVER_AGE),
1853 "Rollover age should be marked as newer");
1854 zassert_true(coap_age_is_newer(COAP_ROLLOVER_AGE, COAP_MAX_AGE),
1855 "Max age should be marked as newer");
1856 }
1857
1858 ZTEST_SUITE(coap, NULL, NULL, NULL, NULL, NULL);
1859