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


ros_web_video
Author(s): Julius Kammer
autogenerated on Thu Jun 6 2019 21:07:01