Contiki 3.x
httpd.c
1 /*
2  * Copyright (c) 2004, Adam Dunkels.
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 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  /* Configurable Contiki Webserver - see httpd.h */
34 
35 #include <string.h>
36 #include <stdio.h>
37 
38 #include "contiki-net.h"
39 #include "httpd.h"
40 
41 #include "webserver.h"
42 #include "httpd-fs.h"
43 
44 #if WEBSERVER_CONF_CGI
45 #include "httpd-cgi.h"
46 #endif
47 
48 #include "lib/petsciiconv.h"
49 
50 #if COFFEE_FILES
51 #include "cfs-coffee-arch.h"
52 #endif
53 
54 #define DEBUG 0
55 #if DEBUG
56 #define PRINTD PRINTA
57 #else
58 #define PRINTD(...)
59 #endif
60 
61 #define STATE_WAITING 0
62 #define STATE_OUTPUT 1
63 /* Allocate memory for the tcp connections */
64 MEMB(conns, struct httpd_state, WEBSERVER_CONF_CONNS);
65 
66 #define ISO_tab 0x09
67 #define ISO_nl 0x0a
68 #define ISO_cr 0x0d
69 #define ISO_space 0x20
70 #define ISO_bang 0x21
71 #define ISO_percent 0x25
72 #define ISO_period 0x2e
73 #define ISO_slash 0x2f
74 #define ISO_colon 0x3a
75 #define ISO_qmark 0x3f
76 
77 
78 /*---------------------------------------------------------------------------*/
79 static unsigned short
80 generate(void *state)
81 {
82  struct httpd_state *s = (struct httpd_state *)state;
83 
84  if(s->file.len > uip_mss()) {
85  s->len = uip_mss();
86  } else {
87  s->len = s->file.len;
88  }
89  httpd_fs_cpy(uip_appdata, s->file.data, s->len);
90  return s->len;
91 }
92 /*---------------------------------------------------------------------------*/
93 static
94 PT_THREAD(send_file(struct httpd_state *s))
95 {
96  PSOCK_BEGIN(&s->sout);
97  do {
98  PSOCK_GENERATOR_SEND(&s->sout, generate, s);
99  s->file.len -= s->len;
100  s->file.data += s->len;
101  } while(s->file.len > 0);
102 
103  PSOCK_END(&s->sout);
104 }
105 /*---------------------------------------------------------------------------*/
106 #if WEBSERVER_CONF_INCLUDE || WEBSERVER_CONF_CGI
107 static
108 PT_THREAD(send_part_of_file(struct httpd_state *s))
109 {
110  PSOCK_BEGIN(&s->sout);
111 
112  static int oldfilelen, oldlen;
113  static char * olddata;
114 
115  //Store stuff that gets clobbered...
116  oldfilelen = s->file.len;
117  oldlen = s->len;
118  olddata = s->file.data;
119 
120  s->file.len = s->len;
121  do {
122  PSOCK_GENERATOR_SEND(&s->sout, generate, s);
123  s->file.len -= s->len;
124  s->file.data += s->len;
125  } while(s->file.len > 0);
126 
127  s->len = oldlen;
128  s->file.len = oldfilelen;
129  s->file.data = olddata;
130 
131  PSOCK_END(&s->sout);
132 }
133 /*---------------------------------------------------------------------------*/
134 static void
135 next_scriptstate(struct httpd_state *s)
136 {
137  char *p;
138 /* Skip over any script parameters to the beginning of the next line */
139  if((p = (char *)httpd_fs_strchr(s->scriptptr, ISO_nl)) != NULL) {
140  p += 1;
141  s->scriptlen -= (unsigned short)(p - s->scriptptr);
142  s->scriptptr = p;
143  } else {
144  s->scriptlen = 0;
145  }
146 }
147 
148 /*---------------------------------------------------------------------------*/
149 char *
150 get_scriptname(char *dest, char *fromfile)
151 {
152  uint8_t i=0,skip=1;
153  /* Extract a file or cgi name, trim leading spaces and replace termination with zero */
154  /* Returns number of characters processed up to the next non-tab or space */
155  do {
156  dest[i]=httpd_fs_getchar(fromfile++);
157  if (dest[i]==ISO_colon) {if (!skip) break;} //allow leading colons
158  else if (dest[i]==ISO_tab ) {if (skip) continue;else break;}//skip leading tabs
159  else if (dest[i]==ISO_space) {if (skip) continue;else break;}//skip leading spaces
160  else if (dest[i]==ISO_nl ) break; //nl is preferred delimiter
161  else if (dest[i]==ISO_cr ) break; //some editors insert cr
162  else if (dest[i]==0 ) break; //files are terminated with null
163  else skip=0;
164  i++;
165  } while (i<(MAX_SCRIPT_NAME_LENGTH+1));
166  fromfile--;
167  while ((dest[i]==ISO_space) || (dest[i]==ISO_tab)) dest[i]=httpd_fs_getchar(++fromfile);
168  dest[i]=0;
169  return (fromfile);
170 }
171 /*---------------------------------------------------------------------------*/
172 
173 static
174 PT_THREAD(handle_script(struct httpd_state *s))
175 {
176  /* Note script includes will attach a leading : to the filename and a trailing zero */
177  static char scriptname[MAX_SCRIPT_NAME_LENGTH+1],*pptr;
178  static uint16_t filelength;
179 
180  PT_BEGIN(&s->scriptpt);
181 
182  filelength=s->file.len;
183  while(s->file.len > 0) {
184  /* Sanity check */
185  if (s->file.len > filelength) break;
186 
187  /* Check if we should start executing a script, flagged by %! */
188  if(httpd_fs_getchar(s->file.data) == ISO_percent &&
189  httpd_fs_getchar(s->file.data + 1) == ISO_bang) {
190 
191  /* Extract name, if starts with colon include file else call cgi */
192  s->scriptptr=get_scriptname(scriptname,s->file.data+2);
193  s->scriptlen=s->file.len-(s->scriptptr-s->file.data);
194  PRINTD("httpd: Handle script named %s\n",scriptname);
195  if(scriptname[0] == ISO_colon) {
196 #if WEBSERVER_CONF_INCLUDE
197  if (httpd_fs_open(&scriptname[1], &s->file)) {
198  PT_WAIT_THREAD(&s->scriptpt, send_file(s));
199  }
200  /*TODO dont print anything if file not found */
201 #endif
202  } else {
203 #if WEBSERVER_CONF_CGI
204  PT_WAIT_THREAD(&s->scriptpt,httpd_cgi(scriptname)(s, s->scriptptr));
205 #endif
206  }
207  next_scriptstate(s);
208 
209  /* Reset the pointers and continue sending the current file. */
210  s->file.data = s->scriptptr;
211  s->file.len = s->scriptlen;
212  } else {
213 
214  /* Send file up to the next potential script */
215  if(s->file.len > uip_mss()) {
216  s->len = uip_mss();
217  } else {
218  s->len = s->file.len;
219  }
220 
221  if(httpd_fs_getchar(s->file.data) == ISO_percent) {
222  pptr = (char *) httpd_fs_strchr(s->file.data + 1, ISO_percent);
223  } else {
224  pptr = (char *) httpd_fs_strchr(s->file.data, ISO_percent);
225  }
226 
227  if(pptr != NULL && pptr != s->file.data) {
228  s->len = (int)(pptr - s->file.data);
229  if(s->len >= uip_mss()) {
230  s->len = uip_mss();
231  }
232  }
233  PRINTD("httpd: Sending %u bytes from 0x%04x\n",s->file.len,(unsigned int)s->file.data);
234  PT_WAIT_THREAD(&s->scriptpt, send_part_of_file(s));
235  s->file.data += s->len;
236  s->file.len -= s->len;
237  }
238  }
239 
240  PT_END(&s->scriptpt);
241 }
242 #endif /* WEBSERVER_CONF_INCLUDE || WEBSERVER_CONF_CGI */
243 /*---------------------------------------------------------------------------*/
244 const char httpd_http[] HTTPD_STRING_ATTR = "HTTP/1.0 ";
245 const char httpd_server[] HTTPD_STRING_ATTR = "\r\nServer: Contiki/2.0 http://www.sics.se/contiki/\r\nConnection: close\r\n";
246 static unsigned short
247 generate_status(void *sstr)
248 {
249  uint8_t slen=httpd_strlen((char *)sstr);
250  httpd_memcpy(uip_appdata, httpd_http, sizeof(httpd_http)-1);
251  httpd_memcpy(uip_appdata+sizeof(httpd_http)-1, (char *)sstr, slen);
252  slen+=sizeof(httpd_http)-1;
253  httpd_memcpy(uip_appdata+slen, httpd_server, sizeof(httpd_server)-1);
254  return slen+sizeof(httpd_server)-1;
255 }
256 /*---------------------------------------------------------------------------*/
257 const char httpd_content[] HTTPD_STRING_ATTR = "Content-type: ";
258 const char httpd_crlf[] HTTPD_STRING_ATTR = "\r\n\r\n";
259 static unsigned short
260 generate_header(void *hstr)
261 {
262  uint8_t slen=httpd_strlen((char *)hstr);
263  httpd_memcpy(uip_appdata,httpd_content,sizeof(httpd_content)-1);
264  httpd_memcpy(uip_appdata+sizeof(httpd_content)-1, (char *)hstr, slen);
265  slen+=sizeof(httpd_content)-1;
266  httpd_memcpy(uip_appdata+slen,httpd_crlf,sizeof(httpd_crlf)-1);
267  return slen+4;
268 }
269 /*---------------------------------------------------------------------------*/
270 const char httpd_mime_htm[] HTTPD_STRING_ATTR = "text/html";
271 #if WEBSERVER_CONF_CSS
272 const char httpd_mime_css[] HTTPD_STRING_ATTR = "text/css";
273 #endif
274 #if WEBSERVER_CONF_PNG
275 const char httpd_mime_png[] HTTPD_STRING_ATTR = "image/png";
276 #endif
277 #if WEBSERVER_CONF_GIF
278 const char httpd_mime_gif[] HTTPD_STRING_ATTR = "image/gif";
279 #endif
280 #if WEBSERVER_CONF_JPG
281 const char httpd_mime_jpg[] HTTPD_STRING_ATTR = "image/jpeg";
282 const char httpd_jpg [] HTTPD_STRING_ATTR = "jpg";
283 #endif
284 #if WEBSERVER_CONF_TXT
285 const char httpd_mime_txt[] HTTPD_STRING_ATTR = "text/plain";
286 #endif
287 #if WEBSERVER_CONF_BIN
288 const char httpd_mime_bin[] HTTPD_STRING_ATTR = "application/octet-stream";
289 #endif
290 #if WEBSERVER_CONF_INCLUDE || WEBSERVER_CONF_CGI
291 const char httpd_shtml [] HTTPD_STRING_ATTR = ".shtml";
292 #endif
293 
294 static
295 PT_THREAD(send_headers(struct httpd_state *s, const char *statushdr))
296 {
297  char *ptr;
298  PSOCK_BEGIN(&s->sout);
299 
300  PSOCK_GENERATOR_SEND(&s->sout, generate_status, (char *)statushdr);
301 
302  ptr = strrchr(s->filename, ISO_period);
303  if (httpd_strncmp("4", statushdr, 1)==0) { //404
304  PSOCK_GENERATOR_SEND(&s->sout, generate_header, &httpd_mime_htm );
305  } else if(ptr == NULL) {
306 #if WEBSERVER_CONF_BIN
307  PSOCK_GENERATOR_SEND(&s->sout, generate_header, &httpd_mime_bin );
308 #else
309  PSOCK_GENERATOR_SEND(&s->sout, generate_header, &httpd_mime_htm );
310 #endif
311  } else {
312  ptr++;
313 #if WEBSERVER_CONF_INCLUDE || WEBSERVER_CONF_CGI
314  if(httpd_strncmp(ptr, &httpd_mime_htm[5],3)== 0 ||httpd_strncmp(ptr, &httpd_shtml[1], 4) == 0) {
315 #else
316  if(httpd_strncmp(ptr, &httpd_mime_htm[5],3)== 0) {
317 #endif
318  PSOCK_GENERATOR_SEND(&s->sout, generate_header, &httpd_mime_htm );
319 #if WEBSEVER_CONF_CSS
320  } else if(httpd_strcmp(ptr, &httpd_mime_css[5]) == 0) {
321  PSOCK_GENERATOR_SEND(&s->sout, generate_header, &httpd_mime_css );
322 #endif
323 #if WEBSERVER_CONF_PNG
324  } else if(httpd_strcmp(ptr, &httpd_mime_png[6]) == 0) {
325  PSOCK_GENERATOR_SEND(&s->sout, generate_header, &httpd_mime_png );
326 #endif
327 #if WEBSERVER_CONF_GIF
328  } else if(httpd_strcmp(ptr, &httpd_mime_gif[6])== 0) {
329  PSOCK_GENERATOR_SEND(&s->sout, generate_header, &httpd_mime_gif );
330 #endif
331 #if WEBSERVER_CONF_JPG
332  } else if(httpd_strcmp(ptr, httpd_mime_jpg) == 0) {
333  PSOCK_GENERATOR_SEND(&s->sout, generate_header, &httpd_mime_jpg );
334 #endif
335 #if WEBSERVER_CONF_TXT
336  } else {
337  PSOCK_GENERATOR_SEND(&s->sout, generate_header, &httpd_mime_txt);
338 #endif
339  }
340  }
341  PSOCK_END(&s->sout);
342 }
343 /*---------------------------------------------------------------------------*/
344 const char httpd_indexfn [] HTTPD_STRING_ATTR = "/index.html";
345 #if WEBSERVER_CONF_INCLUDE || WEBSERVER_CONF_CGI
346 const char httpd_indexsfn [] HTTPD_STRING_ATTR = "/index.shtml";
347 #endif
348 const char httpd_404fn [] HTTPD_STRING_ATTR = "/404.html";
349 const char httpd_404notf [] HTTPD_STRING_ATTR = "404 Not found";
350 const char httpd_200ok [] HTTPD_STRING_ATTR = "200 OK";
351 static
352 PT_THREAD(handle_output(struct httpd_state *s))
353 {
354  char *ptr;
355 
356  PT_BEGIN(&s->outputpt);
357 #if DEBUGLOGIC
358  httpd_strcpy(s->filename,httpd_indexfn);
359 #endif
360  if(!httpd_fs_open(s->filename, &s->file)) {
361 #if WEBSERVER_CONF_INCLUDE || WEBSERVER_CONF_CGI
362  /* If index.html not found try index.shtml */
363  if (httpd_strcmp(s->filename,httpd_indexfn)==0) httpd_strcpy(s->filename,httpd_indexsfn);
364  if (httpd_fs_open(s->filename, &s->file)) goto sendfile;
365 #endif
366  httpd_strcpy(s->filename, httpd_404fn);
367  httpd_fs_open(s->filename, &s->file);
368  PT_WAIT_THREAD(&s->outputpt, send_headers(s, httpd_404notf));
369  PT_WAIT_THREAD(&s->outputpt, send_file(s));
370  } else {
371 sendfile:
372  PT_WAIT_THREAD(&s->outputpt, send_headers(s, httpd_200ok));
373 #if WEBSERVER_CONF_INCLUDE || WEBSERVER_CONF_CGI
374  ptr = strchr(s->filename, ISO_period);
375  if((ptr != NULL && httpd_strncmp(ptr, httpd_shtml, 6) == 0) || httpd_strcmp(s->filename,httpd_indexfn)==0) {
376  PT_INIT(&s->scriptpt);
377  PT_WAIT_THREAD(&s->outputpt, handle_script(s));
378  } else {
379 #else
380  if (1)
381 #endif
382  PT_WAIT_THREAD(&s->outputpt, send_file(s));
383  }
384  }
385  PSOCK_CLOSE(&s->sout);
386  PT_END(&s->outputpt);
387 }
388 /*---------------------------------------------------------------------------*/
389 #if WEBSERVER_CONF_PASSQUERY
390 char httpd_query[WEBSERVER_CONF_PASSQUERY];
391 #endif
392 
393 const char httpd_get[] HTTPD_STRING_ATTR = "GET ";
394 const char httpd_ref[] HTTPD_STRING_ATTR = "Referer:";
395 static
396 PT_THREAD(handle_input(struct httpd_state *s))
397 {
398 
399  PSOCK_BEGIN(&s->sin);
400 
401  PSOCK_READTO(&s->sin, ISO_space);
402 
403  if(httpd_strncmp(s->inputbuf, httpd_get, 4) != 0) {
404  PSOCK_CLOSE_EXIT(&s->sin);
405  }
406  PSOCK_READTO(&s->sin, ISO_space);
407 
408  if(s->inputbuf[0] != ISO_slash) {
409  PSOCK_CLOSE_EXIT(&s->sin);
410  }
411 
412  if(s->inputbuf[1] == ISO_space) {
413  httpd_strcpy(s->filename, httpd_indexfn);
414  } else {
415  uint8_t i;
416  for (i=0;i<sizeof(s->filename)+1;i++) {
417  if (i >= (PSOCK_DATALEN(&s->sin)-1)) break;
418  if (s->inputbuf[i]==ISO_space) break;
419  #if WEBSERVER_CONF_PASSQUERY
420  /* Query string is left in the httpd_query buffer until zeroed by the application! */
421  if (s->inputbuf[i]==ISO_qmark) {
422  strncpy(httpd_query,&s->inputbuf[i+1],sizeof(httpd_query));
423  break;
424  }
425 #endif
426  s->filename[i]=s->inputbuf[i];
427  }
428  s->filename[i]=0;
429  }
430 
431 #if WEBSERVER_CONF_LOG
432  webserver_log_file(&uip_conn->ripaddr, s->filename);
433 // webserver_log(httpd_query);
434 #endif
435 #if WEBSERVER_CONF_LOADTIME
436  s->pagetime = clock_time();
437 #endif
438  s->state = STATE_OUTPUT;
439  while(1) {
440  PSOCK_READTO(&s->sin, ISO_nl);
441 #if WEBSERVER_CONF_LOG && WEBSERVER_CONF_REFERER
442  if(httpd_strncmp(s->inputbuf, httpd_ref, 8) == 0) {
443  s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0;
444  petsciiconv_topetscii(s->inputbuf, PSOCK_DATALEN(&s->sin) - 2);
445  webserver_log(s->inputbuf);
446  }
447 #endif
448  }
449  PSOCK_END(&s->sin);
450 }
451 /*---------------------------------------------------------------------------*/
452 static void
453 handle_connection(struct httpd_state *s)
454 {
455 #if DEBUGLOGIC
456  handle_output(s);
457 #endif
458  handle_input(s);
459  if(s->state == STATE_OUTPUT) {
460  handle_output(s);
461  }
462 }
463 /*---------------------------------------------------------------------------*/
464 void
465 httpd_appcall(void *state)
466 {
467 #if DEBUGLOGIC
468  struct httpd_state *s; //Enter here for debugging with output directed to TCPBUF
469  s = sg = (struct httpd_state *)memb_alloc(&conns);
470  if (1) {
471 #else
472  struct httpd_state *s = (struct httpd_state *)state;
473  if(uip_closed() || uip_aborted() || uip_timedout()) {
474  if(s != NULL) {
475  memb_free(&conns, s);
476  }
477  } else if(uip_connected()) {
478  s = (struct httpd_state *)memb_alloc(&conns);
479  if(s == NULL) {
480  uip_abort();
481  return;
482  }
483 #endif
484  tcp_markconn(uip_conn, s);
485  PSOCK_INIT(&s->sin, (uint8_t *)s->inputbuf, sizeof(s->inputbuf) - 1);
486  PSOCK_INIT(&s->sout, (uint8_t *)s->inputbuf, sizeof(s->inputbuf) - 1);
487  PT_INIT(&s->outputpt);
488  s->state = STATE_WAITING;
489  s->timer = 0;
490 #if WEBSERVER_CONF_AJAX
491  s->ajax_timeout = WEBSERVER_CONF_TIMEOUT;
492 #endif
493  handle_connection(s);
494  } else if(s != NULL) {
495  if(uip_poll()) {
496  ++s->timer;
497 #if WEBSERVER_CONF_AJAX
498  if(s->timer >= s->ajax_timeout) {
499 #else
500  if(s->timer >= WEBSERVER_CONF_TIMEOUT) {
501 #endif
502  uip_abort();
503  memb_free(&conns, s);
504  }
505  } else {
506  s->timer = 0;
507  }
508  handle_connection(s);
509  } else {
510  uip_abort();
511  }
512 }
513 /*---------------------------------------------------------------------------*/
514 void
515 httpd_init(void)
516 {
517  tcp_listen(UIP_HTONS(80));
518  memb_init(&conns);
519  PRINTD(" sizof(struct httpd_state) = %d\n",sizeof(struct httpd_state));
520  PRINTA(" %d bytes used for httpd state storage\n",conns.size * conns.num);
521 #if WEBSERVER_CONF_CGI
522  httpd_cgi_init();
523 #endif
524 }
525 /*---------------------------------------------------------------------------*/
#define PT_WAIT_THREAD(pt, thread)
Block and wait until a child protothread completes.
Definition: pt.h:191
#define PSOCK_READTO(psock, c)
Read data up to a specified character.
Definition: psock.h:291
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
Definition: memb.c:52
#define PSOCK_CLOSE_EXIT(psock)
Close a protosocket and exit the protosocket&#39;s protothread.
Definition: psock.h:331
#define PSOCK_BEGIN(psock)
Start the protosocket protothread in a function.
Definition: psock.h:164
Representation of a uIP TCP connection.
Definition: uip.h:1336
#define uip_aborted()
Has the connection been aborted by the other end?
Definition: uip.h:781
char memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
Definition: memb.c:79
#define uip_mss()
Get the current maximum segment size that can be sent on the current connection.
Definition: uip.h:838
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
Definition: memb.c:59
#define NULL
The null pointer.
#define PT_INIT(pt)
Initialize a protothread.
Definition: pt.h:79
#define uip_poll()
Is the connection being polled by uIP?
Definition: uip.h:817
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
Definition: uip.h:1238
#define PT_THREAD(name_args)
Declaration of a protothread.
Definition: pt.h:99
#define uip_connected()
Has the connection just been connected?
Definition: uip.h:761
CCIF clock_time_t clock_time(void)
Get the current clock time.
Definition: clock.c:41
#define uip_abort()
Abort the current connection.
Definition: uip.h:682
PETSCII/ASCII conversion functions.
#define PSOCK_INIT(psock, buffer, buffersize)
Initialize a protosocket.
Definition: psock.h:150
#define PSOCK_GENERATOR_SEND(psock, generator, arg)
Generate data with a function and send it.
Definition: psock.h:225
#define MEMB(name, structure, num)
Declare a memory block.
Definition: memb.h:89
#define PSOCK_CLOSE(psock)
Close a protosocket.
Definition: psock.h:241
#define PSOCK_END(psock)
Declare the end of a protosocket&#39;s protothread.
Definition: psock.h:348
#define PT_BEGIN(pt)
Declare the start of a protothread inside the C function implementing the protothread.
Definition: pt.h:114
#define uip_timedout()
Has the connection timed out?
Definition: uip.h:791
#define PT_END(pt)
Declare the end of a protothread.
Definition: pt.h:126
CCIF void tcp_listen(uint16_t port)
Open a TCP port.
#define PSOCK_DATALEN(psock)
The length of the data that was previously read.
Definition: psock.h:304
#define uip_closed()
Has the connection been closed by the other end?
Definition: uip.h:771
uip_ipaddr_t ripaddr
The IP address of the remote host.
Definition: uip.h:1337
uip_appdata
Pointer to the application data in the packet buffer.
Definition: tcp_loader.c:74