lwip-1.4.1 (partial)

Dependents:   IGLOO_board

Committer:
ua1arn
Date:
Tue Jul 24 17:36:01 2018 +0000
Revision:
1:119c4f7144c8
lwip 1.4.1 with necessary servers

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ua1arn 1:119c4f7144c8 1 /*
ua1arn 1:119c4f7144c8 2 * The MIT License (MIT)
ua1arn 1:119c4f7144c8 3 *
ua1arn 1:119c4f7144c8 4 * Copyright (c) 2015 by Sergey Fetisov <fsenok@gmail.com>
ua1arn 1:119c4f7144c8 5 *
ua1arn 1:119c4f7144c8 6 * Permission is hereby granted, free of charge, to any person obtaining a copy
ua1arn 1:119c4f7144c8 7 * of this software and associated documentation files (the "Software"), to deal
ua1arn 1:119c4f7144c8 8 * in the Software without restriction, including without limitation the rights
ua1arn 1:119c4f7144c8 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
ua1arn 1:119c4f7144c8 10 * copies of the Software, and to permit persons to whom the Software is
ua1arn 1:119c4f7144c8 11 * furnished to do so, subject to the following conditions:
ua1arn 1:119c4f7144c8 12 *
ua1arn 1:119c4f7144c8 13 * The above copyright notice and this permission notice shall be included in all
ua1arn 1:119c4f7144c8 14 * copies or substantial portions of the Software.
ua1arn 1:119c4f7144c8 15 *
ua1arn 1:119c4f7144c8 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
ua1arn 1:119c4f7144c8 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
ua1arn 1:119c4f7144c8 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
ua1arn 1:119c4f7144c8 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
ua1arn 1:119c4f7144c8 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
ua1arn 1:119c4f7144c8 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
ua1arn 1:119c4f7144c8 22 * SOFTWARE.
ua1arn 1:119c4f7144c8 23 */
ua1arn 1:119c4f7144c8 24
ua1arn 1:119c4f7144c8 25 /*
ua1arn 1:119c4f7144c8 26 * version: 1.0 demo (7.02.2015)
ua1arn 1:119c4f7144c8 27 * brief: part of tiny http ipv4 server using lwip (pcb)
ua1arn 1:119c4f7144c8 28 */
ua1arn 1:119c4f7144c8 29
ua1arn 1:119c4f7144c8 30 #include "http_req.h"
ua1arn 1:119c4f7144c8 31
ua1arn 1:119c4f7144c8 32 #ifdef __cplusplus
ua1arn 1:119c4f7144c8 33 extern "C" {
ua1arn 1:119c4f7144c8 34 #endif
ua1arn 1:119c4f7144c8 35
ua1arn 1:119c4f7144c8 36 const char MIME_TEXT_HTML[] = "text/html";
ua1arn 1:119c4f7144c8 37 const char MIME_TEXT_JS[] = "text/javascript";
ua1arn 1:119c4f7144c8 38 const char MIME_TEXT_PLAIN[] = "text/plain";
ua1arn 1:119c4f7144c8 39 const char MIME_TEXT_XML[] = "text/xml";
ua1arn 1:119c4f7144c8 40 const char MIME_TEXT_CSS[] = "text/css";
ua1arn 1:119c4f7144c8 41 const char MIME_IMAGE_GIF[] = "image/gif";
ua1arn 1:119c4f7144c8 42 const char MIME_IMAGE_JPEG[] = "image/jpeg";
ua1arn 1:119c4f7144c8 43 const char MIME_IMAGE_PJPEG[] = "image/pjpeg";
ua1arn 1:119c4f7144c8 44 const char MIME_IMAGE_PNG[] = "image/png";
ua1arn 1:119c4f7144c8 45 const char MIME_IMAGE_SVG[] = "image/svg+xml";
ua1arn 1:119c4f7144c8 46 const char MIME_IMAGE_TIFF[] = "image/tiff";
ua1arn 1:119c4f7144c8 47 const char MIME_IMAGE_ICON[] = "image/vnd.microsoft.icon";
ua1arn 1:119c4f7144c8 48 const char MIME_IMAGE_WBMP[] = "image/vnd.wap.wbmp";
ua1arn 1:119c4f7144c8 49
ua1arn 1:119c4f7144c8 50 static const char *METHODS_STR[] =
ua1arn 1:119c4f7144c8 51 {
ua1arn 1:119c4f7144c8 52 "",
ua1arn 1:119c4f7144c8 53 "GET",
ua1arn 1:119c4f7144c8 54 "POST",
ua1arn 1:119c4f7144c8 55 "HEAD",
ua1arn 1:119c4f7144c8 56 "PUT",
ua1arn 1:119c4f7144c8 57 "CONNECT",
ua1arn 1:119c4f7144c8 58 "OPTIONS",
ua1arn 1:119c4f7144c8 59 "DELETE",
ua1arn 1:119c4f7144c8 60 "TRACE",
ua1arn 1:119c4f7144c8 61 "PATCH"
ua1arn 1:119c4f7144c8 62 };
ua1arn 1:119c4f7144c8 63
ua1arn 1:119c4f7144c8 64 static const char *CONN_TYPE_STR[] =
ua1arn 1:119c4f7144c8 65 {
ua1arn 1:119c4f7144c8 66 "", "close", "keep-alive"
ua1arn 1:119c4f7144c8 67 };
ua1arn 1:119c4f7144c8 68
ua1arn 1:119c4f7144c8 69 void http_reqb_init(http_reqb_t *reqb, void *buff, int size)
ua1arn 1:119c4f7144c8 70 {
ua1arn 1:119c4f7144c8 71 memset(reqb, 0, sizeof(http_reqb_t));
ua1arn 1:119c4f7144c8 72 reqb->buff = buff;
ua1arn 1:119c4f7144c8 73 reqb->bsize = size;
ua1arn 1:119c4f7144c8 74 }
ua1arn 1:119c4f7144c8 75
ua1arn 1:119c4f7144c8 76 int http_reqb_avail(const http_reqb_t *reqb)
ua1arn 1:119c4f7144c8 77 {
ua1arn 1:119c4f7144c8 78 return reqb->bsize - reqb->size;
ua1arn 1:119c4f7144c8 79 }
ua1arn 1:119c4f7144c8 80
ua1arn 1:119c4f7144c8 81 static chatset_t req_ident =
ua1arn 1:119c4f7144c8 82 {
ua1arn 1:119c4f7144c8 83 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
ua1arn 1:119c4f7144c8 84 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
ua1arn 1:119c4f7144c8 85 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, // '%', '-', '.', '/'
ua1arn 1:119c4f7144c8 86 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // '0'...'9'
ua1arn 1:119c4f7144c8 87 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 'A'...'O'
ua1arn 1:119c4f7144c8 88 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, // 'P'...'Z', '_'
ua1arn 1:119c4f7144c8 89 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 'a'...'z'
ua1arn 1:119c4f7144c8 90 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 'p'...'z'
ua1arn 1:119c4f7144c8 91 };
ua1arn 1:119c4f7144c8 92
ua1arn 1:119c4f7144c8 93 static http_mt_t str_to_method(const char *str)
ua1arn 1:119c4f7144c8 94 {
ua1arn 1:119c4f7144c8 95 http_mt_t res;
ua1arn 1:119c4f7144c8 96 for (res = METHOD_GET; res <= METHOD_PATCH; res++)
ua1arn 1:119c4f7144c8 97 if (strcmp(METHODS_STR[res], str) == 0)
ua1arn 1:119c4f7144c8 98 return res;
ua1arn 1:119c4f7144c8 99 return METHOD_NONE;
ua1arn 1:119c4f7144c8 100 }
ua1arn 1:119c4f7144c8 101
ua1arn 1:119c4f7144c8 102 static http_ct_t str_to_ct(const char *str)
ua1arn 1:119c4f7144c8 103 {
ua1arn 1:119c4f7144c8 104 if (strcmp(str, CONN_TYPE_STR[CT_CLOSE]) == 0) return CT_CLOSE;
ua1arn 1:119c4f7144c8 105 if (strcmp(str, CONN_TYPE_STR[CT_KEEP_ALIVE]) == 0) return CT_KEEP_ALIVE;
ua1arn 1:119c4f7144c8 106 return CT_NONE;
ua1arn 1:119c4f7144c8 107 }
ua1arn 1:119c4f7144c8 108
ua1arn 1:119c4f7144c8 109 void http_req_set_param(http_req_t *req, char *name, char *val)
ua1arn 1:119c4f7144c8 110 {
ua1arn 1:119c4f7144c8 111 if (strcmp(name, "Host") == 0)
ua1arn 1:119c4f7144c8 112 req->host = val;
ua1arn 1:119c4f7144c8 113 else
ua1arn 1:119c4f7144c8 114 if (strcmp(name, "User-Agent") == 0)
ua1arn 1:119c4f7144c8 115 req->user_agent = val;
ua1arn 1:119c4f7144c8 116 else
ua1arn 1:119c4f7144c8 117 if (strcmp(name, "Content-Type") == 0)
ua1arn 1:119c4f7144c8 118 req->mime = val;
ua1arn 1:119c4f7144c8 119 else
ua1arn 1:119c4f7144c8 120 if (strcmp(name, "Content-Length") == 0)
ua1arn 1:119c4f7144c8 121 req->cont_len = strtol(val, NULL, 10);
ua1arn 1:119c4f7144c8 122 else
ua1arn 1:119c4f7144c8 123 if (strcmp(name, "Accept") == 0)
ua1arn 1:119c4f7144c8 124 req->accept = val;
ua1arn 1:119c4f7144c8 125 else
ua1arn 1:119c4f7144c8 126 if (strcmp(name, "Accept-Language") == 0)
ua1arn 1:119c4f7144c8 127 req->accept_lang = val;
ua1arn 1:119c4f7144c8 128 else
ua1arn 1:119c4f7144c8 129 if (strcmp(name, "Accept-Encoding") == 0)
ua1arn 1:119c4f7144c8 130 req->accept_enc = val;
ua1arn 1:119c4f7144c8 131 else
ua1arn 1:119c4f7144c8 132 if (strcmp(name, "Cookie") == 0)
ua1arn 1:119c4f7144c8 133 req->cookie = val;
ua1arn 1:119c4f7144c8 134 else
ua1arn 1:119c4f7144c8 135 if (strcmp(name, "Connection") == 0)
ua1arn 1:119c4f7144c8 136 req->conn_type = str_to_ct(val);
ua1arn 1:119c4f7144c8 137 else
ua1arn 1:119c4f7144c8 138 if (strcmp(name, "Keep-Alive") == 0)
ua1arn 1:119c4f7144c8 139 req->keep_alive = strtol(val, NULL, 10);
ua1arn 1:119c4f7144c8 140 }
ua1arn 1:119c4f7144c8 141
ua1arn 1:119c4f7144c8 142 void http_reqb_push(http_reqb_t *rb, const void *data, int size)
ua1arn 1:119c4f7144c8 143 {
ua1arn 1:119c4f7144c8 144 parser_t p;
ua1arn 1:119c4f7144c8 145 int indeces[4];
ua1arn 1:119c4f7144c8 146
ua1arn 1:119c4f7144c8 147 if (rb->size + size >= rb->bsize)
ua1arn 1:119c4f7144c8 148 {
ua1arn 1:119c4f7144c8 149 rb->state = REQB_REQ_TO_BIG;
ua1arn 1:119c4f7144c8 150 return;
ua1arn 1:119c4f7144c8 151 }
ua1arn 1:119c4f7144c8 152 if (rb->state != REQB_UNFINISHED) return;
ua1arn 1:119c4f7144c8 153
ua1arn 1:119c4f7144c8 154 memcpy(&rb->buff[rb->size], data, size);
ua1arn 1:119c4f7144c8 155 rb->size += size;
ua1arn 1:119c4f7144c8 156
ua1arn 1:119c4f7144c8 157 parser_init(&p, rb->buff, rb->size);
ua1arn 1:119c4f7144c8 158 parser_skip_n(&p, rb->parsing.pos);
ua1arn 1:119c4f7144c8 159
ua1arn 1:119c4f7144c8 160 while (!parser_eof(&p))
ua1arn 1:119c4f7144c8 161 {
ua1arn 1:119c4f7144c8 162 int total;
ua1arn 1:119c4f7144c8 163 switch (rb->parsing.state)
ua1arn 1:119c4f7144c8 164 {
ua1arn 1:119c4f7144c8 165 case 0:
ua1arn 1:119c4f7144c8 166 parser_skip_ws(&p);
ua1arn 1:119c4f7144c8 167 total = p.total;
ua1arn 1:119c4f7144c8 168 parser_skip_before(&p, ' ');
ua1arn 1:119c4f7144c8 169 if (parser_eof(&p)) break;
ua1arn 1:119c4f7144c8 170 rb->buff[p.total] = 0;
ua1arn 1:119c4f7144c8 171 rb->req.method = str_to_method(&rb->buff[total]);
ua1arn 1:119c4f7144c8 172 parser_skip_n(&p, 1);
ua1arn 1:119c4f7144c8 173 rb->parsing.pos = p.total;
ua1arn 1:119c4f7144c8 174 rb->parsing.state = 1;
ua1arn 1:119c4f7144c8 175 break;
ua1arn 1:119c4f7144c8 176 case 1:
ua1arn 1:119c4f7144c8 177 parser_skip_ws(&p);
ua1arn 1:119c4f7144c8 178 total = p.total;
ua1arn 1:119c4f7144c8 179 parser_skip(&p, req_ident);
ua1arn 1:119c4f7144c8 180 if (parser_eof(&p)) break;
ua1arn 1:119c4f7144c8 181 switch (parser_curr(&p))
ua1arn 1:119c4f7144c8 182 {
ua1arn 1:119c4f7144c8 183 case '?': rb->parsing.state = 2; break;
ua1arn 1:119c4f7144c8 184 case ' ': rb->parsing.state = 4; break;
ua1arn 1:119c4f7144c8 185 default: rb->parsing.state = 11; break;
ua1arn 1:119c4f7144c8 186 }
ua1arn 1:119c4f7144c8 187 if (rb->parsing.state >= 10) break; // error
ua1arn 1:119c4f7144c8 188 rb->req.uri = &rb->buff[total];
ua1arn 1:119c4f7144c8 189 rb->buff[p.total] = 0;
ua1arn 1:119c4f7144c8 190 parser_skip_n(&p, 1);
ua1arn 1:119c4f7144c8 191 rb->parsing.pos = p.total;
ua1arn 1:119c4f7144c8 192 break;
ua1arn 1:119c4f7144c8 193 case 2:
ua1arn 1:119c4f7144c8 194 total = p.total;
ua1arn 1:119c4f7144c8 195 parser_skip(&p, req_ident);
ua1arn 1:119c4f7144c8 196 if (parser_eof(&p)) break;
ua1arn 1:119c4f7144c8 197 switch (parser_curr(&p))
ua1arn 1:119c4f7144c8 198 {
ua1arn 1:119c4f7144c8 199 case '&': rb->parsing.state = 2; break;
ua1arn 1:119c4f7144c8 200 case '=': rb->parsing.state = 3; break;
ua1arn 1:119c4f7144c8 201 case ' ': rb->parsing.state = 4; break;
ua1arn 1:119c4f7144c8 202 default: rb->parsing.state = 12; break;
ua1arn 1:119c4f7144c8 203 }
ua1arn 1:119c4f7144c8 204 if (rb->parsing.state >= 10) break; // error
ua1arn 1:119c4f7144c8 205 rb->req.num_params++;
ua1arn 1:119c4f7144c8 206 if (rb->req.num_params <= HTTP_REQ_MAX_PARAMS)
ua1arn 1:119c4f7144c8 207 {
ua1arn 1:119c4f7144c8 208 rb->req.params[rb->req.num_params - 1] = &rb->buff[total];
ua1arn 1:119c4f7144c8 209 rb->req.values[rb->req.num_params - 1] = NULL;
ua1arn 1:119c4f7144c8 210 }
ua1arn 1:119c4f7144c8 211 rb->buff[p.total] = 0;
ua1arn 1:119c4f7144c8 212 parser_skip_n(&p, 1);
ua1arn 1:119c4f7144c8 213 rb->parsing.pos = p.total;
ua1arn 1:119c4f7144c8 214 break;
ua1arn 1:119c4f7144c8 215 case 3:
ua1arn 1:119c4f7144c8 216 total = p.total;
ua1arn 1:119c4f7144c8 217 parser_skip(&p, req_ident);
ua1arn 1:119c4f7144c8 218 if (parser_eof(&p)) break;
ua1arn 1:119c4f7144c8 219 switch (parser_curr(&p))
ua1arn 1:119c4f7144c8 220 {
ua1arn 1:119c4f7144c8 221 case '&': rb->parsing.state = 2; break;
ua1arn 1:119c4f7144c8 222 case ' ': rb->parsing.state = 4; break;
ua1arn 1:119c4f7144c8 223 default: rb->parsing.state = 13; break;
ua1arn 1:119c4f7144c8 224 }
ua1arn 1:119c4f7144c8 225 if (rb->parsing.state >= 10) break; // error
ua1arn 1:119c4f7144c8 226 if (rb->req.num_params <= HTTP_REQ_MAX_PARAMS)
ua1arn 1:119c4f7144c8 227 rb->req.values[rb->req.num_params - 1] = &rb->buff[total];
ua1arn 1:119c4f7144c8 228 rb->buff[p.total] = 0;
ua1arn 1:119c4f7144c8 229 parser_skip_n(&p, 1);
ua1arn 1:119c4f7144c8 230 rb->parsing.pos = p.total;
ua1arn 1:119c4f7144c8 231 break;
ua1arn 1:119c4f7144c8 232 case 4:
ua1arn 1:119c4f7144c8 233 parser_skip_ws(&p);
ua1arn 1:119c4f7144c8 234 total = p.total;
ua1arn 1:119c4f7144c8 235 if (!parser_skip_line(&p)) break;
ua1arn 1:119c4f7144c8 236 rb->req.ver = &rb->buff[total];
ua1arn 1:119c4f7144c8 237 rb->buff[p.total - 2] = 0;
ua1arn 1:119c4f7144c8 238 rb->parsing.pos = p.total;
ua1arn 1:119c4f7144c8 239 rb->parsing.state = 5;
ua1arn 1:119c4f7144c8 240 break;
ua1arn 1:119c4f7144c8 241 case 5:
ua1arn 1:119c4f7144c8 242 parser_skip_ws_in_line(&p);
ua1arn 1:119c4f7144c8 243 if (parser_skip_char(&p, '\r') || parser_skip_char(&p, '\n'))
ua1arn 1:119c4f7144c8 244 {
ua1arn 1:119c4f7144c8 245 // DONE
ua1arn 1:119c4f7144c8 246 rb->state = REQB_FINISHED;
ua1arn 1:119c4f7144c8 247 return;
ua1arn 1:119c4f7144c8 248 }
ua1arn 1:119c4f7144c8 249 // 0 1 2 3
ua1arn 1:119c4f7144c8 250 // Accept: text/html\r\n...
ua1arn 1:119c4f7144c8 251 parser_skip_ws_in_line(&p);
ua1arn 1:119c4f7144c8 252 indeces[0] = p.total;
ua1arn 1:119c4f7144c8 253 parser_skip(&p, req_ident);
ua1arn 1:119c4f7144c8 254 if (parser_eof(&p)) break;
ua1arn 1:119c4f7144c8 255 if (parser_curr(&p) != ':')
ua1arn 1:119c4f7144c8 256 {
ua1arn 1:119c4f7144c8 257 rb->parsing.state = 15;
ua1arn 1:119c4f7144c8 258 break;
ua1arn 1:119c4f7144c8 259 }
ua1arn 1:119c4f7144c8 260 indeces[1] = p.total;
ua1arn 1:119c4f7144c8 261 parser_skip_n(&p, 1);
ua1arn 1:119c4f7144c8 262 parser_skip_ws_in_line(&p);
ua1arn 1:119c4f7144c8 263 indeces[2] = p.total;
ua1arn 1:119c4f7144c8 264 if (!parser_skip_line(&p)) break;
ua1arn 1:119c4f7144c8 265 indeces[3] = p.total;
ua1arn 1:119c4f7144c8 266 rb->buff[indeces[1]] = 0;
ua1arn 1:119c4f7144c8 267 rb->buff[indeces[3] - 2] = 0;
ua1arn 1:119c4f7144c8 268 http_req_set_param(&rb->req,
ua1arn 1:119c4f7144c8 269 &rb->buff[indeces[0]],
ua1arn 1:119c4f7144c8 270 &rb->buff[indeces[2]]);
ua1arn 1:119c4f7144c8 271 rb->parsing.pos = p.total;
ua1arn 1:119c4f7144c8 272 break;
ua1arn 1:119c4f7144c8 273 default:
ua1arn 1:119c4f7144c8 274 rb->state = REQB_SYNT_ERROR;
ua1arn 1:119c4f7144c8 275 return;
ua1arn 1:119c4f7144c8 276 }
ua1arn 1:119c4f7144c8 277 }
ua1arn 1:119c4f7144c8 278 }
ua1arn 1:119c4f7144c8 279
ua1arn 1:119c4f7144c8 280 int http_resp_len(const http_resp_t *resp)
ua1arn 1:119c4f7144c8 281 {
ua1arn 1:119c4f7144c8 282 char temp[1];
ua1arn 1:119c4f7144c8 283 return http_resp_str(resp, temp, 1);
ua1arn 1:119c4f7144c8 284 }
ua1arn 1:119c4f7144c8 285
ua1arn 1:119c4f7144c8 286 int http_resp_str(const http_resp_t *resp, char *str, int size)
ua1arn 1:119c4f7144c8 287 {
ua1arn 1:119c4f7144c8 288 return snprintf(str, size,
ua1arn 1:119c4f7144c8 289 "HTTP/1.1 %d\r\n"
ua1arn 1:119c4f7144c8 290 "Server: %s\r\n"
ua1arn 1:119c4f7144c8 291 // "Content-Type: text/html\r\n"
ua1arn 1:119c4f7144c8 292 "Content-Type: %s\r\n"
ua1arn 1:119c4f7144c8 293 "Content-Length: %d\r\n"
ua1arn 1:119c4f7144c8 294 "Connection: %s\r\n"
ua1arn 1:119c4f7144c8 295 "\r\n",
ua1arn 1:119c4f7144c8 296 resp->code,
ua1arn 1:119c4f7144c8 297 resp->server,
ua1arn 1:119c4f7144c8 298 resp->mime,
ua1arn 1:119c4f7144c8 299 resp->cont_len,
ua1arn 1:119c4f7144c8 300 CONN_TYPE_STR[resp->conn_type]);
ua1arn 1:119c4f7144c8 301 }
ua1arn 1:119c4f7144c8 302
ua1arn 1:119c4f7144c8 303 #ifdef __cplusplus
ua1arn 1:119c4f7144c8 304 }
ua1arn 1:119c4f7144c8 305 #endif