Beispiel #1
0
int32_t rtmp_core_handle_recv(rtmp_session_t *session)
{
    mem_buf_t            *rbuf;
    uint8_t              *payload;
    rtmp_chunk_header_t   hdr;
    rtmp_chunk_stream_t **old_streams;
    rtmp_chunk_stream_t  *st;
    mem_buf_t            *temp_buf;
    size_t                old_size,recv_len,need_len,copy_len;
    int32_t               rc;

    do {
        rbuf = &session->in_chain->chunk;

        /*read chunk head*/
        payload = rtmp_chunk_read(rbuf,&hdr);
        if (payload == 0) {
            return RTMP_OK;
        }

        /*realloc stream ?*/
        if (hdr.csid >= session->max_streams) {

            old_size = session->max_streams * sizeof(rtmp_chunk_stream_t*);
            old_streams = session->chunk_streams;

            session->chunk_streams = mem_pcalloc(session->pool,
                (hdr.csid + 1) * sizeof(rtmp_chunk_stream_t*));
            if (session->chunk_streams == NULL) {
                rtmp_log(RTMP_LOG_ERR,"alloc failed,csid:[%d]",hdr.csid);
                return RTMP_FAILED;
            }

            session->max_streams = hdr.csid + 1;
            memcpy(session->chunk_streams,old_streams,old_size);
        }

        /*get message info*/
        if (rtmp_core_message_info(session,&hdr) != RTMP_OK) {

            rtmp_log(RTMP_LOG_ERR,"[%d] invalid chunk,csid:[%d]",
                session->sid,hdr.csid);
            return RTMP_FAILED;
        }

        st = session->chunk_streams[hdr.csid];
        if (st == NULL) {
            st = mem_pcalloc(session->pool,sizeof(rtmp_chunk_stream_t));
            if (st == NULL) {
                rtmp_log(RTMP_LOG_ERR,"alloc failed,csid:[%d]",hdr.csid);
                return RTMP_FAILED;
            }
            session->chunk_streams[hdr.csid] = st;
        }

        if (st->recvlen == 0) {
            st->hdr = hdr;
        }

        /*an entire chunk ?*/
        recv_len = rbuf->last - payload ;

        if ((recv_len >= session->in_chunk_size)
         || (recv_len + st->recvlen >= st->hdr.msglen))
        {
            if (st->chain == NULL) {
                st->chain = st->last = session->in_chain;
            } else {
                st->last->next = session->in_chain;
                st->last = session->in_chain;
            }

            rtmp_log(RTMP_LOG_DEBUG,"[%d]get a chunk",session->sid);
            rtmp_core_update_chunk_time(session,&hdr);

            session->in_chain = rtmp_core_alloc_chain(session,
                session->c->pool,session->in_chunk_size);

            if (session->in_chain == NULL) {
                rtmp_log(RTMP_LOG_ERR,"[%d]alloc link failed,csid:[%d]",
                    session->sid,hdr.csid);
                return RTMP_FAILED;
            }

            temp_buf = &session->in_chain->chunk;
            need_len = st->hdr.msglen - st->recvlen;

            copy_len = recv_len - rtmp_min(
                rtmp_min(session->in_chunk_size,recv_len),need_len);
            st->recvlen += recv_len - copy_len;
            rbuf->last -= copy_len;

            /*copy left*/
            if (copy_len != 0) {
                memcpy(temp_buf->buf,rbuf->last,copy_len);
                temp_buf->last = temp_buf->buf + copy_len;
            }

            /*remove chunk head*/
            st->last->chunk.buf = payload;

            /*an entire message ?*/
            if (st->recvlen == st->hdr.msglen) {
				/*
				[2015-08-10 14:50:45][info][5][0]get a message:[0]:[20]:[99]
string "connect"
double 1.000000
object: [
[app] : string "live_server"
[type] : string "nonprivate"
[tcUrl] : string "rtmp://localhost/live_server"
[] : ]

				*/
                rtmp_log(RTMP_LOG_INFO,"[%d][%d]get a message:[%d]:[%d]:[%d]",
                    session->sid,session->chunk_time,st->hdr.msgsid,
                    st->hdr.msgtid,st->hdr.msglen);

                st->hdr.chunk_time = session->chunk_time;
                rc = rtmp_core_handle_message(session,&st->hdr,st->chain);

                if (rc != RTMP_OK) {
                    rtmp_log(RTMP_LOG_ERR,"[%d]message (%d)(%d) handler "
                        "failed:[%d]",session->sid,st->hdr.csid,
                        st->hdr.msgtid,rc);

                    return RTMP_FAILED;
                }

                st->recvlen = 0;
                rtmp_core_free_chains(session,session->c->pool,st->chain);
                st->chain = st->last = 0;

                continue;
            }
        }

        break;
    } while (1);

    return RTMP_OK;
}
Beispiel #2
0
int rtmp_server_input(struct rtmp_server_t* ctx, const uint8_t* data, size_t bytes)
{
	int r;
	size_t n;
	const uint8_t* p;

	p = data;
	while (bytes > 0)
	{
		switch (ctx->handshake_state)
		{
		case RTMP_HANDSHAKE_UNINIT: // C0: version
			ctx->handshake_state = RTMP_HANDSHAKE_0;
			ctx->handshake_bytes = 0; // clear buffer
			assert(*p <= RTMP_VERSION);
			bytes -= 1;
			p += 1;
			break;

		case RTMP_HANDSHAKE_0: // C1: 4-time + 4-zero + 1528-random
			assert(RTMP_HANDSHAKE_SIZE > ctx->handshake_bytes);
			n = RTMP_HANDSHAKE_SIZE - ctx->handshake_bytes;
			n = n <= bytes ? n : bytes;
			memcpy(ctx->payload + ctx->handshake_bytes, p, n);
			ctx->handshake_bytes += n;
			bytes -= n;
			p += n;

			if (ctx->handshake_bytes == RTMP_HANDSHAKE_SIZE)
			{
				ctx->handshake_state = RTMP_HANDSHAKE_1;
				ctx->handshake_bytes = 0; // clear buffer
				r = rtmp_server_send_handshake(ctx);
				if(0 != r) return r;
			}
			break;

		case RTMP_HANDSHAKE_1: // C2: 4-time + 4-time2 + 1528-echo
			assert(RTMP_HANDSHAKE_SIZE > ctx->handshake_bytes);
			n = RTMP_HANDSHAKE_SIZE - ctx->handshake_bytes;
			n = n <= bytes ? n : bytes;
			memcpy(ctx->payload + ctx->handshake_bytes, p, n);
			ctx->handshake_bytes += n;
			bytes -= n;
			p += n;

			if (ctx->handshake_bytes == RTMP_HANDSHAKE_SIZE)
			{
				ctx->handshake_state = RTMP_HANDSHAKE_2;
				ctx->handshake_bytes = 0; // clear buffer
			}
			break;

		case RTMP_HANDSHAKE_2:
		default:
			return rtmp_chunk_read(&ctx->rtmp, (const uint8_t*)p, bytes);
		}
	}

	return 0;
}