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