Free (GPLv2) TCP/IP stack developed by TASS Belgium
Dependents: lpc1768-picotcp-demo ZeroMQ_PicoTCP_Publisher_demo TCPSocket_HelloWorld_PicoTCP Pico_TCP_UDP_Test ... more
PicoTCP. Copyright (c) 2013 TASS Belgium NV.
Released under the GNU General Public License, version 2.
Different licensing models may exist, at the sole discretion of the Copyright holders.
Official homepage: http://www.picotcp.com
Bug tracker: https://github.com/tass-belgium/picotcp/issues
Development steps:
initial integration with mbed RTOSgeneric mbed Ethernet driverhigh performance NXP LPC1768 specific Ethernet driverMulti-threading support for mbed RTOSBerkeley sockets and integration with the New Socket APIFork of the apps running on top of the New Socket APIScheduling optimizations- Debugging/benchmarking/testing
Demo application (measuring TCP sender performance):
Import programlpc1768-picotcp-demo
A PicoTCP demo app testing the ethernet throughput on the lpc1768 mbed board.
modules/pico_http_server.c@131:4758606c9316, 2013-12-16 (annotated)
- Committer:
- TASS Belgium NV
- Date:
- Mon Dec 16 11:25:54 2013 +0100
- Revision:
- 131:4758606c9316
- Parent:
- 73:dfb737147f6e
- Child:
- 134:cc4e6d2654d9
Syncronized with master branch
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
tass | 68:0847e35d08a6 | 1 | /********************************************************************* |
TASS Belgium NV |
131:4758606c9316 | 2 | PicoTCP. Copyright (c) 2012 TASS Belgium NV. Some rights reserved. |
TASS Belgium NV |
131:4758606c9316 | 3 | See LICENSE and COPYING for usage. |
tass | 68:0847e35d08a6 | 4 | |
TASS Belgium NV |
131:4758606c9316 | 5 | Author: Andrei Carp <andrei.carp@tass.be> |
TASS Belgium NV |
131:4758606c9316 | 6 | *********************************************************************/ |
tass | 68:0847e35d08a6 | 7 | |
tass | 68:0847e35d08a6 | 8 | #include "pico_stack.h" |
tass | 68:0847e35d08a6 | 9 | #include "pico_http_server.h" |
tass | 68:0847e35d08a6 | 10 | #include "pico_tcp.h" |
tass | 68:0847e35d08a6 | 11 | #include "pico_tree.h" |
tass | 68:0847e35d08a6 | 12 | #include "pico_socket.h" |
tass | 68:0847e35d08a6 | 13 | |
tass | 68:0847e35d08a6 | 14 | #ifdef PICO_SUPPORT_HTTP_SERVER |
tass | 68:0847e35d08a6 | 15 | |
TASS Belgium NV |
131:4758606c9316 | 16 | #define BACKLOG 10 |
tass | 68:0847e35d08a6 | 17 | |
TASS Belgium NV |
131:4758606c9316 | 18 | #define HTTP_SERVER_CLOSED 0 |
TASS Belgium NV |
131:4758606c9316 | 19 | #define HTTP_SERVER_LISTEN 1 |
tass | 68:0847e35d08a6 | 20 | |
TASS Belgium NV |
131:4758606c9316 | 21 | #define HTTP_HEADER_MAX_LINE 256u |
tass | 68:0847e35d08a6 | 22 | |
TASS Belgium NV |
131:4758606c9316 | 23 | #define consumeChar(c) (pico_socket_read(client->sck, &c, 1u)) |
tass | 68:0847e35d08a6 | 24 | |
tass | 68:0847e35d08a6 | 25 | static const char returnOkHeader[] = |
TASS Belgium NV |
131:4758606c9316 | 26 | "HTTP/1.1 200 OK\r\n\ |
tass | 68:0847e35d08a6 | 27 | Host: localhost\r\n\ |
tass | 68:0847e35d08a6 | 28 | Transfer-Encoding: chunked\r\n\ |
tass | 68:0847e35d08a6 | 29 | Connection: close\r\n\ |
tass | 68:0847e35d08a6 | 30 | \r\n"; |
tass | 68:0847e35d08a6 | 31 | |
tass | 68:0847e35d08a6 | 32 | static const char returnFailHeader[] = |
TASS Belgium NV |
131:4758606c9316 | 33 | "HTTP/1.1 404 Not Found\r\n\ |
tass | 68:0847e35d08a6 | 34 | Host: localhost\r\n\ |
tass | 68:0847e35d08a6 | 35 | Connection: close\r\n\ |
tass | 68:0847e35d08a6 | 36 | \r\n\ |
tass | 68:0847e35d08a6 | 37 | <html><body>The resource you requested cannot be found !</body></html>"; |
tass | 68:0847e35d08a6 | 38 | |
tass | 68:0847e35d08a6 | 39 | static const char errorHeader[] = |
TASS Belgium NV |
131:4758606c9316 | 40 | "HTTP/1.1 400 Bad Request\r\n\ |
tass | 68:0847e35d08a6 | 41 | Host: localhost\r\n\ |
tass | 68:0847e35d08a6 | 42 | Connection: close\r\n\ |
tass | 68:0847e35d08a6 | 43 | \r\n\ |
tass | 68:0847e35d08a6 | 44 | <html><body>There was a problem with your request !</body></html>"; |
tass | 68:0847e35d08a6 | 45 | |
tass | 68:0847e35d08a6 | 46 | struct httpServer |
tass | 68:0847e35d08a6 | 47 | { |
TASS Belgium NV |
131:4758606c9316 | 48 | uint16_t state; |
TASS Belgium NV |
131:4758606c9316 | 49 | struct pico_socket *sck; |
TASS Belgium NV |
131:4758606c9316 | 50 | uint16_t port; |
TASS Belgium NV |
131:4758606c9316 | 51 | void (*wakeup)(uint16_t ev, uint16_t param); |
TASS Belgium NV |
131:4758606c9316 | 52 | uint8_t accepted; |
tass | 68:0847e35d08a6 | 53 | }; |
tass | 68:0847e35d08a6 | 54 | |
tass | 68:0847e35d08a6 | 55 | struct httpClient |
tass | 68:0847e35d08a6 | 56 | { |
TASS Belgium NV |
131:4758606c9316 | 57 | uint16_t connectionID; |
TASS Belgium NV |
131:4758606c9316 | 58 | struct pico_socket *sck; |
TASS Belgium NV |
131:4758606c9316 | 59 | void *buffer; |
TASS Belgium NV |
131:4758606c9316 | 60 | uint16_t bufferSize; |
TASS Belgium NV |
131:4758606c9316 | 61 | uint16_t bufferSent; |
TASS Belgium NV |
131:4758606c9316 | 62 | char *resource; |
TASS Belgium NV |
131:4758606c9316 | 63 | uint16_t state; |
tass | 68:0847e35d08a6 | 64 | }; |
tass | 68:0847e35d08a6 | 65 | |
tass | 68:0847e35d08a6 | 66 | /* Local states for clients */ |
TASS Belgium NV |
131:4758606c9316 | 67 | #define HTTP_WAIT_HDR 0 |
TASS Belgium NV |
131:4758606c9316 | 68 | #define HTTP_WAIT_EOF_HDR 1 |
TASS Belgium NV |
131:4758606c9316 | 69 | #define HTTP_EOF_HDR 2 |
tass | 68:0847e35d08a6 | 70 | #define HTTP_WAIT_RESPONSE 3 |
TASS Belgium NV |
131:4758606c9316 | 71 | #define HTTP_WAIT_DATA 4 |
TASS Belgium NV |
131:4758606c9316 | 72 | #define HTTP_SENDING_DATA 5 |
TASS Belgium NV |
131:4758606c9316 | 73 | #define HTTP_ERROR 6 |
TASS Belgium NV |
131:4758606c9316 | 74 | #define HTTP_CLOSED 7 |
tass | 68:0847e35d08a6 | 75 | |
TASS Belgium NV |
131:4758606c9316 | 76 | static struct httpServer server = { |
TASS Belgium NV |
131:4758606c9316 | 77 | 0 |
TASS Belgium NV |
131:4758606c9316 | 78 | }; |
tass | 68:0847e35d08a6 | 79 | |
tass | 68:0847e35d08a6 | 80 | /* |
tass | 68:0847e35d08a6 | 81 | * Private functions |
tass | 68:0847e35d08a6 | 82 | */ |
TASS Belgium NV |
131:4758606c9316 | 83 | static int parseRequest(struct httpClient *client); |
TASS Belgium NV |
131:4758606c9316 | 84 | static int readRemainingHeader(struct httpClient *client); |
TASS Belgium NV |
131:4758606c9316 | 85 | static void sendData(struct httpClient *client); |
TASS Belgium NV |
131:4758606c9316 | 86 | static inline int readData(struct httpClient *client); /* used only in a place */ |
TASS Belgium NV |
131:4758606c9316 | 87 | static inline struct httpClient *findClient(uint16_t conn); |
tass | 68:0847e35d08a6 | 88 | |
TASS Belgium NV |
131:4758606c9316 | 89 | static int compareClients(void *ka, void *kb) |
tass | 68:0847e35d08a6 | 90 | { |
TASS Belgium NV |
131:4758606c9316 | 91 | return ((struct httpClient *)ka)->connectionID - ((struct httpClient *)kb)->connectionID; |
tass | 68:0847e35d08a6 | 92 | } |
tass | 68:0847e35d08a6 | 93 | |
TASS Belgium NV |
131:4758606c9316 | 94 | PICO_TREE_DECLARE(pico_http_clients, compareClients); |
tass | 68:0847e35d08a6 | 95 | |
tass | 68:0847e35d08a6 | 96 | void httpServerCbk(uint16_t ev, struct pico_socket *s) |
tass | 68:0847e35d08a6 | 97 | { |
TASS Belgium NV |
131:4758606c9316 | 98 | struct pico_tree_node *index; |
TASS Belgium NV |
131:4758606c9316 | 99 | struct httpClient *client = NULL; |
TASS Belgium NV |
131:4758606c9316 | 100 | uint8_t serverEvent = FALSE; |
tass | 68:0847e35d08a6 | 101 | |
TASS Belgium NV |
131:4758606c9316 | 102 | /* determine the client for the socket */ |
TASS Belgium NV |
131:4758606c9316 | 103 | if( s == server.sck) |
TASS Belgium NV |
131:4758606c9316 | 104 | { |
TASS Belgium NV |
131:4758606c9316 | 105 | serverEvent = TRUE; |
TASS Belgium NV |
131:4758606c9316 | 106 | } |
TASS Belgium NV |
131:4758606c9316 | 107 | else |
TASS Belgium NV |
131:4758606c9316 | 108 | { |
TASS Belgium NV |
131:4758606c9316 | 109 | pico_tree_foreach(index, &pico_http_clients) |
TASS Belgium NV |
131:4758606c9316 | 110 | { |
TASS Belgium NV |
131:4758606c9316 | 111 | client = index->keyValue; |
TASS Belgium NV |
131:4758606c9316 | 112 | if(client->sck == s) break; |
tass | 68:0847e35d08a6 | 113 | |
TASS Belgium NV |
131:4758606c9316 | 114 | client = NULL; |
TASS Belgium NV |
131:4758606c9316 | 115 | } |
TASS Belgium NV |
131:4758606c9316 | 116 | } |
tass | 68:0847e35d08a6 | 117 | |
TASS Belgium NV |
131:4758606c9316 | 118 | if(!client && !serverEvent) |
TASS Belgium NV |
131:4758606c9316 | 119 | { |
TASS Belgium NV |
131:4758606c9316 | 120 | return; |
TASS Belgium NV |
131:4758606c9316 | 121 | } |
TASS Belgium NV |
131:4758606c9316 | 122 | |
TASS Belgium NV |
131:4758606c9316 | 123 | if (ev & PICO_SOCK_EV_RD) |
TASS Belgium NV |
131:4758606c9316 | 124 | { |
tass | 68:0847e35d08a6 | 125 | |
TASS Belgium NV |
131:4758606c9316 | 126 | if(readData(client) == HTTP_RETURN_ERROR) |
TASS Belgium NV |
131:4758606c9316 | 127 | { |
TASS Belgium NV |
131:4758606c9316 | 128 | /* send out error */ |
TASS Belgium NV |
131:4758606c9316 | 129 | client->state = HTTP_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 130 | pico_socket_write(client->sck, (const char *)errorHeader, sizeof(errorHeader) - 1); |
TASS Belgium NV |
131:4758606c9316 | 131 | server.wakeup(EV_HTTP_ERROR, client->connectionID); |
TASS Belgium NV |
131:4758606c9316 | 132 | } |
TASS Belgium NV |
131:4758606c9316 | 133 | } |
tass | 68:0847e35d08a6 | 134 | |
TASS Belgium NV |
131:4758606c9316 | 135 | if(ev & PICO_SOCK_EV_WR) |
TASS Belgium NV |
131:4758606c9316 | 136 | { |
TASS Belgium NV |
131:4758606c9316 | 137 | if(client->state == HTTP_SENDING_DATA) |
TASS Belgium NV |
131:4758606c9316 | 138 | { |
TASS Belgium NV |
131:4758606c9316 | 139 | sendData(client); |
TASS Belgium NV |
131:4758606c9316 | 140 | } |
TASS Belgium NV |
131:4758606c9316 | 141 | } |
tass | 68:0847e35d08a6 | 142 | |
TASS Belgium NV |
131:4758606c9316 | 143 | if(ev & PICO_SOCK_EV_CONN) |
TASS Belgium NV |
131:4758606c9316 | 144 | { |
TASS Belgium NV |
131:4758606c9316 | 145 | server.accepted = FALSE; |
TASS Belgium NV |
131:4758606c9316 | 146 | server.wakeup(EV_HTTP_CON, HTTP_SERVER_ID); |
TASS Belgium NV |
131:4758606c9316 | 147 | if(!server.accepted) |
TASS Belgium NV |
131:4758606c9316 | 148 | { |
TASS Belgium NV |
131:4758606c9316 | 149 | pico_socket_close(s); /* reject socket */ |
TASS Belgium NV |
131:4758606c9316 | 150 | } |
TASS Belgium NV |
131:4758606c9316 | 151 | } |
tass | 68:0847e35d08a6 | 152 | |
TASS Belgium NV |
131:4758606c9316 | 153 | if((ev & PICO_SOCK_EV_CLOSE) || (ev & PICO_SOCK_EV_FIN)) |
TASS Belgium NV |
131:4758606c9316 | 154 | { |
TASS Belgium NV |
131:4758606c9316 | 155 | server.wakeup(EV_HTTP_CLOSE, (uint16_t)(serverEvent ? HTTP_SERVER_ID : client->connectionID)); |
TASS Belgium NV |
131:4758606c9316 | 156 | } |
tass | 68:0847e35d08a6 | 157 | |
TASS Belgium NV |
131:4758606c9316 | 158 | if(ev & PICO_SOCK_EV_ERR) |
TASS Belgium NV |
131:4758606c9316 | 159 | { |
TASS Belgium NV |
131:4758606c9316 | 160 | server.wakeup(EV_HTTP_ERROR, (uint16_t)(serverEvent ? HTTP_SERVER_ID : client->connectionID)); |
TASS Belgium NV |
131:4758606c9316 | 161 | } |
tass | 68:0847e35d08a6 | 162 | } |
tass | 68:0847e35d08a6 | 163 | |
tass | 68:0847e35d08a6 | 164 | /* |
tass | 68:0847e35d08a6 | 165 | * API for starting the server. If 0 is passed as a port, the port 80 |
tass | 68:0847e35d08a6 | 166 | * will be used. |
tass | 68:0847e35d08a6 | 167 | */ |
tass | 70:cd218dd180e5 | 168 | int8_t pico_http_server_start(uint16_t port, void (*wakeup)(uint16_t ev, uint16_t conn)) |
tass | 68:0847e35d08a6 | 169 | { |
TASS Belgium NV |
131:4758606c9316 | 170 | struct pico_ip4 anything = { |
TASS Belgium NV |
131:4758606c9316 | 171 | 0 |
TASS Belgium NV |
131:4758606c9316 | 172 | }; |
tass | 68:0847e35d08a6 | 173 | |
TASS Belgium NV |
131:4758606c9316 | 174 | server.port = (uint16_t)(port ? short_be(port) : short_be(80u)); |
tass | 68:0847e35d08a6 | 175 | |
TASS Belgium NV |
131:4758606c9316 | 176 | if(!wakeup) |
TASS Belgium NV |
131:4758606c9316 | 177 | { |
TASS Belgium NV |
131:4758606c9316 | 178 | pico_err = PICO_ERR_EINVAL; |
TASS Belgium NV |
131:4758606c9316 | 179 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 180 | } |
tass | 68:0847e35d08a6 | 181 | |
TASS Belgium NV |
131:4758606c9316 | 182 | server.sck = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &httpServerCbk); |
tass | 68:0847e35d08a6 | 183 | |
TASS Belgium NV |
131:4758606c9316 | 184 | if(!server.sck) |
TASS Belgium NV |
131:4758606c9316 | 185 | { |
TASS Belgium NV |
131:4758606c9316 | 186 | pico_err = PICO_ERR_EFAULT; |
TASS Belgium NV |
131:4758606c9316 | 187 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 188 | } |
tass | 68:0847e35d08a6 | 189 | |
TASS Belgium NV |
131:4758606c9316 | 190 | if(pico_socket_bind(server.sck, &anything, &server.port) != 0) |
TASS Belgium NV |
131:4758606c9316 | 191 | { |
TASS Belgium NV |
131:4758606c9316 | 192 | pico_err = PICO_ERR_EADDRNOTAVAIL; |
TASS Belgium NV |
131:4758606c9316 | 193 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 194 | } |
tass | 68:0847e35d08a6 | 195 | |
TASS Belgium NV |
131:4758606c9316 | 196 | if (pico_socket_listen(server.sck, BACKLOG) != 0) |
TASS Belgium NV |
131:4758606c9316 | 197 | { |
TASS Belgium NV |
131:4758606c9316 | 198 | pico_err = PICO_ERR_EADDRINUSE; |
TASS Belgium NV |
131:4758606c9316 | 199 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 200 | } |
TASS Belgium NV |
131:4758606c9316 | 201 | |
TASS Belgium NV |
131:4758606c9316 | 202 | server.wakeup = wakeup; |
TASS Belgium NV |
131:4758606c9316 | 203 | server.state = HTTP_SERVER_LISTEN; |
TASS Belgium NV |
131:4758606c9316 | 204 | return HTTP_RETURN_OK; |
tass | 68:0847e35d08a6 | 205 | } |
tass | 68:0847e35d08a6 | 206 | |
tass | 68:0847e35d08a6 | 207 | /* |
tass | 68:0847e35d08a6 | 208 | * API for accepting new connections. This function should be |
tass | 68:0847e35d08a6 | 209 | * called when the event EV_HTTP_CON is triggered, if not called |
tass | 68:0847e35d08a6 | 210 | * when noticed the connection will be considered rejected and the |
tass | 68:0847e35d08a6 | 211 | * socket will be dropped. |
tass | 68:0847e35d08a6 | 212 | * |
tass | 68:0847e35d08a6 | 213 | * Returns the ID of the new connection or a negative value if error. |
tass | 68:0847e35d08a6 | 214 | */ |
tass | 68:0847e35d08a6 | 215 | int pico_http_server_accept(void) |
tass | 68:0847e35d08a6 | 216 | { |
TASS Belgium NV |
131:4758606c9316 | 217 | struct pico_ip4 orig; |
TASS Belgium NV |
131:4758606c9316 | 218 | struct httpClient *client; |
TASS Belgium NV |
131:4758606c9316 | 219 | uint16_t port; |
tass | 68:0847e35d08a6 | 220 | |
TASS Belgium NV |
131:4758606c9316 | 221 | client = pico_zalloc(sizeof(struct httpClient)); |
TASS Belgium NV |
131:4758606c9316 | 222 | if(!client) |
TASS Belgium NV |
131:4758606c9316 | 223 | { |
TASS Belgium NV |
131:4758606c9316 | 224 | pico_err = PICO_ERR_ENOMEM; |
TASS Belgium NV |
131:4758606c9316 | 225 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 226 | } |
tass | 68:0847e35d08a6 | 227 | |
TASS Belgium NV |
131:4758606c9316 | 228 | client->sck = pico_socket_accept(server.sck, &orig, &port); |
tass | 68:0847e35d08a6 | 229 | |
TASS Belgium NV |
131:4758606c9316 | 230 | if(!client->sck) |
TASS Belgium NV |
131:4758606c9316 | 231 | { |
TASS Belgium NV |
131:4758606c9316 | 232 | pico_err = PICO_ERR_ENOMEM; |
TASS Belgium NV |
131:4758606c9316 | 233 | pico_free(client); |
TASS Belgium NV |
131:4758606c9316 | 234 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 235 | } |
tass | 68:0847e35d08a6 | 236 | |
TASS Belgium NV |
131:4758606c9316 | 237 | server.accepted = TRUE; |
TASS Belgium NV |
131:4758606c9316 | 238 | /* buffer used for async sending */ |
TASS Belgium NV |
131:4758606c9316 | 239 | client->state = HTTP_WAIT_HDR; |
TASS Belgium NV |
131:4758606c9316 | 240 | client->buffer = NULL; |
TASS Belgium NV |
131:4758606c9316 | 241 | client->bufferSize = 0; |
TASS Belgium NV |
131:4758606c9316 | 242 | client->connectionID = pico_rand() & 0x7FFF; |
tass | 68:0847e35d08a6 | 243 | |
TASS Belgium NV |
131:4758606c9316 | 244 | /* add element to the tree, if duplicate because the rand */ |
TASS Belgium NV |
131:4758606c9316 | 245 | /* regenerate */ |
TASS Belgium NV |
131:4758606c9316 | 246 | while(pico_tree_insert(&pico_http_clients, client) != NULL) |
TASS Belgium NV |
131:4758606c9316 | 247 | client->connectionID = pico_rand() & 0x7FFF; |
TASS Belgium NV |
131:4758606c9316 | 248 | return client->connectionID; |
tass | 68:0847e35d08a6 | 249 | } |
tass | 68:0847e35d08a6 | 250 | |
tass | 68:0847e35d08a6 | 251 | /* |
tass | 68:0847e35d08a6 | 252 | * Function used for getting the resource asked by the |
tass | 68:0847e35d08a6 | 253 | * client. It is useful after the request header (EV_HTTP_REQ) |
tass | 68:0847e35d08a6 | 254 | * from client was received, otherwise NULL is returned. |
tass | 68:0847e35d08a6 | 255 | */ |
TASS Belgium NV |
131:4758606c9316 | 256 | char *pico_http_getResource(uint16_t conn) |
tass | 68:0847e35d08a6 | 257 | { |
TASS Belgium NV |
131:4758606c9316 | 258 | struct httpClient *client = findClient(conn); |
tass | 68:0847e35d08a6 | 259 | |
TASS Belgium NV |
131:4758606c9316 | 260 | if(!client) |
TASS Belgium NV |
131:4758606c9316 | 261 | return NULL; |
TASS Belgium NV |
131:4758606c9316 | 262 | else |
TASS Belgium NV |
131:4758606c9316 | 263 | return client->resource; |
tass | 68:0847e35d08a6 | 264 | } |
tass | 68:0847e35d08a6 | 265 | |
tass | 68:0847e35d08a6 | 266 | /* |
tass | 68:0847e35d08a6 | 267 | * After the resource was asked by the client (EV_HTTP_REQ) |
tass | 68:0847e35d08a6 | 268 | * before doing anything else, the server has to let know |
tass | 68:0847e35d08a6 | 269 | * the client if the resource can be provided or not. |
tass | 68:0847e35d08a6 | 270 | * |
tass | 68:0847e35d08a6 | 271 | * This is controlled via the code parameter which can |
tass | 68:0847e35d08a6 | 272 | * have two values : |
tass | 68:0847e35d08a6 | 273 | * |
tass | 68:0847e35d08a6 | 274 | * HTTP_RESOURCE_FOUND or HTTP_RESOURCE_NOT_FOUND |
tass | 68:0847e35d08a6 | 275 | * |
tass | 68:0847e35d08a6 | 276 | * If a resource is reported not found the 404 header will be sent and the connection |
tass | 68:0847e35d08a6 | 277 | * will be closed , otherwise the 200 header is sent and the user should |
tass | 68:0847e35d08a6 | 278 | * immediately submit data. |
tass | 68:0847e35d08a6 | 279 | * |
tass | 68:0847e35d08a6 | 280 | */ |
tass | 68:0847e35d08a6 | 281 | int pico_http_respond(uint16_t conn, uint16_t code) |
tass | 68:0847e35d08a6 | 282 | { |
TASS Belgium NV |
131:4758606c9316 | 283 | struct httpClient *client = findClient(conn); |
tass | 68:0847e35d08a6 | 284 | |
TASS Belgium NV |
131:4758606c9316 | 285 | if(!client) |
TASS Belgium NV |
131:4758606c9316 | 286 | { |
TASS Belgium NV |
131:4758606c9316 | 287 | dbg("Client not found !\n"); |
TASS Belgium NV |
131:4758606c9316 | 288 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 289 | } |
tass | 68:0847e35d08a6 | 290 | |
TASS Belgium NV |
131:4758606c9316 | 291 | if(client->state == HTTP_WAIT_RESPONSE) |
TASS Belgium NV |
131:4758606c9316 | 292 | { |
TASS Belgium NV |
131:4758606c9316 | 293 | if(code == HTTP_RESOURCE_FOUND) |
TASS Belgium NV |
131:4758606c9316 | 294 | { |
TASS Belgium NV |
131:4758606c9316 | 295 | client->state = HTTP_WAIT_DATA; |
TASS Belgium NV |
131:4758606c9316 | 296 | return pico_socket_write(client->sck, (const char *)returnOkHeader, sizeof(returnOkHeader) - 1); /* remove \0 */ |
TASS Belgium NV |
131:4758606c9316 | 297 | } |
TASS Belgium NV |
131:4758606c9316 | 298 | else |
TASS Belgium NV |
131:4758606c9316 | 299 | { |
TASS Belgium NV |
131:4758606c9316 | 300 | int length; |
tass | 68:0847e35d08a6 | 301 | |
TASS Belgium NV |
131:4758606c9316 | 302 | length = pico_socket_write(client->sck, (const char *)returnFailHeader, sizeof(returnFailHeader) - 1); /* remove \0 */ |
TASS Belgium NV |
131:4758606c9316 | 303 | pico_socket_close(client->sck); |
TASS Belgium NV |
131:4758606c9316 | 304 | client->state = HTTP_CLOSED; |
TASS Belgium NV |
131:4758606c9316 | 305 | return length; |
tass | 68:0847e35d08a6 | 306 | |
TASS Belgium NV |
131:4758606c9316 | 307 | } |
TASS Belgium NV |
131:4758606c9316 | 308 | } |
TASS Belgium NV |
131:4758606c9316 | 309 | else |
TASS Belgium NV |
131:4758606c9316 | 310 | { |
TASS Belgium NV |
131:4758606c9316 | 311 | dbg("Bad state for the client \n"); |
TASS Belgium NV |
131:4758606c9316 | 312 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 313 | } |
tass | 68:0847e35d08a6 | 314 | |
tass | 68:0847e35d08a6 | 315 | } |
tass | 68:0847e35d08a6 | 316 | |
tass | 68:0847e35d08a6 | 317 | /* |
tass | 68:0847e35d08a6 | 318 | * API used to submit data to the client. |
tass | 68:0847e35d08a6 | 319 | * Server sends data only using Transfer-Encoding: chunked. |
tass | 68:0847e35d08a6 | 320 | * |
tass | 68:0847e35d08a6 | 321 | * With this function the user will submit a data chunk to |
tass | 68:0847e35d08a6 | 322 | * be sent. |
tass | 68:0847e35d08a6 | 323 | * The function will send the chunk size in hex and the rest will |
tass | 68:0847e35d08a6 | 324 | * be sent using WR event from sockets. |
tass | 68:0847e35d08a6 | 325 | * After each transmision EV_HTTP_PROGRESS is called and at the |
tass | 68:0847e35d08a6 | 326 | * end of the chunk EV_HTTP_SENT is called. |
tass | 68:0847e35d08a6 | 327 | * |
tass | 68:0847e35d08a6 | 328 | * To let the client know this is the last chunk, the user |
tass | 68:0847e35d08a6 | 329 | * should pass a NULL buffer. |
tass | 68:0847e35d08a6 | 330 | */ |
TASS Belgium NV |
131:4758606c9316 | 331 | int8_t pico_http_submitData(uint16_t conn, void *buffer, uint16_t len) |
tass | 68:0847e35d08a6 | 332 | { |
tass | 68:0847e35d08a6 | 333 | |
TASS Belgium NV |
131:4758606c9316 | 334 | struct httpClient *client = findClient(conn); |
TASS Belgium NV |
131:4758606c9316 | 335 | char chunkStr[10]; |
TASS Belgium NV |
131:4758606c9316 | 336 | int chunkCount; |
tass | 68:0847e35d08a6 | 337 | |
TASS Belgium NV |
131:4758606c9316 | 338 | if(client->state != HTTP_WAIT_DATA) |
TASS Belgium NV |
131:4758606c9316 | 339 | { |
TASS Belgium NV |
131:4758606c9316 | 340 | dbg("Client is in a different state than accepted\n"); |
TASS Belgium NV |
131:4758606c9316 | 341 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 342 | } |
tass | 68:0847e35d08a6 | 343 | |
TASS Belgium NV |
131:4758606c9316 | 344 | if(client->buffer) |
TASS Belgium NV |
131:4758606c9316 | 345 | { |
TASS Belgium NV |
131:4758606c9316 | 346 | dbg("Already a buffer submited\n"); |
TASS Belgium NV |
131:4758606c9316 | 347 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 348 | } |
tass | 68:0847e35d08a6 | 349 | |
TASS Belgium NV |
131:4758606c9316 | 350 | if(!client) |
TASS Belgium NV |
131:4758606c9316 | 351 | { |
TASS Belgium NV |
131:4758606c9316 | 352 | dbg("Wrong connection ID\n"); |
TASS Belgium NV |
131:4758606c9316 | 353 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 354 | } |
tass | 68:0847e35d08a6 | 355 | |
TASS Belgium NV |
131:4758606c9316 | 356 | if(!buffer) |
TASS Belgium NV |
131:4758606c9316 | 357 | { |
TASS Belgium NV |
131:4758606c9316 | 358 | len = 0; |
TASS Belgium NV |
131:4758606c9316 | 359 | } |
tass | 68:0847e35d08a6 | 360 | |
TASS Belgium NV |
131:4758606c9316 | 361 | if(len > 0) |
TASS Belgium NV |
131:4758606c9316 | 362 | { |
TASS Belgium NV |
131:4758606c9316 | 363 | client->buffer = pico_zalloc(len); |
TASS Belgium NV |
131:4758606c9316 | 364 | if(!client->buffer) |
TASS Belgium NV |
131:4758606c9316 | 365 | { |
TASS Belgium NV |
131:4758606c9316 | 366 | pico_err = PICO_ERR_ENOMEM; |
TASS Belgium NV |
131:4758606c9316 | 367 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 368 | } |
TASS Belgium NV |
131:4758606c9316 | 369 | |
TASS Belgium NV |
131:4758606c9316 | 370 | /* taking over the buffer */ |
TASS Belgium NV |
131:4758606c9316 | 371 | memcpy(client->buffer, buffer, len); |
TASS Belgium NV |
131:4758606c9316 | 372 | } |
TASS Belgium NV |
131:4758606c9316 | 373 | else |
TASS Belgium NV |
131:4758606c9316 | 374 | client->buffer = NULL; |
tass | 68:0847e35d08a6 | 375 | |
tass | 68:0847e35d08a6 | 376 | |
TASS Belgium NV |
131:4758606c9316 | 377 | client->bufferSize = len; |
TASS Belgium NV |
131:4758606c9316 | 378 | client->bufferSent = 0; |
tass | 68:0847e35d08a6 | 379 | |
TASS Belgium NV |
131:4758606c9316 | 380 | /* create the chunk size and send it */ |
TASS Belgium NV |
131:4758606c9316 | 381 | if(len > 0) |
TASS Belgium NV |
131:4758606c9316 | 382 | { |
TASS Belgium NV |
131:4758606c9316 | 383 | client->state = HTTP_SENDING_DATA; |
TASS Belgium NV |
131:4758606c9316 | 384 | chunkCount = pico_itoaHex(client->bufferSize, chunkStr); |
TASS Belgium NV |
131:4758606c9316 | 385 | chunkStr[chunkCount++] = '\r'; |
TASS Belgium NV |
131:4758606c9316 | 386 | chunkStr[chunkCount++] = '\n'; |
TASS Belgium NV |
131:4758606c9316 | 387 | pico_socket_write(client->sck, chunkStr, chunkCount); |
TASS Belgium NV |
131:4758606c9316 | 388 | } |
TASS Belgium NV |
131:4758606c9316 | 389 | else if(len == 0) |
TASS Belgium NV |
131:4758606c9316 | 390 | { |
TASS Belgium NV |
131:4758606c9316 | 391 | dbg("->\n"); |
TASS Belgium NV |
131:4758606c9316 | 392 | /* end of transmision */ |
TASS Belgium NV |
131:4758606c9316 | 393 | pico_socket_write(client->sck, "0\r\n\r\n", 5u); |
TASS Belgium NV |
131:4758606c9316 | 394 | /* nothing left, close the client */ |
TASS Belgium NV |
131:4758606c9316 | 395 | pico_socket_close(client->sck); |
TASS Belgium NV |
131:4758606c9316 | 396 | client->state = HTTP_CLOSED; |
TASS Belgium NV |
131:4758606c9316 | 397 | } |
tass | 68:0847e35d08a6 | 398 | |
TASS Belgium NV |
131:4758606c9316 | 399 | return HTTP_RETURN_OK; |
tass | 68:0847e35d08a6 | 400 | } |
tass | 68:0847e35d08a6 | 401 | |
tass | 68:0847e35d08a6 | 402 | /* |
tass | 68:0847e35d08a6 | 403 | * When EV_HTTP_PROGRESS is triggered you can use this |
tass | 68:0847e35d08a6 | 404 | * function to check the state of the chunk. |
tass | 68:0847e35d08a6 | 405 | */ |
tass | 68:0847e35d08a6 | 406 | |
TASS Belgium NV |
131:4758606c9316 | 407 | int pico_http_getProgress(uint16_t conn, uint16_t *sent, uint16_t *total) |
tass | 68:0847e35d08a6 | 408 | { |
TASS Belgium NV |
131:4758606c9316 | 409 | struct httpClient *client = findClient(conn); |
tass | 68:0847e35d08a6 | 410 | |
TASS Belgium NV |
131:4758606c9316 | 411 | if(!client) |
TASS Belgium NV |
131:4758606c9316 | 412 | { |
TASS Belgium NV |
131:4758606c9316 | 413 | dbg("Wrong connection id !\n"); |
TASS Belgium NV |
131:4758606c9316 | 414 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 415 | } |
tass | 68:0847e35d08a6 | 416 | |
TASS Belgium NV |
131:4758606c9316 | 417 | *sent = client->bufferSent; |
TASS Belgium NV |
131:4758606c9316 | 418 | *total = client->bufferSize; |
tass | 68:0847e35d08a6 | 419 | |
TASS Belgium NV |
131:4758606c9316 | 420 | return HTTP_RETURN_OK; |
tass | 68:0847e35d08a6 | 421 | } |
tass | 68:0847e35d08a6 | 422 | |
tass | 68:0847e35d08a6 | 423 | /* |
tass | 68:0847e35d08a6 | 424 | * This API can be used to close either a client |
tass | 68:0847e35d08a6 | 425 | * or the server ( if you pass HTTP_SERVER_ID as a connection ID). |
tass | 68:0847e35d08a6 | 426 | */ |
tass | 68:0847e35d08a6 | 427 | int pico_http_close(uint16_t conn) |
tass | 68:0847e35d08a6 | 428 | { |
TASS Belgium NV |
131:4758606c9316 | 429 | /* close the server */ |
TASS Belgium NV |
131:4758606c9316 | 430 | if(conn == HTTP_SERVER_ID) |
TASS Belgium NV |
131:4758606c9316 | 431 | { |
TASS Belgium NV |
131:4758606c9316 | 432 | if(server.state == HTTP_SERVER_LISTEN) |
TASS Belgium NV |
131:4758606c9316 | 433 | { |
TASS Belgium NV |
131:4758606c9316 | 434 | struct pico_tree_node *index, *tmp; |
TASS Belgium NV |
131:4758606c9316 | 435 | /* close the server */ |
TASS Belgium NV |
131:4758606c9316 | 436 | pico_socket_close(server.sck); |
TASS Belgium NV |
131:4758606c9316 | 437 | server.sck = NULL; |
tass | 68:0847e35d08a6 | 438 | |
TASS Belgium NV |
131:4758606c9316 | 439 | /* destroy the tree */ |
TASS Belgium NV |
131:4758606c9316 | 440 | pico_tree_foreach_safe(index, &pico_http_clients, tmp) |
TASS Belgium NV |
131:4758606c9316 | 441 | { |
TASS Belgium NV |
131:4758606c9316 | 442 | struct httpClient *client = index->keyValue; |
tass | 68:0847e35d08a6 | 443 | |
TASS Belgium NV |
131:4758606c9316 | 444 | if(client->resource) |
TASS Belgium NV |
131:4758606c9316 | 445 | pico_free(client->resource); |
tass | 68:0847e35d08a6 | 446 | |
TASS Belgium NV |
131:4758606c9316 | 447 | pico_socket_close(client->sck); |
TASS Belgium NV |
131:4758606c9316 | 448 | pico_tree_delete(&pico_http_clients, client); |
TASS Belgium NV |
131:4758606c9316 | 449 | } |
tass | 68:0847e35d08a6 | 450 | |
TASS Belgium NV |
131:4758606c9316 | 451 | server.state = HTTP_SERVER_CLOSED; |
TASS Belgium NV |
131:4758606c9316 | 452 | return HTTP_RETURN_OK; |
TASS Belgium NV |
131:4758606c9316 | 453 | } |
TASS Belgium NV |
131:4758606c9316 | 454 | else /* nothing to close */ |
TASS Belgium NV |
131:4758606c9316 | 455 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 456 | } /* close a connection in this case */ |
TASS Belgium NV |
131:4758606c9316 | 457 | else |
TASS Belgium NV |
131:4758606c9316 | 458 | { |
tass | 68:0847e35d08a6 | 459 | |
TASS Belgium NV |
131:4758606c9316 | 460 | struct httpClient *client = findClient(conn); |
tass | 68:0847e35d08a6 | 461 | |
TASS Belgium NV |
131:4758606c9316 | 462 | if(!client) |
TASS Belgium NV |
131:4758606c9316 | 463 | { |
TASS Belgium NV |
131:4758606c9316 | 464 | dbg("Client not found..\n"); |
TASS Belgium NV |
131:4758606c9316 | 465 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 466 | } |
tass | 68:0847e35d08a6 | 467 | |
TASS Belgium NV |
131:4758606c9316 | 468 | pico_tree_delete(&pico_http_clients, client); |
tass | 68:0847e35d08a6 | 469 | |
TASS Belgium NV |
131:4758606c9316 | 470 | if(client->resource) |
TASS Belgium NV |
131:4758606c9316 | 471 | pico_free(client->resource); |
tass | 68:0847e35d08a6 | 472 | |
TASS Belgium NV |
131:4758606c9316 | 473 | if(client->buffer) |
TASS Belgium NV |
131:4758606c9316 | 474 | pico_free(client->buffer); |
tass | 68:0847e35d08a6 | 475 | |
TASS Belgium NV |
131:4758606c9316 | 476 | if(client->state != HTTP_CLOSED || !client->sck) |
TASS Belgium NV |
131:4758606c9316 | 477 | pico_socket_close(client->sck); |
tass | 68:0847e35d08a6 | 478 | |
TASS Belgium NV |
131:4758606c9316 | 479 | pico_free(client); |
TASS Belgium NV |
131:4758606c9316 | 480 | return HTTP_RETURN_OK; |
TASS Belgium NV |
131:4758606c9316 | 481 | } |
tass | 68:0847e35d08a6 | 482 | } |
tass | 68:0847e35d08a6 | 483 | |
TASS Belgium NV |
131:4758606c9316 | 484 | /* check the integrity of the request */ |
TASS Belgium NV |
131:4758606c9316 | 485 | int parseRequest(struct httpClient *client) |
tass | 68:0847e35d08a6 | 486 | { |
TASS Belgium NV |
131:4758606c9316 | 487 | char c; |
TASS Belgium NV |
131:4758606c9316 | 488 | /* read first line */ |
TASS Belgium NV |
131:4758606c9316 | 489 | consumeChar(c); |
TASS Belgium NV |
131:4758606c9316 | 490 | if(c == 'G') |
TASS Belgium NV |
131:4758606c9316 | 491 | { /* possible GET */ |
tass | 68:0847e35d08a6 | 492 | |
TASS Belgium NV |
131:4758606c9316 | 493 | char line[HTTP_HEADER_MAX_LINE]; |
TASS Belgium NV |
131:4758606c9316 | 494 | uint32_t index = 0; |
TASS Belgium NV |
131:4758606c9316 | 495 | |
TASS Belgium NV |
131:4758606c9316 | 496 | line[index] = c; |
tass | 68:0847e35d08a6 | 497 | |
TASS Belgium NV |
131:4758606c9316 | 498 | /* consume the full line */ |
TASS Belgium NV |
131:4758606c9316 | 499 | while(consumeChar(c) > 0) /* read char by char only the first line */ |
TASS Belgium NV |
131:4758606c9316 | 500 | { |
TASS Belgium NV |
131:4758606c9316 | 501 | line[++index] = c; |
TASS Belgium NV |
131:4758606c9316 | 502 | if(c == '\n') |
TASS Belgium NV |
131:4758606c9316 | 503 | break; |
tass | 68:0847e35d08a6 | 504 | |
TASS Belgium NV |
131:4758606c9316 | 505 | if(index >= HTTP_HEADER_MAX_LINE) |
TASS Belgium NV |
131:4758606c9316 | 506 | { |
TASS Belgium NV |
131:4758606c9316 | 507 | dbg("Size exceeded \n"); |
TASS Belgium NV |
131:4758606c9316 | 508 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 509 | } |
TASS Belgium NV |
131:4758606c9316 | 510 | } |
TASS Belgium NV |
131:4758606c9316 | 511 | /* extract the function and the resource */ |
TASS Belgium NV |
131:4758606c9316 | 512 | if(memcmp(line, "GET", 3u) || line[3u] != ' ' || index < 10u || line[index] != '\n') |
TASS Belgium NV |
131:4758606c9316 | 513 | { |
TASS Belgium NV |
131:4758606c9316 | 514 | dbg("Wrong command or wrong ending\n"); |
TASS Belgium NV |
131:4758606c9316 | 515 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 516 | } |
tass | 68:0847e35d08a6 | 517 | |
TASS Belgium NV |
131:4758606c9316 | 518 | /* start reading the resource */ |
TASS Belgium NV |
131:4758606c9316 | 519 | index = 4u; /* go after ' ' */ |
TASS Belgium NV |
131:4758606c9316 | 520 | while(line[index] != ' ') |
TASS Belgium NV |
131:4758606c9316 | 521 | { |
TASS Belgium NV |
131:4758606c9316 | 522 | if(line[index] == '\n') /* no terminator ' ' */ |
TASS Belgium NV |
131:4758606c9316 | 523 | { |
TASS Belgium NV |
131:4758606c9316 | 524 | dbg("No terminator...\n"); |
TASS Belgium NV |
131:4758606c9316 | 525 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 526 | } |
tass | 68:0847e35d08a6 | 527 | |
TASS Belgium NV |
131:4758606c9316 | 528 | index++; |
TASS Belgium NV |
131:4758606c9316 | 529 | } |
TASS Belgium NV |
131:4758606c9316 | 530 | client->resource = pico_zalloc(index - 3u); /* allocate without the GET in front + 1 which is \0 */ |
tass | 68:0847e35d08a6 | 531 | |
TASS Belgium NV |
131:4758606c9316 | 532 | if(!client) |
TASS Belgium NV |
131:4758606c9316 | 533 | { |
TASS Belgium NV |
131:4758606c9316 | 534 | pico_err = PICO_ERR_ENOMEM; |
TASS Belgium NV |
131:4758606c9316 | 535 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 536 | } |
tass | 68:0847e35d08a6 | 537 | |
TASS Belgium NV |
131:4758606c9316 | 538 | /* copy the resource */ |
TASS Belgium NV |
131:4758606c9316 | 539 | memcpy(client->resource, line + 4u, index - 4u); /* copy without the \0 which was already set by pico_zalloc */ |
tass | 68:0847e35d08a6 | 540 | |
TASS Belgium NV |
131:4758606c9316 | 541 | client->state = HTTP_WAIT_EOF_HDR; |
TASS Belgium NV |
131:4758606c9316 | 542 | return HTTP_RETURN_OK; |
tass | 68:0847e35d08a6 | 543 | |
TASS Belgium NV |
131:4758606c9316 | 544 | } |
tass | 68:0847e35d08a6 | 545 | |
TASS Belgium NV |
131:4758606c9316 | 546 | return HTTP_RETURN_ERROR; |
tass | 68:0847e35d08a6 | 547 | } |
tass | 68:0847e35d08a6 | 548 | |
tass | 68:0847e35d08a6 | 549 | |
tass | 68:0847e35d08a6 | 550 | |
TASS Belgium NV |
131:4758606c9316 | 551 | int readRemainingHeader(struct httpClient *client) |
tass | 68:0847e35d08a6 | 552 | { |
TASS Belgium NV |
131:4758606c9316 | 553 | char line[100]; |
TASS Belgium NV |
131:4758606c9316 | 554 | int count = 0; |
TASS Belgium NV |
131:4758606c9316 | 555 | int len; |
tass | 68:0847e35d08a6 | 556 | |
TASS Belgium NV |
131:4758606c9316 | 557 | while((len = pico_socket_read(client->sck, line, 100u)) > 0) |
TASS Belgium NV |
131:4758606c9316 | 558 | { |
TASS Belgium NV |
131:4758606c9316 | 559 | char c; |
TASS Belgium NV |
131:4758606c9316 | 560 | int index = 0; |
TASS Belgium NV |
131:4758606c9316 | 561 | /* parse the response */ |
TASS Belgium NV |
131:4758606c9316 | 562 | while(index < len) |
TASS Belgium NV |
131:4758606c9316 | 563 | { |
TASS Belgium NV |
131:4758606c9316 | 564 | c = line[index++]; |
TASS Belgium NV |
131:4758606c9316 | 565 | if(c != '\r' && c != '\n') |
TASS Belgium NV |
131:4758606c9316 | 566 | count++; |
tass | 68:0847e35d08a6 | 567 | |
TASS Belgium NV |
131:4758606c9316 | 568 | if(c == '\n') |
TASS Belgium NV |
131:4758606c9316 | 569 | { |
TASS Belgium NV |
131:4758606c9316 | 570 | if(!count) |
TASS Belgium NV |
131:4758606c9316 | 571 | { |
TASS Belgium NV |
131:4758606c9316 | 572 | client->state = HTTP_EOF_HDR; |
TASS Belgium NV |
131:4758606c9316 | 573 | dbg("End of header !\n"); |
TASS Belgium NV |
131:4758606c9316 | 574 | break; |
TASS Belgium NV |
131:4758606c9316 | 575 | } |
tass | 68:0847e35d08a6 | 576 | |
TASS Belgium NV |
131:4758606c9316 | 577 | count = 0; |
TASS Belgium NV |
131:4758606c9316 | 578 | |
TASS Belgium NV |
131:4758606c9316 | 579 | } |
TASS Belgium NV |
131:4758606c9316 | 580 | } |
TASS Belgium NV |
131:4758606c9316 | 581 | } |
TASS Belgium NV |
131:4758606c9316 | 582 | return HTTP_RETURN_OK; |
tass | 68:0847e35d08a6 | 583 | } |
tass | 68:0847e35d08a6 | 584 | |
TASS Belgium NV |
131:4758606c9316 | 585 | void sendData(struct httpClient *client) |
tass | 68:0847e35d08a6 | 586 | { |
TASS Belgium NV |
131:4758606c9316 | 587 | uint16_t length; |
TASS Belgium NV |
131:4758606c9316 | 588 | while( client->bufferSent < client->bufferSize && |
TASS Belgium NV |
131:4758606c9316 | 589 | (length = (uint16_t)pico_socket_write(client->sck, client->buffer + client->bufferSent, client->bufferSize - client->bufferSent)) > 0 ) |
TASS Belgium NV |
131:4758606c9316 | 590 | { |
TASS Belgium NV |
131:4758606c9316 | 591 | client->bufferSent = (uint16_t)(client->bufferSent + length); |
TASS Belgium NV |
131:4758606c9316 | 592 | server.wakeup(EV_HTTP_PROGRESS, client->connectionID); |
TASS Belgium NV |
131:4758606c9316 | 593 | } |
TASS Belgium NV |
131:4758606c9316 | 594 | if(client->bufferSent == client->bufferSize && client->bufferSize) |
TASS Belgium NV |
131:4758606c9316 | 595 | { |
TASS Belgium NV |
131:4758606c9316 | 596 | /* send chunk trail */ |
TASS Belgium NV |
131:4758606c9316 | 597 | if(pico_socket_write(client->sck, "\r\n", 2) > 0) |
TASS Belgium NV |
131:4758606c9316 | 598 | { |
TASS Belgium NV |
131:4758606c9316 | 599 | client->state = HTTP_WAIT_DATA; |
TASS Belgium NV |
131:4758606c9316 | 600 | /* free the buffer */ |
TASS Belgium NV |
131:4758606c9316 | 601 | pico_free(client->buffer); |
TASS Belgium NV |
131:4758606c9316 | 602 | client->buffer = NULL; |
TASS Belgium NV |
131:4758606c9316 | 603 | server.wakeup(EV_HTTP_SENT, client->connectionID); |
TASS Belgium NV |
131:4758606c9316 | 604 | } |
TASS Belgium NV |
131:4758606c9316 | 605 | } |
tass | 68:0847e35d08a6 | 606 | |
tass | 68:0847e35d08a6 | 607 | } |
tass | 68:0847e35d08a6 | 608 | |
TASS Belgium NV |
131:4758606c9316 | 609 | int readData(struct httpClient *client) |
tass | 68:0847e35d08a6 | 610 | { |
TASS Belgium NV |
131:4758606c9316 | 611 | if(client->state == HTTP_WAIT_HDR) |
TASS Belgium NV |
131:4758606c9316 | 612 | { |
TASS Belgium NV |
131:4758606c9316 | 613 | if(parseRequest(client) < 0 || readRemainingHeader(client) < 0) |
TASS Belgium NV |
131:4758606c9316 | 614 | { |
TASS Belgium NV |
131:4758606c9316 | 615 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 616 | } |
TASS Belgium NV |
131:4758606c9316 | 617 | } /* continue with this in case the header comes line by line not a big chunk */ |
TASS Belgium NV |
131:4758606c9316 | 618 | else if(client->state == HTTP_WAIT_EOF_HDR) |
TASS Belgium NV |
131:4758606c9316 | 619 | { |
TASS Belgium NV |
131:4758606c9316 | 620 | if(readRemainingHeader(client) < 0 ) |
TASS Belgium NV |
131:4758606c9316 | 621 | return HTTP_RETURN_ERROR; |
TASS Belgium NV |
131:4758606c9316 | 622 | } |
tass | 68:0847e35d08a6 | 623 | |
TASS Belgium NV |
131:4758606c9316 | 624 | if(client->state == HTTP_EOF_HDR) |
TASS Belgium NV |
131:4758606c9316 | 625 | { |
TASS Belgium NV |
131:4758606c9316 | 626 | client->state = HTTP_WAIT_RESPONSE; |
TASS Belgium NV |
131:4758606c9316 | 627 | pico_socket_shutdown(client->sck, PICO_SHUT_RD); |
TASS Belgium NV |
131:4758606c9316 | 628 | server.wakeup(EV_HTTP_REQ, client->connectionID); |
TASS Belgium NV |
131:4758606c9316 | 629 | } |
tass | 68:0847e35d08a6 | 630 | |
TASS Belgium NV |
131:4758606c9316 | 631 | return HTTP_RETURN_OK; |
tass | 68:0847e35d08a6 | 632 | } |
tass | 68:0847e35d08a6 | 633 | |
TASS Belgium NV |
131:4758606c9316 | 634 | struct httpClient *findClient(uint16_t conn) |
tass | 68:0847e35d08a6 | 635 | { |
TASS Belgium NV |
131:4758606c9316 | 636 | struct httpClient dummy = { |
TASS Belgium NV |
131:4758606c9316 | 637 | .connectionID = conn |
TASS Belgium NV |
131:4758606c9316 | 638 | }; |
tass | 68:0847e35d08a6 | 639 | |
TASS Belgium NV |
131:4758606c9316 | 640 | return pico_tree_findKey(&pico_http_clients, &dummy); |
tass | 68:0847e35d08a6 | 641 | } |
tass | 68:0847e35d08a6 | 642 | #endif |