Contiki-NG
http-socket.c
1 /*
2  * Copyright (c) 2013, Thingsquare, http://www.thingsquare.com/.
3  * All rights reserved.
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 copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  */
31 #include "contiki-net.h"
32 #include "ipv6/ip64-addr.h"
33 #include "http-socket.h"
34 
35 #include <ctype.h>
36 #include <stdio.h>
37 
38 #define MAX_PATHLEN 80
39 #define MAX_HOSTLEN 40
40 PROCESS(http_socket_process, "HTTP socket process");
41 LIST(socketlist);
42 
43 static void removesocket(struct http_socket *s);
44 /*---------------------------------------------------------------------------*/
45 static void
46 call_callback(struct http_socket *s, http_socket_event_t e,
47  const uint8_t *data, uint16_t datalen)
48 {
49  if(s->callback != NULL) {
50  s->callback(s, s->callbackptr, e,
51  data, datalen);
52  }
53 }
54 /*---------------------------------------------------------------------------*/
55 static void
56 parse_header_init(struct http_socket *s)
57 {
58  PT_INIT(&s->headerpt);
59 }
60 /*---------------------------------------------------------------------------*/
61 static int
62 parse_header_byte(struct http_socket *s, char c)
63 {
64  PT_BEGIN(&s->headerpt);
65 
66  memset(&s->header, -1, sizeof(s->header));
67 
68  /* Skip the HTTP response */
69  while(c != ' ') {
70  PT_YIELD(&s->headerpt);
71  }
72 
73  /* Skip the space */
74  PT_YIELD(&s->headerpt);
75  /* Read three characters of HTTP status and convert to BCD */
76  s->header.status_code = 0;
77  for(s->header_chars = 0; s->header_chars < 3; s->header_chars++) {
78  s->header.status_code = s->header.status_code << 4 | (c - '0');
79  PT_YIELD(&s->headerpt);
80  }
81 
82  if(s->header.status_code == 0x200 || s->header.status_code == 0x206) {
83  /* Read headers until data */
84 
85  while(1) {
86  /* Skip characters until end of line */
87  do {
88  while(c != '\r') {
89  s->header_chars++;
90  PT_YIELD(&s->headerpt);
91  }
92  s->header_chars++;
93  PT_YIELD(&s->headerpt);
94  } while(c != '\n');
95  s->header_chars--;
96  PT_YIELD(&s->headerpt);
97 
98  if(s->header_chars == 0) {
99  /* This was an empty line, i.e. the end of headers */
100  break;
101  }
102 
103  /* Start of line */
104  s->header_chars = 0;
105 
106  /* Read header field */
107  while(c != ' ' && c != '\t' && c != ':' && c != '\r' &&
108  s->header_chars < sizeof(s->header_field) - 1) {
109  s->header_field[s->header_chars++] = c;
110  PT_YIELD(&s->headerpt);
111  }
112  s->header_field[s->header_chars] = '\0';
113  /* Skip linear white spaces */
114  while(c == ' ' || c == '\t') {
115  s->header_chars++;
116  PT_YIELD(&s->headerpt);
117  }
118  if(c == ':') {
119  /* Skip the colon */
120  s->header_chars++;
121  PT_YIELD(&s->headerpt);
122  /* Skip linear white spaces */
123  while(c == ' ' || c == '\t') {
124  s->header_chars++;
125  PT_YIELD(&s->headerpt);
126  }
127  if(!strcmp(s->header_field, "Content-Length")) {
128  s->header.content_length = 0;
129  while(isdigit((int)c)) {
130  s->header.content_length = s->header.content_length * 10 + c - '0';
131  s->header_chars++;
132  PT_YIELD(&s->headerpt);
133  }
134  } else if(!strcmp(s->header_field, "Content-Range")) {
135  /* Skip the bytes-unit token */
136  while(c != ' ' && c != '\t') {
137  s->header_chars++;
138  PT_YIELD(&s->headerpt);
139  }
140  /* Skip linear white spaces */
141  while(c == ' ' || c == '\t') {
142  s->header_chars++;
143  PT_YIELD(&s->headerpt);
144  }
145  s->header.content_range.first_byte_pos = 0;
146  while(isdigit((int)c)) {
147  s->header.content_range.first_byte_pos =
148  s->header.content_range.first_byte_pos * 10 + c - '0';
149  s->header_chars++;
150  PT_YIELD(&s->headerpt);
151  }
152  /* Skip linear white spaces */
153  while(c == ' ' || c == '\t') {
154  s->header_chars++;
155  PT_YIELD(&s->headerpt);
156  }
157  if(c == '-') {
158  /* Skip the dash */
159  s->header_chars++;
160  PT_YIELD(&s->headerpt);
161  /* Skip linear white spaces */
162  while(c == ' ' || c == '\t') {
163  s->header_chars++;
164  PT_YIELD(&s->headerpt);
165  }
166  s->header.content_range.last_byte_pos = 0;
167  while(isdigit((int)c)) {
168  s->header.content_range.last_byte_pos =
169  s->header.content_range.last_byte_pos * 10 + c - '0';
170  s->header_chars++;
171  PT_YIELD(&s->headerpt);
172  }
173  /* Skip linear white spaces */
174  while(c == ' ' || c == '\t') {
175  s->header_chars++;
176  PT_YIELD(&s->headerpt);
177  }
178  if(c == '/') {
179  /* Skip the slash */
180  s->header_chars++;
181  PT_YIELD(&s->headerpt);
182  /* Skip linear white spaces */
183  while(c == ' ' || c == '\t') {
184  s->header_chars++;
185  PT_YIELD(&s->headerpt);
186  }
187  if(c != '*') {
188  s->header.content_range.instance_length = 0;
189  while(isdigit((int)c)) {
190  s->header.content_range.instance_length =
191  s->header.content_range.instance_length * 10 + c - '0';
192  s->header_chars++;
193  PT_YIELD(&s->headerpt);
194  }
195  }
196  }
197  }
198  }
199  }
200  }
201 
202  /* All headers read, now read data */
203  call_callback(s, HTTP_SOCKET_HEADER, (void *)&s->header, sizeof(s->header));
204 
205  /* Should exit the pt here to indicate that all headers have been
206  read */
207  PT_EXIT(&s->headerpt);
208  } else {
209  if(s->header.status_code == 0x404) {
210  printf("File not found\n");
211  } else if(s->header.status_code == 0x301 || s->header.status_code == 0x302) {
212  printf("File moved (not handled)\n");
213  }
214 
215  call_callback(s, HTTP_SOCKET_ERR, (void *)&s->header, sizeof(s->header));
216  tcp_socket_close(&s->s);
217  removesocket(s);
218  PT_EXIT(&s->headerpt);
219  }
220 
221 
222  PT_END(&s->headerpt);
223 }
224 /*---------------------------------------------------------------------------*/
225 static int
226 input_pt(struct http_socket *s,
227  const uint8_t *inputptr, int inputdatalen)
228 {
229  int i;
230  PT_BEGIN(&s->pt);
231 
232  /* Parse the header */
233  s->header_received = 0;
234  do {
235  for(i = 0; i < inputdatalen; i++) {
236  if(!PT_SCHEDULE(parse_header_byte(s, inputptr[i]))) {
237  s->header_received = 1;
238  break;
239  }
240  }
241  inputdatalen -= i;
242  inputptr += i;
243 
244  if(s->header_received == 0) {
245  /* If we have not yet received the full header, we wait for the
246  next packet to arrive. */
247  PT_YIELD(&s->pt);
248  }
249  } while(s->header_received == 0);
250 
251  s->bodylen = 0;
252  do {
253  /* Receive the data */
254  call_callback(s, HTTP_SOCKET_DATA, inputptr, inputdatalen);
255 
256  /* Close the connection if the expected content length has been received */
257  if(s->header.content_length >= 0 && s->bodylen < s->header.content_length) {
258  s->bodylen += inputdatalen;
259  if(s->bodylen >= s->header.content_length) {
260  tcp_socket_close(&s->s);
261  }
262  }
263 
264  PT_YIELD(&s->pt);
265  } while(inputdatalen > 0);
266 
267  PT_END(&s->pt);
268 }
269 /*---------------------------------------------------------------------------*/
270 static void
271 start_timeout_timer(struct http_socket *s)
272 {
273  PROCESS_CONTEXT_BEGIN(&http_socket_process);
274  etimer_set(&s->timeout_timer, HTTP_SOCKET_TIMEOUT);
275  PROCESS_CONTEXT_END(&http_socket_process);
276  s->timeout_timer_started = 1;
277 }
278 /*---------------------------------------------------------------------------*/
279 static int
280 input(struct tcp_socket *tcps, void *ptr,
281  const uint8_t *inputptr, int inputdatalen)
282 {
283  struct http_socket *s = ptr;
284 
285  input_pt(s, inputptr, inputdatalen);
286  start_timeout_timer(s);
287 
288  return 0; /* all data consumed */
289 }
290 /*---------------------------------------------------------------------------*/
291 static int
292 parse_url(const char *url, char *host, uint16_t *portptr, char *path)
293 {
294  const char *urlptr;
295  int i;
296  const char *file;
297  uint16_t port;
298 
299  if(url == NULL) {
300  printf("null url\n");
301  return 0;
302  }
303 
304  /* Don't even try to go further if the URL is empty. */
305  if(strlen(url) == 0) {
306  printf("empty url\n");
307  return 0;
308  }
309 
310  /* See if the URL starts with http:// and remove it. Otherwise, we
311  assume it is an implicit http://. */
312  if(strncmp(url, "http://", strlen("http://")) == 0) {
313  urlptr = url + strlen("http://");
314  } else {
315  urlptr = url;
316  }
317 
318  /* Find host part of the URL. */
319  if(*urlptr == '[') {
320  /* Handle IPv6 addresses - scan for matching ']' */
321  urlptr++;
322  for(i = 0; i < MAX_HOSTLEN; ++i) {
323  if(*urlptr == ']') {
324  if(host != NULL) {
325  host[i] = 0;
326  }
327  urlptr++;
328  break;
329  }
330  if(host != NULL) {
331  host[i] = *urlptr;
332  }
333  ++urlptr;
334  }
335  } else {
336  for(i = 0; i < MAX_HOSTLEN; ++i) {
337  if(*urlptr == 0 ||
338  *urlptr == '/' ||
339  *urlptr == ' ' ||
340  *urlptr == ':') {
341  if(host != NULL) {
342  host[i] = 0;
343  }
344  break;
345  }
346  if(host != NULL) {
347  host[i] = *urlptr;
348  }
349  ++urlptr;
350  }
351  }
352 
353  /* check if host is null terminated */
354  if(!memchr(host, 0, MAX_HOSTLEN)) {
355  return 0;
356  }
357 
358  /* Find the port. Default is 80. */
359  port = 80;
360  if(*urlptr == ':') {
361  port = 0;
362  do {
363  ++urlptr;
364  if(*urlptr >= '0' && *urlptr <= '9') {
365  port = (10 * port) + (*urlptr - '0');
366  }
367  } while(*urlptr >= '0' &&
368  *urlptr <= '9');
369  }
370  if(portptr != NULL) {
371  *portptr = port;
372  }
373  /* Find file part of the URL. */
374  while(*urlptr != '/' && *urlptr != 0) {
375  ++urlptr;
376  }
377  if(*urlptr == '/') {
378  file = urlptr;
379  } else {
380  file = "/";
381  }
382  if(path != NULL) {
383  strncpy(path, file, MAX_PATHLEN);
384  }
385  return 1;
386 }
387 /*---------------------------------------------------------------------------*/
388 static void
389 removesocket(struct http_socket *s)
390 {
391  etimer_stop(&s->timeout_timer);
392  s->timeout_timer_started = 0;
393  list_remove(socketlist, s);
394 }
395 /*---------------------------------------------------------------------------*/
396 static void
397 event(struct tcp_socket *tcps, void *ptr,
398  tcp_socket_event_t e)
399 {
400  struct http_socket *s = ptr;
401  char host[MAX_HOSTLEN];
402  char path[MAX_PATHLEN];
403  uint16_t port;
404  char str[42];
405  int len;
406 
407  if(e == TCP_SOCKET_CONNECTED) {
408  printf("Connected\n");
409  if(parse_url(s->url, host, &port, path)) {
410  tcp_socket_send_str(tcps, s->postdata != NULL ? "POST " : "GET ");
411  if(s->proxy_port != 0) {
412  /* If we are configured to route through a proxy, we should
413  provide the full URL as the path. */
414  tcp_socket_send_str(tcps, s->url);
415  } else {
416  tcp_socket_send_str(tcps, path);
417  }
418  tcp_socket_send_str(tcps, " HTTP/1.1\r\n");
419  tcp_socket_send_str(tcps, "Connection: close\r\n");
420  tcp_socket_send_str(tcps, "Host: ");
421  /* If we have IPv6 host, add the '[' and the ']' characters
422  to the host. As in rfc2732. */
423  if(memchr(host, ':', MAX_HOSTLEN)) {
424  tcp_socket_send_str(tcps, "[");
425  }
426  tcp_socket_send_str(tcps, host);
427  if(memchr(host, ':', MAX_HOSTLEN)) {
428  tcp_socket_send_str(tcps, "]");
429  }
430  tcp_socket_send_str(tcps, "\r\n");
431  if(s->postdata != NULL) {
432  if(s->content_type) {
433  tcp_socket_send_str(tcps, "Content-Type: ");
434  tcp_socket_send_str(tcps, s->content_type);
435  tcp_socket_send_str(tcps, "\r\n");
436  }
437  tcp_socket_send_str(tcps, "Content-Length: ");
438  sprintf(str, "%u", s->postdatalen);
439  tcp_socket_send_str(tcps, str);
440  tcp_socket_send_str(tcps, "\r\n");
441  } else if(s->length || s->pos > 0) {
442  tcp_socket_send_str(tcps, "Range: bytes=");
443  if(s->length) {
444  if(s->pos >= 0) {
445  sprintf(str, "%llu-%llu",
446  (long long unsigned int)s->pos, (long long unsigned int)s->pos + s->length - 1);
447  } else {
448  sprintf(str, "-%llu", (long long unsigned int)s->length);
449  }
450  } else {
451  sprintf(str, "%llu-", (long long unsigned int)s->pos);
452  }
453  tcp_socket_send_str(tcps, str);
454  tcp_socket_send_str(tcps, "\r\n");
455  }
456  tcp_socket_send_str(tcps, "\r\n");
457  if(s->postdata != NULL && s->postdatalen) {
458  len = tcp_socket_send(tcps, s->postdata, s->postdatalen);
459  s->postdata += len;
460  s->postdatalen -= len;
461  }
462  }
463  parse_header_init(s);
464  } else if(e == TCP_SOCKET_CLOSED) {
465  call_callback(s, HTTP_SOCKET_CLOSED, NULL, 0);
466  removesocket(s);
467  printf("Closed\n");
468  } else if(e == TCP_SOCKET_TIMEDOUT) {
469  call_callback(s, HTTP_SOCKET_TIMEDOUT, NULL, 0);
470  removesocket(s);
471  printf("Timedout\n");
472  } else if(e == TCP_SOCKET_ABORTED) {
473  call_callback(s, HTTP_SOCKET_ABORTED, NULL, 0);
474  removesocket(s);
475  printf("Aborted\n");
476  } else if(e == TCP_SOCKET_DATA_SENT) {
477  if(s->postdata != NULL && s->postdatalen) {
478  len = tcp_socket_send(tcps, s->postdata, s->postdatalen);
479  s->postdata += len;
480  s->postdatalen -= len;
481  } else {
482  start_timeout_timer(s);
483  }
484  }
485 }
486 /*---------------------------------------------------------------------------*/
487 static int
488 start_request(struct http_socket *s)
489 {
490  uip_ip4addr_t ip4addr;
491  uip_ip6addr_t ip6addr;
492  uip_ip6addr_t *addr;
493  char host[MAX_HOSTLEN];
494  char path[MAX_PATHLEN];
495  uint16_t port;
496  int ret;
497 
498  if(parse_url(s->url, host, &port, path)) {
499 
500  printf("url %s host %s port %d path %s\n",
501  s->url, host, port, path);
502 
503  /* Check if we are to route the request through a proxy. */
504  if(s->proxy_port != 0) {
505  /* The proxy address should be an IPv6 address. */
506  uip_ip6addr_copy(&ip6addr, &s->proxy_addr);
507  port = s->proxy_port;
508  } else if(uiplib_ip6addrconv(host, &ip6addr) == 0) {
509  /* First check if the host is an IP address. */
510  if(uiplib_ip4addrconv(host, &ip4addr) != 0) {
511  ip64_addr_4to6(&ip4addr, &ip6addr);
512  } else {
513  /* Try to lookup the hostname. If it fails, we initiate a hostname
514  lookup. */
515  ret = resolv_lookup(host, &addr);
516  if(ret == RESOLV_STATUS_UNCACHED ||
517  ret == RESOLV_STATUS_EXPIRED) {
518  resolv_query(host);
519  puts("Resolving host...");
520  return HTTP_SOCKET_OK;
521  }
522  if(addr != NULL) {
523  s->did_tcp_connect = 1;
524  tcp_socket_connect(&s->s, addr, port);
525  return HTTP_SOCKET_OK;
526  } else {
527  return HTTP_SOCKET_ERR;
528  }
529  }
530  }
531  tcp_socket_connect(&s->s, &ip6addr, port);
532  return HTTP_SOCKET_OK;
533  } else {
534  return HTTP_SOCKET_ERR;
535  }
536 }
537 /*---------------------------------------------------------------------------*/
538 PROCESS_THREAD(http_socket_process, ev, data)
539 {
540  PROCESS_BEGIN();
541 
542  while(1) {
543 
545 
546  if(ev == resolv_event_found && data != NULL) {
547  struct http_socket *s;
548  const char *name = data;
549  /* Either found a hostname, or not. We need to go through the
550  list of http sockets and figure out to which connection this
551  reply corresponds, then either restart the HTTP get, or kill
552  it (if no hostname was found). */
553  for(s = list_head(socketlist);
554  s != NULL;
555  s = list_item_next(s)) {
556  char host[MAX_HOSTLEN];
557  if(s->did_tcp_connect) {
558  /* We already connected, ignored */
559  } else if(parse_url(s->url, host, NULL, NULL) &&
560  strcmp(name, host) == 0) {
561  if(resolv_lookup(name, NULL) == RESOLV_STATUS_CACHED) {
562  /* Hostname found, restart get. */
563  start_request(s);
564  } else {
565  /* Hostname not found, kill connection. */
566  call_callback(s, HTTP_SOCKET_HOSTNAME_NOT_FOUND, NULL, 0);
567  removesocket(s);
568  }
569  }
570  }
571  } else if(ev == PROCESS_EVENT_TIMER) {
572  struct http_socket *s;
573  struct etimer *timeout_timer = data;
574  /*
575  * A socket time-out has occurred. We need to go through the list of HTTP
576  * sockets and figure out to which socket this timer event corresponds,
577  * then close this socket.
578  */
579  for(s = list_head(socketlist);
580  s != NULL;
581  s = list_item_next(s)) {
582  if(timeout_timer == &s->timeout_timer && s->timeout_timer_started) {
583  tcp_socket_close(&s->s);
584  break;
585  }
586  }
587  }
588  }
589 
590  PROCESS_END();
591 }
592 /*---------------------------------------------------------------------------*/
593 static void
594 init(void)
595 {
596  static uint8_t inited = 0;
597  if(inited == 0) {
598  process_start(&http_socket_process, NULL);
599  list_init(socketlist);
600  inited = 1;
601  }
602 }
603 /*---------------------------------------------------------------------------*/
604 void
605 http_socket_init(struct http_socket *s)
606 {
607  init();
608  uip_create_unspecified(&s->proxy_addr);
609  s->proxy_port = 0;
610 }
611 /*---------------------------------------------------------------------------*/
612 static void
613 initialize_socket(struct http_socket *s)
614 {
615  s->pos = 0;
616  s->length = 0;
617  s->postdata = NULL;
618  s->postdatalen = 0;
619  s->timeout_timer_started = 0;
620  PT_INIT(&s->pt);
621  tcp_socket_register(&s->s, s,
622  s->inputbuf, sizeof(s->inputbuf),
623  s->outputbuf, sizeof(s->outputbuf),
624  input, event);
625 }
626 /*---------------------------------------------------------------------------*/
627 int
628 http_socket_get(struct http_socket *s,
629  const char *url,
630  int64_t pos,
631  uint64_t length,
632  http_socket_callback_t callback,
633  void *callbackptr)
634 {
635  initialize_socket(s);
636  strncpy(s->url, url, sizeof(s->url));
637  s->pos = pos;
638  s->length = length;
639  s->callback = callback;
640  s->callbackptr = callbackptr;
641 
642  s->did_tcp_connect = 0;
643 
644  list_add(socketlist, s);
645 
646  return start_request(s);
647 }
648 /*---------------------------------------------------------------------------*/
649 int
650 http_socket_post(struct http_socket *s,
651  const char *url,
652  const void *postdata,
653  uint16_t postdatalen,
654  const char *content_type,
655  http_socket_callback_t callback,
656  void *callbackptr)
657 {
658  initialize_socket(s);
659  strncpy(s->url, url, sizeof(s->url));
660  s->postdata = postdata;
661  s->postdatalen = postdatalen;
662  s->content_type = content_type;
663 
664  s->callback = callback;
665  s->callbackptr = callbackptr;
666 
667  s->did_tcp_connect = 0;
668 
669  list_add(socketlist, s);
670 
671  return start_request(s);
672 }
673 /*---------------------------------------------------------------------------*/
674 int
675 http_socket_close(struct http_socket *socket)
676 {
677  struct http_socket *s;
678  for(s = list_head(socketlist);
679  s != NULL;
680  s = list_item_next(s)) {
681  if(s == socket) {
682  tcp_socket_close(&s->s);
683  removesocket(s);
684  return 1;
685  }
686  }
687  return 0;
688 }
689 /*---------------------------------------------------------------------------*/
690 void
691 http_socket_set_proxy(struct http_socket *s,
692  const uip_ipaddr_t *addr, uint16_t port)
693 {
694  uip_ipaddr_copy(&s->proxy_addr, addr);
695  s->proxy_port = port;
696 }
697 /*---------------------------------------------------------------------------*/
process_event_t resolv_event_found
Event that is broadcasted when a DNS name has been resolved.
Definition: resolv.c:276
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
void etimer_stop(struct etimer *et)
Stop a pending event timer.
Definition: etimer.c:243
#define PROCESS_CONTEXT_END(p)
End a context switch.
Definition: process.h:440
Hostname is fresh and usable.
Definition: resolv.h:63
#define PROCESS_WAIT_EVENT()
Wait for an event to be posted to the process.
Definition: process.h:141
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
Definition: uip-nd6.c:107
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
#define PT_BEGIN(pt)
Declare the start of a protothread inside the C function implementing the protothread.
Definition: pt.h:114
Hostname was found, but it&#39;s status has expired.
Definition: resolv.h:71
Representation of an IP address.
Definition: uip.h:95
#define PT_INIT(pt)
Initialize a protothread.
Definition: pt.h:79
#define PT_END(pt)
Declare the end of a protothread.
Definition: pt.h:126
resolv_status_t resolv_lookup(const char *name, uip_ipaddr_t **ipaddr)
Look up a hostname in the array of known hostnames.
Definition: resolv.c:1311
#define PT_SCHEDULE(f)
Schedule a protothread.
Definition: pt.h:270
void * list_head(list_t list)
Get a pointer to the first element of a list.
Definition: list.c:82
#define PT_YIELD(pt)
Yield from the current protothread.
Definition: pt.h:289
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition: uip.h:1015
#define PT_EXIT(pt)
Exit the protothread.
Definition: pt.h:245
A timer.
Definition: etimer.h:76
void list_add(list_t list, void *item)
Add an item at the end of a list.
Definition: list.c:142
Hostname was not found in the cache.
Definition: resolv.h:66
#define uip_create_unspecified(a)
set IP address a to unspecified
Definition: uip.h:1882
void list_init(list_t list)
Initialize a list.
Definition: list.c:65
#define LIST(name)
Declare a linked list.
Definition: list.h:89
#define PROCESS_CONTEXT_BEGIN(p)
Switch context to another process.
Definition: process.h:426
PROCESS_THREAD(cc2538_rf_process, ev, data)
Implementation of the cc2538 RF driver process.
Definition: cc2538-rf.c:1097
static void input(void)
Process a received 6lowpan packet.
Definition: sicslowpan.c:1758
void resolv_query(const char *name)
Queues a name so that a question for the name will be sent out.
Definition: resolv.c:1232
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
Definition: etimer.c:177
void list_remove(list_t list, void *item)
Remove a specific element from a list.
Definition: list.c:237
void * list_item_next(void *item)
Get the next item following this item.
Definition: list.c:322
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99