/*
* Copyright 2015-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.facebook.buck.util.environment;
import ca.weblite.objc.Client;
import ca.weblite.objc.Proxy;
import ca.weblite.objc.RuntimeUtils;
import com.facebook.buck.log.Logger;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import java.util.Optional;
/** Mac OS X implementation of finding the SSID of the default Wi-Fi interface. */
public class MacWifiSsidFinder {
private static final Logger LOG = Logger.get(MacWifiSsidFinder.class);
// Utility class, do not instantiate.
private MacWifiSsidFinder() {}
public static interface CoreWlan extends Library {}
// Need to hold on to an instance of this library so CoreWLAN.framework is kept resident.
public static final CoreWlan CORE_WLAN_INSTANCE =
(CoreWlan) Native.loadLibrary("CoreWLAN", CoreWlan.class);
/** Finds the SSID of the default Wi-Fi interface using Mac OS X APIs. */
public static Optional<String> findCurrentSsid() {
LOG.debug("Getting current SSID..");
// Grab a handle to the Objective-C runtime.
Client objcClient = Client.getInstance();
// Try the OS X 10.10 and later supported API, then fall
// back to the OS X 10.6 API.
Pointer wifiClientClass = RuntimeUtils.cls("CWWiFiClient");
Optional<Proxy> defaultInterface;
if (wifiClientClass != null) {
LOG.verbose("Getting default interface using +[CWWiFiClient sharedWiFiClient]");
defaultInterface = getDefaultWifiInterface(objcClient, wifiClientClass);
} else {
LOG.verbose("Getting default interface using +[CWInterface defaultInterface]");
// CWInterface *defaultInterface = [CWInterface interface];
defaultInterface = Optional.ofNullable(objcClient.sendProxy("CWInterface", "interface"));
}
return getSsidFromInterface(defaultInterface);
}
/** Finds the SSID of the default Wi-Fi interface using Mac OS X 10.10 and later APIs. */
private static Optional<Proxy> getDefaultWifiInterface(
Client objcClient, Pointer wifiClientClass) {
// CWWiFiClient *sharedWiFiClient = [CWWiFiClient sharedWiFiClient];
Proxy sharedWiFiClient = objcClient.sendProxy(wifiClientClass, "sharedWiFiClient");
if (sharedWiFiClient == null) {
LOG.warn("+[CWWiFiClient sharedWiFiClient] returned null, could not find SSID.");
return Optional.empty();
}
// CWInterface *defaultInterface = [sharedWiFiClient interface];
Proxy defaultInterface = sharedWiFiClient.sendProxy("interface");
if (defaultInterface == null) {
LOG.warn("-[sharedWiFiClient interface] returned null, could not find SSID.");
return Optional.empty();
}
return Optional.of(defaultInterface);
}
private static Optional<String> getSsidFromInterface(Optional<Proxy> defaultInterface) {
if (!defaultInterface.isPresent()) {
LOG.debug("No Wi-Fi interface found.");
return Optional.empty();
}
LOG.debug("Getting SSID from Wi-Fi interface: %s", defaultInterface.get());
// NSString *ssid = [defaultInterface ssid];
Object ssid = defaultInterface.get().send("ssid");
if (ssid == null) {
LOG.debug("No SSID found for interface %s.", defaultInterface.get());
return Optional.empty();
}
String ssidString;
if (!(ssid instanceof String)) {
LOG.warn(
"Fetched SSID, but got unexpected non-string type (got: %s).", ssid.getClass().getName());
ssidString = ssid.toString();
} else {
ssidString = (String) ssid;
}
LOG.debug("Found SSID: %s", ssidString);
return Optional.of(ssidString);
}
}