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