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; }
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; }