mirror of
https://github.com/ossrs/srs.git
synced 2025-02-14 20:31:56 +00:00
Fix #1445, limit the createStream recursive depth. 3.0.70
This commit is contained in:
parent
41a9f15626
commit
4f298134af
7 changed files with 327 additions and 9 deletions
|
@ -145,6 +145,7 @@ For previous versions, please read:
|
||||||
|
|
||||||
## V3 changes
|
## V3 changes
|
||||||
|
|
||||||
|
* v3.0, 2019-12-11, Fix [#1445][bug #1445], limit the createStream recursive depth. 3.0.70
|
||||||
* v3.0, 2019-12-11, For [#1042][bug #1042], cover RTMP handshake protocol.
|
* v3.0, 2019-12-11, For [#1042][bug #1042], cover RTMP handshake protocol.
|
||||||
* v3.0, 2019-12-11, Fix [#1229][bug #1229], fix the security risk in logger. 3.0.69
|
* v3.0, 2019-12-11, Fix [#1229][bug #1229], fix the security risk in logger. 3.0.69
|
||||||
* v3.0, 2019-12-11, For [#1229][bug #1229], fix the security risk in HDS. 3.0.69
|
* v3.0, 2019-12-11, For [#1229][bug #1229], fix the security risk in HDS. 3.0.69
|
||||||
|
@ -1515,6 +1516,7 @@ Winlin
|
||||||
[bug #1501]: https://github.com/ossrs/srs/issues/1501
|
[bug #1501]: https://github.com/ossrs/srs/issues/1501
|
||||||
[bug #1229]: https://github.com/ossrs/srs/issues/1229
|
[bug #1229]: https://github.com/ossrs/srs/issues/1229
|
||||||
[bug #1042]: https://github.com/ossrs/srs/issues/1042
|
[bug #1042]: https://github.com/ossrs/srs/issues/1042
|
||||||
|
[bug #1445]: https://github.com/ossrs/srs/issues/1445
|
||||||
[bug #xxxxxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxxxxx
|
[bug #xxxxxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxxxxx
|
||||||
|
|
||||||
[exo #828]: https://github.com/google/ExoPlayer/pull/828
|
[exo #828]: https://github.com/google/ExoPlayer/pull/828
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
// The version config.
|
// The version config.
|
||||||
#define VERSION_MAJOR 3
|
#define VERSION_MAJOR 3
|
||||||
#define VERSION_MINOR 0
|
#define VERSION_MINOR 0
|
||||||
#define VERSION_REVISION 69
|
#define VERSION_REVISION 70
|
||||||
|
|
||||||
// The macros generated by configure script.
|
// The macros generated by configure script.
|
||||||
#include <srs_auto_headers.hpp>
|
#include <srs_auto_headers.hpp>
|
||||||
|
|
|
@ -177,7 +177,8 @@
|
||||||
#define ERROR_HTTP_HIJACK 2052
|
#define ERROR_HTTP_HIJACK 2052
|
||||||
#define ERROR_RTMP_MESSAGE_CREATE 2053
|
#define ERROR_RTMP_MESSAGE_CREATE 2053
|
||||||
#define ERROR_RTMP_PROXY_EXCEED 2054
|
#define ERROR_RTMP_PROXY_EXCEED 2054
|
||||||
//
|
#define ERROR_RTMP_CREATE_STREAM_DEPTH 2055
|
||||||
|
//
|
||||||
// The system control message,
|
// The system control message,
|
||||||
// It's not an error, but special control logic.
|
// It's not an error, but special control logic.
|
||||||
//
|
//
|
||||||
|
|
|
@ -200,9 +200,9 @@ string srs_generate_stream_with_query(string host, string vhost, string stream,
|
||||||
|
|
||||||
// Remove the start & when param is empty.
|
// Remove the start & when param is empty.
|
||||||
srs_string_trim_start(query, "&");
|
srs_string_trim_start(query, "&");
|
||||||
|
|
||||||
// Prefix query with ?.
|
// Prefix query with ?.
|
||||||
if (!srs_string_starts_with(query, "?")) {
|
if (!query.empty() && !srs_string_starts_with(query, "?")) {
|
||||||
url += "?";
|
url += "?";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2538,7 +2538,7 @@ srs_error_t SrsRtmpServer::identify_client(int stream_id, SrsRtmpConnType& type,
|
||||||
SrsAutoFree(SrsPacket, pkt);
|
SrsAutoFree(SrsPacket, pkt);
|
||||||
|
|
||||||
if (dynamic_cast<SrsCreateStreamPacket*>(pkt)) {
|
if (dynamic_cast<SrsCreateStreamPacket*>(pkt)) {
|
||||||
return identify_create_stream_client(dynamic_cast<SrsCreateStreamPacket*>(pkt), stream_id, type, stream_name, duration);
|
return identify_create_stream_client(dynamic_cast<SrsCreateStreamPacket*>(pkt), stream_id, 3, type, stream_name, duration);
|
||||||
}
|
}
|
||||||
if (dynamic_cast<SrsFMLEStartPacket*>(pkt)) {
|
if (dynamic_cast<SrsFMLEStartPacket*>(pkt)) {
|
||||||
return identify_fmle_publish_client(dynamic_cast<SrsFMLEStartPacket*>(pkt), type, stream_name);
|
return identify_fmle_publish_client(dynamic_cast<SrsFMLEStartPacket*>(pkt), type, stream_name);
|
||||||
|
@ -2909,9 +2909,13 @@ srs_error_t SrsRtmpServer::start_flash_publish(int stream_id)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsRtmpServer::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsRtmpConnType& type, string& stream_name, srs_utime_t& duration)
|
srs_error_t SrsRtmpServer::identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, int depth, SrsRtmpConnType& type, string& stream_name, srs_utime_t& duration)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
if (depth <= 0) {
|
||||||
|
return srs_error_new(ERROR_RTMP_CREATE_STREAM_DEPTH, "create stream recursive depth");
|
||||||
|
}
|
||||||
|
|
||||||
if (true) {
|
if (true) {
|
||||||
SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(req->transaction_id, stream_id);
|
SrsCreateStreamResPacket* pkt = new SrsCreateStreamResPacket(req->transaction_id, stream_id);
|
||||||
|
@ -2952,7 +2956,7 @@ srs_error_t SrsRtmpServer::identify_create_stream_client(SrsCreateStreamPacket*
|
||||||
return identify_flash_publish_client(dynamic_cast<SrsPublishPacket*>(pkt), type, stream_name);
|
return identify_flash_publish_client(dynamic_cast<SrsPublishPacket*>(pkt), type, stream_name);
|
||||||
}
|
}
|
||||||
if (dynamic_cast<SrsCreateStreamPacket*>(pkt)) {
|
if (dynamic_cast<SrsCreateStreamPacket*>(pkt)) {
|
||||||
return identify_create_stream_client(dynamic_cast<SrsCreateStreamPacket*>(pkt), stream_id, type, stream_name, duration);
|
return identify_create_stream_client(dynamic_cast<SrsCreateStreamPacket*>(pkt), stream_id, depth-1, type, stream_name, duration);
|
||||||
}
|
}
|
||||||
if (dynamic_cast<SrsFMLEStartPacket*>(pkt)) {
|
if (dynamic_cast<SrsFMLEStartPacket*>(pkt)) {
|
||||||
return identify_haivision_publish_client(dynamic_cast<SrsFMLEStartPacket*>(pkt), type, stream_name);
|
return identify_haivision_publish_client(dynamic_cast<SrsFMLEStartPacket*>(pkt), type, stream_name);
|
||||||
|
|
|
@ -775,7 +775,7 @@ public:
|
||||||
return protocol->expect_message<T>(pmsg, ppacket);
|
return protocol->expect_message<T>(pmsg, ppacket);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
virtual srs_error_t identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, SrsRtmpConnType& type, std::string& stream_name, srs_utime_t& duration);
|
virtual srs_error_t identify_create_stream_client(SrsCreateStreamPacket* req, int stream_id, int depth, SrsRtmpConnType& type, std::string& stream_name, srs_utime_t& duration);
|
||||||
virtual srs_error_t identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsRtmpConnType& type, std::string& stream_name);
|
virtual srs_error_t identify_fmle_publish_client(SrsFMLEStartPacket* req, SrsRtmpConnType& type, std::string& stream_name);
|
||||||
virtual srs_error_t identify_haivision_publish_client(SrsFMLEStartPacket* req, SrsRtmpConnType& type, std::string& stream_name);
|
virtual srs_error_t identify_haivision_publish_client(SrsFMLEStartPacket* req, SrsRtmpConnType& type, std::string& stream_name);
|
||||||
virtual srs_error_t identify_flash_publish_client(SrsPublishPacket* req, SrsRtmpConnType& type, std::string& stream_name);
|
virtual srs_error_t identify_flash_publish_client(SrsPublishPacket* req, SrsRtmpConnType& type, std::string& stream_name);
|
||||||
|
|
|
@ -1594,12 +1594,323 @@ VOID TEST(ProtoStackTest, ServerCommandMessage)
|
||||||
|
|
||||||
SrsCommonMessage* msg = NULL;
|
SrsCommonMessage* msg = NULL;
|
||||||
SrsSetWindowAckSizePacket* pkt = NULL;
|
SrsSetWindowAckSizePacket* pkt = NULL;
|
||||||
HELPER_EXPECT_SUCCESS(p.expect_message(&msg, &pkt));
|
HELPER_ASSERT_SUCCESS(p.expect_message(&msg, &pkt));
|
||||||
EXPECT_EQ(1024, pkt->ackowledgement_window_size);
|
EXPECT_EQ(1024, pkt->ackowledgement_window_size);
|
||||||
|
|
||||||
srs_freep(msg);
|
srs_freep(msg);
|
||||||
srs_freep(pkt);
|
srs_freep(pkt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Response ConnectApp.
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO io;
|
||||||
|
SrsRtmpServer r(&io);
|
||||||
|
|
||||||
|
SrsRequest req;
|
||||||
|
req.objectEncoding = 3.0;
|
||||||
|
|
||||||
|
const char* ip = "1.2.3.4";
|
||||||
|
HELPER_EXPECT_SUCCESS(r.response_connect_app(&req, ip));
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO tio;
|
||||||
|
tio.in_buffer.append(&io.out_buffer);
|
||||||
|
|
||||||
|
SrsProtocol p(&tio);
|
||||||
|
|
||||||
|
// In order to receive and decode the response,
|
||||||
|
// we have to send out a ConnectApp request.
|
||||||
|
if (true) {
|
||||||
|
SrsConnectAppPacket* pkt = new SrsConnectAppPacket();
|
||||||
|
HELPER_EXPECT_SUCCESS(p.send_and_free_packet(pkt, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsCommonMessage* msg = NULL;
|
||||||
|
SrsConnectAppResPacket* pkt = NULL;
|
||||||
|
HELPER_ASSERT_SUCCESS(p.expect_message(&msg, &pkt));
|
||||||
|
|
||||||
|
SrsAmf0Any* prop = pkt->info->get_property("objectEncoding");
|
||||||
|
ASSERT_TRUE(prop && prop->is_number());
|
||||||
|
EXPECT_EQ(3.0, prop->to_number());
|
||||||
|
|
||||||
|
prop = pkt->info->get_property("data");
|
||||||
|
ASSERT_TRUE(prop && prop->is_ecma_array());
|
||||||
|
|
||||||
|
SrsAmf0EcmaArray* arr = prop->to_ecma_array();
|
||||||
|
prop = arr->get_property("srs_server_ip");
|
||||||
|
ASSERT_TRUE(prop && prop->is_string());
|
||||||
|
EXPECT_STREQ("1.2.3.4", prop->to_str().c_str());
|
||||||
|
|
||||||
|
srs_freep(msg);
|
||||||
|
srs_freep(pkt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response ConnectApp rejected.
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO io;
|
||||||
|
SrsRtmpServer r(&io);
|
||||||
|
|
||||||
|
const char* desc = "Rejected";
|
||||||
|
r.response_connect_reject(NULL, desc);
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO tio;
|
||||||
|
tio.in_buffer.append(&io.out_buffer);
|
||||||
|
|
||||||
|
SrsProtocol p(&tio);
|
||||||
|
|
||||||
|
SrsCommonMessage* msg = NULL;
|
||||||
|
SrsCallPacket* pkt = NULL;
|
||||||
|
HELPER_ASSERT_SUCCESS(p.expect_message(&msg, &pkt));
|
||||||
|
|
||||||
|
SrsAmf0Any* prop = pkt->arguments;
|
||||||
|
ASSERT_TRUE(prop && prop->is_object());
|
||||||
|
|
||||||
|
prop = prop->to_object()->get_property(StatusDescription);
|
||||||
|
ASSERT_TRUE(prop && prop->is_string());
|
||||||
|
EXPECT_STREQ(desc, prop->to_str().c_str());
|
||||||
|
|
||||||
|
srs_freep(msg);
|
||||||
|
srs_freep(pkt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response OnBWDone
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO io;
|
||||||
|
SrsRtmpServer r(&io);
|
||||||
|
HELPER_EXPECT_SUCCESS(r.on_bw_done());
|
||||||
|
EXPECT_TRUE(io.out_length() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set peer chunk size.
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO io;
|
||||||
|
SrsRtmpServer r(&io);
|
||||||
|
HELPER_EXPECT_SUCCESS(r.set_chunk_size(1024));
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO tio;
|
||||||
|
tio.in_buffer.append(&io.out_buffer);
|
||||||
|
|
||||||
|
SrsProtocol p(&tio);
|
||||||
|
|
||||||
|
SrsCommonMessage* msg = NULL;
|
||||||
|
HELPER_EXPECT_SUCCESS(p.recv_message(&msg));
|
||||||
|
srs_freep(msg);
|
||||||
|
|
||||||
|
EXPECT_EQ(1024, p.in_chunk_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID TEST(ProtoStackTest, ServerRedirect)
|
||||||
|
{
|
||||||
|
srs_error_t err;
|
||||||
|
|
||||||
|
// Redirect without response.
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO io;
|
||||||
|
SrsRtmpServer r(&io);
|
||||||
|
|
||||||
|
SrsRequest req;
|
||||||
|
req.app = "live";
|
||||||
|
req.stream = "livestream";
|
||||||
|
|
||||||
|
string host = "target.net";
|
||||||
|
int port = 8888;
|
||||||
|
bool accepted = false;
|
||||||
|
HELPER_EXPECT_SUCCESS(r.redirect(&req, host, port, accepted));
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO tio;
|
||||||
|
tio.in_buffer.append(&io.out_buffer);
|
||||||
|
|
||||||
|
SrsProtocol p(&tio);
|
||||||
|
|
||||||
|
SrsCommonMessage* msg = NULL;
|
||||||
|
SrsCallPacket* pkt = NULL;
|
||||||
|
HELPER_ASSERT_SUCCESS(p.expect_message(&msg, &pkt));
|
||||||
|
|
||||||
|
SrsAmf0Any* prop = pkt->arguments;
|
||||||
|
ASSERT_TRUE(prop && prop->is_object());
|
||||||
|
|
||||||
|
prop = prop->to_object()->get_property("ex");
|
||||||
|
ASSERT_TRUE(prop && prop->is_object());
|
||||||
|
SrsAmf0Object* ex = prop->to_object();
|
||||||
|
|
||||||
|
prop = ex->get_property("code");
|
||||||
|
ASSERT_TRUE(prop && prop->is_number());
|
||||||
|
EXPECT_EQ(302, prop->to_number());
|
||||||
|
|
||||||
|
prop = ex->get_property("redirect");
|
||||||
|
ASSERT_TRUE(prop && prop->is_string());
|
||||||
|
EXPECT_STREQ("rtmp://target.net:8888/live/livestream", prop->to_str().c_str());
|
||||||
|
|
||||||
|
srs_freep(msg);
|
||||||
|
srs_freep(pkt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect with response.
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO io;
|
||||||
|
SrsRtmpServer r(&io);
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO tio;
|
||||||
|
SrsProtocol p(&tio);
|
||||||
|
|
||||||
|
SrsCallPacket* call = new SrsCallPacket();
|
||||||
|
call->command_name = "redirected";
|
||||||
|
call->command_object = SrsAmf0Any::object();
|
||||||
|
call->arguments = SrsAmf0Any::str("OK");
|
||||||
|
HELPER_EXPECT_SUCCESS(p.send_and_free_packet(call, 0));
|
||||||
|
|
||||||
|
io.in_buffer.append(&tio.out_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsRequest req;
|
||||||
|
req.app = "live";
|
||||||
|
req.stream = "livestream";
|
||||||
|
|
||||||
|
string host = "target.net";
|
||||||
|
int port = 8888;
|
||||||
|
bool accepted = false;
|
||||||
|
HELPER_EXPECT_SUCCESS(r.redirect(&req, host, port, accepted));
|
||||||
|
EXPECT_TRUE(accepted);
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO tio;
|
||||||
|
tio.in_buffer.append(&io.out_buffer);
|
||||||
|
|
||||||
|
SrsProtocol p(&tio);
|
||||||
|
|
||||||
|
SrsCommonMessage* msg = NULL;
|
||||||
|
SrsCallPacket* pkt = NULL;
|
||||||
|
HELPER_ASSERT_SUCCESS(p.expect_message(&msg, &pkt));
|
||||||
|
|
||||||
|
SrsAmf0Any* prop = pkt->arguments;
|
||||||
|
ASSERT_TRUE(prop && prop->is_object());
|
||||||
|
|
||||||
|
prop = prop->to_object()->get_property("ex");
|
||||||
|
ASSERT_TRUE(prop && prop->is_object());
|
||||||
|
SrsAmf0Object* ex = prop->to_object();
|
||||||
|
|
||||||
|
prop = ex->get_property("code");
|
||||||
|
ASSERT_TRUE(prop && prop->is_number());
|
||||||
|
EXPECT_EQ(302, prop->to_number());
|
||||||
|
|
||||||
|
prop = ex->get_property("redirect");
|
||||||
|
ASSERT_TRUE(prop && prop->is_string());
|
||||||
|
EXPECT_STREQ("rtmp://target.net:8888/live/livestream", prop->to_str().c_str());
|
||||||
|
|
||||||
|
srs_freep(msg);
|
||||||
|
srs_freep(pkt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID TEST(ProtoStackTest, ServerIdentify)
|
||||||
|
{
|
||||||
|
srs_error_t err;
|
||||||
|
|
||||||
|
// Identify failed.
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO io;
|
||||||
|
SrsRtmpServer r(&io);
|
||||||
|
|
||||||
|
string stream_name;
|
||||||
|
SrsRtmpConnType tp;
|
||||||
|
srs_utime_t duration = 0;
|
||||||
|
HELPER_EXPECT_FAILED(r.identify_client(1, tp, stream_name, duration));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identify by CreateStream, Play.
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO io;
|
||||||
|
SrsRtmpServer r(&io);
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO tio;
|
||||||
|
SrsProtocol p(&tio);
|
||||||
|
|
||||||
|
SrsCreateStreamPacket* call = new SrsCreateStreamPacket();
|
||||||
|
HELPER_EXPECT_SUCCESS(p.send_and_free_packet(call, 0));
|
||||||
|
|
||||||
|
SrsPlayPacket* play = new SrsPlayPacket();
|
||||||
|
play->stream_name = "livestream";
|
||||||
|
play->duration = 100;
|
||||||
|
HELPER_EXPECT_SUCCESS(p.send_and_free_packet(play, 0));
|
||||||
|
|
||||||
|
io.in_buffer.append(&tio.out_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
string stream_name;
|
||||||
|
SrsRtmpConnType tp;
|
||||||
|
srs_utime_t duration = 0;
|
||||||
|
HELPER_EXPECT_SUCCESS(r.identify_client(1, tp, stream_name, duration));
|
||||||
|
EXPECT_EQ(SrsRtmpConnPlay, tp);
|
||||||
|
EXPECT_STREQ("livestream", stream_name.c_str());
|
||||||
|
EXPECT_EQ(100000, duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identify by CreateStream, CreateStream, CreateStream, Play.
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO io;
|
||||||
|
SrsRtmpServer r(&io);
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO tio;
|
||||||
|
SrsProtocol p(&tio);
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
SrsCreateStreamPacket* call = new SrsCreateStreamPacket();
|
||||||
|
HELPER_EXPECT_SUCCESS(p.send_and_free_packet(call, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsPlayPacket* play = new SrsPlayPacket();
|
||||||
|
play->stream_name = "livestream";
|
||||||
|
play->duration = 100;
|
||||||
|
HELPER_EXPECT_SUCCESS(p.send_and_free_packet(play, 0));
|
||||||
|
|
||||||
|
io.in_buffer.append(&tio.out_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
string stream_name;
|
||||||
|
SrsRtmpConnType tp;
|
||||||
|
srs_utime_t duration = 0;
|
||||||
|
HELPER_EXPECT_SUCCESS(r.identify_client(1, tp, stream_name, duration));
|
||||||
|
EXPECT_EQ(SrsRtmpConnPlay, tp);
|
||||||
|
EXPECT_STREQ("livestream", stream_name.c_str());
|
||||||
|
EXPECT_EQ(100000, duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For N*CreateStream and N>3, it should fail.
|
||||||
|
|
||||||
|
// Identify by CreateStream, CreateStream, CreateStream, Play.
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO io;
|
||||||
|
SrsRtmpServer r(&io);
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
MockBufferIO tio;
|
||||||
|
SrsProtocol p(&tio);
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
SrsCreateStreamPacket* call = new SrsCreateStreamPacket();
|
||||||
|
HELPER_EXPECT_SUCCESS(p.send_and_free_packet(call, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
io.in_buffer.append(&tio.out_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
string stream_name;
|
||||||
|
SrsRtmpConnType tp;
|
||||||
|
srs_utime_t duration = 0;
|
||||||
|
HELPER_EXPECT_FAILED(r.identify_client(1, tp, stream_name, duration));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue