]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/ARM9_STR91X_IAR/lwip/lwipWebServer/httpd.c
Update version number in readiness for V10.3.0 release. Sync SVN with reviewed releas...
[freertos] / FreeRTOS / Demo / ARM9_STR91X_IAR / lwip / lwipWebServer / httpd.c
1 /*\r
2  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.\r
3  * All rights reserved.\r
4  *\r
5  * Redistribution and use in source and binary forms, with or without modification,\r
6  * are permitted provided that the following conditions are met:\r
7  *\r
8  * 1. Redistributions of source code must retain the above copyright notice,\r
9  *    this list of conditions and the following disclaimer.\r
10  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
11  *    this list of conditions and the following disclaimer in the documentation\r
12  *    and/or other materials provided with the distribution.\r
13  * 3. The name of the author may not be used to endorse or promote products\r
14  *    derived from this software without specific prior written permission.\r
15  *\r
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\r
19  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\r
21  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\r
24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY\r
25  * OF SUCH DAMAGE.\r
26  *\r
27  * This file is part of the lwIP TCP/IP stack.\r
28  *\r
29  * Author: Adam Dunkels <adam@sics.se>\r
30  *\r
31  */\r
32 \r
33 #include "lwip/debug.h"\r
34 #include "lwip/stats.h"\r
35 #include "httpd.h"\r
36 #include "lwip/tcp.h"\r
37 #include "fs.h"\r
38 \r
39 #include <string.h>\r
40 \r
41 #pragma pack(2)\r
42 struct http_state {\r
43   char *file;\r
44   u32_t left;\r
45   u8_t retries;\r
46 };\r
47 #pragma pack()\r
48 \r
49 /*-----------------------------------------------------------------------------------*/\r
50 void conn_err(void *arg, err_t err)\r
51 {\r
52   struct http_state *hs;\r
53 \r
54   hs = arg;\r
55   mem_free(hs);\r
56 }\r
57 /*-----------------------------------------------------------------------------------*/\r
58 static void\r
59 close_conn(struct tcp_pcb *pcb, struct http_state *hs)\r
60 {\r
61   tcp_arg(pcb, NULL);\r
62   tcp_sent(pcb, NULL);\r
63   tcp_recv(pcb, NULL);\r
64   mem_free(hs);\r
65   tcp_close(pcb);\r
66 }\r
67 /*-----------------------------------------------------------------------------------*/\r
68 static void\r
69 send_data(struct tcp_pcb *pcb, struct http_state *hs)\r
70 {\r
71   err_t err;\r
72   u16_t len;\r
73 \r
74   /* We cannot send more data than space available in the send\r
75      buffer. */\r
76   if (tcp_sndbuf(pcb) < hs->left) {\r
77     len = tcp_sndbuf(pcb);\r
78   } else {\r
79     len = hs->left;\r
80   }\r
81 \r
82   do {\r
83     err = tcp_write(pcb, hs->file, len, 0);\r
84     if (err == ERR_MEM) {\r
85       len /= 2;\r
86     }\r
87   } while (err == ERR_MEM && len > 1);\r
88 \r
89   if (err == ERR_OK) {\r
90     hs->file += len;\r
91     hs->left -= len;\r
92     /*  } else {\r
93         printf("send_data: error %s len %d %d\n", lwip_strerr(err), len, tcp_sndbuf(pcb));*/\r
94   }\r
95 }\r
96 /*-----------------------------------------------------------------------------------*/\r
97 err_t http_poll(void *arg, struct tcp_pcb *pcb)\r
98 {\r
99   struct http_state *hs;\r
100 \r
101   hs = arg;\r
102 \r
103   /*  printf("Polll\n");*/\r
104   if (hs == NULL) {\r
105     /*    printf("Null, close\n");*/\r
106     tcp_abort(pcb);\r
107     return ERR_ABRT;\r
108   } else {\r
109     ++hs->retries;\r
110     if (hs->retries == 4) {\r
111       tcp_abort(pcb);\r
112       return ERR_ABRT;\r
113     }\r
114     send_data(pcb, hs);\r
115   }\r
116 \r
117   return ERR_OK;\r
118 }\r
119 /*-----------------------------------------------------------------------------------*/\r
120 err_t http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)\r
121 {\r
122   struct http_state *hs;\r
123 \r
124   hs = arg;\r
125 \r
126   hs->retries = 0;\r
127 \r
128   if (hs->left > 0) {\r
129     send_data(pcb, hs);\r
130   } else {\r
131     close_conn(pcb, hs);\r
132   }\r
133 \r
134   return ERR_OK;\r
135 }\r
136 /*-----------------------------------------------------------------------------------*/\r
137 err_t http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)\r
138 {\r
139   int i;\r
140   char *data;\r
141   struct fs_file file;\r
142   struct http_state *hs;\r
143 \r
144   hs = arg;\r
145 \r
146   if (err == ERR_OK && p != NULL) {\r
147 \r
148     /* Inform TCP that we have taken the data. */\r
149     tcp_recved(pcb, p->tot_len);\r
150 \r
151     if (hs->file == NULL) {\r
152       data = p->payload;\r
153 \r
154       if (strncmp(data, "GET ", 4) == 0) {\r
155         for(i = 0; i < 40; i++) {\r
156           if (((char *)data + 4)[i] == ' ' ||\r
157              ((char *)data + 4)[i] == '\r' ||\r
158              ((char *)data + 4)[i] == '\n') {\r
159             ((char *)data + 4)[i] = 0;\r
160           }\r
161         }\r
162 \r
163         if (*(char *)(data + 4) == '/' &&\r
164            *(char *)(data + 5) == 0) {\r
165           fs_open("/index.html", &file);\r
166         }\r
167         else {\r
168           if (!fs_open((char *)data + 4, &file)) {\r
169             fs_open("/404.html", &file);        \r
170           }\r
171         }\r
172         hs->file = file.data;\r
173         hs->left = file.len;\r
174         /*      printf("data %p len %ld\n", hs->file, hs->left);*/\r
175 \r
176         pbuf_free(p);\r
177         send_data(pcb, hs);\r
178 \r
179         /* Tell TCP that we wish be to informed of data that has been\r
180            successfully sent by a call to the http_sent() function. */\r
181         tcp_sent(pcb, http_sent);\r
182       } else {\r
183         pbuf_free(p);\r
184         close_conn(pcb, hs);\r
185       }\r
186     } else {\r
187       pbuf_free(p);\r
188    }\r
189   }\r
190 \r
191   if (err == ERR_OK && p == NULL) {\r
192     close_conn(pcb, hs);\r
193   }\r
194   return ERR_OK;\r
195 }\r
196 /*-----------------------------------------------------------------------------------*/\r
197 err_t http_accept(void *arg, struct tcp_pcb *pcb, err_t err)\r
198 {\r
199   struct http_state *hs;\r
200 \r
201   tcp_setprio(pcb, TCP_PRIO_MIN);\r
202 \r
203   /* Allocate memory for the structure that holds the state of the\r
204      connection. */\r
205   hs = mem_malloc(sizeof(struct http_state));\r
206 \r
207   if (hs == NULL) {\r
208 //    printf("http_accept: Out of memory\n");\r
209     return ERR_MEM;\r
210   }\r
211 \r
212   /* Initialize the structure. */\r
213   hs->file = NULL;\r
214   hs->left = 0;\r
215   hs->retries = 0;\r
216 \r
217   /* Tell TCP that this is the structure we wish to be passed for our\r
218      callbacks. */\r
219   tcp_arg(pcb, hs);\r
220 \r
221 \r
222   /* Tell TCP that we wish to be informed of incoming data by a call\r
223      to the http_recv() function. */\r
224   tcp_recv(pcb, http_recv);\r
225 \r
226   tcp_err(pcb, conn_err);\r
227 \r
228   tcp_poll(pcb, http_poll, 4);\r
229 \r
230   return ERR_OK;\r
231 }\r
232 \r
233 /*-----------------------------------------------------------------------------------*/\r
234 void httpd_init(void)\r
235 {\r
236   struct tcp_pcb *pcb;\r
237 \r
238   pcb = tcp_new();\r
239   tcp_bind(pcb, NULL, 80);\r
240   pcb = tcp_listen(pcb);\r
241   tcp_accept(pcb, http_accept);\r
242 }\r
243 /*-----------------------------------------------------------------------------------*/\r
244 \r