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

[core][API] Obtaining local interfaces to allow getting connected device name #2989

Draft
wants to merge 34 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
37aa803
Added check code for attempting rendezvous to self
May 9, 2018
7aaeeb3
Fixed build breaks on MICROSOFT
May 9, 2018
e39d94d
Fixed copying by type recognition condition
ethouris May 16, 2018
d798b01
Changed style
ethouris May 16, 2018
2f5a505
Split out apputil.cpp file
May 17, 2018
c9200e1
Added prevention of self-connecting to testing applications
May 17, 2018
00e10c2
Fixed build break on Windows
May 17, 2018
1d5bd08
Fixed incorrect implementation on Windows. Reading all families
May 17, 2018
5616437
Upgraded to latest upstream
May 23, 2019
117295e
Updated to latest upstream
Aug 9, 2019
6356b76
Fixed after merge
Aug 9, 2019
1c1b4f2
Fixed external inet_pton for mingw
Aug 9, 2019
b25e962
Updated to latest master. Made conself-check conditional and default …
Aug 14, 2019
4620850
Moved Iphlpapi lib to test programs only
Aug 14, 2019
99399ff
Some fixes for Windows
Aug 14, 2019
088d295
Merge branch 'master' into dev-add-rendezvous-to-self-prevention
Aug 22, 2019
bf94875
Merge branch 'master' into dev-add-rendezvous-to-self-prevention
Nov 8, 2019
bc3e2ed
Removed empty line to avoid unnecessary changes
Nov 8, 2019
a4134f8
Merge branch 'master' into dev-add-rendezvous-to-self-prevention
Dec 9, 2019
cf243a2
Updated to latest upstream
Nov 28, 2022
e27c268
Fixed compile errors after merge
Nov 28, 2022
a4a4c18
Merge remote-tracking branch 'ethouris/dev-add-rendezvous-to-self-pre…
Jul 26, 2024
c1ed253
[core][API] Added srt_getsockdevname to obtain the device name from a…
Jul 26, 2024
e5aa2dc
Enabled LOCALIF flag on C++11-win workflow
Jul 26, 2024
b8fbbc5
Fixed a case when the address is NULL (found on Cygwin)
ethouris Jul 26, 2024
d51262b
Fixed mistake in workflofs/cxx11-win
ethouris Jul 26, 2024
7b53f6f
Added printing device on listener in verbose mode
Jul 26, 2024
8fe7b3a
Fixed build break on Windows
Jul 26, 2024
0488b25
Merged and fixed
ethouris Jul 26, 2024
42666ca
Fixing wrong withdrawn changes
ethouris Jul 26, 2024
efaf0d7
Updated and fixed
Aug 14, 2024
4f9aa57
Merge remote-tracking branch 'ethouris/dev-add-obtaining-network-id' …
Aug 14, 2024
eb6a84a
Enabled LOCALIF always on windows, not only MICROSOFT
Aug 14, 2024
22fc22b
Fixed Iphlpapi library depend declaration on Windows
ethouris Aug 14, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/cxx11-win.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: configure
run: |
md _build && cd _build
cmake ../ -DENABLE_STDCXX_SYNC=ON -DENABLE_ENCRYPTION=OFF -DENABLE_UNITTESTS=ON -DENABLE_BONDING=ON
cmake ../ -DENABLE_STDCXX_SYNC=ON -DENABLE_ENCRYPTION=OFF -DENABLE_UNITTESTS=ON -DENABLE_BONDING=ON -DENABLE_LOCALIF_WIN32=ON
- name: build
run: cd _build && cmake --build ./ --config Release
- name: test
Expand Down
22 changes: 21 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ option(ENABLE_PKTINFO "Enable using IP_PKTINFO to allow the listener extracting
option(ENABLE_RELATIVE_LIBPATH "Should application contain relative library paths, like ../lib" OFF)
option(ENABLE_GETNAMEINFO "In-logs sockaddr-to-string should do rev-dns" OFF)
option(ENABLE_UNITTESTS "Enable unit tests" OFF)
option(ENABLE_UNITTESTS_AUTO "Enable unit tests" OFF)
option(ENABLE_ENCRYPTION "Enable encryption in SRT" ON)
option(ENABLE_AEAD_API_PREVIEW "Enable AEAD API preview in SRT" Off)
option(ENABLE_MAXREXMITBW "Enable SRTO_MAXREXMITBW (v1.6.0 API preview)" Off)
Expand All @@ -175,6 +176,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_LOCALIF_WIN32 "Enable local interface check ability 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 @@ -1061,6 +1063,10 @@ if (srt_libspec_shared)
if (ENABLE_ENCRYPTION)
target_link_libraries(${TARGET_srt}_shared PRIVATE ${SSL_LIBRARIES})
endif()
if (WIN32 AND ENABLE_LOCALIF_WIN32)
target_link_libraries(${TARGET_srt}_shared PRIVATE Iphlpapi)
add_definitions(-DSRT_ENABLE_LOCALIF_WIN32)
endif()
if (MICROSOFT)
target_link_libraries(${TARGET_srt}_shared PRIVATE ws2_32.lib)
if (NOT (ENABLE_ENCRYPTION AND "${USE_ENCLIB}" STREQUAL "botan"))
Expand All @@ -1082,6 +1088,10 @@ endif()

if (srt_libspec_static)
add_library(${TARGET_srt}_static STATIC ${OBJECT_LIB_SUPPORT} ${VIRTUAL_srt})
if (WIN32 AND ENABLE_LOCALIF_WIN32)
target_link_libraries(${TARGET_srt}_static PRIVATE Iphlpapi)
add_definitions(-DSRT_ENABLE_LOCALIF_WIN32)
endif()

# For Windows, leave the name to be "srt_static.lib".
# Windows generates two different library files:
Expand Down Expand Up @@ -1281,6 +1291,10 @@ macro(srt_add_program_dont_install name)
add_executable(${name} ${ARGN})
target_include_directories(${name} PRIVATE apps)
target_include_directories(${name} PRIVATE common)
if (WIN32 AND ENABLE_LOCALIF_WIN32)
target_link_libraries(${name} Iphlpapi)
add_definitions(-DSRT_ENABLE_LOCALIF_WIN32)
endif()
endmacro()

macro(srt_add_program name)
Expand Down Expand Up @@ -1472,6 +1486,10 @@ endif()
srt_add_example(testcapi-connect.c)
endif()

if (ENABLE_UNITTESTS_AUTO)
set (ENABLE_UNITTESTS ON)
endif()


if (ENABLE_UNITTESTS AND ENABLE_CXX11)

Expand Down Expand Up @@ -1527,7 +1545,9 @@ if (ENABLE_UNITTESTS AND ENABLE_CXX11)
#set_tests_properties(test-srt PROPERTIES RUN_SERIAL TRUE)
else()
set_tests_properties(${tests_srt} PROPERTIES RUN_SERIAL TRUE)
gtest_discover_tests(test-srt)
if (ENABLE_UNITTESTS_AUTO)
gtest_discover_tests(test-srt)
endif()
endif()

enable_testing()
Expand Down
38 changes: 38 additions & 0 deletions apps/apputil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <memory>

#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 @@ -389,3 +390,40 @@ void PrintLibVersion()
const int patch = srtver % 0x100;
cerr << "SRT Library version: " << major << "." << minor << "." << patch << ", clock type: " << SRTClockTypeStr() << endl;
}

bool IsTargetAddrSelf(const sockaddr* boundaddr, const sockaddr* targetaddr)
{
sockaddr_any bound = boundaddr;
sockaddr_any target = targetaddr;

if (!bound.isany())
{
// Bound to a specific local address, so only check if
// this isn't the same address as 'target'.
if (target.equal_address(bound))
{
return true;
}
}
else
{
// Bound to INADDR_ANY, so check matching with any local IP address
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.
// OTOH it should also mean that the network isn't working,
// so it's unlikely, as well as no address should match the
// local address anyway.
for (size_t i = 0; i < locals.size(); ++i)
{
if (locals[i].addr.equal_address(target))
{
return true;
}
}
}

return false;
}

1 change: 1 addition & 0 deletions apps/apputil.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,5 +335,6 @@ std::string OptionHelpItem(const OptionName& o);

const char* SRTClockTypeStr();
void PrintLibVersion();
bool IsTargetAddrSelf(const sockaddr* boundaddr, const sockaddr* targetaddr);

#endif // INC_SRT_APPCOMMON_H
51 changes: 51 additions & 0 deletions srtcore/api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2181,6 +2181,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 @@ -3783,6 +3816,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
85 changes: 85 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,82 @@ 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;
if (pUnicast->Address.lpSockaddr)
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;
if (pif->ifa_addr)
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
Loading
Loading