libcoap  4.1.1
 All Data Structures Files Functions Variables Typedefs Macros Groups Pages
coap-server.c
Go to the documentation of this file.
1 /* coap-server.c -- Example CoAP server using Contiki and libcoap
2  *
3  * Copyright (C) 2011 Olaf Bergmann <bergmann@tzi.org>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 #include "config.h"
34 #include "net/uip-debug.h"
35 
36 #include <string.h>
37 
38 #include "debug.h"
39 #include "coap.h"
40 
42 
43 /* changeable clock base (see handle_put_time()) */
44 static clock_time_t my_clock_base = 0;
45 static coap_resource_t *time_resource = NULL; /* just for testing */
46 
47 PROCESS(coap_server_process, "CoAP server process");
48 AUTOSTART_PROCESSES(&coap_server_process);
49 /*---------------------------------------------------------------------------*/
50 void
52  coap_address_t listen_addr;
53 
54  coap_address_init(&listen_addr);
55  listen_addr.port = UIP_HTONS(COAP_DEFAULT_PORT);
56 
57 #ifdef WITH_CONTIKI
58  /* initialize uIP address for SLAAC */
59  uip_ip6addr(&listen_addr.addr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
60  uip_ds6_set_addr_iid(&listen_addr.addr, &uip_lladdr);
61  uip_ds6_addr_add(&listen_addr.addr, 0, ADDR_AUTOCONF);
62 
63  uip_debug_lladdr_print(&uip_lladdr);
64  printf("\r\n");
65  uip_debug_ipaddr_print(&listen_addr.addr);
66  printf("\r\n");
67 #endif /* WITH_CONTIKI */
68 
69 #ifdef WITH_CONTIKI
70  printf("tentative address: [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
71  listen_addr.addr.u8[0], listen_addr.addr.u8[1],
72  listen_addr.addr.u8[2], listen_addr.addr.u8[3],
73  listen_addr.addr.u8[4], listen_addr.addr.u8[5],
74  listen_addr.addr.u8[6], listen_addr.addr.u8[7],
75  listen_addr.addr.u8[8], listen_addr.addr.u8[9],
76  listen_addr.addr.u8[10], listen_addr.addr.u8[11],
77  listen_addr.addr.u8[12], listen_addr.addr.u8[13],
78  listen_addr.addr.u8[14], listen_addr.addr.u8[15] ,
79  uip_ntohs(listen_addr.port));
80 #endif
81 
82  coap_context = coap_new_context(&listen_addr);
83 
84  coap_set_log_level(LOG_DEBUG);
85 
86  if (!coap_context)
87  coap_log(LOG_CRIT, "cannot create CoAP context\r\n");
88 }
89 
90 /*---------------------------------------------------------------------------*/
91 #ifndef min
92 # define min(a,b) ((a) < (b) ? (a) : (b))
93 #endif
94 
95 void
97  coap_address_t *peer, coap_pdu_t *request, str *token,
98  coap_pdu_t *response) {
99  coap_opt_iterator_t opt_iter;
100  unsigned char buf[2];
101  coap_tick_t now;
102  coap_tick_t t;
103 
104  /* if my_clock_base was deleted, we pretend to have no such resource */
105  response->hdr->code = COAP_RESPONSE_CODE(205),
106 
109 
111  coap_encode_var_bytes(buf, 0x01), buf);
112 
113  /* Check if subscription was requested. */
114  if (request &&
115  coap_check_option(request, COAP_OPTION_SUBSCRIPTION, &opt_iter) &&
116  coap_add_observer(resource, peer, token)) {
117 
118  /* add a new observe value */
120  coap_encode_var_bytes(buf, ctx->observe), buf);
121 
122  if (token->length)
123  coap_add_option(response, COAP_OPTION_TOKEN, token->length, token->s);
124  } else {
126  coap_encode_var_bytes(buf, ctx->observe), buf);
127 
128  if (token->length)
129  coap_add_option(response, COAP_OPTION_TOKEN, token->length, token->s);
130  }
131 
132  /* calculate current time */
133  coap_ticks(&t);
134  now = my_clock_base + (t / COAP_TICKS_PER_SECOND);
135 
136  /* output ticks */
137  response->length += snprintf((char *)response->data,
138  response->max_size - response->length,
139  "%u", (unsigned int)now);
140 }
141 
142 void
144  coap_resource_t *r;
145 #if 0
146  r = coap_resource_init(NULL, 0, 0);
148 
149  coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0);
150  coap_add_attr(r, (unsigned char *)"title", 5, (unsigned char *)"\"General Info\"", 14, 0);
151  coap_add_resource(ctx, r);
152 #endif
153  /* store clock base to use in /time */
154  my_clock_base = clock_offset;
155 
156  r = coap_resource_init((unsigned char *)"time", 4, 0);
157  if (!r)
158  goto error;
159 
160  r->observable = 1;
161  time_resource = r;
163 #if 0
166 #endif
167  coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0);
168  /* coap_add_attr(r, (unsigned char *)"title", 5, (unsigned char *)"\"Internal Clock\"", 16, 0); */
169  coap_add_attr(r, (unsigned char *)"rt", 2, (unsigned char *)"\"Ticks\"", 7, 0);
170  coap_add_attr(r, (unsigned char *)"if", 2, (unsigned char *)"\"clock\"", 7, 0);
171 
172  coap_add_resource(ctx, r);
173 #if 0
174 #ifndef WITHOUT_ASYNC
175  r = coap_resource_init((unsigned char *)"async", 5, 0);
177 
178  coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0);
179  coap_add_resource(ctx, r);
180 #endif /* WITHOUT_ASYNC */
181 #endif
182 
183  return;
184  error:
185  coap_log(LOG_CRIT, "cannot create resource\n");
186 }
187 
188 /* struct etimer notify_timer; */
189 struct etimer dirty_timer;
190 
191 /*---------------------------------------------------------------------------*/
193 {
194  PROCESS_BEGIN();
195 
196  init_coap();
197  init_resources(coap_context);
198 
199  if (!coap_context) {
200  coap_log(LOG_EMERG, "cannot create context\n");
201  PROCESS_EXIT();
202  }
203 
204  /* etimer_set(&notify_timer, 5 * CLOCK_SECOND); */
205  etimer_set(&dirty_timer, 30 * CLOCK_SECOND);
206 
207  while(1) {
208  PROCESS_YIELD();
209  if(ev == tcpip_event) {
210  coap_read(coap_context); /* read received data */
211  coap_dispatch(coap_context); /* and dispatch PDUs from receivequeue */
212  } else if (ev == PROCESS_EVENT_TIMER && etimer_expired(&dirty_timer)) {
213  time_resource->dirty = 1;
214  etimer_reset(&dirty_timer);
215  }
216  }
217 
218  PROCESS_END();
219 }
220 /*---------------------------------------------------------------------------*/