Skip to content

Commit

Permalink
add realdds::dds_adapter_watcher
Browse files Browse the repository at this point in the history
  • Loading branch information
maloel committed Sep 3, 2024
1 parent 29043a3 commit 0ce7468
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 0 deletions.
34 changes: 34 additions & 0 deletions third-party/rsutils/include/rsutils/os/adapter-watcher.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2024 Intel Corporation. All Rights Reserved.
#pragma once

#include <rsutils/subscription.h>


namespace rsutils {
namespace os {
namespace detail {
class adapter_watcher_singleton;
}


// Watch for OS changes to network adapters
//
// We don't get any parameters; just that something changed.
//
// To use, just create a watcher and keep a pointer to it to get notifications. Single callback per instance.
//
class adapter_watcher
{
std::shared_ptr< detail::adapter_watcher_singleton > _singleton;
subscription _subscription;

public:
using callback = std::function< void() >;

adapter_watcher( callback && );
};


} // namespace os
} // namespace rsutils
119 changes: 119 additions & 0 deletions third-party/rsutils/src/adapter-watcher.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2024 Intel Corporation. All Rights Reserved.

//#define _WINSOCKAPI_ // stops windows.h including winsock.h

#include <rsutils/os/adapter-watcher.h>
#include <rsutils/shared-ptr-singleton.h>
#include <rsutils/signal.h>
#include <rsutils/easylogging/easyloggingpp.h>

#ifdef WIN32

#include <windows.h>
//#include <winsock2.h>
#include <iphlpapi.h>
#pragma comment( lib, "iphlpapi.lib" )

#else
#endif


namespace rsutils {
namespace os {
namespace detail {


class adapter_watcher_singleton
{
using public_signal = rsutils::public_signal< adapter_watcher_singleton >;

#ifdef WIN32
HANDLE _done;
std::thread _th;
#else
#endif

public:
public_signal callbacks;

adapter_watcher_singleton()
#ifdef WIN32
: _done( CreateEvent(
nullptr /*security attrs*/, TRUE /*manual reset*/, FALSE /*init unset*/, nullptr /*no name*/ ) )
, _th(
[this]()
{
// We're going to wait on the following handles:
HANDLE handles[2];
DWORD const n_handles = sizeof( handles ) / sizeof( handles[0] );
handles[0] = _done;
// https://learn.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-notifyaddrchange
OVERLAPPED overlap = {0};
//overlap.hEvent = WSACreateEvent();
overlap.hEvent = CreateEvent( nullptr /*security attrs*/,
FALSE /*auto reset*/,
FALSE /*init unset*/,
nullptr /*no name*/ );
handles[1] = overlap.hEvent;

LOG_DEBUG( "starting network adapter watcher" );

while( true )
{
HANDLE h_file = NULL;
NotifyAddrChange( &h_file, &overlap );
// If multiple objects become signaled, the function returns the index of the first handle in the
// array whose object was signaled:
if( WAIT_OBJECT_0
== WaitForMultipleObjects( n_handles, handles, FALSE /*wait-for-all*/, INFINITE ) )
break; // we're done
LOG_DEBUG( "network adapter changes detected!" );
//WSAResetEvent( handles[1] );
callbacks.raise();
}

LOG_DEBUG( "exiting network adapter watcher" );

CancelIPChangeNotify( &overlap );
} )
#else
// https://manpages.ubuntu.com/manpages/oracular/en/man7/netlink.7.html
// https://stackoverflow.com/questions/27008067/how-to-get-notified-about-network-interface-changes-with-netlist-and-rtmgrp-link
On Linux, it is done opening and reading on a special kind of socket.Documentation here.Some nice examples here.
#endif
{
LOG_DEBUG( "network adapter watcher singleton is up" );
}

~adapter_watcher_singleton()
{
#ifdef WIN32
if( _th.joinable() )
{
SetEvent( _done );
_th.join();
}
CloseHandle( _done );
#else
#endif
}
};

static rsutils::shared_ptr_singleton< detail::adapter_watcher_singleton > the_adapter_watcher;


} // namespace detail


adapter_watcher::adapter_watcher( callback && cb )
: _singleton( detail::the_adapter_watcher.instance() ) // keep it alive
, _subscription( _singleton->callbacks.subscribe( std::move( cb ) ) )
{
// As long as someone keeps a pointer to an adapter_watcher, the singleton will be kept alive and it will watch for
// changes; as soon as all instances disappear, the singleton will disappear and the watch should stop.
}


} // namespace os
} // namespace rsutils

0 comments on commit 0ce7468

Please sign in to comment.