LCOV - code coverage report
Current view: top level - netwerk/wifi - nsWifiScannerDBus.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 174 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 12 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Public
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       3             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : #include "nsWifiScannerDBus.h"
       6             : #include "mozilla/ipc/DBusMessageRefPtr.h"
       7             : #include "nsWifiAccessPoint.h"
       8             : 
       9             : namespace mozilla {
      10             : 
      11           0 : nsWifiScannerDBus::nsWifiScannerDBus(nsCOMArray<nsWifiAccessPoint> *aAccessPoints)
      12           0 : : mAccessPoints(aAccessPoints)
      13             : {
      14           0 :   MOZ_ASSERT(mAccessPoints);
      15             : 
      16             :   mConnection =
      17           0 :     already_AddRefed<DBusConnection>(dbus_bus_get(DBUS_BUS_SYSTEM, nullptr));
      18             : 
      19           0 :   if (mConnection) {
      20           0 :     dbus_connection_set_exit_on_disconnect(mConnection, false);
      21             :   }
      22             : 
      23           0 :   MOZ_COUNT_CTOR(nsWifiScannerDBus);
      24           0 : }
      25             : 
      26           0 : nsWifiScannerDBus::~nsWifiScannerDBus()
      27             : {
      28           0 :   MOZ_COUNT_DTOR(nsWifiScannerDBus);
      29           0 : }
      30             : 
      31             : nsresult
      32           0 : nsWifiScannerDBus::Scan()
      33             : {
      34           0 :   if (!mConnection) {
      35           0 :     return NS_ERROR_NOT_AVAILABLE;
      36             :   }
      37             :   return SendMessage("org.freedesktop.NetworkManager",
      38             :                      "/org/freedesktop/NetworkManager",
      39           0 :                      "GetDevices");
      40             : }
      41             : 
      42             : nsresult
      43           0 : nsWifiScannerDBus::SendMessage(const char* aInterface,
      44             :                                const char* aPath,
      45             :                                const char* aFuncCall)
      46             : {
      47           0 :   RefPtr<DBusMessage> msg = already_AddRefed<DBusMessage>(
      48             :     dbus_message_new_method_call("org.freedesktop.NetworkManager",
      49           0 :                                  aPath, aInterface, aFuncCall));
      50           0 :   if (!msg) {
      51           0 :     return NS_ERROR_FAILURE;
      52             :   }
      53             : 
      54             :   DBusMessageIter argsIter;
      55           0 :   dbus_message_iter_init_append(msg, &argsIter);
      56             : 
      57           0 :   if (!strcmp(aFuncCall, "Get")) {
      58           0 :     const char* paramInterface = "org.freedesktop.NetworkManager.Device";
      59           0 :     if (!dbus_message_iter_append_basic(&argsIter, DBUS_TYPE_STRING,
      60             :                                         &paramInterface)) {
      61           0 :       return NS_ERROR_FAILURE;
      62             :     }
      63             : 
      64           0 :     const char* paramDeviceType = "DeviceType";
      65           0 :     if (!dbus_message_iter_append_basic(&argsIter, DBUS_TYPE_STRING,
      66             :                                         &paramDeviceType)) {
      67           0 :       return NS_ERROR_FAILURE;
      68             :     }
      69           0 :   } else if (!strcmp(aFuncCall, "GetAll")) {
      70           0 :     const char* param = "";
      71           0 :     if (!dbus_message_iter_append_basic(&argsIter, DBUS_TYPE_STRING, &param)) {
      72           0 :       return NS_ERROR_FAILURE;
      73             :     }
      74             :   }
      75             : 
      76             :   DBusError err;
      77           0 :   dbus_error_init(&err);
      78             : 
      79             :   // http://dbus.freedesktop.org/doc/api/html/group__DBusConnection.html
      80             :   // Refer to function dbus_connection_send_with_reply_and_block.
      81           0 :   const uint32_t DBUS_DEFAULT_TIMEOUT = -1;
      82           0 :   RefPtr<DBusMessage> reply = already_AddRefed<DBusMessage>(
      83             :     dbus_connection_send_with_reply_and_block(mConnection, msg,
      84           0 :                                               DBUS_DEFAULT_TIMEOUT, &err));
      85           0 :   if (dbus_error_is_set(&err)) {
      86           0 :     dbus_error_free(&err);
      87             : 
      88             :     // In the GetAccessPoints case, if there are no access points, error is set.
      89             :     // We don't want to error out here.
      90           0 :     if (!strcmp(aFuncCall, "GetAccessPoints")) {
      91           0 :       return NS_OK;
      92             :     }
      93           0 :     return NS_ERROR_FAILURE;
      94             :   }
      95             : 
      96             :   nsresult rv;
      97           0 :   if (!strcmp(aFuncCall, "GetDevices")) {
      98           0 :     rv = IdentifyDevices(reply);
      99           0 :   } else if (!strcmp(aFuncCall, "Get")) {
     100           0 :     rv = IdentifyDeviceType(reply, aPath);
     101           0 :   } else if (!strcmp(aFuncCall, "GetAccessPoints")) {
     102           0 :     rv = IdentifyAccessPoints(reply);
     103           0 :   } else if (!strcmp(aFuncCall, "GetAll")) {
     104           0 :     rv = IdentifyAPProperties(reply);
     105             :   } else {
     106           0 :     rv = NS_ERROR_FAILURE;
     107             :   }
     108           0 :   return rv;
     109             : }
     110             : 
     111             : nsresult
     112           0 : nsWifiScannerDBus::IdentifyDevices(DBusMessage* aMsg)
     113             : {
     114             :   DBusMessageIter iter;
     115           0 :   nsresult rv = GetDBusIterator(aMsg, &iter);
     116           0 :   NS_ENSURE_SUCCESS(rv, rv);
     117             : 
     118             :   const char* devicePath;
     119           0 :   do {
     120           0 :     if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH) {
     121           0 :       return NS_ERROR_FAILURE;
     122             :     }
     123             : 
     124           0 :     dbus_message_iter_get_basic(&iter, &devicePath);
     125           0 :     if (!devicePath) {
     126           0 :       return NS_ERROR_FAILURE;
     127             :     }
     128             : 
     129           0 :     rv = SendMessage("org.freedesktop.DBus.Properties", devicePath, "Get");
     130           0 :     NS_ENSURE_SUCCESS(rv, rv);
     131           0 :   } while (dbus_message_iter_next(&iter));
     132             : 
     133           0 :   return NS_OK;
     134             : }
     135             : 
     136             : nsresult
     137           0 : nsWifiScannerDBus::IdentifyDeviceType(DBusMessage* aMsg, const char* aDevicePath)
     138             : {
     139             :   DBusMessageIter args;
     140           0 :   if (!dbus_message_iter_init(aMsg, &args)) {
     141           0 :     return NS_ERROR_FAILURE;
     142             :   }
     143             : 
     144           0 :   if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_VARIANT) {
     145           0 :     return NS_ERROR_FAILURE;
     146             :   }
     147             : 
     148             :   DBusMessageIter variantIter;
     149           0 :   dbus_message_iter_recurse(&args, &variantIter);
     150           0 :   if (dbus_message_iter_get_arg_type(&variantIter) != DBUS_TYPE_UINT32) {
     151           0 :     return NS_ERROR_FAILURE;
     152             :   }
     153             : 
     154             :   uint32_t deviceType;
     155           0 :   dbus_message_iter_get_basic(&variantIter, &deviceType);
     156             : 
     157             :   // http://projects.gnome.org/NetworkManager/developers/api/07/spec-07.html
     158             :   // Refer to NM_DEVICE_TYPE_WIFI under NM_DEVICE_TYPE.
     159           0 :   const uint32_t NM_DEVICE_TYPE_WIFI = 2;
     160           0 :   nsresult rv = NS_OK;
     161           0 :   if (deviceType == NM_DEVICE_TYPE_WIFI) {
     162             :     rv = SendMessage("org.freedesktop.NetworkManager.Device.Wireless",
     163           0 :                      aDevicePath, "GetAccessPoints");
     164             :   }
     165             : 
     166           0 :   return rv;
     167             : }
     168             : 
     169             : nsresult
     170           0 : nsWifiScannerDBus::IdentifyAccessPoints(DBusMessage* aMsg)
     171             : {
     172             :   DBusMessageIter iter;
     173           0 :   nsresult rv = GetDBusIterator(aMsg, &iter);
     174           0 :   NS_ENSURE_SUCCESS(rv, rv);
     175             : 
     176             :   const char* path;
     177           0 :   do {
     178           0 :     if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_OBJECT_PATH) {
     179           0 :       return NS_ERROR_FAILURE;
     180             :     }
     181           0 :     dbus_message_iter_get_basic(&iter, &path);
     182           0 :     if (!path) {
     183           0 :       return NS_ERROR_FAILURE;
     184             :     }
     185             : 
     186           0 :     rv = SendMessage("org.freedesktop.DBus.Properties", path, "GetAll");
     187           0 :     NS_ENSURE_SUCCESS(rv, rv);
     188           0 :   } while (dbus_message_iter_next(&iter));
     189             : 
     190           0 :   return NS_OK;
     191             : }
     192             : 
     193             : nsresult
     194           0 : nsWifiScannerDBus::IdentifyAPProperties(DBusMessage* aMsg)
     195             : {
     196             :   DBusMessageIter arr;
     197           0 :   nsresult rv = GetDBusIterator(aMsg, &arr);
     198           0 :   NS_ENSURE_SUCCESS(rv, rv);
     199             : 
     200           0 :   RefPtr<nsWifiAccessPoint> ap = new nsWifiAccessPoint();
     201           0 :   do {
     202             :     DBusMessageIter dict;
     203           0 :     dbus_message_iter_recurse(&arr, &dict);
     204             : 
     205           0 :     do {
     206             :       const char* key;
     207           0 :       dbus_message_iter_get_basic(&dict, &key);
     208           0 :       if (!key) {
     209           0 :         return NS_ERROR_FAILURE;
     210             :       }
     211           0 :       dbus_message_iter_next(&dict);
     212             : 
     213             :       DBusMessageIter variant;
     214           0 :       dbus_message_iter_recurse(&dict, &variant);
     215             : 
     216           0 :       if (!strncmp(key, "Ssid", strlen("Ssid"))) {
     217           0 :         nsresult rv = StoreSsid(&variant, ap);
     218           0 :         NS_ENSURE_SUCCESS(rv, rv);
     219           0 :         break;
     220             :       }
     221             : 
     222           0 :       if (!strncmp(key, "HwAddress", strlen("HwAddress"))) {
     223           0 :         nsresult rv = SetMac(&variant, ap);
     224           0 :         NS_ENSURE_SUCCESS(rv, rv);
     225           0 :         break;
     226             :       }
     227             : 
     228           0 :       if (!strncmp(key, "Strength", strlen("Strength"))) {
     229           0 :         if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_BYTE) {
     230           0 :           return NS_ERROR_FAILURE;
     231             :         }
     232             : 
     233             :         uint8_t strength;
     234           0 :         dbus_message_iter_get_basic(&variant, &strength);
     235           0 :         ap->setSignal(strength);
     236             :       }
     237           0 :     } while (dbus_message_iter_next(&dict));
     238           0 :   } while (dbus_message_iter_next(&arr));
     239             : 
     240           0 :   mAccessPoints->AppendObject(ap);
     241           0 :   return NS_OK;
     242             : }
     243             : 
     244             : nsresult
     245           0 : nsWifiScannerDBus::StoreSsid(DBusMessageIter* aVariant, nsWifiAccessPoint* aAp)
     246             : {
     247           0 :   if (dbus_message_iter_get_arg_type(aVariant) != DBUS_TYPE_ARRAY) {
     248           0 :     return NS_ERROR_FAILURE;
     249             :   }
     250             : 
     251             :   DBusMessageIter variantMember;
     252           0 :   dbus_message_iter_recurse(aVariant, &variantMember);
     253             : 
     254           0 :   const uint32_t MAX_SSID_LEN = 32;
     255             :   char ssid[MAX_SSID_LEN];
     256           0 :   memset(ssid, '\0', ArrayLength(ssid));
     257           0 :   uint32_t i = 0;
     258           0 :   do {
     259           0 :     if (dbus_message_iter_get_arg_type(&variantMember) != DBUS_TYPE_BYTE) {
     260           0 :       return NS_ERROR_FAILURE;
     261             :     }
     262             : 
     263           0 :     dbus_message_iter_get_basic(&variantMember, &ssid[i]);
     264           0 :     i++;
     265           0 :   } while (dbus_message_iter_next(&variantMember) && i < MAX_SSID_LEN);
     266             : 
     267           0 :   aAp->setSSID(ssid, i);
     268           0 :   return NS_OK;
     269             : }
     270             : 
     271             : nsresult
     272           0 : nsWifiScannerDBus::SetMac(DBusMessageIter* aVariant, nsWifiAccessPoint* aAp)
     273             : {
     274           0 :   if (dbus_message_iter_get_arg_type(aVariant) != DBUS_TYPE_STRING) {
     275           0 :     return NS_ERROR_FAILURE;
     276             :   }
     277             : 
     278             :   // hwAddress format is XX:XX:XX:XX:XX:XX. Need to convert to XXXXXX format.
     279             :   char* hwAddress;
     280           0 :   dbus_message_iter_get_basic(aVariant, &hwAddress);
     281           0 :   if (!hwAddress) {
     282           0 :     return NS_ERROR_FAILURE;
     283             :   }
     284             : 
     285           0 :   const uint32_t MAC_LEN = 6;
     286             :   uint8_t macAddress[MAC_LEN];
     287           0 :   char* token = strtok(hwAddress, ":");
     288           0 :   for (uint32_t i = 0; i < ArrayLength(macAddress); i++) {
     289           0 :     if (!token) {
     290           0 :       return NS_ERROR_FAILURE;
     291             :     }
     292           0 :     macAddress[i] = strtoul(token, nullptr, 16);
     293           0 :     token = strtok(nullptr, ":");
     294             :   }
     295           0 :   aAp->setMac(macAddress);
     296           0 :   return NS_OK;
     297             : }
     298             : 
     299             : nsresult
     300           0 : nsWifiScannerDBus::GetDBusIterator(DBusMessage* aMsg,
     301             :                                    DBusMessageIter* aIterArray)
     302             : {
     303             :   DBusMessageIter iter;
     304           0 :   if (!dbus_message_iter_init(aMsg, &iter)) {
     305           0 :     return NS_ERROR_FAILURE;
     306             :   }
     307             : 
     308           0 :   if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
     309           0 :     return NS_ERROR_FAILURE;
     310             :   }
     311             : 
     312           0 :   dbus_message_iter_recurse(&iter, aIterArray);
     313           0 :   return NS_OK;
     314             : }
     315             : 
     316             : } // mozilla
     317             : 
     318             : nsresult
     319           0 : nsWifiMonitor::DoScan()
     320             : {
     321           0 :   nsCOMArray<nsWifiAccessPoint> accessPoints;
     322           0 :   mozilla::nsWifiScannerDBus wifiScanner(&accessPoints);
     323           0 :   nsCOMArray<nsWifiAccessPoint> lastAccessPoints;
     324             : 
     325           0 :   while (mKeepGoing) {
     326           0 :     accessPoints.Clear();
     327           0 :     nsresult rv = wifiScanner.Scan();
     328           0 :     NS_ENSURE_SUCCESS(rv, rv);
     329           0 :     bool accessPointsChanged = !AccessPointsEqual(accessPoints,
     330           0 :                                                   lastAccessPoints);
     331           0 :     ReplaceArray(lastAccessPoints, accessPoints);
     332             : 
     333           0 :     rv = CallWifiListeners(lastAccessPoints, accessPointsChanged);
     334           0 :     NS_ENSURE_SUCCESS(rv, rv);
     335             : 
     336           0 :     LOG(("waiting on monitor\n"));
     337           0 :     mozilla::ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     338           0 :     mon.Wait(PR_SecondsToInterval(kDefaultWifiScanInterval));
     339             :   }
     340             : 
     341           0 :   return NS_OK;
     342             : }

Generated by: LCOV version 1.13