multiplex: basic sending and receiving works on ipv6, but not on ipv4

This commit is contained in:
Heikki Tampio 2023-04-05 12:18:50 +03:00
parent fab904a39a
commit 5091876961
5 changed files with 83 additions and 87 deletions

View File

@ -27,6 +27,7 @@ namespace uvgrtp {
class reception_flow;
class holepuncher;
class socket;
class socketfactory;
namespace frame {
struct rtp_frame;
@ -51,7 +52,7 @@ namespace uvgrtp {
public:
/// \cond DO_NOT_DOCUMENT
media_stream(std::string cname, std::string remote_addr, std::string local_addr, uint16_t src_port, uint16_t dst_port,
rtp_format_t fmt, int rce_flags);
rtp_format_t fmt, std::shared_ptr<uvgrtp::socketfactory> sfp, int rce_flags);
~media_stream();
/* Initialize traditional RTP session
@ -385,6 +386,8 @@ namespace uvgrtp {
std::shared_ptr<uvgrtp::rtp> rtp_;
std::shared_ptr<uvgrtp::rtcp> rtcp_;
std::shared_ptr<uvgrtp::socketfactory> sfp_;
sockaddr_in remote_sockaddr_;
sockaddr_in6 remote_sockaddr_ip6_;
std::string remote_address_;

View File

@ -17,6 +17,7 @@
#include "srtp/srtp.hh"
#include "formats/media.hh"
#include "global.hh"
#include "socketfactory.hh"
#ifdef _WIN32
#include <Ws2tcpip.h>
#else
@ -31,13 +32,14 @@
uvgrtp::media_stream::media_stream(std::string cname, std::string remote_addr,
std::string local_addr, uint16_t src_port, uint16_t dst_port, rtp_format_t fmt,
int rce_flags) :
std::shared_ptr<uvgrtp::socketfactory> sfp, int rce_flags) :
key_(uvgrtp::random::generate_32()),
srtp_(nullptr),
srtcp_(nullptr),
socket_(nullptr),
rtp_(nullptr),
rtcp_(nullptr),
sfp_(sfp),
remote_sockaddr_(),
remote_sockaddr_ip6_(),
remote_address_(remote_addr),
@ -82,41 +84,10 @@ rtp_error_t uvgrtp::media_stream::init_connection()
{
rtp_error_t ret = RTP_GENERIC_ERROR;
ipv6_ = sfp_->get_ipv6();
// Use getaddrinfo() to determine whether we are using ipv4 or ipv6 addresses
struct addrinfo hint, * res = NULL;
memset(&hint, '\0', sizeof(hint));
hint.ai_family = PF_UNSPEC;
hint.ai_flags = AI_NUMERICHOST;
socket_ = sfp_->create_new_socket();
if (getaddrinfo(local_address_.c_str(), NULL, &hint, &res) != 0) {
if (getaddrinfo(remote_address_.c_str(), NULL, &hint, &res) != 0) {
UVG_LOG_ERROR("Invalid IP address");
return RTP_GENERIC_ERROR;
}
}
if (res->ai_family == AF_INET6) {
ipv6_ = true;
UVG_LOG_DEBUG("Using an IPv6 address");
}
else {
UVG_LOG_DEBUG("Using an IPv4 address");
}
// Initialize socket
if ((ret = socket_->init(res->ai_family, SOCK_DGRAM, 0)) != RTP_OK) {
return ret;
}
#ifdef _WIN32
/* Make the socket non-blocking */
int enabled = 1;
if (::ioctlsocket(socket_->get_raw_socket(), FIONBIO, (u_long*)&enabled) < 0)
UVG_LOG_ERROR("Failed to make the socket non-blocking!");
#endif
if (!(rce_flags_ & RCE_RECEIVE_ONLY) && remote_address_ != "" && dst_port_ != 0)
{
// no reason to fail sending even if binding fails so we set remote address first
@ -137,16 +108,7 @@ rtp_error_t uvgrtp::media_stream::init_connection()
if (!(rce_flags_ & RCE_SEND_ONLY))
{
if (local_address_ != "" && src_port_ != 0) {
if (ipv6_) {
sockaddr_in6 bind_addr6 = socket_->create_ip6_sockaddr(local_address_, src_port_);
ret = socket_->bind_ip6(bind_addr6);
}
else {
sockaddr_in bind_addr = socket_->create_sockaddr(AF_INET, local_address_, src_port_);
ret = socket_->bind(bind_addr);
}
if (ret != RTP_OK)
if ((ret = sfp_->bind_socket(socket_, src_port_)) != RTP_OK)
{
log_platform_error("bind(2) failed");
return ret;
@ -154,14 +116,7 @@ rtp_error_t uvgrtp::media_stream::init_connection()
}
else if (src_port_ != 0)
{
if (ipv6_) {
sockaddr_in6 ip6_any = socket_->create_ip6_sockaddr_any(src_port_);
ret = socket_->bind_ip6(ip6_any);
}
else {
ret = socket_->bind(AF_INET, INADDR_ANY, src_port_);
}
if (ret != RTP_OK)
if ((ret = sfp_->bind_socket_anyip(socket_, src_port_)) != RTP_OK)
{
log_platform_error("bind(2) to any failed");
return ret;

View File

@ -105,7 +105,7 @@ uvgrtp::media_stream* uvgrtp::session::create_stream(uint16_t src_port, uint16_t
}
uvgrtp::media_stream* stream =
new uvgrtp::media_stream(cname_, remote_address_, local_address_, src_port, dst_port, fmt, rce_flags);
new uvgrtp::media_stream(cname_, remote_address_, local_address_, src_port, dst_port, fmt, sf_, rce_flags);
if (rce_flags & RCE_SRTP) {
if (!uvgrtp::crypto::enabled()) {

View File

@ -42,52 +42,86 @@ rtp_error_t uvgrtp::socketfactory::set_local_interface(std::string local_addr)
return RTP_OK;
}
std::shared_ptr<uvgrtp::socket> uvgrtp::socketfactory::create_new_socket(uint16_t local_port)
std::shared_ptr<uvgrtp::socket> uvgrtp::socketfactory::create_new_socket()
{
rtp_error_t ret = RTP_OK;
if (std::find(used_ports_.begin(), used_ports_.end(), local_port) == used_ports_.end()) {
std::shared_ptr<uvgrtp::socket> socket = std::make_shared<uvgrtp::socket>(rce_flags_);
std::shared_ptr<uvgrtp::socket> socket = std::make_shared<uvgrtp::socket>(rce_flags_);
if (ipv6_) {
if ((ret = socket->init(AF_INET6, SOCK_DGRAM, 0)) != RTP_OK) {
return nullptr;
}
}
else {
if ((ret = socket->init(AF_INET6, SOCK_DGRAM, 0)) != RTP_OK) {
return nullptr;
}
}
#ifdef _WIN32
/* Make the socket non-blocking */
int enabled = 1;
if (::ioctlsocket(socket->get_raw_socket(), FIONBIO, (u_long*)&enabled) < 0) {
if (ipv6_) {
if ((ret = socket->init(AF_INET6, SOCK_DGRAM, 0)) != RTP_OK) {
return nullptr;
}
}
else {
if ((ret = socket->init(AF_INET6, SOCK_DGRAM, 0)) != RTP_OK) {
return nullptr;
}
}
#ifdef _WIN32
/* Make the socket non-blocking */
int enabled = 1;
if (::ioctlsocket(socket->get_raw_socket(), FIONBIO, (u_long*)&enabled) < 0) {
return nullptr;
}
#endif
if (ret == RTP_OK) {
used_sockets_.push_back(socket);
if (ipv6_) {
sockaddr_in6 bind_addr6 = socket->create_ip6_sockaddr(local_address_, local_port);
ret = socket->bind_ip6(bind_addr6);
}
else {
sockaddr_in bind_addr = socket->create_sockaddr(AF_INET, local_address_, local_port);
ret = socket->bind(bind_addr);
}
if (ret == RTP_OK) {
used_ports_.push_back(local_port);
return socket;
}
return socket;
}
return nullptr;
}
rtp_error_t uvgrtp::socketfactory::bind_socket(std::shared_ptr<uvgrtp::socket> soc, uint16_t port)
{
rtp_error_t ret = RTP_GENERIC_ERROR;
if (std::find(used_ports_.begin(), used_ports_.end(), port) == used_ports_.end()) {
if (ipv6_) {
sockaddr_in6 bind_addr6 = soc->create_ip6_sockaddr(local_address_, port);
ret = soc->bind_ip6(bind_addr6);
}
else {
sockaddr_in bind_addr = soc->create_sockaddr(AF_INET, local_address_, port);
ret = soc->bind(bind_addr);
}
if (ret == RTP_OK) {
used_ports_.push_back(port);
return RTP_OK;
}
}
return ret;
}
rtp_error_t uvgrtp::socketfactory::bind_socket_anyip(std::shared_ptr<uvgrtp::socket> soc, uint16_t port)
{
rtp_error_t ret = RTP_GENERIC_ERROR;
if (std::find(used_ports_.begin(), used_ports_.end(), port) == used_ports_.end()) {
if (ipv6_) {
sockaddr_in6 bind_addr6 = soc->create_ip6_sockaddr_any(port);
ret = soc->bind_ip6(bind_addr6);
}
else {
ret = soc->bind(AF_INET, INADDR_ANY, port);
}
if (ret == RTP_OK) {
used_ports_.push_back(port);
return RTP_OK;
}
}
return ret;
}
std::shared_ptr<uvgrtp::socket> uvgrtp::socketfactory::get_socket_ptr() const
{
return nullptr;
}
bool uvgrtp::socketfactory::get_ipv6() const
{
return ipv6_;
}

View File

@ -15,9 +15,13 @@ namespace uvgrtp {
~socketfactory();
rtp_error_t set_local_interface(std::string local_addr);
std::shared_ptr<uvgrtp::socket> create_new_socket(uint16_t local_port);
std::shared_ptr<uvgrtp::socket> create_new_socket();
rtp_error_t bind_socket(std::shared_ptr<uvgrtp::socket> soc, uint16_t port);
rtp_error_t bind_socket_anyip(std::shared_ptr<uvgrtp::socket> soc, uint16_t port);
std::shared_ptr<uvgrtp::socket> get_socket_ptr() const;
bool get_ipv6() const;
private: