ipv6: add ipv6 support

ipv6 support for rtp, rtcp, srtp+zrtp, no context flags needed

# Conflicts:
#	src/media_stream.cc
#	src/rtcp.cc
#	src/socket.cc
This commit is contained in:
Heikki Tampio 2023-03-06 10:21:56 +02:00
parent e6c759f514
commit 84bf8c9e4c
11 changed files with 521 additions and 122 deletions

View File

@ -11,6 +11,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#include <ws2ipdef.h>
namespace uvgrtp {
@ -348,6 +349,8 @@ namespace uvgrtp {
*/
uint32_t get_ssrc() const;
bool get_ipv6() const;
private:
/* Initialize the connection by initializing the socket
* and binding ourselves to specified interface and creating
@ -381,10 +384,12 @@ namespace uvgrtp {
std::shared_ptr<uvgrtp::rtcp> rtcp_;
sockaddr_in remote_sockaddr_;
sockaddr_in6 remote_sockaddr_ip6_;
std::string remote_address_;
std::string local_address_;
uint16_t src_port_;
uint16_t dst_port_;
bool ipv6_;
rtp_format_t fmt_;
/* Media context config */

View File

@ -4,6 +4,13 @@
#include "util.hh"
#include "frame.hh"
#ifdef _WIN32
#include <ws2ipdef.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#include <bitset>
#include <map>
#include <thread>
@ -223,6 +230,8 @@ namespace uvgrtp {
/* Getter for interval_ms_, which is calculated by set_session_bandwidth */
uint32_t get_rtcp_interval_ms() const;
void set_ipv6(bool set);
/* Set RTCP packet transmission interval in milliseconds
*
* Return RTP_OK if interval was set successfully
@ -597,9 +606,11 @@ namespace uvgrtp {
std::map<uint32_t, std::unique_ptr<rtcp_participant>> participants_;
uint8_t num_receivers_; // maximum is 32 at the moment (5 bits)
bool ipv6_;
/* Address of the socket that we are sending data to */
sockaddr_in socket_address_ = {};
sockaddr_in socket_address_;
sockaddr_in6 socket_address_ipv6_;
/* Map for keeping track of sources for timeouts

View File

@ -17,13 +17,21 @@
#include "srtp/srtp.hh"
#include "formats/media.hh"
#include "global.hh"
#ifdef _WIN32
#include <Ws2tcpip.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#endif
#include <cstring>
#include <errno.h>
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):
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) :
key_(uvgrtp::random::generate_32()),
srtp_(nullptr),
srtcp_(nullptr),
@ -31,10 +39,12 @@ uvgrtp::media_stream::media_stream(std::string cname, std::string remote_addr,
rtp_(nullptr),
rtcp_(nullptr),
remote_sockaddr_(),
remote_sockaddr_ip6_(),
remote_address_(remote_addr),
local_address_(local_addr),
src_port_(src_port),
dst_port_(dst_port),
ipv6_(false),
fmt_(fmt),
rce_flags_(rce_flags),
initialized_(false),
@ -70,9 +80,34 @@ uvgrtp::media_stream::~media_stream()
rtp_error_t uvgrtp::media_stream::init_connection()
{
rtp_error_t ret = RTP_OK;
if ((ret = socket_->init(AF_INET, SOCK_DGRAM, 0)) != RTP_OK)
rtp_error_t ret = RTP_GENERIC_ERROR;
// Use getaddrinfo() to determine whether we are using ipv4 or ipv6 addresses
int ret1;
struct addrinfo hint;
struct addrinfo* res = NULL;
memset(&hint, '\0', sizeof(hint));
hint.ai_family = PF_UNSPEC;
hint.ai_flags = AI_NUMERICHOST;
if ((ret1 = getaddrinfo(local_address_.c_str(), NULL, &hint, &res)) != 0) {
if ((ret1 = 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_INFO("Using an IPv6 address");
}
else {
UVG_LOG_INFO("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 */
@ -81,14 +116,19 @@ rtp_error_t uvgrtp::media_stream::init_connection()
if (::ioctlsocket(socket_->get_raw_socket(), FIONBIO, (u_long *)&enabled) < 0)
UVG_LOG_ERROR("Failed to make the socket non-blocking!");
#endif
short int family = AF_INET;
//TODO FIX THIS
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
remote_sockaddr_ = socket_->create_sockaddr(family, remote_address_, dst_port_);
socket_->set_sockaddr(remote_sockaddr_);
if (ipv6_) {
remote_sockaddr_ip6_ = socket_->create_ip6_sockaddr(remote_address_, dst_port_);
socket_->set_sockaddr6(remote_sockaddr_ip6_);
}
else {
remote_sockaddr_ = socket_->create_sockaddr(AF_INET, remote_address_, dst_port_);
socket_->set_sockaddr(remote_sockaddr_);
}
}
else
{
@ -98,9 +138,16 @@ rtp_error_t uvgrtp::media_stream::init_connection()
if (!(rce_flags_ & RCE_SEND_ONLY))
{
if (local_address_ != "" && src_port_ != 0) {
sockaddr_in bind_addr = socket_->create_sockaddr(family, local_address_, src_port_);
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 = socket_->bind(bind_addr)) != RTP_OK)
if (ret != RTP_OK)
{
log_platform_error("bind(2) failed");
return ret;
@ -108,7 +155,14 @@ rtp_error_t uvgrtp::media_stream::init_connection()
}
else if (src_port_ != 0)
{
if ((ret = socket_->bind(family, INADDR_ANY, src_port_)) != RTP_OK)
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)
{
log_platform_error("bind(2) to any failed");
return ret;
@ -250,11 +304,14 @@ rtp_error_t uvgrtp::media_stream::init()
UVG_LOG_ERROR("Failed to initialize the underlying socket");
return free_resources(RTP_GENERIC_ERROR);
}
reception_flow_ = std::unique_ptr<uvgrtp::reception_flow> (new uvgrtp::reception_flow());
rtp_ = std::shared_ptr<uvgrtp::rtp> (new uvgrtp::rtp(fmt_, ssrc_));
rtcp_ = std::shared_ptr<uvgrtp::rtcp> (new uvgrtp::rtcp(rtp_, ssrc_, cname_, rce_flags_));
if (ipv6_) {
rtcp_->set_ipv6(true);
}
socket_->install_handler(rtcp_.get(), rtcp_->send_packet_handler_vec);
@ -294,7 +351,7 @@ rtp_error_t uvgrtp::media_stream::init(std::shared_ptr<uvgrtp::zrtp> zrtp)
}
rtp_error_t ret = RTP_OK;
if ((ret = zrtp->init(rtp_->get_ssrc(), socket_, remote_sockaddr_, perform_dh)) != RTP_OK) {
if ((ret = zrtp->init(rtp_->get_ssrc(), socket_, remote_sockaddr_, remote_sockaddr_ip6_, perform_dh, ipv6_)) != RTP_OK) {
UVG_LOG_WARN("Failed to initialize ZRTP for media stream!");
return free_resources(ret);
}
@ -310,7 +367,9 @@ rtp_error_t uvgrtp::media_stream::init(std::shared_ptr<uvgrtp::zrtp> zrtp)
zrtp->dh_has_finished(); // only after the DH stream has gotten its keys, do we let non-DH stream perform ZRTP
rtcp_ = std::shared_ptr<uvgrtp::rtcp> (new uvgrtp::rtcp(rtp_, ssrc_, cname_, srtcp_, rce_flags_));
if (ipv6_) {
rtcp_->set_ipv6(true);
}
socket_->install_handler(rtcp_.get(), rtcp_->send_packet_handler_vec);
socket_->install_handler(srtp_.get(), srtp_->send_packet_handler);
@ -703,7 +762,7 @@ rtp_error_t uvgrtp::media_stream::configure_ctx(int rcc_flag, ssize_t value)
break;
}
case RCC_SESSION_BANDWIDTH: {
bandwidth_ = value;
bandwidth_ = (uint32_t)value;
// TODO: Is there a max value for bandwidth?
if (value <= 0) {
UVG_LOG_WARN("Bandwidth cannot be negative");
@ -748,6 +807,10 @@ uint32_t uvgrtp::media_stream::get_ssrc() const
return *ssrc_.get();
}
bool uvgrtp::media_stream::get_ipv6() const {
return ipv6_;
}
rtp_error_t uvgrtp::media_stream::init_srtp_with_zrtp(int rce_flags, int type, std::shared_ptr<uvgrtp::base_srtp> srtp,
std::shared_ptr<uvgrtp::zrtp> zrtp)
{

View File

@ -16,6 +16,10 @@
#ifndef _WIN32
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#else
#include <ws2ipdef.h>
#endif
#include <cassert>
@ -40,13 +44,16 @@ constexpr int ESTIMATED_MAX_RECEPTION_TIME_MS = 10;
const uint32_t MAX_SUPPORTED_PARTICIPANTS = 31;
uvgrtp::rtcp::rtcp(std::shared_ptr<uvgrtp::rtp> rtp, std::shared_ptr<std::atomic_uint> ssrc, std::string cname, int rce_flags):
rce_flags_(rce_flags), our_role_(RECEIVER),
rce_flags_(rce_flags), our_role_(RECEIVER),
tp_(0), tc_(0), tn_(0), pmembers_(0),
members_(0), senders_(0), rtcp_bandwidth_(0), reduced_minimum_(0),
we_sent_(false), local_addr_(""), remote_addr_(""), local_port_(0), dst_port_(0),
avg_rtcp_pkt_pize_(0), avg_rtcp_size_(64), rtcp_pkt_count_(0), rtcp_byte_count_(0),
rtcp_pkt_sent_count_(0), initial_(true), ssrc_(ssrc),
rtcp_pkt_sent_count_(0), initial_(true), ssrc_(rtp->get_ssrc()),
num_receivers_(0),
ipv6_(false),
socket_address_({}),
socket_address_ipv6_({}),
sender_hook_(nullptr),
receiver_hook_(nullptr),
sdes_hook_(nullptr),
@ -194,9 +201,13 @@ rtp_error_t uvgrtp::rtcp::start()
active_ = true;
rtcp_socket_ = std::unique_ptr<uvgrtp::socket>(new uvgrtp::socket(0));
rtp_error_t ret = RTP_OK;
if ((ret = rtcp_socket_->init(AF_INET, SOCK_DGRAM, 0)) != RTP_OK)
{
if (ipv6_) {
ret = rtcp_socket_->init(AF_INET6, SOCK_DGRAM, 0);
}
else {
ret = rtcp_socket_->init(AF_INET, SOCK_DGRAM, 0);
}
if (ret != RTP_OK) {
return ret;
}
@ -233,19 +244,47 @@ rtp_error_t uvgrtp::rtcp::start()
if (local_addr_ != "")
{
UVG_LOG_INFO("Binding RTCP to port %s:%d", local_addr_.c_str(), local_port_);
sockaddr_in bind_addr = rtcp_socket_->create_sockaddr(AF_INET, local_addr_, local_port_);
if ((ret = rtcp_socket_->bind(bind_addr)) != RTP_OK)
{
return ret;
if (ipv6_) {
sockaddr_in6 bind_addr6 = rtcp_socket_->create_ip6_sockaddr(local_addr_, local_port_);
if ((ret = rtcp_socket_->bind_ip6(bind_addr6)) != RTP_OK)
{
return ret;
}
}
else {
sockaddr_in bind_addr = rtcp_socket_->create_sockaddr(AF_INET, local_addr_, local_port_);
if ((ret = rtcp_socket_->bind(bind_addr)) != RTP_OK)
{
return ret;
}
}
}
else
{
UVG_LOG_WARN("No local address provided");
return ret;
UVG_LOG_WARN("No local address provided, binding RTCP to INADDR_ANY");
UVG_LOG_INFO("Binding RTCP to port %s:%d", local_addr_.c_str(), local_port_);
if (ipv6_) {
sockaddr_in6 bind_addr6 = rtcp_socket_->create_ip6_sockaddr_any(local_port_);
if ((ret = rtcp_socket_->bind_ip6(bind_addr6)) != RTP_OK)
{
return ret;
}
}
else {
sockaddr_in bind_addr = rtcp_socket_->create_sockaddr(AF_INET, INADDR_ANY, local_port_);
if ((ret = rtcp_socket_->bind(bind_addr)) != RTP_OK)
{
return ret;
}
}
}
if (ipv6_) {
socket_address_ipv6_ = rtcp_socket_->create_ip6_sockaddr(remote_addr_, dst_port_);
}
else {
socket_address_ = rtcp_socket_->create_sockaddr(AF_INET, remote_addr_, dst_port_);
}
socket_address_ = rtcp_socket_->create_sockaddr(AF_INET, remote_addr_, dst_port_);
report_generator_.reset(new std::thread(rtcp_runner, this));
report_reader_.reset(new std::thread(rtcp_report_reader, this));
@ -1623,7 +1662,7 @@ rtp_error_t uvgrtp::rtcp::send_rtcp_packet_to_participants(uint8_t* frame, uint3
if (rtcp_socket_ != nullptr)
{
std::lock_guard prtcp_lock(participants_mutex_);
if ((ret = rtcp_socket_->sendto(socket_address_, frame, frame_size, 0)) != RTP_OK)
if ((ret = rtcp_socket_->sendto(socket_address_, socket_address_ipv6_, frame, frame_size, 0)) != RTP_OK)
{
UVG_LOG_ERROR("Sending rtcp packet with sendto() failed!");
}
@ -1997,6 +2036,10 @@ uint32_t uvgrtp::rtcp::get_rtcp_interval_ms() const
return interval_ms_.load();
}
void uvgrtp::rtcp::set_ipv6(bool set) {
ipv6_ = set;
}
rtp_error_t uvgrtp::rtcp::set_network_addresses(std::string local_addr, std::string remote_addr,
uint16_t local_port, uint16_t dst_port)
{

View File

@ -100,7 +100,7 @@ uvgrtp::media_stream* uvgrtp::session::create_stream(uint16_t src_port, uint16_t
rtp_errno = RTP_INVALID_VALUE;
return nullptr;
}
uvgrtp::media_stream* stream =
new uvgrtp::media_stream(cname_, remote_address_, local_address_, src_port, dst_port, fmt, rce_flags);

View File

@ -8,13 +8,17 @@
#include <thread>
#ifdef _WIN32
#include <Windows.h>
#include <winsock2.h>
#include <Ws2tcpip.h>
#include <ws2def.h>
#include <ws2ipdef.h>
#else
#include <unistd.h>
#include <poll.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#if defined(__MINGW32__) || defined(__MINGW64__)
@ -29,10 +33,13 @@ using namespace mingw;
#define WSABUF_SIZE 256
uvgrtp::socket::socket(int rce_flags):
uvgrtp::socket::socket(int rce_flags) :
socket_(0),
remote_address_(),
local_address_(),
remote_ip6_address_(),
local_ip6_address_(),
ipv6_(false),
rce_flags_(rce_flags),
#ifdef _WIN32
buffers_()
@ -55,7 +62,12 @@ uvgrtp::socket::~socket()
rtp_error_t uvgrtp::socket::init(short family, int type, int protocol)
{
assert(family == AF_INET);
if (family == AF_INET6) {
ipv6_ = true;
}
else {
ipv6_ = false;
}
#ifdef _WIN32
if ((socket_ = ::socket(family, type, protocol)) == INVALID_SOCKET) {
@ -100,7 +112,12 @@ rtp_error_t uvgrtp::socket::bind(sockaddr_in& local_address)
{
local_address_ = local_address;
UVG_LOG_DEBUG("Binding to address %s", sockaddr_to_string(local_address_).c_str());
if (ipv6_) {
UVG_LOG_DEBUG("Binding to address %s", sockaddr_ip6_to_string(local_ip6_address_).c_str());
}
else {
UVG_LOG_DEBUG("Binding to address %s", sockaddr_to_string(local_address_).c_str());
}
if (::bind(socket_, (struct sockaddr*)&local_address_, sizeof(local_address_)) < 0) {
#ifdef _WIN32
@ -115,6 +132,25 @@ rtp_error_t uvgrtp::socket::bind(sockaddr_in& local_address)
return RTP_OK;
}
rtp_error_t uvgrtp::socket::bind_ip6(sockaddr_in6& local_address)
{
local_ip6_address_ = local_address;
//UVG_LOG_DEBUG("Binding to address %s", sockaddr_to_string(local_address_).c_str());
if (::bind(socket_, (struct sockaddr*)&local_ip6_address_, sizeof(local_ip6_address_)) < 0) {
#ifdef _WIN32
win_get_last_error();
#else
fprintf(stderr, "%s\n", strerror(errno));
#endif
UVG_LOG_ERROR("Binding to port %u failed!", ntohs(local_address_.sin_port));
return RTP_BIND_ERROR;
}
return RTP_OK;
}
sockaddr_in uvgrtp::socket::create_sockaddr(short family, unsigned host, short port) const
{
assert(family == AF_INET);
@ -145,14 +181,71 @@ sockaddr_in uvgrtp::socket::create_sockaddr(short family, std::string host, shor
return addr;
}
sockaddr_in6 uvgrtp::socket::create_ip6_sockaddr(unsigned host, short port) const
{
sockaddr_in6 addr;
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
std::string host_str = std::to_string(host);
inet_pton(AF_INET6, host_str.c_str(), &addr.sin6_addr);
addr.sin6_port = htons((uint16_t)port);
return addr;
}
sockaddr_in6 uvgrtp::socket::create_ip6_sockaddr(std::string host, short port) const
{
/*
struct addrinfo hints = { 0 }, *addr_i;
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
std::string port_str = std::to_string(port);
int status = getaddrinfo(host.c_str(), port_str.c_str(), &hints, &addr_i);
// exit??
if (status != 0) {
UVG_LOG_ERROR("Invalid address");
}*/
sockaddr_in6 addr;
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
inet_pton(AF_INET6, host.c_str(), &addr.sin6_addr);
addr.sin6_port = htons((uint16_t)port);
return addr;
}
sockaddr_in6 uvgrtp::socket::create_ip6_sockaddr_any(short src_port) {
sockaddr_in6 addr;
memset(&addr, 0, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_addr = in6addr_any;
addr.sin6_port = htons(src_port);
return addr;
}
std::string uvgrtp::socket::get_socket_path_string() const
{
if (ipv6_) {
return sockaddr_ip6_to_string(local_ip6_address_) + " -> " + sockaddr_ip6_to_string(remote_ip6_address_);
}
return sockaddr_to_string(local_address_) + " -> " + sockaddr_to_string(remote_address_);
}
std::string uvgrtp::socket::sockaddr_to_string(const sockaddr_in& addr) const
{
int addr_len = INET_ADDRSTRLEN;
// tyhjennä turhat "ipv6 supportit" pois
char* c_string = new char[INET_ADDRSTRLEN];
memset(c_string, 0, INET_ADDRSTRLEN);
if (addr.sin_family == AF_INET6)
{
@ -176,11 +269,27 @@ std::string uvgrtp::socket::sockaddr_to_string(const sockaddr_in& addr) const
return string;
}
std::string uvgrtp::socket::sockaddr_ip6_to_string(const sockaddr_in6& addr6) const
{
char* c_string = new char[INET6_ADDRSTRLEN];
memset(c_string, 0, INET6_ADDRSTRLEN);
inet_ntop(AF_INET6, &addr6.sin6_addr, c_string, INET_ADDRSTRLEN);
std::string string(c_string);
string.append(":" + std::to_string(ntohs(addr6.sin6_port)));
delete[] c_string;
return string;
}
void uvgrtp::socket::set_sockaddr(sockaddr_in addr)
{
remote_address_ = addr;
}
void uvgrtp::socket::set_sockaddr6(sockaddr_in6 addr)
{
remote_ip6_address_ = addr;
}
socket_t& uvgrtp::socket::get_raw_socket()
{
return socket_;
@ -201,12 +310,18 @@ rtp_error_t uvgrtp::socket::install_handler(void *arg, packet_handler_vec handle
return RTP_OK;
}
rtp_error_t uvgrtp::socket::__sendto(sockaddr_in& addr, uint8_t *buf, size_t buf_len, int send_flags, int *bytes_sent)
rtp_error_t uvgrtp::socket::__sendto(sockaddr_in& addr, sockaddr_in6& addr6, bool ipv6, uint8_t *buf, size_t buf_len, int send_flags, int *bytes_sent)
{
int nsend = 0;
#ifndef _WIN32
if ((nsend = ::sendto(socket_, buf, buf_len, send_flags, (const struct sockaddr *)&addr, sizeof(addr))) == -1) {
if (ipv6) {
nsend = ::sendto(socket_, buf, buf_len, send_flags, (const struct sockaddr*)&addr6, sizeof(addr6)));
}
else {
nsend = ::sendto(socket_, buf, buf_len, send_flags, (const struct sockaddr*)&addr, sizeof(addr)));
}
if ((nsend == -1) {
UVG_LOG_ERROR("Failed to send data: %s", strerror(errno));
if (bytes_sent)
@ -219,11 +334,17 @@ rtp_error_t uvgrtp::socket::__sendto(sockaddr_in& addr, uint8_t *buf, size_t buf
data_buf.buf = (char *)buf;
data_buf.len = (ULONG)buf_len;
if (WSASendTo(socket_, &data_buf, 1, &sent_bytes, send_flags, (const struct sockaddr *)&addr, sizeof(addr), nullptr, nullptr) == -1) {
int result = -1;
if (ipv6) {
result = WSASendTo(socket_, &data_buf, 1, &sent_bytes, send_flags, (const struct sockaddr*)&addr6, sizeof(addr6), nullptr, nullptr);
}
else {
result = WSASendTo(socket_, &data_buf, 1, &sent_bytes, send_flags, (const struct sockaddr*)&addr, sizeof(addr), nullptr, nullptr);
}
if (result == -1) {
win_get_last_error();
UVG_LOG_ERROR("Failed to send to %s", sockaddr_to_string(addr).c_str());
// FIX THIS
UVG_LOG_ERROR("Failed to send to %s", 1 /*sockaddr_to_string(addr).c_str()*/);
if (bytes_sent)
*bytes_sent = -1;
@ -244,26 +365,28 @@ rtp_error_t uvgrtp::socket::__sendto(sockaddr_in& addr, uint8_t *buf, size_t buf
rtp_error_t uvgrtp::socket::sendto(uint8_t *buf, size_t buf_len, int send_flags)
{
return __sendto(remote_address_, buf, buf_len, send_flags, nullptr);
return __sendto(remote_address_, remote_ip6_address_, ipv6_, buf, buf_len, send_flags, nullptr);
}
rtp_error_t uvgrtp::socket::sendto(uint8_t *buf, size_t buf_len, int send_flags, int *bytes_sent)
{
return __sendto(remote_address_, buf, buf_len, send_flags, bytes_sent);
return __sendto(remote_address_, remote_ip6_address_, ipv6_, buf, buf_len, send_flags, bytes_sent);
}
rtp_error_t uvgrtp::socket::sendto(sockaddr_in& addr, uint8_t *buf, size_t buf_len, int send_flags, int *bytes_sent)
rtp_error_t uvgrtp::socket::sendto(sockaddr_in& addr, sockaddr_in6& addr6, uint8_t *buf, size_t buf_len, int send_flags, int *bytes_sent)
{
return __sendto(addr, buf, buf_len, send_flags, bytes_sent);
return __sendto(addr, addr6, ipv6_, buf, buf_len, send_flags, bytes_sent);
}
rtp_error_t uvgrtp::socket::sendto(sockaddr_in& addr, uint8_t *buf, size_t buf_len, int send_flags)
rtp_error_t uvgrtp::socket::sendto(sockaddr_in& addr, sockaddr_in6& addr6, uint8_t *buf, size_t buf_len, int send_flags)
{
return __sendto(addr, buf, buf_len, send_flags, nullptr);
return __sendto(addr, addr6, ipv6_, buf, buf_len, send_flags, nullptr);
}
rtp_error_t uvgrtp::socket::__sendtov(
sockaddr_in& addr,
sockaddr_in6& addr6,
bool ipv6,
uvgrtp::buf_vec& buffers,
int send_flags, int *bytes_sent
)
@ -277,14 +400,21 @@ rtp_error_t uvgrtp::socket::__sendtov(
sent_bytes += buffers.at(i).first;
}
header_.msg_hdr.msg_name = (void *)&addr;
header_.msg_hdr.msg_namelen = sizeof(addr);
if (ipv6) {
header_.msg_hdr.msg_name = (void*)&addr6;
header_.msg_hdr.msg_namelen = sizeof(addr6);
}
else {
// mikä tämä void* on??
header_.msg_hdr.msg_name = (void *)&addr;
header_.msg_hdr.msg_namelen = sizeof(addr);
}
header_.msg_hdr.msg_iov = chunks_;
header_.msg_hdr.msg_iovlen = buffers.size();
header_.msg_hdr.msg_control = 0;
header_.msg_hdr.msg_controllen = 0;
// MIKÄ TÄMÄ SENDMMSG ON???
if (sendmmsg(socket_, &header_, 1, send_flags) < 0) {
UVG_LOG_ERROR("Failed to send RTP frame: %s!", strerror(errno));
set_bytes(bytes_sent, -1);
@ -305,12 +435,23 @@ rtp_error_t uvgrtp::socket::__sendtov(
buffers_[i].len = (ULONG)buffers.at(i).first;
buffers_[i].buf = (char *)buffers.at(i).second;
}
if (WSASendTo(socket_, buffers_, (DWORD)buffers.size(), &sent_bytes, send_flags,
(SOCKADDR *)&addr, sizeof(addr), nullptr, nullptr) == -1) {
int success = 0;
if (ipv6) {
success = WSASendTo(socket_, buffers_, (DWORD)buffers.size(), &sent_bytes, send_flags,
(SOCKADDR*)&addr6, sizeof(addr6), nullptr, nullptr);
}
else {
success = WSASendTo(socket_, buffers_, (DWORD)buffers.size(), &sent_bytes, send_flags,
(SOCKADDR*)&addr, sizeof(addr), nullptr, nullptr);
}
if (success != 0) {
win_get_last_error();
UVG_LOG_ERROR("Failed to send to %s", sockaddr_to_string(addr).c_str());
if (ipv6_) {
UVG_LOG_ERROR("Failed to send to %s", sockaddr_ip6_to_string(addr6).c_str());
}
else {
UVG_LOG_ERROR("Failed to send to %s", sockaddr_to_string(addr).c_str());
}
set_bytes(bytes_sent, -1);
return RTP_SEND_ERROR;
@ -338,7 +479,7 @@ rtp_error_t uvgrtp::socket::sendto(buf_vec& buffers, int send_flags)
}
}
return __sendtov(remote_address_, buffers, send_flags, nullptr);
return __sendtov(remote_address_, remote_ip6_address_, ipv6_, buffers, send_flags, nullptr);
}
rtp_error_t uvgrtp::socket::sendto(buf_vec& buffers, int send_flags, int *bytes_sent)
@ -352,10 +493,10 @@ rtp_error_t uvgrtp::socket::sendto(buf_vec& buffers, int send_flags, int *bytes_
}
}
return __sendtov(remote_address_, buffers, send_flags, bytes_sent);
return __sendtov(remote_address_, remote_ip6_address_, ipv6_, buffers, send_flags, bytes_sent);
}
rtp_error_t uvgrtp::socket::sendto(sockaddr_in& addr, buf_vec& buffers, int send_flags)
rtp_error_t uvgrtp::socket::sendto(sockaddr_in& addr, sockaddr_in6& addr6, buf_vec& buffers, int send_flags)
{
rtp_error_t ret = RTP_OK;
@ -365,12 +506,13 @@ rtp_error_t uvgrtp::socket::sendto(sockaddr_in& addr, buf_vec& buffers, int send
return ret;
}
}
return __sendtov(addr, buffers, send_flags, nullptr);
// buf_vec
return __sendtov(addr, addr6, ipv6_, buffers, send_flags, nullptr);
}
rtp_error_t uvgrtp::socket::sendto(
sockaddr_in& addr,
sockaddr_in6 & addr6,
buf_vec& buffers,
int send_flags, int *bytes_sent
)
@ -383,12 +525,14 @@ rtp_error_t uvgrtp::socket::sendto(
return ret;
}
}
return __sendtov(addr, buffers, send_flags, bytes_sent);
// buf_vec
return __sendtov(addr, addr6, ipv6_, buffers, send_flags, bytes_sent);
}
rtp_error_t uvgrtp::socket::__sendtov(
sockaddr_in& addr,
sockaddr_in6& addr6,
bool ipv6,
uvgrtp::pkt_vec& buffers,
int send_flags, int *bytes_sent
)
@ -404,8 +548,14 @@ rtp_error_t uvgrtp::socket::__sendtov(
for (size_t i = 0; i < buffers.size(); ++i) {
headers[i].msg_hdr.msg_iov = new struct iovec[buffers[i].size()];
headers[i].msg_hdr.msg_iovlen = buffers[i].size();
headers[i].msg_hdr.msg_name = (void *)&addr;
headers[i].msg_hdr.msg_namelen = sizeof(addr);
if (ipv6) {
headers[i].msg_hdr.msg_name = (void*)&addr6;
headers[i].msg_hdr.msg_namelen = sizeof(addr6);
}
else {
headers[i].msg_hdr.msg_name = (void *)&addr;
headers[i].msg_hdr.msg_namelen = sizeof(addr);
}
headers[i].msg_hdr.msg_control = 0;
headers[i].msg_hdr.msg_controllen = 0;
@ -420,6 +570,7 @@ rtp_error_t uvgrtp::socket::__sendtov(
ssize_t bptr = buffers.size();
while (bptr > npkts) {
// MIKÄ SENDMMSG
if (sendmmsg(socket_, hptr, npkts, send_flags) < 0) {
log_platform_error("sendmmsg(2) failed");
return_value = RTP_SEND_ERROR;
@ -466,18 +617,32 @@ rtp_error_t uvgrtp::socket::__sendtov(
send_:
DWORD sent_bytes_dw = 0;
ret = WSASendTo(
socket_,
wsa_bufs,
(DWORD)buffer.size(),
&sent_bytes_dw,
send_flags,
(SOCKADDR *)&addr,
sizeof(addr),
nullptr,
nullptr
);
if (ipv6) {
ret = WSASendTo(
socket_,
wsa_bufs,
(DWORD)buffer.size(),
&sent_bytes_dw,
send_flags,
(SOCKADDR*)&addr6,
sizeof(addr6),
nullptr,
nullptr
);
}
else {
ret = WSASendTo(
socket_,
wsa_bufs,
(DWORD)buffer.size(),
&sent_bytes_dw,
send_flags,
(SOCKADDR*)&addr,
sizeof(addr),
nullptr,
nullptr
);
}
sent_bytes = sent_bytes_dw;
if (ret == SOCKET_ERROR) {
@ -492,8 +657,12 @@ send_:
{
UVG_LOG_DEBUG("WSASendTo failed with error %li", error);
log_platform_error("WSASendTo() failed");
UVG_LOG_ERROR("Failed to send to %s", sockaddr_to_string(addr).c_str());
if (ipv6_) {
UVG_LOG_ERROR("Failed to send to %s", sockaddr_ip6_to_string(addr6).c_str());
}
else {
UVG_LOG_ERROR("Failed to send to %s", sockaddr_to_string(addr).c_str());
}
}
sent_bytes = -1;
@ -523,8 +692,7 @@ rtp_error_t uvgrtp::socket::sendto(pkt_vec& buffers, int send_flags)
}
}
}
return __sendtov(remote_address_, buffers, send_flags, nullptr);
return __sendtov(remote_address_, remote_ip6_address_, ipv6_, buffers, send_flags, nullptr);
}
rtp_error_t uvgrtp::socket::sendto(pkt_vec& buffers, int send_flags, int *bytes_sent)
@ -539,11 +707,10 @@ rtp_error_t uvgrtp::socket::sendto(pkt_vec& buffers, int send_flags, int *bytes_
}
}
}
return __sendtov(remote_address_, buffers, send_flags, bytes_sent);
return __sendtov(remote_address_, remote_ip6_address_, ipv6_, buffers, send_flags, bytes_sent);
}
rtp_error_t uvgrtp::socket::sendto(sockaddr_in& addr, pkt_vec& buffers, int send_flags)
rtp_error_t uvgrtp::socket::sendto(sockaddr_in& addr, sockaddr_in6& addr6, pkt_vec& buffers, int send_flags)
{
rtp_error_t ret = RTP_OK;
@ -555,11 +722,10 @@ rtp_error_t uvgrtp::socket::sendto(sockaddr_in& addr, pkt_vec& buffers, int send
}
}
}
return __sendtov(addr, buffers, send_flags, nullptr);
return __sendtov(addr, addr6, ipv6_, buffers, send_flags, nullptr);
}
rtp_error_t uvgrtp::socket::sendto(sockaddr_in& addr, pkt_vec& buffers, int send_flags, int *bytes_sent)
rtp_error_t uvgrtp::socket::sendto(sockaddr_in& addr, sockaddr_in6& addr6, pkt_vec& buffers, int send_flags, int *bytes_sent)
{
rtp_error_t ret = RTP_OK;
@ -571,8 +737,7 @@ rtp_error_t uvgrtp::socket::sendto(sockaddr_in& addr, pkt_vec& buffers, int send
}
}
}
return __sendtov(addr, buffers, send_flags, bytes_sent);
return __sendtov(addr, addr6, ipv6_, buffers, send_flags, bytes_sent);
}
rtp_error_t uvgrtp::socket::__recv(uint8_t *buf, size_t buf_len, int recv_flags, int *bytes_read)
@ -694,6 +859,61 @@ rtp_error_t uvgrtp::socket::__recvfrom(uint8_t *buf, size_t buf_len, int recv_fl
return RTP_OK;
}
rtp_error_t uvgrtp::socket::__recvfrom_ip6(uint8_t* buf, size_t buf_len, int recv_flags, sockaddr_in6* sender, int* bytes_read)
{
socklen_t* len_ptr = nullptr;
socklen_t len = sizeof(sockaddr_in6);
if (sender)
len_ptr = &len;
#ifndef _WIN32
int32_t ret = ::recvfrom(socket_, buf, buf_len, recv_flags, (struct sockaddr*)sender, len_ptr);
if (ret == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
set_bytes(bytes_read, 0);
return RTP_INTERRUPTED;
}
UVG_LOG_ERROR("recvfrom failed: %s", strerror(errno));
set_bytes(bytes_read, -1);
return RTP_GENERIC_ERROR;
}
set_bytes(bytes_read, ret);
#else
(void)recv_flags;
WSABUF DataBuf;
DataBuf.len = (u_long)buf_len;
DataBuf.buf = (char*)buf;
DWORD bytes_received = 0;
DWORD d_recv_flags = 0;
int rc = ::WSARecvFrom(socket_, &DataBuf, 1, &bytes_received, &d_recv_flags, (SOCKADDR*)sender, (int*)len_ptr, NULL, NULL);
if (WSAGetLastError() == WSAEWOULDBLOCK)
return RTP_INTERRUPTED;
int err = 0;
if ((rc == SOCKET_ERROR) && (WSA_IO_PENDING != (err = WSAGetLastError()))) {
/* win_get_last_error(); */
set_bytes(bytes_read, -1);
return RTP_GENERIC_ERROR;
}
set_bytes(bytes_read, bytes_received);
#endif
#ifndef NDEBUG
++received_packets_;
#endif // !NDEBUG
return RTP_OK;
}
rtp_error_t uvgrtp::socket::recvfrom(uint8_t *buf, size_t buf_len, int recv_flags, sockaddr_in *sender, int *bytes_read)
{
return __recvfrom(buf, buf_len, recv_flags, sender, bytes_read);
@ -701,6 +921,9 @@ rtp_error_t uvgrtp::socket::recvfrom(uint8_t *buf, size_t buf_len, int recv_flag
rtp_error_t uvgrtp::socket::recvfrom(uint8_t *buf, size_t buf_len, int recv_flags, int *bytes_read)
{
if (ipv6_) {
return __recvfrom_ip6(buf, buf_len, recv_flags, nullptr, bytes_read);
}
return __recvfrom(buf, buf_len, recv_flags, nullptr, bytes_read);
}

View File

@ -3,13 +3,18 @@
#include "uvgrtp/util.hh"
#ifdef _WIN32
#include <Windows.h>
#include <winsock2.h>
#include <mswsock.h>
#include <inaddr.h>
#include <ws2ipdef.h>
#include <WS2tcpip.h>
#else
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#include <vector>
@ -83,6 +88,7 @@ namespace uvgrtp {
* Return RTP_BIND_ERROR if the bind failed */
rtp_error_t bind(short family, unsigned host, short port);
rtp_error_t bind(sockaddr_in& local_address);
rtp_error_t bind_ip6(sockaddr_in6& local_address);
/* Same as setsockopt(2), used to manipulate the underlying socket object
*
@ -100,6 +106,7 @@ namespace uvgrtp {
*
* Return RTP_OK on success and write the amount of bytes sent to "bytes_sent"
* Return RTP_SEND_ERROR on error and set "bytes_sent" to -1 */
// nämä done
rtp_error_t sendto(uint8_t *buf, size_t buf_len, int send_flags);
rtp_error_t sendto(uint8_t *buf, size_t buf_len, int send_flags, int *bytes_sent);
rtp_error_t sendto(buf_vec& buffers, int send_flags);
@ -108,12 +115,15 @@ namespace uvgrtp {
rtp_error_t sendto(pkt_vec& buffers, int send_flags, int *bytes_sent);
/* Same as sendto() but the remote address given as parameter */
rtp_error_t sendto(sockaddr_in& addr, uint8_t *buf, size_t buf_len, int send_flags);
rtp_error_t sendto(sockaddr_in& addr, uint8_t *buf, size_t buf_len, int send_flags, int *bytes_sent);
rtp_error_t sendto(sockaddr_in& addr, buf_vec& buffers, int send_flags);
rtp_error_t sendto(sockaddr_in& addr, buf_vec& buffers, int send_flags, int *bytes_sent);
rtp_error_t sendto(sockaddr_in& addr, pkt_vec& buffers, int send_flags);
rtp_error_t sendto(sockaddr_in& addr, pkt_vec& buffers, int send_flags, int *bytes_sent);
// mitäs näille tehdään???
// rtcp käyttää tätä, ei korjattu
rtp_error_t sendto(sockaddr_in& addr, sockaddr_in6& addr6, uint8_t *buf, size_t buf_len, int send_flags);
// zrtp käyttää tätä, ei korjattu
rtp_error_t sendto(sockaddr_in& addr, sockaddr_in6& addr6, uint8_t *buf, size_t buf_len, int send_flags, int *bytes_sent);
rtp_error_t sendto(sockaddr_in& addr, sockaddr_in6& addr6, buf_vec& buffers, int send_flags);
rtp_error_t sendto(sockaddr_in& addr, sockaddr_in6& addr6, buf_vec& buffers, int send_flags, int *bytes_sent);
rtp_error_t sendto(sockaddr_in& addr, sockaddr_in6& addr6, pkt_vec& buffers, int send_flags);
rtp_error_t sendto(sockaddr_in& addr, sockaddr_in6& addr6, pkt_vec& buffers, int send_flags, int *bytes_sent);
/* Same as recv(2), receives a message from socket (remote address not known)
*
@ -123,6 +133,7 @@ namespace uvgrtp {
* Return RTP_INTERRUPTED if the call was interrupted due to timeout and set "bytes_sent" to 0
* Return RTP_GENERIC_ERROR on error and set "bytes_sent" to -1 */
rtp_error_t recv(uint8_t *buf, size_t buf_len, int recv_flags);
// used in poll
rtp_error_t recv(uint8_t *buf, size_t buf_len, int recv_flags, int *bytes_read);
/* Same as recvfrom(2), receives a message from remote
@ -135,6 +146,7 @@ namespace uvgrtp {
* Return RTP_GENERIC_ERROR on error and set "bytes_sent" to -1 */
rtp_error_t recvfrom(uint8_t *buf, size_t buf_len, int recv_flags, sockaddr_in *sender, int *bytes_read);
rtp_error_t recvfrom(uint8_t *buf, size_t buf_len, int recv_flags, sockaddr_in *sender);
// used in rec flow
rtp_error_t recvfrom(uint8_t *buf, size_t buf_len, int recv_flags, int *bytes_read);
rtp_error_t recvfrom(uint8_t *buf, size_t buf_len, int recv_flags);
@ -146,9 +158,15 @@ namespace uvgrtp {
* NOTE: "family" must be AF_INET */
sockaddr_in create_sockaddr(short family, std::string host, short port) const;
sockaddr_in6 create_ip6_sockaddr(unsigned host, short port) const;
sockaddr_in6 create_ip6_sockaddr(std::string host, short port) const;
sockaddr_in6 create_ip6_sockaddr_any(short src_port);
std::string get_socket_path_string() const;
std::string sockaddr_to_string(const sockaddr_in& addr) const;
std::string sockaddr_ip6_to_string(const sockaddr_in6& addr6) const;
/* Get reference to the actual socket object */
socket_t& get_raw_socket();
@ -157,6 +175,7 @@ namespace uvgrtp {
* This is used when calling send() */
void set_sockaddr(sockaddr_in addr);
void set_sockaddr6(sockaddr_in6 addr);
/* Get the out address for the socket if it exists */
sockaddr_in& get_out_address();
@ -172,17 +191,24 @@ namespace uvgrtp {
private:
/* helper function for sending UPD packets, see documentation for sendto() above */
rtp_error_t __sendto(sockaddr_in& addr, uint8_t *buf, size_t buf_len, int send_flags, int *bytes_sent);
rtp_error_t __sendto(sockaddr_in& addr, sockaddr_in6& addr6, bool ipv6, uint8_t *buf, size_t buf_len, int send_flags, int *bytes_sent);
rtp_error_t __recv(uint8_t *buf, size_t buf_len, int recv_flags, int *bytes_read);
rtp_error_t __recvfrom_ip6(uint8_t* buf, size_t buf_len, int recv_flags, sockaddr_in6* sender, int* bytes_read);
rtp_error_t __recvfrom(uint8_t *buf, size_t buf_len, int recv_flags, sockaddr_in *sender, int *bytes_read);
/* __sendtov() does the same as __sendto but it combines multiple buffers into one frame and sends them */
rtp_error_t __sendtov(sockaddr_in& addr, buf_vec& buffers, int send_flags, int *bytes_sent);
rtp_error_t __sendtov(sockaddr_in& addr, uvgrtp::pkt_vec& buffers, int send_flags, int *bytes_sent);
rtp_error_t __sendtov(sockaddr_in& addr, sockaddr_in6& addr6, bool ipv6, buf_vec& buffers, int send_flags, int *bytes_sent);
rtp_error_t __sendtov(sockaddr_in& addr, sockaddr_in6& addr6, bool ipv6, uvgrtp::pkt_vec& buffers, int send_flags, int *bytes_sent);
socket_t socket_;
SOCKET socket_;
sockaddr_in remote_address_;
sockaddr_in local_address_;
sockaddr_in6 remote_ip6_address_;
sockaddr_in6 local_ip6_address_;
bool ipv6_;
int rce_flags_;
/* __sendto() calls these handlers in order before sending the packet */

View File

@ -11,7 +11,12 @@
#include "crypto.hh"
#include "random.hh"
#include "debug.hh"
#ifdef _WIN32
#include <ws2ipdef.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#include <cstring>
#include <thread>
@ -27,6 +32,7 @@ using namespace uvgrtp::zrtp_msg;
uvgrtp::zrtp::zrtp():
ssrc_(0),
remote_addr_(),
remote_ip6_addr_(),
initialized_(false),
receiver_(),
dh_finished_(false)
@ -377,7 +383,7 @@ rtp_error_t uvgrtp::zrtp::begin_session()
UVG_LOG_DEBUG("Sending ZRTP hello # %i, path: %s", i + 1, path.c_str());
int type = 0;
if (hello.send_msg(local_socket_, remote_addr_) != RTP_OK) {
if (hello.send_msg(local_socket_, remote_addr_, remote_ip6_addr_) != RTP_OK) {
UVG_LOG_ERROR("Failed to send Hello message");
}
else if (receiver_.recv_msg(local_socket_, rto, 0, type) == RTP_OK) {
@ -388,7 +394,7 @@ rtp_error_t uvgrtp::zrtp::begin_session()
/* We received Hello message from remote, parse it and send */
if (type == ZRTP_FT_HELLO) {
UVG_LOG_DEBUG("Got ZRTP Hello. Sending Hello ACK");
hello_ack.send_msg(local_socket_, remote_addr_);
hello_ack.send_msg(local_socket_, remote_addr_, remote_ip6_addr_);
if (!hello_recv) {
hello_recv = true;
@ -480,7 +486,7 @@ rtp_error_t uvgrtp::zrtp::init_session(int key_agreement)
rto = 150;
for (int i = 0; i < 10; ++i) {
if (commit.send_msg(local_socket_, remote_addr_) != RTP_OK) {
if (commit.send_msg(local_socket_, remote_addr_, remote_ip6_addr_) != RTP_OK) {
UVG_LOG_ERROR("Failed to send Commit message!");
}
else if (receiver_.recv_msg(local_socket_, rto, 0, type) == RTP_OK) {
@ -519,7 +525,7 @@ rtp_error_t uvgrtp::zrtp::dh_part1()
int type = 0;
for (int i = 0; i < 10; ++i) {
if (dhpart.send_msg(local_socket_, remote_addr_) != RTP_OK) {
if (dhpart.send_msg(local_socket_, remote_addr_, remote_ip6_addr_) != RTP_OK) {
UVG_LOG_ERROR("Failed to send DHPart1 Message!");
}
@ -563,7 +569,7 @@ rtp_error_t uvgrtp::zrtp::dh_part2()
generate_shared_secrets_dh();
for (int i = 0; i < 10; ++i) {
if ((ret = dhpart.send_msg(local_socket_, remote_addr_)) != RTP_OK) {
if ((ret = dhpart.send_msg(local_socket_, remote_addr_, remote_ip6_addr_)) != RTP_OK) {
UVG_LOG_ERROR("Failed to send DHPart2 Message!");
return ret;
}
@ -590,7 +596,7 @@ rtp_error_t uvgrtp::zrtp::responder_finalize_session()
int type = 0;
for (int i = 0; i < 10; ++i) {
if (confirm.send_msg(local_socket_, remote_addr_) != RTP_OK) {
if (confirm.send_msg(local_socket_, remote_addr_, remote_ip6_addr_) != RTP_OK) {
UVG_LOG_ERROR("Failed to send Confirm1 Message!");
}
@ -608,7 +614,7 @@ rtp_error_t uvgrtp::zrtp::responder_finalize_session()
}
/* TODO: send in a loop? */
confack.send_msg(local_socket_, remote_addr_);
confack.send_msg(local_socket_, remote_addr_, remote_ip6_addr_);
return RTP_OK;
}
}
@ -638,7 +644,7 @@ rtp_error_t uvgrtp::zrtp::initiator_finalize_session()
}
for (int i = 0; i < 10; ++i) {
if ((ret = confirm.send_msg(local_socket_, remote_addr_)) != RTP_OK) {
if ((ret = confirm.send_msg(local_socket_, remote_addr_, remote_ip6_addr_)) != RTP_OK) {
UVG_LOG_ERROR("Failed to send Confirm2 Message!");
return ret;
}
@ -657,7 +663,7 @@ rtp_error_t uvgrtp::zrtp::initiator_finalize_session()
return RTP_TIMEOUT;
}
rtp_error_t uvgrtp::zrtp::init(uint32_t ssrc, std::shared_ptr<uvgrtp::socket> socket, sockaddr_in& addr, bool perform_dh)
rtp_error_t uvgrtp::zrtp::init(uint32_t ssrc, std::shared_ptr<uvgrtp::socket> socket, sockaddr_in& addr, sockaddr_in6& addr6, bool perform_dh, bool ipv6)
{
rtp_error_t ret = RTP_OK;
@ -672,7 +678,7 @@ rtp_error_t uvgrtp::zrtp::init(uint32_t ssrc, std::shared_ptr<uvgrtp::socket> so
}
// perform Diffie-Hellman (DH)
ret = init_dhm(ssrc, socket, addr);
ret = init_dhm(ssrc, socket, addr, addr6, ipv6);
zrtp_mtx_.unlock();
}
else
@ -684,17 +690,21 @@ rtp_error_t uvgrtp::zrtp::init(uint32_t ssrc, std::shared_ptr<uvgrtp::socket> so
}
// multistream mode
ret = init_msm(ssrc, socket, addr);
ret = init_msm(ssrc, socket, addr, addr6);
}
return ret;
}
rtp_error_t uvgrtp::zrtp::init_dhm(uint32_t ssrc, std::shared_ptr<uvgrtp::socket> socket, sockaddr_in& addr)
rtp_error_t uvgrtp::zrtp::init_dhm(uint32_t ssrc, std::shared_ptr<uvgrtp::socket> socket, sockaddr_in& addr, sockaddr_in6& addr6, bool ipv6)
{
rtp_error_t ret = RTP_OK;
UVG_LOG_DEBUG("Starting ZRTP Diffie-Hellman negotiation with %s", socket->sockaddr_to_string(addr).c_str());
if (ipv6) {
UVG_LOG_DEBUG("Starting ZRTP Diffie-Hellman negotiation with %s", socket->sockaddr_ip6_to_string(addr6).c_str());
}
else {
UVG_LOG_DEBUG("Starting ZRTP Diffie-Hellman negotiation with %s", socket->sockaddr_to_string(addr).c_str());
}
/* TODO: set all fields initially to zero */
memset(session_.hash_ctx.o_hvi, 0, sizeof(session_.hash_ctx.o_hvi));
@ -708,6 +718,7 @@ rtp_error_t uvgrtp::zrtp::init_dhm(uint32_t ssrc, std::shared_ptr<uvgrtp::socket
local_socket_ = socket;
remote_addr_ = addr;
remote_ip6_addr_ = addr6;
session_.seq = 0;
session_.ssrc = ssrc;
@ -789,12 +800,13 @@ rtp_error_t uvgrtp::zrtp::init_dhm(uint32_t ssrc, std::shared_ptr<uvgrtp::socket
return RTP_OK;
}
rtp_error_t uvgrtp::zrtp::init_msm(uint32_t ssrc, std::shared_ptr<uvgrtp::socket> socket, sockaddr_in& addr)
rtp_error_t uvgrtp::zrtp::init_msm(uint32_t ssrc, std::shared_ptr<uvgrtp::socket> socket, sockaddr_in& addr, sockaddr_in6& addr6)
{
rtp_error_t ret;
local_socket_ = socket;
remote_addr_ = addr;
remote_ip6_addr_ = addr6;
session_.ssrc = ssrc;
session_.seq = 0;

View File

@ -8,9 +8,13 @@
#include <winsock2.h>
#include <mswsock.h>
#include <inaddr.h>
#include <ws2ipdef.h>
#else
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#endif
#include <mutex>
@ -42,7 +46,7 @@ namespace uvgrtp {
*
* Return RTP_OK on success
* Return RTP_TIMEOUT if remote did not send messages in timely manner */
rtp_error_t init(uint32_t ssrc, std::shared_ptr<uvgrtp::socket> socket, sockaddr_in& addr, bool perform_dh);
rtp_error_t init(uint32_t ssrc, std::shared_ptr<uvgrtp::socket> socket, sockaddr_in& addr, sockaddr_in6& addr6, bool perform_dh, bool ipv6);
/* Get SRTP keys for the session that was just initialized
*
@ -85,13 +89,13 @@ namespace uvgrtp {
*
* Return RTP_OK on success
* Return RTP_TIMEOUT if remote did not send messages in timely manner */
rtp_error_t init_dhm(uint32_t ssrc, std::shared_ptr<uvgrtp::socket> socket, sockaddr_in& addr);
rtp_error_t init_dhm(uint32_t ssrc, std::shared_ptr<uvgrtp::socket> socket, sockaddr_in& addr, sockaddr_in6& addr6, bool ipv6);
/* Initialize ZRTP session between us and remote using Multistream mode
*
* Return RTP_OK on success
* Return RTP_TIMEOUT if remote did not send messages in timely manner */
rtp_error_t init_msm(uint32_t ssrc, std::shared_ptr<uvgrtp::socket> socket, sockaddr_in& addr);
rtp_error_t init_msm(uint32_t ssrc, std::shared_ptr<uvgrtp::socket> socket, sockaddr_in& addr, sockaddr_in6& addr6);
/* Generate zid for this ZRTP instance. ZID is a unique, 96-bit long ID */
void generate_zid();
@ -170,6 +174,7 @@ namespace uvgrtp {
uint32_t ssrc_;
std::shared_ptr<uvgrtp::socket> local_socket_;
sockaddr_in remote_addr_;
sockaddr_in6 remote_ip6_addr_;
/* Has the ZRTP connection been initialized using DH */
bool initialized_;

View File

@ -6,6 +6,12 @@
#include "debug.hh"
#include <string>
#ifdef _WIN32
#include <ws2ipdef.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif
uvgrtp::zrtp_msg::zrtp_message::zrtp_message():
frame_(nullptr),
@ -26,11 +32,10 @@ uvgrtp::zrtp_msg::zrtp_message::~zrtp_message()
(void)uvgrtp::frame::dealloc_frame((uvgrtp::frame::zrtp_frame*)rframe_);
}
rtp_error_t uvgrtp::zrtp_msg::zrtp_message::send_msg(std::shared_ptr<uvgrtp::socket> socket, sockaddr_in& addr)
rtp_error_t uvgrtp::zrtp_msg::zrtp_message::send_msg(std::shared_ptr<uvgrtp::socket> socket, sockaddr_in& addr, sockaddr_in6& addr6)
{
rtp_error_t ret;
if ((ret = socket->sendto(addr, (uint8_t *)frame_, len_, 0, nullptr)) != RTP_OK)
if ((ret = socket->sendto(addr, addr6, (uint8_t*)frame_, len_, 0, nullptr)) != RTP_OK)
log_platform_error("Failed to send ZRTP message");
return ret;

View File

@ -7,6 +7,12 @@
#include "uvgrtp/util.hh"
#include <memory>
#ifdef _WIN32
#include <ws2ipdef.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif
namespace uvgrtp {
@ -19,7 +25,7 @@ namespace uvgrtp {
zrtp_message();
~zrtp_message();
rtp_error_t send_msg(std::shared_ptr<uvgrtp::socket> socket, sockaddr_in& addr);
rtp_error_t send_msg(std::shared_ptr<uvgrtp::socket> socket, sockaddr_in& addr, sockaddr_in6& addr6);
virtual rtp_error_t parse_msg(uvgrtp::zrtp_msg::receiver& receiver,
zrtp_session_t& session) = 0;