Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IPv6 support (for 3.0 release) #988

Merged
merged 12 commits into from
Oct 14, 2017
2 changes: 1 addition & 1 deletion AUTHORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ CONTRIBUTORS ordered by first contribution.
* lovecat<littlefawn@163.com> "Bug fixed"
* panda1986<542638787@qq.com> "Bug fixed"
* YueHonghui<hongf.yue@hotmail.com> "Bug fixed"

* ThomasDreibholz<dreibh@simula.no> "IPv6 support"
2 changes: 1 addition & 1 deletion trunk/src/app/srs_app_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3659,7 +3659,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",
Expand Down
2 changes: 1 addition & 1 deletion trunk/src/app/srs_app_heartbeat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ void SrsHttpHeartbeat::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()];
}
Expand Down
64 changes: 43 additions & 21 deletions trunk/src/app/srs_app_listener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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");
Expand All @@ -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);
}

Expand Down Expand Up @@ -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");
}
Expand Down
4 changes: 2 additions & 2 deletions trunk/src/app/srs_app_listener.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#include <srs_app_st.hpp>
#include <srs_app_thread.hpp>

struct sockaddr_in;
struct sockaddr;

/**
* the udp packet handler.
Expand All @@ -57,7 +57,7 @@ class ISrsUdpHandler
* @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;
};

/**
Expand Down
15 changes: 12 additions & 3 deletions trunk/src/app/srs_app_mpegts_udp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -157,10 +158,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);
Expand Down
4 changes: 2 additions & 2 deletions trunk/src/app/srs_app_mpegts_udp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

#ifdef SRS_AUTO_STREAM_CASTER

struct sockaddr_in;
struct sockaddr;
#include <string>
#include <map>

Expand Down Expand Up @@ -101,7 +101,7 @@ class SrsMpegtsOverUdp : virtual public ISrsTsHandler
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 int on_udp_bytes(std::string host, int port, char* buf, int nb_buf);
// interface ISrsTsHandler
Expand Down
2 changes: 1 addition & 1 deletion trunk/src/app/srs_app_rtmp_conn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()];

Expand Down
4 changes: 2 additions & 2 deletions trunk/src/app/srs_app_rtsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand All @@ -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)
{
int ret = ERROR_SUCCESS;
srs_error_t err = srs_success;
Expand Down
2 changes: 1 addition & 1 deletion trunk/src/app/srs_app_rtsp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class SrsRtpConn: public ISrsUdpHandler
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);
};

/**
Expand Down
2 changes: 1 addition & 1 deletion trunk/src/app/srs_app_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
95 changes: 52 additions & 43 deletions trunk/src/app/srs_app_utility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <signal.h>
#include <sys/wait.h>
#include <math.h>
#include <netdb.h>

#ifdef SRS_OSX
#include <sys/sysctl.h>
Expand Down Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions trunk/src/app/srs_app_utility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading