14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/tools/balsa/balsa_frame.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Visual C++ defines _M_IX86_FP as 2 if the /arch:SSE2 compiler option is
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// specified.
9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if !defined(__SSE2__) && _M_IX86_FP == 2
10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#define __SSE2__ 1
11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif
12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h>
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if __SSE2__
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <emmintrin.h>
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // __SSE2__
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utility>
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/port.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h"
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/tools/balsa/balsa_enums.h"
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/tools/balsa/balsa_headers.h"
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/tools/balsa/balsa_visitor_interface.h"
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/tools/balsa/buffer_interface.h"
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/tools/balsa/simple_buffer.h"
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/tools/balsa/split.h"
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/tools/balsa/string_piece_utils.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(COMPILER_MSVC)
35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <intrin.h>
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <string.h>
37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#pragma intrinsic(_BitScanForward)
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
40116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic int ffs(int i) {
41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  unsigned long index;
42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return _BitScanForward(&index, i) ? index + 1 : 0;
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define strncasecmp _strnicmp
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#else
47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <strings.h>
48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Constants holding some header names for headers which can affect the way the
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HTTP message is framed, and so must be processed specially:
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kContentLength[] = "content-length";
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kContentLengthSize = sizeof(kContentLength) - 1;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kTransferEncoding[] = "transfer-encoding";
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kTransferEncodingSize = sizeof(kTransferEncoding) - 1;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaFrame::BalsaFrame()
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : last_char_was_slash_r_(false),
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      saw_non_newline_char_(false),
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_was_space_(true),
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chunk_length_character_extracted_(false),
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_request_(true),
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_was_head_(false),
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_header_length_(16 * 1024),
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_request_uri_length_(2048),
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visitor_(&do_nothing_visitor_),
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chunk_length_remaining_(0),
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_length_remaining_(0),
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_slash_n_loc_(NULL),
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_recorded_slash_n_loc_(NULL),
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_slash_n_idx_(0),
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      term_chars_(0),
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parse_state_(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE),
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_error_(BalsaFrameEnums::NO_ERROR),
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers_(NULL) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BalsaFrame::~BalsaFrame() {}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaFrame::Reset() {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_char_was_slash_r_ = false;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  saw_non_newline_char_ = false;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  start_was_space_ = true;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chunk_length_character_extracted_ = false;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is_request_ = true;               // not reset between messages.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // request_was_head_ = false;        // not reset between messages.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // max_header_length_ = 4096;        // not reset between messages.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // max_request_uri_length_ = 2048;   // not reset between messages.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // visitor_ = &do_nothing_visitor_;  // not reset between messages.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chunk_length_remaining_ = 0;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content_length_remaining_ = 0;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_slash_n_loc_ = NULL;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_recorded_slash_n_loc_ = NULL;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_slash_n_idx_ = 0;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  term_chars_ = 0;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parse_state_ = BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_error_ = BalsaFrameEnums::NO_ERROR;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lines_.clear();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (headers_ != NULL) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headers_->Clear();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BalsaFrameEnums::ParseStateToString(
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BalsaFrameEnums::ParseState error_code) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (error_code) {
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case PARSE_ERROR:
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return "PARSE_ERROR";
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case READING_HEADER_AND_FIRSTLINE:
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "READING_HEADER_AND_FIRSTLINE";
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case READING_CHUNK_LENGTH:
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "READING_CHUNK_LENGTH";
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case READING_CHUNK_EXTENSION:
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "READING_CHUNK_EXTENSION";
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case READING_CHUNK_DATA:
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "READING_CHUNK_DATA";
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case READING_CHUNK_TERM:
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "READING_CHUNK_TERM";
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case READING_LAST_CHUNK_TERM:
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "READING_LAST_CHUNK_TERM";
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case READING_TRAILER:
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "READING_TRAILER";
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case READING_UNTIL_CLOSE:
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "READING_UNTIL_CLOSE";
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case READING_CONTENT:
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "READING_CONTENT";
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MESSAGE_FULLY_READ:
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "MESSAGE_FULLY_READ";
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case NUM_STATES:
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "UNKNOWN_STATE";
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "UNKNOWN_STATE";
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* BalsaFrameEnums::ErrorCodeToString(
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BalsaFrameEnums::ErrorCode error_code) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (error_code) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case NO_ERROR:
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "NO_ERROR";
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case NO_STATUS_LINE_IN_RESPONSE:
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "NO_STATUS_LINE_IN_RESPONSE";
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case NO_REQUEST_LINE_IN_REQUEST:
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "NO_REQUEST_LINE_IN_REQUEST";
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FAILED_TO_FIND_WS_AFTER_RESPONSE_VERSION:
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "FAILED_TO_FIND_WS_AFTER_RESPONSE_VERSION";
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FAILED_TO_FIND_WS_AFTER_REQUEST_METHOD:
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "FAILED_TO_FIND_WS_AFTER_REQUEST_METHOD";
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FAILED_TO_FIND_WS_AFTER_RESPONSE_STATUSCODE:
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "FAILED_TO_FIND_WS_AFTER_RESPONSE_STATUSCODE";
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FAILED_TO_FIND_WS_AFTER_REQUEST_REQUEST_URI:
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "FAILED_TO_FIND_WS_AFTER_REQUEST_REQUEST_URI";
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FAILED_TO_FIND_NL_AFTER_RESPONSE_REASON_PHRASE:
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "FAILED_TO_FIND_NL_AFTER_RESPONSE_REASON_PHRASE";
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FAILED_TO_FIND_NL_AFTER_REQUEST_HTTP_VERSION:
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "FAILED_TO_FIND_NL_AFTER_REQUEST_HTTP_VERSION";
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case FAILED_CONVERTING_STATUS_CODE_TO_INT:
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "FAILED_CONVERTING_STATUS_CODE_TO_INT";
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case REQUEST_URI_TOO_LONG:
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "REQUEST_URI_TOO_LONG";
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case HEADERS_TOO_LONG:
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "HEADERS_TOO_LONG";
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case UNPARSABLE_CONTENT_LENGTH:
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "UNPARSABLE_CONTENT_LENGTH";
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MAYBE_BODY_BUT_NO_CONTENT_LENGTH:
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "MAYBE_BODY_BUT_NO_CONTENT_LENGTH";
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case REQUIRED_BODY_BUT_NO_CONTENT_LENGTH:
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "REQUIRED_BODY_BUT_NO_CONTENT_LENGTH";
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case HEADER_MISSING_COLON:
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "HEADER_MISSING_COLON";
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case INVALID_CHUNK_LENGTH:
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "INVALID_CHUNK_LENGTH";
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CHUNK_LENGTH_OVERFLOW:
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "CHUNK_LENGTH_OVERFLOW";
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CALLED_BYTES_SPLICED_WHEN_UNSAFE_TO_DO_SO:
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "CALLED_BYTES_SPLICED_WHEN_UNSAFE_TO_DO_SO";
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CALLED_BYTES_SPLICED_AND_EXCEEDED_SAFE_SPLICE_AMOUNT:
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "CALLED_BYTES_SPLICED_AND_EXCEEDED_SAFE_SPLICE_AMOUNT";
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MULTIPLE_CONTENT_LENGTH_KEYS:
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "MULTIPLE_CONTENT_LENGTH_KEYS";
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MULTIPLE_TRANSFER_ENCODING_KEYS:
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "MULTIPLE_TRANSFER_ENCODING_KEYS";
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case UNKNOWN_TRANSFER_ENCODING:
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "UNKNOWN_TRANSFER_ENCODING";
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case INVALID_HEADER_FORMAT:
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "INVALID_HEADER_FORMAT";
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case INTERNAL_LOGIC_ERROR:
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "INTERNAL_LOGIC_ERROR";
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case NUM_ERROR_CODES:
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "UNKNOWN_ERROR";
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "UNKNOWN_ERROR";
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Summary:
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     Parses the first line of either a request or response.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     Note that in the case of a detected warning, error_code will be set
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   but the function will not return false.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     Exactly zero or one warning or error (but not both) may be detected
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   by this function.
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     Note that this function will not write the data of the first-line
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   into the header's buffer (that should already have been done elsewhere).
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Pre-conditions:
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     begin != end
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     *begin should be a character which is > ' '. This implies that there
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   is at least one non-whitespace characters between [begin, end).
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   headers is a valid pointer to a BalsaHeaders class.
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     error_code is a valid pointer to a BalsaFrameEnums::ErrorCode value.
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     Entire first line must exist between [begin, end)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     Exactly zero or one newlines -may- exist between [begin, end)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     [begin, end) should exist in the header's buffer.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Side-effects:
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   headers will be modified
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   error_code may be modified if either a warning or error is detected
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns:
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   True if no error (as opposed to warning) is detected.
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   False if an error (as opposed to warning) is detected.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If there is indeed non-whitespace in the line, then the following
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// will take care of this for you:
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  while (*begin <= ' ') ++begin;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  ProcessFirstLine(begin, end, is_request, &headers, &error_code);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParseHTTPFirstLine(const char* begin,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const char* end,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        bool is_request,
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        size_t max_request_uri_length,
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        BalsaHeaders* headers,
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        BalsaFrameEnums::ErrorCode* error_code) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* current = begin;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // HTTP firstlines all have the following structure:
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  LWS         NONWS  LWS    NONWS   LWS    NONWS   NOTCRLF  CRLF
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  [\t \r\n]+ [^\t ]+ [\t ]+ [^\t ]+ [\t ]+ [^\t ]+ [^\r\n]+ "\r\n"
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  ws1        nws1    ws2    nws2    ws3    nws3             ws4
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //  |          [-------)      [-------)      [----------------)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    REQ:     method         request_uri    version
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   RESP:     version        statuscode     reason
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   The first NONWS->LWS component we'll call firstline_a.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   The second firstline_b, and the third firstline_c.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   firstline_a goes from nws1 to (but not including) ws2
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   firstline_b goes from nws2 to (but not including) ws3
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   firstline_c goes from nws3 to (but not including) ws4
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In the code:
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    ws1 == whitespace_1_idx_
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   nws1 == non_whitespace_1_idx_
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    ws2 == whitespace_2_idx_
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   nws2 == non_whitespace_2_idx_
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    ws3 == whitespace_3_idx_
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   nws3 == non_whitespace_3_idx_
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    ws4 == whitespace_4_idx_
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Kill all whitespace (including '\r\n') at the end of the line.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  --end;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*end != '\n') {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *error_code = BalsaFrameEnums::INTERNAL_LOGIC_ERROR;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(DFATAL) << "INTERNAL_LOGIC_ERROR Headers: \n"
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << headers->OriginalHeadersForDebugging();
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (begin < end && *end <= ' ') {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    --end;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(*end != '\n');
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*end == '\n') {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *error_code = BalsaFrameEnums::INTERNAL_LOGIC_ERROR;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(DFATAL) << "INTERNAL_LOGIC_ERROR Headers: \n"
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << headers->OriginalHeadersForDebugging();
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++end;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The two following statements should not be possible.
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (end == begin) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *error_code = BalsaFrameEnums::INTERNAL_LOGIC_ERROR;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(DFATAL) << "INTERNAL_LOGIC_ERROR Headers: \n"
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << headers->OriginalHeadersForDebugging();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // whitespace_1_idx_
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  headers->whitespace_1_idx_ = current - begin;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This loop is commented out as it is never used in current code.  This is
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // true only because we don't begin parsing the headers at all until we've
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // encountered a non whitespace character at the beginning of the stream, at
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // which point we begin our demarcation of header-start.  If we did -not- do
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this (for instance, only looked for [\r\n] instead of (< ' ')), this loop
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // would be necessary for the proper functioning of this parsing.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is left here as this function may (in the future) be refactored out
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of the BalsaFrame class so that it may be shared between code in
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // BalsaFrame and BalsaHeaders (where it would be used in some variant of the
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // set_first_line() function (at which point it would be necessary).
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (*current <= ' ') {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++current;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // non_whitespace_1_idx_
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  headers->non_whitespace_1_idx_ = current - begin;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The first time through, we're guaranteed that the current character
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // won't be a whitespace (else the loop above wouldn't have terminated).
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // That implies that we're guaranteed to get at least one non-whitespace
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // character if we get into this loop at all.
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++current;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (current == end) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers->whitespace_2_idx_ = current - begin;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers->non_whitespace_2_idx_ = current - begin;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers->whitespace_3_idx_ = current - begin;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers->non_whitespace_3_idx_ = current - begin;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers->whitespace_4_idx_ = current - begin;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // FAILED_TO_FIND_WS_AFTER_REQUEST_METHOD   for request
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // FAILED_TO_FIND_WS_AFTER_RESPONSE_VERSION for response
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *error_code =
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<BalsaFrameEnums::ErrorCode>(
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_RESPONSE_VERSION +
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            is_request);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!is_request) {  // FAILED_TO_FIND_WS_AFTER_RESPONSE_VERSION
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto output_exhausted;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (*current > ' ');
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // whitespace_2_idx_
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  headers->whitespace_2_idx_ = current - begin;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++current;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that due to the loop which consumes all of the whitespace
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // at the end of the line, current can never == end while in this function.
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (*current <= ' ');
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // non_whitespace_2_idx_
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  headers->non_whitespace_2_idx_ = current - begin;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++current;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (current == end) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers->whitespace_3_idx_ = current - begin;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers->non_whitespace_3_idx_ = current - begin;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers->whitespace_4_idx_ = current - begin;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // FAILED_TO_FIND_START_OF_REQUEST_REQUEST_URI for request
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // FAILED_TO_FIND_START_OF_RESPONSE_STATUSCODE for response
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *error_code =
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<BalsaFrameEnums::ErrorCode>(
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            BalsaFrameEnums::FAILED_TO_FIND_WS_AFTER_RESPONSE_STATUSCODE
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 + is_request);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto output_exhausted;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (*current > ' ');
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // whitespace_3_idx_
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  headers->whitespace_3_idx_ = current - begin;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++current;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that due to the loop which consumes all of the whitespace
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // at the end of the line, current can never == end while in this function.
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (*current <= ' ');
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // non_whitespace_3_idx_
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  headers->non_whitespace_3_idx_ = current - begin;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  headers->whitespace_4_idx_ = end - begin;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_exhausted:
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that we don't fail the parse immediately when parsing of the
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // firstline fails.  Depending on the protocol type, we may want to accept
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a firstline with only one or two elements, e.g., for HTTP/0.9:
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   GET\r\n
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // or
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   GET /\r\n
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should be parsed without issue (though the visitor should know that
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // parsing the entire line was not exactly as it should be).
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Eventually, these errors may be removed alltogether, as the visitor can
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // detect them on its own by examining the size of the various fields.
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // headers->set_first_line(non_whitespace_1_idx_, current);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_request) {
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((headers->whitespace_3_idx_ - headers->non_whitespace_2_idx_) >
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        max_request_uri_length) {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // For requests, we need at least the method.  We could assume that a
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // blank URI means "/".  If version isn't stated, it should be assumed
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to be HTTP/0.9 by the visitor.
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *error_code = BalsaFrameEnums::REQUEST_URI_TOO_LONG;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headers->parsed_response_code_ = 0;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const char* parsed_response_code_current =
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        begin + headers->non_whitespace_2_idx_;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const char* parsed_response_code_end = begin + headers->whitespace_3_idx_;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const size_t kMaxDiv10 = std::numeric_limits<size_t>::max() / 10;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Convert a string of [0-9]* into an int.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Note that this allows for the conversion of response codes which
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // are outside the bounds of normal HTTP response codes (no checking
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // is done to ensure that these are valid-- they're merely parsed)!
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (parsed_response_code_current < parsed_response_code_end) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (*parsed_response_code_current < '0' ||
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            *parsed_response_code_current > '9') {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *error_code = BalsaFrameEnums::FAILED_CONVERTING_STATUS_CODE_TO_INT;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_t status_code_x_10 = headers->parsed_response_code_ * 10;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint8 c = *parsed_response_code_current - '0';
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((headers->parsed_response_code_ > kMaxDiv10) ||
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (std::numeric_limits<size_t>::max() - status_code_x_10) < c) {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // overflow.
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *error_code = BalsaFrameEnums::FAILED_CONVERTING_STATUS_CODE_TO_INT;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        headers->parsed_response_code_ = status_code_x_10 + c;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ++parsed_response_code_current;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// begin - beginning of the firstline
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// end - end of the firstline
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A precondition for this function is that there is non-whitespace between
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// [begin, end). If this precondition is not met, the function will not perform
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as expected (and bad things may happen, and it will eat your first, second,
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and third unborn children!).
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Another precondition for this function is that [begin, end) includes
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// at most one newline, which must be at the end of the line.
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaFrame::ProcessFirstLine(const char* begin, const char* end) {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BalsaFrameEnums::ErrorCode previous_error = last_error_;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ParseHTTPFirstLine(begin,
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          end,
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          is_request_,
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          max_request_uri_length_,
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          headers_,
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          &last_error_)) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parse_state_ = BalsaFrameEnums::PARSE_ERROR;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    visitor_->HandleHeaderError(this);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (previous_error != last_error_) {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    visitor_->HandleHeaderWarning(this);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_request_) {
450f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    size_t version_length =
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        headers_->whitespace_4_idx_ - headers_->non_whitespace_3_idx_;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    visitor_->ProcessRequestFirstLine(
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        begin + headers_->non_whitespace_1_idx_,
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        headers_->whitespace_4_idx_ - headers_->non_whitespace_1_idx_,
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        begin + headers_->non_whitespace_1_idx_,
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        headers_->whitespace_2_idx_ - headers_->non_whitespace_1_idx_,
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        begin + headers_->non_whitespace_2_idx_,
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        headers_->whitespace_3_idx_ - headers_->non_whitespace_2_idx_,
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        begin + headers_->non_whitespace_3_idx_,
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        version_length);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (version_length == 0)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parse_state_ = BalsaFrameEnums::MESSAGE_FULLY_READ;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    visitor_->ProcessResponseFirstLine(
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        begin + headers_->non_whitespace_1_idx_,
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        headers_->whitespace_4_idx_ - headers_->non_whitespace_1_idx_,
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        begin + headers_->non_whitespace_1_idx_,
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        headers_->whitespace_2_idx_ - headers_->non_whitespace_1_idx_,
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        begin + headers_->non_whitespace_2_idx_,
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        headers_->whitespace_3_idx_ - headers_->non_whitespace_2_idx_,
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        begin + headers_->non_whitespace_3_idx_,
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        headers_->whitespace_4_idx_ - headers_->non_whitespace_3_idx_);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'stream_begin' points to the first character of the headers buffer.
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'line_begin' points to the first character of the line.
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'current' points to a char which is ':'.
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'line_end' points to the position of '\n' + 1.
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'line_begin' points to the position of first character of line.
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaFrame::CleanUpKeyValueWhitespace(
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* stream_begin,
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* line_begin,
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* current,
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* line_end,
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HeaderLineDescription* current_header_line) {
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* colon_loc = current;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LT(colon_loc, line_end);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(':', *colon_loc);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(':', *current);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(' ', *line_end)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    << "\"" << std::string(line_begin, line_end) << "\"";
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(fenix): Investigate whether or not the bounds tests in the
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // while loops here are redundant, and if so, remove them.
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  --current;
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (current > line_begin && *current <= ' ') --current;
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current += (current != colon_loc);
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_header_line->key_end_idx = current - stream_begin;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current = colon_loc;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(':', *current);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++current;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (current < line_end && *current <= ' ') ++current;
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  current_header_line->value_begin_idx = current - stream_begin;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(current_header_line->key_end_idx,
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            current_header_line->first_char_idx);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(current_header_line->value_begin_idx,
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            current_header_line->key_end_idx);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(current_header_line->last_char_idx,
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            current_header_line->value_begin_idx);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void BalsaFrame::FindColonsAndParseIntoKeyValue() {
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!lines_.empty());
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* stream_begin = headers_->OriginalHeaderStreamBegin();
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The last line is always just a newline (and is uninteresting).
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Lines::size_type lines_size_m1 = lines_.size() - 1;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if __SSE2__
521116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const __m128i colons = _mm_set1_epi8(':');
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* header_lines_end_m16 = headers_->OriginalHeaderStreamEnd() - 16;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // __SSE2__
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* current = stream_begin + lines_[1].first;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This code is a bit more subtle than it may appear at first glance.
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This code looks for a colon in the current line... but it also looks
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // beyond the current line. If there is no colon in the current line, then
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for each subsequent line (until the colon which -has- been found is
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // associated with a line), no searching for a colon will be performed. In
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this way, we minimize the amount of bytes we have scanned for a colon.
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (Lines::size_type i = 1; i < lines_size_m1;) {
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* line_begin = stream_begin + lines_[i].first;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Here we handle possible continuations.  Note that we do not replace
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the '\n' in the line before a continuation (at least, as of now),
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // which implies that any code which looks for a value must deal with
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "\r\n", etc -within- the line (and not just at the end of it).
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (++i; i < lines_size_m1; ++i) {
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const char c = *(stream_begin + lines_[i].first);
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (c > ' ') {
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Not a continuation, so stop.  Note that if the 'original' i = 1,
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // and the next line is not a continuation, we'll end up with i = 2
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // when we break. This handles the incrementing of i for the outer
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // loop.
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* line_end = stream_begin + lines_[i - 1].second;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LT(line_begin - stream_begin, line_end - stream_begin);
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We cleanup the whitespace at the end of the line before doing anything
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // else of interest as it allows us to do nothing when irregularly formatted
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // headers are parsed (e.g. those with only keys, only values, or no colon).
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're guaranteed to have *line_end > ' ' while line_end >= line_begin.
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    --line_end;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ('\n', *line_end)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "\"" << std::string(line_begin, line_end) << "\"";
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (*line_end <= ' ' && line_end > line_begin) {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      --line_end;
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++line_end;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_GE(' ', *line_end);
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LT(line_begin, line_end);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We use '0' for the block idx, because we're always writing to the first
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // block from the framer (we do this because the framer requires that the
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // entire header sequence be in a contiguous buffer).
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headers_->header_lines_.push_back(
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        HeaderLineDescription(line_begin - stream_begin,
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              line_end - stream_begin,
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              line_end - stream_begin,
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              line_end - stream_begin,
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              0));
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (current >= line_end) {
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_error_ = BalsaFrameEnums::HEADER_MISSING_COLON;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visitor_->HandleHeaderWarning(this);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Then the next colon will not be found within this header line-- time
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // to try again with another header-line.
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (current < line_begin) {
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // When this condition is true, the last detected colon was part of a
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // previous line.  We reset to the beginning of the line as we don't care
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // about the presence of any colon before the beginning of the current
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // line.
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      current = line_begin;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if __SSE2__
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (current < header_lines_end_m16) {
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      __m128i header_bytes =
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        _mm_loadu_si128(reinterpret_cast<const __m128i *>(current));
592116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      __m128i colon_cmp = _mm_cmpeq_epi8(header_bytes, colons);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int colon_msk = _mm_movemask_epi8(colon_cmp);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (colon_msk == 0) {
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        current += 16;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      current += (ffs(colon_msk) - 1);
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (current > line_end) {
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto found_colon;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // __SSE2__
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (; current < line_end; ++current) {
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (*current != ':') {
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto found_colon;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we've gotten to here, then there was no colon
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // in the line. The arguments we passed into the construction
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // for the HeaderLineDescription object should be OK-- it assumes
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // that the entire content is 'key' by default (which is true, as
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // there was no colon, there can be no value). Note that this is a
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // construct which is technically not allowed by the spec.
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_error_ = BalsaFrameEnums::HEADER_MISSING_COLON;
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    visitor_->HandleHeaderWarning(this);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    continue;
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found_colon:
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(*current, ':');
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LE(current - stream_begin, line_end - stream_begin);
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LE(stream_begin - stream_begin, current - stream_begin);
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HeaderLineDescription& current_header_line = headers_->header_lines_.back();
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_header_line.key_end_idx = current - stream_begin;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_header_line.value_begin_idx = current_header_line.key_end_idx;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (current < line_end) {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++current_header_line.key_end_idx;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CleanUpKeyValueWhitespace(stream_begin,
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                line_begin,
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                current,
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                line_end,
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                &current_header_line);
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaFrame::ProcessContentLengthLine(
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HeaderLines::size_type line_idx,
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BalsaHeadersEnums::ContentLengthStatus* status,
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t* length) {
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HeaderLineDescription& header_line = headers_->header_lines_[line_idx];
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* stream_begin = headers_->OriginalHeaderStreamBegin();
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* line_end = stream_begin + header_line.last_char_idx;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* value_begin = (stream_begin + header_line.value_begin_idx);
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (value_begin >= line_end) {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // There is no non-whitespace value data.
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if DEBUGFRAMER
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(INFO) << "invalid content-length -- no non-whitespace value data";
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *status = BalsaHeadersEnums::INVALID_CONTENT_LENGTH;
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *length = 0;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (value_begin < line_end) {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*value_begin < '0' || *value_begin > '9') {
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // bad! content-length found, and couldn't parse all of it!
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *status = BalsaHeadersEnums::INVALID_CONTENT_LENGTH;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if DEBUGFRAMER
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(INFO) << "invalid content-length - non numeric character detected";
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // DEBUGFRAMER
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t kMaxDiv10 = std::numeric_limits<size_t>::max() / 10;
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t length_x_10 = *length * 10;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const unsigned char c = *value_begin - '0';
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*length > kMaxDiv10 ||
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (std::numeric_limits<size_t>::max() - length_x_10) < c) {
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *status = BalsaHeadersEnums::CONTENT_LENGTH_OVERFLOW;
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if DEBUGFRAMER
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(INFO) << "content-length overflow";
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // DEBUGFRAMER
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *length = length_x_10 + c;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++value_begin;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if DEBUGFRAMER
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "content_length parsed: " << *length;
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // DEBUGFRAMER
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *status = BalsaHeadersEnums::VALID_CONTENT_LENGTH;
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaFrame::ProcessTransferEncodingLine(HeaderLines::size_type line_idx) {
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const HeaderLineDescription& header_line = headers_->header_lines_[line_idx];
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* stream_begin = headers_->OriginalHeaderStreamBegin();
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* line_end = stream_begin + header_line.last_char_idx;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* value_begin = stream_begin + header_line.value_begin_idx;
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t value_length = line_end - value_begin;
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((value_length == 7) &&
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !strncasecmp(value_begin, "chunked", 7)) {
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headers_->transfer_encoding_is_chunked_ = true;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if ((value_length == 8) &&
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !strncasecmp(value_begin, "identity", 8)) {
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headers_->transfer_encoding_is_chunked_ = false;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_error_ = BalsaFrameEnums::UNKNOWN_TRANSFER_ENCODING;
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parse_state_ = BalsaFrameEnums::PARSE_ERROR;
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    visitor_->HandleHeaderError(this);
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SplitStringPiece(base::StringPiece original, char delim,
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      base::StringPiece* before, base::StringPiece* after) {
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* p = original.data();
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* end = p + original.size();
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (p != end) {
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*p == delim) {
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++p;
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const char* start = p;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (++p != end && *p != delim) {
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Skip to the next occurence of the delimiter.
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *before = base::StringPiece(start, p - start);
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (p != end)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *after = base::StringPiece(p + 1, end - (p + 1));
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *after = base::StringPiece("");
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      StringPieceUtils::RemoveWhitespaceContext(before);
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      StringPieceUtils::RemoveWhitespaceContext(after);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *before = original;
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *after = "";
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(phython): Fix this function to properly deal with quoted values.
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// E.g. ";;foo", "\";;\"", or \"aa;
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The last example, the semi-colon is a separator between extensions.
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProcessChunkExtensionsManual(base::StringPiece all_extensions,
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  BalsaHeaders* extensions) {
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece extension;
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece remaining;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringPieceUtils::RemoveWhitespaceContext(&all_extensions);
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SplitStringPiece(all_extensions, ';', &extension, &remaining);
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!extension.empty()) {
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringPiece key;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringPiece value;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SplitStringPiece(extension, '=', &key, &value);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!value.empty()) {
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Strip quotation marks if they exist.
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!value.empty() && value[0] == '"')
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value.remove_prefix(1);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!value.empty() && value[value.length() - 1] == '"')
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value.remove_suffix(1);
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions->AppendHeader(key, value);
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StringPieceUtils::RemoveWhitespaceContext(&remaining);
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SplitStringPiece(remaining, ';', &extension, &remaining);
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // anonymous namespace
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaFrame::ProcessChunkExtensions(const char* input, size_t size,
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        BalsaHeaders* extensions) {
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessChunkExtensionsManual(base::StringPiece(input, size), extensions);
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaFrame::ProcessHeaderLines() {
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeaderLines::size_type content_length_idx = 0;
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeaderLines::size_type transfer_encoding_idx = 0;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!lines_.empty());
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if DEBUGFRAMER
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "******@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@**********\n";
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // DEBUGFRAMER
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There is no need to attempt to process headers if no header lines exist.
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There are at least two lines in the message which are not header lines.
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These two non-header lines are the first line of the message, and the
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // last line of the message (which is an empty line).
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Thus, we test to see if we have more than two lines total before attempting
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to parse any header lines.
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (lines_.size() > 2) {
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* stream_begin = headers_->OriginalHeaderStreamBegin();
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Then, for the rest of the header data, we parse these into key-value
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // pairs.
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FindColonsAndParseIntoKeyValue();
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // At this point, we've parsed all of the headers.  Time to look for those
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // headers which we require for framing.
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HeaderLines::size_type
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      header_lines_size = headers_->header_lines_.size();
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (HeaderLines::size_type i = 0; i < header_lines_size; ++i) {
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const HeaderLineDescription& current_header_line =
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        headers_->header_lines_[i];
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const char* key_begin =
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (stream_begin + current_header_line.first_char_idx);
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const char* key_end = (stream_begin + current_header_line.key_end_idx);
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const size_t key_len = key_end - key_begin;
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const char c = *key_begin;
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if DEBUGFRAMER
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(INFO) << "[" << i << "]: " << std::string(key_begin, key_len)
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << " c: '" << c << "' key_len: " << key_len;
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // DEBUGFRAMER
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If a header begins with either lowercase or uppercase 'c' or 't', then
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the header may be one of content-length, connection, content-encoding
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // or transfer-encoding. These headers are special, as they change the way
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // that the message is framed, and so the framer is required to search
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // for them.
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (c == 'c' || c == 'C') {
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((key_len == kContentLengthSize) &&
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            0 == strncasecmp(key_begin, kContentLength, kContentLengthSize)) {
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          BalsaHeadersEnums::ContentLengthStatus content_length_status =
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            BalsaHeadersEnums::NO_CONTENT_LENGTH;
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          size_t length = 0;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ProcessContentLengthLine(i, &content_length_status, &length);
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (content_length_idx != 0) {  // then we've already seen one!
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if ((headers_->content_length_status_ != content_length_status) ||
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ((headers_->content_length_status_ ==
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  BalsaHeadersEnums::VALID_CONTENT_LENGTH) &&
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 length != headers_->content_length_)) {
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              last_error_ = BalsaFrameEnums::MULTIPLE_CONTENT_LENGTH_KEYS;
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              parse_state_ = BalsaFrameEnums::PARSE_ERROR;
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              visitor_->HandleHeaderError(this);
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              return;
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            continue;
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            content_length_idx = i + 1;
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            headers_->content_length_status_ = content_length_status;
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            headers_->content_length_ = length;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            content_length_remaining_ = length;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (c == 't' || c == 'T') {
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((key_len == kTransferEncodingSize) &&
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            0 == strncasecmp(key_begin, kTransferEncoding,
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kTransferEncodingSize)) {
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (transfer_encoding_idx != 0) {
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            last_error_ = BalsaFrameEnums::MULTIPLE_TRANSFER_ENCODING_KEYS;
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            parse_state_ = BalsaFrameEnums::PARSE_ERROR;
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            visitor_->HandleHeaderError(this);
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return;
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          transfer_encoding_idx = i + 1;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (i == 0 && (key_len == 0 || c == ' ')) {
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_error_ = BalsaFrameEnums::INVALID_HEADER_FORMAT;
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        parse_state_ = BalsaFrameEnums::PARSE_ERROR;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        visitor_->HandleHeaderError(this);
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (headers_->transfer_encoding_is_chunked_) {
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers_->content_length_ = 0;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers_->content_length_status_ = BalsaHeadersEnums::NO_CONTENT_LENGTH;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_length_remaining_ = 0;
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (transfer_encoding_idx != 0) {
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ProcessTransferEncodingLine(transfer_encoding_idx - 1);
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaFrame::AssignParseStateAfterHeadersHaveBeenParsed() {
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For responses, can't have a body if the request was a HEAD, or if it is
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // one of these response-codes.  rfc2616 section 4.3
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parse_state_ = BalsaFrameEnums::MESSAGE_FULLY_READ;
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_request_ ||
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !(request_was_head_ ||
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (headers_->parsed_response_code_ >= 100 &&
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         headers_->parsed_response_code_ < 200) ||
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (headers_->parsed_response_code_ == 204) ||
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (headers_->parsed_response_code_ == 304))) {
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Then we can have a body.
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (headers_->transfer_encoding_is_chunked_) {
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Note that
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // if ( Transfer-Encoding: chunked &&  Content-length: )
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // then Transfer-Encoding: chunked trumps.
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This is as specified in the spec.
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // rfc2616 section 4.4.3
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parse_state_ = BalsaFrameEnums::READING_CHUNK_LENGTH;
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Errors parsing content-length definitely can cause
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // protocol errors/warnings
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (headers_->content_length_status_) {
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If we have a content-length, and it is parsed
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // properly, there are two options.
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // 1) zero content, in which case the message is done, and
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // 2) nonzero content, in which case we have to
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //    consume the body.
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case BalsaHeadersEnums::VALID_CONTENT_LENGTH:
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (headers_->content_length_ == 0) {
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            parse_state_ = BalsaFrameEnums::MESSAGE_FULLY_READ;
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            parse_state_ = BalsaFrameEnums::READING_CONTENT;
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case BalsaHeadersEnums::CONTENT_LENGTH_OVERFLOW:
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case BalsaHeadersEnums::INVALID_CONTENT_LENGTH:
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // If there were characters left-over after parsing the
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // content length, we should flag an error and stop.
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          parse_state_ = BalsaFrameEnums::PARSE_ERROR;
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          last_error_ = BalsaFrameEnums::UNPARSABLE_CONTENT_LENGTH;
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          visitor_->HandleHeaderError(this);
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // We can have: no transfer-encoding, no content length, and no
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // connection: close...
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Unfortunately, this case doesn't seem to be covered in the spec.
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // We'll assume that the safest thing to do here is what the google
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // binaries before 2008 already do, which is to assume that
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // everything until the connection is closed is body.
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        case BalsaHeadersEnums::NO_CONTENT_LENGTH:
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (is_request_) {
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base::StringPiece method = headers_->request_method();
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // POSTs and PUTs should have a detectable body length.  If they
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // do not we consider it an error.
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if ((method.size() == 4 &&
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 strncmp(method.data(), "POST", 4) == 0) ||
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                (method.size() == 3 &&
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 strncmp(method.data(), "PUT", 3) == 0)) {
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              parse_state_ = BalsaFrameEnums::PARSE_ERROR;
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              last_error_ =
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  BalsaFrameEnums::REQUIRED_BODY_BUT_NO_CONTENT_LENGTH;
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              visitor_->HandleHeaderError(this);
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              break;
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            parse_state_ = BalsaFrameEnums::MESSAGE_FULLY_READ;
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            parse_state_ = BalsaFrameEnums::READING_UNTIL_CLOSE;
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            last_error_ = BalsaFrameEnums::MAYBE_BODY_BUT_NO_CONTENT_LENGTH;
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            visitor_->HandleHeaderWarning(this);
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // The COV_NF_... statements here provide hints to the apparatus
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // which computes coverage reports/ratios that this code is never
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // intended to be executed, and should technically be impossible.
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // COV_NF_START
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default:
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          LOG(FATAL) << "Saw a content_length_status: "
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << headers_->content_length_status_ << " which is unknown.";
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // COV_NF_END
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t BalsaFrame::ProcessHeaders(const char* message_start,
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  size_t message_length) {
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* const original_message_start = message_start;
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* const message_end = message_start + message_length;
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* message_current = message_start;
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* checkpoint = message_start;
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message_length == 0) {
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto bottom;
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (message_current < message_end) {
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t base_idx = headers_->GetReadableBytesFromHeaderStream();
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Yes, we could use strchr (assuming null termination), or
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // memchr, but as it turns out that is slower than this tight loop
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // for the input that we see.
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!saw_non_newline_char_) {
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      do {
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const char c = *message_current;
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (c != '\r' && c != '\n') {
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (c <= ' ') {
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            parse_state_ = BalsaFrameEnums::PARSE_ERROR;
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            last_error_ = BalsaFrameEnums::NO_REQUEST_LINE_IN_REQUEST;
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            visitor_->HandleHeaderError(this);
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            goto bottom;
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            saw_non_newline_char_ = true;
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            checkpoint = message_start = message_current;
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            goto read_real_message;
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ++message_current;
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } while (message_current < message_end);
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto bottom;  // this is necessary to skip 'last_char_was_slash_r' checks
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_real_message:
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Note that SSE2 can be enabled on certain piii platforms.
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if __SSE2__
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const char* const message_end_m16 = message_end - 16;
998116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        __m128i newlines = _mm_set1_epi8('\n');
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (message_current < message_end_m16) {
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // What this does (using compiler intrinsics):
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          //
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Load 16 '\n's into an xmm register
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Load 16 bytes of currennt message into an xmm register
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Do byte-wise equals on those two xmm registers
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Take the first bit of each byte, and put that into the first
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          //   16 bits of a mask
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // If the mask is zero, no '\n' found. increment by 16 and try again
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Else scan forward to find the first set bit.
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // Increment current by the index of the first set bit
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          //   (ffs returns index of first set bit + 1)
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          __m128i msg_bytes =
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            _mm_loadu_si128(const_cast<__m128i *>(
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    reinterpret_cast<const __m128i *>(message_current)));
1014116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          __m128i newline_cmp = _mm_cmpeq_epi8(msg_bytes, newlines);
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          int newline_msk = _mm_movemask_epi8(newline_cmp);
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (newline_msk == 0) {
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            message_current += 16;
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            continue;
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          message_current += (ffs(newline_msk) - 1);
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const size_t relative_idx = message_current - message_start;
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const size_t message_current_idx = 1 + base_idx + relative_idx;
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          lines_.push_back(std::make_pair(last_slash_n_idx_,
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          message_current_idx));
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (lines_.size() == 1) {
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            headers_->WriteFromFramer(checkpoint,
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      1 + message_current - checkpoint);
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            checkpoint = message_current + 1;
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            const char* begin = headers_->OriginalHeaderStreamBegin();
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if DEBUGFRAMER
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          LOG(INFO) << "First line " << std::string(begin, lines_[0].second);
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          LOG(INFO) << "is_request_: " << is_request_;
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ProcessFirstLine(begin, begin + lines_[0].second);
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (parse_state_ == BalsaFrameEnums::MESSAGE_FULLY_READ)
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              goto process_lines;
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else if (parse_state_ == BalsaFrameEnums::PARSE_ERROR)
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              goto bottom;
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const size_t chars_since_last_slash_n = (message_current_idx -
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   last_slash_n_idx_);
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          last_slash_n_idx_ = message_current_idx;
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (chars_since_last_slash_n > 2) {
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // We have a slash-n, but the last slash n was
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // more than 2 characters away from this. Thus, we know
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // that this cannot be an end-of-header.
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ++message_current;
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            continue;
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if ((chars_since_last_slash_n == 1) ||
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (((message_current > message_start) &&
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                (*(message_current - 1) == '\r')) ||
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               (last_char_was_slash_r_))) {
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            goto process_lines;
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ++message_current;
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // __SSE2__
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (message_current < message_end) {
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (*message_current != '\n') {
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ++message_current;
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          continue;
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const size_t relative_idx = message_current - message_start;
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const size_t message_current_idx = 1 + base_idx + relative_idx;
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lines_.push_back(std::make_pair(last_slash_n_idx_,
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        message_current_idx));
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (lines_.size() == 1) {
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          headers_->WriteFromFramer(checkpoint,
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    1 + message_current - checkpoint);
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          checkpoint = message_current + 1;
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const char* begin = headers_->OriginalHeaderStreamBegin();
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if DEBUGFRAMER
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          LOG(INFO) << "First line " << std::string(begin, lines_[0].second);
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          LOG(INFO) << "is_request_: " << is_request_;
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ProcessFirstLine(begin, begin + lines_[0].second);
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (parse_state_ == BalsaFrameEnums::MESSAGE_FULLY_READ)
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            goto process_lines;
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          else if (parse_state_ == BalsaFrameEnums::PARSE_ERROR)
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            goto bottom;
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const size_t chars_since_last_slash_n = (message_current_idx -
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 last_slash_n_idx_);
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_slash_n_idx_ = message_current_idx;
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (chars_since_last_slash_n > 2) {
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // false positive.
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ++message_current;
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          continue;
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((chars_since_last_slash_n == 1) ||
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (((message_current > message_start) &&
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              (*(message_current - 1) == '\r')) ||
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             (last_char_was_slash_r_))) {
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          goto process_lines;
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ++message_current;
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    continue;
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) process_lines:
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++message_current;
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(message_current >= message_start);
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (message_current > message_start) {
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers_->WriteFromFramer(checkpoint, message_current - checkpoint);
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check if we have exceeded maximum headers length
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Although we check for this limit before and after we call this function
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we check it here as well to make sure that in case the visitor changed
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the max_header_length_ (for example after processing the first line)
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we handle it gracefully.
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (headers_->GetReadableBytesFromHeaderStream() > max_header_length_) {
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parse_state_ = BalsaFrameEnums::PARSE_ERROR;
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_error_ = BalsaFrameEnums::HEADERS_TOO_LONG;
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visitor_->HandleHeaderError(this);
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto bottom;
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Since we know that we won't be writing any more bytes of the header,
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we tell that to the headers object. The headers object may make
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // more efficient allocation decisions when this is signaled.
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headers_->DoneWritingFromFramer();
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const char* readable_ptr = NULL;
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      size_t readable_size = 0;
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers_->GetReadablePtrFromHeaderStream(&readable_ptr, &readable_size);
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visitor_->ProcessHeaderInput(readable_ptr, readable_size);
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ok, now that we've written everything into our header buffer, it is
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // time to process the header lines (extract proper values for headers
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // which are important for framing).
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProcessHeaderLines();
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (parse_state_ == BalsaFrameEnums::PARSE_ERROR) {
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto bottom;
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AssignParseStateAfterHeadersHaveBeenParsed();
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (parse_state_ == BalsaFrameEnums::PARSE_ERROR) {
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto bottom;
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    visitor_->ProcessHeaders(*headers_);
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    visitor_->HeaderDone();
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (parse_state_ == BalsaFrameEnums::MESSAGE_FULLY_READ) {
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visitor_->MessageDone();
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto bottom;
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we've gotten to here, it means that we've consumed all of the
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // available input. We need to record whether or not the last character we
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // saw was a '\r' so that a subsequent call to ProcessInput correctly finds
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a header framing that is split across the two calls.
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  last_char_was_slash_r_ = (*(message_end - 1) == '\r');
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_current >= message_start);
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message_current > message_start) {
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headers_->WriteFromFramer(checkpoint, message_current - checkpoint);
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bottom:
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return message_current - original_message_start;
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t BalsaFrame::BytesSafeToSplice() const {
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (parse_state_) {
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BalsaFrameEnums::READING_CHUNK_DATA:
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return chunk_length_remaining_;
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BalsaFrameEnums::READING_UNTIL_CLOSE:
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return std::numeric_limits<size_t>::max();
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BalsaFrameEnums::READING_CONTENT:
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return content_length_remaining_;
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BalsaFrame::BytesSpliced(size_t bytes_spliced) {
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (parse_state_) {
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BalsaFrameEnums::READING_CHUNK_DATA:
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (chunk_length_remaining_ >= bytes_spliced) {
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        chunk_length_remaining_ -= bytes_spliced;
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (chunk_length_remaining_ == 0) {
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          parse_state_ = BalsaFrameEnums::READING_CHUNK_TERM;
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_error_ =
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          BalsaFrameEnums::CALLED_BYTES_SPLICED_AND_EXCEEDED_SAFE_SPLICE_AMOUNT;
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto error_exit;
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BalsaFrameEnums::READING_UNTIL_CLOSE:
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case BalsaFrameEnums::READING_CONTENT:
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (content_length_remaining_ >= bytes_spliced) {
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content_length_remaining_ -= bytes_spliced;
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (content_length_remaining_ == 0) {
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          parse_state_ = BalsaFrameEnums::MESSAGE_FULLY_READ;
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          visitor_->MessageDone();
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_error_ =
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          BalsaFrameEnums::CALLED_BYTES_SPLICED_AND_EXCEEDED_SAFE_SPLICE_AMOUNT;
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto error_exit;
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_error_ = BalsaFrameEnums::CALLED_BYTES_SPLICED_WHEN_UNSAFE_TO_DO_SO;
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto error_exit;
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_exit:
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parse_state_ = BalsaFrameEnums::PARSE_ERROR;
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visitor_->HandleBodyError(this);
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// You may note that the state-machine contained within this function has both
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// switch and goto labels for nearly the same thing. For instance, the
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// following two labels refer to the same code block:
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   label_reading_chunk_data:
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   case BalsaFrameEnums::READING_CHUNK_DATA:
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The 'case' statement is required for the switch statement which occurs when
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProcessInput is invoked. The goto label is required as the state-machine
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// does not use a computed goto in any subsequent operations.
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Since several states exit the state machine for various reasons, there is
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// also one label at the bottom of the function. When it is appropriate to
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// return from the function, that part of the state machine instead issues a
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// goto bottom; This results in less code duplication, and makes debugging
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// easier (as you can add a statement to a section of code which is guaranteed
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to be invoked when the function is exiting.
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t BalsaFrame::ProcessInput(const char* input, size_t size) {
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* current = input;
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* on_entry = current;
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* end = current + size;
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if DEBUGFRAMER
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "\n=============="
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << BalsaFrameEnums::ParseStateToString(parse_state_)
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "===============\n";
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // DEBUGFRAMER
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(headers_ != NULL);
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (headers_ == NULL) return 0;
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parse_state_ == BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE) {
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t header_length = headers_->GetReadableBytesFromHeaderStream();
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Yes, we still have to check this here as the user can change the
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // max_header_length amount!
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Also it is possible that we have reached the maximum allowed header size,
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and we have more to consume (remember we are still inside
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // READING_HEADER_AND_FIRSTLINE) in which case we directly declare an error.
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (header_length > max_header_length_ ||
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (header_length == max_header_length_ && size > 0)) {
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parse_state_ = BalsaFrameEnums::PARSE_ERROR;
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_error_ = BalsaFrameEnums::HEADERS_TOO_LONG;
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visitor_->HandleHeaderError(this);
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      goto bottom;
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t bytes_to_process = max_header_length_ - header_length;
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (bytes_to_process > size) {
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bytes_to_process = size;
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current += ProcessHeaders(input, bytes_to_process);
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we are still reading headers check if we have crossed the headers
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // limit. Note that we check for >= as opposed to >. This is because if
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // header_length_after equals max_header_length_ and we are still in the
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // parse_state_  BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE we know for
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // sure that the headers limit will be crossed later on
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (parse_state_ == BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE) {
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Note that headers_ is valid only if we are still reading headers.
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const size_t header_length_after =
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          headers_->GetReadableBytesFromHeaderStream();
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (header_length_after >= max_header_length_) {
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        parse_state_ = BalsaFrameEnums::PARSE_ERROR;
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_error_ = BalsaFrameEnums::HEADERS_TOO_LONG;
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        visitor_->HandleHeaderError(this);
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto bottom;
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (parse_state_ == BalsaFrameEnums::MESSAGE_FULLY_READ ||
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             parse_state_ == BalsaFrameEnums::PARSE_ERROR) {
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Can do nothing more 'till we're reset.
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    goto bottom;
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (current < end) {
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (parse_state_) {
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label_reading_chunk_length:
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case BalsaFrameEnums::READING_CHUNK_LENGTH:
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // In this state we read the chunk length.
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Note that once we hit a character which is not in:
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // [0-9;A-Fa-f\n], we transition to a different state.
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // If we used strtol, etc, we'd have to buffer this line.
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // This is more annoying than simply doing the conversion
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // here. This code accounts for overflow.
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          static const signed char buf[] = {
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // %0  %1  %2  %3  %4  %5  %6  %7  %8  \t  \n  %b  %c  \r  %e  %f
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -1, -1, -2, -1, -1,
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // %10 %11 %12 %13 %14 %15 %16 %17 %18 %19 %1a %1b %1c %1d %1e %1f
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // ' ' %21 %22 %23 %24 %25 %26 %27 %28 %29 %2a %2b %2c %2d %2e %2f
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // %30 %31 %32 %33 %34 %35 %36 %37 %38 %39 %3a ';' %3c %3d %3e %3f
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -2, -1, -1, -1, -1,
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // %40 'A' 'B' 'C' 'D' 'E' 'F' %47 %48 %49 %4a %4b %4c %4d %4e %4f
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // %50 %51 %52 %53 %54 %55 %56 %57 %58 %59 %5a %5b %5c %5d %5e %5f
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // %60 'a' 'b' 'c' 'd' 'e' 'f' %67 %68 %69 %6a %6b %6c %6d %6e %6f
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // %70 %71 %72 %73 %74 %75 %76 %77 %78 %79 %7a %7b %7c %7d %7e %7f
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          };
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // valid cases:
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          //  "09123\n"                      // -> 09123
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          //  "09123\r\n"                    // -> 09123
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          //  "09123  \n"                    // -> 09123
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          //  "09123  \r\n"                  // -> 09123
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          //  "09123  12312\n"               // -> 09123
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          //  "09123  12312\r\n"             // -> 09123
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          //  "09123; foo=bar\n"             // -> 09123
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          //  "09123; foo=bar\r\n"           // -> 09123
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          //  "FFFFFFFFFFFFFFFF\r\n"         // -> FFFFFFFFFFFFFFFF
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          //  "FFFFFFFFFFFFFFFF 22\r\n"      // -> FFFFFFFFFFFFFFFF
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // invalid cases:
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // "[ \t]+[^\n]*\n"
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // "FFFFFFFFFFFFFFFFF\r\n"  (would overflow)
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // "\r\n"
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // "\n"
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          while (current < end) {
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            const char c = *current;
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ++current;
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            const signed char addition = buf[static_cast<int>(c)];
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (addition >= 0) {
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              chunk_length_character_extracted_ = true;
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              size_t length_x_16 = chunk_length_remaining_ * 16;
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              const size_t kMaxDiv16 = std::numeric_limits<size_t>::max() / 16;
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              if ((chunk_length_remaining_ > kMaxDiv16) ||
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  ((std::numeric_limits<size_t>::max() - length_x_16) <
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   static_cast<size_t>(addition))) {
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                // overflow -- asked for a chunk-length greater than 2^64 - 1!!
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                parse_state_ = BalsaFrameEnums::PARSE_ERROR;
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                last_error_ = BalsaFrameEnums::CHUNK_LENGTH_OVERFLOW;
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                visitor_->ProcessBodyInput(on_entry, current - on_entry);
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                visitor_->HandleChunkingError(this);
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                goto bottom;
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              }
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              chunk_length_remaining_ = length_x_16 + addition;
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              continue;
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (!chunk_length_character_extracted_ || addition == -1) {
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              // ^[0-9;A-Fa-f][ \t\n] -- was not matched, either because no
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              // characters were converted, or an unexpected character was
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              // seen.
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              parse_state_ = BalsaFrameEnums::PARSE_ERROR;
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              last_error_ = BalsaFrameEnums::INVALID_CHUNK_LENGTH;
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              visitor_->ProcessBodyInput(on_entry, current - on_entry);
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              visitor_->HandleChunkingError(this);
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              goto bottom;
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            --current;
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            parse_state_ = BalsaFrameEnums::READING_CHUNK_EXTENSION;
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            visitor_->ProcessChunkLength(chunk_length_remaining_);
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            goto label_reading_chunk_extension;
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        visitor_->ProcessBodyInput(on_entry, current - on_entry);
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto bottom;  // case BalsaFrameEnums::READING_CHUNK_LENGTH
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label_reading_chunk_extension:
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case BalsaFrameEnums::READING_CHUNK_EXTENSION:
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // TODO(phython): Convert this scanning to be 16 bytes at a time if
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // there is data to be read.
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const char* extensions_start = current;
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          size_t extensions_length = 0;
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          while (current < end) {
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            const char c = *current;
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == '\r' || c == '\n') {
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              extensions_length =
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  (extensions_start == current) ?
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  0 :
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  current - extensions_start - 1;
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ++current;
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (c == '\n') {
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              chunk_length_character_extracted_ = false;
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              visitor_->ProcessChunkExtensions(
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  extensions_start, extensions_length);
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              if (chunk_length_remaining_ != 0) {
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                parse_state_ = BalsaFrameEnums::READING_CHUNK_DATA;
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                goto label_reading_chunk_data;
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              }
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              HeaderFramingFound('\n');
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              parse_state_ = BalsaFrameEnums::READING_LAST_CHUNK_TERM;
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              goto label_reading_last_chunk_term;
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          visitor_->ProcessChunkExtensions(
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              extensions_start, extensions_length);
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        visitor_->ProcessBodyInput(on_entry, current - on_entry);
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto bottom;  // case BalsaFrameEnums::READING_CHUNK_EXTENSION
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label_reading_chunk_data:
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case BalsaFrameEnums::READING_CHUNK_DATA:
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (current < end) {
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (chunk_length_remaining_ == 0) {
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // read in the chunk
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          size_t bytes_remaining = end - current;
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          size_t consumed_bytes = (chunk_length_remaining_ < bytes_remaining) ?
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            chunk_length_remaining_ : bytes_remaining;
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const char* tmp_current = current + consumed_bytes;
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          visitor_->ProcessBodyInput(on_entry, tmp_current - on_entry);
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          visitor_->ProcessBodyData(current, consumed_bytes);
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          on_entry = current = tmp_current;
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          chunk_length_remaining_ -= consumed_bytes;
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (chunk_length_remaining_ == 0) {
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          parse_state_ = BalsaFrameEnums::READING_CHUNK_TERM;
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          goto label_reading_chunk_term;
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        visitor_->ProcessBodyInput(on_entry, current - on_entry);
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto bottom;  // case BalsaFrameEnums::READING_CHUNK_DATA
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label_reading_chunk_term:
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case BalsaFrameEnums::READING_CHUNK_TERM:
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (current < end) {
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const char c = *current;
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ++current;
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (c == '\n') {
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            parse_state_ = BalsaFrameEnums::READING_CHUNK_LENGTH;
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            goto label_reading_chunk_length;
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        visitor_->ProcessBodyInput(on_entry, current - on_entry);
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto bottom;  // case BalsaFrameEnums::READING_CHUNK_TERM
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label_reading_last_chunk_term:
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case BalsaFrameEnums::READING_LAST_CHUNK_TERM:
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (current < end) {
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const char c = *current;
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!HeaderFramingFound(c)) {
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // If not, however, since the spec only suggests that the
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // client SHOULD indicate the presence of trailers, we get to
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // *test* that they did or didn't.
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // If all of the bytes we've seen since:
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            //   OPTIONAL_WS 0 OPTIONAL_STUFF CRLF
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // are either '\r', or '\n', then we can assume that we don't yet
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // know if we need to parse headers, or if the next byte will make
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // the HeaderFramingFound condition (above) true.
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (HeaderFramingMayBeFound()) {
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              // If true, then we have seen only characters '\r' or '\n'.
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              ++current;
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              // Lets try again! There is no state change here.
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              continue;
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            } else {
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              // If (!HeaderFramingMayBeFound()), then we know that we must be
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              // reading the first non CRLF character of a trailer.
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              parse_state_ = BalsaFrameEnums::READING_TRAILER;
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              visitor_->ProcessBodyInput(on_entry, current - on_entry);
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              on_entry = current;
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              goto label_reading_trailer;
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          } else {
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // If we've found a "\r\n\r\n", then the message
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // is done.
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ++current;
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            parse_state_ = BalsaFrameEnums::MESSAGE_FULLY_READ;
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            visitor_->ProcessBodyInput(on_entry, current - on_entry);
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            visitor_->MessageDone();
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            goto bottom;
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;  // from while loop
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        visitor_->ProcessBodyInput(on_entry, current - on_entry);
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto bottom;  // case BalsaFrameEnums::READING_LAST_CHUNK_TERM
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label_reading_trailer:
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case BalsaFrameEnums::READING_TRAILER:
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (current < end) {
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const char c = *current;
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ++current;
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // TODO(fenix): If we ever care about trailers as part of framing,
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // deal with them here (see below for part of the 'solution')
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // if (LineFramingFound(c)) {
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // trailer_lines_.push_back(make_pair(start_of_line_,
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          //                                   trailer_length_ - 1));
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // start_of_line_ = trailer_length_;
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // }
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (HeaderFramingFound(c)) {
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // ProcessTrailers(visitor_, &trailers_);
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            parse_state_ = BalsaFrameEnums::MESSAGE_FULLY_READ;
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            visitor_->ProcessTrailerInput(on_entry, current - on_entry);
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            visitor_->MessageDone();
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            goto bottom;
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        visitor_->ProcessTrailerInput(on_entry, current - on_entry);
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;  // case BalsaFrameEnums::READING_TRAILER
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Note that there is no label:
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        //   'label_reading_until_close'
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // here. This is because the state-machine exists immediately after
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // reading the headers instead of transitioning here (as it would
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // do if it was consuming all the data it could, all the time).
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case BalsaFrameEnums::READING_UNTIL_CLOSE:
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const size_t bytes_remaining = end - current;
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (bytes_remaining > 0) {
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            visitor_->ProcessBodyInput(current, bytes_remaining);
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            visitor_->ProcessBodyData(current, bytes_remaining);
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            current += bytes_remaining;
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto bottom;  // case BalsaFrameEnums::READING_UNTIL_CLOSE
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // label_reading_content:
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case BalsaFrameEnums::READING_CONTENT:
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if DEBUGFRAMER
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(INFO) << "ReadingContent: " << content_length_remaining_;
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // DEBUGFRAMER
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        while (content_length_remaining_ && current < end) {
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // read in the content
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const size_t bytes_remaining = end - current;
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          const size_t consumed_bytes =
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            (content_length_remaining_ < bytes_remaining) ?
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            content_length_remaining_ : bytes_remaining;
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          visitor_->ProcessBodyInput(current, consumed_bytes);
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          visitor_->ProcessBodyData(current, consumed_bytes);
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          current += consumed_bytes;
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content_length_remaining_ -= consumed_bytes;
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (content_length_remaining_ == 0) {
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          parse_state_ = BalsaFrameEnums::MESSAGE_FULLY_READ;
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          visitor_->MessageDone();
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        goto bottom;  // case BalsaFrameEnums::READING_CONTENT
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The state-machine should never be in a state that isn't handled
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // above.  This is a glaring logic error, and we should do something
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // drastic to ensure that this gets looked-at and fixed.
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(FATAL) << "Unknown state: " << parse_state_  // COV_NF_LINE
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " memory corruption?!";                     // COV_NF_LINE
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bottom:
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if DEBUGFRAMER
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(INFO) << "\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n"
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    << std::string(input, current)
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    << "\n$$$$$$$$$$$$$$"
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    << BalsaFrameEnums::ParseStateToString(parse_state_)
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    << "$$$$$$$$$$$$$$$"
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    << " consumed: " << (current - input);
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (Error()) {
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(INFO) << BalsaFrameEnums::ErrorCodeToString(ErrorCode());
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // DEBUGFRAMER
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return current - input;
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
1577