winlin

refine the protocol, add comments, add utest for empty packet

@@ -497,6 +497,8 @@ int SrsProtocol::do_send_message(SrsMessage* msg, SrsPacket* packet) @@ -497,6 +497,8 @@ int SrsProtocol::do_send_message(SrsMessage* msg, SrsPacket* packet)
497 } 497 }
498 } else { 498 } else {
499 // write no message header chunk stream, fmt is 3 499 // write no message header chunk stream, fmt is 3
  500 + // @remark, if perfer_cid > 0x3F, that is, use 2B/3B chunk header,
  501 + // SRS will rollback to 1B chunk header.
500 *pheader++ = 0xC0 | (msg->header.perfer_cid & 0x3F); 502 *pheader++ = 0xC0 | (msg->header.perfer_cid & 0x3F);
501 503
502 // chunk extended timestamp header, 0 or 4 bytes, big-endian 504 // chunk extended timestamp header, 0 or 4 bytes, big-endian
@@ -550,7 +552,8 @@ int SrsProtocol::do_send_message(SrsMessage* msg, SrsPacket* packet) @@ -550,7 +552,8 @@ int SrsProtocol::do_send_message(SrsMessage* msg, SrsPacket* packet)
550 } 552 }
551 } while (p < (char*)msg->payload + msg->size); 553 } while (p < (char*)msg->payload + msg->size);
552 554
553 - if ((ret = on_send_message(msg, packet)) != ERROR_SUCCESS) { 555 + // only process the callback event when with packet
  556 + if (packet && (ret = on_send_packet(msg, packet)) != ERROR_SUCCESS) {
554 srs_error("hook the send message failed. ret=%d", ret); 557 srs_error("hook the send message failed. ret=%d", ret);
555 return ret; 558 return ret;
556 } 559 }
@@ -1224,7 +1227,7 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz @@ -1224,7 +1227,7 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
1224 */ 1227 */
1225 if (!is_first_chunk_of_msg && chunk_timestamp > 0 && chunk_timestamp != timestamp) { 1228 if (!is_first_chunk_of_msg && chunk_timestamp > 0 && chunk_timestamp != timestamp) {
1226 mh_size -= 4; 1229 mh_size -= 4;
1227 - srs_warn("no 4bytes extended timestamp in the continued chunk"); 1230 + srs_info("no 4bytes extended timestamp in the continued chunk");
1228 } else { 1231 } else {
1229 chunk->header.timestamp = timestamp; 1232 chunk->header.timestamp = timestamp;
1230 } 1233 }
@@ -1251,18 +1254,11 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz @@ -1251,18 +1254,11 @@ int SrsProtocol::read_message_header(SrsChunkStream* chunk, char fmt, int bh_siz
1251 // milliseconds. 1254 // milliseconds.
1252 // in a word, 31bits timestamp is ok. 1255 // in a word, 31bits timestamp is ok.
1253 // convert extended timestamp to 31bits. 1256 // convert extended timestamp to 31bits.
1254 - if (chunk->header.timestamp > 0x7fffffff) {  
1255 - srs_warn("RTMP 31bits timestamp overflow, time=%"PRId64, chunk->header.timestamp);  
1256 - }  
1257 chunk->header.timestamp &= 0x7fffffff; 1257 chunk->header.timestamp &= 0x7fffffff;
1258 1258
1259 - // valid message  
1260 - if (chunk->header.payload_length < 0) {  
1261 - ret = ERROR_RTMP_MSG_INVLIAD_SIZE;  
1262 - srs_error("RTMP message size must not be negative. size=%d, ret=%d",  
1263 - chunk->header.payload_length, ret);  
1264 - return ret;  
1265 - } 1259 + // valid message, the payload_length is 24bits,
  1260 + // so it should never be negative.
  1261 + srs_assert(chunk->header.payload_length >= 0);
1266 1262
1267 // copy header to msg 1263 // copy header to msg
1268 chunk->msg->header = chunk->header; 1264 chunk->msg->header = chunk->header;
@@ -1417,14 +1413,12 @@ int SrsProtocol::on_recv_message(SrsMessage* msg) @@ -1417,14 +1413,12 @@ int SrsProtocol::on_recv_message(SrsMessage* msg)
1417 return ret; 1413 return ret;
1418 } 1414 }
1419 1415
1420 -int SrsProtocol::on_send_message(SrsMessage* msg, SrsPacket* packet) 1416 +int SrsProtocol::on_send_packet(SrsMessage* msg, SrsPacket* packet)
1421 { 1417 {
1422 int ret = ERROR_SUCCESS; 1418 int ret = ERROR_SUCCESS;
1423 1419
1424 - // ignore raw bytes oriented RTMP message.  
1425 - if (!packet) {  
1426 - return ret;  
1427 - } 1420 + // should never be raw bytes oriented RTMP message.
  1421 + srs_assert(packet);
1428 1422
1429 switch (msg->header.message_type) { 1423 switch (msg->header.message_type) {
1430 case RTMP_MSG_SetChunkSize: { 1424 case RTMP_MSG_SetChunkSize: {
@@ -170,6 +170,7 @@ public: @@ -170,6 +170,7 @@ public:
170 * always NULL if error, 170 * always NULL if error,
171 * NULL for unknown packet but return success. 171 * NULL for unknown packet but return success.
172 * never NULL if decode success. 172 * never NULL if decode success.
  173 + * @remark, drop message when msg is empty or payload length is empty.
173 */ 174 */
174 virtual int recv_message(SrsMessage** pmsg); 175 virtual int recv_message(SrsMessage** pmsg);
175 /** 176 /**
@@ -237,7 +238,7 @@ private: @@ -237,7 +238,7 @@ private:
237 /** 238 /**
238 * when message sentout, update the context. 239 * when message sentout, update the context.
239 */ 240 */
240 - virtual int on_send_message(SrsMessage* msg, SrsPacket* packet); 241 + virtual int on_send_packet(SrsMessage* msg, SrsPacket* packet);
241 private: 242 private:
242 /** 243 /**
243 * auto response the ack message. 244 * auto response the ack message.
@@ -4425,3 +4425,41 @@ VOID TEST(ProtocolStackTest, ProtocolRecvVCid3BMax) @@ -4425,3 +4425,41 @@ VOID TEST(ProtocolStackTest, ProtocolRecvVCid3BMax)
4425 EXPECT_EQ(65599, msg->header.perfer_cid); 4425 EXPECT_EQ(65599, msg->header.perfer_cid);
4426 } 4426 }
4427 4427
  4428 +/**
  4429 +* recv a zero length video message.
  4430 +*/
  4431 +VOID TEST(ProtocolStackTest, ProtocolRecvV0LenMessage)
  4432 +{
  4433 + MockBufferIO bio;
  4434 + SrsProtocol proto(&bio);
  4435 +
  4436 + // video message
  4437 + char data[] = {
  4438 + // video #1
  4439 + // 12bytes header, 1byts chunk header, 11bytes msg heder
  4440 + (char)0x03,
  4441 + (char)0x00, (char)0x00, (char)0x00, // timestamp
  4442 + (char)0x00, (char)0x00, (char)0x00, // length
  4443 + (char)0x09, // message_type
  4444 + (char)0x00, (char)0x00, (char)0x00, (char)0x00, // stream_id
  4445 +
  4446 + // video #2
  4447 + // 12bytes header, 1byts chunk header, 11bytes msg heder
  4448 + (char)0x03,
  4449 + (char)0x00, (char)0x00, (char)0x00, // timestamp
  4450 + (char)0x00, (char)0x00, (char)0x04, // length
  4451 + (char)0x09, // message_type
  4452 + (char)0x00, (char)0x00, (char)0x00, (char)0x00, // stream_id
  4453 + // msg payload start
  4454 + (char)0x00, (char)0x00, (char)0x07, (char)0x63
  4455 + };
  4456 + bio.in_buffer.append(data, sizeof(data));
  4457 +
  4458 + SrsMessage* msg = NULL;
  4459 + ASSERT_TRUE(ERROR_SUCCESS == proto.recv_message(&msg));
  4460 + SrsAutoFree(SrsMessage, msg);
  4461 + EXPECT_TRUE(msg->header.is_video());
  4462 + // protocol stack will ignore the empty video message.
  4463 + EXPECT_EQ(4, msg->header.payload_length);
  4464 +}
  4465 +