mirror of
https://github.com/ossrs/srs.git
synced 2025-02-12 19:31:53 +00:00
IPv6 support (for 3.0 release) (#988)
* IPv6 support, part 1. * IPv6 support, part 2. * Some more IPv6 work. * Made functions for address:port paŕsing IPv6-capable. * Fixed type (compile warning). * Fixed formatting. * Reverted option change. * Replaced abort() by proper error handling. * Also retrieving local IPv6 addresses now.
This commit is contained in:
parent
db08f1586c
commit
feaae341b9
20 changed files with 296 additions and 201 deletions
|
@ -26,4 +26,4 @@ CONTRIBUTORS ordered by first contribution.
|
||||||
* lovecat<littlefawn@163.com> "Bug fixed"
|
* lovecat<littlefawn@163.com> "Bug fixed"
|
||||||
* panda1986<542638787@qq.com> "Bug fixed"
|
* panda1986<542638787@qq.com> "Bug fixed"
|
||||||
* YueHonghui<hongf.yue@hotmail.com> "Bug fixed"
|
* YueHonghui<hongf.yue@hotmail.com> "Bug fixed"
|
||||||
|
* ThomasDreibholz<dreibh@simula.no> "IPv6 support"
|
||||||
|
|
|
@ -3607,7 +3607,7 @@ srs_error_t SrsConfig::check_normal_config()
|
||||||
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "invalid stats.network=%d", get_stats_network());
|
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "invalid stats.network=%d", get_stats_network());
|
||||||
}
|
}
|
||||||
if (true) {
|
if (true) {
|
||||||
vector<std::string> ips = srs_get_local_ipv4_ips();
|
vector<std::string> ips = srs_get_local_ips();
|
||||||
int index = get_stats_network();
|
int index = get_stats_network();
|
||||||
if (index >= (int)ips.size()) {
|
if (index >= (int)ips.size()) {
|
||||||
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "invalid stats.network=%d of %d",
|
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "invalid stats.network=%d of %d",
|
||||||
|
|
|
@ -68,7 +68,7 @@ srs_error_t SrsHttpHeartbeat::do_heartbeat()
|
||||||
std::string ip = "";
|
std::string ip = "";
|
||||||
std::string device_id = _srs_config->get_heartbeat_device_id();
|
std::string device_id = _srs_config->get_heartbeat_device_id();
|
||||||
|
|
||||||
vector<string>& ips = srs_get_local_ipv4_ips();
|
vector<string>& ips = srs_get_local_ips();
|
||||||
if (!ips.empty()) {
|
if (!ips.empty()) {
|
||||||
ip = ips[_srs_config->get_stats_network() % (int)ips.size()];
|
ip = ips[_srs_config->get_stats_network() % (int)ips.size()];
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <netdb.h>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#include <srs_kernel_log.hpp>
|
#include <srs_kernel_log.hpp>
|
||||||
|
@ -111,20 +112,31 @@ srs_error_t SrsUdpListener::listen()
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
if ((_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
|
char port_string[8];
|
||||||
return srs_error_new(ERROR_SOCKET_CREATE, "create socket");
|
snprintf(port_string, sizeof(port_string), "%d", port);
|
||||||
|
addrinfo hints;
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_DGRAM;
|
||||||
|
hints.ai_flags = AI_NUMERICHOST;
|
||||||
|
addrinfo* result = NULL;
|
||||||
|
if(getaddrinfo(ip.c_str(), port_string, (const addrinfo*)&hints, &result) != 0) {
|
||||||
|
return srs_error_new(ERROR_SYSTEM_IP_INVALID, "bad address");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((_fd = socket(result->ai_family, result->ai_socktype, result->ai_protocol)) == -1) {
|
||||||
|
freeaddrinfo(result);
|
||||||
|
return srs_error_new(ERROR_SOCKET_CREATE, "create linux socket error. ip=%s, port=%d", ip.c_str(), port);
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_fd_close_exec(_fd);
|
srs_fd_close_exec(_fd);
|
||||||
srs_socket_reuse_addr(_fd);
|
srs_socket_reuse_addr(_fd);
|
||||||
|
|
||||||
sockaddr_in addr;
|
if (bind(_fd, result->ai_addr, result->ai_addrlen) == -1) {
|
||||||
addr.sin_family = AF_INET;
|
freeaddrinfo(result);
|
||||||
addr.sin_port = htons(port);
|
return srs_error_new(ERROR_SOCKET_BIND, "bind socket error. ep=%s:%d", ip.c_str(), port);;
|
||||||
addr.sin_addr.s_addr = inet_addr(ip.c_str());
|
|
||||||
if (bind(_fd, (const sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
|
|
||||||
return srs_error_new(ERROR_SOCKET_BIND, "bind socket");
|
|
||||||
}
|
}
|
||||||
|
freeaddrinfo(result);
|
||||||
|
|
||||||
if ((_stfd = srs_netfd_open_socket(_fd)) == NULL){
|
if ((_stfd = srs_netfd_open_socket(_fd)) == NULL){
|
||||||
return srs_error_new(ERROR_ST_OPEN_SOCKET, "st open socket");
|
return srs_error_new(ERROR_ST_OPEN_SOCKET, "st open socket");
|
||||||
|
@ -148,16 +160,15 @@ srs_error_t SrsUdpListener::cycle()
|
||||||
return srs_error_wrap(err, "udp listener");
|
return srs_error_wrap(err, "udp listener");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: FIXME: support ipv6, @see man 7 ipv6
|
sockaddr_storage from;
|
||||||
sockaddr_in from;
|
int nb_from = sizeof(from);
|
||||||
int nb_from = sizeof(sockaddr_in);
|
|
||||||
int nread = 0;
|
int nread = 0;
|
||||||
|
|
||||||
if ((nread = srs_recvfrom(_stfd, buf, nb_buf, (sockaddr*)&from, &nb_from, SRS_UTIME_NO_TIMEOUT)) <= 0) {
|
if ((nread = srs_recvfrom(_stfd, buf, nb_buf, (sockaddr*)&from, &nb_from, SRS_UTIME_NO_TIMEOUT)) <= 0) {
|
||||||
return srs_error_new(ERROR_SOCKET_READ, "udp read, nread=%d", nread);
|
return srs_error_new(ERROR_SOCKET_READ, "udp read, nread=%d", nread);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = handler->on_udp_packet(&from, buf, nread)) != srs_success) {
|
if ((err = handler->on_udp_packet((const sockaddr*)&from, nb_from, buf, nread)) != srs_success) {
|
||||||
return srs_error_wrap(err, "handle packet %d bytes", nread);
|
return srs_error_wrap(err, "handle packet %d bytes", nread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,20 +208,31 @@ srs_error_t SrsTcpListener::listen()
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
if ((_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
|
char port_string[8];
|
||||||
return srs_error_new(ERROR_SOCKET_CREATE, "create socket");
|
snprintf(port_string, sizeof(port_string), "%d", port);
|
||||||
|
addrinfo hints;
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_flags = AI_NUMERICHOST;
|
||||||
|
addrinfo* result = NULL;
|
||||||
|
if(getaddrinfo(ip.c_str(), port_string, (const addrinfo*)&hints, &result) != 0) {
|
||||||
|
return srs_error_new(ERROR_SYSTEM_IP_INVALID, "bad address");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((_fd = socket(result->ai_family, result->ai_socktype, result->ai_protocol)) == -1) {
|
||||||
|
freeaddrinfo(result);
|
||||||
|
return srs_error_new(ERROR_SOCKET_CREATE, "create linux socket error. ip=%s, port=%d", ip.c_str(), port);
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_fd_close_exec(_fd);
|
srs_fd_close_exec(_fd);
|
||||||
srs_socket_reuse_addr(_fd);
|
srs_socket_reuse_addr(_fd);
|
||||||
|
|
||||||
sockaddr_in addr;
|
if (bind(_fd, result->ai_addr, result->ai_addrlen) == -1) {
|
||||||
addr.sin_family = AF_INET;
|
freeaddrinfo(result);
|
||||||
addr.sin_port = htons(port);
|
return srs_error_new(ERROR_SOCKET_BIND, "bind socket error. ep=%s:%d", ip.c_str(), port);;
|
||||||
addr.sin_addr.s_addr = inet_addr(ip.c_str());
|
|
||||||
if (bind(_fd, (const sockaddr*)&addr, sizeof(sockaddr_in)) == -1) {
|
|
||||||
return srs_error_new(ERROR_SOCKET_BIND, "bind socket");
|
|
||||||
}
|
}
|
||||||
|
freeaddrinfo(result);
|
||||||
|
|
||||||
if (::listen(_fd, SERVER_LISTEN_BACKLOG) == -1) {
|
if (::listen(_fd, SERVER_LISTEN_BACKLOG) == -1) {
|
||||||
return srs_error_new(ERROR_SOCKET_LISTEN, "listen socket");
|
return srs_error_new(ERROR_SOCKET_LISTEN, "listen socket");
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
#include <srs_app_st.hpp>
|
#include <srs_app_st.hpp>
|
||||||
#include <srs_app_thread.hpp>
|
#include <srs_app_thread.hpp>
|
||||||
|
|
||||||
struct sockaddr_in;
|
struct sockaddr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the udp packet handler.
|
* the udp packet handler.
|
||||||
|
@ -57,7 +57,7 @@ public:
|
||||||
* @param nb_buf, the size of udp packet bytes.
|
* @param nb_buf, the size of udp packet bytes.
|
||||||
* @remark user should never use the buf, for it's a shared memory bytes.
|
* @remark user should never use the buf, for it's a shared memory bytes.
|
||||||
*/
|
*/
|
||||||
virtual srs_error_t on_udp_packet(sockaddr_in* from, char* buf, int nb_buf) = 0;
|
virtual srs_error_t on_udp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <netdb.h>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#include <srs_app_config.hpp>
|
#include <srs_app_config.hpp>
|
||||||
|
@ -155,10 +156,18 @@ SrsMpegtsOverUdp::~SrsMpegtsOverUdp()
|
||||||
srs_freep(pprint);
|
srs_freep(pprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsMpegtsOverUdp::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf)
|
srs_error_t SrsMpegtsOverUdp::on_udp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf)
|
||||||
{
|
{
|
||||||
std::string peer_ip = inet_ntoa(from->sin_addr);
|
char address_string[64];
|
||||||
int peer_port = ntohs(from->sin_port);
|
char port_string[16];
|
||||||
|
if(getnameinfo(from, fromlen,
|
||||||
|
(char*)&address_string, sizeof(address_string),
|
||||||
|
(char*)&port_string, sizeof(port_string),
|
||||||
|
NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
|
||||||
|
return srs_error_new(ERROR_SYSTEM_IP_INVALID, "bad address");
|
||||||
|
}
|
||||||
|
std::string peer_ip = std::string(address_string);
|
||||||
|
int peer_port = atoi(port_string);
|
||||||
|
|
||||||
// append to buffer.
|
// append to buffer.
|
||||||
buffer->append(buf, nb_buf);
|
buffer->append(buf, nb_buf);
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
#ifdef SRS_AUTO_STREAM_CASTER
|
#ifdef SRS_AUTO_STREAM_CASTER
|
||||||
|
|
||||||
struct sockaddr_in;
|
struct sockaddr;
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ public:
|
||||||
virtual ~SrsMpegtsOverUdp();
|
virtual ~SrsMpegtsOverUdp();
|
||||||
// interface ISrsUdpHandler
|
// interface ISrsUdpHandler
|
||||||
public:
|
public:
|
||||||
virtual srs_error_t on_udp_packet(sockaddr_in* from, char* buf, int nb_buf);
|
virtual srs_error_t on_udp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf);
|
||||||
private:
|
private:
|
||||||
virtual srs_error_t on_udp_bytes(std::string host, int port, char* buf, int nb_buf);
|
virtual srs_error_t on_udp_bytes(std::string host, int port, char* buf, int nb_buf);
|
||||||
// interface ISrsTsHandler
|
// interface ISrsTsHandler
|
||||||
|
|
|
@ -87,7 +87,7 @@ SrsSimpleRtmpClient::~SrsSimpleRtmpClient()
|
||||||
|
|
||||||
srs_error_t SrsSimpleRtmpClient::connect_app()
|
srs_error_t SrsSimpleRtmpClient::connect_app()
|
||||||
{
|
{
|
||||||
std::vector<std::string> ips = srs_get_local_ipv4_ips();
|
std::vector<std::string> ips = srs_get_local_ips();
|
||||||
assert(_srs_config->get_stats_network() < (int)ips.size());
|
assert(_srs_config->get_stats_network() < (int)ips.size());
|
||||||
std::string local_ip = ips[_srs_config->get_stats_network()];
|
std::string local_ip = ips[_srs_config->get_stats_network()];
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ SrsRtpConn::SrsRtpConn(SrsRtspConn* r, int p, int sid)
|
||||||
_port = p;
|
_port = p;
|
||||||
stream_id = sid;
|
stream_id = sid;
|
||||||
// TODO: support listen at <[ip:]port>
|
// TODO: support listen at <[ip:]port>
|
||||||
listener = new SrsUdpListener(this, "0.0.0.0", p);
|
listener = new SrsUdpListener(this, (srs_check_ipv6() ? "::" : "0.0.0.0"), p);
|
||||||
cache = new SrsRtpPacket();
|
cache = new SrsRtpPacket();
|
||||||
pprint = SrsPithyPrint::create_caster();
|
pprint = SrsPithyPrint::create_caster();
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ srs_error_t SrsRtpConn::listen()
|
||||||
return listener->listen();
|
return listener->listen();
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsRtpConn::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf)
|
srs_error_t SrsRtpConn::on_udp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ public:
|
||||||
virtual srs_error_t listen();
|
virtual srs_error_t listen();
|
||||||
// interface ISrsUdpHandler
|
// interface ISrsUdpHandler
|
||||||
public:
|
public:
|
||||||
virtual srs_error_t on_udp_packet(sockaddr_in* from, char* buf, int nb_buf);
|
virtual srs_error_t on_udp_packet(const sockaddr* from, const int fromlen, char* buf, int nb_buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1137,7 +1137,7 @@ srs_error_t SrsServer::listen_stream_caster()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: support listen at <[ip:]port>
|
// TODO: support listen at <[ip:]port>
|
||||||
if ((err = listener->listen("0.0.0.0", port)) != srs_success) {
|
if ((err = listener->listen( (srs_check_ipv6() ? "::" : "0.0.0.0"), port)) != srs_success) {
|
||||||
return srs_error_wrap(err, "listen at %d", port);
|
return srs_error_wrap(err, "listen at %d", port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
#ifdef SRS_OSX
|
#ifdef SRS_OSX
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
@ -1103,76 +1104,84 @@ void srs_update_rtmp_server(int nb_conn, SrsKbps* kbps)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int srs_check_ipv6()
|
||||||
|
{
|
||||||
|
int sd = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||||
|
if(sd >= 0) {
|
||||||
|
close(sd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
string srs_get_local_ip(int fd)
|
string srs_get_local_ip(int fd)
|
||||||
{
|
{
|
||||||
std::string ip;
|
|
||||||
|
|
||||||
// discovery client information
|
// discovery client information
|
||||||
sockaddr_in addr;
|
sockaddr_storage addr;
|
||||||
socklen_t addrlen = sizeof(addr);
|
socklen_t addrlen = sizeof(addr);
|
||||||
if (getsockname(fd, (sockaddr*)&addr, &addrlen) == -1) {
|
if (getsockname(fd, (sockaddr*)&addr, &addrlen) == -1) {
|
||||||
return ip;
|
return "";
|
||||||
}
|
}
|
||||||
srs_verbose("get local ip success.");
|
srs_verbose("get local ip success.");
|
||||||
|
|
||||||
// ip v4 or v6
|
char address_string[64];
|
||||||
char buf[INET6_ADDRSTRLEN];
|
const int success = getnameinfo((const sockaddr*)&addr, addrlen,
|
||||||
memset(buf, 0, sizeof(buf));
|
(char*)&address_string, sizeof(address_string),
|
||||||
|
NULL, 0,
|
||||||
if ((inet_ntop(addr.sin_family, &addr.sin_addr, buf, sizeof(buf))) == NULL) {
|
NI_NUMERICHOST);
|
||||||
return ip;
|
if(success != 0) {
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
ip = buf;
|
srs_verbose("get local ip of client ip=%s, fd=%d", address_string, fd);
|
||||||
|
return std::string(address_string);
|
||||||
srs_verbose("get local ip of client ip=%s, fd=%d", buf, fd);
|
|
||||||
|
|
||||||
return ip;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int srs_get_local_port(int fd)
|
int srs_get_local_port(int fd)
|
||||||
{
|
{
|
||||||
// discovery client information
|
// discovery client information
|
||||||
sockaddr_in addr;
|
sockaddr_storage addr;
|
||||||
socklen_t addrlen = sizeof(addr);
|
socklen_t addrlen = sizeof(addr);
|
||||||
if (getsockname(fd, (sockaddr*)&addr, &addrlen) == -1) {
|
if (getsockname(fd, (sockaddr*)&addr, &addrlen) == -1) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
srs_verbose("get local ip success.");
|
srs_verbose("get local ip success.");
|
||||||
|
|
||||||
int port = ntohs(addr.sin_port);
|
int port = 0;
|
||||||
|
switch(addr.ss_family) {
|
||||||
srs_verbose("get local ip of client port=%s, fd=%d", port, fd);
|
case AF_INET:
|
||||||
|
port = ntohs(((sockaddr_in*)&addr)->sin_port);
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
port = ntohs(((sockaddr_in6*)&addr)->sin6_port);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
srs_verbose("get local port of client port=%s, fd=%d", port, fd);
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
string srs_get_peer_ip(int fd)
|
string srs_get_peer_ip(int fd)
|
||||||
{
|
{
|
||||||
std::string ip;
|
|
||||||
|
|
||||||
// discovery client information
|
// discovery client information
|
||||||
sockaddr_in addr;
|
sockaddr_storage addr;
|
||||||
socklen_t addrlen = sizeof(addr);
|
socklen_t addrlen = sizeof(addr);
|
||||||
if (getpeername(fd, (sockaddr*)&addr, &addrlen) == -1) {
|
if (getsockname(fd, (sockaddr*)&addr, &addrlen) == -1) {
|
||||||
return ip;
|
return "";
|
||||||
}
|
}
|
||||||
srs_verbose("get peer name success.");
|
srs_verbose("get peer ip success.");
|
||||||
|
|
||||||
// ip v4 or v6
|
char address_string[64];
|
||||||
char buf[INET6_ADDRSTRLEN];
|
const int success = getnameinfo((const sockaddr*)&addr, addrlen,
|
||||||
memset(buf, 0, sizeof(buf));
|
(char*)&address_string, sizeof(address_string),
|
||||||
|
NULL, 0,
|
||||||
if ((inet_ntop(addr.sin_family, &addr.sin_addr, buf, sizeof(buf))) == NULL) {
|
NI_NUMERICHOST);
|
||||||
return ip;
|
if(success != 0) {
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
srs_verbose("get peer ip of client ip=%s, fd=%d", buf, fd);
|
|
||||||
|
|
||||||
ip = buf;
|
srs_verbose("get peer ip of client ip=%s, fd=%d", address_string, fd);
|
||||||
|
return std::string(address_string);
|
||||||
srs_verbose("get peer ip success. ip=%s, fd=%d", ip.c_str(), fd);
|
|
||||||
|
|
||||||
return ip;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool srs_is_digit_number(const string& str)
|
bool srs_is_digit_number(const string& str)
|
||||||
|
|
|
@ -643,6 +643,9 @@ extern SrsNetworkRtmpServer* srs_get_network_rtmp_server();
|
||||||
// the deamon st-thread will update it.
|
// the deamon st-thread will update it.
|
||||||
extern void srs_update_rtmp_server(int nb_conn, SrsKbps* kbps);
|
extern void srs_update_rtmp_server(int nb_conn, SrsKbps* kbps);
|
||||||
|
|
||||||
|
// check for IPv6 support
|
||||||
|
extern int srs_check_ipv6();
|
||||||
|
|
||||||
// get local or peer ip.
|
// get local or peer ip.
|
||||||
// where local ip is the server ip which client connected.
|
// where local ip is the server ip which client connected.
|
||||||
extern std::string srs_get_local_ip(int fd);
|
extern std::string srs_get_local_ip(int fd);
|
||||||
|
|
|
@ -154,50 +154,79 @@ int64_t srs_update_system_time_ms()
|
||||||
return _srs_system_time_us_cache / 1000;
|
return _srs_system_time_us_cache / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
string srs_dns_resolve(string host)
|
string srs_dns_resolve(string host, int& family)
|
||||||
{
|
{
|
||||||
if (inet_addr(host.c_str()) != INADDR_NONE) {
|
addrinfo hints;
|
||||||
return host;
|
memset(&hints, 0, sizeof(hints));
|
||||||
}
|
hints.ai_family = family;
|
||||||
|
addrinfo* result = NULL;
|
||||||
hostent* answer = gethostbyname(host.c_str());
|
if(getaddrinfo(host.c_str(), NULL, NULL, &result) != 0) {
|
||||||
if (answer == NULL) {
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
char ipv4[16];
|
char address_string[64];
|
||||||
memset(ipv4, 0, sizeof(ipv4));
|
const int success = getnameinfo(result->ai_addr, result->ai_addrlen,
|
||||||
|
(char*)&address_string, sizeof(address_string),
|
||||||
|
NULL, 0,
|
||||||
|
NI_NUMERICHOST);
|
||||||
|
freeaddrinfo(result);
|
||||||
|
|
||||||
// covert the first entry to ip.
|
if(success) {
|
||||||
if (answer->h_length > 0) {
|
family = result->ai_family;
|
||||||
inet_ntop(AF_INET, answer->h_addr_list[0], ipv4, sizeof(ipv4));
|
return string(address_string);
|
||||||
}
|
}
|
||||||
|
return "";
|
||||||
return ipv4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void srs_parse_hostport(const string& hostport, string& host, int& port)
|
void srs_parse_hostport(const string& hostport, string& host, int& port)
|
||||||
{
|
{
|
||||||
size_t pos = hostport.find(":");
|
const size_t pos = hostport.rfind(":"); // Look for ":" from the end, to work with IPv6.
|
||||||
if (pos != std::string::npos) {
|
if (pos != std::string::npos) {
|
||||||
string p = hostport.substr(pos + 1);
|
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);
|
host = hostport.substr(0, pos);
|
||||||
|
}
|
||||||
port = ::atoi(p.c_str());
|
port = ::atoi(p.c_str());
|
||||||
} else {
|
} else {
|
||||||
host = hostport;
|
host = hostport;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_ipv6()
|
||||||
|
{
|
||||||
|
int sd = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||||
|
if(sd >= 0) {
|
||||||
|
close(sd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void srs_parse_endpoint(string hostport, string& ip, int& port)
|
void srs_parse_endpoint(string hostport, string& ip, int& port)
|
||||||
{
|
{
|
||||||
ip = "0.0.0.0";
|
const size_t pos = hostport.rfind(":"); // Look for ":" from the end, to work with IPv6.
|
||||||
|
if (pos != std::string::npos) {
|
||||||
size_t pos = string::npos;
|
if ((pos >= 1) &&
|
||||||
if ((pos = hostport.find(":")) != string::npos) {
|
(hostport[0] == '[') &&
|
||||||
|
(hostport[pos - 1] == ']')) {
|
||||||
|
// Handle IPv6 in RFC 2732 format, e.g. [3ffe:dead:beef::1]:1935
|
||||||
|
ip = hostport.substr(1, pos - 2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Handle IP address
|
||||||
ip = hostport.substr(0, pos);
|
ip = hostport.substr(0, pos);
|
||||||
string sport = hostport.substr(pos + 1);
|
}
|
||||||
|
const string sport = hostport.substr(pos + 1);
|
||||||
port = ::atoi(sport.c_str());
|
port = ::atoi(sport.c_str());
|
||||||
} else {
|
} else {
|
||||||
|
ip = check_ipv6() ? "::" : "0.0.0.0";
|
||||||
port = ::atoi(hostport.c_str());
|
port = ::atoi(hostport.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -317,7 +346,7 @@ string srs_string_remove(string str, string remove_chars)
|
||||||
|
|
||||||
bool srs_string_ends_with(string str, string flag)
|
bool srs_string_ends_with(string str, string flag)
|
||||||
{
|
{
|
||||||
ssize_t pos = str.rfind(flag);
|
const size_t pos = str.rfind(flag);
|
||||||
return (pos != string::npos) && (pos == str.length() - flag.length());
|
return (pos != string::npos) && (pos == str.length() - flag.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ extern int64_t srs_get_system_startup_time_ms();
|
||||||
extern int64_t srs_update_system_time_ms();
|
extern int64_t srs_update_system_time_ms();
|
||||||
|
|
||||||
// dns resolve utility, return the resolved ip address.
|
// dns resolve utility, return the resolved ip address.
|
||||||
extern std::string srs_dns_resolve(std::string host);
|
extern std::string srs_dns_resolve(std::string host, int& family);
|
||||||
|
|
||||||
// split the host:port to host and port.
|
// split the host:port to host and port.
|
||||||
// @remark the hostport format in <host[:port]>, where port is optional.
|
// @remark the hostport format in <host[:port]>, where port is optional.
|
||||||
|
|
|
@ -64,6 +64,8 @@
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
#include <srs_kernel_utility.hpp>
|
#include <srs_kernel_utility.hpp>
|
||||||
#include <srs_kernel_consts.hpp>
|
#include <srs_kernel_consts.hpp>
|
||||||
|
@ -73,6 +75,7 @@
|
||||||
struct SrsBlockSyncSocket
|
struct SrsBlockSyncSocket
|
||||||
{
|
{
|
||||||
SOCKET fd;
|
SOCKET fd;
|
||||||
|
int family;
|
||||||
int64_t rbytes;
|
int64_t rbytes;
|
||||||
int64_t sbytes;
|
int64_t sbytes;
|
||||||
// The send/recv timeout in ms.
|
// The send/recv timeout in ms.
|
||||||
|
@ -106,7 +109,12 @@ int srs_hijack_io_create_socket(srs_hijack_io_t ctx, srs_rtmp_t owner)
|
||||||
{
|
{
|
||||||
SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx;
|
SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx;
|
||||||
|
|
||||||
skt->fd = ::socket(AF_INET, SOCK_STREAM, 0);
|
skt->family = AF_INET6;
|
||||||
|
skt->fd = ::socket(skt->family, SOCK_STREAM, 0); // Try IPv6 first.
|
||||||
|
if (!SOCKET_VALID(skt->fd)) {
|
||||||
|
skt->family = AF_INET;
|
||||||
|
skt->fd = ::socket(skt->family, SOCK_STREAM, 0); // Try IPv4 instead, if IPv6 fails.
|
||||||
|
}
|
||||||
if (!SOCKET_VALID(skt->fd)) {
|
if (!SOCKET_VALID(skt->fd)) {
|
||||||
return ERROR_SOCKET_CREATE;
|
return ERROR_SOCKET_CREATE;
|
||||||
}
|
}
|
||||||
|
@ -117,15 +125,23 @@ int srs_hijack_io_connect(srs_hijack_io_t ctx, const char* server_ip, int port)
|
||||||
{
|
{
|
||||||
SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx;
|
SrsBlockSyncSocket* skt = (SrsBlockSyncSocket*)ctx;
|
||||||
|
|
||||||
sockaddr_in addr;
|
char port_string[8];
|
||||||
addr.sin_family = AF_INET;
|
snprintf(port_string, sizeof(port_string), "%d", port);
|
||||||
addr.sin_port = htons(port);
|
addrinfo hints;
|
||||||
addr.sin_addr.s_addr = inet_addr(server_ip);
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = skt->family;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_flags = AI_NUMERICHOST;
|
||||||
|
addrinfo* result = NULL;
|
||||||
|
|
||||||
if(::connect(skt->fd, (const struct sockaddr*)&addr, sizeof(sockaddr_in)) < 0){
|
if(getaddrinfo(server_ip, port_string, (const addrinfo*)&hints, &result) == 0) {
|
||||||
|
if(::connect(skt->fd, result->ai_addr, result->ai_addrlen) < 0){
|
||||||
|
freeaddrinfo(result);
|
||||||
return ERROR_SOCKET_CONNECT;
|
return ERROR_SOCKET_CONNECT;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(result);
|
||||||
return ERROR_SUCCESS;
|
return ERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
int srs_hijack_io_read(srs_hijack_io_t ctx, void* buf, size_t size, ssize_t* nread)
|
int srs_hijack_io_read(srs_hijack_io_t ctx, void* buf, size_t size, ssize_t* nread)
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <srs_librtmp.hpp>
|
#include <srs_librtmp.hpp>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
// for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
// for srs-librtmp, @see https://github.com/ossrs/srs/issues/213
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
@ -341,15 +342,11 @@ const char* inet_ntop(int af, const void *src, char *dst, socklen_t size)
|
||||||
{
|
{
|
||||||
switch (af) {
|
switch (af) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
return (inet_ntop4( (unsigned char*)src, (char*)dst, size)); // ****
|
return (inet_ntop4( (unsigned char*)src, (char*)dst, size));
|
||||||
#ifdef AF_INET6
|
case AF_INET6:
|
||||||
#error "IPv6 not supported"
|
return (char*)(inet_ntop6( (unsigned char*)src, (char*)dst, size));
|
||||||
//case AF_INET6:
|
|
||||||
// return (char*)(inet_ntop6( (unsigned char*)src, (char*)dst, size)); // ****
|
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
// return (NULL); // ****
|
return (NULL);
|
||||||
return 0 ; // ****
|
|
||||||
}
|
}
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
@ -498,7 +495,8 @@ int srs_librtmp_context_resolve_host(Context* context)
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
// connect to server:port
|
// connect to server:port
|
||||||
context->ip = srs_dns_resolve(context->host);
|
int family = AF_UNSPEC;
|
||||||
|
context->ip = srs_dns_resolve(context->host, family);
|
||||||
if (context->ip.empty()) {
|
if (context->ip.empty()) {
|
||||||
return ERROR_SYSTEM_DNS_RESOLVE;
|
return ERROR_SYSTEM_DNS_RESOLVE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <st.h>
|
#include <st.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <netdb.h>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
#include <srs_kernel_error.hpp>
|
#include <srs_kernel_error.hpp>
|
||||||
|
@ -104,8 +105,6 @@ srs_thread_t srs_thread_self()
|
||||||
|
|
||||||
srs_error_t srs_socket_connect(string server, int port, int64_t tm, srs_netfd_t* pstfd)
|
srs_error_t srs_socket_connect(string server, int port, int64_t tm, srs_netfd_t* pstfd)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
|
||||||
|
|
||||||
st_utime_t timeout = ST_UTIME_NO_TIMEOUT;
|
st_utime_t timeout = ST_UTIME_NO_TIMEOUT;
|
||||||
if (tm != SRS_CONSTS_NO_TMMS) {
|
if (tm != SRS_CONSTS_NO_TMMS) {
|
||||||
timeout = (st_utime_t)(tm * 1000);
|
timeout = (st_utime_t)(tm * 1000);
|
||||||
|
@ -113,45 +112,43 @@ srs_error_t srs_socket_connect(string server, int port, int64_t tm, srs_netfd_t*
|
||||||
|
|
||||||
*pstfd = NULL;
|
*pstfd = NULL;
|
||||||
srs_netfd_t stfd = NULL;
|
srs_netfd_t stfd = NULL;
|
||||||
sockaddr_in addr;
|
|
||||||
|
|
||||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
char port_string[8];
|
||||||
if(sock == -1){
|
snprintf(port_string, sizeof(port_string), "%d", port);
|
||||||
return srs_error_new(ERROR_SOCKET_CREATE, "create socket");
|
addrinfo hints;
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
addrinfo* result = NULL;
|
||||||
|
if(getaddrinfo(server.c_str(), port_string, (const addrinfo*)&hints, &result) != 0) {
|
||||||
|
return srs_error_new(ERROR_SYSTEM_IP_INVALID, "dns resolve server error");
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_fd_close_exec(sock);
|
int sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
|
||||||
|
if(sock == -1){
|
||||||
|
freeaddrinfo(result);
|
||||||
|
return srs_error_new(ERROR_SOCKET_CREATE, "create socket");
|
||||||
|
}
|
||||||
|
|
||||||
srs_assert(!stfd);
|
srs_assert(!stfd);
|
||||||
stfd = st_netfd_open_socket(sock);
|
stfd = st_netfd_open_socket(sock);
|
||||||
if(stfd == NULL){
|
if(stfd == NULL){
|
||||||
|
srs_close_stfd(stfd);
|
||||||
|
freeaddrinfo(result);
|
||||||
return srs_error_new(ERROR_ST_OPEN_SOCKET, "open socket");
|
return srs_error_new(ERROR_ST_OPEN_SOCKET, "open socket");
|
||||||
}
|
}
|
||||||
|
|
||||||
// connect to server.
|
if (st_connect((st_netfd_t)stfd, result->ai_addr, result->ai_addrlen, timeout) == -1){
|
||||||
std::string ip = srs_dns_resolve(server);
|
|
||||||
if (ip.empty()) {
|
|
||||||
return srs_error_new(ERROR_SYSTEM_IP_INVALID, "resolve server %s", server.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(port);
|
|
||||||
addr.sin_addr.s_addr = inet_addr(ip.c_str());
|
|
||||||
|
|
||||||
if (st_connect((st_netfd_t)stfd, (const struct sockaddr*)&addr, sizeof(sockaddr_in), timeout) == -1){
|
|
||||||
err = srs_error_new(ERROR_ST_CONNECT, "connect to %s:%d", ip.c_str(), port);
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
srs_info("connect ok. server=%s, ip=%s, port=%d", server.c_str(), ip.c_str(), port);
|
|
||||||
|
|
||||||
*pstfd = stfd;
|
|
||||||
return err;
|
|
||||||
|
|
||||||
failed:
|
|
||||||
if (stfd) {
|
|
||||||
srs_close_stfd(stfd);
|
srs_close_stfd(stfd);
|
||||||
|
freeaddrinfo(result);
|
||||||
|
return srs_error_new(ERROR_ST_CONNECT, "connect to %s:%d", server.c_str(), port);
|
||||||
}
|
}
|
||||||
return err;
|
|
||||||
|
srs_info("connect ok. server=%s, port=%d", server.c_str(), port);
|
||||||
|
|
||||||
|
freeaddrinfo(result);
|
||||||
|
*pstfd = stfd;
|
||||||
|
return srs_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_cond_t srs_cond_new()
|
srs_cond_t srs_cond_new()
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
|
#include <netdb.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -61,9 +62,11 @@ bool srs_net_device_is_internet(string ifname)
|
||||||
return _srs_device_ifs[ifname];
|
return _srs_device_ifs[ifname];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool srs_net_device_is_internet(in_addr_t addr)
|
bool srs_net_device_is_internet(const sockaddr* addr)
|
||||||
{
|
{
|
||||||
uint32_t addr_h = ntohl(addr);
|
if(addr->sa_family == AF_INET) {
|
||||||
|
const in_addr inaddr = ((sockaddr_in*)addr)->sin_addr;
|
||||||
|
const uint32_t addr_h = ntohl(inaddr.s_addr);
|
||||||
|
|
||||||
// lo, 127.0.0.0-127.0.0.1
|
// lo, 127.0.0.0-127.0.0.1
|
||||||
if (addr_h >= 0x7f000000 && addr_h <= 0x7f000001) {
|
if (addr_h >= 0x7f000000 && addr_h <= 0x7f000001) {
|
||||||
|
@ -84,21 +87,29 @@ bool srs_net_device_is_internet(in_addr_t addr)
|
||||||
if (addr_h >= 0xc0a80000 && addr_h <= 0xc0a8ffff) {
|
if (addr_h >= 0xc0a80000 && addr_h <= 0xc0a8ffff) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
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))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<string> _srs_system_ipv4_ips;
|
vector<string> _srs_system_ips;
|
||||||
|
|
||||||
void retrieve_local_ipv4_ips()
|
void retrieve_local_ips()
|
||||||
{
|
{
|
||||||
vector<string>& ips = _srs_system_ipv4_ips;
|
vector<string>& ips = _srs_system_ips;
|
||||||
|
|
||||||
ips.clear();
|
ips.clear();
|
||||||
|
|
||||||
ifaddrs* ifap;
|
ifaddrs* ifap;
|
||||||
if (getifaddrs(&ifap) == -1) {
|
if (getifaddrs(&ifap) == -1) {
|
||||||
srs_warn("retrieve local ips, ini ifaddrs failed.");
|
srs_warn("retrieve local ips, getifaddrs failed.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,32 +122,33 @@ void retrieve_local_ipv4_ips()
|
||||||
ifaddrs* p = ifap;
|
ifaddrs* p = ifap;
|
||||||
while (p != NULL) {
|
while (p != NULL) {
|
||||||
ifaddrs* cur = p;
|
ifaddrs* cur = p;
|
||||||
sockaddr* addr = cur->ifa_addr;
|
|
||||||
p = p->ifa_next;
|
p = p->ifa_next;
|
||||||
|
|
||||||
// retrieve ipv4 addr
|
// retrieve IP address
|
||||||
// ignore the tun0 network device,
|
// ignore the tun0 network device,
|
||||||
// which addr is NULL.
|
// which addr is NULL.
|
||||||
// @see: https://github.com/ossrs/srs/issues/141
|
// @see: https://github.com/ossrs/srs/issues/141
|
||||||
if (addr && addr->sa_family == AF_INET) {
|
if ( (cur->ifa_addr) &&
|
||||||
in_addr* inaddr = &((sockaddr_in*)addr)->sin_addr;
|
( (cur->ifa_addr->sa_family == AF_INET) ||
|
||||||
|
(cur->ifa_addr->sa_family == AF_INET6) ) ) {
|
||||||
char buf[16];
|
char address_string[64];
|
||||||
memset(buf, 0, sizeof(buf));
|
const int success = getnameinfo(cur->ifa_addr, sizeof(sockaddr_storage),
|
||||||
|
(char*)&address_string, sizeof(address_string),
|
||||||
if ((inet_ntop(addr->sa_family, inaddr, buf, sizeof(buf))) == NULL) {
|
NULL, 0,
|
||||||
srs_warn("convert local ip failed");
|
NI_NUMERICHOST);
|
||||||
|
if(success != 0) {
|
||||||
|
srs_warn("convert local ip failed: %s", gai_strerror(success));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ip = buf;
|
std::string ip = address_string;
|
||||||
if (ip != SRS_CONSTS_LOCALHOST) {
|
if (ip != SRS_CONSTS_LOCALHOST) {
|
||||||
ss0 << ", local[" << (int)ips.size() << "] ipv4 " << ip;
|
ss0 << ", local[" << (int)ips.size() << "] ipv4 " << ip;
|
||||||
ips.push_back(ip);
|
ips.push_back(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the device internet status.
|
// set the device internet status.
|
||||||
if (!srs_net_device_is_internet(inaddr->s_addr)) {
|
if (!srs_net_device_is_internet(cur->ifa_addr)) {
|
||||||
ss1 << ", intranet ";
|
ss1 << ", intranet ";
|
||||||
_srs_device_ifs[cur->ifa_name] = false;
|
_srs_device_ifs[cur->ifa_name] = false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -152,13 +164,13 @@ void retrieve_local_ipv4_ips()
|
||||||
freeifaddrs(ifap);
|
freeifaddrs(ifap);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<string>& srs_get_local_ipv4_ips()
|
vector<string>& srs_get_local_ips()
|
||||||
{
|
{
|
||||||
if (_srs_system_ipv4_ips.empty()) {
|
if (_srs_system_ips.empty()) {
|
||||||
retrieve_local_ipv4_ips();
|
retrieve_local_ips();
|
||||||
}
|
}
|
||||||
|
|
||||||
return _srs_system_ipv4_ips;
|
return _srs_system_ips;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string _public_internet_address;
|
std::string _public_internet_address;
|
||||||
|
@ -169,7 +181,7 @@ string srs_get_public_internet_address()
|
||||||
return _public_internet_address;
|
return _public_internet_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string>& ips = srs_get_local_ipv4_ips();
|
std::vector<std::string>& ips = srs_get_local_ips();
|
||||||
|
|
||||||
// find the best match public address.
|
// find the best match public address.
|
||||||
for (int i = 0; i < (int)ips.size(); i++) {
|
for (int i = 0; i < (int)ips.size(); i++) {
|
||||||
|
|
|
@ -37,14 +37,14 @@ extern bool srs_string_is_http(std::string url);
|
||||||
extern bool srs_string_is_rtmp(std::string url);
|
extern bool srs_string_is_rtmp(std::string url);
|
||||||
|
|
||||||
// get local ip, fill to @param ips
|
// get local ip, fill to @param ips
|
||||||
extern std::vector<std::string>& srs_get_local_ipv4_ips();
|
extern std::vector<std::string>& srs_get_local_ips();
|
||||||
|
|
||||||
// get local public ip, empty string if no public internet address found.
|
// get local public ip, empty string if no public internet address found.
|
||||||
extern std::string srs_get_public_internet_address();
|
extern std::string srs_get_public_internet_address();
|
||||||
|
|
||||||
// detect whether specified device is internet public address.
|
// detect whether specified device is internet public address.
|
||||||
extern bool srs_net_device_is_internet(std::string ifname);
|
extern bool srs_net_device_is_internet(std::string ifname);
|
||||||
extern bool srs_net_device_is_internet(in_addr_t addr);
|
extern bool srs_net_device_is_internet(const sockaddr* addr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue