| 1180 | } |
| 1181 | |
| 1182 | ParseResult ParseHttpMessage(butil::IOBuf *source, Socket *socket, |
| 1183 | bool read_eof, const void* arg) { |
| 1184 | HttpContext* http_imsg = |
| 1185 | static_cast<HttpContext*>(socket->parsing_context()); |
| 1186 | if (http_imsg == NULL) { |
| 1187 | if (read_eof || source->empty()) { |
| 1188 | // 1. read_eof: Read EOF after intact HTTP messages, a common case. |
| 1189 | // Notice that errors except NOT_ENOUGH_DATA can't be returned |
| 1190 | // otherwise the Socket will be SetFailed() and messages just |
| 1191 | // in ProcessHttpXXX() may be dropped. |
| 1192 | // 2. source->empty(): also common, InputMessage tries parse |
| 1193 | // handlers until error is met. If a message was consumed, |
| 1194 | // source is likely to be empty. |
| 1195 | return MakeParseError(PARSE_ERROR_NOT_ENOUGH_DATA); |
| 1196 | } |
| 1197 | http_imsg = new (std::nothrow) HttpContext( |
| 1198 | socket->is_read_progressive(), |
| 1199 | socket->http_request_method()); |
| 1200 | if (http_imsg == NULL) { |
| 1201 | LOG(FATAL) << "Fail to new HttpContext"; |
| 1202 | return MakeParseError(PARSE_ERROR_NO_RESOURCE); |
| 1203 | } |
| 1204 | // Parsing http is costly, parsing an incomplete http message from the |
| 1205 | // beginning repeatedly should be avoided, otherwise the cost may reach |
| 1206 | // O(n^2) in the worst case. Save incomplete http messages in sockets |
| 1207 | // to prevent re-parsing. The message will be released when it is |
| 1208 | // completed or destroyed along with the socket. |
| 1209 | socket->reset_parsing_context(http_imsg); |
| 1210 | } |
| 1211 | ssize_t rc = 0; |
| 1212 | if (read_eof) { |
| 1213 | // Send EOF to HttpContext, check comments in http_message.h |
| 1214 | rc = http_imsg->ParseFromArray(NULL, 0); |
| 1215 | } else { |
| 1216 | // Empty `source' is sliently ignored and 0 is returned, check |
| 1217 | // comments in http_message.h |
| 1218 | rc = http_imsg->ParseFromIOBuf(*source); |
| 1219 | } |
| 1220 | if (http_imsg->is_stage2()) { |
| 1221 | // The header part is already parsed as an intact HTTP message |
| 1222 | // to the ProcessHttpXXX. Here parses the body part. |
| 1223 | if (rc >= 0) { |
| 1224 | source->pop_front(rc); |
| 1225 | if (http_imsg->Completed()) { |
| 1226 | // Already returned the message before, don't return again. |
| 1227 | CHECK_EQ(http_imsg, socket->release_parsing_context()); |
| 1228 | // NOTE: calling http_imsg->Destroy() is wrong which can only |
| 1229 | // be called from ProcessHttpXXX |
| 1230 | http_imsg->RemoveOneRefForStage2(); |
| 1231 | socket->OnProgressiveReadCompleted(); |
| 1232 | return MakeMessage(NULL); |
| 1233 | } else { |
| 1234 | return MakeParseError(PARSE_ERROR_NOT_ENOUGH_DATA); |
| 1235 | } |
| 1236 | } else { |
| 1237 | // Fail to parse the body. Since headers were parsed successfully, |
| 1238 | // the message is assumed to be HTTP, stop trying other protocols. |
| 1239 | const char* err = http_errno_description( |