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