netwerk/wifi/nsWifiScannerDBus.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial