1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Refine SRT code, with StateThread adpater

This commit is contained in:
hondaxiao 2022-04-15 13:54:24 +08:00 committed by winlin
parent 3ed4aed824
commit 94fa0ff7bd
25 changed files with 4131 additions and 68 deletions

View file

@ -6,84 +6,461 @@
#include <srs_utest_srt.hpp>
#include <srs_kernel_error.hpp>
#include <srt_conn.hpp>
#include <srs_kernel_utility.hpp>
#include <srs_service_st_srt.hpp>
#include <srs_rtmp_stack.hpp>
#include <srs_app_srt_utility.hpp>
#include <srs_app_srt_server.hpp>
#include <sstream>
#include <vector>
using namespace std;
VOID TEST(ProtocolSrtTest, SrtGetStreamInfoNormal) {
extern SrsSrtEventLoop* _srt_eventloop;
// Test srt st service
VOID TEST(ServiceSrtPoller, SrtPollOperateSocket)
{
srs_error_t err = srs_success;
SrsSrtPoller* srt_poller = new SrsSrtPoller();
HELPER_EXPECT_SUCCESS(srt_poller->initialize());
SRTSOCKET srt_fd = SRT_INVALID_SOCK;
HELPER_EXPECT_SUCCESS(srs_srt_socket(&srt_fd));
EXPECT_TRUE(srt_fd > 0);
SrsSrtSocket* srt_socket = new SrsSrtSocket(srt_poller, srt_fd);
EXPECT_EQ(srt_socket->events(), 0);
// Enable read, will subscribe SRT_EPOLL_IN and SRT_EPOLL_ERR event in srt poller.
HELPER_EXPECT_SUCCESS(srt_socket->enable_read());
EXPECT_TRUE(srt_socket->events() & SRT_EPOLL_IN);
EXPECT_TRUE(srt_socket->events() & SRT_EPOLL_ERR);
// Enable read, will subscribe SRT_EPOLL_OUT and SRT_EPOLL_ERR event in srt poller.
HELPER_EXPECT_SUCCESS(srt_socket->enable_write());
EXPECT_TRUE(srt_socket->events() & SRT_EPOLL_OUT);
EXPECT_TRUE(srt_socket->events() & SRT_EPOLL_ERR);
// Disable read, will unsubscribe SRT_EPOLL_IN event in srt poller.
HELPER_EXPECT_SUCCESS(srt_socket->disable_read());
EXPECT_FALSE(srt_socket->events() & SRT_EPOLL_IN);
EXPECT_TRUE(srt_socket->events() & SRT_EPOLL_ERR);
// Disable write, will unsubscribe SRT_EPOLL_OUT event in srt poller.
HELPER_EXPECT_SUCCESS(srt_socket->disable_write());
EXPECT_FALSE(srt_socket->events() & SRT_EPOLL_OUT);
EXPECT_TRUE(srt_socket->events() & SRT_EPOLL_ERR);
EXPECT_EQ(srt_poller->fd_sockets_.size(), 1);
// Delete socket, will remove in srt poller.
srs_freep(srt_socket);
EXPECT_EQ(srt_poller->fd_sockets_.size(), 0);
srs_freep(srt_poller);
}
VOID TEST(ServiceSrtPoller, SrtSetGetSocketOpt)
{
srs_error_t err = srs_success;
SRTSOCKET srt_fd = SRT_INVALID_SOCK;
HELPER_EXPECT_SUCCESS(srs_srt_socket(&srt_fd));
HELPER_EXPECT_SUCCESS(srs_srt_nonblock(srt_fd));
int maxbw = 20000;
int mss = 1400;
int payload_size = 1316;
int connect_timeout = 5000;
int peer_idle_timeout = 10000;
bool tsbpdmode = false;
int sndbuf = 2 * 1024 * 1024;
int rcvbuf = 10 * 1024 * 1024;
bool tlpktdrop = false;
int latency = 0;
int rcv_latency = 120;
int peer_latency = 120;
std::string streamid = "SRS_SRT";
HELPER_EXPECT_SUCCESS(srs_srt_set_maxbw(srt_fd, maxbw));
HELPER_EXPECT_SUCCESS(srs_srt_set_mss(srt_fd, mss));
HELPER_EXPECT_SUCCESS(srs_srt_set_payload_size(srt_fd, payload_size));
HELPER_EXPECT_SUCCESS(srs_srt_set_connect_timeout(srt_fd, connect_timeout));
HELPER_EXPECT_SUCCESS(srs_srt_set_peer_idle_timeout(srt_fd, peer_idle_timeout));
HELPER_EXPECT_SUCCESS(srs_srt_set_tsbpdmode(srt_fd, tsbpdmode));
HELPER_EXPECT_SUCCESS(srs_srt_set_sndbuf(srt_fd, sndbuf));
HELPER_EXPECT_SUCCESS(srs_srt_set_rcvbuf(srt_fd, rcvbuf));
HELPER_EXPECT_SUCCESS(srs_srt_set_tlpktdrop(srt_fd, tlpktdrop));
HELPER_EXPECT_SUCCESS(srs_srt_set_latency(srt_fd, latency));
HELPER_EXPECT_SUCCESS(srs_srt_set_rcv_latency(srt_fd, rcv_latency));
HELPER_EXPECT_SUCCESS(srs_srt_set_peer_latency(srt_fd, peer_latency));
HELPER_EXPECT_SUCCESS(srs_srt_set_streamid(srt_fd, streamid));
bool b;
int i = 0;
std::string s;
HELPER_EXPECT_SUCCESS(srs_srt_get_maxbw(srt_fd, i));
EXPECT_EQ(i, maxbw);
HELPER_EXPECT_SUCCESS(srs_srt_get_mss(srt_fd, i));
EXPECT_EQ(i, mss);
HELPER_EXPECT_SUCCESS(srs_srt_get_payload_size(srt_fd, i));
EXPECT_EQ(i, payload_size);
HELPER_EXPECT_SUCCESS(srs_srt_get_connect_timeout(srt_fd, i));
EXPECT_EQ(i, connect_timeout);
HELPER_EXPECT_SUCCESS(srs_srt_get_peer_idle_timeout(srt_fd, i));
EXPECT_EQ(i, peer_idle_timeout);
// Don't check b equal to option blow, because some opt will deterimated after srt handshake done or change when set.
HELPER_EXPECT_SUCCESS(srs_srt_get_tsbpdmode(srt_fd, b));
HELPER_EXPECT_SUCCESS(srs_srt_get_sndbuf(srt_fd, i));
HELPER_EXPECT_SUCCESS(srs_srt_get_rcvbuf(srt_fd, i));
HELPER_EXPECT_SUCCESS(srs_srt_get_tlpktdrop(srt_fd, b));
HELPER_EXPECT_SUCCESS(srs_srt_get_latency(srt_fd, i));
HELPER_EXPECT_SUCCESS(srs_srt_get_rcv_latency(srt_fd, i));
HELPER_EXPECT_SUCCESS(srs_srt_get_peer_latency(srt_fd, i));
HELPER_EXPECT_SUCCESS(srs_srt_get_streamid(srt_fd, s));
EXPECT_EQ(s, streamid);
}
class MockSrtServer
{
public:
SrsSrtSocket* srt_socket_;
SRTSOCKET srt_server_fd_;
MockSrtServer() {
srt_server_fd_ = SRT_INVALID_SOCK;
srt_socket_ = NULL;
}
srs_error_t create_socket() {
srs_error_t err = srs_success;
if ((err = srs_srt_socket_with_default_option(&srt_server_fd_)) != srs_success) {
return srs_error_wrap(err, "create srt socket");
}
return err;
}
srs_error_t listen(std::string ip, int port) {
srs_error_t err = srs_success;
if ((err = srs_srt_listen(srt_server_fd_, ip, port)) != srs_success) {
return srs_error_wrap(err, "srt listen");
}
srt_socket_ = new SrsSrtSocket(_srt_eventloop->get_srt_poller(), srt_server_fd_);
return err;
}
virtual ~MockSrtServer() {
srs_freep(srt_socket_);
}
virtual srs_error_t accept(SRTSOCKET* client_fd) {
srs_error_t err = srs_success;
if ((err = srt_socket_->accept(client_fd)) != srs_success) {
return srs_error_wrap(err, "srt accept");
}
return err;
}
};
VOID TEST(ServiceStSRTTest, ListenConnectAccept)
{
srs_error_t err = srs_success;
std::string server_ip = "127.0.0.1";
int server_port = 9000;
MockSrtServer srt_server;
HELPER_EXPECT_SUCCESS(srt_server.create_socket());
HELPER_EXPECT_SUCCESS(srt_server.listen(server_ip, server_port));
SRTSOCKET srt_client_fd = SRT_INVALID_SOCK;
HELPER_EXPECT_SUCCESS(srs_srt_socket(&srt_client_fd));
SrsSrtSocket* srt_client_socket = new SrsSrtSocket(_srt_eventloop->get_srt_poller(), srt_client_fd);
// No client connected, accept will timeout.
SRTSOCKET srt_fd = SRT_INVALID_SOCK;
// Make utest fast timeout.
srt_server.srt_socket_->set_recv_timeout(50 * SRS_UTIME_MILLISECONDS);
err = srt_server.accept(&srt_fd);
EXPECT_EQ(srs_error_code(err), ERROR_SRT_TIMEOUT);
EXPECT_EQ(srt_fd, SRT_INVALID_SOCK);
// Client connect to server
HELPER_EXPECT_SUCCESS(srt_client_socket->connect(server_ip, server_port));
// Server will accept one client.
HELPER_EXPECT_SUCCESS(srt_server.accept(&srt_fd));
EXPECT_NE(srt_fd, SRT_INVALID_SOCK);
}
VOID TEST(ServiceStSRTTest, ConnectTimeout)
{
srs_error_t err = srs_success;
SRTSOCKET srt_client_fd = SRT_INVALID_SOCK;
HELPER_EXPECT_SUCCESS(srs_srt_socket_with_default_option(&srt_client_fd));
SrsSrtSocket* srt_client_socket = new SrsSrtSocket(_srt_eventloop->get_srt_poller(), srt_client_fd);
srt_client_socket->set_send_timeout(50 * SRS_UTIME_MILLISECONDS);
// Client connect to server which is no listening.
HELPER_EXPECT_FAILED(srt_client_socket->connect("127.0.0.1", 9099));
}
VOID TEST(ServiceStSRTTest, ConnectWithStreamid)
{
srs_error_t err = srs_success;
std::string server_ip = "127.0.0.1";
int server_port = 9000;
MockSrtServer srt_server;
HELPER_EXPECT_SUCCESS(srt_server.create_socket());
HELPER_EXPECT_SUCCESS(srt_server.listen(server_ip, server_port));
std::string streamid = "SRS_SRT_Streamid";
SRTSOCKET srt_client_fd = SRT_INVALID_SOCK;
HELPER_EXPECT_SUCCESS(srs_srt_socket_with_default_option(&srt_client_fd));
HELPER_EXPECT_SUCCESS(srs_srt_set_streamid(srt_client_fd, streamid));
SrsSrtSocket* srt_client_socket = new SrsSrtSocket(_srt_eventloop->get_srt_poller(), srt_client_fd);
HELPER_EXPECT_SUCCESS(srt_client_socket->connect("127.0.0.1", 9000));
SRTSOCKET srt_server_accepted_fd = SRT_INVALID_SOCK;
HELPER_EXPECT_SUCCESS(srt_server.accept(&srt_server_accepted_fd));
EXPECT_NE(srt_server_accepted_fd, SRT_INVALID_SOCK);
std::string s;
HELPER_EXPECT_SUCCESS(srs_srt_get_streamid(srt_server_accepted_fd, s));
EXPECT_EQ(s, streamid);
}
VOID TEST(ServiceStSRTTest, ReadWrite)
{
srs_error_t err = srs_success;
std::string server_ip = "127.0.0.1";
int server_port = 9000;
MockSrtServer srt_server;
HELPER_EXPECT_SUCCESS(srt_server.create_socket());
HELPER_EXPECT_SUCCESS(srt_server.listen(server_ip, server_port));
SRTSOCKET srt_client_fd = SRT_INVALID_SOCK;
HELPER_EXPECT_SUCCESS(srs_srt_socket_with_default_option(&srt_client_fd));
SrsSrtSocket* srt_client_socket = new SrsSrtSocket(_srt_eventloop->get_srt_poller(), srt_client_fd);
// Client connect to server
HELPER_EXPECT_SUCCESS(srt_client_socket->connect(server_ip, server_port));
// Server will accept one client.
SRTSOCKET srt_server_accepted_fd = SRT_INVALID_SOCK;
HELPER_EXPECT_SUCCESS(srt_server.accept(&srt_server_accepted_fd));
EXPECT_NE(srt_server_accepted_fd, SRT_INVALID_SOCK);
SrsSrtSocket* srt_server_accepted_socket = new SrsSrtSocket(_srt_eventloop->get_srt_poller(), srt_server_accepted_fd);
if (true) {
int mode; string vhost; string subpath;
EXPECT_TRUE(get_streamid_info("#!::r=live/livestream,key1=value1,key2=value2", mode, vhost, subpath));
EXPECT_EQ(PULL_SRT_MODE, mode);
std::string content = "Hello, SRS SRT!";
// Client send msg to server.
ssize_t nb_write = 0;
HELPER_EXPECT_SUCCESS(srt_client_socket->sendmsg((char*)content.data(), content.size(), &nb_write));
EXPECT_EQ(nb_write, content.size());
// Server recv msg from client
char buf[1500];
ssize_t nb_read = 0;
HELPER_EXPECT_SUCCESS(srt_server_accepted_socket->recvmsg(buf, sizeof(buf), &nb_read));
EXPECT_EQ(nb_read, content.size());
EXPECT_EQ(std::string(buf, nb_read), content);
// Server echo msg back to client.
HELPER_EXPECT_SUCCESS(srt_server_accepted_socket->sendmsg(buf, nb_read, &nb_write));
EXPECT_EQ(nb_write, content.size());
// Client recv echo msg from server.
HELPER_EXPECT_SUCCESS(srt_client_socket->recvmsg(buf, sizeof(buf), &nb_read));
EXPECT_EQ(nb_read, content.size());
EXPECT_EQ(std::string(buf, nb_read), content);
}
if (true) {
char buf[1500];
ssize_t nb_read = 0;
// Make socket fast timeout in ustet.
srt_server_accepted_socket->set_recv_timeout(50 * SRS_UTIME_MILLISECONDS);
// Recv msg from client, but client no send any msg, so will be timeout.
err = srt_server_accepted_socket->recvmsg(buf, sizeof(buf), &nb_read);
EXPECT_EQ(srs_error_code(err), ERROR_SRT_TIMEOUT);
}
}
// Test srt server
class MockSrtHandler : public ISrsSrtHandler
{
private:
SRTSOCKET srt_fd;
public:
MockSrtHandler() {
srt_fd = SRT_INVALID_SOCK;
}
virtual ~MockSrtHandler() {
}
public:
virtual srs_error_t on_srt_client(SRTSOCKET fd) {
srt_fd = fd;
return srs_success;
}
};
VOID TEST(SrtServerTest, SrtListener)
{
srs_error_t err = srs_success;
if (true) {
MockSrtHandler h;
SrsSrtListener srt_listener(&h, "127.0.0.1", 9000);
HELPER_EXPECT_SUCCESS(srt_listener.create_socket());
HELPER_EXPECT_SUCCESS(srt_listener.listen());
EXPECT_TRUE(srt_listener.fd() > 0);
}
}
// Test srt app
VOID TEST(ProtocolSrtTest, SrtGetStreamInfoNormal)
{
if (true) {
SrtMode mode; string vhost; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::r=live/livestream,key1=value1,key2=value2", mode, vhost, subpath));
EXPECT_EQ(SrtModePull, mode);
EXPECT_STREQ("", vhost.c_str());
EXPECT_STREQ("live/livestream?key1=value1&key2=value2", subpath.c_str());
}
if (true) {
int mode; string vhost; string subpath;
EXPECT_TRUE(get_streamid_info("#!::h=host.com,r=live/livestream,key1=value1,key2=value2", mode, vhost, subpath));
EXPECT_EQ(PULL_SRT_MODE, mode);
SrtMode mode; string vhost; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::h=host.com,r=live/livestream,key1=value1,key2=value2", mode, vhost, subpath));
EXPECT_EQ(SrtModePull, mode);
EXPECT_STREQ("host.com", vhost.c_str());
EXPECT_STREQ("live/livestream?vhost=host.com&key1=value1&key2=value2", subpath.c_str());
}
}
VOID TEST(ProtocolSrtTest, SrtGetStreamInfoMethod) {
VOID TEST(ProtocolSrtTest, SrtGetStreamInfoMethod)
{
if (true) {
int mode; string vhost; string subpath;
EXPECT_TRUE(get_streamid_info("#!::r=live/livestream,m=request", mode, vhost, subpath));
EXPECT_EQ(PULL_SRT_MODE, mode);
SrtMode mode; string vhost; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::r=live/livestream,m=request", mode, vhost, subpath));
EXPECT_EQ(SrtModePull, mode);
EXPECT_STREQ("live/livestream", subpath.c_str());
}
if (true) {
int mode; string vhost; string subpath;
EXPECT_TRUE(get_streamid_info("#!::r=live/livestream,m=publish", mode, vhost, subpath));
EXPECT_EQ(PUSH_SRT_MODE, mode);
SrtMode mode; string vhost; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::r=live/livestream,m=publish", mode, vhost, subpath));
EXPECT_EQ(SrtModePush, mode);
EXPECT_STREQ("live/livestream", subpath.c_str());
}
}
VOID TEST(ProtocolSrtTest, SrtGetStreamInfoCompatible) {
VOID TEST(ProtocolSrtTest, SrtGetStreamInfoCompatible)
{
if (true) {
int mode; string vhost; string subpath;
EXPECT_TRUE(get_streamid_info("#!::h=live/livestream,m=request", mode, vhost, subpath));
EXPECT_EQ(PULL_SRT_MODE, mode);
SrtMode mode; string vhost; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::h=live/livestream,m=request", mode, vhost, subpath));
EXPECT_EQ(SrtModePull, mode);
EXPECT_STREQ("", vhost.c_str());
EXPECT_STREQ("live/livestream", subpath.c_str());
}
if (true) {
int mode; string vhost; string subpath;
EXPECT_TRUE(get_streamid_info("#!::h=live/livestream,m=publish", mode, vhost, subpath));
EXPECT_EQ(PUSH_SRT_MODE, mode);
SrtMode mode; string vhost; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::h=live/livestream,m=publish", mode, vhost, subpath));
EXPECT_EQ(SrtModePush, mode);
EXPECT_STREQ("", vhost.c_str());
EXPECT_STREQ("live/livestream", subpath.c_str());
}
if (true) {
int mode; string vhost; string subpath;
EXPECT_TRUE(get_streamid_info("#!::h=srs.srt.com.cn/live/livestream,m=request", mode, vhost, subpath));
EXPECT_EQ(PULL_SRT_MODE, mode);
SrtMode mode; string vhost; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::h=srs.srt.com.cn/live/livestream,m=request", mode, vhost, subpath));
EXPECT_EQ(SrtModePull, mode);
EXPECT_STREQ("srs.srt.com.cn", vhost.c_str());
EXPECT_STREQ("live/livestream?vhost=srs.srt.com.cn", subpath.c_str());
}
if (true) {
int mode; string vhost; string subpath;
EXPECT_TRUE(get_streamid_info("#!::h=srs.srt.com.cn/live/livestream,m=publish", mode, vhost, subpath));
EXPECT_EQ(PUSH_SRT_MODE, mode);
SrtMode mode; string vhost; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::h=srs.srt.com.cn/live/livestream,m=publish", mode, vhost, subpath));
EXPECT_EQ(SrtModePush, mode);
EXPECT_STREQ("srs.srt.com.cn", vhost.c_str());
EXPECT_STREQ("live/livestream?vhost=srs.srt.com.cn", subpath.c_str());
}
if (true) {
int mode; string vhost; string subpath;
EXPECT_TRUE(get_streamid_info("#!::h=live/livestream?secret=d6d2be37,m=publish", mode, vhost, subpath));
EXPECT_EQ(PUSH_SRT_MODE, mode);
SrtMode mode; string vhost; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::h=live/livestream?secret=d6d2be37,m=publish", mode, vhost, subpath));
EXPECT_EQ(SrtModePush, mode);
EXPECT_STREQ("", vhost.c_str());
EXPECT_STREQ("live/livestream?secret=d6d2be37", subpath.c_str());
}
}
VOID TEST(ProtocolSrtTest, SrtStreamIdToRequest)
{
if (true) {
SrtMode mode;
SrsRequest req;
EXPECT_TRUE(srs_srt_streamid_to_request("#!::r=live/livestream?key1=val1,key2=val2", mode, &req));
EXPECT_EQ(mode, SrtModePull);
EXPECT_STREQ(req.vhost.c_str(), "");
EXPECT_STREQ(req.app.c_str(), "live");
EXPECT_STREQ(req.stream.c_str(), "livestream");
EXPECT_STREQ(req.param.c_str(), "key1=val1&key2=val2");
}
if (true) {
SrtMode mode;
SrsRequest req;
EXPECT_TRUE(srs_srt_streamid_to_request("#!::h=srs.srt.com.cn,r=live/livestream?key1=val1,key2=val2", mode, &req));
EXPECT_EQ(mode, SrtModePull);
EXPECT_STREQ(req.vhost.c_str(), "srs.srt.com.cn");
EXPECT_STREQ(req.app.c_str(), "live");
EXPECT_STREQ(req.stream.c_str(), "livestream");
EXPECT_STREQ(req.param.c_str(), "vhost=srs.srt.com.cn&key1=val1&key2=val2");
}
if (true) {
SrtMode mode;
SrsRequest req;
EXPECT_TRUE(srs_srt_streamid_to_request("#!::h=live/livestream?key1=val1,key2=val2", mode, &req));
EXPECT_EQ(mode, SrtModePull);
EXPECT_STREQ(req.vhost.c_str(), "");
EXPECT_STREQ(req.app.c_str(), "live");
EXPECT_STREQ(req.stream.c_str(), "livestream");
EXPECT_STREQ(req.param.c_str(), "key1=val1&key2=val2");
}
if (true) {
SrtMode mode;
SrsRequest req;
EXPECT_TRUE(srs_srt_streamid_to_request("#!::h=srs.srt.com.cn/live/livestream?key1=val1,key2=val2", mode, &req));
EXPECT_EQ(mode, SrtModePull);
EXPECT_STREQ(req.vhost.c_str(), "srs.srt.com.cn");
EXPECT_STREQ(req.app.c_str(), "live");
EXPECT_STREQ(req.stream.c_str(), "livestream");
EXPECT_STREQ(req.param.c_str(), "vhost=srs.srt.com.cn&key1=val1&key2=val2");
}
}
// TODO: FIXME: add mpegts conn test
// set srt option, recv srt client, get srt client opt and check.