Free (GPLv2) TCP/IP stack developed by TASS Belgium
Fork of PicoTCP by
modules/pico_simple_http.c@3:b4047e8a0123, 2013-05-24 (annotated)
- Committer:
- daniele
- Date:
- Fri May 24 15:25:25 2013 +0000
- Revision:
- 3:b4047e8a0123
Updated from main repo + fixed Mutexes;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
daniele | 3:b4047e8a0123 | 1 | /********************************************************************* |
daniele | 3:b4047e8a0123 | 2 | PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved. |
daniele | 3:b4047e8a0123 | 3 | See LICENSE and COPYING for usage. |
daniele | 3:b4047e8a0123 | 4 | |
daniele | 3:b4047e8a0123 | 5 | Author: Andrei Carp <andrei.carp@tass.be> |
daniele | 3:b4047e8a0123 | 6 | *********************************************************************/ |
daniele | 3:b4047e8a0123 | 7 | |
daniele | 3:b4047e8a0123 | 8 | #include "pico_config.h" |
daniele | 3:b4047e8a0123 | 9 | #include "pico_socket.h" |
daniele | 3:b4047e8a0123 | 10 | #include "pico_tcp.h" |
daniele | 3:b4047e8a0123 | 11 | #include "pico_ipv4.h" |
daniele | 3:b4047e8a0123 | 12 | #include "pico_simple_http.h" |
daniele | 3:b4047e8a0123 | 13 | |
daniele | 3:b4047e8a0123 | 14 | /* The HTTP Server cannot be available without TCP support */ |
daniele | 3:b4047e8a0123 | 15 | #if (defined PICO_SUPPORT_HTTP) && (defined PICO_SUPPORT_IPV4) && (defined PICO_SUPPORT_TCP) |
daniele | 3:b4047e8a0123 | 16 | |
daniele | 3:b4047e8a0123 | 17 | #define HTTP_LISTEN_PORT 80u |
daniele | 3:b4047e8a0123 | 18 | #define HTTP_BACKLOG 5u |
daniele | 3:b4047e8a0123 | 19 | #define HTTP_HEADER_SIZE 256u |
daniele | 3:b4047e8a0123 | 20 | |
daniele | 3:b4047e8a0123 | 21 | #define HTTP_SUCCESS 0 |
daniele | 3:b4047e8a0123 | 22 | #define HTTP_ERROR -1 |
daniele | 3:b4047e8a0123 | 23 | |
daniele | 3:b4047e8a0123 | 24 | static struct pico_socket * httpServer = NULL; |
daniele | 3:b4047e8a0123 | 25 | static char httpResponse[] = |
daniele | 3:b4047e8a0123 | 26 | "HTTP/1.0 200 OK\r\n\ |
daniele | 3:b4047e8a0123 | 27 | Content-Type: text/html\r\n\ |
daniele | 3:b4047e8a0123 | 28 | \r\n\ |
daniele | 3:b4047e8a0123 | 29 | <html><head>\r\n\ |
daniele | 3:b4047e8a0123 | 30 | <title>picoTCP Simple Http server</title>\r\n\ |
daniele | 3:b4047e8a0123 | 31 | </head>\r\n\ |
daniele | 3:b4047e8a0123 | 32 | <body>\r\n\ |
daniele | 3:b4047e8a0123 | 33 | <h1>Hello world from picoTCP !!</h1>\r\n\ |
daniele | 3:b4047e8a0123 | 34 | </body>\r\n"; |
daniele | 3:b4047e8a0123 | 35 | |
daniele | 3:b4047e8a0123 | 36 | static void httpEventCbk(uint16_t ev, struct pico_socket *self) |
daniele | 3:b4047e8a0123 | 37 | { |
daniele | 3:b4047e8a0123 | 38 | static struct pico_socket * client = NULL; |
daniele | 3:b4047e8a0123 | 39 | uint32_t peer; |
daniele | 3:b4047e8a0123 | 40 | uint16_t port; |
daniele | 3:b4047e8a0123 | 41 | int r; |
daniele | 3:b4047e8a0123 | 42 | char buffer[HTTP_HEADER_SIZE]; |
daniele | 3:b4047e8a0123 | 43 | |
daniele | 3:b4047e8a0123 | 44 | switch(ev) |
daniele | 3:b4047e8a0123 | 45 | { |
daniele | 3:b4047e8a0123 | 46 | case PICO_SOCK_EV_CONN : |
daniele | 3:b4047e8a0123 | 47 | if(!client) |
daniele | 3:b4047e8a0123 | 48 | client = pico_socket_accept(self, &peer, &port); |
daniele | 3:b4047e8a0123 | 49 | break; |
daniele | 3:b4047e8a0123 | 50 | |
daniele | 3:b4047e8a0123 | 51 | case PICO_SOCK_EV_RD: |
daniele | 3:b4047e8a0123 | 52 | // do not check http integrity, just mark that the http header has arrived |
daniele | 3:b4047e8a0123 | 53 | // prepare to send the response |
daniele | 3:b4047e8a0123 | 54 | r = pico_socket_recvfrom(self, buffer, HTTP_HEADER_SIZE, &peer, &port); |
daniele | 3:b4047e8a0123 | 55 | if(r>0 && memcmp(buffer,"GET",3u) == 0u) |
daniele | 3:b4047e8a0123 | 56 | { // it is an http header asking for data, return data and close |
daniele | 3:b4047e8a0123 | 57 | pico_socket_write(self,httpResponse,sizeof(httpResponse)); |
daniele | 3:b4047e8a0123 | 58 | pico_socket_close(self); |
daniele | 3:b4047e8a0123 | 59 | } |
daniele | 3:b4047e8a0123 | 60 | else |
daniele | 3:b4047e8a0123 | 61 | { |
daniele | 3:b4047e8a0123 | 62 | // kill the connection, invalid header |
daniele | 3:b4047e8a0123 | 63 | pico_socket_close(self); |
daniele | 3:b4047e8a0123 | 64 | } |
daniele | 3:b4047e8a0123 | 65 | break; |
daniele | 3:b4047e8a0123 | 66 | |
daniele | 3:b4047e8a0123 | 67 | case PICO_SOCK_EV_ERR: |
daniele | 3:b4047e8a0123 | 68 | case PICO_SOCK_EV_CLOSE: |
daniele | 3:b4047e8a0123 | 69 | // free the used socket |
daniele | 3:b4047e8a0123 | 70 | client = NULL; |
daniele | 3:b4047e8a0123 | 71 | break; |
daniele | 3:b4047e8a0123 | 72 | |
daniele | 3:b4047e8a0123 | 73 | default : |
daniele | 3:b4047e8a0123 | 74 | break; |
daniele | 3:b4047e8a0123 | 75 | } |
daniele | 3:b4047e8a0123 | 76 | } |
daniele | 3:b4047e8a0123 | 77 | |
daniele | 3:b4047e8a0123 | 78 | int pico_startHttpServer(struct pico_ip4 * address) |
daniele | 3:b4047e8a0123 | 79 | { |
daniele | 3:b4047e8a0123 | 80 | |
daniele | 3:b4047e8a0123 | 81 | uint16_t localHttpPort = short_be(HTTP_LISTEN_PORT); |
daniele | 3:b4047e8a0123 | 82 | |
daniele | 3:b4047e8a0123 | 83 | if(!pico_is_port_free(localHttpPort,PICO_PROTO_TCP, address, &pico_proto_ipv4)) |
daniele | 3:b4047e8a0123 | 84 | { |
daniele | 3:b4047e8a0123 | 85 | pico_err = PICO_ERR_EADDRINUSE; |
daniele | 3:b4047e8a0123 | 86 | return HTTP_ERROR; |
daniele | 3:b4047e8a0123 | 87 | } |
daniele | 3:b4047e8a0123 | 88 | |
daniele | 3:b4047e8a0123 | 89 | httpServer = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, httpEventCbk); |
daniele | 3:b4047e8a0123 | 90 | |
daniele | 3:b4047e8a0123 | 91 | if(!httpServer) |
daniele | 3:b4047e8a0123 | 92 | { |
daniele | 3:b4047e8a0123 | 93 | pico_err = PICO_ERR_ENOMEM; |
daniele | 3:b4047e8a0123 | 94 | return HTTP_ERROR; |
daniele | 3:b4047e8a0123 | 95 | } |
daniele | 3:b4047e8a0123 | 96 | |
daniele | 3:b4047e8a0123 | 97 | // both functions set the pico_err themselves. |
daniele | 3:b4047e8a0123 | 98 | if(pico_socket_bind(httpServer,address,&localHttpPort)) |
daniele | 3:b4047e8a0123 | 99 | return HTTP_ERROR; |
daniele | 3:b4047e8a0123 | 100 | |
daniele | 3:b4047e8a0123 | 101 | if(pico_socket_listen(httpServer,HTTP_BACKLOG)) |
daniele | 3:b4047e8a0123 | 102 | return HTTP_ERROR; |
daniele | 3:b4047e8a0123 | 103 | |
daniele | 3:b4047e8a0123 | 104 | return HTTP_SUCCESS; |
daniele | 3:b4047e8a0123 | 105 | } |
daniele | 3:b4047e8a0123 | 106 | |
daniele | 3:b4047e8a0123 | 107 | int pico_stopHttpServer(void) |
daniele | 3:b4047e8a0123 | 108 | { |
daniele | 3:b4047e8a0123 | 109 | if(!httpServer) |
daniele | 3:b4047e8a0123 | 110 | { |
daniele | 3:b4047e8a0123 | 111 | pico_err = PICO_ERR_EINVAL; |
daniele | 3:b4047e8a0123 | 112 | return HTTP_ERROR; |
daniele | 3:b4047e8a0123 | 113 | } |
daniele | 3:b4047e8a0123 | 114 | |
daniele | 3:b4047e8a0123 | 115 | if(pico_socket_close(httpServer)) |
daniele | 3:b4047e8a0123 | 116 | { |
daniele | 3:b4047e8a0123 | 117 | // no need to set the error here, function already set it |
daniele | 3:b4047e8a0123 | 118 | httpServer = NULL; |
daniele | 3:b4047e8a0123 | 119 | return HTTP_ERROR; |
daniele | 3:b4047e8a0123 | 120 | } |
daniele | 3:b4047e8a0123 | 121 | |
daniele | 3:b4047e8a0123 | 122 | httpServer = NULL; |
daniele | 3:b4047e8a0123 | 123 | return HTTP_SUCCESS; |
daniele | 3:b4047e8a0123 | 124 | } |
daniele | 3:b4047e8a0123 | 125 | |
daniele | 3:b4047e8a0123 | 126 | #endif |
daniele | 3:b4047e8a0123 | 127 | |
daniele | 3:b4047e8a0123 | 128 |