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

Fixed default binding for IPv6-target rendezvous. Updated documentation. #1381

Merged
merged 4 commits into from
Aug 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions apps/transmitmedia.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,25 +436,28 @@ void SrtCommon::OpenRendezvous(string adapter, string host, int port)
if ( stat == SRT_ERROR )
Error("ConfigurePre");

sockaddr_any sa = CreateAddr(host, port);
if (sa.family() == AF_UNSPEC)
{
Error("OpenRendezvous: invalid target host specification: " + host);
}

const int outport = m_outgoing_port ? m_outgoing_port : port;

sockaddr_any localsa = CreateAddr(adapter, outport);
sockaddr* plsa = localsa.get();
sockaddr_any localsa = CreateAddr(adapter, outport, sa.family());

Verb() << "Binding a server on " << adapter << ":" << outport;

stat = srt_bind(m_sock, plsa, sizeof localsa);
stat = srt_bind(m_sock, localsa.get(), sizeof localsa);
if ( stat == SRT_ERROR )
{
srt_close(m_sock);
Error("srt_bind");
}

sockaddr_any sa = CreateAddr(host, port);
sockaddr* psa = sa.get();
Verb() << "Connecting to " << host << ":" << port;

stat = srt_connect(m_sock, psa, sizeof sa);
stat = srt_connect(m_sock, sa.get(), sizeof sa);
if ( stat == SRT_ERROR )
{
srt_close(m_sock);
Expand Down
47 changes: 47 additions & 0 deletions docs/srt-live-transmit.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,53 @@ specified in the URI:
- The **adapter** parameter can be used to specify the adapter.
- The **port** parameter can be used to specify the local port to bind to.

**IMPORTANT** information about IPv6.

This application can also use an address specified as IPv6 with
the following restrictions:

1. The IPv6 address in the URI is specified in square brackets: e.g.
`srt://[::1]:5000`.

2. In listener mode, if you leave the host empty, the socket is bound to
`INADDR_ANY` for IPv4 only. If you want to make it listen on IPv6, you need to
specify the host as `::`.
NOTE: Don't use square brackets syntax in the adapter specification,
as in this case only the host is expected.

3. If you want to listen for connections from both IPv4 and IPv6, mind the
`ipv6only` option. The default value for this option is system default (see
system manual for `IPV6_V6ONLY` socket option); if unsure, you might want to
enforce `ipv6only=0` in order to be able to accept both IPv4 and IPv6
connections in the same listener.

4. In rendezvous mode you may only interconnect both parties using IPv4,
or both using IPv6. Unlike listener mode, if you want to leave the socket
default-bound (you don't specify `adapter`), the socket will be bound with the
same IP version as the target address. If you do specify `adapter`,
then both this address and the target address must be of the same family.

Examples:

* `srt://:5000` defines listener mode with IPv4.

* `srt://[::]:5000` defines caller mode (!) with IPv6.

* `srt://[::]:5000?mode=listener` defines listener mode with IPv6. If the
* default value for `IPV6_V6ONLY` system socket option is 0, it will accept
* also IPv4 connections.

* `srt://192.168.0.5:5000?mode=rendezvous` will make a rendezvous connection
* with local address `INADDR_ANY` (IPv4) and port 5000 to a destination with
* port 5000.

* `srt://[::1]:5000?mode=rendezvous&port=4000` will make a rendezvous
* connection with local address `inaddr6_any` (IPv6) and port 4000 to a
* destination with port 5000.

* `srt://[::1]:5000?adapter=127.0.0.1&mode=rendezvous` - this URI is invalid
* (different IP versions for binding and target address)

Some parameters handled for SRT medium are specific, all others are socket options. The following parameters are handled special way by *srt-live-transmit*:

- **mode**: enforce caller, listener or rendezvous mode
Expand Down
17 changes: 15 additions & 2 deletions srtcore/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1589,8 +1589,19 @@ int CUDTUnited::connectIn(CUDTSocket* s, const sockaddr_any& target_addr, int32_
// -> pthread_create(...C(Snd|Rcv)Queue::worker...)
s->m_Status = SRTS_OPENED;
}
else if (s->m_Status != SRTS_OPENED)
throw CUDTException(MJ_NOTSUP, MN_ISCONNECTED, 0);
else
{
if (s->m_Status != SRTS_OPENED)
throw CUDTException(MJ_NOTSUP, MN_ISCONNECTED, 0);

// status = SRTS_OPENED, so family should be known already.
if (target_addr.family() != s->m_SelfAddr.family())
{
LOGP(mglog.Error, "srt_connect: socket is bound to a different family than target address");
throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
}
}


// connect_complete() may be called before connect() returns.
// So we need to update the status before connect() is called,
Expand Down Expand Up @@ -2474,6 +2485,7 @@ void CUDTUnited::updateMux(
s->m_pUDT->m_pSndQueue = i->second.m_pSndQueue;
s->m_pUDT->m_pRcvQueue = i->second.m_pRcvQueue;
s->m_iMuxID = i->second.m_iID;
s->m_SelfAddr.family(addr.family());
return;
}
}
Expand Down Expand Up @@ -2534,6 +2546,7 @@ void CUDTUnited::updateMux(
sockaddr_any sa;
m.m_pChannel->getSockAddr((sa));
m.m_iPort = sa.hport();
s->m_SelfAddr = sa; // Will be also completed later, but here it's needed for later checks

m.m_pTimer = new CTimer;

Expand Down
18 changes: 15 additions & 3 deletions testing/testmedia.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1125,15 +1125,27 @@ void SrtCommon::Error(string src, int reason, int force_result)
throw TransmissionError("error: " + src + ": " + message);
}

void SrtCommon::SetupRendezvous(string adapter, int port)
void SrtCommon::SetupRendezvous(string adapter, string host, int port)
{
sockaddr_any target = CreateAddr(host, port);
if (target.family() == AF_UNSPEC)
{
Error("Unable to resolve target host: " + host);
}

bool yes = true;
srt_setsockopt(m_sock, 0, SRTO_RENDEZVOUS, &yes, sizeof yes);

const int outport = m_outgoing_port ? m_outgoing_port : port;

auto localsa = CreateAddr(adapter, outport);
Verb() << "Binding a server on " << adapter << ":" << outport << " ...";
// Prefer the same IPv as target host
auto localsa = CreateAddr(adapter, outport, target.family());
string showhost = adapter;
if (showhost == "")
showhost = "ANY";
if (target.family() == AF_INET6)
showhost = "[" + showhost + "]";
Verb() << "Binding rendezvous: " << showhost << ":" << outport << " ...";
int stat = srt_bind(m_sock, localsa.get(), localsa.size());
if (stat == SRT_ERROR)
{
Expand Down
4 changes: 2 additions & 2 deletions testing/testmedia.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class SrtCommon
void PrepareClient();
void SetupAdapter(const std::string& host, int port);
void ConnectClient(string host, int port);
void SetupRendezvous(string adapter, int port);
void SetupRendezvous(string adapter, string host, int port);

void OpenServer(string host, int port, int backlog = 1)
{
Expand All @@ -140,7 +140,7 @@ class SrtCommon
void OpenRendezvous(string adapter, string host, int port)
{
PrepareClient();
SetupRendezvous(adapter, port);
SetupRendezvous(adapter, host, port);
ConnectClient(host, port);
}

Expand Down