Skip to content

Commit

Permalink
[core][API] Added srt_getsockdevname to obtain the device name from a…
Browse files Browse the repository at this point in the history
… connected socket
  • Loading branch information
Mikolaj Malecki committed Jul 26, 2024
1 parent a4a4c18 commit c1ed253
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 88 deletions.
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ option(USE_OPENSSL_PC "Use pkg-config to find OpenSSL libraries" ON)
option(OPENSSL_USE_STATIC_LIBS "Link OpenSSL libraries statically." OFF)
option(USE_BUSY_WAITING "Enable more accurate sending times at a cost of potentially higher CPU load" OFF)
option(USE_GNUSTL "Get c++ library/headers from the gnustl.pc" OFF)
option(ENABLE_CONSELF_CHECK_WIN32 "Enable rendezvous-connect-to-self prevention on Windows (adds Iphlpapi.lib dep)" OFF)
option(ENABLE_LOCALIF_WIN32 "Enable rendezvous-connect-to-self prevention on Windows (adds Iphlpapi.lib dep)" OFF)
option(ENABLE_SOCK_CLOEXEC "Enable setting SOCK_CLOEXEC on a socket" ON)
option(ENABLE_SHOW_PROJECT_CONFIG "Enable show Project Configuration" OFF)

Expand Down Expand Up @@ -1293,9 +1293,9 @@ macro(srt_add_program name)
else()
message(WARNING "No location to install program ${name}")
endif()
if (MICROSOFT AND ENABLE_CONSELF_CHECK_WIN32)
if (MICROSOFT AND ENABLE_LOCALIF_WIN32)
target_link_libraries(${name} Iphlpapi)
add_definitions(-DSRT_ENABLE_CONSELF_CHECK_WIN32)
add_definitions(-DSRT_ENABLE_LOCALIF_WIN32)
endif()
endmacro()

Expand Down
87 changes: 3 additions & 84 deletions apps/apputil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
#include <utility>
#include <memory>

#include <ifaddrs.h>
#include "srt.h" // Required for SRT_SYNC_CLOCK_* definitions.
#include "common.h"
#include "apputil.hpp"
#include "netinet_any.h"
#include "srt_compat.h"
Expand Down Expand Up @@ -391,79 +391,6 @@ void PrintLibVersion()
cerr << "SRT Library version: " << major << "." << minor << "." << patch << ", clock type: " << SRTClockTypeStr() << endl;
}

#ifdef _WIN32
#if SRT_ENABLE_CONSELF_CHECK_WIN32
#define ENABLE_CONSELF_CHECK 1
#endif
#else

// For non-Windows platofm, enable always.
#define ENABLE_CONSELF_CHECK 1
#endif

#if ENABLE_CONSELF_CHECK

static vector<sockaddr_any> GetLocalInterfaces()
{
vector<sockaddr_any> locals;
#ifdef _WIN32
ULONG flags = GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_ALL_INTERFACES;
ULONG outBufLen4 = 0, outBufLen6 = 0, outBufLen = 0;

// This function doesn't allocate memory by itself, you have to do it
// yourself, worst case when it's too small, the size will be corrected
// and the function will do nothing. So, simply, call the function with
// always too little 0 size and make it show the correct one.
GetAdaptersAddresses(AF_INET, flags, NULL, NULL, &outBufLen4);
GetAdaptersAddresses(AF_INET, flags, NULL, NULL, &outBufLen6);
// Ignore errors. Check errors on the real call.
// (Have doubts about this "max" here, as VC reports errors when
// using std::max, so it will likely resolve to a macro - hope this
// won't cause portability problems, this code is Windows only.
outBufLen = max(outBufLen4, outBufLen6);

// Good, now we can allocate memory
PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)::operator new(outBufLen);
ULONG st = GetAdaptersAddresses(AF_INET, flags, NULL, pAddresses, &outBufLen);
if (st == ERROR_SUCCESS)
{
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = pAddresses->FirstUnicastAddress;
while (pUnicast)
{
locals.push_back(pUnicast->Address.lpSockaddr);
pUnicast = pUnicast->Next;
}
}
st = GetAdaptersAddresses(AF_INET6, flags, NULL, pAddresses, &outBufLen);
if (st == ERROR_SUCCESS)
{
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = pAddresses->FirstUnicastAddress;
while (pUnicast)
{
locals.push_back(pUnicast->Address.lpSockaddr);
pUnicast = pUnicast->Next;
}
}

