What is required to register for CoreWLAN events?

I have a simple piece of demo code I am attempting to write for MacOS Yosemite that uses CoreWLAN to report on WiFi events. I've tried every combination I can think of Sandboxed, Signed, etc., all to no avail. Currently, I have the app set for Sandbox mode, and allowing outbound network connections in the entitlements. Any ideas as to how to get this to work? Sample code and scenario below:


import CoreWLAN
class WirelessMonitor: CWEventDelegate {
    func registerForEvents() {
        let client = CWWiFiClient.sharedWiFiClient()
        client.delegate = self
        var error:NSError?
        puts("Registering for SSID change...")
        client.startMonitoringEventWithType(.SSIDDidChange, error: &error)
        if (error != nil) {
            puts("error registering for SSID Change: \(error)")
        }
    }
    func ssidDidChangeForWiFiInterfaceWithName(interfaceName: String!) {
        print("ssid changed.")
    }
}



When I run this, I receive an error upon calling startMonitoringEventWithType(...):


"Couldn’t communicate with a helper application." (The connection to service named com.apple.airportd was invalidated.)


In the MaOS console, I see this message:


7/18/15 12:19:11.753 AM sandboxd[504]: ([4105]) WiFi Debugger(4105) deny mach-lookup com.apple.airportd

Accepted Reply

At this point I’m going to have to revisit this issue in depth and that’s not something I can do in the context of DevForums.

It turns out that a different developer open a DTS tech support incident about this issue and that gave me an excuse to re-test.

CWWiFiClient
is definitely working for me an 10.13.4. The only oddity, and I suspect that this is what’s tripped you up, is that this API is now gated by the
com.apple.security.network.client
entitlement. Please make sure to enable that entitlement (Xcode > project editor > target > Capabilities > App Sandbox > Outgoing Connections (Client)) and retest.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

I wanted to post an update on this issue. If you read the current Apple documentation you’ll find it says:

In order to monitor Wi-Fi events, you must specify the com.apple.wifi.events entitlement for your app.

The bad news is that this is incorrect (r. 37154185). The good news is that it is possible to use

CWWiFiClient
from both sandboxed and non-sandboxed apps on recent versions of macOS.

The not-so-good news is that an OS bug (r. 36702504) prevents sandboxed apps from using

CWWiFiClient
without applying a workaround. Moreover, I’m not going to explain that workaround here on DevForums. If you need to use
CWWiFiClient
from a sandboxed app, please open a DTS tech support incident and I can walk you through that process.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you for the information Quinn!

I specifically need startMonitoringEvent(with: .scanCacheUpdated) to work in a sandboxed environment, and I only have one DTS available, could you please walk me through the process of getting this work?

Thanks in Advance!

please walk me through the process of getting this work?

Let’s start with the basics. Have you tried this on 10.13.4? One of the bugs I mentioned above (r. 36702504) is reported as fixed on that release, and it should allow

CWWiFiClient
to work without any specialist entitlements. Alas, I haven’t had a chance to try this for myself yet.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks a bunch Quinn, for the prompt reply!


Yes, I have tried this on 10.13.4 which works fine in the non-sandboxed environment only.

Sandboxed environment throws the following error: "Couldn’t communicate with a helper application".


Code:

try self.wifiClient.startMonitoringEvent(with: .scanCacheUpdated)


Tested on MacOS 10.13.4 with Xcode 9.3.

Hmmmm, I’m not sure why helper application this is referring to. If you catch the error and

NSLog
it, what do you see:
do {
    try … stuff …
} catch {
    NSLog("%@", "\(%@)")
}

I guess I need to bite the bullet and install 10.3.4, eh? (-:

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Sorry I was printing the localizedDescription of the error which isn't helpful at all. 😟


So, this is what I Catch:


(lldb) po error

Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.airportd was invalidated." UserInfo={NSDebugDescription=The connection to service named com.apple.airportd was invalidated.}


(lldb) po error.localizedDescription

"Couldn’t communicate with a helper application."

Error Domain=NSCocoaErrorDomain Code=4099

Hmmm, that looks exactly like the error that I was under the impression we’d fixed in 10.13.4 (r. 36702504). At this point I’m going to have to revisit this issue in depth and that’s not something I can do in the context of DevForums.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

At this point I’m going to have to revisit this issue in depth and that’s not something I can do in the context of DevForums.

It turns out that a different developer open a DTS tech support incident about this issue and that gave me an excuse to re-test.

CWWiFiClient
is definitely working for me an 10.13.4. The only oddity, and I suspect that this is what’s tripped you up, is that this API is now gated by the
com.apple.security.network.client
entitlement. Please make sure to enable that entitlement (Xcode > project editor > target > Capabilities > App Sandbox > Outgoing Connections (Client)) and retest.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

It works, though the events are not consistently working with a little testing that I did but I did get them.

Thank you Quinn!

I did get them.

Excellent news.

though the events are not consistently working with a little testing that I did

I’m not aware of any specific problems with

CWWiFiClient
, but I should explain one gotcha that hit me while it was testing it.
CWWiFiClient
calls its delegate on a background queue. If you update your UI from such a delegate callback, you are calling AppKit from a secondary thread, which is not allowed. There are a variety of ways that this problem can manifest itself. In my case it meant that the UI wasn’t updating promptly, leading me to think that
CWWiFiClient
was misbehaving.

So, make sure you’re not doing UI stuff in your

CWWiFiClient
delegate callbacks or, if you need to do that, bounce to the main queue beforehand.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Using the com.apple.security.network.client entitlement seems sufficient for monitoring events, but it also seems to allow for scanning of networks by calling the [CWInterface scanForNetworksUsingXXX] methods directly on a reference of CWInterface gotten via CWWiFiClient. Is this expected?

Yes. Its allowing to scan for other networks (with sandbox ON), but export it with developer signed ID or ad-hoc entitlement and it won't work. It logs "SandboxViolation: deny(1) mach-lookup com.apple.network.EAPOLController" in Console.

Its allowing to scan for other networks (with sandbox ON), but export it with developer signed ID or ad-hoc entitlement and it won't work.

I’m not sure how “ad hoc entitlements” come into this; ad hoc signing is an iOS concept and not supported on macOS.

With regards “developer signed ID”, are you talking about Developer ID signing? If so, it’s possible that might behave differently from development signing, but it strikes me as unlikely. Are you sure that the Developer ID version of the app was signed with the correct entitlements? That’s the usual cause of problems like this.

I recommend that you dump the entitlements of the built binary using:

$ codesign -d --entitlements :- /path/to/your.app

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

My mistake, there is no ad-hoc.

By "developer signed ID" I meant "Developer ID signed".

By "developer signed ID" I meant "Developer ID signed".

OK. And the entitlements of your built binary?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"