37 class InterfacesNotifierImp ;
40class GNet::InterfacesNotifierImp :
public InterfacesNotifier
43 InterfacesNotifierImp( Interfaces * , EventState es ) ;
46 ~InterfacesNotifierImp()
override ;
54 static void CALLBACK interface_callback_fn(
void * p , MIB_IPINTERFACE_ROW * , MIB_NOTIFICATION_TYPE ) ;
55 static void CALLBACK address_callback_fn(
void * p , MIB_UNICASTIPADDRESS_ROW * , MIB_NOTIFICATION_TYPE ) ;
58 static constexpr unsigned int MAGIC = 0xdeadbeef ;
59 unsigned int m_magic ;
63 FutureEvent m_future_event ;
71void GNet::Interfaces::loadImp( EventState es , std::vector<Item> & list )
73 if( !m_notifier.get() )
74 m_notifier = std::make_unique<InterfacesNotifierImp>(
this ,es ) ;
77 flags |= GAA_FLAG_SKIP_ANYCAST ;
78 flags |= GAA_FLAG_SKIP_MULTICAST ;
79 flags |= GAA_FLAG_SKIP_DNS_SERVER ;
84 buffer.resize( 15000U ) ;
85 ULONG size =
static_cast<ULONG
>( buffer.size() ) ;
86 IP_ADAPTER_ADDRESSES * p = G::buffer_cast<IP_ADAPTER_ADDRESSES*>( buffer ) ;
88 ULONG rc = GetAdaptersAddresses( AF_UNSPEC , flags ,
nullptr , p , &size ) ;
90 if( rc == ERROR_BUFFER_OVERFLOW )
92 buffer.resize( size ) ;
93 p = G::buffer_cast<IP_ADAPTER_ADDRESSES*>( buffer ) ;
94 rc = GetAdaptersAddresses( AF_UNSPEC , flags ,
nullptr , p , &size ) ;
97 if( rc != ERROR_NO_DATA )
99 if( rc != ERROR_SUCCESS )
102 for( ; p ; p = p->Next )
105 item.name = std::string( p->AdapterName ) ;
107 item.up = p->OperStatus == IfOperStatusUp ;
108 item.loopback = p->IfType == IF_TYPE_SOFTWARE_LOOPBACK ;
110 for( IP_ADAPTER_UNICAST_ADDRESS * ap = p->FirstUnicastAddress ; ap ; ap = ap->Next )
112 item.address_family = ap->Address.lpSockaddr->sa_family ;
115 item.address = Address( ap->Address.lpSockaddr , ap->Address.iSockaddrLength ) ;
116 item.valid_address = !item.address.isAny() ;
119 UINT8 prefix_length = ap->OnLinkPrefixLength ;
120 if( prefix_length <= 128U )
122 item.has_netmask = true ;
123 item.netmask_bits = prefix_length ;
126 item.ifindex = p->IfIndex ? p->IfIndex : p->Ipv6IfIndex ;
127 list.push_back( item ) ;
135GNet::InterfacesNotifierImp::InterfacesNotifierImp( Interfaces * outer , EventState es ) :
140 m_future_event(*outer,es)
142 m_handle = m_future_event.handle() ;
144 NotifyIpInterfaceChange( AF_UNSPEC , &InterfacesNotifierImp::interface_callback_fn ,
145 this , FALSE , &m_notify_1 ) ;
147 NotifyUnicastIpAddressChange( AF_UNSPEC , &InterfacesNotifierImp::address_callback_fn ,
148 this , FALSE , &m_notify_2 ) ;
151GNet::InterfacesNotifierImp::~InterfacesNotifierImp()
154 if( m_notify_1 ) CancelMibChangeNotify2( m_notify_1 ) ;
155 if( m_notify_2 ) CancelMibChangeNotify2( m_notify_2 ) ;
158void GNet::InterfacesNotifierImp::interface_callback_fn(
void * this_vp , MIB_IPINTERFACE_ROW * ,
159 MIB_NOTIFICATION_TYPE )
162 InterfacesNotifierImp * this_ =
static_cast<InterfacesNotifierImp*
>(this_vp) ;
163 if( this_->m_magic == InterfacesNotifierImp::MAGIC && this_->m_handle )
169void GNet::InterfacesNotifierImp::address_callback_fn(
void * this_vp , MIB_UNICASTIPADDRESS_ROW * ,
170 MIB_NOTIFICATION_TYPE )
173 InterfacesNotifierImp * this_ =
static_cast<InterfacesNotifierImp*
>(this_vp) ;
174 if( this_->m_magic == InterfacesNotifierImp::MAGIC && this_->m_handle )
176 FutureEvent::send( this_->m_handle ,
false ) ;
183 return std::string() ;
188 return "network-change" ;
static bool supports(Family) noexcept
Returns true if the implementation supports the given address family.
virtual std::string readEvent()=0
Called by GNet::Interfaces to handle a read event.
virtual std::string onFutureEvent()=0
Called by GNet::Interfaces to handle a future event.
static bool active()
Returns true if the implementation can raise InterfacesHandler events.
static std::string narrow(const std::wstring &)
Narrows from UTF-16/UCS-4 wstring to UTF-8.
A general-purpose exception class derived from std::exception and containing an error message.
A substitute for std::vector<char> that has more useful alignment guarantees and explicitly avoids de...