void HttpClient::startRequest(std::string& url) { http_request_.setDataCallback([this] (uint8_t* data, uint32_t len) { onData(data, len); }); http_request_.setWriteCallback([this] (int err) { onSend(err); }); http_request_.setErrorCallback([this] (int err) { onClose(err); }); http_request_.setHeaderCompleteCallback([this] { onHeaderComplete(); }); http_request_.setResponseCompleteCallback([this] { onRequestComplete(); }); http_request_.sendRequest("GET", url.c_str(), "HTTP/1.1"); }
int HttpTest::attachSocket(TcpSocket&& tcp, HttpParser&& parser) { http_.setWriteCallback([this] (int err) { onSend(err); }); http_.setErrorCallback([this] (int err) { onClose(err); }); http_.setDataCallback([this] (uint8_t* data, uint32_t len) { onHttpData(data, len); }); http_.setHeaderCompleteCallback([this] () { onHeaderComplete(); }); http_.setRequestCompleteCallback([this] () { onRequestComplete(); }); http_.setResponseCompleteCallback([this] () { onResponseComplete(); }); return http_.attachSocket(std::move(tcp), std::move(parser)); }
int HttpTest::attachFd(SOCKET_FD fd, uint32_t ssl_flags) { http_.setWriteCallback([this] (int err) { onSend(err); }); http_.setErrorCallback([this] (int err) { onClose(err); }); http_.setDataCallback([this] (uint8_t* data, uint32_t len) { onHttpData(data, len); }); http_.setHeaderCompleteCallback([this] () { onHeaderComplete(); }); http_.setRequestCompleteCallback([this] () { onRequestComplete(); }); http_.setResponseCompleteCallback([this] () { onResponseComplete(); }); http_.setSslFlags(ssl_flags); return http_.attachFd(fd); }
HttpParserImpl::ParseState HttpParserImpl::parseHttp(const char*& cur_pos, const char* end) { const char* line = nullptr; const char* line_end = nullptr; bool b_line = false; if(HTTP_READ_LINE == read_state_) {// try to get status line while ((b_line = getLine(cur_pos, end, line, line_end)) && line == line_end && str_buf_.empty()) ; if(b_line && (line != line_end || !str_buf_.empty())) { if(!parseStartLine(line, line_end)) { read_state_ = HTTP_READ_ERROR; return PARSE_STATE_ERROR; } read_state_ = HTTP_READ_HEAD; } else { // need more data if(saveData(cur_pos, end) != KUMA_ERROR_NOERR) { return PARSE_STATE_ERROR; } cur_pos = end; // all data was consumed return PARSE_STATE_CONTINUE; } } if(HTTP_READ_HEAD == read_state_) { while ((b_line = getLine(cur_pos, end, line, line_end))) { if(line == line_end && bufferEmpty()) {// blank line, header completed onHeaderComplete(); if(paused_) { return PARSE_STATE_CONTINUE; } if(hasBody() && !upgrade_) { read_state_ = HTTP_READ_BODY; } else { read_state_ = HTTP_READ_DONE; onComplete(); return PARSE_STATE_DONE; } break; } parseHeaderLine(line, line_end); } if(HTTP_READ_HEAD == read_state_) {// need more data if(saveData(cur_pos, end) != KUMA_ERROR_NOERR) { return PARSE_STATE_ERROR; } cur_pos = end; // all data was consumed return PARSE_STATE_CONTINUE; } } if(HTTP_READ_BODY == read_state_ && cur_pos < end) {// try to get body if(is_chunked_) { return parseChunk(cur_pos, end); } else { uint32_t cur_len = uint32_t(end - cur_pos); if(has_content_length_ && (content_length_ - total_bytes_read_) <= cur_len) {// data enough const char* notify_data = cur_pos; uint32_t notify_len = content_length_ - total_bytes_read_; cur_pos += notify_len; total_bytes_read_ = content_length_; read_state_ = HTTP_READ_DONE; KUMA_ASSERT(!destroy_flag_ptr_); bool destroyed = false; destroy_flag_ptr_ = &destroyed; if(cb_data_) cb_data_(notify_data, notify_len); if(destroyed) { return PARSE_STATE_DESTROY; } destroy_flag_ptr_ = nullptr; onComplete(); return PARSE_STATE_DONE; } else {// need more data, or read untill EOF const char* notify_data = cur_pos; total_bytes_read_ += cur_len; cur_pos = end; if(cb_data_) cb_data_(notify_data, cur_len); return PARSE_STATE_CONTINUE; } } } return HTTP_READ_DONE == read_state_?PARSE_STATE_DONE:PARSE_STATE_CONTINUE; }