From a9abcc37cdc361a6cd3b35e8791e9603d793c424 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 2 Apr 2013 04:59:44 +0200 Subject: [PATCH] Rework initial auto joining and add big TODOs. * If we have a configured network, then we always try to connect to it as soon as the interface has been brought up. * If we don't have a configured network and are auto configuring, we use the AutoconfigLooper to also do initial auto joins. * Before issuing auto joins we need to wait for scan results to come in, so we watch for corresponding messages. For now auto joining is a one shot attempt as the infrastructure to properly tell reasons for scans apart is not yet there. --- headers/private/net/NetServer.h | 1 + src/servers/net/AutoconfigLooper.cpp | 83 +++++++++++++++++++++++----- src/servers/net/AutoconfigLooper.h | 2 + src/servers/net/NetServer.cpp | 50 ++++++++--------- 4 files changed, 96 insertions(+), 40 deletions(-) diff --git a/headers/private/net/NetServer.h b/headers/private/net/NetServer.h index 9b66ad9a0f..d0d1bf13ef 100644 --- a/headers/private/net/NetServer.h +++ b/headers/private/net/NetServer.h @@ -19,6 +19,7 @@ #define kMsgRemovePersistentNetwork 'RPnw' #define kMsgJoinNetwork 'JNnw' #define kMsgLeaveNetwork 'LVnw' +#define kMsgAutoJoinNetwork 'AJnw' #endif // _NET_SERVER_H diff --git a/src/servers/net/AutoconfigLooper.cpp b/src/servers/net/AutoconfigLooper.cpp index 5fc84a5fe7..bd11a2f589 100644 --- a/src/servers/net/AutoconfigLooper.cpp +++ b/src/servers/net/AutoconfigLooper.cpp @@ -33,7 +33,8 @@ AutoconfigLooper::AutoconfigLooper(BMessenger target, const char* device) fTarget(target), fDevice(device), fCurrentClient(NULL), - fLastMediaStatus(0) + fLastMediaStatus(0), + fJoiningNetwork(false) { BMessage ready(kMsgReadyToRun); PostMessage(&ready); @@ -124,7 +125,8 @@ AutoconfigLooper::_ConfigureIPv4() void AutoconfigLooper::_ReadyToRun() { - start_watching_network(B_WATCH_NETWORK_LINK_CHANGES, this); + start_watching_network( + B_WATCH_NETWORK_LINK_CHANGES | B_WATCH_NETWORK_WLAN_CHANGES, this); BNetworkInterface interface(fDevice.String()); if (interface.HasLink()) { @@ -139,22 +141,35 @@ AutoconfigLooper::_ReadyToRun() void -AutoconfigLooper::MessageReceived(BMessage* message) +AutoconfigLooper::_NetworkMonitorNotification(BMessage* message) { - switch (message->what) { - case kMsgReadyToRun: - _ReadyToRun(); - break; + int32 opcode; + BString device; + if (message->FindString("device", &device) != B_OK) { + if (message->FindString("interface", &device) != B_OK) + return; - case B_NETWORK_MONITOR: - const char* device; - int32 opcode; + // TODO: Clean this mess up. Wireless devices currently use their + // "device_name" in the interface field. First of all the + // joins/leaves/scans should be device, not interface specific, so + // the field should be changed. Then the device_name as seen by the + // driver is missing the "/dev" part, as it is a relative path within + // "/dev". On the other hand the net stack uses names that include + // "/dev" as it uses them to open the fds, hence a full absolute path. + // Note that the wpa_supplicant does the same workaround as we do here + // to build an interface name, so that has to be changed as well when + // this is fixed. + device.Prepend("/dev/"); + } + + if (device != fDevice || message->FindInt32("opcode", &opcode) != B_OK) + return; + + switch (opcode) { + case B_NETWORK_DEVICE_LINK_CHANGED: + { int32 media; - if (message->FindInt32("opcode", &opcode) != B_OK - || opcode != B_NETWORK_DEVICE_LINK_CHANGED - || message->FindString("device", &device) != B_OK - || fDevice != device - || message->FindInt32("media", &media) != B_OK) + if (message->FindInt32("media", &media) != B_OK) break; if ((fLastMediaStatus & IFM_ACTIVE) == 0 @@ -163,8 +178,46 @@ AutoconfigLooper::MessageReceived(BMessage* message) _ConfigureIPv4(); //_ConfigureIPv6(); // TODO: router advertisement and dhcpv6 } + fLastMediaStatus = media; break; + } + + case B_NETWORK_WLAN_SCANNED: + { + if (fJoiningNetwork || (fLastMediaStatus & IFM_ACTIVE) != 0) { + // We already have a link or are already joining. + break; + } + + fJoiningNetwork = true; + // TODO: For now we never reset this flag. We can only do that + // after infrastructure has been added to discern a scan reason. + // If we would always auto join we would possibly interfere + // with active scans in the process of connecting to an AP + // either for the initial connection, or after connection loss + // to re-establish the link. + + BMessage message(kMsgAutoJoinNetwork); + message.AddString("device", fDevice); + fTarget.SendMessage(&message); + break; + } + } +} + + +void +AutoconfigLooper::MessageReceived(BMessage* message) +{ + switch (message->what) { + case kMsgReadyToRun: + _ReadyToRun(); + break; + + case B_NETWORK_MONITOR: + _NetworkMonitorNotification(message); + break; default: BLooper::MessageReceived(message); diff --git a/src/servers/net/AutoconfigLooper.h b/src/servers/net/AutoconfigLooper.h index fef9c2f95c..4ec5a5427f 100644 --- a/src/servers/net/AutoconfigLooper.h +++ b/src/servers/net/AutoconfigLooper.h @@ -30,11 +30,13 @@ private: void _RemoveClient(); void _ConfigureIPv4(); void _ReadyToRun(); + void _NetworkMonitorNotification(BMessage* message); BMessenger fTarget; BString fDevice; AutoconfigClient* fCurrentClient; int32 fLastMediaStatus; + bool fJoiningNetwork; }; #endif // AUTOCONFIG_LOOPER_H diff --git a/src/servers/net/NetServer.cpp b/src/servers/net/NetServer.cpp index e24e70dada..bf1f06f121 100644 --- a/src/servers/net/NetServer.cpp +++ b/src/servers/net/NetServer.cpp @@ -88,7 +88,7 @@ private: void _StartServices(); status_t _HandleDeviceMonitor(BMessage* message); - status_t _AutoJoinNetwork(const char* name); + status_t _AutoJoinNetwork(const BMessage& message); status_t _JoinNetwork(const BMessage& message, const char* name = NULL); status_t _LeaveNetwork(const BMessage& message); @@ -321,6 +321,12 @@ NetServer::MessageReceived(BMessage* message) break; } + case kMsgAutoJoinNetwork: + { + _AutoJoinNetwork(*message); + break; + } + case kMsgCountPersistentNetworks: { BMessage reply(B_REPLY); @@ -532,26 +538,6 @@ NetServer::_ConfigureInterface(BMessage& message) } } - BNetworkDevice device(name); - if (device.IsWireless() && !device.HasLink()) { - const char* networkName; - if (message.FindString("network", &networkName) == B_OK) { - // join configured network - status_t status = _JoinNetwork(message, networkName); - if (status != B_OK) { - fprintf(stderr, "%s: joining network \"%s\" failed: %s\n", - interface.Name(), networkName, strerror(status)); - } - } else { - // auto select network to join - status_t status = _AutoJoinNetwork(name); - if (status != B_OK) { - fprintf(stderr, "%s: auto joining network failed: %s\n", - interface.Name(), strerror(status)); - } - } - } - // Set up IPv6 Link Local address (based on MAC, if not loopback) _ConfigureIPv6LinkLocal(name); @@ -671,6 +657,19 @@ NetServer::_ConfigureInterface(BMessage& message) } } + const char* networkName; + if (message.FindString("network", &networkName) == B_OK) { + // We want to join a specific network. + BNetworkDevice device(name); + if (device.IsWireless() && !device.HasLink()) { + status_t status = _JoinNetwork(message, networkName); + if (status != B_OK) { + fprintf(stderr, "%s: joining network \"%s\" failed: %s\n", + interface.Name(), networkName, strerror(status)); + } + } + } + if (startAutoConfig) { // start auto configuration AutoconfigLooper* looper = new AutoconfigLooper(this, name); @@ -987,12 +986,13 @@ NetServer::_HandleDeviceMonitor(BMessage* message) status_t -NetServer::_AutoJoinNetwork(const char* name) +NetServer::_AutoJoinNetwork(const BMessage& message) { - BNetworkDevice device(name); + const char* name = NULL; + if (message.FindString("device", &name) != B_OK) + return B_BAD_VALUE; - BMessage message; - message.AddString("device", name); + BNetworkDevice device(name); // Choose among configured networks