::operator delete(pAddresses);

#else
// Use POSIX method: getifaddrs
struct ifaddrs* pif, * pifa;
int st = getifaddrs(&pifa);
if (st == 0)
{
for (pif = pifa; pif; pif = pif->ifa_next)
{
locals.push_back(pif->ifa_addr);
}
}

freeifaddrs(pifa);
#endif
return locals;
}

bool IsTargetAddrSelf(const sockaddr* boundaddr, const sockaddr* targetaddr)
{
sockaddr_any bound = boundaddr;
Expand All @@ -481,7 +408,7 @@ bool IsTargetAddrSelf(const sockaddr* boundaddr, const sockaddr* targetaddr)
else
{
// Bound to INADDR_ANY, so check matching with any local IP address
vector<sockaddr_any> locals = GetLocalInterfaces();
vector<srt::LocalInterface> locals = srt::GetLocalInterfaces();

// If any of the above function fails, it will collect
// no local interfaces, so it's impossible to check anything.
Expand All @@ -490,7 +417,7 @@ bool IsTargetAddrSelf(const sockaddr* boundaddr, const sockaddr* targetaddr)
// local address anyway.
for (size_t i = 0; i < locals.size(); ++i)
{
if (locals[i].equal_address(target))
if (locals[i].addr.equal_address(target))
{
return true;
}
Expand All @@ -500,11 +427,3 @@ bool IsTargetAddrSelf(const sockaddr* boundaddr, const sockaddr* targetaddr)
return false;
}

#else
bool IsTargetAddrSelf(const sockaddr* , const sockaddr* )
{
// State that the given address is never "self", so
// prevention from connecting to self will not be in force.
return false;
}
#endif
2 changes: 1 addition & 1 deletion apps/verbose.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ inline void Print(Log& ) {}
template <typename Arg1, typename... Args>
inline void Print(Log& out, Arg1&& arg1, Args&&... args)
{
out << std::forward(arg1);
out << std::forward<Arg1>(arg1);
Print(out, args...);
}

Expand Down
51 changes: 51 additions & 0 deletions srtcore/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2180,6 +2180,39 @@ void srt::CUDTUnited::getsockname(const SRTSOCKET u, sockaddr* pw_name, int* pw_
*pw_namelen = len;
}

void srt::CUDTUnited::getsockdevname(const SRTSOCKET u, char* pw_name, size_t* pw_namelen)
{
if (!pw_name || !pw_namelen)
throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);

CUDTSocket* s = locateSocket(u);

if (!s)
throw CUDTException(MJ_NOTSUP, MN_SIDINVAL, 0);

if (s->core().m_bBroken)
throw CUDTException(MJ_NOTSUP, MN_SIDINVAL, 0);

if (s->m_Status == SRTS_INIT)
throw CUDTException(MJ_CONNECTION, MN_NOCONN, 0);

vector<LocalInterface> locals = GetLocalInterfaces();

for (vector<LocalInterface>::iterator i = locals.begin(); i != locals.end(); ++i)
{
if (i->addr.equal_address(s->m_SelfAddr))
{
if (*pw_namelen < i->name.size() + 1)
throw CUDTException(MJ_NOTSUP, MN_INVAL);
memcpy((pw_name), i->name.c_str(), i->name.size()+1);
*pw_namelen = i->name.size();
return;
}
}

*pw_namelen = 0; // report empty one
}

int srt::CUDTUnited::select(UDT::UDSET* readfds, UDT::UDSET* writefds, UDT::UDSET* exceptfds, const timeval* timeout)
{
const steady_clock::time_point entertime = steady_clock::now();
Expand Down Expand Up @@ -3784,6 +3817,24 @@ int srt::CUDT::getsockname(SRTSOCKET u, sockaddr* name, int* namelen)
}
}

int srt::CUDT::getsockdevname(SRTSOCKET u, char* name, size_t* namelen)
{
try
{
uglobal().getsockdevname(u, name, namelen);
return 0;
}
catch (const CUDTException& e)
{
return APIError(e);
}
catch (const std::exception& ee)
{
LOGC(aclog.Fatal, log << "getsockname: UNEXPECTED EXCEPTION: " << typeid(ee).name() << ": " << ee.what());
return APIError(MJ_UNKNOWN, MN_NONE, 0);
}
}

int srt::CUDT::getsockopt(SRTSOCKET u, int, SRT_SOCKOPT optname, void* pw_optval, int* pw_optlen)
{
if (!pw_optval || !pw_optlen)
Expand Down
1 change: 1 addition & 0 deletions srtcore/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ class CUDTUnited
int close(CUDTSocket* s);
void getpeername(const SRTSOCKET u, sockaddr* name, int* namelen);
void getsockname(const SRTSOCKET u, sockaddr* name, int* namelen);
void getsockdevname(const SRTSOCKET u, char* name, size_t* namelen);
int select(UDT::UDSET* readfds, UDT::UDSET* writefds, UDT::UDSET* exceptfds, const timeval* timeout);
int selectEx(const std::vector<SRTSOCKET>& fds,
std::vector<SRTSOCKET>* readfds,
Expand Down
83 changes: 83 additions & 0 deletions srtcore/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ modified by
#include <iomanip>
#include <iterator>
#include <vector>

#if _WIN32
#if SRT_ENABLE_LOCALIF_WIN32
#include <iphlpapi.h>
#endif
#else
#include <ifaddrs.h>
#endif

#include "udt.h"
#include "md5.h"
#include "common.h"
Expand Down Expand Up @@ -461,6 +470,80 @@ bool SrtParseConfig(const string& s, SrtConfig& w_config)

return true;
}

vector<LocalInterface> GetLocalInterfaces()
{
vector<LocalInterface> locals;
#ifdef _WIN32
// If not enabled, simply an empty local vector will be returned
#if SRT_ENABLE_LOCALIF_WIN32
ULONG flags = GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_INCLUDE_ALL_INTERFACES;
ULONG outBufLen = 0;

// This function doesn't allocate memory by itself, you have to do it
// yourself, worst case when it's too small, the size will be corrected
// and the function will do nothing. So, simply, call the function with
// always too little 0 size and make it show the correct one.
GetAdaptersAddresses(AF_UNSPEC, flags, NULL, NULL, &outBufLen);
// Ignore errors. Check errors on the real call.
// (Have doubts about this "max" here, as VC reports errors when
// using std::max, so it will likely resolve to a macro - hope this
// won't cause portability problems, this code is Windows only.

// Good, now we can allocate memory
PIP_ADAPTER_ADDRESSES pAddresses = (PIP_ADAPTER_ADDRESSES)::operator new(outBufLen);
ULONG st = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, pAddresses, &outBufLen);
if (st == ERROR_SUCCESS)
{
for (PIP_ADAPTER_ADDRESSES* i = pAddresses; i; i = pAddresses->Next)
{
std::string name = i->AdapterName;
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = pAddresses->FirstUnicastAddress;
while (pUnicast)
{
LocalInterface a;
a.addr = pUnicast->Address.lpSockaddr;
if (a.addr.len > 0)
{
// DO NOT collect addresses that are not of
// AF_INET or AF_INET6 family.
a.name = name;
locals.push_back(a);
}
pUnicast = pUnicast->Next;
}
}
}

::operator delete(pAddresses);
#endif

#else
// Use POSIX method: getifaddrs
struct ifaddrs* pif, * pifa;
int st = getifaddrs(&pifa);
if (st == 0)
{
for (pif = pifa; pif; pif = pif->ifa_next)
{
LocalInterface i;
i.addr = pif->ifa_addr;
if (i.addr.len > 0)
{
// DO NOT collect addresses that are not of
// AF_INET or AF_INET6 family.
i.name = pif->ifa_name ? pif->ifa_name : "";
locals.push_back(i);
}
}
}

freeifaddrs(pifa);
#endif
return locals;
}


} // namespace srt

