Skip to content

Commit

Permalink
fixup! rename to (dds_)network_adapter_watcher
Browse files Browse the repository at this point in the history
  • Loading branch information
maloel committed Sep 11, 2024
1 parent 3c03fc0 commit e535953
Showing 1 changed file with 84 additions and 74 deletions.
158 changes: 84 additions & 74 deletions third-party/rsutils/src/network-adapter-watcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <linux/rtnetlink.h>
#include <sys/eventfd.h>
#include <unistd.h>
#include <errno.h>
#include <poll.h>

#endif
Expand All @@ -39,8 +40,8 @@ class network_adapter_watcher_singleton
#ifdef _WIN32
HANDLE _done;
#else
int _socket;
int _done;
int _socket;
#endif
std::thread _th;

Expand Down Expand Up @@ -98,80 +99,89 @@ class network_adapter_watcher_singleton
// https://stackoverflow.com/questions/27008067/how-to-get-notified-about-network-interface-changes-with-netlist-and-rtmgrp-link
: _socket( open_netlink() )
, _done( eventfd( 0, 0 ) )
, _th(
[this]
{
// We're going to wait on the following handles:
LOG_DEBUG( "starting network adapter watcher" );

int const timeout = -1; // negative value = infinite
int const nfds = 2;
pollfd fds[nfds];
memset( fds, 0, sizeof( fds ) );
fds[0].fd = _done;
fds[0].events = POLLIN;
fds[1].fd = _socket;
fds[1].events = POLLIN;

while( true )
{
fds[0].revents = 0;
fds[1].revents = 0;
auto rv = poll( fds, nfds, timeout );
if( rv <= 0 )
{
LOG_ERROR( "poll failed: " << rv );
break;
}

if( fds[0].revents != 0 )
break; // we're done

LOG_DEBUG( "network adapter changes detected!" );

char buf[4096];
struct sockaddr_nl snl;
iovec iov = { buf, sizeof( buf ) };
msghdr msg = { (void *)&snl, sizeof snl, &iov, 1, NULL, 0, 0 };
int status = recvmsg( _socket, &msg, 0 );
if( status < 0 )
{
// Socket non-blocking so bail out once we have read everything
if( errno == EWOULDBLOCK || errno == EAGAIN )
continue;

// Anything else is an error
LOG_DEBUG( "read_netlink: Error recvmsg: " << status );
break;
}
if( status == 0 )
LOG_DEBUG( "read_netlink: EOF" );

// We need to handle more than one message per recvmsg
for( auto h = (struct nlmsghdr *)buf; NLMSG_OK( h, (unsigned int)status );
h = NLMSG_NEXT( h, status ) )
{
// Finish reading
if( h->nlmsg_type == NLMSG_DONE )
continue;

// Message is some kind of error
if( h->nlmsg_type == NLMSG_ERROR )
{
LOG_DEBUG( "read_netlink: got NLMSG_ERROR" );
continue;
}
}

// Call our clients once for all the messages... outside the loop
callbacks.raise();
}

LOG_DEBUG( "exiting network adapter watcher" );
} )
#endif
{
LOG_DEBUG( "network adapter watcher singleton is up" );
#ifndef _WIN32
if( _socket < 0 )
{
auto const error = errno;
LOG_ERROR( "Failed to start network adapter watcher (errno= " << error << ")" );
}
else
{
_th = std::thread(
[this]
{
// We're going to wait on the following handles:
LOG_DEBUG( "starting network adapter watcher" );

int const timeout = -1; // negative value = infinite
int const nfds = 2;
pollfd fds[nfds];
memset( fds, 0, sizeof( fds ) );
fds[0].fd = _done;
fds[0].events = POLLIN;
fds[1].fd = _socket;
fds[1].events = POLLIN;

while( true )
{
fds[0].revents = 0;
fds[1].revents = 0;
auto rv = poll( fds, nfds, timeout );
if( rv <= 0 )
{
LOG_ERROR( "poll failed: " << rv );
break;
}

if( fds[0].revents != 0 )
break; // we're done

LOG_DEBUG( "network adapter changes detected!" );

char buf[4096];
struct sockaddr_nl snl;
iovec iov = { buf, sizeof( buf ) };
msghdr msg = { (void *)&snl, sizeof snl, &iov, 1, NULL, 0, 0 };
int status = recvmsg( _socket, &msg, 0 );
if( status < 0 )
{
// Socket non-blocking so bail out once we have read everything
if( errno == EWOULDBLOCK || errno == EAGAIN )
continue;

// Anything else is an error
LOG_DEBUG( "read_netlink: Error recvmsg: " << status );
break;
}
if( status == 0 )
LOG_DEBUG( "read_netlink: EOF" );

// We need to handle more than one message per recvmsg
for( auto h = (struct nlmsghdr *)buf; NLMSG_OK( h, (unsigned int)status );
h = NLMSG_NEXT( h, status ) )
{
// Finish reading
if( h->nlmsg_type == NLMSG_DONE )
continue;

// Message is some kind of error
if( h->nlmsg_type == NLMSG_ERROR )
{
LOG_DEBUG( "read_netlink: got NLMSG_ERROR" );
continue;
}
}

// Call our clients once for all the messages... outside the loop
callbacks.raise();
}

LOG_DEBUG( "exiting network adapter watcher" );
} );
}
#endif
}

~network_adapter_watcher_singleton()
Expand Down Expand Up @@ -204,7 +214,7 @@ class network_adapter_watcher_singleton
// https://manpages.ubuntu.com/manpages/oracular/en/man7/netlink.7.html
int sock = socket( AF_NETLINK, SOCK_RAW, NETLINK_ROUTE );
if( sock < 0 )
return sock;
return -1;

struct sockaddr_nl addr;
memset( (void *)&addr, 0, sizeof( addr ) );
Expand Down

0 comments on commit e535953

Please sign in to comment.