diff --git a/headers/os/net/NetworkDevice.h b/headers/os/net/NetworkDevice.h index c310718878..9c83dc17b9 100644 --- a/headers/os/net/NetworkDevice.h +++ b/headers/os/net/NetworkDevice.h @@ -114,6 +114,8 @@ public: status_t GetNextNetwork(uint32& cookie, wireless_network& network); + status_t GetNetworks(wireless_network*& networks, + uint32& count); status_t GetNetwork(const char* name, wireless_network& network); status_t GetNetwork(const BNetworkAddress& address, diff --git a/src/apps/networkstatus/NetworkStatusView.cpp b/src/apps/networkstatus/NetworkStatusView.cpp index b39ff178f8..0fa95ca9c9 100644 --- a/src/apps/networkstatus/NetworkStatusView.cpp +++ b/src/apps/networkstatus/NetworkStatusView.cpp @@ -401,14 +401,15 @@ NetworkStatusView::MouseDown(BPoint point) if (!wifiInterface.IsEmpty()) { std::set associated; BNetworkAddress address; - wireless_network network; uint32 cookie = 0; while (device.GetNextAssociatedNetwork(cookie, address) == B_OK) associated.insert(address); - int32 wifiCount = 0; - cookie = 0; - while (device.GetNextNetwork(cookie, network) == B_OK) { + uint32 networksCount = 0; + wireless_network* networks = NULL; + device.GetNetworks(networks, networksCount); + for (uint32 i = 0; i < networksCount; i++) { + const wireless_network& network = networks[i]; BMessage* message = new BMessage(kMsgJoinNetwork); message->AddString("device", wifiInterface); message->AddString("name", network.name); @@ -416,12 +417,12 @@ NetworkStatusView::MouseDown(BPoint point) BMenuItem* item = new WirelessNetworkMenuItem(network, message); menu->AddItem(item); - wifiCount++; if (associated.find(network.address) != associated.end()) item->SetMarked(true); } + delete[] networks; - if (wifiCount == 0) { + if (networksCount == 0) { BMenuItem* item = new BMenuItem( B_TRANSLATE(""), NULL); item->SetEnabled(false); diff --git a/src/kits/network/libnetapi/NetworkDevice.cpp b/src/kits/network/libnetapi/NetworkDevice.cpp index c6ddac7c86..4ec6dc65a6 100644 --- a/src/kits/network/libnetapi/NetworkDevice.cpp +++ b/src/kits/network/libnetapi/NetworkDevice.cpp @@ -423,6 +423,59 @@ fill_wireless_network(wireless_network& network, const char* networkName, } +static status_t +get_scan_results(const char* device, wireless_network*& networks, uint32& count) +{ + if (networks != NULL) + return B_BAD_VALUE; + + // TODO: Find some way to reduce code duplication with the following function! + const size_t kBufferSize = 64 * 1024; + uint8* buffer = (uint8*)malloc(kBufferSize); + if (buffer == NULL) + return B_NO_MEMORY; + MemoryDeleter deleter(buffer); + + int32 length = kBufferSize; + status_t status = get_80211(device, IEEE80211_IOC_SCAN_RESULTS, buffer, + length); + if (status != B_OK) + return status; + + BObjectList networksList(true); + + int32 bytesLeft = length; + uint8* entry = buffer; + + while (bytesLeft > (int32)sizeof(struct ieee80211req_scan_result)) { + ieee80211req_scan_result* result + = (ieee80211req_scan_result*)entry; + + char networkName[32]; + strlcpy(networkName, (char*)(result + 1), + min_c((int)sizeof(networkName), result->isr_ssid_len + 1)); + + wireless_network* network = new wireless_network; + fill_wireless_network(*network, networkName, *result); + networksList.AddItem(network); + + entry += result->isr_len; + bytesLeft -= result->isr_len; + } + + count = 0; + if (!networksList.IsEmpty()) { + networks = new wireless_network[networksList.CountItems()]; + for (int32 i = 0; i < networksList.CountItems(); i++) { + networks[i] = *networksList.ItemAt(i); + count++; + } + } + + return B_OK; +} + + static status_t get_scan_result(const char* device, wireless_network& network, uint32 index, const BNetworkAddress* address, const char* name) @@ -430,7 +483,8 @@ get_scan_result(const char* device, wireless_network& network, uint32 index, if (address != NULL && address->Family() != AF_LINK) return B_BAD_VALUE; - const size_t kBufferSize = 65535; + // TODO: Find some way to reduce code duplication with the preceding function! + const size_t kBufferSize = 64 * 1024; uint8* buffer = (uint8*)malloc(kBufferSize); if (buffer == NULL) return B_NO_MEMORY; @@ -787,6 +841,13 @@ BNetworkDevice::GetNextNetwork(uint32& cookie, wireless_network& network) } +status_t +BNetworkDevice::GetNetworks(wireless_network*& networks, uint32& count) +{ + return get_scan_results(Name(), networks, count); +} + + status_t BNetworkDevice::GetNetwork(const char* name, wireless_network& network) { diff --git a/src/preferences/network/InterfaceView.cpp b/src/preferences/network/InterfaceView.cpp index 9515754dd4..ef0499bd1e 100644 --- a/src/preferences/network/InterfaceView.cpp +++ b/src/preferences/network/InterfaceView.cpp @@ -15,6 +15,7 @@ #include +#include #include #include #include @@ -270,10 +271,11 @@ InterfaceView::_Update(bool updateWirelessNetworks) while (device.GetNextAssociatedNetwork(cookie, address) == B_OK) associated.insert(address); - wireless_network network; - cookie = 0; - if ((fPulseCount % 15) == 0 - && device.GetNextNetwork(cookie, network) != B_OK) { + wireless_network* networks = NULL; + uint32 networksCount = 0; + device.GetNetworks(networks, networksCount); + + if ((fPulseCount % 15) == 0 && networksCount == 0) { // We don't seem to know of any networks, and it's been long // enough since the last scan, so trigger one to try and // find some networks. @@ -286,8 +288,12 @@ InterfaceView::_Update(bool updateWirelessNetworks) // to merit such a wait. It's only just over ~4 vertical // retraces, anyway. snooze(50 * 1000); + + device.GetNetworks(networks, networksCount); } + ArrayDeleter networksDeleter(networks); + // go through menu items and remove networks that have dropped out for (int32 index = 0; index < count; index++) { WirelessNetworkMenuItem* networkItem = @@ -297,9 +303,8 @@ InterfaceView::_Update(bool updateWirelessNetworks) break; bool networkFound = false; - cookie = 0; - while (device.GetNextNetwork(cookie, network) == B_OK) { - if (networkItem->Network() == network) { + for (uint32 i = 0; i < networksCount; i++) { + if (networkItem->Network() == networks[i]) { networkFound = true; break; } @@ -312,8 +317,9 @@ InterfaceView::_Update(bool updateWirelessNetworks) } // go through networks and add new ones to menu - cookie = 0; - while (device.GetNextNetwork(cookie, network) == B_OK) { + for (uint32 i = 0; i < networksCount; i++) { + const wireless_network& network = networks[i]; + bool networkFound = false; for (int32 index = 0; index < count; index++) { WirelessNetworkMenuItem* networkItem =