1 /*
2  * Copyright (c) 2018 Intel Corporation
3  * Copyright (c) 2023 Basalte bv
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/logging/log.h>
9 LOG_MODULE_DECLARE(net_coap_service_sample);
10 
11 #include <zephyr/sys/printk.h>
12 #include <zephyr/net/coap_service.h>
13 
14 #include "net_private.h"
15 
piggyback_get(struct coap_resource * resource,struct coap_packet * request,struct sockaddr * addr,socklen_t addr_len)16 static int piggyback_get(struct coap_resource *resource,
17 			 struct coap_packet *request,
18 			 struct sockaddr *addr, socklen_t addr_len)
19 {
20 	uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE];
21 	struct coap_packet response;
22 	uint8_t payload[40];
23 	uint8_t token[COAP_TOKEN_MAX_LEN];
24 	uint16_t id;
25 	uint8_t code;
26 	uint8_t type;
27 	uint8_t tkl;
28 	int r;
29 
30 	code = coap_header_get_code(request);
31 	type = coap_header_get_type(request);
32 	id = coap_header_get_id(request);
33 	tkl = coap_header_get_token(request, token);
34 
35 	LOG_INF("*******");
36 	LOG_INF("type: %u code %u id %u", type, code, id);
37 	LOG_INF("*******");
38 
39 	if (type == COAP_TYPE_CON) {
40 		type = COAP_TYPE_ACK;
41 	} else {
42 		type = COAP_TYPE_NON_CON;
43 	}
44 
45 	r = coap_packet_init(&response, data, sizeof(data),
46 			     COAP_VERSION_1, type, tkl, token,
47 			     COAP_RESPONSE_CODE_CONTENT, id);
48 	if (r < 0) {
49 		return r;
50 	}
51 
52 	r = coap_append_option_int(&response, COAP_OPTION_CONTENT_FORMAT,
53 				   COAP_CONTENT_FORMAT_TEXT_PLAIN);
54 	if (r < 0) {
55 		return r;
56 	}
57 
58 	r = coap_packet_append_payload_marker(&response);
59 	if (r < 0) {
60 		return r;
61 	}
62 
63 	/* The response that coap-client expects */
64 	r = snprintk((char *) payload, sizeof(payload),
65 		     "Type: %u\nCode: %u\nMID: %u\n", type, code, id);
66 	if (r < 0) {
67 		return r;
68 	}
69 
70 	r = coap_packet_append_payload(&response, (uint8_t *)payload,
71 				       strlen(payload));
72 	if (r < 0) {
73 		return r;
74 	}
75 
76 	r = coap_resource_send(resource, &response, addr, addr_len, NULL);
77 
78 	return r;
79 }
80 
test_del(struct coap_resource * resource,struct coap_packet * request,struct sockaddr * addr,socklen_t addr_len)81 static int test_del(struct coap_resource *resource,
82 		    struct coap_packet *request,
83 		    struct sockaddr *addr, socklen_t addr_len)
84 {
85 	uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE];
86 	struct coap_packet response;
87 	uint8_t token[COAP_TOKEN_MAX_LEN];
88 	uint8_t tkl;
89 	uint8_t code;
90 	uint8_t type;
91 	uint16_t id;
92 	int r;
93 
94 	code = coap_header_get_code(request);
95 	type = coap_header_get_type(request);
96 	id = coap_header_get_id(request);
97 	tkl = coap_header_get_token(request, token);
98 
99 	LOG_INF("*******");
100 	LOG_INF("type: %u code %u id %u", type, code, id);
101 	LOG_INF("*******");
102 
103 	if (type == COAP_TYPE_CON) {
104 		type = COAP_TYPE_ACK;
105 	} else {
106 		type = COAP_TYPE_NON_CON;
107 	}
108 
109 	r = coap_packet_init(&response, data, sizeof(data),
110 			     COAP_VERSION_1, type, tkl, token,
111 			     COAP_RESPONSE_CODE_DELETED, id);
112 	if (r < 0) {
113 		return r;
114 	}
115 
116 	r = coap_resource_send(resource, &response, addr, addr_len, NULL);
117 
118 	return r;
119 }
120 
test_put(struct coap_resource * resource,struct coap_packet * request,struct sockaddr * addr,socklen_t addr_len)121 static int test_put(struct coap_resource *resource,
122 		    struct coap_packet *request,
123 		    struct sockaddr *addr, socklen_t addr_len)
124 {
125 	uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE];
126 	struct coap_packet response;
127 	uint8_t token[COAP_TOKEN_MAX_LEN];
128 	const uint8_t *payload;
129 	uint16_t payload_len;
130 	uint8_t code;
131 	uint8_t type;
132 	uint8_t tkl;
133 	uint16_t id;
134 	int r;
135 
136 	code = coap_header_get_code(request);
137 	type = coap_header_get_type(request);
138 	id = coap_header_get_id(request);
139 	tkl = coap_header_get_token(request, token);
140 
141 	LOG_INF("*******");
142 	LOG_INF("type: %u code %u id %u", type, code, id);
143 	LOG_INF("*******");
144 
145 	payload = coap_packet_get_payload(request, &payload_len);
146 	if (payload) {
147 		net_hexdump("PUT Payload", payload, payload_len);
148 	}
149 
150 	if (type == COAP_TYPE_CON) {
151 		type = COAP_TYPE_ACK;
152 	} else {
153 		type = COAP_TYPE_NON_CON;
154 	}
155 
156 	r = coap_packet_init(&response, data, sizeof(data),
157 			     COAP_VERSION_1, type, tkl, token,
158 			     COAP_RESPONSE_CODE_CHANGED, id);
159 	if (r < 0) {
160 		return r;
161 	}
162 
163 	r = coap_resource_send(resource, &response, addr, addr_len, NULL);
164 
165 	return r;
166 }
167 
test_post(struct coap_resource * resource,struct coap_packet * request,struct sockaddr * addr,socklen_t addr_len)168 static int test_post(struct coap_resource *resource,
169 		     struct coap_packet *request,
170 		     struct sockaddr *addr, socklen_t addr_len)
171 {
172 	static const char * const location_path[] = { "location1",
173 						      "location2",
174 						      "location3",
175 						      NULL };
176 	uint8_t data[CONFIG_COAP_SERVER_MESSAGE_SIZE];
177 	const char * const *p;
178 	struct coap_packet response;
179 	uint8_t token[COAP_TOKEN_MAX_LEN];
180 	const uint8_t *payload;
181 	uint16_t payload_len;
182 	uint8_t code;
183 	uint8_t type;
184 	uint8_t tkl;
185 	uint16_t id;
186 	int r;
187 
188 	code = coap_header_get_code(request);
189 	type = coap_header_get_type(request);
190 	id = coap_header_get_id(request);
191 	tkl = coap_header_get_token(request, token);
192 
193 	LOG_INF("*******");
194 	LOG_INF("type: %u code %u id %u", type, code, id);
195 	LOG_INF("*******");
196 
197 	payload = coap_packet_get_payload(request, &payload_len);
198 	if (payload) {
199 		net_hexdump("POST Payload", payload, payload_len);
200 	}
201 
202 	if (type == COAP_TYPE_CON) {
203 		type = COAP_TYPE_ACK;
204 	} else {
205 		type = COAP_TYPE_NON_CON;
206 	}
207 
208 	r = coap_packet_init(&response, data, sizeof(data),
209 			     COAP_VERSION_1, type, tkl, token,
210 			     COAP_RESPONSE_CODE_CREATED, id);
211 	if (r < 0) {
212 		return r;
213 	}
214 
215 	for (p = location_path; *p; p++) {
216 		r = coap_packet_append_option(&response,
217 					      COAP_OPTION_LOCATION_PATH,
218 					      *p, strlen(*p));
219 		if (r < 0) {
220 			return r;
221 		}
222 	}
223 
224 	r = coap_resource_send(resource, &response, addr, addr_len, NULL);
225 
226 	return r;
227 }
228 
229 static const char * const test_path[] = { "test", NULL };
230 COAP_RESOURCE_DEFINE(test, coap_server,
231 {
232 	.get = piggyback_get,
233 	.post = test_post,
234 	.del = test_del,
235 	.put = test_put,
236 	.path = test_path,
237 });
238 
239 static const char * const segments_path[] = { "seg1", "seg2", "seg3", NULL };
240 COAP_RESOURCE_DEFINE(segments, coap_server,
241 {
242 	.get = piggyback_get,
243 	.path = segments_path,
244 });
245 
246 #if defined(CONFIG_COAP_URI_WILDCARD)
247 
248 static const char * const wildcard1_path[] = { "wild1", "+", "wild3", NULL };
249 COAP_RESOURCE_DEFINE(wildcard1, coap_server,
250 {
251 	.get = piggyback_get,
252 	.path = wildcard1_path,
253 });
254 
255 static const char * const wildcard2_path[] = { "wild2", "#", NULL };
256 COAP_RESOURCE_DEFINE(wildcard2, coap_server,
257 {
258 	.get = piggyback_get,
259 	.path = wildcard2_path,
260 });
261 
262 #endif
263