示例#1
0
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);
}
示例#2
0
void EventLoop::Impl::appendPendingObject(PendingObject *obj)
{
    KUMA_ASSERT(inSameThread());
    if (pending_objects_) {
        obj->next_ = pending_objects_;
        pending_objects_->prev_ = obj;
    }
    pending_objects_ = obj;
}
示例#3
0
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_;
    }
}
示例#4
0
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;
}