annotate asyncdreactor/protocol/http11_parser.rl @ 11:5836613d16ac

reorg! reorg!
author rick@minifunk
date Tue, 12 Aug 2008 16:59:56 -0400
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
11
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
1 /**
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
2 * Copyright (c) 2005 Zed A. Shaw,
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
3 * Modified for D/DReactor by Rick Richardson, 2008
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
4 * You can redistribute it and/or modify it under the same terms as Ruby.
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
5 */
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
6
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
7 alias void delegate (void *data, const char *at, size_t length) element_cb;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
8 alias void delegate (void *data, const char *field, size_t flen, const char *value, size_t vlen) field_cb;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
9
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
10 class Http11Parser
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
11 {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
12 int cs;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
13 size_t body_start;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
14 int content_len;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
15 size_t nread;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
16 size_t mark;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
17 size_t field_start;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
18 size_t field_len;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
19 size_t query_start;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
20
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
21 void *data;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
22
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
23 field_cb http_field;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
24 element_cb request_method;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
25 element_cb request_uri;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
26 element_cb fragment;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
27 element_cb request_path;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
28 element_cb query_string;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
29 element_cb http_version;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
30 element_cb header_done;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
31
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
32 /*
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
33 * capitalizes all lower-case ASCII characters,
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
34 * converts dashes to underscores.
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
35 */
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
36 private void snake_upcase_char(char *c)
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
37 {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
38 if (*c >= 'a' && *c <= 'z')
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
39 *c &= ~0x20;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
40 else if (*c == '-')
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
41 *c = '_';
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
42 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
43
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
44 //#define LEN(AT, FPC) (FPC - buffer - parser->AT)
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
45 private int LEN(char* at, char* fpc)
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
46 {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
47 return (fpc - buffer.ptr - at);
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
48 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
49
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
50 //#define MARK(M,FPC) (parser->M = (FPC) - buffer)
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
51 private void MARK(size_t* item, char* fpc)
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
52 {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
53 *item = fpc - buffer.ptr;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
54 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
55
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
56 //#define PTR_TO(F) (buffer + parser->F)
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
57 private char* PTR_TO(size_t F)
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
58 {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
59 return (buffer.ptr + F);
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
60 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
61 /** Machine **/
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
62
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
63 %%{
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
64
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
65 machine http_parser;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
66
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
67 action mark {MARK(mark, fpc); }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
68
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
69
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
70 action start_field { MARK(field_start, fpc); }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
71 action snake_upcase_field { snake_upcase_char((char *)fpc); }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
72 action write_field {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
73 field_len = LEN(field_start, fpc);
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
74 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
75
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
76 action start_value { MARK(mark, fpc); }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
77 action write_value {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
78 if(http_field)
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
79 http_field(data,
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
80 PTR_TO(field_start),
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
81 field_len,
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
82 PTR_TO(mark),
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
83 LEN(mark, fpc));
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
84 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
85 action request_method {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
86 if(request_method)
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
87 request_method(data, PTR_TO(mark), LEN(mark, fpc));
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
88 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
89
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
90 action request_uri {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
91 if(request_uri)
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
92 request_uri(data, PTR_TO(mark), LEN(mark, fpc));
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
93 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
94
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
95 action fragment {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
96 if(fragment)
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
97 fragment(data, PTR_TO(mark), LEN(mark, fpc));
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
98 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
99
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
100 action start_query {MARK(query_start, fpc); }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
101
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
102 action query_string {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
103 if(query_string)
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
104 query_string(data, PTR_TO(query_start), LEN(query_start, fpc));
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
105 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
106
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
107 action http_version {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
108 if(http_version)
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
109 http_version(data, PTR_TO(mark), LEN(mark, fpc));
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
110 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
111
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
112 action request_path {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
113 if(request_path)
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
114 request_path(data, PTR_TO(mark), LEN(mark,fpc));
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
115 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
116
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
117 action done {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
118 body_start = fpc - buffer + 1;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
119 if(header_done)
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
120 header_done(data, fpc + 1, pe - fpc - 1);
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
121 fbreak;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
122 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
123
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
124 include http_parser_common "http11_parser_common.rl";
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
125
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
126 }%%
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
127
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
128 /** Data **/
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
129 %% write data;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
130
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
131 this ()
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
132 {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
133 cs = 0;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
134 %% write init;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
135
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
136 body_start = 0;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
137 content_len = 0;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
138 mark = 0;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
139 nread = 0;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
140 field_len = 0;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
141 field_start = 0;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
142 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
143
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
144
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
145 /** exec **/
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
146 size_t execute(const char[] buffer, size_t off) {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
147 const char *p, *pe;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
148 int len = buffer.length;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
149
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
150 assert(off <= len && "offset past end of buffer");
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
151
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
152 p = buffer.ptr+off;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
153 pe = buffer.ptr+len;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
154
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
155 /* assert(*pe == '\0' && "pointer does not end on NUL"); */
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
156 assert(pe - p == len - off && "pointers aren't same distance");
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
157
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
158 %% write exec;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
159
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
160 //parser->cs = cs;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
161 nread += p - (buffer.ptr + off);
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
162
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
163 assert(p <= pe && "buffer overflow after parsing execute");
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
164 assert(nread <= len && "nread longer than length");
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
165 assert(body_start <= len && "body starts after buffer end");
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
166 assert(mark < len && "mark is after buffer end");
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
167 assert(field_len <= len && "field has length longer than whole buffer");
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
168 assert(field_start < len && "field starts after buffer end");
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
169
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
170 return(nread);
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
171 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
172
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
173 int finish()
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
174 {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
175 if (has_error() ) {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
176 return -1;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
177 } else if (is_finished() ) {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
178 return 1;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
179 } else {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
180 return 0;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
181 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
182 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
183
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
184 bool has_error() {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
185 return cs == http_parser_error;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
186 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
187
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
188 bool is_finished() {
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
189 return cs >= http_parser_first_final;
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
190 }
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
191
5836613d16ac reorg! reorg!
rick@minifunk
parents:
diff changeset
192 }