mirror of
https://github.com/ossrs/srs.git
synced 2025-02-15 04:42:04 +00:00
Merge branch '3.0release' into develop
This commit is contained in:
commit
048742f468
20 changed files with 655 additions and 88 deletions
|
@ -148,6 +148,10 @@ For previous versions, please read:
|
|||
|
||||
## V3 changes
|
||||
|
||||
* v3.0, 2020-01-05, Always use string instance to avoid crash risk. 3.0.95
|
||||
* v3.0, 2020-01-05, For [#460][bug #460], fix ipv6 hostport parsing bug. 3.0.94
|
||||
* v3.0, 2020-01-05, For [#460][bug #460], fix ipv6 intranet address filter bug. 3.0.93
|
||||
* v3.0, 2020-01-05, For [#1543][bug #1543], use getpeername to retrieve client ip. 3.0.92
|
||||
* v3.0, 2020-01-02, For [#1042][bug #1042], improve test coverage for config. 3.0.91
|
||||
* v3.0, 2019-12-30, Fix mp4 security issue, check buffer when required size is variable.
|
||||
* <strong>v3.0, 2019-12-29, [3.0 alpha7(3.0.90)][r3.0a7] released. 116356 lines.</strong>
|
||||
|
@ -1583,6 +1587,7 @@ Winlin
|
|||
[bug #1105]: https://github.com/ossrs/srs/issues/1105
|
||||
[bug #1544]: https://github.com/ossrs/srs/issues/1544
|
||||
[bug #1255]: https://github.com/ossrs/srs/issues/1255
|
||||
[bug #1543]: https://github.com/ossrs/srs/issues/1543
|
||||
[bug #xxxxxxxxxxxxx]: https://github.com/ossrs/srs/issues/xxxxxxxxxxxxx
|
||||
|
||||
[bug #1111]: https://github.com/ossrs/srs/issues/1111
|
||||
|
|
|
@ -296,7 +296,7 @@ bool srs_config_apply_filter(SrsConfDirective* dvr_apply, SrsRequest* req)
|
|||
return false;
|
||||
}
|
||||
|
||||
string srs_config_bool2switch(const string& sbool)
|
||||
string srs_config_bool2switch(string sbool)
|
||||
{
|
||||
return sbool == "true"? "on":"off";
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ extern bool srs_stream_caster_is_flv(std::string caster);
|
|||
extern bool srs_config_apply_filter(SrsConfDirective* dvr_apply, SrsRequest* req);
|
||||
|
||||
// Convert bool in str to on/off
|
||||
extern std::string srs_config_bool2switch(const std::string& sbool);
|
||||
extern std::string srs_config_bool2switch(std::string sbool);
|
||||
|
||||
// Parse loaded vhost directives to compatible mode.
|
||||
// For exmaple, SRS1/2 use the follow refer style:
|
||||
|
|
|
@ -81,7 +81,7 @@ int SrsDummyCoroutine::cid()
|
|||
|
||||
_ST_THREAD_CREATE_PFN _pfn_st_thread_create = (_ST_THREAD_CREATE_PFN)st_thread_create;
|
||||
|
||||
SrsSTCoroutine::SrsSTCoroutine(const string& n, ISrsCoroutineHandler* h, int cid)
|
||||
SrsSTCoroutine::SrsSTCoroutine(string n, ISrsCoroutineHandler* h, int cid)
|
||||
{
|
||||
name = n;
|
||||
handler = h;
|
||||
|
|
|
@ -132,7 +132,7 @@ private:
|
|||
public:
|
||||
// Create a thread with name n and handler h.
|
||||
// @remark User can specify a cid for thread to use, or we will allocate a new one.
|
||||
SrsSTCoroutine(const std::string& n, ISrsCoroutineHandler* h, int cid = 0);
|
||||
SrsSTCoroutine(std::string n, ISrsCoroutineHandler* h, int cid = 0);
|
||||
virtual ~SrsSTCoroutine();
|
||||
public:
|
||||
// Start the thread.
|
||||
|
|
|
@ -1142,7 +1142,7 @@ string srs_get_peer_ip(int fd)
|
|||
// discovery client information
|
||||
sockaddr_storage addr;
|
||||
socklen_t addrlen = sizeof(addr);
|
||||
if (getsockname(fd, (sockaddr*)&addr, &addrlen) == -1) {
|
||||
if (getpeername(fd, (sockaddr*)&addr, &addrlen) == -1) {
|
||||
return "";
|
||||
}
|
||||
|
||||
|
@ -1157,7 +1157,7 @@ string srs_get_peer_ip(int fd)
|
|||
return std::string(saddr);
|
||||
}
|
||||
|
||||
bool srs_is_boolean(const string& str)
|
||||
bool srs_is_boolean(string str)
|
||||
{
|
||||
return str == "true" || str == "false";
|
||||
}
|
||||
|
|
|
@ -644,7 +644,7 @@ extern std::string srs_get_peer_ip(int fd);
|
|||
// is_bool("true") == true
|
||||
// is_bool("false") == true
|
||||
// otherwise, false.
|
||||
extern bool srs_is_boolean(const std::string& str);
|
||||
extern bool srs_is_boolean(std::string str);
|
||||
|
||||
// Dump summaries for /api/v1/summaries.
|
||||
extern void srs_api_dump_summaries(SrsJsonObject* obj);
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
// The version config.
|
||||
#define VERSION_MAJOR 3
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 91
|
||||
#define VERSION_REVISION 95
|
||||
|
||||
// The macros generated by configure script.
|
||||
#include <srs_auto_headers.hpp>
|
||||
|
|
|
@ -110,12 +110,12 @@ void srs_mp4_delimiter_newline(stringstream& ss, SrsMp4DumpContext dc)
|
|||
srs_mp4_padding(ss, dc);
|
||||
}
|
||||
|
||||
int srs_mp4_string_length(const string& v)
|
||||
int srs_mp4_string_length(string v)
|
||||
{
|
||||
return (int)v.length()+1;
|
||||
}
|
||||
|
||||
void srs_mp4_string_write(SrsBuffer* buf, const string& v)
|
||||
void srs_mp4_string_write(SrsBuffer* buf, string v)
|
||||
{
|
||||
if (!v.empty()) {
|
||||
buf->write_bytes((char*)v.data(), (int)v.length());
|
||||
|
|
|
@ -2169,7 +2169,7 @@ std::stringstream& srs_dumps_array(std::vector<T>&arr, std::stringstream& ss, Sr
|
|||
|
||||
pfn(elem, ss, dc);
|
||||
|
||||
if (i < limit - 1) {
|
||||
if ((int)i < limit - 1) {
|
||||
delimiter(ss, dc);
|
||||
}
|
||||
}
|
||||
|
@ -2192,7 +2192,7 @@ std::stringstream& srs_dumps_array(T* arr, int size, std::stringstream& ss, SrsM
|
|||
|
||||
pfn(elem, ss, dc);
|
||||
|
||||
if (i < limit - 1) {
|
||||
if ((int)i < limit - 1) {
|
||||
delimiter(ss, dc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -170,44 +170,60 @@ string srs_dns_resolve(string host, int& family)
|
|||
{
|
||||
addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = family;
|
||||
hints.ai_family = family;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFree(addrinfo, r);
|
||||
|
||||
if(getaddrinfo(host.c_str(), NULL, NULL, &r)) {
|
||||
if(getaddrinfo(host.c_str(), NULL, &hints, &r)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
char saddr[64];
|
||||
char* h = (char*)saddr;
|
||||
socklen_t nbh = sizeof(saddr);
|
||||
const int r0 = getnameinfo(r->ai_addr, r->ai_addrlen, h, nbh, NULL, 0, NI_NUMERICHOST);
|
||||
|
||||
if(!r0) {
|
||||
family = r->ai_family;
|
||||
return string(saddr);
|
||||
char shost[64];
|
||||
memset(shost, 0, sizeof(shost));
|
||||
if (getnameinfo(r->ai_addr, r->ai_addrlen, shost, sizeof(shost), NULL, 0, NI_NUMERICHOST)) {
|
||||
return "";
|
||||
}
|
||||
return "";
|
||||
|
||||
family = r->ai_family;
|
||||
return string(shost);
|
||||
}
|
||||
|
||||
void srs_parse_hostport(const string& hostport, string& host, int& port)
|
||||
void srs_parse_hostport(string hostport, string& host, int& port)
|
||||
{
|
||||
const size_t pos = hostport.rfind(":"); // Look for ":" from the end, to work with IPv6.
|
||||
if (pos != std::string::npos) {
|
||||
const string p = hostport.substr(pos + 1);
|
||||
if ((pos >= 1) &&
|
||||
(hostport[0] == '[') &&
|
||||
(hostport[pos - 1] == ']')) {
|
||||
// Handle IPv6 in RFC 2732 format, e.g. [3ffe:dead:beef::1]:1935
|
||||
host = hostport.substr(1, pos - 2);
|
||||
} else {
|
||||
// Handle IP address
|
||||
host = hostport.substr(0, pos);
|
||||
}
|
||||
port = ::atoi(p.c_str());
|
||||
} else {
|
||||
// No host or port.
|
||||
if (hostport.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t pos = string::npos;
|
||||
|
||||
// Host only for ipv4.
|
||||
if ((pos = hostport.rfind(":")) == string::npos) {
|
||||
host = hostport;
|
||||
return;
|
||||
}
|
||||
|
||||
// For ipv4(only one colon), host:port.
|
||||
if (hostport.find(":") == pos) {
|
||||
host = hostport.substr(0, pos);
|
||||
string p = hostport.substr(pos + 1);
|
||||
if (!p.empty()) {
|
||||
port = ::atoi(p.c_str());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Host only for ipv6.
|
||||
if (hostport.at(0) != '[' || (pos = hostport.rfind("]:")) == string::npos) {
|
||||
host = hostport;
|
||||
return;
|
||||
}
|
||||
|
||||
// For ipv6, [host]:port.
|
||||
host = hostport.substr(1, pos - 1);
|
||||
string p = hostport.substr(pos + 2);
|
||||
if (!p.empty()) {
|
||||
port = ::atoi(p.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ extern std::string srs_dns_resolve(std::string host, int& family);
|
|||
|
||||
// Split the host:port to host and port.
|
||||
// @remark the hostport format in <host[:port]>, where port is optional.
|
||||
extern void srs_parse_hostport(const std::string& hostport, std::string& host, int& port);
|
||||
extern void srs_parse_hostport(std::string hostport, std::string& host, int& port);
|
||||
|
||||
// Parse the endpoint to ip and port.
|
||||
// @remark The hostport format in <[ip:]port>, where ip is default to "0.0.0.0".
|
||||
|
|
|
@ -1731,7 +1731,7 @@ SrsJsonAny* srs_json_parse_tree(json_value* node)
|
|||
}
|
||||
}
|
||||
|
||||
SrsJsonAny* SrsJsonAny::loads(const string& str)
|
||||
SrsJsonAny* SrsJsonAny::loads(string str)
|
||||
{
|
||||
if (str.empty()) {
|
||||
return NULL;
|
||||
|
|
|
@ -107,7 +107,7 @@ public:
|
|||
public:
|
||||
// Read json tree from string.
|
||||
// @return json object. NULL if error.
|
||||
static SrsJsonAny* loads(const std::string& str);
|
||||
static SrsJsonAny* loads(std::string str);
|
||||
};
|
||||
|
||||
class SrsJsonObject : public SrsJsonAny
|
||||
|
|
|
@ -157,7 +157,7 @@ srs_error_t srs_tcp_connect(string server, int port, srs_utime_t tm, srs_netfd_t
|
|||
|
||||
addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
|
@ -187,6 +187,43 @@ srs_error_t srs_tcp_connect(string server, int port, srs_utime_t tm, srs_netfd_t
|
|||
return srs_success;
|
||||
}
|
||||
|
||||
srs_error_t do_srs_tcp_listen(int fd, addrinfo* r, srs_netfd_t* pfd)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
// Detect alive for TCP connection.
|
||||
// @see https://github.com/ossrs/srs/issues/1044
|
||||
if ((err = srs_fd_keepalive(fd)) != srs_success) {
|
||||
return srs_error_wrap(err, "set keepalive");
|
||||
}
|
||||
|
||||
if ((err = srs_fd_closeexec(fd)) != srs_success) {
|
||||
return srs_error_wrap(err, "set closeexec");
|
||||
}
|
||||
|
||||
if ((err = srs_fd_reuseaddr(fd)) != srs_success) {
|
||||
return srs_error_wrap(err, "set reuseaddr");
|
||||
}
|
||||
|
||||
if ((err = srs_fd_reuseport(fd)) != srs_success) {
|
||||
return srs_error_wrap(err, "set reuseport");
|
||||
}
|
||||
|
||||
if (bind(fd, r->ai_addr, r->ai_addrlen) == -1) {
|
||||
return srs_error_new(ERROR_SOCKET_BIND, "bind");
|
||||
}
|
||||
|
||||
if (::listen(fd, SERVER_LISTEN_BACKLOG) == -1) {
|
||||
return srs_error_new(ERROR_SOCKET_LISTEN, "listen");
|
||||
}
|
||||
|
||||
if ((*pfd = srs_netfd_open_socket(fd)) == NULL){
|
||||
return srs_error_new(ERROR_ST_OPEN_SOCKET, "st open");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t srs_tcp_listen(std::string ip, int port, srs_netfd_t* pfd)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
@ -213,41 +250,36 @@ srs_error_t srs_tcp_listen(std::string ip, int port, srs_netfd_t* pfd)
|
|||
r->ai_family, r->ai_socktype, r->ai_protocol);
|
||||
}
|
||||
|
||||
// Detect alive for TCP connection.
|
||||
// @see https://github.com/ossrs/srs/issues/1044
|
||||
if ((err = srs_fd_keepalive(fd)) != srs_success) {
|
||||
if ((err = do_srs_tcp_listen(fd, r, pfd)) != srs_success) {
|
||||
::close(fd);
|
||||
return srs_error_wrap(err, "set keepalive fd=%d", fd);
|
||||
return srs_error_wrap(err, "fd=%d", fd);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t do_srs_udp_listen(int fd, addrinfo* r, srs_netfd_t* pfd)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
if ((err = srs_fd_closeexec(fd)) != srs_success) {
|
||||
::close(fd);
|
||||
return srs_error_wrap(err, "set closeexec fd=%d", fd);
|
||||
return srs_error_wrap(err, "set closeexec");
|
||||
}
|
||||
|
||||
if ((err = srs_fd_reuseaddr(fd)) != srs_success) {
|
||||
::close(fd);
|
||||
return srs_error_wrap(err, "set reuseaddr fd=%d", fd);
|
||||
return srs_error_wrap(err, "set reuseaddr");
|
||||
}
|
||||
|
||||
if ((err = srs_fd_reuseport(fd)) != srs_success) {
|
||||
::close(fd);
|
||||
return srs_error_wrap(err, "set reuseport fd=%d", fd);
|
||||
return srs_error_wrap(err, "set reuseport");
|
||||
}
|
||||
|
||||
if (bind(fd, r->ai_addr, r->ai_addrlen) == -1) {
|
||||
::close(fd);
|
||||
return srs_error_new(ERROR_SOCKET_BIND, "bind fd=%d", fd);
|
||||
}
|
||||
|
||||
if (::listen(fd, SERVER_LISTEN_BACKLOG) == -1) {
|
||||
::close(fd);
|
||||
return srs_error_new(ERROR_SOCKET_LISTEN, "listen fd=%d", fd);
|
||||
return srs_error_new(ERROR_SOCKET_BIND, "bind");
|
||||
}
|
||||
|
||||
if ((*pfd = srs_netfd_open_socket(fd)) == NULL){
|
||||
::close(fd);
|
||||
return srs_error_new(ERROR_ST_OPEN_SOCKET, "st open fd=%d", fd);
|
||||
return srs_error_new(ERROR_ST_OPEN_SOCKET, "st open");
|
||||
}
|
||||
|
||||
return err;
|
||||
|
@ -279,29 +311,9 @@ srs_error_t srs_udp_listen(std::string ip, int port, srs_netfd_t* pfd)
|
|||
r->ai_family, r->ai_socktype, r->ai_protocol);
|
||||
}
|
||||
|
||||
if ((err = srs_fd_closeexec(fd)) != srs_success) {
|
||||
if ((err = do_srs_udp_listen(fd, r, pfd)) != srs_success) {
|
||||
::close(fd);
|
||||
return srs_error_wrap(err, "set closeexec fd=%d", fd);
|
||||
}
|
||||
|
||||
if ((err = srs_fd_reuseaddr(fd)) != srs_success) {
|
||||
::close(fd);
|
||||
return srs_error_wrap(err, "set reuseaddr fd=%d", fd);
|
||||
}
|
||||
|
||||
if ((err = srs_fd_reuseport(fd)) != srs_success) {
|
||||
::close(fd);
|
||||
return srs_error_wrap(err, "set reuseport fd=%d", fd);
|
||||
}
|
||||
|
||||
if (bind(fd, r->ai_addr, r->ai_addrlen) == -1) {
|
||||
::close(fd);
|
||||
return srs_error_new(ERROR_SOCKET_BIND, "bind fd=%d", fd);
|
||||
}
|
||||
|
||||
if ((*pfd = srs_netfd_open_socket(fd)) == NULL){
|
||||
::close(fd);
|
||||
return srs_error_new(ERROR_ST_OPEN_SOCKET, "st open fd=%d", fd);
|
||||
return srs_error_wrap(err, "fd=%d", fd);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
|
|
@ -51,7 +51,7 @@ bool srs_string_is_rtmp(string url)
|
|||
return srs_string_starts_with(url, "rtmp://");
|
||||
}
|
||||
|
||||
bool srs_is_digit_number(const string& str)
|
||||
bool srs_is_digit_number(string str)
|
||||
{
|
||||
if (str.empty()) {
|
||||
return false;
|
||||
|
@ -115,8 +115,28 @@ bool srs_net_device_is_internet(const sockaddr* addr)
|
|||
}
|
||||
} else if(addr->sa_family == AF_INET6) {
|
||||
const sockaddr_in6* a6 = (const sockaddr_in6*)addr;
|
||||
if ((IN6_IS_ADDR_LINKLOCAL(&a6->sin6_addr)) ||
|
||||
(IN6_IS_ADDR_SITELOCAL(&a6->sin6_addr))) {
|
||||
|
||||
// IPv6 loopback is ::1
|
||||
if (IN6_IS_ADDR_LOOPBACK(&a6->sin6_addr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// IPv6 unspecified is ::
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&a6->sin6_addr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// From IPv4, you might know APIPA (Automatic Private IP Addressing) or AutoNet.
|
||||
// Whenever automatic IP configuration through DHCP fails.
|
||||
// The prefix of a site-local address is FE80::/10.
|
||||
if (IN6_IS_ADDR_LINKLOCAL(&a6->sin6_addr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Site-local addresses are equivalent to private IP addresses in IPv4.
|
||||
// The prefix of a site-local address is FEC0::/10.
|
||||
// https://4sysops.com/archives/ipv6-tutorial-part-6-site-local-addresses-and-link-local-addresses/
|
||||
if (IN6_IS_ADDR_SITELOCAL(&a6->sin6_addr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ extern bool srs_string_is_rtmp(std::string url);
|
|||
// is_digit("10e3") === false
|
||||
// is_digit("!1234567890") === false
|
||||
// is_digit("") === false
|
||||
extern bool srs_is_digit_number(const std::string& str);
|
||||
extern bool srs_is_digit_number(std::string str);
|
||||
|
||||
// Get local ip, fill to @param ips
|
||||
extern std::vector<std::string>& srs_get_local_ips();
|
||||
|
|
|
@ -4253,6 +4253,118 @@ VOID TEST(KernelUtilityTest, CoverTimeUtilityAll)
|
|||
|
||||
_srs_system_time_us_cache -= 300*1000 * 1000 + 1;
|
||||
EXPECT_TRUE(srs_update_system_time() > 0);
|
||||
|
||||
if (true) {
|
||||
string host = "127.0.0.1:1935";
|
||||
int port = 0;
|
||||
srs_parse_hostport(host, host, port);
|
||||
EXPECT_EQ(1935, port);
|
||||
EXPECT_STREQ("127.0.0.1", host.c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
string host;
|
||||
int port = 8080;
|
||||
srs_parse_hostport("::1", host, port);
|
||||
EXPECT_EQ(8080, port);
|
||||
EXPECT_STREQ("::1", host.c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
string host;
|
||||
int port = 8080;
|
||||
srs_parse_hostport("::", host, port);
|
||||
EXPECT_EQ(8080, port);
|
||||
EXPECT_STREQ("::", host.c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
string host;
|
||||
int port = 0;
|
||||
srs_parse_hostport("3ffe:dead:beef::1", host, port);
|
||||
EXPECT_EQ(0, port);
|
||||
EXPECT_STREQ("3ffe:dead:beef::1", host.c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
string host;
|
||||
int port = 10;
|
||||
srs_parse_hostport("2001:da8:6000:291:21f:d0ff:fed4:928c", host, port);
|
||||
EXPECT_EQ(10, port);
|
||||
EXPECT_STREQ("2001:da8:6000:291:21f:d0ff:fed4:928c", host.c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
string host;
|
||||
int port = 0;
|
||||
srs_parse_hostport("[2001:da8:6000:291:21f:d0ff:fed4:928c]:167", host, port);
|
||||
EXPECT_EQ(167, port);
|
||||
EXPECT_STREQ("2001:da8:6000:291:21f:d0ff:fed4:928c", host.c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
string host;
|
||||
int port = 0;
|
||||
srs_parse_hostport("[::A.B.C.D]:167", host, port);
|
||||
EXPECT_EQ(167, port);
|
||||
EXPECT_STREQ("::A.B.C.D", host.c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
string host;
|
||||
int port = 0;
|
||||
srs_parse_hostport("::A.B.C.D", host, port);
|
||||
EXPECT_EQ(0, port);
|
||||
EXPECT_STREQ("::A.B.C.D", host.c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
string host;
|
||||
int port = 0;
|
||||
srs_parse_hostport("[::FFFF:A.B.C.D]:167", host, port);
|
||||
EXPECT_EQ(167, port);
|
||||
EXPECT_STREQ("::FFFF:A.B.C.D", host.c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
string host;
|
||||
int port = 0;
|
||||
srs_parse_hostport("[ff00::]:167", host, port);
|
||||
EXPECT_EQ(167, port);
|
||||
EXPECT_STREQ("ff00::", host.c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
string host;
|
||||
int port = 0;
|
||||
srs_parse_hostport("[fe80::a00:27ff:fe84:be2%eth0]:167", host, port);
|
||||
EXPECT_EQ(167, port);
|
||||
EXPECT_STREQ("fe80::a00:27ff:fe84:be2%eth0", host.c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
string host;
|
||||
int port = 0;
|
||||
srs_parse_hostport("::FFFF:A.B.C.D", host, port);
|
||||
EXPECT_EQ(0, port);
|
||||
EXPECT_STREQ("::FFFF:A.B.C.D", host.c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
string host;
|
||||
int port = 8080;
|
||||
srs_parse_hostport("", host, port);
|
||||
EXPECT_EQ(8080, port);
|
||||
EXPECT_STREQ("", host.c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
string host;
|
||||
int port = 8080;
|
||||
srs_parse_hostport("3ffe:dead:beef::1", host, port);
|
||||
EXPECT_EQ(8080, port);
|
||||
EXPECT_STREQ("3ffe:dead:beef::1", host.c_str());
|
||||
}
|
||||
|
||||
if (true) {
|
||||
string host;
|
||||
|
|
|
@ -35,6 +35,9 @@ using namespace std;
|
|||
#include <srs_core_autofree.hpp>
|
||||
#include <srs_utest_protocol.hpp>
|
||||
#include <srs_utest_http.hpp>
|
||||
#include <srs_service_utility.hpp>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
class MockSrsConnection : public ISrsConnection
|
||||
{
|
||||
|
@ -679,3 +682,400 @@ VOID TEST(TCPServerTest, MessageWritev)
|
|||
}
|
||||
}
|
||||
|
||||
VOID TEST(TCPServerTest, TCPListen)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
// Failed for invalid ip.
|
||||
if (true) {
|
||||
srs_netfd_t pfd = NULL;
|
||||
HELPER_EXPECT_FAILED(srs_tcp_listen("10.0.0.abc", 1935, &pfd));
|
||||
srs_close_stfd(pfd);
|
||||
}
|
||||
|
||||
// If listen multiple times, should success for we already set the REUSEPORT.
|
||||
if (true) {
|
||||
srs_netfd_t pfd = NULL;
|
||||
HELPER_ASSERT_SUCCESS(srs_tcp_listen("127.0.0.1", 1935, &pfd));
|
||||
|
||||
srs_netfd_t pfd2 = NULL;
|
||||
srs_error_t err2 = srs_tcp_listen("127.0.0.1", 1935, &pfd2);
|
||||
|
||||
srs_close_stfd(pfd);
|
||||
srs_close_stfd(pfd2);
|
||||
HELPER_EXPECT_SUCCESS(err2);
|
||||
}
|
||||
|
||||
// Typical listen.
|
||||
if (true) {
|
||||
srs_netfd_t pfd = NULL;
|
||||
HELPER_ASSERT_SUCCESS(srs_tcp_listen("127.0.0.1", 1935, &pfd));
|
||||
srs_close_stfd(pfd);
|
||||
}
|
||||
}
|
||||
|
||||
VOID TEST(TCPServerTest, UDPListen)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
// Failed for invalid ip.
|
||||
if (true) {
|
||||
srs_netfd_t pfd = NULL;
|
||||
HELPER_EXPECT_FAILED(srs_udp_listen("10.0.0.abc", 1935, &pfd));
|
||||
srs_close_stfd(pfd);
|
||||
}
|
||||
|
||||
// If listen multiple times, should success for we already set the REUSEPORT.
|
||||
if (true) {
|
||||
srs_netfd_t pfd = NULL;
|
||||
HELPER_ASSERT_SUCCESS(srs_udp_listen("127.0.0.1", 1935, &pfd));
|
||||
|
||||
srs_netfd_t pfd2 = NULL;
|
||||
srs_error_t err2 = srs_udp_listen("127.0.0.1", 1935, &pfd2);
|
||||
|
||||
srs_close_stfd(pfd);
|
||||
srs_close_stfd(pfd2);
|
||||
HELPER_EXPECT_SUCCESS(err2);
|
||||
}
|
||||
|
||||
// Typical listen.
|
||||
if (true) {
|
||||
srs_netfd_t pfd = NULL;
|
||||
HELPER_ASSERT_SUCCESS(srs_udp_listen("127.0.0.1", 1935, &pfd));
|
||||
srs_close_stfd(pfd);
|
||||
}
|
||||
}
|
||||
|
||||
class MockOnCycleThread : public ISrsCoroutineHandler
|
||||
{
|
||||
public:
|
||||
SrsSTCoroutine trd;
|
||||
srs_cond_t cond;
|
||||
MockOnCycleThread() : trd("mock", this, 0) {
|
||||
cond = srs_cond_new();
|
||||
};
|
||||
virtual ~MockOnCycleThread() {
|
||||
srs_cond_destroy(cond);
|
||||
}
|
||||
virtual srs_error_t cycle() {
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
for (;;) {
|
||||
srs_usleep(10 * SRS_UTIME_MILLISECONDS);
|
||||
srs_cond_signal(cond);
|
||||
// If no one waiting on the cond, directly return event signal more than one time.
|
||||
// If someone waiting, signal them more than one time.
|
||||
srs_cond_signal(cond);
|
||||
|
||||
if ((err = trd.pull()) != srs_success) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
};
|
||||
|
||||
VOID TEST(TCPServerTest, ThreadCondWait)
|
||||
{
|
||||
MockOnCycleThread trd;
|
||||
trd.trd.start();
|
||||
|
||||
srs_usleep(20 * SRS_UTIME_MILLISECONDS);
|
||||
srs_cond_wait(trd.cond);
|
||||
trd.trd.stop();
|
||||
}
|
||||
|
||||
class MockOnCycleThread2 : public ISrsCoroutineHandler
|
||||
{
|
||||
public:
|
||||
SrsSTCoroutine trd;
|
||||
srs_mutex_t lock;
|
||||
MockOnCycleThread2() : trd("mock", this, 0) {
|
||||
lock = srs_mutex_new();
|
||||
};
|
||||
virtual ~MockOnCycleThread2() {
|
||||
srs_mutex_destroy(lock);
|
||||
}
|
||||
virtual srs_error_t cycle() {
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
for (;;) {
|
||||
srs_mutex_lock(lock);
|
||||
srs_usleep(10 * SRS_UTIME_MILLISECONDS);
|
||||
srs_mutex_unlock(lock);
|
||||
|
||||
srs_error_t err = trd.pull();
|
||||
if (err != srs_success) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
};
|
||||
|
||||
VOID TEST(TCPServerTest, ThreadMutexWait)
|
||||
{
|
||||
MockOnCycleThread2 trd;
|
||||
trd.trd.start();
|
||||
|
||||
srs_usleep(20 * SRS_UTIME_MILLISECONDS);
|
||||
|
||||
srs_mutex_lock(trd.lock);
|
||||
trd.trd.stop();
|
||||
srs_mutex_unlock(trd.lock);
|
||||
}
|
||||
|
||||
class MockOnCycleThread3 : public ISrsCoroutineHandler
|
||||
{
|
||||
public:
|
||||
SrsSTCoroutine trd;
|
||||
srs_netfd_t fd;
|
||||
MockOnCycleThread3() : trd("mock", this, 0) {
|
||||
};
|
||||
virtual ~MockOnCycleThread3() {
|
||||
trd.stop();
|
||||
srs_close_stfd(fd);
|
||||
}
|
||||
virtual srs_error_t start(string ip, int port) {
|
||||
srs_error_t err = srs_success;
|
||||
if ((err = srs_tcp_listen(ip, port, &fd)) != srs_success) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return trd.start();
|
||||
}
|
||||
virtual srs_error_t do_cycle(srs_netfd_t cfd) {
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
SrsStSocket skt;
|
||||
if ((err = skt.initialize(cfd)) != srs_success) {
|
||||
return err;
|
||||
}
|
||||
|
||||
skt.set_recv_timeout(1 * SRS_UTIME_SECONDS);
|
||||
skt.set_send_timeout(1 * SRS_UTIME_SECONDS);
|
||||
|
||||
while (true) {
|
||||
if ((err = trd.pull()) != srs_success) {
|
||||
return err;
|
||||
}
|
||||
|
||||
char buf[5];
|
||||
if ((err = skt.read_fully(buf, 5, NULL)) != srs_success) {
|
||||
return err;
|
||||
}
|
||||
if ((err = skt.write(buf, 5, NULL)) != srs_success) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
virtual srs_error_t cycle() {
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
srs_netfd_t cfd = srs_accept(fd, NULL, NULL, SRS_UTIME_NO_TIMEOUT);
|
||||
if (cfd == NULL) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = do_cycle(cfd);
|
||||
srs_close_stfd(cfd);
|
||||
srs_freep(err);
|
||||
|
||||
return err;
|
||||
}
|
||||
};
|
||||
|
||||
VOID TEST(TCPServerTest, TCPClientServer)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
MockOnCycleThread3 trd;
|
||||
HELPER_ASSERT_SUCCESS(trd.start("127.0.0.1", 1935));
|
||||
|
||||
SrsTcpClient c("127.0.0.1", 1935, 1 * SRS_UTIME_SECONDS);
|
||||
HELPER_ASSERT_SUCCESS(c.connect());
|
||||
|
||||
c.set_recv_timeout(1 * SRS_UTIME_SECONDS);
|
||||
c.set_send_timeout(1 * SRS_UTIME_SECONDS);
|
||||
|
||||
if (true) {
|
||||
HELPER_ASSERT_SUCCESS(c.write((void*)"Hello", 5, NULL));
|
||||
|
||||
char buf[6]; HELPER_ARRAY_INIT(buf, 6, 0);
|
||||
HELPER_ASSERT_SUCCESS(c.read(buf, 5, NULL));
|
||||
EXPECT_STREQ("Hello", buf);
|
||||
}
|
||||
|
||||
if (true) {
|
||||
HELPER_ASSERT_SUCCESS(c.write((void*)"Hello", 5, NULL));
|
||||
|
||||
char buf[6]; HELPER_ARRAY_INIT(buf, 6, 0);
|
||||
HELPER_ASSERT_SUCCESS(c.read_fully(buf, 5, NULL));
|
||||
EXPECT_STREQ("Hello", buf);
|
||||
}
|
||||
|
||||
if (true) {
|
||||
HELPER_ASSERT_SUCCESS(c.write((void*)"Hello", 5, NULL));
|
||||
|
||||
char buf[6]; HELPER_ARRAY_INIT(buf, 6, 0);
|
||||
ASSERT_EQ(5, srs_read(c.stfd, buf, 5, 1*SRS_UTIME_SECONDS));
|
||||
EXPECT_STREQ("Hello", buf);
|
||||
}
|
||||
}
|
||||
|
||||
VOID TEST(TCPServerTest, CoverUtility)
|
||||
{
|
||||
EXPECT_TRUE(srs_string_is_http("http://"));
|
||||
EXPECT_TRUE(srs_string_is_http("https://"));
|
||||
EXPECT_TRUE(srs_string_is_http("http://localhost"));
|
||||
EXPECT_TRUE(srs_string_is_http("https://localhost"));
|
||||
EXPECT_FALSE(srs_string_is_http("ftp://"));
|
||||
EXPECT_FALSE(srs_string_is_http("ftps://"));
|
||||
EXPECT_FALSE(srs_string_is_http("http:"));
|
||||
EXPECT_FALSE(srs_string_is_http("https:"));
|
||||
EXPECT_TRUE(srs_string_is_rtmp("rtmp://"));
|
||||
EXPECT_TRUE(srs_string_is_rtmp("rtmp://localhost"));
|
||||
EXPECT_FALSE(srs_string_is_rtmp("http://"));
|
||||
EXPECT_FALSE(srs_string_is_rtmp("rtmp:"));
|
||||
|
||||
// ipv4 loopback
|
||||
if (true) {
|
||||
addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFree(addrinfo, r);
|
||||
ASSERT_TRUE(!getaddrinfo("127.0.0.1", NULL, &hints, &r));
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr));
|
||||
}
|
||||
|
||||
// ipv4 intranet
|
||||
if (true) {
|
||||
addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFree(addrinfo, r);
|
||||
ASSERT_TRUE(!getaddrinfo("192.168.0.1", NULL, &hints, &r));
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr));
|
||||
}
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet("eth0"));
|
||||
|
||||
if (true) {
|
||||
sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0x12000000);
|
||||
EXPECT_TRUE(srs_net_device_is_internet((sockaddr*)&addr));
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0x7f000000);
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr));
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0x7f000001);
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr));
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0x0a000000);
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr));
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0x0a000001);
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr));
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0x0affffff);
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr));
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0xc0a80000);
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr));
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0xc0a80001);
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr));
|
||||
|
||||
addr.sin_addr.s_addr = htonl(0xc0a8ffff);
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)&addr));
|
||||
}
|
||||
|
||||
// Normal ipv6 address.
|
||||
if (true) {
|
||||
addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET6;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFree(addrinfo, r);
|
||||
ASSERT_TRUE(!getaddrinfo("2001:da8:6000:291:21f:d0ff:fed4:928c", NULL, &hints, &r));
|
||||
|
||||
EXPECT_TRUE(srs_net_device_is_internet((sockaddr*)r->ai_addr));
|
||||
}
|
||||
if (true) {
|
||||
addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET6;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFree(addrinfo, r);
|
||||
ASSERT_TRUE(!getaddrinfo("3ffe:dead:beef::1", NULL, &hints, &r));
|
||||
|
||||
EXPECT_TRUE(srs_net_device_is_internet((sockaddr*)r->ai_addr));
|
||||
}
|
||||
|
||||
// IN6_IS_ADDR_UNSPECIFIED
|
||||
if (true) {
|
||||
addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET6;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFree(addrinfo, r);
|
||||
ASSERT_TRUE(!getaddrinfo("::", NULL, &hints, &r));
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr));
|
||||
}
|
||||
|
||||
// IN6_IS_ADDR_SITELOCAL
|
||||
if (true) {
|
||||
addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET6;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFree(addrinfo, r);
|
||||
ASSERT_TRUE(!getaddrinfo("fec0::", NULL, &hints, &r));
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr));
|
||||
}
|
||||
|
||||
// IN6_IS_ADDR_LINKLOCAL
|
||||
if (true) {
|
||||
addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET6;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFree(addrinfo, r);
|
||||
ASSERT_TRUE(!getaddrinfo("FE80::", NULL, &hints, &r));
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr));
|
||||
}
|
||||
|
||||
// IN6_IS_ADDR_LINKLOCAL
|
||||
if (true) {
|
||||
addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET6;
|
||||
|
||||
addrinfo* r = NULL;
|
||||
SrsAutoFree(addrinfo, r);
|
||||
ASSERT_TRUE(!getaddrinfo("::1", NULL, &hints, &r));
|
||||
|
||||
EXPECT_FALSE(srs_net_device_is_internet((sockaddr*)r->ai_addr));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,5 +29,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
*/
|
||||
#include <srs_utest.hpp>
|
||||
|
||||
#include <srs_app_st.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in a new issue