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


async_web_server_cpp
Author(s): Mitchell Wills
autogenerated on Thu Aug 27 2015 12:27:39