示例#1
0
std::size_t message::read(std::istream& in,
                          boost::system::error_code& ec,
                          parser& http_parser)
{
    // make sure that we start out with an empty message & clear error_code
    clear();
    ec.clear();
    
    // parse data from file one byte at a time
    boost::tribool parse_result;
    char c;
    while (in) {
        in.read(&c, 1);
        if ( ! in ) {
            ec = make_error_code(boost::system::errc::io_error);
            break;
        }
        http_parser.set_read_buffer(&c, 1);
        parse_result = http_parser.parse(*this, ec);
        if (! boost::indeterminate(parse_result)) break;
    }

    if (boost::indeterminate(parse_result)) {
        if (http_parser.check_premature_eof(*this)) {
            // premature EOF encountered
            if (! ec)
                ec = make_error_code(boost::system::errc::io_error);
        } else {
            // EOF reached when content length unknown
            // assume it is the correct end of content
            // and everything is OK
            parse_result = true;
            ec.clear();
        }
    }
    
    return (http_parser.get_total_bytes_read());
}
示例#2
0
std::size_t message::receive(tcp::connection& tcp_conn,
                             boost::system::error_code& ec,
                             parser& http_parser)
{
    std::size_t last_bytes_read = 0;

    // make sure that we start out with an empty message
    clear();

    if (tcp_conn.get_pipelined()) {
        // there are pipelined messages available in the connection's read buffer
        const char *read_ptr;
        const char *read_end_ptr;
        tcp_conn.load_read_pos(read_ptr, read_end_ptr);
        last_bytes_read = (read_end_ptr - read_ptr);
        http_parser.set_read_buffer(read_ptr, last_bytes_read);
    } else {
        // read buffer is empty (not pipelined) -> read some bytes from the connection
        last_bytes_read = tcp_conn.read_some(ec);
        if (ec) return 0;
        BOOST_ASSERT(last_bytes_read > 0);
        http_parser.set_read_buffer(tcp_conn.get_read_buffer().data(), last_bytes_read);
    }

    // incrementally read and parse bytes from the connection
    bool force_connection_closed = false;
    boost::tribool parse_result;
    while (true) {
        // parse bytes available in the read buffer
        parse_result = http_parser.parse(*this, ec);
        if (! boost::indeterminate(parse_result)) break;

        // read more bytes from the connection
        last_bytes_read = tcp_conn.read_some(ec);
        if (ec || last_bytes_read == 0) {
            if (http_parser.check_premature_eof(*this)) {
                // premature EOF encountered
                if (! ec)
                    ec = make_error_code(boost::system::errc::io_error);
                return http_parser.get_total_bytes_read();
            } else {
                // EOF reached when content length unknown
                // assume it is the correct end of content
                // and everything is OK
                force_connection_closed = true;
                parse_result = true;
                ec.clear();
                break;
            }
            break;
        }

        // update the HTTP parser's read buffer
        http_parser.set_read_buffer(tcp_conn.get_read_buffer().data(), last_bytes_read);
    }
    
    if (parse_result == false) {
        // an error occurred while parsing the message headers
        return http_parser.get_total_bytes_read();
    }

    // set the connection's lifecycle type
    if (!force_connection_closed && check_keep_alive()) {
        if ( http_parser.eof() ) {
            // the connection should be kept alive, but does not have pipelined messages
            tcp_conn.set_lifecycle(tcp::connection::LIFECYCLE_KEEPALIVE);
        } else {
            // the connection has pipelined messages
            tcp_conn.set_lifecycle(tcp::connection::LIFECYCLE_PIPELINED);
            
            // save the read position as a bookmark so that it can be retrieved
            // by a new HTTP parser, which will be created after the current
            // message has been handled
            const char *read_ptr;
            const char *read_end_ptr;
            http_parser.load_read_pos(read_ptr, read_end_ptr);
            tcp_conn.save_read_pos(read_ptr, read_end_ptr);
        }
    } else {
        // default to close the connection
        tcp_conn.set_lifecycle(tcp::connection::LIFECYCLE_CLOSE);
        
        // save the read position as a bookmark so that it can be retrieved
        // by a new HTTP parser
        if (http_parser.get_parse_headers_only()) {
            const char *read_ptr;
            const char *read_end_ptr;
            http_parser.load_read_pos(read_ptr, read_end_ptr);
            tcp_conn.save_read_pos(read_ptr, read_end_ptr);
        }
    }

    return (http_parser.get_total_bytes_read());
}