Esempio n. 1
0
void SinkBase::cb_data(mblk_t *m)
{
	uint32_t st = mblk_get_timestamp_info(m);

	mblk_t *fm = dupmsg(m);
	mblk_meta_copy(m, fm);
	MSQueue *queue = post_handle(fm);	// 此处 dupmsg(m) 将不会导致 m 被释放
	bool first = true;

	unsigned char *obuf = 0;
	size_t olen = 0;
	int index = 0;
	size_t off = 0;
	bool key = false;

	while (mblk_t *om = ms_queue_get(queue)) {

		int dlen = size_for(index, om);
		obuf = (unsigned char*)realloc(obuf, off + dlen);
		save_for(index, om, obuf + off);

		if (index == 0)
			key = is_key(index, om);

		index++;
		off += dlen;

		// 处理时间戳回绕
		if (first_frame_) {
			first_frame_ = false;
		}
		else {
			uint32_t delta = st - last_stamp_;

			// 检查,是否乱序,乱序包直接扔掉!
			if (delta > 0x80000000) {
				fprintf(stderr, "??? maybe timestamp confusioned!, curr=%u, last=%u\n", st, last_stamp_);
				return;
			}

			next_stamp_ += delta / payload_freq();
		}

		last_stamp_ = st;

		freemsg(om);
	}

	if (cb_data_ && obuf) {
		cb_data_(opaque_, next_stamp_, obuf, off, key);
	}

	if (obuf) free(obuf);
}
Esempio n. 2
0
int HttpParserImpl::parse(const char* data, uint32_t len)
{
    if(HTTP_READ_DONE == read_state_ || HTTP_READ_ERROR == read_state_) {
        KUMA_WARNTRACE("HttpParser::parse, invalid state="<<read_state_);
        return 0;
    }
    if(HTTP_READ_BODY == read_state_ && !is_chunked_ && !has_content_length_)
    {// return directly, read untill EOF
        total_bytes_read_ += len;
        if(cb_data_) cb_data_(data, len);
        return len;
    }
    const char* pos = data;
    const char* end = data + len;
    ParseState parse_state = parseHttp(pos, end);
    int parsed_len = (int)(pos - data);
    if(PARSE_STATE_DESTROY == parse_state) {
        return parsed_len;
    }
    if(PARSE_STATE_ERROR == parse_state && cb_event_) {
        cb_event_(HTTP_ERROR);
    }
    return parsed_len;
}
Esempio n. 3
0
void WebSocketImpl::onWsData(uint8_t* data, uint32_t len)
{
    if(cb_data_) cb_data_(data, len);
}
Esempio n. 4
0
HttpParserImpl::ParseState HttpParserImpl::parseChunk(const char*& cur_pos, const char* end)
{
    const char* p_line = nullptr;
    const char* p_end = nullptr;
    bool b_line = false;
    while (cur_pos < end)
    {
        switch (chunk_state_)
        {
            case CHUNK_READ_SIZE:
            {
                b_line = getLine(cur_pos, end, p_line, p_end);
                if(!b_line)
                {// need more data, save remain data.
                    if(saveData(cur_pos, end) != KUMA_ERROR_NOERR) {
                        return PARSE_STATE_ERROR;
                    }
                    cur_pos = end;
                    return PARSE_STATE_CONTINUE;
                }
                std::string str;
                if(!str_buf_.empty()) {
                    str.swap(str_buf_);
                    clearBuffer();
                }
                str.append(p_line, p_end);
                // need not parse chunk extension
                chunk_size_ = (uint32_t)strtol(str.c_str(), NULL, 16);
                KUMA_INFOTRACE("HttpParser::parseChunk, chunk_size="<<chunk_size_);
                if(0 == chunk_size_)
                {// chunk completed
                    chunk_state_ = CHUNK_READ_TRAILER;
                } else {
                    chunk_bytes_read_ = 0;
                    chunk_state_ = CHUNK_READ_DATA;
                }
                break;
            }
            case CHUNK_READ_DATA:
            {
                uint32_t cur_len = uint32_t(end - cur_pos);
                if(chunk_size_ - chunk_bytes_read_ <= cur_len) {// data enough
                    const char* notify_data = cur_pos;
                    uint32_t notify_len = chunk_size_ - chunk_bytes_read_;
                    total_bytes_read_ += notify_len;
                    chunk_bytes_read_ = chunk_size_ = 0; // reset
                    chunk_state_ = CHUNK_READ_DATA_CR;
                    cur_pos += notify_len;
                    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;
                } else {// need more data
                    const char* notify_data = cur_pos;
                    total_bytes_read_ += cur_len;
                    chunk_bytes_read_ += cur_len;
                    cur_pos += cur_len;
                    if(cb_data_) cb_data_(notify_data, cur_len);
                    return PARSE_STATE_CONTINUE;
                }
                break;
            }
            case CHUNK_READ_DATA_CR:
            {
                if(*cur_pos != CR) {
                    KUMA_ERRTRACE("HttpParser::parseChunk, can not find data CR");
                    read_state_ = HTTP_READ_ERROR;
                    return PARSE_STATE_ERROR;
                }
                ++cur_pos;
                chunk_state_ = CHUNK_READ_DATA_LF;
                break;
            }
            case CHUNK_READ_DATA_LF:
            {
                if(*cur_pos != LF) {
                    KUMA_ERRTRACE("HttpParser::parseChunk, can not find data LF");
                    read_state_ = HTTP_READ_ERROR;
                    return PARSE_STATE_ERROR;
                }
                ++cur_pos;
                chunk_state_ = CHUNK_READ_SIZE;
                break;
            }
            case CHUNK_READ_TRAILER:
            {
                b_line = getLine(cur_pos, end, p_line, p_end);
                if(b_line) {
                    if(p_line == p_end && bufferEmpty()) {
                        // blank line, http completed
                        read_state_ = HTTP_READ_DONE;
                        onComplete();
                        return PARSE_STATE_DONE;
                    }
                    clearBuffer(); // discard trailer
                } 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;
                }
                break;
            }
        }
    }
    return HTTP_READ_DONE == read_state_?PARSE_STATE_DONE:PARSE_STATE_CONTINUE;
}
Esempio n. 5
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;
}