6 #include "contiki-net.h"
9 #include "coap-server.h"
10 #include "rest-util.h"
15 #if !UIP_CONF_IPV6_RPL && !defined (CONTIKI_TARGET_MINIMAL_NET)
16 #include "static-routing.h"
22 #define PRINTF(...) printf(__VA_ARGS__)
23 #define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
24 #define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",(lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3],(lladdr)->addr[4], (lladdr)->addr[5])
27 #define PRINT6ADDR(addr)
28 #define PRINTLLADDR(addr)
31 #define MAX_PAYLOAD_LEN 120
32 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
33 #define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
36 static uint16_t current_tid;
38 static service_callback service_cbk =
NULL;
41 coap_set_service_callback(service_callback callback)
43 service_cbk = callback;
47 parse_message(coap_packet_t* packet, uint8_t* buf, uint16_t size)
51 PRINTF(
"parse_message size %d-->\n",size);
55 packet->ver = (buf[0] & COAP_HEADER_VERSION_MASK) >> COAP_HEADER_VERSION_POSITION;
56 packet->type = (buf[0] & COAP_HEADER_TYPE_MASK) >> COAP_HEADER_TYPE_POSITION;
57 packet->option_count = buf[0] & COAP_HEADER_OPTION_COUNT_MASK;
58 packet->code = buf[1];
59 packet->tid = (buf[2] << 8) + buf[3];
63 if (packet->option_count) {
67 uint8_t* option_buf = buf + processed;
68 packet->options = (header_option_t*)allocate_buffer(
sizeof(header_option_t) * packet->option_count);
70 if (packet->options) {
71 header_option_t* current_option = packet->options;
72 header_option_t* prev_option =
NULL;
73 while(option_index < packet->option_count) {
75 option_delta = (option_buf[i] & COAP_HEADER_OPTION_DELTA_MASK) >> COAP_HEADER_OPTION_DELTA_POSITION;
76 option_len = (option_buf[i] & COAP_HEADER_OPTION_SHORT_LENGTH_MASK);
78 if (option_len == 0xf) {
79 option_len += option_buf[i];
83 current_option->option = option_delta;
84 current_option->len = option_len;
85 current_option->value = option_buf + i;
87 prev_option->next = current_option;
90 current_option->option += prev_option->option;
93 if (current_option->option == Option_Type_Uri_Path) {
94 packet->url = (
char*)current_option->value;
95 packet->url_len = current_option->len;
96 }
else if (current_option->option == Option_Type_Uri_Query){
97 packet->query = (
char*)current_option->value;
98 packet->query_len = current_option->len;
101 PRINTF(
"OPTION %d %u %s \n", current_option->option, current_option->len, current_option->value);
105 prev_option = current_option++;
107 current_option->next =
NULL;
109 PRINTF(
"MEMORY ERROR\n");
116 if (processed < size) {
117 packet->payload = &buf[processed];
118 packet->payload_len = size - processed;
124 if (packet->url && !packet->query) {
125 if ((packet->query = strchr(packet->url,
'?'))) {
126 uint16_t total_url_len = packet->url_len;
128 packet->url_len = packet->query - packet->url;
130 packet->query_len = packet->url + total_url_len - packet->query;
132 PRINTF(
"url %s, url_len %u, query %s, query_len %u\n", packet->url, packet->url_len, packet->query, packet->query_len);
136 PRINTF(
"PACKET ver:%d type:%d oc:%d \ncode:%d tid:%u url:%s len:%u payload:%s pay_len %u\n", (
int)packet->ver, (
int)packet->type, (
int)packet->option_count, (
int)packet->code, packet->tid, packet->url, packet->url_len, packet->payload, packet->payload_len);
140 coap_get_query_variable(coap_packet_t* packet,
const char *name,
char* output, uint16_t output_size)
143 return get_variable(name, packet->query, packet->query_len, output, output_size, 0);
150 coap_get_post_variable(coap_packet_t* packet,
const char *name,
char* output, uint16_t output_size)
152 if (packet->payload) {
153 return get_variable(name, packet->payload, packet->payload_len, output, output_size, 1);
159 static header_option_t*
160 allocate_header_option(uint16_t variable_len)
162 PRINTF(
"sizeof header_option_t %u variable size %u\n",
sizeof(header_option_t), variable_len);
163 uint8_t* buffer = allocate_buffer(
sizeof(header_option_t) + variable_len);
165 header_option_t* option = (header_option_t*) buffer;
168 option->value = buffer +
sizeof(header_option_t);
177 coap_set_option(coap_packet_t* packet, option_type option_type, uint16_t len, uint8_t* value)
179 PRINTF(
"coap_set_option len %u\n", len);
180 header_option_t* option = allocate_header_option(len);
184 option->option = option_type;
185 memcpy(option->value, value, len);
186 header_option_t* option_current = packet->options;
187 header_option_t* prev =
NULL;
188 while (option_current){
189 if (option_current->option > option->option){
192 prev = option_current;
193 option_current = option_current->next;
198 option->next = option_current;
200 packet->options = option;
202 option->next = option_current;
206 packet->option_count++;
208 PRINTF(
"option->len %u option->option %u option->value %x next %x\n", option->len, option->option, (
unsigned int) option->value, (
unsigned int)option->next);
211 for ( ; i < option->len ; i++ ){
212 PRINTF(
" (%u)", option->value[i]);
223 coap_get_option(coap_packet_t* packet, option_type option_type)
225 PRINTF(
"coap_get_option count: %u--> \n", packet->option_count);
228 header_option_t* current_option = packet->options;
229 for (; i < packet->option_count; current_option = current_option->next, i++) {
230 PRINTF(
"Current option: %u\n", current_option->option);
231 if (current_option->option == option_type){
232 return current_option;
240 fill_error_packet(coap_packet_t* packet,
int error, uint16_t tid)
243 packet->option_count=0;
245 packet->options=
NULL;
247 case MEMORY_ALLOC_ERR:
248 packet->code=INTERNAL_SERVER_ERROR_500;
250 packet->type=MESSAGE_TYPE_ACK;
258 init_response(coap_packet_t* request, coap_packet_t* response)
260 init_packet(response);
261 if(request->type == MESSAGE_TYPE_CON) {
262 response->code = OK_200;
263 response->tid = request->tid;
264 response->type = MESSAGE_TYPE_ACK;
269 coap_get_payload(coap_packet_t* packet, uint8_t** payload)
271 if (packet->payload) {
272 *payload = packet->payload;
273 return packet->payload_len;
281 coap_set_payload(coap_packet_t* packet, uint8_t* payload, uint16_t size)
283 packet->payload = copy_to_buffer(payload, size);
284 if (packet->payload) {
285 packet->payload_len = size;
293 coap_set_header_content_type(coap_packet_t* packet, content_type_t content_type)
297 return coap_set_option(packet, Option_Type_Content_Type, len, (uint8_t*) &content_type);
301 coap_get_header_content_type(coap_packet_t* packet)
303 header_option_t* option = coap_get_option(packet, Option_Type_Content_Type);
305 return (uint8_t)(*(option->value));
308 return DEFAULT_CONTENT_TYPE;
312 coap_get_header_subscription_lifetime(coap_packet_t* packet, uint32_t* lifetime)
314 PRINTF(
"coap_get_header_subscription_lifetime --> \n");
315 header_option_t* option = coap_get_option(packet, Option_Type_Subscription_Lifetime);
317 PRINTF(
"Subs Found len %u (first byte %u)\n", option->len, (uint16_t)option->value[0]);
319 *lifetime = read_int(option->value, option->len);
327 coap_set_header_subscription_lifetime(coap_packet_t* packet, uint32_t lifetime)
330 uint16_t len = write_variable_int(temp, lifetime);
332 return coap_set_option(packet, Option_Type_Subscription_Lifetime, len, temp);
336 coap_get_header_block(coap_packet_t* packet, block_option_t* block)
339 PRINTF(
"coap_get_header_block --> \n");
340 header_option_t* option = coap_get_option(packet, Option_Type_Block);
342 PRINTF(
"Block Found len %u (first byte %u)\n", option->len, (uint16_t)option->value[0]);
344 all_block = read_int(option->value, option->len);
345 block->number = all_block >> 4;
346 block->more = (all_block & 0x8) >> 3;
347 block->size = (all_block & 0x7);
355 coap_set_header_block(coap_packet_t* packet, uint32_t number, uint8_t more, uint8_t size)
358 size = log_2(size/16);
359 number = number << 4;
360 number |= (more << 3) & 0x8;
361 number |= size & 0x7;
363 uint16_t len = write_variable_int(temp, number);
364 PRINTF(
"number %lu, more %u, size %u block[0] %u block[1] %u block[2] %u block[3] %u\n",
365 number, (uint16_t)more, (uint16_t)size, (uint16_t)temp[0], (uint16_t)temp[1], (uint16_t)temp[2], (uint16_t)temp[3]);
366 return coap_set_option(packet, Option_Type_Block, len, temp);
371 coap_set_header_uri(coap_packet_t* packet,
char* uri)
373 return coap_set_option(packet, Option_Type_Uri_Path, strlen(uri), (uint8_t*) uri);
377 coap_set_header_etag(coap_packet_t* packet, uint8_t* etag, uint8_t size)
379 return coap_set_option(packet, Option_Type_Etag, size, etag);
383 coap_set_code(coap_packet_t* packet, status_code_t code)
385 packet->code = (uint8_t)code;
389 coap_get_method(coap_packet_t* packet)
391 return (coap_method_t)packet->code;
395 coap_set_method(coap_packet_t* packet, coap_method_t method)
397 packet->code = (uint8_t)method;
400 static void send_request(coap_packet_t* request,
struct uip_udp_conn *client_conn)
402 char buf[MAX_PAYLOAD_LEN];
405 data_size = serialize_packet(request, buf);
407 PRINTF(
"Created a connection with the server ");
408 PRINT6ADDR(&client_conn->
ripaddr);
409 PRINTF(
" local/remote port %u/%u\n",
412 PRINTF(
"Sending to: ");
413 PRINT6ADDR(&client_conn->
ripaddr);
414 uip_udp_packet_send(client_conn, buf, data_size);
418 handle_incoming_data(
void)
421 char buf[MAX_PAYLOAD_LEN];
423 PRINTF(
"uip_datalen received %u \n",(uint16_t)
uip_datalen());
431 ((
char *)data)[datalen] = 0;
432 PRINTF(
"Server received: '%s' (port:%u) from ", (
char *)data,
uip_htons(UIP_UDP_BUF->srcport));
436 if (init_buffer(COAP_DATA_BUFF_SIZE)) {
437 coap_packet_t* request = (coap_packet_t*)allocate_buffer(
sizeof(coap_packet_t));
438 parse_message(request, (uint8_t*)data, datalen);
442 if (request->type != MESSAGE_TYPE_ACK) {
443 coap_packet_t* response = (coap_packet_t*)allocate_buffer(
sizeof(coap_packet_t));
444 init_response(request, response);
447 service_cbk(request, response);
450 data_size = serialize_packet(response, buf);
455 PRINTF(
"Memory Alloc Error\n");
456 error = MEMORY_ALLOC_ERR;
458 coap_packet_t error_packet;
459 fill_error_packet(&error_packet,error, (data[2] << 8) + data[3]);
460 data_size = serialize_packet(&error_packet, buf);
464 server_conn->
rport = UIP_UDP_BUF->srcport;
466 PRINTF(
"Responding with message size: %d\n",data_size);
467 uip_udp_packet_send(server_conn, buf, data_size);
470 server_conn->
rport = 0;
476 process_event_t resource_changed_event;
479 resource_changed(
struct periodic_resource_t* resource)
481 process_post(&coap_server, resource_changed_event, (process_data_t)resource);
487 PROCESS(coap_server,
"Coap Server");
491 PRINTF(
"COAP SERVER\n");
494 #if !UIP_CONF_IPV6_RPL && !defined (CONTIKI_TARGET_MINIMAL_NET)
495 set_global_address();
512 handle_incoming_data();
513 }
else if (ev == resource_changed_event) {
514 periodic_resource_t* resource = (periodic_resource_t*)data;
515 PRINTF(
"resource_changed_event \n");
517 if (init_buffer(COAP_DATA_BUFF_SIZE)) {
518 coap_packet_t* request = (coap_packet_t*)allocate_buffer(
sizeof(coap_packet_t));
519 init_packet(request);
520 coap_set_code(request, COAP_GET);
521 request->tid = current_tid++;
522 coap_set_header_subscription_lifetime(request, resource->lifetime);
523 coap_set_header_uri(request, (
char *)resource->resource->url);
524 if (resource->periodic_request_generator) {
525 resource->periodic_request_generator(request);
528 if (!resource->client_conn) {
534 if (resource->client_conn) {
535 send_request(request, resource->client_conn);
uint16_t rport
The remote port number in network byte order.
#define PROCESS_BEGIN()
Define the beginning of a process.
CCIF struct uip_udp_conn * udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate)
Create a new UDP connection.
#define uip_newdata()
Is new incoming data available?
#define NULL
The null pointer.
process_event_t process_alloc_event(void)
Allocate a global event number.
uint16_t lport
The local port number in network byte order.
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
uip_ipaddr_t ripaddr
The IP address of the remote peer.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
#define UIP_IP_BUF
Pointer to IP header.
#define PROCESS_END()
Define the end of a process.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
CCIF uint16_t uip_htons(uint16_t val)
Convert a 16-bit quantity from host byte order to network byte order.
uint8_t uip_ext_len
The length of the extension headers.
#define PROCESS(name, strname)
Declare a process.
#define uip_datalen()
The length of any incoming data that is currently available (if available) in the uip_appdata buffer...
process_event_t tcpip_event
The uIP event.
#define PROCESS_YIELD()
Yield the currently running process.
#define udp_bind(conn, port)
Bind a UDP connection to a local port.
Representation of a uIP UDP connection.
unsigned short random_rand(void)
Generate the next state and return the upper part of it.
uip_appdata
Pointer to the application data in the packet buffer.