1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +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:
Thomas Dreibholz 2017-10-14 05:29:33 +02:00 committed by winlin
parent db08f1586c
commit feaae341b9
20 changed files with 296 additions and 201 deletions

View file

@ -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());
}
if (true) {
vector<std::string> ips = srs_get_local_ipv4_ips();
vector<std::string> ips = srs_get_local_ips();
int index = get_stats_network();
if (index >= (int)ips.size()) {
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "invalid stats.network=%d of %d",

View file

@ -68,7 +68,7 @@ srs_error_t SrsHttpHeartbeat::do_heartbeat()
std::string ip = "";
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()) {
ip = ips[_srs_config->get_stats_network() % (int)ips.size()];
}

View file

@ -31,6 +31,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <netdb.h>
using namespace std;
#include <srs_kernel_log.hpp>
@ -111,20 +112,31 @@ srs_error_t SrsUdpListener::listen()
{
srs_error_t err = srs_success;
if ((_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
return srs_error_new(ERROR_SOCKET_CREATE, "create socket");
char port_string[8];
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_socket_reuse_addr(_fd);
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(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");
if (bind(_fd, result->ai_addr, result->ai_addrlen) == -1) {
freeaddrinfo(result);
return srs_error_new(ERROR_SOCKET_BIND, "bind socket error. ep=%s:%d", ip.c_str(), port);;
}
freeaddrinfo(result);
if ((_stfd = srs_netfd_open_socket(_fd)) == NULL){
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");
}
// TODO: FIXME: support ipv6, @see man 7 ipv6
sockaddr_in from;
int nb_from = sizeof(sockaddr_in);
sockaddr_storage from;
int nb_from = sizeof(from);
int nread = 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);
}
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);
}
@ -197,21 +208,32 @@ srs_error_t SrsTcpListener::listen()
{
srs_error_t err = srs_success;
if ((_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
return srs_error_new(ERROR_SOCKET_CREATE, "create socket");
char port_string[8];
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_socket_reuse_addr(_fd);
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(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");
if (bind(_fd, result->ai_addr, result->ai_addrlen) == -1) {
freeaddrinfo(result);
return srs_error_new(ERROR_SOCKET_BIND, "bind socket error. ep=%s:%d", ip.c_str(), port);;
}
freeaddrinfo(result);
if (::listen(_fd, SERVER_LISTEN_BACKLOG) == -1) {
return srs_error_new(ERROR_SOCKET_LISTEN, "listen socket");
}

View file

@ -31,7 +31,7 @@
#include <srs_app_st.hpp>
#include <srs_app_thread.hpp>
struct sockaddr_in;
struct sockaddr;
/**
* the udp packet handler.
@ -57,7 +57,7 @@ public:
* @param nb_buf, the size of udp packet 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;
};
/**

View file

@ -29,6 +29,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
using namespace std;
#include <srs_app_config.hpp>
@ -155,10 +156,18 @@ SrsMpegtsOverUdp::~SrsMpegtsOverUdp()
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);
int peer_port = ntohs(from->sin_port);
char address_string[64];
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.
buffer->append(buf, nb_buf);

View file

@ -28,7 +28,7 @@
#ifdef SRS_AUTO_STREAM_CASTER
struct sockaddr_in;
struct sockaddr;
#include <string>
#include <map>
@ -100,7 +100,7 @@ public:
virtual ~SrsMpegtsOverUdp();
// interface ISrsUdpHandler
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:
virtual srs_error_t on_udp_bytes(std::string host, int port, char* buf, int nb_buf);
// interface ISrsTsHandler

View file

@ -87,7 +87,7 @@ SrsSimpleRtmpClient::~SrsSimpleRtmpClient()
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());
std::string local_ip = ips[_srs_config->get_stats_network()];

View file

@ -54,7 +54,7 @@ SrsRtpConn::SrsRtpConn(SrsRtspConn* r, int p, int sid)
_port = p;
stream_id = sid;
// 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();
pprint = SrsPithyPrint::create_caster();
}
@ -76,7 +76,7 @@ srs_error_t SrsRtpConn::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;

View file

@ -74,7 +74,7 @@ public:
virtual srs_error_t listen();
// interface ISrsUdpHandler
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);
};
/**

View file

@ -1137,7 +1137,7 @@ srs_error_t SrsServer::listen_stream_caster()
}
// 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);
}
}

View file

@ -30,6 +30,7 @@
#include <signal.h>
#include <sys/wait.h>
#include <math.h>
#include <netdb.h>
#ifdef SRS_OSX
#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)
{
std::string ip;
// discovery client information
sockaddr_in addr;
sockaddr_storage addr;
socklen_t addrlen = sizeof(addr);
if (getsockname(fd, (sockaddr*)&addr, &addrlen) == -1) {
return ip;
return "";
}
srs_verbose("get local ip success.");
// ip v4 or v6
char buf[INET6_ADDRSTRLEN];
memset(buf, 0, sizeof(buf));
if ((inet_ntop(addr.sin_family, &addr.sin_addr, buf, sizeof(buf))) == NULL) {
return ip;
char address_string[64];
const int success = getnameinfo((const sockaddr*)&addr, addrlen,
(char*)&address_string, sizeof(address_string),
NULL, 0,
NI_NUMERICHOST);
if(success != 0) {
return "";
}
ip = buf;
srs_verbose("get local ip of client ip=%s, fd=%d", buf, fd);
return ip;
srs_verbose("get local ip of client ip=%s, fd=%d", address_string, fd);
return std::string(address_string);
}
int srs_get_local_port(int fd)
{
// discovery client information
sockaddr_in addr;
sockaddr_storage addr;
socklen_t addrlen = sizeof(addr);
if (getsockname(fd, (sockaddr*)&addr, &addrlen) == -1) {
return 0;
}
srs_verbose("get local ip success.");
int port = ntohs(addr.sin_port);
srs_verbose("get local ip of client port=%s, fd=%d", port, fd);
int port = 0;
switch(addr.ss_family) {
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;
}
string srs_get_peer_ip(int fd)
{
std::string ip;
// discovery client information
sockaddr_in addr;
sockaddr_storage addr;
socklen_t addrlen = sizeof(addr);
if (getpeername(fd, (sockaddr*)&addr, &addrlen) == -1) {
return ip;
if (getsockname(fd, (sockaddr*)&addr, &addrlen) == -1) {
return "";
}
srs_verbose("get peer name success.");
// ip v4 or v6
char buf[INET6_ADDRSTRLEN];
memset(buf, 0, sizeof(buf));
if ((inet_ntop(addr.sin_family, &addr.sin_addr, buf, sizeof(buf))) == NULL) {
return ip;
srs_verbose("get peer ip success.");
char address_string[64];
const int success = getnameinfo((const sockaddr*)&addr, addrlen,
(char*)&address_string, sizeof(address_string),
NULL, 0,
NI_NUMERICHOST);
if(success != 0) {
return "";
}
srs_verbose("get peer ip of client ip=%s, fd=%d", buf, fd);
ip = buf;
srs_verbose("get peer ip success. ip=%s, fd=%d", ip.c_str(), fd);
return ip;
srs_verbose("get peer ip of client ip=%s, fd=%d", address_string, fd);
return std::string(address_string);
}
bool srs_is_digit_number(const string& str)

View file

@ -643,6 +643,9 @@ extern SrsNetworkRtmpServer* srs_get_network_rtmp_server();
// the deamon st-thread will update it.
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.
// where local ip is the server ip which client connected.
extern std::string srs_get_local_ip(int fd);