namespace srt_logging
Expand Down
8 changes: 8 additions & 0 deletions srtcore/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -1453,6 +1453,14 @@ inline std::string FormatLossArray(const std::vector< std::pair<int32_t, int32_t
return os.str();
}

struct LocalInterface
{
sockaddr_any addr;
std::string name;
};

std::vector<LocalInterface> GetLocalInterfaces();

} // namespace srt

#endif
1 change: 1 addition & 0 deletions srtcore/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ class CUDT
static int close(SRTSOCKET u);
static int getpeername(SRTSOCKET u, sockaddr* name, int* namelen);
static int getsockname(SRTSOCKET u, sockaddr* name, int* namelen);
static int getsockdevname(SRTSOCKET u, char* name, size_t* namelen);
static int getsockopt(SRTSOCKET u, int level, SRT_SOCKOPT optname, void* optval, int* optlen);
static int setsockopt(SRTSOCKET u, int level, SRT_SOCKOPT optname, const void* optval, int optlen);
static int send(SRTSOCKET u, const char* buf, int len, int flags);
Expand Down
1 change: 1 addition & 0 deletions srtcore/srt.h
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ SRT_API int srt_rendezvous (SRTSOCKET u, const struct sockaddr* local_na
SRT_API int srt_close (SRTSOCKET u);
SRT_API int srt_getpeername (SRTSOCKET u, struct sockaddr* name, int* namelen);
SRT_API int srt_getsockname (SRTSOCKET u, struct sockaddr* name, int* namelen);
SRT_API int srt_getsockdevname(SRTSOCKET u, char* name, size_t* namelen);
SRT_API int srt_getsockopt (SRTSOCKET u, int level /*ignored*/, SRT_SOCKOPT optname, void* optval, int* optlen);
SRT_API int srt_setsockopt (SRTSOCKET u, int level /*ignored*/, SRT_SOCKOPT optname, const void* optval, int optlen);
SRT_API int srt_getsockflag (SRTSOCKET u, SRT_SOCKOPT opt, void* optval, int* optlen);
Expand Down
1 change: 1 addition & 0 deletions srtcore/srt_c_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ int srt_close(SRTSOCKET u)

int srt_getpeername(SRTSOCKET u, struct sockaddr * name, int * namelen) { return CUDT::getpeername(u, name, namelen); }
int srt_getsockname(SRTSOCKET u, struct sockaddr * name, int * namelen) { return CUDT::getsockname(u, name, namelen); }
int srt_getsockdevname(SRTSOCKET u, char* devname, size_t * devnamelen) { return CUDT::getsockdevname(u, devname, devnamelen); }
int srt_getsockopt(SRTSOCKET u, int level, SRT_SOCKOPT optname, void * optval, int * optlen)
{ return CUDT::getsockopt(u, level, optname, optval, optlen); }
int srt_setsockopt(SRTSOCKET u, int level, SRT_SOCKOPT optname, const void * optval, int optlen)
Expand Down
12 changes: 12 additions & 0 deletions testing/testmedia.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1419,6 +1419,18 @@ void SrtCommon::ConnectClient(string host, int port)
}

Verb() << " connected.";

sockaddr_any agent;
string dev;
if (Verbose::on)
{
srt_getsockname(m_sock, agent.get(), &agent.len);
char name[256];
size_t len = 255;
if (srt_getsockdevname(m_sock, name, &len) == SRT_SUCCESS)
dev.assign(name, len);
}
Verb("Connected AGENT:", agent.str(), "[", dev, "] PEER:", sa.str());
stat = ConfigurePost(m_sock);
if (stat == SRT_ERROR)
Error("ConfigurePost");
Expand Down

0 comments on commit c1ed253

Please sign in to comment.