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.
This commit is contained in:
Michael Lotz 2013-04-02 04:59:44 +02:00
parent e484cc5098
commit a9abcc37cd
4 changed files with 96 additions and 40 deletions

View File

@ -19,6 +19,7 @@
#define kMsgRemovePersistentNetwork 'RPnw'
#define kMsgJoinNetwork 'JNnw'
#define kMsgLeaveNetwork 'LVnw'
#define kMsgAutoJoinNetwork 'AJnw'
#endif // _NET_SERVER_H

View File

@ -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);

View File

@ -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

View File

@ -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