Stroika Library 3.0d25
 
Loading...
Searching...
No Matches
LinkMonitor.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#ifndef _Stroika_Foundation_IO_Network_LinkMonitor_h_
5#define _Stroika_Foundation_IO_Network_LinkMonitor_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#if qStroika_Platform_POSIX
10#include <arpa/inet.h>
11#elif qStroika_Platform_Windows
12#include <WinSock2.h>
13
14#include <in6addr.h>
15#include <inaddr.h>
16#endif
17
19#include "Stroika/Foundation/Common/Common.h"
24
25/**
26 * \file
27 *
28 * \note Code-Status: <a href="Code-Status.md#Alpha">Alpha</a>
29 *
30 * TODO:
31 * @todo Should this API be renamed InterfaceMonitor? Probably yes?
32 *
33 * @todo LinkMonitor rnetlink support DELETE
34 */
35
37
38 using Characters::String;
39
40 /**
41 * Create an instance of this class, and add callbacks to it, and they will be notified
42 * when a network connection comes up or down.
43 *
44 * All LinkMonitors share one watcher of the OS's address changes - on Linux and macOS a thread, on Windows an OS
45 * registration (NotifyUnicastIpAddressChange) - started by the first to add a callback, and stopped when the last of those
46 * goes. So several cost about what one does.
47 *
48 * \note A change from when AddCallback () returns is reported. Where the OS cannot tell (e.g. some containers),
49 * AddCallback () throws.
50 *
51 * \note Callbacks run on that thread (on Windows, the OS's), not the caller's - so a slow one delays the others' - and
52 * one LinkMonitor's one at a time. An exception from one is logged and ignored.
53 *
54 * \note Once RemoveCallback () returns, or the LinkMonitor is destroyed, that callback is not running and is not called
55 * again (except that, done from within the callback itself, the call already running finishes). A callback may
56 * add or remove callbacks, and create or destroy LinkMonitors - but not destroy the last one: that would have to
57 * stop the thread calling it.
58 *
59 * \note AddCallback () and RemoveCallback () may be called from any thread, at once - and AddCallback () never waits for a
60 * running callback (@see Execution::CallbackRegistry).
61 *
62 * @todo POSIX code is not really posix but assumes linux==posix =- relaly need separate define to check for netlink
63 * and a windoze impl.
64 *
65 * @todo Decide if this should always auto-call the callback when first loaded? Might be an easier to use
66 * API (with added - for any existing interfaces)? Windoze makes that easy, but not sure about rnetlink?
67 */
68 struct LinkMonitor {
69 LinkMonitor ();
70 LinkMonitor (LinkMonitor&& rhs) noexcept = default;
71 LinkMonitor (const LinkMonitor&) = delete;
72
73 LinkMonitor& operator= (LinkMonitor&& rhs) noexcept = default;
74 LinkMonitor& operator= (const LinkMonitor&) = delete;
75
76 /**
77 * \note Common::DefaultNames<> supported
78 */
79 enum class LinkChange {
80 eAdded,
81 eRemoved,
82
83 Stroika_Define_Enum_Bounds (eAdded, eRemoved)
84 };
85
86 /**
87 * \brief What a callback is told: an address added to (or removed from) an interface.
88 *
89 * \note IPv4 and IPv6 addresses. Only an address's becoming usable, and ceasing to be, is reported - not a change that
90 * leaves it as it was (its lifetime renewed, say). So an address still checking it is no duplicate is reported
91 * once that is done (Linux, Windows), and on Windows - which keeps the address of a network that goes (Wi-Fi off,
92 * within its DHCP lease), marking it deprecated - the network's going and coming back is reported as the
93 * address's removal and addition.
94 */
95 struct Event {
96 /**
97 * Whether fAddress was added to the interface, or removed from it.
98 */
100
101 /**
102 * The interface's Interface::fInterfaceID - so SystemInterfacesMgr::GetById () finds the rest of it, if it is still
103 * there. Empty where the OS no longer knows the interface (an address removed along with it, say).
104 */
106
107 /**
108 * The address added (or removed) - always given: each Event is about one address. Linux: the netlink message's
109 * IFA_LOCAL (else IFA_ADDRESS, as for IPv6); macOS: the routing message's RTAX_IFA; Windows: MIB_UNICASTIPADDRESS_ROW::Address.
110 */
112
113 /**
114 * @see Characters::ToString ();
115 */
116 nonvirtual String ToString () const;
117 };
118
119 using Callback = function<void (const Event&)>;
120
121 /**
122 * \brief Names a callback AddCallback added, for RemoveCallback.
123 */
124 using CallbackID = Execution::CallbackRegistry<void (const Event&)>::ID;
125
126 /**
127 * \brief Call callback with each change from when this returns (@see LinkMonitor) - until RemoveCallback, with the ID this
128 * returns, or until the LinkMonitor goes.
129 */
130 nonvirtual CallbackID AddCallback (const Callback& callback);
131
132 /**
133 * \brief Once this returns, that callback is not running, and is not called again (@see LinkMonitor).
134 */
135 nonvirtual void RemoveCallback (CallbackID callback);
136
137 private:
138 struct Rep_;
139 shared_ptr<Rep_> fRep_;
140 };
141
142}
143
144/*
145 ********************************************************************************
146 ***************************** Implementation Details ***************************
147 ********************************************************************************
148 */
149#include "LinkMonitor.inl"
150
151#endif /*_Stroika_Foundation_IO_Network_LinkMonitor_h_*/
#define Stroika_Define_Enum_Bounds(FIRST_ITEM, LAST_ITEM)
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
The callbacks an object calls when something happens - each added, and removed by the ID Add gave it ...