lwip-1.4.1 (partial)
Embed:
(wiki syntax)
Show/hide line numbers
http_req.c
00001 /* 00002 * The MIT License (MIT) 00003 * 00004 * Copyright (c) 2015 by Sergey Fetisov <fsenok@gmail.com> 00005 * 00006 * Permission is hereby granted, free of charge, to any person obtaining a copy 00007 * of this software and associated documentation files (the "Software"), to deal 00008 * in the Software without restriction, including without limitation the rights 00009 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00010 * copies of the Software, and to permit persons to whom the Software is 00011 * furnished to do so, subject to the following conditions: 00012 * 00013 * The above copyright notice and this permission notice shall be included in all 00014 * copies or substantial portions of the Software. 00015 * 00016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00018 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00019 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00020 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00021 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00022 * SOFTWARE. 00023 */ 00024 00025 /* 00026 * version: 1.0 demo (7.02.2015) 00027 * brief: part of tiny http ipv4 server using lwip (pcb) 00028 */ 00029 00030 #include "http_req.h" 00031 00032 #ifdef __cplusplus 00033 extern "C" { 00034 #endif 00035 00036 const char MIME_TEXT_HTML[] = "text/html"; 00037 const char MIME_TEXT_JS[] = "text/javascript"; 00038 const char MIME_TEXT_PLAIN[] = "text/plain"; 00039 const char MIME_TEXT_XML[] = "text/xml"; 00040 const char MIME_TEXT_CSS[] = "text/css"; 00041 const char MIME_IMAGE_GIF[] = "image/gif"; 00042 const char MIME_IMAGE_JPEG[] = "image/jpeg"; 00043 const char MIME_IMAGE_PJPEG[] = "image/pjpeg"; 00044 const char MIME_IMAGE_PNG[] = "image/png"; 00045 const char MIME_IMAGE_SVG[] = "image/svg+xml"; 00046 const char MIME_IMAGE_TIFF[] = "image/tiff"; 00047 const char MIME_IMAGE_ICON[] = "image/vnd.microsoft.icon"; 00048 const char MIME_IMAGE_WBMP[] = "image/vnd.wap.wbmp"; 00049 00050 static const char *METHODS_STR[] = 00051 { 00052 "", 00053 "GET", 00054 "POST", 00055 "HEAD", 00056 "PUT", 00057 "CONNECT", 00058 "OPTIONS", 00059 "DELETE", 00060 "TRACE", 00061 "PATCH" 00062 }; 00063 00064 static const char *CONN_TYPE_STR[] = 00065 { 00066 "", "close", "keep-alive" 00067 }; 00068 00069 void http_reqb_init(http_reqb_t *reqb, void *buff, int size) 00070 { 00071 memset(reqb, 0, sizeof(http_reqb_t)); 00072 reqb->buff = buff; 00073 reqb->bsize = size; 00074 } 00075 00076 int http_reqb_avail(const http_reqb_t *reqb) 00077 { 00078 return reqb->bsize - reqb->size; 00079 } 00080 00081 static chatset_t req_ident = 00082 { 00083 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00084 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00085 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, // '%', '-', '.', '/' 00086 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, // '0'...'9' 00087 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 'A'...'O' 00088 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, // 'P'...'Z', '_' 00089 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 'a'...'z' 00090 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 'p'...'z' 00091 }; 00092 00093 static http_mt_t str_to_method(const char *str) 00094 { 00095 http_mt_t res; 00096 for (res = METHOD_GET; res <= METHOD_PATCH; res++) 00097 if (strcmp(METHODS_STR[res], str) == 0) 00098 return res; 00099 return METHOD_NONE; 00100 } 00101 00102 static http_ct_t str_to_ct(const char *str) 00103 { 00104 if (strcmp(str, CONN_TYPE_STR[CT_CLOSE]) == 0) return CT_CLOSE; 00105 if (strcmp(str, CONN_TYPE_STR[CT_KEEP_ALIVE]) == 0) return CT_KEEP_ALIVE; 00106 return CT_NONE; 00107 } 00108 00109 void http_req_set_param(http_req_t *req, char *name, char *val) 00110 { 00111 if (strcmp(name, "Host") == 0) 00112 req->host = val; 00113 else 00114 if (strcmp(name, "User-Agent") == 0) 00115 req->user_agent = val; 00116 else 00117 if (strcmp(name, "Content-Type") == 0) 00118 req->mime = val; 00119 else 00120 if (strcmp(name, "Content-Length") == 0) 00121 req->cont_len = strtol(val, NULL, 10); 00122 else 00123 if (strcmp(name, "Accept") == 0) 00124 req->accept = val; 00125 else 00126 if (strcmp(name, "Accept-Language") == 0) 00127 req->accept_lang = val; 00128 else 00129 if (strcmp(name, "Accept-Encoding") == 0) 00130 req->accept_enc = val; 00131 else 00132 if (strcmp(name, "Cookie") == 0) 00133 req->cookie = val; 00134 else 00135 if (strcmp(name, "Connection") == 0) 00136 req->conn_type = str_to_ct(val); 00137 else 00138 if (strcmp(name, "Keep-Alive") == 0) 00139 req->keep_alive = strtol(val, NULL, 10); 00140 } 00141 00142 void http_reqb_push(http_reqb_t *rb, const void *data, int size) 00143 { 00144 parser_t p; 00145 int indeces[4]; 00146 00147 if (rb->size + size >= rb->bsize) 00148 { 00149 rb->state = REQB_REQ_TO_BIG; 00150 return; 00151 } 00152 if (rb->state != REQB_UNFINISHED) return; 00153 00154 memcpy(&rb->buff[rb->size], data, size); 00155 rb->size += size; 00156 00157 parser_init(&p, rb->buff, rb->size); 00158 parser_skip_n(&p, rb->parsing.pos); 00159 00160 while (!parser_eof(&p)) 00161 { 00162 int total; 00163 switch (rb->parsing.state) 00164 { 00165 case 0: 00166 parser_skip_ws(&p); 00167 total = p.total; 00168 parser_skip_before(&p, ' '); 00169 if (parser_eof(&p)) break; 00170 rb->buff[p.total] = 0; 00171 rb->req.method = str_to_method(&rb->buff[total]); 00172 parser_skip_n(&p, 1); 00173 rb->parsing.pos = p.total; 00174 rb->parsing.state = 1; 00175 break; 00176 case 1: 00177 parser_skip_ws(&p); 00178 total = p.total; 00179 parser_skip(&p, req_ident); 00180 if (parser_eof(&p)) break; 00181 switch (parser_curr(&p)) 00182 { 00183 case '?': rb->parsing.state = 2; break; 00184 case ' ': rb->parsing.state = 4; break; 00185 default: rb->parsing.state = 11; break; 00186 } 00187 if (rb->parsing.state >= 10) break; // error 00188 rb->req.uri = &rb->buff[total]; 00189 rb->buff[p.total] = 0; 00190 parser_skip_n(&p, 1); 00191 rb->parsing.pos = p.total; 00192 break; 00193 case 2: 00194 total = p.total; 00195 parser_skip(&p, req_ident); 00196 if (parser_eof(&p)) break; 00197 switch (parser_curr(&p)) 00198 { 00199 case '&': rb->parsing.state = 2; break; 00200 case '=': rb->parsing.state = 3; break; 00201 case ' ': rb->parsing.state = 4; break; 00202 default: rb->parsing.state = 12; break; 00203 } 00204 if (rb->parsing.state >= 10) break; // error 00205 rb->req.num_params++; 00206 if (rb->req.num_params <= HTTP_REQ_MAX_PARAMS) 00207 { 00208 rb->req.params[rb->req.num_params - 1] = &rb->buff[total]; 00209 rb->req.values[rb->req.num_params - 1] = NULL; 00210 } 00211 rb->buff[p.total] = 0; 00212 parser_skip_n(&p, 1); 00213 rb->parsing.pos = p.total; 00214 break; 00215 case 3: 00216 total = p.total; 00217 parser_skip(&p, req_ident); 00218 if (parser_eof(&p)) break; 00219 switch (parser_curr(&p)) 00220 { 00221 case '&': rb->parsing.state = 2; break; 00222 case ' ': rb->parsing.state = 4; break; 00223 default: rb->parsing.state = 13; break; 00224 } 00225 if (rb->parsing.state >= 10) break; // error 00226 if (rb->req.num_params <= HTTP_REQ_MAX_PARAMS) 00227 rb->req.values[rb->req.num_params - 1] = &rb->buff[total]; 00228 rb->buff[p.total] = 0; 00229 parser_skip_n(&p, 1); 00230 rb->parsing.pos = p.total; 00231 break; 00232 case 4: 00233 parser_skip_ws(&p); 00234 total = p.total; 00235 if (!parser_skip_line(&p)) break; 00236 rb->req.ver = &rb->buff[total]; 00237 rb->buff[p.total - 2] = 0; 00238 rb->parsing.pos = p.total; 00239 rb->parsing.state = 5; 00240 break; 00241 case 5: 00242 parser_skip_ws_in_line(&p); 00243 if (parser_skip_char(&p, '\r') || parser_skip_char(&p, '\n')) 00244 { 00245 // DONE 00246 rb->state = REQB_FINISHED; 00247 return; 00248 } 00249 // 0 1 2 3 00250 // Accept: text/html\r\n... 00251 parser_skip_ws_in_line(&p); 00252 indeces[0] = p.total; 00253 parser_skip(&p, req_ident); 00254 if (parser_eof(&p)) break; 00255 if (parser_curr(&p) != ':') 00256 { 00257 rb->parsing.state = 15; 00258 break; 00259 } 00260 indeces[1] = p.total; 00261 parser_skip_n(&p, 1); 00262 parser_skip_ws_in_line(&p); 00263 indeces[2] = p.total; 00264 if (!parser_skip_line(&p)) break; 00265 indeces[3] = p.total; 00266 rb->buff[indeces[1]] = 0; 00267 rb->buff[indeces[3] - 2] = 0; 00268 http_req_set_param(&rb->req, 00269 &rb->buff[indeces[0]], 00270 &rb->buff[indeces[2]]); 00271 rb->parsing.pos = p.total; 00272 break; 00273 default: 00274 rb->state = REQB_SYNT_ERROR; 00275 return; 00276 } 00277 } 00278 } 00279 00280 int http_resp_len(const http_resp_t *resp) 00281 { 00282 char temp[1]; 00283 return http_resp_str(resp, temp, 1); 00284 } 00285 00286 int http_resp_str(const http_resp_t *resp, char *str, int size) 00287 { 00288 return snprintf(str, size, 00289 "HTTP/1.1 %d\r\n" 00290 "Server: %s\r\n" 00291 // "Content-Type: text/html\r\n" 00292 "Content-Type: %s\r\n" 00293 "Content-Length: %d\r\n" 00294 "Connection: %s\r\n" 00295 "\r\n", 00296 resp->code, 00297 resp->server, 00298 resp->mime, 00299 resp->cont_len, 00300 CONN_TYPE_STR[resp->conn_type]); 00301 } 00302 00303 #ifdef __cplusplus 00304 } 00305 #endif
Generated on Wed Jul 13 2022 09:48:37 by 1.7.2