BTW: the forum software things that the abort cause number is "sensitive language," and it's taken me about 20 minutes to figure tha tout.
Post
Replies
Boosts
Views
Activity
What changes were made to NWEndpoint?
I filed FB14076199
As a workaround, if we exclude 8.8.8.8 UDP all ports... it works.
At an extreme end, I was thinking of having the wrapping process (the one that would load & instantiate the class) setting up its own Mach listening for the correct name, so it'd be able to test those parts.
As part of the other stuff I've bee doing recently, I've been factoring out some of the code (for example, all of the flow reads & writes are done in a different class now, resulting in reduced complexity in the TPP subclass.)
Ok, I've created FB13968785 and attached system logs, a screen recording, and an app log. (The coworker did not run sysdiagnose.)
At one point, I had an instance variable named socket, and a function called write(), so I got into the habit, for that file, of using Darwin. for everything. 😄
AH HA!
Honestly, I have no idea if anyone cares about this, but I'm going to document it anyway.
First, I verified that the problem was with my code by writing a very simple proxy. (I still can't see how one uses NERelay!) After all weekend working on it, I got it all working. I cheated and used ObjC for the proxy code, because doing things with sockets was easier.
Second: having my simple TPP app successfully using a proxy, I took the changes I'd made to my code for the provider over to our real app, and it immediately continued to not work.
After days of working on that, the bulk of my problems were due to my Swift clumsiness.
In one case:
let nwritten = data.withUnsafeBytes { (ptr: UnsafeRawBufferPointer) in
var t = ptr
let count = data.count
let kr = Darwin.write(self.socket, &t, count)
return kr
}
That did a great job of writing the UnsafeRawBufferPointer to the socket, when what I wanted was, obviously, the data that it pointed to.
Similarly, in another place, I had
var buffer = message.data(using: .ascii)!
let nwritten = Darwin.write(self.socket, &buffer, buffer.count)
and yeah that wasn't right. I changed them both to be variants of
let nwritten = buffer.withUnsafeBytes { ptr in
return Darwin.write(self.socket, ptr, buffer.count)
}
and then AMAZINGLY it all started working!
The problem with saying it's the routing table is that the first cycle -- writing to the socket from the TPP, reading from the socket in the user-space proxy, then reading that from the socket in the TPP -- works; it's the second write from the TPP that ... vanishes. The connection is localhost:12345, and running tcpdump -i lo0 -s 0 -vvvvvvv -A port 12345 shows the first two, but the last data ... isn't there.
The write() succeeds -- it returns the number of bytes, and the addresses on both ends of the socket are correct.
A bunch of issues, but that's not the problem I'm trying to solve right now -- right now, I'm trying to understand why the 2nd write() doesn't show up on the interface (according to tcpdump, and according to the socket's other side's read()).
The XPC issues have mostly to do with the fact that macOS is, as is sadly usual, an also-have, and the bulk of the code is built around 3rd party libraries that use select/kevent, and hooking them up to the XPC model is, as I said, fraught. So I am trying some other approaches.
I'm not sure how NSRelay works. (Oh! It's the same thing our user-land proxy does, I think. I'm talking about the problems from the TPP.)
Our TPP talks to a user-land proxy that does a bunch of stuff. It's cross-platform; for Windows, it is a much simpler design. The XPC data interchange (flow.read() -> XPC call -> user-land agent -> process, get response -> XPC call -> flow.write()) has been fraught. I am trying to see if instead of XPC, I can connect to the user-land proxy's proxy port.
And, well, I can -- but after the first exchange of data (TPP: socket -> connect -> write -> read -> write; agent socket -> bind -> listen -> accept -> read -> write -> read), the data that the TPP writes ... doesn't show up on the interface, and isn't received by the user-land agent.
(We're not doing just port 80 and 443.)
Well, we'd also want to be able to test the XPC parts, since they're such a large part of the, ahem, process.
Which fits with the parameter being nil in the dumb, but I can't figure out why that would be the case! Very frustrating.
My (much smaller) test TPP app was able to do the FileHandle passing, but the (much bigger) real app wasn't. So I know it's possible, but also just as clearly I'm doing something wrong. Somewhere. :)
Oh, also, I am somehow causing sysextd to die often:
Termination Reason: Namespace SIGNAL, Code 4 Illegal instruction: 4
Terminating Process: exc handler [20261]
Thread 0 Crashed:: Dispatch queue: sysextd.extension_manager
0 sysextd 0x105fb8217 0x105f5d000 + 373271
1 sysextd 0x105f94340 0x105f5d000 + 226112
2 sysextd 0x105f94036 0x105f5d000 + 225334
3 sysextd 0x105f9749e 0x105f5d000 + 238750
4 sysextd 0x105f93df7 0x105f5d000 + 224759
5 sysextd 0x105f93c01 0x105f5d000 + 224257
6 sysextd 0x105f93e78 0x105f5d000 + 224888
7 Foundation 0x7ff80c04d018 __NSXPCCONNECTION_IS_CALLING_OUT_TO_EXPORTED_OBJECT_S1__ + 10
8 Foundation 0x7ff80bff76e8 -[NSXPCConnection _decodeAndInvokeMessageWithEvent:flags:] + 2347
9 Foundation 0x7ff80bfae2ce message_handler + 206
10 libxpc.dylib 0x7ff80ae07ae0 _xpc_connection_call_event_handler + 56
11 libxpc.dylib 0x7ff80ae068c6 _xpc_connection_mach_event + 1413
12 libdispatch.dylib 0x7ff80af113b1 _dispatch_client_callout4 + 9
13 libdispatch.dylib 0x7ff80af2a041 _dispatch_mach_msg_invoke + 445
14 libdispatch.dylib 0x7ff80af171cd _dispatch_lane_serial_drain + 342
15 libdispatch.dylib 0x7ff80af2ab77 _dispatch_mach_invoke + 484
16 libdispatch.dylib 0x7ff80af171cd _dispatch_lane_serial_drain + 342
17 libdispatch.dylib 0x7ff80af17dfd _dispatch_lane_invoke + 366
18 libdispatch.dylib 0x7ff80af21eee _dispatch_workloop_worker_thread + 753
19 libsystem_pthread.dylib 0x7ff80b0c5fd0 _pthread_wqthread + 326
20 libsystem_pthread.dylib 0x7ff80b0c4f57 start_wqthread + 15
As the documentation says, property list types are all allowed by default. You do need to set it for both sides of the interface (I just found this out with FileHandle). The ObjC side of the code is
NSXPCInterface *interface = [NSXPCInterface interfaceWithProtocol:@protocol(RedirectorControlProtocol)];
NSSet<Class> *baseClasses;
baseClasses = [interface classesForSelector:@selector(getApplicationBypass:) argumentIndex:0 ofReply:YES];
NSSet<Class> *newClasses = [baseClasses setByAddingObject:[MyClass class]];
[interface setClasses:newClasses forSelector:@selector(getApplicationBypass:) argumentIndex:0 ofReply:YES];
[interface setClasses:newClasses forSelector:@selector(addAppBypass:) argumentIndex:0 ofReply:NO];
_connection.remoteObjectInterface = interface;