]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/net/lwip_tcpip/v2_0/tests/httpd.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / net / lwip_tcpip / v2_0 / tests / httpd.c
1 /*
2  * Copyright (c) 2001, Swedish Institute of Computer Science.
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 lwIP TCP/IP stack.
30  * 
31  * Author: Adam Dunkels <adam@sics.se>
32  *
33  */
34
35 #include "lwip/debug.h"
36 #include "lwip/stats.h"
37 #include "lwip/tcp.h"
38 #include <cyg/infra/testcase.h>
39
40 #ifdef CYGPKG_LWIP_TCP
41
42 struct http_state {
43   const char *file;
44   u32_t left;
45   u8_t retries;
46 };
47
48 /* Stack smashing arch-independent shellcode: will brick your target :-) */
49 static const char sdata[] __attribute__ ((aligned)) = {
50         0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, 0x2e, 0x30, 0x20, 0x32, 
51         0x30, 0x30, 0x20, 0x4f, 0x4b, 0xd, 0xa, 0x43, 0x6f, 0x6e, 
52         0x74, 0x65, 0x6e, 0x74, 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 
53         0x20, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 
54         0xd, 0xa, 0xd, 0xa, 0x49, 0x74, 0x20, 0x77, 0x6f, 0x72, 
55         0x6b, 0x65, 0x64, 0x2e, 0xa, };
56
57
58
59
60 /*-----------------------------------------------------------------------------------*/
61 static void
62 conn_err(void *arg, err_t err)
63 {
64   struct http_state *hs;
65
66   hs = arg;
67   mem_free(hs);
68 }
69 /*-----------------------------------------------------------------------------------*/
70 static void
71 close_conn(struct tcp_pcb *pcb, struct http_state *hs)
72 {
73   tcp_arg(pcb, NULL);
74   tcp_sent(pcb, NULL);
75   tcp_recv(pcb, NULL);
76   mem_free(hs);
77   tcp_close(pcb);
78 }
79 /*-----------------------------------------------------------------------------------*/
80 static void
81 send_data(struct tcp_pcb *pcb, struct http_state *hs)
82 {
83   err_t err;
84   u16_t len;
85
86   /* We cannot send more data than space available in the send
87      buffer. */     
88   if(tcp_sndbuf(pcb) < hs->left) {
89     len = tcp_sndbuf(pcb);
90   } else {
91     len = hs->left;
92   }
93
94   do {
95     err = tcp_write(pcb, hs->file, len, 0);
96     if(err == ERR_MEM) {
97       len /= 2;
98     }
99   } while(err == ERR_MEM && len > 1);  
100   
101   if(err == ERR_OK) {
102     hs->file += len;
103     hs->left -= len;
104   }
105 }
106 /*-----------------------------------------------------------------------------------*/
107 static err_t
108 http_poll(void *arg, struct tcp_pcb *pcb)
109 {
110   struct http_state *hs;
111
112   hs = arg;
113   
114   /*  printf("Polll\n");*/
115   if(hs == NULL) {
116     /*    printf("Null, close\n");*/
117     tcp_abort(pcb);
118     return ERR_ABRT;
119   } else {
120     ++hs->retries;
121     if(hs->retries == 4) {
122       tcp_abort(pcb);
123       return ERR_ABRT;
124     }
125     send_data(pcb, hs);
126   }
127
128   return ERR_OK;
129 }
130 /*-----------------------------------------------------------------------------------*/
131 static err_t
132 http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
133 {
134   struct http_state *hs;
135
136   hs = arg;
137
138   hs->retries = 0;
139   
140   if(hs->left > 0) {    
141     send_data(pcb, hs);
142   } else {
143     close_conn(pcb, hs);
144   }
145
146   return ERR_OK;
147 }
148 /*-----------------------------------------------------------------------------------*/
149 static err_t
150 http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
151 {
152   int i;
153   char *data;
154   struct http_state *hs;
155
156   hs = arg;
157
158   if(err == ERR_OK && p != NULL) {
159
160     /* Inform TCP that we have taken the data. */
161     tcp_recved(pcb, p->tot_len);
162     
163     if(hs->file == NULL) {
164       data = p->payload;
165       
166       if(*data =='G') {
167         for(i = 0; i < 40; i++) {
168           if(((char *)data + 4)[i] == ' ' ||
169              ((char *)data + 4)[i] == '\r' ||
170              ((char *)data + 4)[i] == '\n') {
171             ((char *)data + 4)[i] = 0;
172           }
173         }
174
175         hs->file = sdata;
176         hs->left = sizeof(sdata);
177
178         pbuf_free(p);
179         send_data(pcb, hs);
180
181         /* Tell TCP that we wish be to informed of data that has been
182            successfully sent by a call to the http_sent() function. */
183         tcp_sent(pcb, http_sent);
184       } else {
185         pbuf_free(p);
186         close_conn(pcb, hs);
187       }
188     } else {
189       pbuf_free(p);
190     }
191   }
192
193   if(err == ERR_OK && p == NULL) {
194     close_conn(pcb, hs);
195   }
196   return ERR_OK;
197 }
198 /*-----------------------------------------------------------------------------------*/
199 static err_t
200 http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
201 {
202   struct http_state *hs;
203
204   tcp_setprio(pcb, TCP_PRIO_MIN);
205   
206   /* Allocate memory for the structure that holds the state of the
207      connection. */
208   hs = mem_malloc(sizeof(struct http_state));
209
210   if(hs == NULL) {
211     return ERR_MEM;
212   }
213   
214   /* Initialize the structure. */
215   hs->file = NULL;
216   hs->left = 0;
217   hs->retries = 0;
218   
219   /* Tell TCP that this is the structure we wish to be passed for our
220      callbacks. */
221   tcp_arg(pcb, hs);
222
223   /* Tell TCP that we wish to be informed of incoming data by a call
224      to the http_recv() function. */
225   tcp_recv(pcb, http_recv);
226
227   tcp_err(pcb, conn_err);
228   
229   tcp_poll(pcb, http_poll, 4);
230   return ERR_OK;
231 }
232
233 /*-----------------------------------------------------------------------------------*/
234 void
235 httpd_init(void *arg)
236 {
237   struct tcp_pcb *pcb;
238
239   pcb = tcp_new();
240   tcp_bind(pcb, IP_ADDR_ANY, 80);
241   pcb = tcp_listen(pcb);
242   tcp_accept(pcb, http_accept);
243   while(1)
244           cyg_thread_delay(1000);
245 }
246
247 void
248 tmain(cyg_addrword_t p)
249 {
250   lwip_init();  
251   sys_thread_new(httpd_init, (void*)"httpd",7);  
252 }
253
254 #define STACK_SIZE 0x1000
255 static char stack[STACK_SIZE];
256 static cyg_thread thread_data;
257 static cyg_handle_t thread_handle;
258
259 void
260 httpd_main(void)
261 {
262     CYG_TEST_INIT();
263     // Create a main thread, so we can run the scheduler and have time 'pass'
264     cyg_thread_create(10,                // Priority - just a number
265                       tmain,          // entry
266                       0,                 // entry parameter
267                       "thread",        // Name
268                       &stack[0],         // Stack
269                       STACK_SIZE,        // Size
270                       &thread_handle,    // Handle
271                       &thread_data       // Thread data structure
272             );
273     cyg_thread_resume(thread_handle);  // Start it
274     cyg_scheduler_start();
275     CYG_TEST_FAIL_FINISH("Not reached");
276 }
277
278 externC void
279 cyg_start( void )
280 {
281     httpd_main();
282 }
283
284 #else // def CYGPKG_LWIP_TCP
285 #define N_A_MSG "TCP support disabled"
286 #endif // def CYGFUN_KERNEL_API_C
287
288 #ifdef N_A_MSG
289 externC void
290 cyg_start( void )
291 {
292     CYG_TEST_INIT();
293     CYG_TEST_NA(N_A_MSG);
294 }
295 #endif // N_A_MSG
296