![]() |
Home | Libraries | People | FAQ | More |
00001 #include "request_parser.hpp" 00002 #include "request.hpp" 00003 00004 namespace http { 00005 namespace server { 00006 00007 request_parser::request_parser() 00008 : state_(method_start) 00009 { 00010 } 00011 00012 void request_parser::reset() 00013 { 00014 state_ = method_start; 00015 } 00016 00017 boost::tribool request_parser::consume(request& req, char input) 00018 { 00019 switch (state_) 00020 { 00021 case method_start: 00022 if (!is_char(input) || is_ctl(input) || is_tspecial(input)) 00023 { 00024 return false; 00025 } 00026 else 00027 { 00028 state_ = method; 00029 req.method.push_back(input); 00030 return boost::indeterminate; 00031 } 00032 case method: 00033 if (input == ' ') 00034 { 00035 state_ = uri; 00036 return boost::indeterminate; 00037 } 00038 else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) 00039 { 00040 return false; 00041 } 00042 else 00043 { 00044 req.method.push_back(input); 00045 return boost::indeterminate; 00046 } 00047 case uri_start: 00048 if (is_ctl(input)) 00049 { 00050 return false; 00051 } 00052 else 00053 { 00054 state_ = uri; 00055 req.uri.push_back(input); 00056 return boost::indeterminate; 00057 } 00058 case uri: 00059 if (input == ' ') 00060 { 00061 state_ = http_version_h; 00062 return boost::indeterminate; 00063 } 00064 else if (is_ctl(input)) 00065 { 00066 return false; 00067 } 00068 else 00069 { 00070 req.uri.push_back(input); 00071 return boost::indeterminate; 00072 } 00073 case http_version_h: 00074 if (input == 'H') 00075 { 00076 state_ = http_version_t_1; 00077 return boost::indeterminate; 00078 } 00079 else 00080 { 00081 return false; 00082 } 00083 case http_version_t_1: 00084 if (input == 'T') 00085 { 00086 state_ = http_version_t_2; 00087 return boost::indeterminate; 00088 } 00089 else 00090 { 00091 return false; 00092 } 00093 case http_version_t_2: 00094 if (input == 'T') 00095 { 00096 state_ = http_version_p; 00097 return boost::indeterminate; 00098 } 00099 else 00100 { 00101 return false; 00102 } 00103 case http_version_p: 00104 if (input == 'P') 00105 { 00106 state_ = http_version_slash; 00107 return boost::indeterminate; 00108 } 00109 else 00110 { 00111 return false; 00112 } 00113 case http_version_slash: 00114 if (input == '/') 00115 { 00116 req.http_version_major = 0; 00117 req.http_version_minor = 0; 00118 state_ = http_version_major_start; 00119 return boost::indeterminate; 00120 } 00121 else 00122 { 00123 return false; 00124 } 00125 case http_version_major_start: 00126 if (is_digit(input)) 00127 { 00128 req.http_version_major = req.http_version_major * 10 + input - '0'; 00129 state_ = http_version_major; 00130 return boost::indeterminate; 00131 } 00132 else 00133 { 00134 return false; 00135 } 00136 case http_version_major: 00137 if (input == '.') 00138 { 00139 state_ = http_version_minor_start; 00140 return boost::indeterminate; 00141 } 00142 else if (is_digit(input)) 00143 { 00144 req.http_version_major = req.http_version_major * 10 + input - '0'; 00145 return boost::indeterminate; 00146 } 00147 else 00148 { 00149 return false; 00150 } 00151 case http_version_minor_start: 00152 if (is_digit(input)) 00153 { 00154 req.http_version_minor = req.http_version_minor * 10 + input - '0'; 00155 state_ = http_version_minor; 00156 return boost::indeterminate; 00157 } 00158 else 00159 { 00160 return false; 00161 } 00162 case http_version_minor: 00163 if (input == '\r') 00164 { 00165 state_ = expecting_newline_1; 00166 return boost::indeterminate; 00167 } 00168 else if (is_digit(input)) 00169 { 00170 req.http_version_minor = req.http_version_minor * 10 + input - '0'; 00171 return boost::indeterminate; 00172 } 00173 else 00174 { 00175 return false; 00176 } 00177 case expecting_newline_1: 00178 if (input == '\n') 00179 { 00180 state_ = header_line_start; 00181 return boost::indeterminate; 00182 } 00183 else 00184 { 00185 return false; 00186 } 00187 case header_line_start: 00188 if (input == '\r') 00189 { 00190 state_ = expecting_newline_3; 00191 return boost::indeterminate; 00192 } 00193 else if (!req.headers.empty() && (input == ' ' || input == '\t')) 00194 { 00195 state_ = header_lws; 00196 return boost::indeterminate; 00197 } 00198 else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) 00199 { 00200 return false; 00201 } 00202 else 00203 { 00204 req.headers.push_back(header()); 00205 req.headers.back().name.push_back(input); 00206 state_ = header_name; 00207 return boost::indeterminate; 00208 } 00209 case header_lws: 00210 if (input == '\r') 00211 { 00212 state_ = expecting_newline_2; 00213 return boost::indeterminate; 00214 } 00215 else if (input == ' ' || input == '\t') 00216 { 00217 return boost::indeterminate; 00218 } 00219 else if (is_ctl(input)) 00220 { 00221 return false; 00222 } 00223 else 00224 { 00225 state_ = header_value; 00226 req.headers.back().value.push_back(input); 00227 return boost::indeterminate; 00228 } 00229 case header_name: 00230 if (input == ':') 00231 { 00232 state_ = space_before_header_value; 00233 return boost::indeterminate; 00234 } 00235 else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) 00236 { 00237 return false; 00238 } 00239 else 00240 { 00241 req.headers.back().name.push_back(input); 00242 return boost::indeterminate; 00243 } 00244 case space_before_header_value: 00245 if (input == ' ') 00246 { 00247 state_ = header_value; 00248 return boost::indeterminate; 00249 } 00250 else 00251 { 00252 return false; 00253 } 00254 case header_value: 00255 if (input == '\r') 00256 { 00257 state_ = expecting_newline_2; 00258 return boost::indeterminate; 00259 } 00260 else if (is_ctl(input)) 00261 { 00262 return false; 00263 } 00264 else 00265 { 00266 req.headers.back().value.push_back(input); 00267 return boost::indeterminate; 00268 } 00269 case expecting_newline_2: 00270 if (input == '\n') 00271 { 00272 state_ = header_line_start; 00273 return boost::indeterminate; 00274 } 00275 else 00276 { 00277 return false; 00278 } 00279 case expecting_newline_3: 00280 return (input == '\n'); 00281 default: 00282 return false; 00283 } 00284 } 00285 00286 bool request_parser::is_char(int c) 00287 { 00288 return c >= 0 && c <= 127; 00289 } 00290 00291 bool request_parser::is_ctl(int c) 00292 { 00293 return c >= 0 && c <= 31 || c == 127; 00294 } 00295 00296 bool request_parser::is_tspecial(int c) 00297 { 00298 switch (c) 00299 { 00300 case '(': case ')': case '<': case '>': case '@': 00301 case ',': case ';': case ':': case '\\': case '"': 00302 case '/': case '[': case ']': case '?': case '=': 00303 case '{': case '}': case ' ': case '\t': 00304 return true; 00305 default: 00306 return false; 00307 } 00308 } 00309 00310 bool request_parser::is_digit(int c) 00311 { 00312 return c >= '0' && c <= '9'; 00313 } 00314 00315 } // namespace server 00316 } // namespace http
Copyright © 2003 - 2006 Christopher M. Kohlhoff |