AI: Add utest to cover caster flv module.

This commit is contained in:
OSSRS-AI 2025-10-11 10:21:08 -04:00 committed by winlin
parent 4004ddb5c0
commit e8ac08dfa2
8 changed files with 1592 additions and 15 deletions

View File

@ -10,6 +10,7 @@
using namespace std;
#include <srs_app_config.hpp>
#include <srs_app_factory.hpp>
#include <srs_app_http_conn.hpp>
#include <srs_app_rtmp_conn.hpp>
#include <srs_app_st.hpp>
@ -38,19 +39,23 @@ SrsHttpFlvListener::SrsHttpFlvListener()
{
listener_ = new SrsTcpListener(this);
caster_ = new SrsAppCasterFlv();
config_ = _srs_config;
}
SrsHttpFlvListener::~SrsHttpFlvListener()
{
srs_freep(caster_);
srs_freep(listener_);
config_ = NULL;
}
srs_error_t SrsHttpFlvListener::initialize(SrsConfDirective *c)
{
srs_error_t err = srs_success;
int port = _srs_config->get_stream_caster_listen(c);
int port = config_->get_stream_caster_listen(c);
if (port <= 0) {
return srs_error_new(ERROR_STREAM_CASTER_PORT, "invalid port=%d", port);
}
@ -104,6 +109,8 @@ SrsAppCasterFlv::SrsAppCasterFlv()
{
http_mux_ = new SrsHttpServeMux();
manager_ = new SrsResourceManager("CFLV");
config_ = _srs_config;
}
SrsAppCasterFlv::~SrsAppCasterFlv()
@ -116,13 +123,15 @@ SrsAppCasterFlv::~SrsAppCasterFlv()
ISrsConnection *conn = *it;
srs_freep(conn);
}
config_ = NULL;
}
srs_error_t SrsAppCasterFlv::initialize(SrsConfDirective *c)
{
srs_error_t err = srs_success;
output_ = _srs_config->get_stream_caster_output(c);
output_ = config_->get_stream_caster_output(c);
if ((err = http_mux_->handle("/", this)) != srs_success) {
return srs_error_wrap(err, "handle root");
@ -143,11 +152,11 @@ srs_error_t SrsAppCasterFlv::on_tcp_client(ISrsListener *listener, srs_netfd_t s
string ip = srs_get_peer_ip(fd);
int port = srs_get_peer_port(fd);
if (ip.empty() && !_srs_config->empty_ip_ok()) {
if (ip.empty() && !config_->empty_ip_ok()) {
srs_warn("empty ip for fd=%d", srs_netfd_fileno(stfd));
}
SrsDynamicHttpConn *conn = new SrsDynamicHttpConn(this, stfd, http_mux_, ip, port);
ISrsDynamicHttpConn *conn = new SrsDynamicHttpConn(this, stfd, http_mux_, ip, port);
conns_.push_back(conn);
if ((err = conn->start()) != srs_success) {
@ -291,17 +300,19 @@ SrsDynamicHttpConn::SrsDynamicHttpConn(ISrsResourceManager *cm, srs_netfd_t fd,
ip_ = cip;
port_ = cport;
_srs_config->subscribe(this);
config_ = _srs_config;
app_factory_ = _srs_app_factory;
}
SrsDynamicHttpConn::~SrsDynamicHttpConn()
{
_srs_config->unsubscribe(this);
srs_freep(conn_);
srs_freep(skt_);
srs_freep(sdk_);
srs_freep(pprint_);
config_ = NULL;
app_factory_ = NULL;
}
srs_error_t SrsDynamicHttpConn::proxy(ISrsHttpResponseWriter *w, ISrsHttpMessage *r, std::string o)
@ -343,7 +354,7 @@ srs_error_t SrsDynamicHttpConn::do_proxy(ISrsHttpResponseReader *rr, SrsFlvDecod
srs_utime_t cto = SRS_CONSTS_RTMP_TIMEOUT;
srs_utime_t sto = SRS_CONSTS_RTMP_PULSE;
sdk_ = new SrsSimpleRtmpClient(output_, cto, sto);
sdk_ = app_factory_->create_rtmp_client(output_, cto, sto);
if ((err = sdk_->connect()) != srs_success) {
return srs_error_wrap(err, "connect %s failed, cto=%dms, sto=%dms.", output_.c_str(), srsu2msi(cto), srsu2msi(sto));
@ -439,7 +450,7 @@ srs_error_t SrsDynamicHttpConn::start()
{
srs_error_t err = srs_success;
bool v = _srs_config->get_http_stream_crossdomain();
bool v = config_->get_http_stream_crossdomain();
if ((err = conn_->set_crossdomain_enabled(v)) != srs_success) {
return srs_error_wrap(err, "set cors=%d", v);
}

View File

@ -23,6 +23,12 @@ class SrsFlvDecoder;
class SrsTcpClient;
class SrsSimpleRtmpClient;
class SrsAppCasterFlv;
class ISrsAppCasterFlv;
class ISrsAppConfig;
class ISrsAppFactory;
class ISrsBasicRtmpClient;
class ISrsProtocolReadWriter;
class ISrsHttpConn;
#include <srs_app_http_conn.hpp>
#include <srs_app_listener.hpp>
@ -43,9 +49,12 @@ public:
// A TCP listener, for flv stream server.
class SrsHttpFlvListener : public ISrsHttpFlvListener
{
private:
ISrsAppConfig *config_;
private:
SrsTcpListener *listener_;
SrsAppCasterFlv *caster_;
ISrsAppCasterFlv *caster_;
public:
SrsHttpFlvListener();
@ -68,11 +77,15 @@ public:
virtual ~ISrsAppCasterFlv();
public:
virtual srs_error_t initialize(SrsConfDirective *c) = 0;
};
// The stream caster for flv stream over HTTP POST.
class SrsAppCasterFlv : public ISrsAppCasterFlv
{
private:
ISrsAppConfig *config_;
private:
std::string output_;
SrsHttpServeMux *http_mux_;
@ -110,7 +123,7 @@ public:
};
// The dynamic http connection, never drop the body.
class ISrsDynamicHttpConn: public ISrsConnection, public ISrsStartable, public ISrsHttpConnOwner, public ISrsReloadHandler
class ISrsDynamicHttpConn : public ISrsConnection, public ISrsStartable, public ISrsHttpConnOwner
{
public:
ISrsDynamicHttpConn();
@ -122,14 +135,18 @@ public:
// The dynamic http connection, never drop the body.
class SrsDynamicHttpConn : public ISrsDynamicHttpConn
{
private:
ISrsAppConfig *config_;
ISrsAppFactory *app_factory_;
private:
// The manager object to manage the connection.
ISrsResourceManager *manager_;
std::string output_;
SrsPithyPrint *pprint_;
SrsSimpleRtmpClient *sdk_;
SrsTcpConnection *skt_;
SrsHttpConn *conn_;
ISrsBasicRtmpClient *sdk_;
ISrsProtocolReadWriter *skt_;
ISrsHttpConn *conn_;
private:
// The ip and port of client.

View File

@ -337,6 +337,7 @@ public:
virtual std::string get_https_stream_ssl_key() = 0;
virtual std::string get_https_stream_ssl_cert() = 0;
virtual std::string get_http_stream_dir() = 0;
virtual bool get_http_stream_crossdomain() = 0;
public:
// WebRTC config

View File

@ -49,6 +49,14 @@ ISrsHttpConnOwner::~ISrsHttpConnOwner()
{
}
ISrsHttpConn::ISrsHttpConn()
{
}
ISrsHttpConn::~ISrsHttpConn()
{
}
SrsHttpConn::SrsHttpConn(ISrsHttpConnOwner *handler, ISrsProtocolReadWriter *fd, ISrsHttpServeMux *m, string cip, int cport)
{
parser_ = new SrsHttpParser();

View File

@ -58,9 +58,27 @@ public:
virtual srs_error_t on_conn_done(srs_error_t r0) = 0;
};
// The HTTP connection, for HTTP stream or static file.
class ISrsHttpConn : public ISrsConnection, public ISrsStartable, public ISrsCoroutineHandler, public ISrsExpire
{
public:
ISrsHttpConn();
virtual ~ISrsHttpConn();
public:
// Whether the connection coroutine is error or terminated.
virtual srs_error_t pull() = 0;
// Whether enable the CORS(cross-domain).
virtual srs_error_t set_crossdomain_enabled(bool v) = 0;
// Whether enable the Auth.
virtual srs_error_t set_auth_enabled(bool auth_enabled) = 0;
// Whether enable the JSONP.
virtual srs_error_t set_jsonp(bool v) = 0;
};
// TODO: FIXME: Should rename to roundtrip or responder, not connection.
// The http connection which request the static or stream content.
class SrsHttpConn : public ISrsConnection, public ISrsStartable, public ISrsCoroutineHandler, public ISrsExpire
class SrsHttpConn : public ISrsHttpConn
{
protected:
SrsHttpParser *parser_;

File diff suppressed because it is too large Load Diff

View File

@ -12,10 +12,12 @@
*/
#include <srs_utest.hpp>
#include <srs_app_caster_flv.hpp>
#include <srs_app_config.hpp>
#include <srs_app_factory.hpp>
#include <srs_app_listener.hpp>
#include <srs_app_mpegts_udp.hpp>
#include <srs_kernel_pithy_print.hpp>
#include <srs_protocol_raw_avc.hpp>
#include <srs_protocol_rtmp_conn.hpp>
#include <srs_utest_app10.hpp>
@ -161,4 +163,297 @@ public:
void reset();
};
// Mock ISrsAppConfig for testing SrsHttpFlvListener
class MockAppConfigForHttpFlvListener : public MockAppConfig
{
public:
int stream_caster_listen_port_;
public:
MockAppConfigForHttpFlvListener();
virtual ~MockAppConfigForHttpFlvListener();
public:
virtual int get_stream_caster_listen(SrsConfDirective *conf);
};
// Mock SrsTcpListener for testing SrsHttpFlvListener
class MockTcpListenerForHttpFlv : public SrsTcpListener
{
public:
std::string endpoint_ip_;
int endpoint_port_;
std::string label_;
bool set_endpoint_called_;
bool set_label_called_;
bool listen_called_;
bool close_called_;
public:
MockTcpListenerForHttpFlv(ISrsTcpHandler *h);
virtual ~MockTcpListenerForHttpFlv();
public:
virtual ISrsListener *set_endpoint(const std::string &i, int p);
virtual ISrsListener *set_label(const std::string &label);
virtual srs_error_t listen();
void close();
void reset();
};
// Mock ISrsAppCasterFlv for testing SrsHttpFlvListener
class MockAppCasterFlv : public ISrsAppCasterFlv
{
public:
bool initialize_called_;
bool on_tcp_client_called_;
srs_error_t initialize_error_;
srs_error_t on_tcp_client_error_;
public:
MockAppCasterFlv();
virtual ~MockAppCasterFlv();
public:
virtual srs_error_t initialize(SrsConfDirective *c);
virtual srs_error_t on_tcp_client(ISrsListener *listener, srs_netfd_t stfd);
virtual srs_error_t start();
virtual bool empty();
virtual size_t size();
virtual void add(ISrsResource *conn, bool *exists);
virtual void add_with_id(const std::string &id, ISrsResource *conn);
virtual void add_with_fast_id(uint64_t id, ISrsResource *conn);
virtual void add_with_name(const std::string &name, ISrsResource *conn);
virtual ISrsResource *at(int index);
virtual ISrsResource *find_by_id(std::string id);
virtual ISrsResource *find_by_fast_id(uint64_t id);
virtual ISrsResource *find_by_name(std::string name);
virtual void remove(ISrsResource *c);
virtual void subscribe(ISrsDisposingHandler *h);
virtual void unsubscribe(ISrsDisposingHandler *h);
virtual srs_error_t serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessage *r);
void reset();
};
// Mock ISrsAppConfig for testing SrsAppCasterFlv
class MockAppConfigForAppCasterFlv : public MockAppConfig
{
public:
std::string stream_caster_output_;
public:
MockAppConfigForAppCasterFlv();
virtual ~MockAppConfigForAppCasterFlv();
public:
virtual std::string get_stream_caster_output(SrsConfDirective *conf);
};
// Mock SrsHttpServeMux for testing SrsAppCasterFlv
class MockHttpServeMuxForAppCasterFlv : public SrsHttpServeMux
{
public:
bool handle_called_;
std::string handle_pattern_;
ISrsHttpHandler *handle_handler_;
srs_error_t handle_error_;
public:
MockHttpServeMuxForAppCasterFlv();
virtual ~MockHttpServeMuxForAppCasterFlv();
public:
virtual srs_error_t handle(std::string pattern, ISrsHttpHandler *handler);
void reset();
};
// Mock SrsResourceManager for testing SrsAppCasterFlv
class MockResourceManagerForAppCasterFlv : public SrsResourceManager
{
public:
bool start_called_;
srs_error_t start_error_;
public:
MockResourceManagerForAppCasterFlv();
virtual ~MockResourceManagerForAppCasterFlv();
public:
virtual srs_error_t start();
void reset();
};
// Mock ISrsHttpResponseReader for testing SrsDynamicHttpConn::do_proxy
class MockHttpResponseReaderForDynamicConn : public ISrsHttpResponseReader
{
public:
std::string content_;
size_t read_pos_;
bool eof_;
public:
MockHttpResponseReaderForDynamicConn();
virtual ~MockHttpResponseReaderForDynamicConn();
public:
virtual bool eof();
virtual srs_error_t read(void *buf, size_t size, ssize_t *nread);
void reset();
};
// Mock ISrsFlvDecoder for testing SrsDynamicHttpConn::do_proxy
class MockFlvDecoderForDynamicConn : public ISrsFlvDecoder
{
public:
bool read_tag_header_called_;
bool read_tag_data_called_;
bool read_previous_tag_size_called_;
srs_error_t read_tag_header_error_;
srs_error_t read_tag_data_error_;
srs_error_t read_previous_tag_size_error_;
// Mock return values for read_tag_header
char tag_type_;
int32_t tag_size_;
uint32_t tag_time_;
// Mock tag data to return
char *tag_data_;
int tag_data_size_;
public:
MockFlvDecoderForDynamicConn();
virtual ~MockFlvDecoderForDynamicConn();
public:
virtual srs_error_t initialize(ISrsReader *fr);
virtual srs_error_t read_header(char header[9]);
virtual srs_error_t read_tag_header(char *ptype, int32_t *pdata_size, uint32_t *ptime);
virtual srs_error_t read_tag_data(char *data, int32_t size);
virtual srs_error_t read_previous_tag_size(char previous_tag_size[4]);
void reset();
};
// Mock ISrsBasicRtmpClient for testing SrsDynamicHttpConn::do_proxy
class MockRtmpClientForDynamicConn : public ISrsBasicRtmpClient
{
public:
bool connect_called_;
bool publish_called_;
bool close_called_;
bool send_and_free_message_called_;
srs_error_t connect_error_;
srs_error_t publish_error_;
srs_error_t send_and_free_message_error_;
int stream_id_;
int send_message_count_;
public:
MockRtmpClientForDynamicConn();
virtual ~MockRtmpClientForDynamicConn();
public:
virtual srs_error_t connect();
virtual void close();
virtual srs_error_t publish(int chunk_size, bool with_vhost = true, std::string *pstream = NULL);
virtual srs_error_t play(int chunk_size, bool with_vhost = true, std::string *pstream = NULL);
virtual void kbps_sample(const char *label, srs_utime_t age);
virtual srs_error_t recv_message(SrsRtmpCommonMessage **pmsg);
virtual srs_error_t decode_message(SrsRtmpCommonMessage *msg, SrsRtmpCommand **ppacket);
virtual srs_error_t send_and_free_messages(SrsMediaPacket **msgs, int nb_msgs);
virtual srs_error_t send_and_free_message(SrsMediaPacket *msg);
virtual void set_recv_timeout(srs_utime_t timeout);
virtual int sid();
void reset();
};
// Mock ISrsAppFactory for testing SrsDynamicHttpConn::do_proxy
class MockAppFactoryForDynamicConn : public SrsAppFactory
{
public:
MockRtmpClientForDynamicConn *mock_rtmp_client_;
bool create_rtmp_client_called_;
public:
MockAppFactoryForDynamicConn();
virtual ~MockAppFactoryForDynamicConn();
public:
virtual ISrsBasicRtmpClient *create_rtmp_client(std::string url, srs_utime_t cto, srs_utime_t sto);
void reset();
};
// Mock ISrsPithyPrint for testing SrsDynamicHttpConn::do_proxy
class MockPithyPrintForDynamicConn : public ISrsPithyPrint
{
public:
bool elapse_called_;
bool can_print_called_;
bool can_print_result_;
srs_utime_t age_value_;
public:
MockPithyPrintForDynamicConn();
virtual ~MockPithyPrintForDynamicConn();
public:
virtual void elapse();
virtual bool can_print();
virtual srs_utime_t age();
void reset();
};
// Mock ISrsResourceManager for testing SrsDynamicHttpConn
class MockResourceManagerForDynamicConn : public ISrsResourceManager
{
public:
bool remove_called_;
ISrsResource *removed_resource_;
public:
MockResourceManagerForDynamicConn();
virtual ~MockResourceManagerForDynamicConn();
public:
virtual srs_error_t start();
virtual bool empty();
virtual size_t size();
virtual void add(ISrsResource *conn, bool *exists = NULL);
virtual void add_with_id(const std::string &id, ISrsResource *conn);
virtual void add_with_fast_id(uint64_t id, ISrsResource *conn);
virtual void add_with_name(const std::string &name, ISrsResource *conn);
virtual ISrsResource *at(int index);
virtual ISrsResource *find_by_id(std::string id);
virtual ISrsResource *find_by_fast_id(uint64_t id);
virtual ISrsResource *find_by_name(std::string name);
virtual void remove(ISrsResource *c);
virtual void subscribe(ISrsDisposingHandler *h);
virtual void unsubscribe(ISrsDisposingHandler *h);
void reset();
};
// Mock ISrsHttpConn for testing SrsDynamicHttpConn
class MockHttpConnForDynamicConn : public ISrsHttpConn
{
public:
std::string remote_ip_;
SrsContextId context_id_;
public:
MockHttpConnForDynamicConn();
virtual ~MockHttpConnForDynamicConn();
public:
virtual srs_error_t start();
virtual srs_error_t cycle();
virtual srs_error_t pull();
virtual srs_error_t set_crossdomain_enabled(bool v);
virtual srs_error_t set_auth_enabled(bool auth_enabled);
virtual srs_error_t set_jsonp(bool v);
virtual std::string remote_ip();
virtual const SrsContextId &get_id();
virtual std::string desc();
virtual void expire();
};
#endif

View File

@ -291,6 +291,7 @@ public:
virtual std::string get_https_stream_ssl_key() { return ""; }
virtual std::string get_https_stream_ssl_cert() { return ""; }
virtual std::string get_http_stream_dir() { return ""; }
virtual bool get_http_stream_crossdomain() { return false; }
virtual bool get_rtc_server_enabled() { return false; }
virtual bool get_rtc_server_tcp_enabled() { return false; }
virtual std::vector<std::string> get_rtc_server_tcp_listens() { return std::vector<std::string>(); }