1 /* 2 * Copyright 2015, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 //! The backbone of the NetworkAvailable event, and condition. 8 9 10 #include "NetworkWatcher.h" 11 12 #include <Application.h> 13 #include <Autolock.h> 14 #include <NetworkDevice.h> 15 #include <NetworkInterface.h> 16 #include <NetworkRoster.h> 17 18 #include "Utility.h" 19 20 21 static const bigtime_t kNetworkUpdateInterval = 1000000; 22 // Update network availability every second 23 24 static BLocker sLocker("network watcher"); 25 static NetworkWatcher* sWatcher; 26 27 static bool sLastNetworkAvailable; 28 static bigtime_t sLastNetworkUpdate; 29 30 31 NetworkListener::~NetworkListener() 32 { 33 } 34 35 36 // #pragma mark - 37 38 39 NetworkWatcher::NetworkWatcher() 40 : 41 BHandler("network watcher"), 42 fAvailable(false) 43 { 44 if (be_app->Lock()) { 45 be_app->AddHandler(this); 46 47 start_watching_network(B_WATCH_NETWORK_INTERFACE_CHANGES 48 | B_WATCH_NETWORK_LINK_CHANGES, this); 49 be_app->Unlock(); 50 } 51 } 52 53 54 NetworkWatcher::~NetworkWatcher() 55 { 56 if (be_app->Lock()) { 57 stop_watching_network(this); 58 59 be_app->RemoveHandler(this); 60 be_app->Unlock(); 61 } 62 } 63 64 65 void 66 NetworkWatcher::AddListener(NetworkListener* listener) 67 { 68 BAutolock lock(sLocker); 69 fListeners.AddItem(listener); 70 71 if (fListeners.CountItems() == 1) 72 UpdateAvailability(); 73 } 74 75 76 void 77 NetworkWatcher::RemoveListener(NetworkListener* listener) 78 { 79 BAutolock lock(sLocker); 80 fListeners.RemoveItem(listener); 81 } 82 83 84 int32 85 NetworkWatcher::CountListeners() const 86 { 87 BAutolock lock(sLocker); 88 return fListeners.CountItems(); 89 } 90 91 92 void 93 NetworkWatcher::MessageReceived(BMessage* message) 94 { 95 switch (message->what) { 96 case B_NETWORK_MONITOR: 97 UpdateAvailability(); 98 break; 99 } 100 } 101 102 103 /*static*/ void 104 NetworkWatcher::Register(NetworkListener* listener) 105 { 106 BAutolock lock(sLocker); 107 if (sWatcher == NULL) 108 sWatcher = new NetworkWatcher(); 109 110 sWatcher->AddListener(listener); 111 } 112 113 114 /*static*/ void 115 NetworkWatcher::Unregister(NetworkListener* listener) 116 { 117 BAutolock lock(sLocker); 118 sWatcher->RemoveListener(listener); 119 120 if (sWatcher->CountListeners() == 0) 121 delete sWatcher; 122 } 123 124 125 /*static*/ bool 126 NetworkWatcher::NetworkAvailable(bool immediate) 127 { 128 if (!immediate 129 && system_time() - sLastNetworkUpdate < kNetworkUpdateInterval) { 130 return sLastNetworkAvailable; 131 } 132 133 bool isAvailable = false; 134 135 BNetworkRoster& roster = BNetworkRoster::Default(); 136 BNetworkInterface interface; 137 uint32 cookie = 0; 138 while (roster.GetNextInterface(&cookie, interface) == B_OK) { 139 uint32 flags = interface.Flags(); 140 if ((flags & (IFF_LOOPBACK | IFF_CONFIGURING | IFF_UP | IFF_LINK)) 141 == (IFF_UP | IFF_LINK)) { 142 isAvailable = true; 143 break; 144 } 145 } 146 147 sLastNetworkAvailable = isAvailable; 148 sLastNetworkUpdate = system_time(); 149 return isAvailable; 150 } 151 152 153 void 154 NetworkWatcher::UpdateAvailability() 155 { 156 bool isAvailable = NetworkAvailable(true); 157 if (isAvailable != fAvailable) { 158 fAvailable = isAvailable; 159 160 BAutolock lock(sLocker); 161 for (int32 i = 0; i < fListeners.CountItems(); i++) { 162 fListeners.ItemAt(i)->NetworkAvailabilityChanged(fAvailable); 163 } 164 } 165 } 166