Mon, 06 Mar 2017 17:32:26 +0100
merge srvctrl into default branch
1 | 1 | /* |
2 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. | |
3 | * | |
44
3da1f7b6847f
added some error messages
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
25
diff
changeset
|
4 | * Copyright 2013 Olaf Wintermann. All rights reserved. |
1 | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | |
7 | * modification, are permitted provided that the following conditions are met: | |
8 | * | |
9 | * 1. Redistributions of source code must retain the above copyright | |
10 | * notice, this list of conditions and the following disclaimer. | |
11 | * | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | |
15 | * | |
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | |
20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
26 | * POSSIBILITY OF SUCH DAMAGE. | |
27 | */ | |
28 | ||
29 | #include <stdio.h> | |
30 | #include <stdlib.h> | |
31 | ||
32 | #include "httpparser.h" | |
14
b8bf95b39952
New source folder layout
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
1
diff
changeset
|
33 | #include "../public/nsapi.h" |
1 | 34 | //include "request.h" |
35 | ||
36 | ||
37 | HttpParser* http_parser_new(HTTPRequest *request) { | |
38 | HttpParser *parser = malloc(sizeof(HttpParser)); | |
39 | parser->request = request; | |
40 | ||
41 | parser->state = 0; | |
42 | parser->start_line.ptr = (char*)request->netbuf->inbuf; | |
43 | parser->start_line.length = 0; | |
101
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
44 | |
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
45 | parser->offset = 0; |
1 | 46 | |
47 | return parser; | |
48 | } | |
49 | ||
50 | void http_parser_free(HttpParser *parser) { | |
51 | free(parser); | |
52 | } | |
53 | ||
54 | int http_parser_process(HttpParser *parser) { | |
55 | switch(parser->state) { | |
56 | case 0: { | |
57 | int r = get_start_line(parser); | |
58 | switch(r) { | |
59 | case 0: break; | |
60 | default: return r; | |
61 | } | |
62 | parse_request_line(parser); | |
63 | parser->state++; | |
64 | } | |
65 | case 1: { | |
66 | return http_parser_parse_header(parser); | |
67 | } | |
68 | case 2: { | |
69 | return 0; | |
70 | } | |
71 | } | |
25
5dee29c7c530
Fixed config parser bug
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
20
diff
changeset
|
72 | return -1; |
1 | 73 | } |
74 | ||
75 | int get_start_line(HttpParser *parser) { | |
76 | netbuf *buf = parser->request->netbuf; | |
77 | while(buf->pos < buf->cursize) { | |
78 | unsigned char c = buf->inbuf[buf->pos]; | |
79 | if(c == '\n') { | |
101
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
80 | size_t lnlen = buf->pos - parser->offset + 1; |
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
81 | if(lnlen <= 2) { |
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
82 | if(lnlen == 1 || buf->inbuf[buf->pos-1] == '\r') { |
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
83 | // skip empty line |
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
84 | buf->pos++; |
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
85 | parser->offset = buf->pos; |
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
86 | return 1; |
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
87 | } |
1 | 88 | // insufficient chars for request, return error |
89 | return 2; | |
90 | } | |
91 | if(buf->inbuf[buf->pos - 1] == '\r') { | |
101
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
92 | parser->start_line.length = lnlen - 1; |
1 | 93 | } else { |
101
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
94 | parser->start_line.length = lnlen; |
1 | 95 | } |
101
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
96 | parser->start_line.ptr = (char*)buf->inbuf + parser->offset; |
1 | 97 | buf->pos++; |
98 | return 0; | |
99 | } | |
100 | buf->pos++; | |
101 | } | |
102 | return 1; | |
103 | } | |
104 | ||
105 | int http_parser_parse_header(HttpParser *parser) { | |
106 | netbuf *buf = parser->request->netbuf; | |
107 | ||
108 | parser->offset = buf->pos; // line offset | |
109 | parser->name.ptr = NULL; | |
101
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
110 | parser->name.length = 0; |
1 | 111 | parser->value.ptr = NULL; |
101
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
112 | parser->value.length = 0; |
1 | 113 | while(1) { |
114 | if(buf->pos >= buf->cursize) { | |
115 | return 1; | |
116 | } | |
117 | char c = (char)buf->inbuf[buf->pos++]; | |
118 | ||
119 | if(c > 32) { | |
120 | parser->wl = 0; | |
121 | if(c == ':' && parser->value.ptr == NULL) { | |
122 | parser->name.ptr = (char*)buf->inbuf + parser->offset; | |
101
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
123 | parser->name.length = buf->pos - parser->offset - 1; |
1 | 124 | } else if(parser->name.ptr != NULL && parser->value.ptr == NULL) { |
125 | parser->value.ptr = (char*)buf->inbuf + buf->pos - 1; | |
126 | } | |
127 | } else if(c == '\n') { | |
128 | if(parser->wl) { | |
129 | // line contains only white space -> end of request | |
130 | parser->state++; | |
131 | return 0; | |
132 | } else { | |
133 | parser->offset = buf->pos; | |
162
b169992137a8
improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
101
diff
changeset
|
134 | if(parser->name.length != 0) { |
b169992137a8
improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
101
diff
changeset
|
135 | if(parser->value.ptr) { |
b169992137a8
improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
101
diff
changeset
|
136 | parser->value.length = (buf->inbuf + buf->pos - 1) |
101
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
137 | - (unsigned char*)parser->value.ptr; |
162
b169992137a8
improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
101
diff
changeset
|
138 | if(buf->inbuf[buf->pos-2] == '\r') { |
b169992137a8
improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
101
diff
changeset
|
139 | parser->value.length--; |
b169992137a8
improves cgi error handling and allows requests with empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
101
diff
changeset
|
140 | } |
163
3589ed579127
fixes empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
162
diff
changeset
|
141 | } else { |
3589ed579127
fixes empty headers
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
162
diff
changeset
|
142 | parser->value.ptr = ""; |
20
7b235fa88008
Some fixes for mod_jk
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
14
diff
changeset
|
143 | } |
1 | 144 | // add header |
145 | header_add( | |
146 | parser->request->headers, | |
101
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
147 | parser->name, |
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
148 | parser->value); |
1 | 149 | } else { |
150 | // error: no value | |
151 | return 2; | |
152 | } | |
153 | parser->name.ptr = NULL; | |
154 | parser->value.ptr = NULL; | |
101
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
155 | parser->name.length = 0; |
7fbcdbad0baa
added support for absolute URIs and improved keep alive
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
44
diff
changeset
|
156 | parser->value.length = 0; |
1 | 157 | parser->wl = 1; |
158 | } | |
159 | } | |
160 | } | |
161 | } | |
162 | ||
163 | int parse_request_line(HttpParser *parser) { | |
164 | sstr_t line = parser->start_line; | |
165 | parser->request->request_line = line; | |
166 | ||
167 | /* | |
168 | * parse method, url and http version | |
169 | */ | |
170 | ||
171 | int i = 0; | |
172 | int ns = 0; | |
173 | ||
174 | parser->request->method.ptr = line.ptr; | |
175 | for(;i<line.length;i++) { | |
176 | if(!ns && line.ptr[i] == ' ') { | |
177 | ns = 1; | |
178 | //line.ptr[i] = 0; // TODO: remove | |
179 | parser->request->method.length = i; | |
180 | } else if(ns) { | |
181 | if(line.ptr[i] != ' ') { | |
182 | break; | |
183 | } | |
184 | } | |
185 | } | |
186 | ||
187 | parser->request->uri.ptr = line.ptr + i; | |
188 | ns = 0; | |
189 | int s = i; | |
190 | for(;i<line.length;i++) { | |
191 | if(!ns && line.ptr[i] < 33) { | |
192 | ns = 1; | |
193 | //line.ptr[i] = 0; // TODO: remove | |
194 | parser->request->uri.length = i - s; | |
195 | } else if(ns) { | |
196 | if(line.ptr[i] > 32) { | |
197 | break; | |
198 | } | |
199 | } | |
200 | } | |
201 | ||
202 | parser->request->httpv.ptr = line.ptr + i; | |
203 | ns = 0; | |
204 | s = i; | |
205 | for(;i<line.length;i++) { | |
206 | if(!ns && line.ptr[i] < 33) { | |
207 | ns = 1; | |
208 | //line.ptr[i] = 0; // TODO: remove | |
209 | parser->request->httpv.length = i - s; | |
210 | } else if(ns) { | |
211 | if(line.ptr[i] > 32) { | |
212 | break; | |
213 | } | |
214 | } | |
215 | } | |
216 | ||
217 | return 0; | |
218 | } |