37 class InterfacesNotifierImp ;
40class GNet::InterfacesNotifierImp :
public InterfacesNotifier
43 InterfacesNotifierImp( Interfaces * , ExceptionSink 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( ExceptionSink 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 ) ;
108 item.altname = altname.s ;
109 item.up = p->OperStatus == IfOperStatusUp ;
110 item.loopback = p->IfType == IF_TYPE_SOFTWARE_LOOPBACK ;
112 for( IP_ADAPTER_UNICAST_ADDRESS * ap = p->FirstUnicastAddress ; ap ; ap = ap->Next )
114 item.address_family = ap->Address.lpSockaddr->sa_family ;
117 item.address = Address( ap->Address.lpSockaddr , ap->Address.iSockaddrLength ) ;
118 item.valid_address = !item.address.isAny() ;
121 UINT8 prefix_length = ap->OnLinkPrefixLength ;
122 if( prefix_length <= 128U )
124 item.has_netmask = true ;
125 item.netmask_bits = prefix_length ;
128 item.ifindex = p->IfIndex ? p->IfIndex : p->Ipv6IfIndex ;
129 list.push_back( item ) ;
137GNet::InterfacesNotifierImp::InterfacesNotifierImp( Interfaces * outer , ExceptionSink es ) :
142 m_future_event(*outer,es)
144 m_handle = m_future_event.handle() ;
146 NotifyIpInterfaceChange( AF_UNSPEC , &InterfacesNotifierImp::interface_callback_fn ,
147 this , FALSE , &m_notify_1 ) ;
149 NotifyUnicastIpAddressChange( AF_UNSPEC , &InterfacesNotifierImp::address_callback_fn ,
150 this , FALSE , &m_notify_2 ) ;
153GNet::InterfacesNotifierImp::~InterfacesNotifierImp()
156 if( m_notify_1 ) CancelMibChangeNotify2( m_notify_1 ) ;
157 if( m_notify_2 ) CancelMibChangeNotify2( m_notify_2 ) ;
160void GNet::InterfacesNotifierImp::interface_callback_fn(
void * this_vp , MIB_IPINTERFACE_ROW * ,
161 MIB_NOTIFICATION_TYPE )
164 InterfacesNotifierImp * this_ =
static_cast<InterfacesNotifierImp*
>(this_vp) ;
165 if( this_->m_magic == InterfacesNotifierImp::MAGIC && this_->m_handle )
171void GNet::InterfacesNotifierImp::address_callback_fn(
void * this_vp , MIB_UNICASTIPADDRESS_ROW * ,
172 MIB_NOTIFICATION_TYPE )
175 InterfacesNotifierImp * this_ =
static_cast<InterfacesNotifierImp*
>(this_vp) ;
176 if( this_->m_magic == InterfacesNotifierImp::MAGIC && this_->m_handle )
178 FutureEvent::send( this_->m_handle ,
false ) ;
185 return std::string() ;
190 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 void convert(utf8 &utf_out, const std::string &in_)
Converts between string types/encodings: native to utf8.
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...
A string wrapper that indicates UTF-8 encoding.