int SrsHandshakeBytes::create_s0s1s2(const char* c1) { int ret = ERROR_SUCCESS; if (s0s1s2) { return ret; } s0s1s2 = new char[3073]; srs_random_generate(s0s1s2, 3073); // plain text required. SrsStream stream; if ((ret = stream.initialize(s0s1s2, 9)) != ERROR_SUCCESS) { return ret; } stream.write_1bytes(0x03); stream.write_4bytes(::time(NULL)); // s2 time2 copy from c1 if (c0c1) { stream.write_bytes(c0c1 + 1, 4); } // if c1 specified, copy c1 to s2. // @see: https://github.com/winlinvip/simple-rtmp-server/issues/46 if (c1) { memcpy(s0s1s2 + 1537, c1, 1536); } return ret; }
srs_amf0_t srs_amf0_parse(char* data, int size, int* nparsed) { int ret = ERROR_SUCCESS; srs_amf0_t amf0 = NULL; SrsStream stream; if ((ret = stream.initialize(data, size)) != ERROR_SUCCESS) { return amf0; } SrsAmf0Any* any = NULL; if ((ret = SrsAmf0Any::discovery(&stream, &any)) != ERROR_SUCCESS) { return amf0; } stream.reset(); if ((ret = any->read(&stream)) != ERROR_SUCCESS) { srs_freep(any); return amf0; } *nparsed = stream.pos(); amf0 = (srs_amf0_t)any; return amf0; }
// read/write stream using SrsStream. void __srs_stream_write_4bytes(char* pp, int32_t value) { static SrsStream stream; int ret = stream.initialize(pp, 4); srs_assert(ret == ERROR_SUCCESS); stream.write_4bytes(value); }
/** * test the stream utility, access size */ VOID TEST(KernelStreamTest, StreamSize) { SrsStream s; char data[1024]; EXPECT_TRUE(s.size() == 0); EXPECT_TRUE(ERROR_SUCCESS == s.initialize(data, 1024)); EXPECT_TRUE(s.size() == 1024); }
int32_t __srs_stream_read_4bytes(char* pp) { static SrsStream stream; int ret = stream.initialize(pp, 4); srs_assert(ret == ERROR_SUCCESS); return stream.read_4bytes(); }
/** * test the stream utility, access data */ VOID TEST(KernelStreamTest, StreamData) { SrsStream s; char data[1024]; EXPECT_TRUE(s.data() == NULL); EXPECT_TRUE(ERROR_SUCCESS == s.initialize(data, 1024)); EXPECT_TRUE(s.data() == data); }
int SrsRtpConn::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) { int ret = ERROR_SUCCESS; pprint->elapse(); if (true) { SrsStream stream; if ((ret = stream.initialize(buf, nb_buf)) != ERROR_SUCCESS) { return ret; } SrsRtpPacket pkt; if ((ret = pkt.decode(&stream)) != ERROR_SUCCESS) { srs_error("rtsp: decode rtp packet failed. ret=%d", ret); return ret; } if (pkt.chunked) { if (!cache) { cache = new SrsRtpPacket(); } cache->copy(&pkt); cache->payload->append(pkt.payload->bytes(), pkt.payload->length()); if (!cache->completed && pprint->can_print()) { srs_trace("<- "SRS_CONSTS_LOG_STREAM_CASTER" rtsp: rtp chunked %dB, age=%d, vt=%d/%u, sts=%u/%#x/%#x, paylod=%dB", nb_buf, pprint->age(), cache->version, cache->payload_type, cache->sequence_number, cache->timestamp, cache->ssrc, cache->payload->length() ); return ret; } } else { srs_freep(cache); cache = new SrsRtpPacket(); cache->reap(&pkt); } } if (pprint->can_print()) { srs_trace("<- "SRS_CONSTS_LOG_STREAM_CASTER" rtsp: rtp #%d %dB, age=%d, vt=%d/%u, sts=%u/%u/%#x, paylod=%dB, chunked=%d", stream_id, nb_buf, pprint->age(), cache->version, cache->payload_type, cache->sequence_number, cache->timestamp, cache->ssrc, cache->payload->length(), cache->chunked ); } // always free it. SrsAutoFree(SrsRtpPacket, cache); if ((ret = rtsp->on_rtp_packet(cache, stream_id)) != ERROR_SUCCESS) { srs_error("rtsp: process rtp packet failed. ret=%d", ret); return ret; } return ret; }
/** * test the stream utility, bytes from/to basic types. */ VOID TEST(KernelStreamTest, StreamInitialize) { SrsStream s; char data[1024]; EXPECT_TRUE(ERROR_SUCCESS == s.initialize(data, 1024)); EXPECT_TRUE(ERROR_SUCCESS != s.initialize(NULL, 1024)); EXPECT_TRUE(ERROR_SUCCESS != s.initialize(data, 0)); EXPECT_TRUE(ERROR_SUCCESS != s.initialize(data, -1)); }
int srs_amf0_serialize(srs_amf0_t amf0, char* data, int size) { int ret = ERROR_SUCCESS; SrsAmf0Any* any = (SrsAmf0Any*)amf0; SrsStream stream; if ((ret = stream.initialize(data, size)) != ERROR_SUCCESS) { return ret; } if ((ret = any->write(&stream)) != ERROR_SUCCESS) { return ret; } return ret; }
/** * test the stream utility, write 8bytes */ VOID TEST(KernelStreamTest, StreamWrite8Bytes) { SrsStream s; char data[1024]; EXPECT_TRUE(ERROR_SUCCESS == s.initialize(data, 1024)); s.write_8bytes(0x1011121314151617); s.write_8bytes(0x1819202122232425); s.skip(-1 * s.pos()); EXPECT_EQ(0x10, s.read_1bytes()); s.skip(2); EXPECT_EQ(0x13, s.read_1bytes()); s.skip(5); EXPECT_EQ(0x19, s.read_1bytes()); }
/** * test the stream utility, read 8bytes */ VOID TEST(KernelStreamTest, StreamRead8Bytes) { SrsStream s; char data[1024]; EXPECT_TRUE(ERROR_SUCCESS == s.initialize(data, 1024)); data[0] = 0x01; data[1] = 0x02; data[2] = 0x03; data[3] = 0x04; data[4] = 0x05; data[5] = 0x06; data[6] = 0x07; data[7] = 0x08; data[8] = 0x09; data[9] = 0x0a; data[10] = 0x0b; data[11] = 0x0c; data[12] = 0x0d; data[13] = 0x0e; data[14] = 0x0f; data[15] = 0x10; data[16] = 0x11; data[17] = 0x12; data[18] = 0x13; data[19] = 0x14; EXPECT_EQ(0x0102030405060708, s.read_8bytes()); EXPECT_EQ(0x090a0b0c0d0e0f10, s.read_8bytes()); s.skip(-1 * s.pos()); s.skip(5); EXPECT_EQ(0x060708090a0b0c0d, s.read_8bytes()); }
/** * test the stream utility, read 4bytes */ VOID TEST(KernelStreamTest, StreamRead4Bytes) { SrsStream s; char data[1024]; EXPECT_TRUE(ERROR_SUCCESS == s.initialize(data, 1024)); data[0] = 0x01; data[1] = 0x02; data[2] = 0x03; data[3] = 0x04; data[4] = 0x05; data[5] = 0x06; data[6] = 0x07; data[7] = 0x08; data[8] = 0x09; data[9] = 0x0a; EXPECT_EQ(0x01020304, s.read_4bytes()); EXPECT_EQ(0x05060708, s.read_4bytes()); s.skip(-1 * s.pos()); s.skip(5); EXPECT_EQ(0x06070809, s.read_4bytes()); }
/** * test the stream utility, access require */ VOID TEST(KernelStreamTest, StreamRequire) { SrsStream s; char data[1024]; EXPECT_FALSE(s.require(1)); EXPECT_TRUE(ERROR_SUCCESS == s.initialize(data, 1024)); EXPECT_TRUE(s.require(1)); EXPECT_TRUE(s.require(1024)); s.read_bytes(data, 1000); EXPECT_TRUE(s.require(1)); s.read_bytes(data, 24); EXPECT_FALSE(s.require(1)); }
int SrsSource::on_dvr_request_sh() { int ret = ERROR_SUCCESS; #ifdef SRS_AUTO_DVR // feed the dvr the metadata/sequence header, // when reload to start dvr, dvr will never get the sequence header in stream, // use the SrsSource.on_dvr_request_sh to push the sequence header to DVR. if (cache_metadata) { char* payload = (char*)cache_metadata->payload; int size = (int)cache_metadata->size; SrsStream stream; if ((ret = stream.initialize(payload, size)) != ERROR_SUCCESS) { srs_error("dvr decode metadata stream failed. ret=%d", ret); return ret; } SrsOnMetaDataPacket pkt; if ((ret = pkt.decode(&stream)) != ERROR_SUCCESS) { srs_error("dvr decode metadata packet failed."); return ret; } if ((ret = dvr->on_meta_data(&pkt)) != ERROR_SUCCESS) { srs_error("dvr process onMetaData message failed. ret=%d", ret); return ret; } } if (cache_sh_video && (ret = dvr->on_video(cache_sh_video->copy())) != ERROR_SUCCESS) { srs_error("dvr process video sequence header message failed. ret=%d", ret); return ret; } if (cache_sh_audio && (ret = dvr->on_audio(cache_sh_audio->copy())) != ERROR_SUCCESS) { srs_error("dvr process audio sequence header message failed. ret=%d", ret); return ret; } #endif return ret; }
/** * test the stream utility, write 1bytes */ VOID TEST(KernelStreamTest, StreamWrite1Bytes) { SrsStream s; char data[1024]; EXPECT_TRUE(ERROR_SUCCESS == s.initialize(data, 1024)); s.write_1bytes(0x10); s.write_1bytes(0x11); s.write_1bytes(0x12); s.write_1bytes(0x13); s.skip(-1 * s.pos()); EXPECT_EQ(0x10, s.read_1bytes()); s.skip(2); EXPECT_EQ(0x13, s.read_1bytes()); }
/** * test the stream utility, write bytes */ VOID TEST(KernelStreamTest, StreamWriteBytes) { SrsStream s; char data[1024]; EXPECT_TRUE(ERROR_SUCCESS == s.initialize(data, 1024)); char str[] = { (char)0x10, (char)0x11, (char)0x12, (char)0x13, (char)0x14, (char)0x15, (char)0x16, (char)0x17, (char)0x18, (char)0x19, (char)0x20, (char)0x21 }; s.write_bytes(str, 12); s.skip(-1 * s.pos()); EXPECT_EQ(0x10, s.read_1bytes()); s.skip(2); EXPECT_EQ(0x13, s.read_1bytes()); s.skip(5); EXPECT_EQ(0x19, s.read_1bytes()); }
int SrsHandshakeBytes::create_c0c1() { int ret = ERROR_SUCCESS; if (c0c1) { return ret; } c0c1 = new char[1537]; srs_random_generate(c0c1, 1537); // plain text required. static SrsStream stream; if ((ret = stream.initialize(c0c1, 9)) != ERROR_SUCCESS) { return ret; } stream.write_1bytes(0x03); stream.write_4bytes(::time(NULL)); stream.write_4bytes(0x00); return ret; }
int SrsHandshakeBytes::create_c2() { int ret = ERROR_SUCCESS; if (c2) { return ret; } c2 = new char[1536]; srs_random_generate(c2, 1536); // time SrsStream stream; if ((ret = stream.initialize(c2, 8)) != ERROR_SUCCESS) { return ret; } stream.write_4bytes(::time(NULL)); // c2 time2 copy from s1 if (s0s1s2) { stream.write_bytes(s0s1s2 + 1, 4); } return ret; }
/** * test the stream utility, skip bytes */ VOID TEST(KernelStreamTest, StreamSkip) { SrsStream s; char data[1024]; EXPECT_TRUE(ERROR_SUCCESS == s.initialize(data, 1024)); EXPECT_EQ(0, s.pos()); s.skip(1); EXPECT_EQ(1, s.pos()); s.skip(-1); EXPECT_EQ(0 , s.pos()); }
/** * test the stream utility, access pos */ VOID TEST(KernelStreamTest, StreamPos) { SrsStream s; char data[1024]; EXPECT_TRUE(s.pos() == 0); EXPECT_TRUE(ERROR_SUCCESS == s.initialize(data, 1024)); EXPECT_TRUE(s.pos() == 0); s.read_bytes(data, 1024); EXPECT_TRUE(s.pos() == 1024); }
/** * test the stream utility, access empty */ VOID TEST(KernelStreamTest, StreamEmpty) { SrsStream s; char data[1024]; EXPECT_TRUE(s.empty()); EXPECT_TRUE(ERROR_SUCCESS == s.initialize(data, 1024)); EXPECT_FALSE(s.empty()); s.read_bytes(data, 1024); EXPECT_TRUE(s.empty()); }
/** * test the stream utility, read 1bytes */ VOID TEST(KernelStreamTest, StreamRead1Bytes) { SrsStream s; char data[1024]; EXPECT_TRUE(ERROR_SUCCESS == s.initialize(data, 1024)); data[0] = 0x12; data[99] = 0x13; data[100] = 0x14; data[101] = 0x15; EXPECT_EQ(0x12, s.read_1bytes()); s.skip(-1 * s.pos()); s.skip(100); EXPECT_EQ(0x14, s.read_1bytes()); }
/** * test the stream utility, read string */ VOID TEST(KernelStreamTest, StreamReadString) { SrsStream s; char data[] = "Hello, world!"; EXPECT_TRUE(ERROR_SUCCESS == s.initialize(data, sizeof(data) - 1)); string str = s.read_string(2); EXPECT_STREQ("He", str.c_str()); str = s.read_string(2); EXPECT_STREQ("ll", str.c_str()); s.skip(3); str = s.read_string(6); EXPECT_STREQ("world!", str.c_str()); EXPECT_TRUE(s.empty()); }
/** * test the stream utility, read bytes */ VOID TEST(KernelStreamTest, StreamReadBytes) { SrsStream s; char data[] = "Hello, world!"; EXPECT_TRUE(ERROR_SUCCESS == s.initialize(data, sizeof(data) - 1)); char bytes[64]; s.read_bytes(bytes, 2); bytes[2] = 0; EXPECT_STREQ("He", bytes); s.read_bytes(bytes, 2); bytes[2] = 0; EXPECT_STREQ("ll", bytes); s.skip(3); s.read_bytes(bytes, 6); bytes[6] = 0; EXPECT_STREQ("world!", bytes); EXPECT_TRUE(s.empty()); }
int SrsSource::on_aggregate(SrsMessage* msg) { int ret = ERROR_SUCCESS; SrsStream* stream = aggregate_stream; if ((ret = stream->initialize((char*)msg->payload, msg->size)) != ERROR_SUCCESS) { return ret; } while (!stream->empty()) { if (!stream->require(1)) { ret = ERROR_RTMP_AGGREGATE; srs_error("invalid aggregate message type. ret=%d", ret); return ret; } int8_t type = stream->read_1bytes(); if (!stream->require(3)) { ret = ERROR_RTMP_AGGREGATE; srs_error("invalid aggregate message size. ret=%d", ret); return ret; } int32_t data_size = stream->read_3bytes(); if (data_size < 0) { ret = ERROR_RTMP_AGGREGATE; srs_error("invalid aggregate message size(negative). ret=%d", ret); return ret; } if (!stream->require(3)) { ret = ERROR_RTMP_AGGREGATE; srs_error("invalid aggregate message time. ret=%d", ret); return ret; } int32_t timestamp = stream->read_3bytes(); if (!stream->require(1)) { ret = ERROR_RTMP_AGGREGATE; srs_error("invalid aggregate message time(high). ret=%d", ret); return ret; } int32_t time_h = stream->read_1bytes(); timestamp |= time_h<<24; timestamp &= 0x7FFFFFFF; if (!stream->require(3)) { ret = ERROR_RTMP_AGGREGATE; srs_error("invalid aggregate message stream_id. ret=%d", ret); return ret; } int32_t stream_id = stream->read_3bytes(); if (data_size > 0 && !stream->require(data_size)) { ret = ERROR_RTMP_AGGREGATE; srs_error("invalid aggregate message data. ret=%d", ret); return ret; } // to common message. SrsCommonMessage __o; SrsMessage& o = __o; o.header.message_type = type; o.header.payload_length = data_size; o.header.timestamp_delta = timestamp; o.header.timestamp = timestamp; o.header.stream_id = stream_id; o.header.perfer_cid = msg->header.perfer_cid; if (data_size > 0) { o.size = data_size; o.payload = new char[o.size]; stream->read_bytes(o.payload, o.size); } if (!stream->require(4)) { ret = ERROR_RTMP_AGGREGATE; srs_error("invalid aggregate message previous tag size. ret=%d", ret); return ret; } stream->read_4bytes(); // process parsed message if (o.header.is_audio()) { if ((ret = on_audio(&o)) != ERROR_SUCCESS) { return ret; } } else if (o.header.is_video()) { if ((ret = on_video(&o)) != ERROR_SUCCESS) { return ret; } } } return ret; }
VOID TEST(AMF0Test, ApiAnyAssert) { SrsStream s; SrsAmf0Any* o = NULL; char buf[1024]; memset(buf, 0, sizeof(buf)); EXPECT_EQ(ERROR_SUCCESS, s.initialize(buf, sizeof(buf))); // read any if (true) { s.reset(); s.current()[0] = 0x12; EXPECT_NE(ERROR_SUCCESS, srs_amf0_read_any(&s, &o)); EXPECT_TRUE(NULL == o); srs_freep(o); } // any convert if (true) { o = SrsAmf0Any::str(); SrsAutoFree(SrsAmf0Any, o); EXPECT_TRUE(o->is_string()); } if (true) { o = SrsAmf0Any::number(); SrsAutoFree(SrsAmf0Any, o); EXPECT_TRUE(o->is_number()); } if (true) { o = SrsAmf0Any::boolean(); SrsAutoFree(SrsAmf0Any, o); EXPECT_TRUE(o->is_boolean()); } if (true) { o = SrsAmf0Any::null(); SrsAutoFree(SrsAmf0Any, o); EXPECT_TRUE(o->is_null()); } if (true) { o = SrsAmf0Any::undefined(); SrsAutoFree(SrsAmf0Any, o); EXPECT_TRUE(o->is_undefined()); } if (true) { o = SrsAmf0Any::object(); SrsAutoFree(SrsAmf0Any, o); EXPECT_TRUE(o->is_object()); } if (true) { o = SrsAmf0Any::ecma_array(); SrsAutoFree(SrsAmf0Any, o); EXPECT_TRUE(o->is_ecma_array()); } if (true) { o = SrsAmf0Any::strict_array(); SrsAutoFree(SrsAmf0Any, o); EXPECT_TRUE(o->is_strict_array()); } // empty object if (true) { o = SrsAmf0Any::object(); SrsAutoFree(SrsAmf0Any, o); s.reset(); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(1+3, s.pos()); } // empty ecma array if (true) { o = SrsAmf0Any::ecma_array(); SrsAutoFree(SrsAmf0Any, o); s.reset(); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(1+4+3, s.pos()); } // strict array if (true) { o = SrsAmf0Any::strict_array(); SrsAutoFree(SrsAmf0Any, o); s.reset(); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(1+4, s.pos()); } }
VOID TEST(AMF0Test, ApiAnyIO) { SrsStream s; SrsAmf0Any* o = NULL; char buf[1024]; memset(buf, 0, sizeof(buf)); EXPECT_EQ(ERROR_SUCCESS, s.initialize(buf, sizeof(buf))); // object eof if (true) { s.reset(); s.current()[2] = 0x09; o = SrsAmf0Any::object_eof(); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); EXPECT_EQ(o->total_size(), s.pos()); EXPECT_EQ(3, s.pos()); s.reset(); s.current()[0] = 0x01; EXPECT_NE(ERROR_SUCCESS, o->read(&s)); } if (true) { s.reset(); o = SrsAmf0Any::object_eof(); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); EXPECT_EQ(3, s.pos()); s.skip(-3); EXPECT_EQ(0x09, s.read_3bytes()); } // string if (true) { s.reset(); o = SrsAmf0Any::str("winlin"); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); EXPECT_EQ(2, s.read_1bytes()); EXPECT_EQ(6, s.read_2bytes()); EXPECT_EQ('w', s.current()[0]); EXPECT_EQ('n', s.current()[5]); s.reset(); s.current()[3] = 'x'; EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); EXPECT_EQ(o->total_size(), s.pos()); EXPECT_STREQ("xinlin", o->to_str().c_str()); } // number if (true) { s.reset(); o = SrsAmf0Any::number(10); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); EXPECT_EQ(0, s.read_1bytes()); s.reset(); EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); EXPECT_EQ(o->total_size(), s.pos()); EXPECT_DOUBLE_EQ(10, o->to_number()); } // boolean if (true) { s.reset(); o = SrsAmf0Any::boolean(true); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); EXPECT_EQ(1, s.read_1bytes()); s.reset(); EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); EXPECT_EQ(o->total_size(), s.pos()); EXPECT_TRUE(o->to_boolean()); } if (true) { s.reset(); o = SrsAmf0Any::boolean(false); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); EXPECT_EQ(1, s.read_1bytes()); s.reset(); EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); EXPECT_EQ(o->total_size(), s.pos()); EXPECT_FALSE(o->to_boolean()); } // null if (true) { s.reset(); o = SrsAmf0Any::null(); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); EXPECT_EQ(5, s.read_1bytes()); s.reset(); EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); EXPECT_EQ(o->total_size(), s.pos()); EXPECT_TRUE(o->is_null()); } // undefined if (true) { s.reset(); o = SrsAmf0Any::undefined(); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); EXPECT_EQ(6, s.read_1bytes()); s.reset(); EXPECT_EQ(ERROR_SUCCESS, o->read(&s)); EXPECT_EQ(o->total_size(), s.pos()); EXPECT_TRUE(o->is_undefined()); } // any: string if (true) { s.reset(); o = SrsAmf0Any::str("winlin"); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); SrsAmf0Any* po = NULL; EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); SrsAutoFree(SrsAmf0Any, po); ASSERT_TRUE(po->is_string()); EXPECT_STREQ("winlin", po->to_str().c_str()); } // any: number if (true) { s.reset(); o = SrsAmf0Any::number(10); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); SrsAmf0Any* po = NULL; EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); SrsAutoFree(SrsAmf0Any, po); ASSERT_TRUE(po->is_number()); EXPECT_DOUBLE_EQ(10, po->to_number()); } // any: boolean if (true) { s.reset(); o = SrsAmf0Any::boolean(true); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); SrsAmf0Any* po = NULL; EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); SrsAutoFree(SrsAmf0Any, po); ASSERT_TRUE(po->is_boolean()); EXPECT_TRUE(po->to_boolean()); } // any: null if (true) { s.reset(); o = SrsAmf0Any::null(); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); SrsAmf0Any* po = NULL; EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); SrsAutoFree(SrsAmf0Any, po); ASSERT_TRUE(po->is_null()); } // any: undefined if (true) { s.reset(); o = SrsAmf0Any::undefined(); SrsAutoFree(SrsAmf0Any, o); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(o->total_size(), s.pos()); s.reset(); SrsAmf0Any* po = NULL; EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); SrsAutoFree(SrsAmf0Any, po); ASSERT_TRUE(po->is_undefined()); } // mixed any if (true) { s.reset(); o = SrsAmf0Any::str("winlin"); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); srs_freep(o); o = SrsAmf0Any::number(10); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); srs_freep(o); o = SrsAmf0Any::boolean(true); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); srs_freep(o); o = SrsAmf0Any::null(); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); srs_freep(o); o = SrsAmf0Any::undefined(); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); srs_freep(o); s.reset(); SrsAmf0Any* po = NULL; EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); ASSERT_TRUE(po->is_string()); EXPECT_STREQ("winlin", po->to_str().c_str()); srs_freep(po); EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); ASSERT_TRUE(po->is_number()); EXPECT_DOUBLE_EQ(10, po->to_number()); srs_freep(po); EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); ASSERT_TRUE(po->is_boolean()); EXPECT_TRUE(po->to_boolean()); srs_freep(po); EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); ASSERT_TRUE(po->is_null()); srs_freep(po); EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &po)); ASSERT_TRUE(NULL != po); ASSERT_TRUE(po->is_undefined()); srs_freep(po); } }
// user scenario: coding and decoding with amf0 VOID TEST(AMF0Test, ScenarioMain) { // coded amf0 object int nb_bytes = 0; char* bytes = NULL; // coding data to binaries by amf0 // for example, send connect app response to client. if (true) { // props: object // fmsVer: string // capabilities: number // mode: number // info: object // level: string // code: string // descrption: string // objectEncoding: number // data: array // version: string // srs_sig: string SrsAmf0Object* props = SrsAmf0Any::object(); SrsAutoFree(SrsAmf0Object, props); props->set("fmsVer", SrsAmf0Any::str("FMS/3,5,3,888")); props->set("capabilities", SrsAmf0Any::number(253)); props->set("mode", SrsAmf0Any::number(123)); SrsAmf0Object* info = SrsAmf0Any::object(); SrsAutoFree(SrsAmf0Object, info); info->set("level", SrsAmf0Any::str("info")); info->set("code", SrsAmf0Any::str("NetStream.Connnect.Success")); info->set("descrption", SrsAmf0Any::str("connected")); info->set("objectEncoding", SrsAmf0Any::number(3)); SrsAmf0EcmaArray* data = SrsAmf0Any::ecma_array(); info->set("data", data); data->set("version", SrsAmf0Any::str("FMS/3,5,3,888")); data->set("srs_sig", SrsAmf0Any::str("srs")); // buf store the serialized props/info nb_bytes = props->total_size() + info->total_size(); ASSERT_GT(nb_bytes, 0); bytes = new char[nb_bytes]; // use SrsStream to write props/info to binary buf. SrsStream s; EXPECT_EQ(ERROR_SUCCESS, s.initialize(bytes, nb_bytes)); EXPECT_EQ(ERROR_SUCCESS, props->write(&s)); EXPECT_EQ(ERROR_SUCCESS, info->write(&s)); EXPECT_TRUE(s.empty()); // now, user can use the buf EXPECT_EQ(0x03, bytes[0]); EXPECT_EQ(0x09, bytes[nb_bytes - 1]); } SrsAutoFree(char, bytes); // decoding amf0 object from bytes // when user know the schema if (true) { ASSERT_TRUE(NULL != bytes); // use SrsStream to assist amf0 object to read from bytes. SrsStream s; EXPECT_EQ(ERROR_SUCCESS, s.initialize(bytes, nb_bytes)); // decoding // if user know the schema, for instance, it's an amf0 object, // user can use specified object to decoding. SrsAmf0Object* props = SrsAmf0Any::object(); SrsAutoFree(SrsAmf0Object, props); EXPECT_EQ(ERROR_SUCCESS, props->read(&s)); // user can use specified object to decoding. SrsAmf0Object* info = SrsAmf0Any::object(); SrsAutoFree(SrsAmf0Object, info); EXPECT_EQ(ERROR_SUCCESS, info->read(&s)); // use the decoded data. SrsAmf0Any* prop = NULL; // if user requires specified property, use ensure of amf0 object EXPECT_TRUE(NULL != (prop = props->ensure_property_string("fmsVer"))); // the property can assert to string. ASSERT_TRUE(prop->is_string()); // get the prop string value. EXPECT_STREQ("FMS/3,5,3,888", prop->to_str().c_str()); // get other type property value EXPECT_TRUE(NULL != (prop = info->get_property("data"))); // we cannot assert the property is ecma array if (prop->is_ecma_array()) { SrsAmf0EcmaArray* data = prop->to_ecma_array(); // it must be a ecma array. ASSERT_TRUE(NULL != data); // get property of array EXPECT_TRUE(NULL != (prop = data->ensure_property_string("srs_sig"))); ASSERT_TRUE(prop->is_string()); EXPECT_STREQ("srs", prop->to_str().c_str()); } // confidence about the schema EXPECT_TRUE(NULL != (prop = info->ensure_property_string("level"))); ASSERT_TRUE(prop->is_string()); EXPECT_STREQ("info", prop->to_str().c_str()); } // use any to decoding it, // if user donot know the schema if (true) { ASSERT_TRUE(NULL != bytes); // use SrsStream to assist amf0 object to read from bytes. SrsStream s; EXPECT_EQ(ERROR_SUCCESS, s.initialize(bytes, nb_bytes)); // decoding a amf0 any, for user donot know SrsAmf0Any* any = NULL; EXPECT_EQ(ERROR_SUCCESS, srs_amf0_read_any(&s, &any)); SrsAutoFree(SrsAmf0Any, any); // for amf0 object if (any->is_object()) { SrsAmf0Object* obj = any->to_object(); ASSERT_TRUE(NULL != obj); // use foreach to process properties for (int i = 0; i < obj->count(); ++i) { string name = obj->key_at(i); SrsAmf0Any* value = obj->value_at(i); // use the property name EXPECT_TRUE("" != name); // use the property value EXPECT_TRUE(NULL != value); } } } }
VOID TEST(AMF0Test, ApiStrictArray) { SrsStream s; char buf[1024]; memset(buf, 0, sizeof(buf)); EXPECT_EQ(ERROR_SUCCESS, s.initialize(buf, sizeof(buf))); SrsAmf0StrictArray* o = NULL; // append property if (true) { o = SrsAmf0Any::strict_array(); SrsAutoFree(SrsAmf0StrictArray, o); o->append(SrsAmf0Any::number(100)); EXPECT_DOUBLE_EQ(100, o->at(0)->to_number()); o->append(SrsAmf0Any::number(101)); EXPECT_DOUBLE_EQ(101, o->at(1)->to_number()); o->append(SrsAmf0Any::str("winlin")); EXPECT_STREQ("winlin", o->at(2)->to_str().c_str()); } // count if (true) { o = SrsAmf0Any::strict_array(); SrsAutoFree(SrsAmf0StrictArray, o); EXPECT_EQ(0, o->count()); o->append(SrsAmf0Any::boolean()); EXPECT_EQ(1, o->count()); o->append(SrsAmf0Any::boolean()); EXPECT_EQ(2, o->count()); o->clear(); EXPECT_EQ(0, o->count()); } // io if (true) { o = SrsAmf0Any::strict_array(); SrsAutoFree(SrsAmf0StrictArray, o); s.reset(); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(5, s.pos()); s.reset(); EXPECT_EQ(0x0a, s.read_1bytes()); EXPECT_EQ(0x00, s.read_4bytes()); } if (true) { o = SrsAmf0Any::strict_array(); SrsAutoFree(SrsAmf0StrictArray, o); o->append(SrsAmf0Any::number(0)); s.reset(); EXPECT_EQ(ERROR_SUCCESS, o->write(&s)); EXPECT_EQ(5 + SrsAmf0Size::number(), s.pos()); } }