ESP8266 ILI9341 display support code with printf sources, wire-frame viewer and custom fonts  1.0
ESP8266ILI9341DisplayProject
web.c
Go to the documentation of this file.
1 
24 #include "user_config.h"
25 
26 #include <stdint.h>
27 #include <stdarg.h>
28 #include <string.h>
29 #include <math.h>
30 
31 #include "display/ili9341.h"
32 #include "web/web.h"
33 
34 
35 // References: http://www.w3.org/Protocols/rfc2616/rfc2616.html
36 
38 #define MAX_MSG 1024
39 #define CGI_TOKEN_SIZE 128
41 #define BUFFER_SIZE 1000
44 
46 
47 extern window *winmsg,*wintop;
48 
51 
55 static esp_tcp WebTcp;
56 
57 // =======================================================
58 // http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4
59 
62  { "GET", TOKEN_GET },
63  { "PUT", TOKEN_PUT },
64  { "POST", TOKEN_POST },
65  { "HEAD", TOKEN_HEAD },
66  { "Host:", TOKEN_HOST },
67  { "User-Agent:", TOKEN_USER_AGENT },
68  { "HTTPS:", TOKEN_HTTPS},
69  { "DNT:", TOKEN_DNT},
70  { "Accept:", TOKEN_ACCEPT },
71  { "Accept-Language:", TOKEN_ACCEPT_LANGUAGE },
72  { "Accept-Encoding:", TOKEN_ACCEPT_ENCODING },
73  { "Connection:", TOKEN_CONNECTION },
74  { "Referer:", TOKEN_REFERER },
75  { "Content-Length:", TOKEN_CONTENT_LENGTH },
76  { "Content-Type:", TOKEN_CONTENT_TYPE },
77  { "Cache-Control:", TOKEN_CACHE_CONTROL },
78  { NULL, -1}
79 };
80 
81 
82 
83 // =============================================================
84 
86 char *http_status[] = {
87  // Successful
88  "200 OK",
89  // 200 status code is by far the most common returned.
90  // It means, simply, that the request was received and understood
91  // and is being processed.
92  "201 Created",
93  // 201 status code indicates that a request was successful
94  // and as a result, a resource has been created (for example a new page).
95  "202 Accepted",
96  // 202 indicates that server has received and understood the request,
97  // and that it has been accepted for processing, although it may not
98  // be processed immediately.
99  "204 No Content",
100  // 204 means that the request was received and understood, but that
101  // there is no need to send any data back.
102 
103  // Redirection
104  "301 Moved Permanently",
105  // 301 tells a client that the resource they asked
106  // for has permanently moved to a new location. The response should
107  // also include this location. It tells the client to use the new URL
108  // the next time it wants to fetch the same resource.
109  "302 Found",
110  // 302 tells a client that the resource they asked for has temporarily
111  // moved to a new location. The response should also include this location.
112  // It tells the client that it should carry on using the same URL
113  // to access this resource.
114  "304 Not Modified",
115  // 304 status code is sent in response to a request (for a document)
116  // that asked for the document only if it was newer than the one the
117  // client already had. Normally, when a document is cached, the date
118  // it was cached is stored. The next time the document is viewed, the
119  // client asks the server if the document has changed. If not, the
120  // client just reloads the document from the cache.
121 
122  // Client Error
123  "400 Bad Request",
124  // 400 indicates that the server did not understand the request due
125  // to bad syntax.
126  "401 Unauthorized",
127  // 401 status code indicates that before a resource can be accessed,
128  // the client must be authorised by the server.
129  "403 Forbidden",
130  // 403 status code indicates that the client cannot access the
131  // requested resource. That might mean that the wrong username
132  // and password were sent in the request, or that the permissions
133  // on the server do not allow what was being asked.
134  "404 Not Found",
135  // The best known of them all, the 404 status code indicates that
136  // the requested resource was not found at the URL given, and the
137  // server has no idea how long for.
138 
139  // Server Error
140 
141  "500 Internal Server Error",
142  // 500 status code (all too often seen by Perl programmers) indicates
143  // that the server encountered something it didn't expect and was unable
144  // to complete the request.
145  "501 Not Implemented",
146  // The 501 status code indicates that the server does not support all
147  // that is needed for the request to be completed.
148  "502 Bad Gateway",
149  // 502 status code indicates that a server, while acting as a proxy,
150  // received a response from a server further upstream that it judged
151  // invalid.
152  "503 Service Unavailable",
153  // 503 status code is most often seen on extremely busy servers, and
154  // it indicates that the server was unable to complete the request
155  // due to a server overload.
156  NULL
157 };
158 
161  { PTYPE_TEXT, "text/plain", ".text", ".txt" },
162  { PTYPE_HTML, "text/html", ".htm", ".html" },
163  { PTYPE_PDF, "application/pdf", ".pdf",NULL},
164  { PTYPE_CSS, "text/css", ".css", NULL },
165  { PTYPE_CGI, "text/html", ".cgi", NULL },
166  { PTYPE_JS, "text/plain", ".js", NULL },
167  { PTYPE_XML, "text/plain", ".xml", NULL },
168  { PTYPE_ICO, "mage/vnd.microsoft.icon", ".ico", NULL },
169  { PTYPE_GIF, "image/gif", ".gif", NULL },
170  { PTYPE_JPEG, "image/jpeg", ".jpg", ".jpeg" },
171  { PTYPE_MPEG, "video/mpeg", ".mpg", ".mpeg" },
172  { PTYPE_FLASH, "application/x-shockwave-flash", ".swf", NULL },
173  { PTYPE_ERR, "text/html", NULL , NULL }
174 };
175 
176 // =======================================================
181 MEMSPACE
182 void web_sep(void)
183 {
184  printf("\n==========================================\n");
185 }
186 
187 // =======================================================
194 MEMSPACE
196 {
197  int len;
198 
199  if(!p)
200  {
201 #if WEB_DEBUG & 1
202  printf("wait_send: p = NULL\n");
203 #endif
204  return (-1);
205  }
206 
207  if(!p->conn)
208  {
209 #if WEB_DEBUG & 1
210  printf("wait_send: conn=NULL\n");
211 #endif
212  return (-1);
213  }
214 
215  if(!p->wbuf)
216  {
217 #if WEB_DEBUG & 1
218  printf("wait_send: p->wbuf = NULL\n");
219 #endif
220  return (-1);
221  }
222 
223  // The send socket is NOT busy so nothing to do
224  if(!p->send)
225  {
226  return 0;
227  }
228 
229  // The send socket is busy
230 #if WEB_DEBUG & 4
231  printf("wait_send: waiting conn=%p, len:%d\n", (void *)p->conn, p->send);
232 #endif
233 
234  // send socket is busy with the last send request
235  len = p->send;
236  while(p && p->send )
237  {
238  optimistic_yield(1000);
239  }
240 
241  if(!p)
242  {
243 #if WEB_DEBUG & 4
244  printf("wait_send: p = NULL after wait\n");
245  printf("\n");
246 #endif
247  return(-1);
248  }
249 #if WEB_DEBUG & 4
250  printf("wait_send: done conn=%p, len:%d\n", (void *)p->conn, len);
251  printf("\n");
252 #endif
253  return(len);
254 }
255 
256 
257 // =======================================================
265 MEMSPACE
267 {
268  int i;
269  int ret;
270  int len;
271 
272 
273  if(wait_send(p) == -1)
274  return(-1);
275 
276  if(p->delete)
277  return(0);
278 
279  // wait for existing buffers to send before filling new one
280  if(!p->wind )
281  return(0);
282 
283  len = p->wind;
284 
285 #if WEB_DEBUG & 16
286  for(i=0;i<p->wind;++i)
287  putchar(p->wbuf[i]);
288 #endif
289  // sent callback resets send and wind for us
290  ret = espconn_send(p->conn, (uint8_t *)p->wbuf, p->wind );
291 
292  if( !ret )
293  {
294  // flag that send socket is busy with the last send request
295  p->send = p->wind;
296  return( p->send );
297  }
298 
299  // failed!
300 #if WEB_DEBUG & 1
301  printf("write_buffer: espconn_send(%d bytes) error:%d\n", p->wind, ret);
302  printf("\tconn=%p, p->wbuf:%08p\n", (long)p->conn, (long)p->wbuf);
303  if(ret == ESPCONN_MEM)
304  printf("\tOut of memory;n");
305  if(ret == ESPCONN_ARG)
306  printf("\tillegal argument; cannot find network transmission according to structure espconn\n");
307  if(ret == ESPCONN_MAXNUM)
308  printf("\tbuffer (or 8 packets at most) of sending data is full\n");
309  if(ret == ESPCONN_IF)
310  printf("fail to send UDP data.\n");
311 #endif
312  p->delete = 1;
313  espconn_disconnect(p->conn);
314  return(-1);
315 }
316 
322 MEMSPACE
324 {
325  int ret = write_buffer(p);
326  if(ret == -1)
327  return(ret);
328  // The send code clears the bufferi, index and send flag
329  return( wait_send(p) );
330 }
331 
338 MEMSPACE
339 int write_byte(rwbuf_t *p, int c)
340 {
341  int i;
342  int ret;
343 
344  // We let the routines that call us report errors
345  if(!p || !p->conn || !p->wbuf)
346  {
347  return (0);
348  }
349 
350  if(p->delete)
351  {
352  return(0);
353  }
354 
355  p->wbuf[p->wind++] = c;
356  if(p->wind >= p->wsize)
357  {
358  if( write_flush(p) == -1)
359  return(0);
360  }
361  return(1);
362 }
363 
364 
365 // =======================================================
366 MEMSPACE
372 static _led = 0;
373 MEMSPACE
374 void led_on(int led)
375 {
376  printf("LED%d on\n", led);
377 }
383 MEMSPACE
384 void led_off(int led)
385 {
386  printf("LED%d off\n", led);
387 }
388 
389 // =======================================================
390 
399 MEMSPACE
400 static void tcp_accept(espconn_t *esp_config, esp_tcp *esp_tcp_config,
401  uint16_t port, void (*connect_callback)(struct espconn *))
402 {
403 
404  int ret;
405 #if WEB_DEBUG & 2
406  printf("memory free:%ld, connections:%d\n", system_get_free_heap_size(), connections);
407 #endif
408 
409 #if WEB_DEBUG & 2
410  web_sep();
411  printf("tcp_accept: %p\n", esp_config);
412 #endif
413 
414  memset(esp_tcp_config, 0, sizeof(esp_tcp));
415  esp_tcp_config->local_port = port;
416  memset(esp_config, 0, sizeof(espconn_t));
417  esp_config->type = ESPCONN_TCP;
418  esp_config->state = ESPCONN_NONE;
419  esp_config->proto.tcp = esp_tcp_config;
420  espconn_regist_connectcb(esp_config, (espconn_connect_callback)connect_callback);
421  espconn_accept(esp_config);
422  ret = espconn_tcp_set_max_con_allow(esp_config, MAX_CONNECTIONS);
423  if(ret)
424  printf("espconn_tcp_set_max_con_allow(%d) != (%d) failed\n",
425  MAX_CONNECTIONS, espconn_tcp_get_max_con_allow(esp_config));
426 #if WEB_DEBUG & 2
427  printf("espconn_tcp_get_max_con_allow:(%d)\n", (int) espconn_tcp_get_max_con_allow(esp_config));
428 #endif
429 }
430 // =======================================================
431 
432 
438 MEMSPACE
440 {
441  if(!p)
442  return;
443  p->received = 0;
444  p->rind = 0;
445 }
446 
452 MEMSPACE
454 {
455  if(!p)
456  return;
457  p->send = 0;
458  p->wind = 0;
459 }
460 
469 MEMSPACE
470 void display_ipv4(char *msg, uint8_t *ip, int port)
471 {
472  printf("%s: %d.%d.%d.%d:%d\n",
473  msg,
474  (int)ip[0],
475  (int)ip[1],
476  (int)ip[2],
477  (int)ip[3],
478  port );
479 }
480 
486 MEMSPACE
488 {
489  if(!p)
490  return;
491 
492  p->delete = 0;
493  // Free receive buffer
494  p->rsize = 0;
495  if(p->rbuf)
496  safefree(p->rbuf);
497  p->rbuf = NULL;
498  rwbuf_rinit(p);
499 
500  // Free write buffer
501  p->wsize = 0;
502  if(p->wbuf)
503  safefree(p->wbuf);
504  p->wbuf = NULL;
505  rwbuf_winit(p);
506 
507  p->remote_ip[0] = 0; p->remote_ip[1] = 0; p->remote_ip[2] = 0; p->remote_ip[3] = 0;
508  p->remote_port = 0;
509  p->local_ip[0] = 0; p->local_ip[1] = 0; p->local_ip[2] = 0; p->local_ip[3] = 0;
510  p->local_port = 0;
511 
512  // FIXME
513  if( p->conn != &WebConn)
514  {
515  p->conn = NULL;
516  safefree(p);
517  }
518 }
519 
520 
525 MEMSPACE
527 {
528  char *buf;
529 
530  // connect struction for this connection
531  // Always over allocate to allow an extra EOS or TWO
532  rwbuf_t *p = safecalloc(sizeof(rwbuf_t)+4,1);
533  if(!p)
534  {
535 #if WEB_DEBUG & 1
536  printf("rwbuf_create:calloc failed\n");
537 #endif
538  return(NULL);
539  }
540  p->conn = NULL;
541 
542  // read buffer for this connection
543  rwbuf_rinit(p);
544  // Always over allocate to allow an extra EOS or TWO
545  buf = safecalloc(BUFFER_SIZE+4,1);
546  if(!buf)
547  {
548 #if WEB_DEBUG & 1
549  printf("rwbuf_create rbuf: calloc failed\n");
550 #endif
551  rwbuf_delete(p);
552  return(NULL);
553  }
554  p->rbuf = buf;
555  p->rsize = BUFFER_SIZE;
556 
557  // write buffer for this connection
558  rwbuf_winit(p);
559  // Always over allocate to allow an extra EOS or TWO
560  buf = safecalloc(BUFFER_SIZE+4,1);
561  if(!buf)
562  {
563 #if WEB_DEBUG & 1
564  printf("rwbuf_create wbuf: calloc failed\n");
565 #endif
566  rwbuf_delete(p);
567  return(NULL);
568  }
569  p->wbuf = buf;
570  p->wsize = BUFFER_SIZE;
571  p->delete = 0;
572  p->remote_ip[0] = 0; p->remote_ip[1] = 0; p->remote_ip[2] = 0; p->remote_ip[3] = 0;
573  p->remote_port = 0;
574  p->local_ip[0] = 0; p->local_ip[1] = 0; p->local_ip[2] = 0; p->local_ip[3] = 0;
575  p->local_port = 0;
576  return(p);
577 }
578 
579 
580 // =======================================================
581 
589 MEMSPACE
590 rwbuf_t *find_connection(espconn_t *conn, int *index, char *msg)
591 {
592  rwbuf_t *p;
593  int i;
594 
595  *index = -1;
596  if(!conn)
597  {
598 #if WEB_DEBUG & 1
599  printf("%s: find_connection: conn=NULL\n",msg);
600 #endif
601  return(NULL);
602  }
603 
604  if(conn == &WebConn)
605  {
606 #if WEB_DEBUG & 2
607  printf("%s: find_connection:(%08p == &WebConn)\n",msg, conn);
608 #endif
609  }
610 
611  if(!conn->proto.tcp || !conn->proto.tcp->remote_ip || !conn->proto.tcp->remote_port)
612  {
613 #if WEB_DEBUG & 1
614  printf("%s: find_connection: conn->proto.tcp NULL\n",msg);
615 #endif
616  return(NULL);
617  }
618 
619 // FIXME TODO make sure only one matches !!!!
620  for(i=0;i<MAX_CONNECTIONS;++i)
621  {
622  if( (p = web_connections[i]) )
623  {
624  if(!p->conn)
625  continue;
626 
627  // skip if the connection protocol doesn't match
628  if (conn->type != p->conn->type)
629  continue;
630 
631  // local ports must match
632  if( conn->proto.tcp->local_port != p->local_port )
633  continue;
634 
635  // remote ports must match
636  if( conn->proto.tcp->remote_port != p->remote_port)
637  continue;
638 
639  // If the structure pointer does not match check
640  // the IP and ports
641  if( memcmp( conn->proto.tcp->remote_ip, p->remote_ip,4) != 0)
642  continue;
643 
644  // If the structure pointer does not match check
645  // the IP and ports
646  if( memcmp( conn->proto.tcp->local_ip, p->local_ip,4) != 0)
647  continue;
648 
649  *index = i;
650  return (p);
651  }
652  }
653 #if WEB_DEBUG & 2
654  printf("%s: find_connection: mismatch conn=%p\n", msg, conn );
655  display_ipv4("local ", conn->proto.tcp->local_ip, conn->proto.tcp->local_port);
656  display_ipv4("remote ", conn->proto.tcp->remote_ip, conn->proto.tcp->remote_port);
657  printf("\n");
658 #endif
659 
660  return(NULL);
661 }
662 
668 MEMSPACE
670 {
671  rwbuf_t *p;
672  int index;
673  int i;
674 
675  for(i=0;i<MAX_CONNECTIONS;++i)
676  {
677  if(web_connections[i] == NULL)
678  {
679  p = rwbuf_create();
680  if(!p)
681  {
682 #if WEB_DEBUG & 1
683  printf("create_connection: NO MEMORY conn=%p\n",conn);
684 #endif
685  break;
686  }
687  // FIXME no no no COPY conn structure, etc
688  web_connections[i] = p;
689  p->conn = conn;
690  // local ports must match
691  p->remote_port = conn->proto.tcp->remote_port;
692  memcpy(p->remote_ip, conn->proto.tcp->remote_ip, 4);
693  p->local_port = conn->proto.tcp->local_port;
694  memcpy(p->local_ip, conn->proto.tcp->local_ip, 4);
695 #if WEB_DEBUG & 2
696  printf("create_connection: conn=%p\n",conn);
697 #endif
698  return(p);
699  break;
700  }
701  }
702 #if WEB_DEBUG & 1
703  printf("create_connection: NO FREE connections for conn=%p\n",conn);
704 #endif
705  return(NULL);
706 }
707 
708 
709 
714 MEMSPACE
716 {
717  int i;
718 
719  if(!p)
720  {
721  printf("delete_connection: NULL STRUCTURE NOT FOUND!!!!\n");
722  return(0);
723 
724  }
725 
726  for(i=0;i<MAX_CONNECTIONS;++i)
727  {
728  if( (p == web_connections[i]) )
729  {
730 #if WEB_DEBUG & 2
731  printf("delete_connection: conn=%p\n",p->conn);
732  display_ipv4("local ", p->local_ip, p->local_port);
733  display_ipv4("remote ", p->remote_ip, p->remote_port);
734 #endif
735  rwbuf_delete(p);
736  web_connections[i] = NULL;
737  return(1);
738  }
739  }
740 #if WEB_DEBUG & 2
741  printf("delete_connection: conn=%p NOT FOUND!!!!\n",p->conn);
742  printf("\n");
743 #endif
744  return(0);
745 }
746 
747 
748 // =======================================================
749 
757 MEMSPACE
758 void write_len(rwbuf_t *p, char *str, int len)
759 {
760  while(len--)
761  {
762  if( write_byte(p,*str++) == -1)
763  return;
764  }
765 }
766 
773 MEMSPACE
774 void write_str(rwbuf_t *p, char *str)
775 {
776  while(*str)
777  {
778  if( write_byte(p,*str++) == -1)
779  return;
780  }
781 }
782 
789 MEMSPACE
790 static void _write_byte_fn(struct _printf_t *pr, char c)
791 {
792  rwbuf_t *p = (rwbuf_t *) pr->buffer;
793 
794  // if errors happen they will not get sent
795  (void) write_byte(p,c);
796  pr->sent++;
797 }
798 
799 
807 MEMSPACE
808 int vsock_printf(rwbuf_t *p, const char *fmt, va_list va)
809 {
810  printf_t fn;
811 
812  fn.put = _write_byte_fn;
813  fn.sent= 0;
814  fn.buffer = (void *) p;
815 
816  _printf_fn(&fn, fmt, va);
817 
818  return(fn.sent);
819 }
820 
821 
829 MEMSPACE
830 int sock_printf(rwbuf_t *p, const char *fmt, ...)
831 {
832  int len;
833  va_list va;
834 
835  va_start(va, fmt);
836  len = vsock_printf(p, fmt, va);
837  va_end(va);
838 
839  return len;
840 }
841 
842 // =================================================================
852 MEMSPACE
853 int html_msg(rwbuf_t *p, int status, char type, char *fmt, ...)
854 
855 {
856  int len,ret;
857  char *header;
858  char *body;
859  char *ptr;
860 
861  char *statp = html_status(status);
862  char *mimep = mime_type( type );
863 
864  va_list args;
865 
866  va_start(args, fmt);
867 
868 
869  // Always over allocate to allow an extra EOS or TWO
870  header = safecalloc(MAX_MSG+4,1);
871  if(!header) {
872 #if WEB_DEBUG & 1
873  printf("html_msg: calloc failed\n");
874  printf("\tstatus: %s\n",statp);
875  printf("\tmime: %s\n",mimep);
876  printf(fmt, args);
877 #endif
878  return(0);
879  }
880  // Make header for room for 5 byte size starting at #
881 
882  // HTTP/1.1 200 OK\n
883  snprintf(header,MAX_MSG,
884  "HTTP/1.1 %s\nContent-Type: %s\nContent-Length: # \n\n",
885  statp, mimep);
886 
887  // Make body point to message after header
888  body = header;
889  while(*body)
890  body++;
891 
892 
893  // Start of body
894  strncat(header,"<html><body>",MAX_MSG);
895  ptr = header;
896  while(*ptr)
897  ptr++;
898 
899  len = strlen(body);
900  // We allocated MAX_MSG to header so we subtract len
901  vsnprintf(ptr,MAX_MSG - len - 1, fmt, args);
902 
903  strncat(header,"</html></body>",MAX_MSG);
904  len = strlen(body);
905 
906  // Patch in the message size
907  ptr = header;
908  while(*ptr && *ptr != '#')
909  ++ptr;
910  u5toa(ptr,(uint16_t) len);
911 
912  // send buffer
913  len = strlen(header);
914  write_len(p,header,len);
915 
916  safefree(header);
917  return(len);
918 }
919 
920 
921 
922 // =======================================================================
923 // MEMORY gets FUNCTIONS
924 
932 MEMSPACE
933 char *meminit(mem_t *p, char *ptr, int size)
934 {
935  if(!ptr)
936  return(ptr);
937  p->next = ptr;
938  p->ptr = ptr;
939  p->size = size;
940  // We always allocate 4 bytes more then we need
941  return(p->next);
942 }
943 
944 
951 MEMSPACE
952 char *memgets(mem_t *p)
953 {
954  char *base = p->next;
955  char *ptr = p->next;
956 
957  if(!p->ptr || p->size <= 0)
958  return(NULL);
959 
960  // Mark end of this string and point to start of next string
961  while(*ptr && *ptr != '\n' && p->size) {
962  ++ptr;
963  p->size--;
964  }
965  // replace newline with EOS
966  *ptr = 0;
967  // only advance pointer if size > 0
968  if(p->size)
969  ++ptr;
970  p->next = ptr;
971  return(base);
972 }
973 
974 
975 // ==============================================================
976 
982 MEMSPACE
983 char *mime_type(int type)
984 {
985  if(type >= PTYPE_ERR)
986  type = PTYPE_ERR;
987  return(mimes[type].mime);
988 }
989 
995 MEMSPACE
996 int file_type(char *name)
997 {
998  char *ptr;
999  int i;
1000 
1001  ptr = name;
1002  while(*ptr)
1003  {
1004  if(*ptr == '.')
1005  name = ptr;
1006  ++ptr;
1007  }
1008 
1009  for(i=0;i<PTYPE_ERR;++i)
1010  {
1011  if(mimes[i].ext1 == NULL)
1012  break;
1013  if(strcasecmp(name, mimes[i].ext1) == 0)
1014  return(i);
1015  if(mimes[i].ext2 == NULL)
1016  continue;
1017  if(strcasecmp(name, mimes[i].ext2) == 0)
1018  return(i);
1019  }
1020  return(i);
1021 }
1022 
1023 
1029 MEMSPACE
1030 char *html_status(int status)
1031 {
1032  int i;
1033  for(i=0;http_status[i];++i) {
1034  if(status == atoi(http_status[i]))
1035  return(http_status[i]);
1036  }
1037  // Not found ? Then find 500 error and return that
1038  for(i=0;http_status[i];++i) {
1039  if(500 == atoi(http_status[i]))
1040  return(http_status[i]);
1041  }
1042 #if WEB_DEBUG & 1
1043  printf("html_status: %d not found\n",status);
1044 #endif
1045  return("500 Internal Server Error");
1046 }
1047 
1048 
1054 MEMSPACE
1056 {
1057  hi->type = -1; // GET,PUT,HEADER
1058  hi->filename = NULL;
1059  hi->connection = NULL;
1060  hi->args = NULL;
1061  hi->arg_ptr = NULL;
1062  hi->args_length = 0;
1063  hi->html_encoding= NULL;
1064  hi->content_type = NULL;
1065  hi->content_length = 0;
1066  hi->msg = NULL;
1067 }
1068 
1069 
1076 MEMSPACE
1077 int match_headers(char *str, char **p)
1078 {
1079  int len, i,ind;
1080  char *ptr;
1081 
1082  if(!str)
1083  return(-1);
1084 
1085  str = skipspaces(str);
1086  trim_tail(str);
1087 
1088  len = strlen(str);
1089  if(!len)
1090  return(-1);
1091 
1092  for(i=0;msg_headers[i].type != -1; ++i) {
1093  if( (ind = MATCHI_LEN(str, msg_headers[i].pattern)) ) {
1094  ptr = str + ind;
1095  ptr = skipspaces(ptr);
1096  // Instead of reallocating we now assume we can replace the EOL with EOS in ram
1097  // msg_headers[i].value = ptr; // stralloc(ptr);
1098  *p = ptr;
1099  return(i);
1100  }
1101  }
1102  return(-1);
1103 }
1104 
1115 MEMSPACE
1116 char *process_args(hinfo_t *hi, char *ptr)
1117 {
1118  char *out;
1119  int h,l,num;
1120  char *end;
1121  int len;
1122  int size = 0;
1123 
1124  len = strlen(ptr);
1125 #if WEB_DEBUG & 8
1126  printf("process_args:(%d)[%s]\n",len,ptr);
1127 #endif
1128 
1129  // find next space or EOS - after arguments
1130  // HTTP/Versions follows space
1131  end = nextspace(ptr);
1132  if(*end)
1133  *end++ = 0; // EOS after arguments
1134 
1135  hi->args = ptr;
1136  hi->arg_ptr = ptr;
1137  hi->args_length = len; // initial undecoded length
1138 
1139 #if WEB_DEBUG & 8
1140  printf("process_args:[%s]\n",hi->args);
1141  printf("process_args_length:[%d]\n",hi->args_length);
1142 #endif
1143 
1144  if(!hi->args_length)
1145  {
1146 #if WEB_DEBUG & 8
1147  // this is not an error - just a notice
1148  printf("process_args: zero length\n");
1149 #endif
1150  return(end);
1151  }
1152  len = hi->args_length;
1153 
1154  // We are overwriting the input buffer
1155  // The output will always be <= in size - so this works
1156  out = ptr;
1157  while(len > 0) {
1158  // Name = Value
1159  if(*ptr == '=') { // Name =
1160  ptr++;
1161  --len;
1162  *out++ = 0; // EOS break
1163  ++size;
1164  continue;
1165  }
1166  if( *ptr == '&' ) { // New Argument
1167  ptr++;
1168  --len;
1169  *out++ = 0; // EOS break
1170  ++size;
1171  continue;
1172  }
1173  if(*ptr == '+') { // Space
1174  ptr++;
1175  --len;
1176  *out++ = ' ';
1177  ++size;
1178  continue;
1179  }
1180  if ( *ptr == '%') {
1181  // skip %
1182  ++ptr;
1183  --len;
1184  // Make sure we do not go past the end of the string
1185  if(!ptr[0] || !ptr[1])
1186  {
1187 #if WEB_DEBUG & 1+8
1188  printf("process_args: HTML %HEX decode short string\n");
1189 #endif
1190  break;
1191  }
1192 
1193  // Is the data HEX ?
1194  h = atodigit( *ptr++, 16);
1195  l = atodigit( *ptr++, 16);
1196  len -=2;
1197 
1198  if(h < 0 || l < 0) // The data was not HEX
1199  {
1200  num = ' ';
1201 #if WEB_DEBUG & 1+8
1202  printf("process_args: HTML %HEX bad value\n");
1203 #endif
1204  }
1205  else
1206  {
1207  // The data was HEX
1208  num = (h << 4) | l;
1209  }
1210 
1211  *out++ = num;
1212  ++size;
1213  continue;
1214  } // '%'
1215 
1216  // Default is to copy
1217  *out++ = *ptr++; // Character
1218  ++size;
1219  --len;
1220  }
1221  // EOS at very end of buffer
1222  *out = 0;
1223  // Compute new length of arguments string space after decoding
1224  hi->args_length = size;
1225 
1226  return(end);
1227 }
1228 
1234 MEMSPACE
1235 char *first_arg(hinfo_t *hi)
1236 {
1237  return(hi->arg_ptr = hi->args);
1238 }
1239 
1246 MEMSPACE
1247 char *next_arg(hinfo_t *hi)
1248 {
1249  uint8_t len;
1250  char *ptr = hi->arg_ptr;
1251 
1252  if(!ptr)
1253  return(NULL);
1254 
1255  // At or past the end of arguments
1256  if(ptr >= (hi->args + hi->args_length) )
1257  return(hi->arg_ptr = NULL);
1258 
1259  // Name
1260  len = strlen(ptr);
1261  // Empty name will also terminate arguments
1262  if(!len) // Done ??
1263  return(hi->arg_ptr = NULL);
1264 
1265 #if WEB_DEBUG & 8
1266  printf("next_arg:%s=",ptr);
1267 #endif
1268 
1269  ptr += len+1; // skip past name
1270 
1271  // Are we past the argument list ? if so we have an error
1272  if(ptr > (hi->args + hi->args_length) )
1273  return(hi->arg_ptr = NULL);
1274 
1275  // VALUE
1276 #if WEB_DEBUG & 8
1277  printf("next_arg:%s\n",ptr);
1278 #endif
1279 
1280  // Value can be empty
1281  len = strlen(ptr);
1282  // point past value
1283  ptr += len+1; // skip past name
1284 
1285  // Are we at the end - or past the argument list ?
1286  if(ptr >= (hi->args + hi->args_length) )
1287  return(hi->arg_ptr = NULL);
1288 
1289  return(hi->arg_ptr = ptr);
1290 }
1291 
1297 MEMSPACE
1298 char *arg_name(hinfo_t *hi)
1299 {
1300  char *ptr = hi->arg_ptr;
1301  int len;
1302 
1303  // NAME
1304  // Are we at the end - or past the argument list ?
1305  if(!ptr || ptr >= (hi->args + hi->args_length) )
1306  {
1307 #if WEB_DEBUG & 8
1308  printf("arg_name: END OF ARGS\n");
1309 #endif
1310  return(hi->arg_ptr = NULL);
1311  }
1312 
1313  len = strlen(ptr);
1314 
1315  if(!len) // End of list
1316  {
1317 #if WEB_DEBUG & 8
1318  printf("arg_name: END OF ARGS\n");
1319 #endif
1320  return(hi->arg_ptr = NULL);
1321  }
1322 
1323 #if WEB_DEBUG & 8
1324  printf("arg_name: name(%d)=%s\n", len,ptr);
1325 #endif
1326 
1327  // Does name extend past the list ?
1328  if((ptr + len) > (hi->args + hi->args_length) )
1329  {
1330 #if WEB_DEBUG & 1+8
1331  printf("arg_name: name(%d) size is > args length by (%d)\n",
1332  len, ((ptr + len) - (hi->args + hi->args_length)) );
1333 #endif
1334  return(hi->arg_ptr = NULL);
1335  }
1336 
1337  return(ptr);
1338 }
1339 
1345 MEMSPACE
1346 char *arg_value(hinfo_t *hi)
1347 {
1348  char *ptr = hi->arg_ptr;
1349  int len;
1350 
1351  // NAME
1352  // Are we at the end - or past the argument list ?
1353  if(!ptr || ptr >= (hi->args + hi->args_length) )
1354  {
1355 #if WEB_DEBUG & 8
1356  printf("arg_value: name END OF ARGS\n");
1357 #endif
1358  return(hi->arg_ptr = NULL);
1359  }
1360 
1361  len = strlen(ptr);
1362 
1363  if(!len) // End of list
1364  {
1365 #if WEB_DEBUG & 8
1366  printf("arg_value: name END OF ARGS\n");
1367 #endif
1368  return(hi->arg_ptr = NULL);
1369  }
1370 
1371 #if WEB_DEBUG & 8
1372  printf("arg_value: name(%d)=%s\n", len,ptr);
1373 #endif
1374 
1375  // Does name extend past the list ?
1376  if((ptr + len) > (hi->args + hi->args_length) )
1377  {
1378 #if WEB_DEBUG & 1+8
1379  printf("arg_value: name(%d) size is > args length by (%d)\n",
1380  len, ((ptr + len) - (hi->args + hi->args_length)) );
1381 #endif
1382  return(hi->arg_ptr = NULL);
1383  }
1384  ptr += len;
1385 
1386  // VALUE
1387  if((ptr + 1) > (hi->args + hi->args_length) )
1388  {
1389 #if WEB_DEBUG & 1+8
1390  printf("arg_value: value start is > args length by (%d)\n",
1391  ((ptr + 1) - (hi->args + hi->args_length)) );
1392 #endif
1393  hi->arg_ptr = NULL;
1394  return(ptr);
1395  }
1396  ++ptr;
1397 
1398  // VALUE can be empty but must not be past the argument list
1399  len = strlen(ptr);
1400 
1401  // Does value extend past the list ?
1402  if((ptr + len) > (hi->args + hi->args_length) )
1403  {
1404 #if WEB_DEBUG & 1+8
1405  printf("arg_value: value size is > args length by (%d)\n",
1406  ((ptr + len) - (hi->args + hi->args_length)) );
1407 #endif
1408 
1409  return(hi->arg_ptr = NULL);
1410  }
1411 
1412  return(ptr); // Value
1413 }
1414 
1421 MEMSPACE
1422 char *http_value(hinfo_t *hi, char *str)
1423 {
1424  char *name,*value;
1425 
1426  first_arg(hi);
1427  while( (name = arg_name(hi)) ) {
1428  if(strcasecmp(name,str) == 0) {
1429  value = arg_value(hi);
1430  if(!value)
1431  return(NULL);
1432 #if WEB_DEBUG & 8
1433  printf("http_value:%s=%s\n",str,value);
1434 #endif
1435  return(value);
1436  }
1437  if(!next_arg(hi))
1438  break;
1439  }
1440  return(NULL);
1441 }
1442 
1443 
1450 MEMSPACE
1451 int is_header(char *str, char **p)
1452 {
1453  if(!str)
1454  {
1455  return (0);
1456  }
1457  while(*str && *str != ':') {
1458  if(*str <= ' ' || *str > 'z')
1459  break;
1460  ++str;
1461  }
1462  if(*str == ':')
1463  {
1464  *p = str+1;
1465  return(1);
1466  }
1467  return(0);
1468 }
1469 
1475 MEMSPACE
1476 char *nextbreak(char *ptr)
1477 {
1478  if(!ptr)
1479  return(ptr);
1480 
1481  while(*ptr) {
1482  if(*ptr == ' ' || *ptr == '\t' || *ptr == '?')
1483  break;
1484  ++ptr;
1485  }
1486  return(ptr);
1487 }
1488 
1489 
1496 MEMSPACE
1497 void u5toa(char *ptr, uint16_t num)
1498 {
1499  char buf[10];
1500  snprintf(buf,5,"%5u",num);
1501  memcpy(ptr,buf,5);
1502 }
1503 
1504 
1505 
1506 // =================================================================
1507 
1508 
1517 MEMSPACE
1518 void html_head(rwbuf_t *p, int status, char type, int len )
1519 {
1520  sock_printf(p,"HTTP/1.1 %s\nContent-Type: %s\nContent-Length: %lu\n\n",
1521  html_status(status),
1522  mime_type(type),
1523  len );
1524 }
1525 
1526 
1527 // ==============================================================================
1534 MEMSPACE
1536 {
1537  int ret,len;
1538  int c,type,header;
1539 
1540  char *ptr;
1541  char *value;
1542  char *name;
1543  char *save;
1544  mem_t memp;
1545 
1546  init_hinfo(hi); // Init Headers
1547 
1548  type = -1;
1549 
1550 #if WEB_DEBUG & 8
1551  printf("\nparse_http_request\n");
1552 #endif
1553  if(!p || !p->rbuf || !p->received)
1554  {
1555 #if WEB_DEBUG & 1
1556  printf("EMPTY\n");
1557 #endif
1558  return(0);
1559  }
1560 
1561  ptr = meminit(&memp, p->rbuf, p->received);
1562 
1563  // memgets converts '\n' to EOS, then points to next string
1564  while( (ptr = memgets(&memp)) )
1565  {
1566  save = ptr;
1567  // check against known headers
1568  header = match_headers(save,&ptr);
1569 
1570  if(header == -1)
1571  {
1572  // Does it at least look like a header ?
1573  if( !is_header(save, &ptr))
1574  {
1575 #if WEB_DEBUG & 8
1576  printf("Header break ==== \n");
1577 #endif
1578  break;
1579  }
1580 #if WEB_DEBUG & 8
1581  printf("header skip:[%s]\n",save);
1582 #endif
1583  // skip the unknown header
1584  continue;
1585  }
1586 
1587 #if WEB_DEBUG & 8
1588  printf("header: %s %s\n",msg_headers[header].pattern,ptr);
1589 #endif
1590  // ptr now points just after the matched header pattern
1591 
1592  type = msg_headers[header].type;
1593 
1594  if(type == TOKEN_CONTENT_LENGTH)
1595  {
1596  hi->content_length = atoi(ptr);
1597  continue;
1598  }
1599 
1600  if(type == TOKEN_CONTENT_TYPE )
1601  {
1602  hi->content_type = ptr;
1603  continue;
1604  }
1605 
1606  // Process CONNECTION directive
1607  if(type == TOKEN_CONNECTION)
1608  {
1609  hi->connection = (char *)ptr;
1610  ptr = nextbreak(ptr);
1611  if(*ptr)
1612  *ptr++ = 0; // Filename EOS
1614 #if WEB_DEBUG & 8
1615  printf("connection: %s\n", hi->connection);
1616 #endif
1617  }
1618 
1619  // Process GET,POST or HEAD directive
1620  // These methods put EOS characters withing the current string
1621  if(type == TOKEN_GET)
1622  {
1623  hi->type = type;
1624  hi->filename = ptr;
1625  ptr = nextbreak(ptr);
1626  c = *ptr;
1627  if(*ptr)
1628  *ptr++ = 0; // Filename EOS
1629 #if WEB_DEBUG & 8
1630  printf("filename: [%s]\n",hi->filename);
1631 #endif
1632  // ? implies Arguments
1633  if(c == '?')
1634  ptr = process_args(hi,ptr);
1635 
1636  // HTTP Encoding
1637  ptr = skipspaces(ptr);
1638  hi->html_encoding = ptr;
1639  } // GET
1640 
1641  else if(type == TOKEN_POST || type == TOKEN_HEAD )
1642  {
1643  hi->type = type;
1644  hi->filename = ptr;
1645  // find next space - after arguments
1646  ptr = nextbreak(ptr);
1647  c = *ptr;
1648  if(*ptr)
1649  *ptr++ = 0; // Filename EOS
1650 #if WEB_DEBUG & 8
1651  printf("filename: [%s]\n",hi->filename);
1652 #endif
1653  // ? implies Arguments
1654  if(c == '?') {
1655 #if WEB_DEBUG & 8
1656  printf("Warning arguments not expected for %d\n", type);
1657 #endif
1658  ptr = process_args(hi,ptr);
1659  }
1660  // HTTP Encoding
1661  ptr = skipspaces(ptr);
1662  hi->html_encoding = ptr;
1663  } // POST or HEAD
1664  else if( type == -1) {
1665 #if WEB_DEBUG & 8
1666  printf("Unknown type: %d\n", hi->type);
1667 #endif
1668  return(0);
1669  }
1670  }
1671 
1672  // POST has arguments after all headers
1673  if(hi->type == TOKEN_POST ) {
1674  // Get first non blank line
1675  while( (ptr = memgets(&memp)) ) {
1676 #if WEB_DEBUG & 8
1677  printf("process_args:[%s]\n",ptr);
1678 #endif
1679  if(strlen(ptr) > 1)
1680  break;
1681  }
1682  if(strlen(ptr) != hi->content_length)
1683  {
1684 #if WEB_DEBUG & 8
1685  printf("strlen:[%d] != hi->content_length:[%d]\n",
1686  strlen(ptr) , hi->content_length);
1687 #endif
1688 
1689  }
1690  if(ptr)
1691  ptr = process_args(hi,ptr);
1692  }
1693 
1694 #if WEB_DEBUG & 8
1695  if(hi->type == TOKEN_POST && hi->content_length)
1696  {
1697  int len;
1698  printf("ARGS\n");
1699  first_arg(hi);
1700  while( (name = arg_name(hi)) ) {
1701  len = strlen(name);
1702  value = arg_value(hi);
1703  printf("\t%s=%s\n",name,value);
1704  if(!next_arg(hi))
1705  break;;
1706  }
1707  printf("END ARGS\n");
1708  }
1709 
1710  if( hi->type != -1)
1711  printf("type: %s\n",msg_headers[hi->type].pattern);
1712  if(hi->filename)
1713  printf("Filename: %s\n",hi->filename);
1714  if(hi->html_encoding)
1715  printf("Html_encoding: %s\n",hi->html_encoding);
1716  if(hi->content_type )
1717  printf("Content-Type: %s\n",hi->content_type);
1718  if(hi->content_length)
1719  printf("Content-Length: %d\n",hi->content_length);
1720 #endif
1721  return(1);
1722 }
1723 
1724 
1725 
1726 // =================================================================
1734 MEMSPACE
1735 static void web_data_receive_callback(void *arg, char *data, unsigned short length)
1736 {
1737  espconn_t *conn = (espconn_t *) arg;
1738  int index;
1739  rwbuf_t *p = find_connection(conn, &index, "web_data_receive_callback");
1740 
1741 #if WEB_DEBUG & 2
1742  printf("memory free:%ld, connections:%d\n", system_get_free_heap_size(), connections);
1743 #endif
1744 
1745  if(!p)
1746  {
1747 #if WEB_DEBUG & 1
1748  printf("web_data_receive_callback: mismatch conn=%p\n",conn);
1749 #endif
1750  // delete the bad connection
1751  espconn_disconnect(conn);
1752  esp_schedule();
1753  return;
1754  }
1755 
1756  // The main task has not yet read the data - we must discard it
1757  if(p->received)
1758  {
1759 #if WEB_DEBUG & 1
1760  printf("web_data_receive_callback: receive buffer busy rejecting:%d\n",length);
1761 #endif
1762  // FIXME flag overrun
1763  esp_schedule();
1764  return;
1765  }
1766 
1767  // TRIM buffer size if needed
1768  if(length > p->rsize)
1769  {
1770  // FIXME we may want to permit multi packet receive
1771  // FIXME flag overrun
1772 #if WEB_DEBUG & 1
1773  printf("web_data_receive_callback: receive too big:%d, trim to:%d\n",length,p->rsize);
1774 #endif
1775  length = p->rsize;
1776  }
1777 
1778  // reset read pointers
1779  rwbuf_rinit(p);
1780  if(p->rbuf)
1781  {
1782  memset(p->rbuf,0, p->rsize);
1783  memcpy(p->rbuf,data,length);
1784  p->received = length;
1785 #if WEB_DEBUG & 2
1786  printf("web_data_receive_callback: conn=%p, received:%d\n",conn,length);
1787 #endif
1788  }
1789  else
1790  {
1791 #if WEB_DEBUG & 1
1792  printf("web_data_receive_callback: buffer NULL\n");
1793 #endif
1794  }
1795 #if WEB_DEBUG & 2
1796  display_ipv4("local ", conn->proto.tcp->local_ip, conn->proto.tcp->local_port);
1797  display_ipv4("remote ", conn->proto.tcp->remote_ip, conn->proto.tcp->remote_port);
1798  printf("\n");
1799 #endif
1800 
1801  esp_schedule();
1802 }
1803 
1809 MEMSPACE
1810 static void web_data_sent_callback(void *arg)
1811 {
1812  espconn_t *conn = (espconn_t *) arg;
1813 
1814  int index;
1815  rwbuf_t *p = find_connection(conn, &index,"web_data_sent_callback");
1816 
1817 #if WEB_DEBUG & 2
1818  printf("memory free:%ld, connections:%d\n", system_get_free_heap_size(), connections);
1819 #endif
1820 
1821  if(!p)
1822  {
1823 #if WEB_DEBUG & 1
1824  printf("web_data_sent_callback: conn mismatch\n");
1825 #endif
1826  return;
1827  }
1828 
1829  if(!p->send)
1830  {
1831 #if WEB_DEBUG & 1
1832  printf("web_data_send_callback: NO send value\n");
1833 #endif
1834  return;
1835  }
1836 
1837 
1838 #if WEB_DEBUG & 2
1839  printf("web_data_send_callback: conn=%p sent:%d\n",p->conn, p->send);
1840  display_ipv4("local ", conn->proto.tcp->local_ip, conn->proto.tcp->local_port);
1841  display_ipv4("remote ", conn->proto.tcp->remote_ip, conn->proto.tcp->remote_port);
1842 #endif
1843 
1844  rwbuf_winit(p);
1845  esp_schedule();
1846 }
1847 
1848 // FIXME we still have issues with deleting connection
1853 MEMSPACE
1854 static void web_data_disconnect_callback(void *arg)
1855 {
1856  espconn_t *conn = (espconn_t *) arg;
1857  int i, index;
1858  rwbuf_t *p;
1859 
1860 #if WEB_DEBUG & 2
1861  printf("memory free:%ld, connections:%d\n", system_get_free_heap_size(), connections);
1862 #endif
1863 
1864  if(!conn)
1865  return;
1866  p = find_connection(conn, &index, "web_data_disconnect_callback");
1867  if(p)
1868  {
1869 #if WEB_DEBUG & 2
1870  printf("web_data_disconnect_callback: disconnect %p\n", conn);
1871 #endif
1872  delete_connection(p);
1873  esp_schedule();
1874  }
1875 
1876 #if WEB_DEBUG & 2
1877  printf("****************************************************\n");
1878  printf("web_data_disconnect_callback: disconnect mismatch %p\n", conn);
1879  display_ipv4("local ", conn->proto.tcp->local_ip, conn->proto.tcp->local_port);
1880  display_ipv4("remote ", conn->proto.tcp->remote_ip, conn->proto.tcp->remote_port);
1881  printf("****************************************************\n");
1882  printf("\n");
1883 #endif
1884  esp_schedule();
1885 }
1886 
1887 
1888 
1894 MEMSPACE
1895 static void web_data_error_callback(void *arg, int8_t err)
1896 {
1897  struct espconn *conn = arg;
1898  int index;
1899 
1900 #if WEB_DEBUG & 2
1901  printf("memory free:%ld, connections:%d\n", system_get_free_heap_size(), connections);
1902 #endif
1903 
1904  rwbuf_t *p = find_connection(conn,&index, "web_data_error_callback");
1905 #if WEB_DEBUG & 2
1906  printf("************************************************\n");
1907  printf("web_data_error_callback: connection %p\n", conn);
1908  if(!p)
1909  {
1910  printf("\tNOT found\n");
1911  }
1912  display_ipv4("\tlocal ", conn->proto.tcp->local_ip, conn->proto.tcp->local_port);
1913  display_ipv4("\tremote ", conn->proto.tcp->remote_ip, conn->proto.tcp->remote_port);
1914  printf("************************************************\n");
1915  printf("\n");
1916 #endif
1917  // delete the bad connection
1918  espconn_disconnect(conn);
1919  esp_schedule();
1920 }
1921 
1927 MEMSPACE
1929 {
1930  long mem = system_get_free_heap_size();
1931  if( mem < 12000)
1932  {
1933 #if WEB_DEBUG & 1
1934  printf("**************************************************\n");
1935  printf("**************************************************\n");
1936  printf("rejecting connection: %p, memory:%ld\n", conn, mem);
1937  printf("**************************************************\n");
1938  printf("**************************************************\n");
1939 #endif
1940  esp_schedule();
1941  return;
1942  }
1943 
1944  // FIXME *** really broken ***
1945  // we need to malloc conn (we just have the one) and copy it (see tcp_accept!)
1946 #if WEB_DEBUG & 2
1947  printf("memory free:%ld, connections:%d\n", system_get_free_heap_size(), connections);
1948 #endif
1949 
1950 #if WEB_DEBUG & 2
1951  printf("web_data_connect_callback: conn=%p\n", conn);
1952 #endif
1953 
1954  // MUST BE MAX_CONNECTIONS - attach rwbuf_t stuff to that
1955 
1956  rwbuf_t *p = create_connection(conn);
1957  if(!p)
1958  {
1959 #if WEB_DEBUG & 1
1960  printf("Can not create connection\n");
1961 #endif
1962  esp_schedule();
1963  return;
1964  }
1965 
1966 #if WEB_DEBUG & 2
1967  display_ipv4("local ", conn->proto.tcp->local_ip, conn->proto.tcp->local_port);
1968  display_ipv4("remote ", conn->proto.tcp->remote_ip, conn->proto.tcp->remote_port);
1969  printf("\n");
1970 #endif
1971 
1972  espconn_regist_recvcb(conn, web_data_receive_callback);
1973  espconn_regist_sentcb(conn, web_data_sent_callback);
1974  // disconnect will get the index into the connection pool
1975  espconn_regist_disconcb(conn, web_data_disconnect_callback);
1976  espconn_regist_reconcb(conn, web_data_error_callback);
1977 
1978  // FIXME we should REUSE!!!!!!!
1979  // espconn_set_opt(conn, ESPCONN_REUSEADDR);
1980 
1981  espconn_regist_time(conn, 10, 0);
1982  // FIXME
1983  esp_schedule();
1984 }
1985 
1986 
1987 // ==========================================================================
1988 
1998 MEMSPACE
2000 {
2001  if(c >= 'A' && c <= 'Z')
2002  return(1);
2003  else if(c >= 'a' && c <= 'z')
2004  return(1);
2005  else if(c >= '0' && c <= '9')
2006  return(1);
2007  else if( c == '-')
2008  return(1);
2009  else if(c == '@' || c == '_' )
2010  return(1);
2011  return(0);
2012 }
2013 
2023 MEMSPACE
2024 int find_cgitoken_start(char *str)
2025 {
2026  int offset = 0;
2027 
2028  while(*str) {
2029  // End of Token
2030  if( str[0] == '@' && str[1] == '_')
2031  {
2032  return(offset);
2033  }
2034  ++str;
2035  ++offset;
2036  }
2037  return(-1);
2038 }
2039 
2050 
2092 
2136 
2327 
2430 
2440 
2489 
MEMSPACE int is_cgitoken_char(int c)
test to see if a character is a valid member of the CGI token character set CGI tokens have the follo...
Definition: web.c:1999
uint16_t content_length
Definition: web.h:50
char * rbuf
Definition: web.h:145
int rsize
Definition: web.h:148
MEMSPACE WEAK_ATR char * strncat(char *dest, const char *src, size_t max)
Append string of at most N bytes from src.
Definition: stringsup.c:214
MEMSPACE int atodigit(int c, int radix)
Convert ASCII character to radix based digit , or -1.
Definition: mathio.c:58
MEMSPACE char * meminit(mem_t *p, char *ptr, int size)
in memory memory gets function
Definition: web.c:933
MEMSPACE char * http_value(hinfo_t *hi, char *str)
Lookup and argument name and return its value.
Definition: web.c:1422
MEMSPACE char * memgets(mem_t *p)
Memory gets function We ASSUME we can replace any with a \0.
Definition: web.c:952
MEMSPACE rwbuf_t * rwbuf_create()
Create socket read/write buffer for a connection.
Definition: web.c:526
int wsize
Definition: web.h:153
MEMSPACE int vsnprintf(char *str, size_t size, const char *format, va_list va)
vsnprintf function
Definition: printf.c:1135
#define BUFFER_SIZE
max size of read/write socket buffers Note: reducing this size below 1500 will slow down transfer a g...
Definition: web.c:43
Definition: web.h:122
MEMSPACE void rwbuf_rinit(rwbuf_t *p)
Initialize socket read status and read index.
Definition: web.c:439
char * ptr
Definition: web.h:58
unsigned short uint16_t
Definition: send.c:18
MEMSPACE size_t WEAK_ATR strlen(const char *str)
String Length.
Definition: stringsup.c:146
MEMSPACE int find_cgitoken_start(char *str)
Find start of CGI token in a string CGI tokens have the following syntax @ They start with "@_" and e...
Definition: web.c:2024
Master include file for project Includes all project includes and defines here.
int type
Definition: web.h:39
static MEMSPACE void web_data_disconnect_callback(void *arg)
Network disconnect callback function.
Definition: web.c:1854
int send
Definition: web.h:151
int local_port
Definition: web.h:158
Definition: web.h:70
MEMSPACE int write_byte(rwbuf_t *p, int c)
Write a byte (buffered) using the rwbuf_t socket buffers for this connection If the buffers are full ...
Definition: web.c:339
uint16_t args_length
Definition: web.h:43
char * next
Definition: web.h:59
char * http_status[]
HTTP status code messages.
Definition: web.c:86
int type
Definition: web.h:90
static MEMSPACE void _write_byte_fn(struct _printf_t *pr, char c)
low level vsock_printf function that calls socket write_byte
Definition: web.c:790
Definition: web.h:73
MEMSPACE int vsock_printf(rwbuf_t *p, const char *fmt, va_list va)
vsock_printf function
Definition: web.c:808
Definition: web.h:120
MEMSPACE void write_len(rwbuf_t *p, char *str, int len)
Write data using buffered write_byte function.
Definition: web.c:758
MEMSPACE void html_head(rwbuf_t *p, int status, char type, int len)
Write HTTP Contenet-Type/Content-Length header.
Definition: web.c:1518
MEMSPACE char * mime_type(int type)
return strung pointer for mime type index
Definition: web.c:983
MEMSPACE void _printf_fn(printf_t *fn, __memx const char *fmt, va_list va)
vsnprintf function
Definition: printf.c:741
uint8_t local_ip[4]
Definition: web.h:156
MEMSPACE rwbuf_t * find_connection(espconn_t *conn, int *index, char *msg)
Find a read/write socket buffer for an espconn connection.
Definition: web.c:590
window * winmsg
#define MAX_MSG
max size of ERROR/REDIRECT/STATUS Message buffer
Definition: web.c:38
static MEMSPACE void web_data_sent_callback(void *arg)
Network sent callback function.
Definition: web.c:1810
MEMSPACE int sock_printf(rwbuf_t *p, const char *fmt,...)
sock_printf function
Definition: web.c:830
MEMSPACE int WEAK_ATR strcasecmp(const char *str, const char *pat)
Compare two strings without case.
Definition: stringsup.c:410
#define snprintf(s, size, format, args...)
Definition: cpu.h:81
Definition: web.h:76
MEMSPACE char * next_arg(hinfo_t *hi)
Find next POST/GET argument We have to skip a name and a value.
Definition: web.c:1247
espconn_t WebConn
Master espconn structure of the web server.
Definition: web.c:53
MEMSPACE char * process_args(hinfo_t *hi, char *ptr)
Process GET argments or POST message name/value data. HTML encoding is done in place often reducting ...
Definition: web.c:1116
MEMSPACE char * first_arg(hinfo_t *hi)
Find first POST/GET argument.
Definition: web.c:1235
void optimistic_yield(uint32_t interval_us)
Definition: user_task.c:102
Definition: web.h:130
Definition: web.h:72
Definition: web.h:57
MEMSPACE int file_type(char *name)
Determin mimetype using file name extension.
Definition: web.c:996
MEMSPACE int is_header(char *str, char **p)
Does the string look like a header token with a &#39;:&#39; ?
Definition: web.c:1451
int putchar(int c)
put a character to stdout See fdevopen() sets stream->put get for TTY devices
Definition: posix.c:351
Small web server for esp8266.
MEMSPACE char * nextbreak(char *ptr)
Find next space or ? character.
Definition: web.c:1476
header_t msg_headers[]
HTTP headers we understand.
Definition: web.c:61
Definition: web.h:142
MEMSPACE rwbuf_t * create_connection(espconn_t *conn)
Allocate read/write socket buffers and add it to the working pool.
Definition: web.c:669
Definition: web.h:123
Definition: web.h:69
static MEMSPACE void web_data_receive_callback(void *arg, char *data, unsigned short length)
Network receive callback function.
Definition: web.c:1735
static MEMSPACE void web_data_connect_callback(espconn_t *conn)
incomming connection setup callbacks
Definition: web.c:1928
#define NULL
Definition: cpu.h:55
Definition: web.h:133
int rind
Definition: web.h:147
MEMSPACE void led_off(int led)
Turn off virtual LED.
Definition: web.c:384
int remote_port
Definition: web.h:157
char * html_encoding
Definition: web.h:44
MEMSPACE void write_str(rwbuf_t *p, char *str)
Write string using buffered write_byte function.
Definition: web.c:774
MEMSPACE int write_buffer(rwbuf_t *p)
Socket write buffer for this connection We wait for previous send to complete - then send any new dat...
Definition: web.c:266
MEMSPACE void trim_tail(char *str)
Trim White space and control characters from end of string.
Definition: stringsup.c:271
MEMSPACE int MATCHI_LEN(char *str, char *pat)
Compare two strings without case limted to length of pattern.
Definition: stringsup.c:537
window * wintop
Definition: web.h:88
char * pattern
Definition: web.h:89
signed char int8_t
Definition: web.h:121
#define MAX_CONNECTIONS
Definition: web.h:31
MEMSPACE void display_ipv4(char *msg, uint8_t *ip, int port)
Display IPV4 address.
Definition: web.c:470
MEMSPACE void led_on(int led)
Definition: web.c:374
Definition: web.h:125
MEMSPACE int html_msg(rwbuf_t *p, int status, char type, char *fmt,...)
Send an HTML status message to socket.
Definition: web.c:853
struct espconn espconn_t
Definition: web.h:27
MEMSPACE char * nextspace(char *ptr)
Skip to first white space in a string - tabs and spaces.
Definition: stringsup.c:306
MEMSPACE void init_hinfo(hinfo_t *hi)
Definition: web.c:1055
int ind
Definition: ili9341.c:373
espconn_t * conn
Definition: web.h:143
void * buffer
Definition: mathio.h:84
MEMSPACE void web_sep(void)
printer seperator
Definition: web.c:182
MEMSPACE char * html_status(int status)
Convert html status into string using http_status table.
Definition: web.c:1030
MEMSPACE int wait_send(rwbuf_t *p)
Wait for buffer to send for this connection If write_buffer sending flag is set then wait for it to c...
Definition: web.c:195
char * arg_ptr
Definition: web.h:41
int wind
Definition: web.h:152
int delete
Definition: web.h:160
static MEMSPACE void tcp_accept(espconn_t *esp_config, esp_tcp *esp_tcp_config, uint16_t port, void(*connect_callback)(struct espconn *))
Accept an incomming connection, setup connect_callback.
Definition: web.c:400
int connections
Definition: web.c:45
MEMSPACE int match_headers(char *str, char **p)
Match GET/POST message headers.
Definition: web.c:1077
char * filename
Definition: web.h:40
#define MEMSPACE
Definition: cpu.h:25
Definition: web.h:36
MEMSPACE int delete_connection(rwbuf_t *p)
Delete our main connection structure and connection buffers.
Definition: web.c:715
Definition: web.h:71
MEMSPACE void u5toa(char *ptr, uint16_t num)
Print a decimal number into a string without an EOS.
Definition: web.c:1497
MEMSPACE int printf(const char *format,...)
uint8_t remote_ip[4]
Definition: web.h:155
Definition: ili9341.h:34
MEMSPACE int write_flush(rwbuf_t *p)
Write all outstanding data and wait for it to send.
Definition: web.c:323
ili9341 driver inspired by Adafruit ili9341 code All code in this file has been rewritten by Mike Gor...
int sent
Definition: mathio.h:86
MEMSPACE char * arg_value(hinfo_t *hi)
Return the argument value for current argument.
Definition: web.c:1346
MEMSPACE void safefree(void *p)
Safe free - Only free a pointer if it is in malloc memory range. We want to try to catch frees of sta...
Definition: system.c:165
char * connection
Definition: web.h:45
MEMSPACE void rwbuf_delete(rwbuf_t *p)
Delete socket read/write buffers.
Definition: web.c:487
Definition: web.h:126
static MEMSPACE void web_data_error_callback(void *arg, int8_t err)
Network Error callback function.
Definition: web.c:1895
char * content_type
Definition: web.h:49
unsigned char uint8_t
Definition: send.c:17
rwbuf_t * web_connections[MAX_CONNECTIONS]
socket buffers for this connection
Definition: web.c:50
MEMSPACE void rwbuf_winit(rwbuf_t *p)
Initialize socket send status and write index.
Definition: web.c:453
MEMSPACE char * arg_name(hinfo_t *hi)
Return the argument name for current argument.
Definition: web.c:1298
MEMSPACE int parse_http_request(rwbuf_t *p, hinfo_t *hi)
Get arguments for a GET or POST request.
Definition: web.c:1535
MEMSPACE int atoi(const char *str)
Convert ASCII string to number in base 10.
Definition: mathio.c:281
void esp_schedule()
Definition: user_task.c:79
char * msg
Definition: web.h:52
void(* put)(struct _printf_t *, char)
Definition: mathio.h:83
static MEMSPACE _led
Turn on virtual LED.
Definition: web.c:372
MEMSPACE void * safecalloc(size_t nmemb, size_t size)
Safe Calloc - Display Error message if Calloc fails.
Definition: system.c:128
Definition: web.h:124
int size
Definition: web.h:60
char * wbuf
Definition: web.h:150
char * args
Definition: web.h:42
MEMSPACE char * skipspaces(char *ptr)
Skip white space in a string - tabs and spaces.
Definition: stringsup.c:289
mime_t mimes[]
MIME types.
Definition: web.c:160
undefine any potential macro version of these functions
Definition: mathio.h:81
int received
Definition: web.h:146
static esp_tcp WebTcp
Master network configuration for the web server.
Definition: web.c:55