1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include <stdio.h>
30 #include <stdlib.h>
31
32 #include "httpparser.h"
33 #include "../public/nsapi.h"
34
35
36
37 HttpParser* http_parser_new(HTTPRequest *request) {
38 HttpParser *parser = calloc(
1,
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;
44
45 parser->offset =
0;
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 }
72 return -
1;
73 }
74
75 int http_parser_validate(HttpParser *parser) {
76 HTTPRequest *req = parser->request;
77 if(
78 !req->method.ptr || req->method.length ==
0
79 || !req->uri.ptr || req->uri.length ==
0
80 || !req->httpv.ptr || req->httpv.length ==
0)
81 {
82 return 0;
83 }
84 return 1;
85 }
86
87 int get_start_line(HttpParser *parser) {
88 netbuf *buf = parser->request->netbuf;
89 while(buf->pos < buf->cursize) {
90 unsigned char c = buf->inbuf[buf->pos];
91 if(c ==
'\n') {
92 size_t lnlen = buf->pos - parser->offset +
1;
93 if(lnlen <=
2) {
94 if(lnlen ==
1 || buf->inbuf[buf->pos-
1] ==
'\r') {
95
96 buf->pos++;
97 parser->offset = buf->pos;
98 return 1;
99 }
100
101 return 2;
102 }
103 if(buf->inbuf[buf->pos -
1] ==
'\r') {
104 parser->start_line.length = lnlen -
1;
105 }
else {
106 parser->start_line.length = lnlen;
107 }
108 parser->start_line.ptr = (
char*)buf->inbuf + parser->offset;
109 buf->pos++;
110 return 0;
111 }
112 buf->pos++;
113 }
114 return 1;
115 }
116
117 int http_parser_parse_header(HttpParser *parser) {
118 netbuf *buf = parser->request->netbuf;
119
120 parser->offset = buf->pos;
121 parser->name.ptr =
NULL;
122 parser->name.length =
0;
123 parser->value.ptr =
NULL;
124 parser->value.length =
0;
125 while(
1) {
126 if(buf->pos >= buf->cursize) {
127 return 1;
128 }
129 char c = (
char)buf->inbuf[buf->pos++];
130
131 if(c >
32) {
132 parser->wl =
0;
133 if(c ==
':' && parser->value.ptr ==
NULL) {
134 parser->name.ptr = (
char*)buf->inbuf + parser->offset;
135 parser->name.length = buf->pos - parser->offset -
1;
136 }
else if(parser->name.ptr !=
NULL && parser->value.ptr ==
NULL) {
137 parser->value.ptr = (
char*)buf->inbuf + buf->pos -
1;
138 }
139 }
else if(c ==
'\n') {
140 if(parser->wl) {
141
142 parser->state++;
143 return 0;
144 }
else {
145 parser->offset = buf->pos;
146 if(parser->name.length !=
0) {
147 if(parser->value.ptr) {
148 parser->value.length = (buf->inbuf + buf->pos -
1)
149 - (
unsigned char*)parser->value.ptr;
150 if(buf->inbuf[buf->pos-
2] ==
'\r') {
151 parser->value.length--;
152 }
153 }
else {
154 parser->value.ptr =
"";
155 }
156
157 header_add(
158 parser->request->headers,
159 parser->name,
160 parser->value);
161 }
else {
162
163 return 2;
164 }
165 parser->name.ptr =
NULL;
166 parser->value.ptr =
NULL;
167 parser->name.length =
0;
168 parser->value.length =
0;
169 parser->wl =
1;
170 }
171 }
172 }
173 }
174
175 int parse_request_line(HttpParser *parser) {
176 cxmutstr line = parser->start_line;
177 parser->request->request_line = line;
178
179
180
181
182
183 int i =
0;
184 int ns =
0;
185
186 parser->request->method.ptr = line.ptr;
187 for(;i<line.length;i++) {
188 if(!ns && line.ptr[i] ==
' ') {
189 ns =
1;
190 parser->request->method.length = i;
191 }
else if(ns) {
192 if(line.ptr[i] !=
' ') {
193 break;
194 }
195 }
196 }
197
198 parser->request->uri.ptr = line.ptr + i;
199 ns =
0;
200 int s = i;
201 for(;i<line.length;i++) {
202 if(!ns && isspace(line.ptr[i])) {
203 ns =
1;
204 parser->request->uri.length = i - s;
205 }
else if(ns) {
206 if(line.ptr[i] >
32) {
207 break;
208 }
209 }
210 }
211
212 parser->request->httpv.ptr = line.ptr + i;
213 ns =
0;
214 s = i;
215 for(;i<line.length;i++) {
216 if(!ns && isspace(line.ptr[i])) {
217 ns =
1;
218 parser->request->httpv.length = i - s;
219 }
else if(ns) {
220 if(line.ptr[i] >
32) {
221 break;
222 }
223 }
224 }
225
226 return 0;
227 }
228