void WebSocketImpl::onReceive(int err) { if(init_data_ && init_len_ > 0) { bool destroyed = false; KUMA_ASSERT(nullptr == destroy_flag_ptr_); destroy_flag_ptr_ = &destroyed; WSHandler::WSError err = ws_handler_.handleData(init_data_, init_len_); if(destroyed) { return; } destroy_flag_ptr_ = nullptr; delete [] init_data_; init_data_ = nullptr; init_len_ = 0; if(getState() == STATE_ERROR || getState() == STATE_CLOSED) { return; } if(err != WSHandler::WSError::WS_ERROR_NOERR && err != WSHandler::WSError::WS_ERROR_NEED_MORE_DATA) { cleanup(); setState(STATE_CLOSED); if(cb_error_) cb_error_(KUMA_ERROR_FAILED); return; } } uint8_t buf[128*1024]; do { int ret = tcp_socket_.receive(buf, sizeof(buf)); if(ret < 0) { cleanup(); setState(STATE_CLOSED); if(cb_error_) cb_error_(KUMA_ERROR_SOCKERR); } else if(0 == ret) { break; } else if(getState() == STATE_HANDSHAKE || getState() == STATE_OPEN) { bool destroyed = false; KUMA_ASSERT(nullptr == destroy_flag_ptr_); destroy_flag_ptr_ = &destroyed; WSHandler::WSError err = ws_handler_.handleData(buf, ret); if(destroyed) { return; } destroy_flag_ptr_ = nullptr; if(getState() == STATE_ERROR || getState() == STATE_CLOSED) { break; } if(err != WSHandler::WSError::WS_ERROR_NOERR && err != WSHandler::WSError::WS_ERROR_NEED_MORE_DATA) { cleanup(); setState(STATE_CLOSED); if(cb_error_) cb_error_(KUMA_ERROR_FAILED); return; } } else { KUMA_WARNXTRACE("onReceive, invalid state: "<<getState()); } } while(true); }
void EventLoop::Impl::appendPendingObject(PendingObject *obj) { KUMA_ASSERT(inSameThread()); if (pending_objects_) { obj->next_ = pending_objects_; pending_objects_->prev_ = obj; } pending_objects_ = obj; }
void EventLoop::Impl::removePendingObject(PendingObject *obj) { KUMA_ASSERT(inSameThread()); if (pending_objects_ == obj) { pending_objects_ = obj->next_; } if (obj->prev_) { obj->prev_->next_ = obj->next_; } if (obj->next_) { obj->next_->prev_ = obj->prev_; } }
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; }