Thanks, Quinn. Your response was very helpful and also clarifying on how to best code the .receive completion handler!!
--Barry
Post
Replies
Boosts
Views
Activity
I ran into NFS issues from a launchd daemon a few months back. Seems that Catalina forward handles NFS differently. Here's the note I made to myself for future reference. Hopefully it will be of some help. This did solve my issue.
NOTE: Pre-Catalina, a base export path like /Path/to/myFolder works as expected. But in Catalina, the base path to folders now start at /System/Volumes/Data. This is due to major file system changes in Catalina involving APFS, virtual volumes, etc. So now what was /Path/to/myFolder should be exported as /System/Volumes/Data/Path/to/myFolder.
--Barry
UPDATE: With Matt Eaton's invaluable input, I've been able to get the following code to work. This listener is now running in my dev environment (i.e. localhost with a self-signed CA cert in the Login Keychain). Safari requests to "https://" (on port 443) now work as expected, whereas before only "http://" (on port 80) worked.
// Function used by the HTTPService class below
//
func getSecIdentity() -> SecIdentity? {
let certName = "LocalNetworkTLSLeaf"
let getquery = [kSecClass : kSecClassCertificate,
kSecAttrLabel: certName,
kSecReturnRef: true] as NSDictionary
var item : CFTypeRef?
var identity: SecIdentity?
let status = SecItemCopyMatching(getquery as CFDictionary, &item)
guard status == errSecSuccess else {
print("Failed to get cetificate: \(status)")
return nil
}
let certificate = item as! SecCertificate
let identityStatus = SecIdentityCreateWithCertificate(nil, certificate, &identity)
guard identityStatus == errSecSuccess else {
print("Failed to get sec identity: \(identityStatus)")
return nil
}
return identity
}
final class HTTPService {
.
.
.
private let Listener : NWListener
init?( port: UInt16, root: String, tls: Bool = false ) {
.
.
.
// Configure the main service Listener
//
guard let port = NWEndpoint.Port(rawValue: port)
else {
LogMessage("Not able to configure \(port) for listening")
return nil
}
let TCP_opts = NWProtocolTCP.Options()
TCP_opts.disableECN = true // Explicit Congestion Notification
TCP_opts.enableKeepalive = false // Send Keep-Alive packets
TCP_opts.connectionTimeout = 5 // Connection handshake timeout (seconds)
TCP_opts.connectionDropTime = 5 // Seconds TCP will do packet retransmission
let Parameters: NWParameters
if (tls) {
let TLS_opts = NWProtocolTLS.Options()
Parameters = NWParameters(tls: TLS_opts, tcp: TCP_opts)
Parameters.allowLocalEndpointReuse = true
// Get SecIdentity from the Keychain
//
if let secIdentity = getSecIdentity(), let identity = sec_identity_create(secIdentity) {
sec_protocol_options_set_min_tls_protocol_version(TLS_opts.securityProtocolOptions, .TLSv13)
sec_protocol_options_set_local_identity(TLS_opts.securityProtocolOptions, identity)
sec_protocol_options_append_tls_ciphersuite( TLS_opts.securityProtocolOptions, tls_ciphersuite_t(rawValue: UInt16(TLS_AES_128_GCM_SHA256))! )
}
}
else {
Parameters = NWParameters(tls: nil, tcp: TCP_opts)
Parameters.allowLocalEndpointReuse = true
}
guard let L = try? NWListener( using: Parameters, on: port )
else {
LogMessage("Not able to configure TCP listener on port \(port)")
return nil
}
self.Listener = L
self.Listener.newConnectionHandler = self.NewConnection(_:)
.
.
.
}
}