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:
parent
db08f1586c
commit
feaae341b9
20 changed files with 296 additions and 201 deletions
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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()];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()];
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue