Comments (29)
Is there a way for me to supply the option that I want a self-signed certificate to be ok? (I assume this was the reason for the error)
It is the reason for the error, and yes there is. There are two ways you can handle this: the good way, and the bad way.
Firstly, let's talk about the good way.
The Good Way
In order to accept self-signed certificates, what you are essentially doing is disabling TLS certificate verification. This is obviously very bad: in general, you want to leave TLS certificate verification on. Turning it off negates all of the security benefits of TLS and essentially means you're burning a bunch of CPU power doing a bunch of math for no benefit whatsoever.
Ideally what you'd do is trust a specific self-signed certificate only for a specific service. This can be quite hard, so the next best option is to trust only a specific self-signed certificate, but for everything.
The hard way, trusting a specific self-signed certificate for a specific service, involves setting a verification callback. You can use this callback to modify the SecTrust
object to add the specific self-signed certificate as a trusted root and then perform the trust evaluation. This is somewhat involved, but would look something like this (NB, I haven't actually written this code, I'm just typing it into a window so it may not compile):
import Security
func tlsConfig() -> NIOTSConnectionBootstrap {
let options = NWProtocolTLS.Options()
let verifyQueue = DispatchQueue(label: "verifyQueue")
let mySelfSignedCert: SecCertificate = getCert() // You must implement this!
let verifyBlock: sec_protocol_verify_t = { (metadata, trust, verifyCompleteCB) in
let actualTrust = sec_trust_copy_ref(trust).takeRetainedValue()
SecTrustSetAnchorCertificates(actualTrust, [mySelfSignedCert] as CFArray)
SecTrustEvaluateAsync(actualTrust, verifyQueue) { (_, result) in
switch result {
case .proceed, .unspecified:
verifyCompleteCB(true)
default:
verifyCompleteCB(false)
}
}
}
sec_protocol_options_set_verify_block(options.securityProtocolOptions, verifyBlock, verifyQueue)
return self.tlsOptions(options)
}
The limitations here are that you need a way to get hold of the self-signed cert in your program, and this will only trust the self-signed cert, not the regular roots. If you want to trust more than that, you need to investigate the rest of the APIs on SecTrust
.
This is the best possible thing to do: it restricts the escape hatch of the self-signed cert to a specific service, limiting the ability of a compromise of that self-signed cert to cause problems for other traffic. However, it is the most fiddly. You also need to write custom code to handle this for the Linux case, which requires different code.
Your next best option is to trust the self-signed cert for everything. This is still not good, but it's easier, and in some cases may be worth doing if you feel confident with the risks. In that case, you can add the certificate to your keychain and mark it trusted (on macOS), or create a profile that trusts it and add that profile (iOS/tvOS), or place the certificate in your root cert store (on Linux). This again leaves it up to the user whether they need to use a self-signed certificate or whether they'll provision a proper one. But it's worse than doing the above.
The Bad Way, Do Not Do This
If you are really, really, definitely happy with turning off all of TLS's security properties, you can do so like this:
import Security
func tlsConfig() -> NIOTSConnectionBootstrap {
let options = NWProtocolTLS.Options()
sec_protocol_options_set_peer_authentication_required(options.securityProtocolOptions, false)
return self.tlsOptions(options)
}
But please don't.
from swift-nio-transport-services.
Can you try reducing your program to a simpler use-case?
Try running the server on localhost and then using this program:
import NIO
import NIOTransportServices
import Network
import Security
import Dispatch
let options = NWProtocolTLS.Options()
sec_protocol_options_set_peer_authentication_required(options.securityProtocolOptions, false)
let group = NIOTSEventLoopGroup()
NIOTSConnectionBootstrap(group: group).tlsOptions(options).connect(host: "127.0.0.1", port: 4433).whenComplete {
print($0)
}
dispatchMain()
It should print success(NIOTransportServices.NIOTSConnectionChannel)
. Does that match your result?
from swift-nio-transport-services.
Thank you very, very much for your very detailed answer, Cory. :-)
The case of the self-signed certificate is that a default database instance comes with a self-signed certificate, and that is what I use for spinning up test servers that I test with locally.
I had until now only supported actual valid certificates or self-signed, but adding support for a specific certificate sounds like a good option I should implement.
And making clear the points you are making here in the user documentation is something I'll be sure to do too.
Your Swift window-typing skills are excellent. :-) I haven't gotten the three options working just yet, for instance: even with the sec_protocol_options_set_peer_authentication_required set to false, I somehow got a verification error. Still working on it, though, I'll be back with an update in a little while. :-)
from swift-nio-transport-services.
Hi again, and sorry for the delay.
I've really struggled trying to get the self-signed certificates to work. I created a sample repo https://github.com/niklassaers/learningNIOTransportServices that sets up a little Node.js server with a self-signed certificate, and has a swift client that uses the example above, and then tries to run a test with allowing self-signed certificates. However, when running the test for the little client that is trying to connect, I still get
2019-05-05 13:28:33.288222+0200 xctest[20997:907189] [BoringSSL] boringssl_context_alert_callback_handler(3724) [C1:1][0x100e064f0] Alert level: fatal, description: certificate unknown
2019-05-05 13:28:33.288353+0200 xctest[20997:907189] [BoringSSL] boringssl_context_error_print(3676) boringssl ctx 0x100e06310: 4307486760:error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED:/BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl/boringssl-109.250.2/ssl/handshake.cc:360:
2019-05-05 13:28:33.288602+0200 xctest[20997:907189] [BoringSSL] boringssl_context_get_error_code(3560) [C1:1][0x100e064f0] SSL_AD_CERTIFICATE_UNKNOWN
The errors above, should they really come given the option peer_authentication_required set to false?
Cheers
Niklas
from swift-nio-transport-services.
Do the log lines actually lead to a test failure?
from swift-nio-transport-services.
Great question, that was the way I read it. It's a bit more nuanced, so here is what I found:
let channel = try bootstrap.connect(host: hostname, port: port).wait()
is the line that both triggers the logs and causes the test to fail. This is for both the case that I've said to trust the self-signed certificate (function tlsConfigIgnoreCertificateValidity()) and the case where I've said to trust this particular certificate (function tlsConfigOneTrustedCert()). I'm very confused by the fact that I get both the same warnings and the same failures with both of them.
If, with ignore certificate errors, hostname is "www.google.com" and port is 443, this works fine. If I replace the hostname with the IP address that it was resolved to, "172.217.17.68", private func connect(_ connectAction: @escaping (Channel, EventLoopPromise<Void>) -> Void) -> EventLoopFuture<Channel>
in NIOTSConnectionBootstrap.swift will throw a timeout error in line 172:
▿ connectTimeout : TimeAmount
- nanoseconds : 10000000000
Of course, in HTTPS land a server can have many host names, so it would validate the name, and I'm afraid I don't know how this is done, but I would think it would need to connect before deciding the hostname didn't match? So it's probably not that, but then why the timeout? For the database I ultimately want to connect to, there is as far as I know no similar virtualhosts.
I get the same experience if I use my local server on port 3000 with either my local IP or "127.0.0.1". Perhaps I just cannot use IP addresses in place of hostname? Using "localhost" instead gives me a new kind of error:
▿ -9808: Optional(bad certificate format)
- tls : -9808
in the failed condition on line 659 in private func stateUpdateHandler(newState: NWConnection.State)
in NIOTSConnectionChannel.swift. I don't know why it cares about the certificate when I've asked it not to, and I don't understand why this would be different than just the IP.
If I go to either
https://localhost:3000, https://:3000 or https://127.0.0.1:3000 in my browser and allow the certificate, it works in all cases (just like curl --insecure -o - -v -v https://localhost:3000/
)
from swift-nio-transport-services.
Hrm, is it possible for you to provide the private key and certificate? I'd like to try to reproduce locally.
from swift-nio-transport-services.
Obviously please only do this if you're ok compromising the private key, i.e. don't do so with the key of a production service!
from swift-nio-transport-services.
Absolutely, it was generated for the purpose of this test using the script in the test-repo above. Attached:
from swift-nio-transport-services.
(Note you may need to change the port.)
from swift-nio-transport-services.
Thank you, Cory.
Short summary: it printed failure(NIO.ChannelError.connectTimeout(NIO.TimeAmount(nanoseconds: 10000000000)))
When running the code (I set port to 3000, wrapped it in a class to call from my test) I get the same error:
Output:
Test Case '-[sslTestTests.sslTestTests testTheSimpleTest]' started.
2019-05-07 21:05:51.273365+0200 xctest[33107:1988197] [BoringSSL] boringssl_context_alert_callback_handler(3724) [C1:1][0x100a80850] Alert level: fatal, description: certificate unknown
2019-05-07 21:05:51.273503+0200 xctest[33107:1988197] [BoringSSL] boringssl_context_error_print(3676) boringssl ctx 0x100a80840: 4305993592:error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED:/BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl/boringssl-109.250.2/ssl/handshake.cc:360:
2019-05-07 21:05:51.273559+0200 xctest[33107:1988197] [BoringSSL] boringssl_context_get_error_code(3560) [C1:1][0x100a80850] SSL_AD_CERTIFICATE_UNKNOWN
failure(NIO.ChannelError.connectTimeout(NIO.TimeAmount(nanoseconds: 10000000000)))
Adding exception breakpoints, it stops in NIOTSConnectionBootstrap.swift line 172 function private func connect(_ connectAction: @escaping (Channel, EventLoopPromise<Void>) -> Void) -> EventLoopFuture<Channel>
:
}.map { conn }.flatMapErrorThrowing {
conn.close(promise: nil)
throw $0
}
where "po $0" outputs
▿ ChannelError
▿ connectTimeout : TimeAmount
- nanoseconds : 10000000000
Like before, if I swap out "127.0.0.1" with "localhost" the breakpoint comes in private func stateUpdateHandler(newState: NWConnection.State)
in NIOTSConnectionChannel.swift in line 659 where po err
gives
▿ -9808: Optional(bad certificate format)
- tls : -9808
and the print statement in the whenComplete block prints failure(-9808: Optional(bad certificate format))
For good measure, both
curl --insecure -o - -v -v https://127.0.0.1:3000/
curl --insecure -o - -v -v https://localhost:3000/
were able to connect just fine and return a 200 OK with the body "Hello HTTPS!"
I'm really confused why those give two different results, and why none of them gave the expected success
from swift-nio-transport-services.
This is really interesting. What happens if you replace your server with openssl s_server -cert server.cert -key server.key
? It listens on port 4433. Again, both with my code and your apps.
from swift-nio-transport-services.
The same as before:
2019-05-07 21:45:14.242241+0200 xctest[33798:2019967] [BoringSSL] boringssl_context_alert_callback_handler(3724) [C1:1][0x100b8bf40] Alert level: fatal, description: certificate unknown
2019-05-07 21:45:14.242350+0200 xctest[33798:2019967] [BoringSSL] boringssl_context_error_print(3676) boringssl ctx 0x100b8a8b0: 4307084136:error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED:/BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl/boringssl-109.250.2/ssl/handshake.cc:360:
2019-05-07 21:45:14.242398+0200 xctest[33798:2019967] [BoringSSL] boringssl_context_get_error_code(3560) [C1:1][0x100b8bf40] SSL_AD_CERTIFICATE_UNKNOWN
failure(NIO.ChannelError.connectTimeout(NIO.TimeAmount(nanoseconds: 10000000000)))
From the terminal:
% openssl s_server -cert server.cert -key server.key
Using auto DH parameters
Using default temp ECDH parameters
ACCEPT
ERROR
4558816876:error:14037416:SSL routines:ACCEPT_SR_KEY_EXCH:sslv3 alert certificate unknown:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.250.1/libressl-2.6/ssl/ssl_pkt.c:1205:SSL alert number 46
shutting down SSL
CONNECTION CLOSED
ACCEPT
^C
When I replace "127.0.0.1" with "localhost" I get the same error as in my last comment, and openssl outputs the same as above
What does the OpenSSL error mean.
To keep it all in the thread, the certificate was made like this:
openssl req -nodes -new -x509 -keyout server.key -out server.cert
One more thing I've been meaning to ask, the error in the client I get are from BoringSSL, which in turn is Googles fork of OpenSSL. I was under the impression that Network framework used a TLS implementation built from the ground up by Apple, same used by now deprecated Secure Transport? How does BoringSSL fit in?
from swift-nio-transport-services.
Sorry about the delay, I went to consult with the folks who own the Security framework. Unfortunately it seems like sec_protocol_options_set_peer_authentication_required
is broken in the release you're running, so I've filed a radar on your behalf.
This means that we need to investigate the alternative option of using a custom SecTrust
. Have you investigated this yet with your self-signed certs?
from swift-nio-transport-services.
Thank you, Cory. Could you recommend a macOS or iOS version where it is not broken?
Does that mean that the code where I trust the generated certificate only (almost identical to the code you provided, link to it here) should be working, or does it have implications for that too?
Beyond the code listed here I don't really know SecTrust. I will be sure to read up on that this weekend.
from swift-nio-transport-services.
Does that mean that the code where I trust the generated certificate only (almost identical to the code you provided, link to it here) should be working, or does it have implications for that too?
Yes, that should be working: is it not?
from swift-nio-transport-services.
Nope, it's failing for me in the exact same way:
In order to get the certificate from a file, I've converted it to a der-file:
openssl x509 -in server.cert -outform der -out /tmp/server.der
Then I implemented the getCert() from your example above like this:
let path = "/tmp/server.der"
let data: Data = try! Data(contentsOf: URL(fileURLWithPath: path))
let allocator = CFAllocatorGetDefault()!
_ = allocator.retain()
let cert = SecCertificateCreateWithData(allocator.takeRetainedValue(), data as NSData)
allocator.release()
return cert!
(crude implementation with the hardcoded path and bang, I wanted it short for the example project. While I'm used to Cocoas retain/release, I'm not sure I got the CoreFoundation style right (first time dealing with an allocator). However, from inspecting the returning cert I thought it looked right)
Again openssl outputs
% openssl s_server -cert server.cert -key server.key
Using auto DH parameters
Using default temp ECDH parameters
ACCEPT
ERROR
4534969964:error:14037416:SSL routines:ACCEPT_SR_KEY_EXCH:sslv3 alert certificate unknown:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.250.1/libressl-2.6/ssl/ssl_pkt.c:1205:SSL alert number 46
shutting down SSL
CONNECTION CLOSED
ACCEPT
and the errors I get from my test have the same small difference depending on whether I use "localhost" or "127.0.0.1".
Did I misunderstand anything in this context? Anything different I should try to have it trust this certificate?
from swift-nio-transport-services.
Yeah, this time you're bouncing off the fact that the certificate doesn't contain the hostname you're trying to connect to. Network.framework will normally configure the SecTrust
to use a TLS policy with the hostname you give it to connect to.
To get around this, you can either amend the certificate to contain a subjectAlternativeName
field valid for the hostname in question, or you can amend the SecTrust
policies to not require this validation by calling SecTrustSetPolicies(actualTrust, SecPolicyCreateSSL(true, nil))
before you call SecTrustEvaluateAsync
.
Incidentally, you're doing a bit too much when you create your SecCertificate
. Your getCert
function can be:
let path = "/tmp/server.der"
let data: Data = try! Data(contentsOf: URL(fileURLWithPath: path))
let cert = SecCertificateCreateWithData(nil, data as CFData)
return cert!
Passing nil
as the allocator will automatically use the default allocator.
from swift-nio-transport-services.
Hi Cory,
sorry for being late in writing back - I thought I had. Just wanted to say thanks for the feedback, I've updated getCert - that was indeed a lot cleaner. I had problems with the trusted certificate, but those turned out to be local. So working through it and will get back to you soon. Thanks again for all your help :-)
from swift-nio-transport-services.
Awesome, I take this as a “it works now” and close this, if anything’s still not working, please reopen.
from swift-nio-transport-services.
Hi Cory & Weissi,
I'm sorry to report I still have problems with trusting the self-signed certificate. The very happy path with putting it in my keychain as trusted made everything work well: both my test and the test you suggested above sailed through well, with success as response. While that's fine, that's a bit much for accessing a database server. Getting hold of the certificate and asking to trust that, much like with ssh, is friendlier and something that can be done with a config-file, which is why I want to make trusting the certificate from code work.
I used your example above, Cory, to read the server.der file, but following your example above, I did not get success, but failure(-9808: Optional(bad certificate format))
:
2019-05-23 21:33:51.753676+0200 xctest[65191:4129976] [BoringSSL] boringssl_context_alert_callback_handler(3724) [C1.1:1][0x100c43db0] Alert level: fatal, description: certificate unknown
2019-05-23 21:33:51.753779+0200 xctest[65191:4129976] [BoringSSL] boringssl_context_error_print(3676) boringssl ctx 0x100c43cd0: 4307839800:error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED:/BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl/boringssl-109.250.2/ssl/handshake.cc:360:
2019-05-23 21:33:51.753879+0200 xctest[65191:4129976] [BoringSSL] boringssl_context_get_error_code(3560) [C1.1:1][0x100c43db0] SSL_AD_CERTIFICATE_UNKNOWN
failure(-9808: Optional(bad certificate format))
openssl says
Using auto DH parameters
Using default temp ECDH parameters
ACCEPT
ERROR
4533261932:error:14037416:SSL routines:ACCEPT_SR_KEY_EXCH:sslv3 alert certificate unknown:/BuildRoot/Library/Caches/com.apple.xbs/Sources/libressl/libressl-22.250.1/libressl-2.6/ssl/ssl_pkt.c:1205:SSL alert number 46
shutting down SSL
CONNECTION CLOSED
Now the really odd thing is, that when I run my first test, it doesn't fail anymore, and openssl says
Using auto DH parameters
Using default temp ECDH parameters
ACCEPT
-----BEGIN SSL SESSION PARAMETERS-----
MIGJAgEBAgIDAwQCwDAEIKYoS/wj6NFK4dd17zmGlsonMs6S5GZqkWkJUVwQxUl9
BDCzkXw3+hh1IC2o7ANRZQKKVHGlWSMEftAZLWK9s6veG8xJwP6UpQ9qoPhFa96v
k1ShBgIEXOb2HKIEAgIcIKQGBAQBAAAAphIEEHNhbXBsZS5zYWVycy5jb20=
-----END SSL SESSION PARAMETERS-----
Shared ciphers:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-CHACHA20-POLY1305:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:DES-CBC3-SHA
CIPHER is ECDHE-RSA-AES256-GCM-SHA384
Secure Renegotiation IS supported
GET /
so that looks beautiful. :-) Still working at trying to understand the difference.
New since last time is that I've made sure to have the full hostname in the certificate. I couldn't get setting only the SecTrust policy to work, and I worry a bit about this since most installs have a default generated self-signed SSL certificate. I'll be sure to report back on that as I progress.
So to conclude for now: I seem to have a working way, but I need to understand why I could not get the simple test you suggested above to return success. Then I'll use the success to get to talk to the database, and figure out how to deal with the default certificates.
from swift-nio-transport-services.
@niklassaers reopened
from swift-nio-transport-services.
@niklassaers Can you please share a new copy of the certificate you're trying with, as well as a sample of your code?
from swift-nio-transport-services.
Hi Cory,
good news. :-) Both tests are running fine now, I had set invalid options for the last test.
For reference, the certificate is attached. It was made using this script
The demo repo is here. The modified version of your test is here and now returns success(NIOTransportServices.NIOTSConnectionChannel)
. :-)
Further-more, using this I have been able to connect to the Neo4j database via Bolt over SSL given the trusted certificate, so that's wonderful - now I can complete the version of Theo, the Neo4j Swift driver, based on SwiftNIO 2. :-)
A final question: since I need a certificate to trust, is there a common way I could request the server certificate? I could then could ask the user if he wants to trust it (like when ssh'ing to a new host the first time), as an alternative to having the option of the user converting it to the right format and configuring it himself.
Yours sincerely
Niklas
from swift-nio-transport-services.
A final question: since I need a certificate to trust, is there a common way I could request the server certificate?
The common way is simply to make the connection attempt and obtain the peer certificate. This is actually somewhat hard to do with the APIs exposed by SwiftNIO, but you can use the same trick of overriding the verify callback to do this. As the verify callback should run on a non-event-loop thread, you could even present the user with a UI asking them whether they want to trust the certificate before you proceed.
from swift-nio-transport-services.
Thank you Cory, I'll be sure to go that route. I'll post a little update when the Theo update is ready. :-)
from swift-nio-transport-services.
Theo 5 is marching along merrily, hoping to release it this month. :-) Gave the community a heads-up so I hopefully can get a few people other than me testing it as well before general availability. :-)
@Lukasa I followed your advice of putting this in the verify block:
if let publicKey = sec_protocol_metadata_copy_peer_public_key(metadata) {
let publicKeyData = publicKey as! Data
sha1 = publicKeyData.sha1()
let cert = SecCertificateCreateWithData(nil, publicKeyData as CFData)
if let cert = cert {
print("Good place")
} else {
print("Not so good")
}
}
This gives me two issues, though. First the probably easy one: as I read the docs, dispatch_data_t should be zero-cost bridgeable to NSData. Yet I cannot simply us "as Data", since the Swift compiler says casting from __DispatchData to unrelated type Data always fails. Any suggestion how to make this safe and warning-free?
The data in publicKeyData is 270 bytes, where the der-file I read in above was 686 bytes. SecCertificateCreateWithData does return a certificate with the der-file, it does not with only the public key. So I always get to "Not so good" in the code above. This isn't a show-stopper, I can store a list of trusted SHA1s and perform verifyCompleteCB(true)
for them. Is this what I should be doing, or is there another way of requesting the certificate?
from swift-nio-transport-services.
The above code cannot work: you're taking a peer public key and attempting to turn it into a certificate, but a public key is not a certificate, only a part of it.
My proposed suggestion was to do this in the verify callback, which is given the peer certificate in the trust. This will also avoid the issues with Data
you're running into.
from swift-nio-transport-services.
Thanks, Cory, and sorry for my late response. I got the certificate now and it's working beautifully. :-)
from swift-nio-transport-services.
Related Issues (20)
- Compile failure on Windows HOT 5
- NIOFilterEmptyWritesHandler isn't guarded by `if #canImport(Network)` HOT 1
- Application Crash when attempting to connect to `Ports > UInt16.max` HOT 2
- Adding to iOS project hides all simulators and devices
- Cannot get NIO transport services to resolve - still not working :-( HOT 8
- Can't build for release on iOS 15 HOT 1
- Adopt new Channel-focused APIs from NIO
- Failed to build module 'Network'; this SDK is not supported by the compiler HOT 2
- Example for Bounjour service announcement would be useful HOT 4
- Race condition when closing connection HOT 4
- copy-paste error in NIOTSConnectionChannel getOption0 allowLocalEndpointReuse HOT 4
- Add Async Await support to NIOTSListenerBootstrap childChannelInitializer HOT 1
- flaky test `NIOTSChannelOptionsTests.testDataTransferReport`
- xcodebuild is failed HOT 3
- Flaky test -[NIOTransportServicesTests.NIOTSChannelOptionsTests testDataTransferReport] HOT 1
- Make `NIOTSNetworkEvents` initialisers public
- URGENT : NIOTransportServices / NIOTSConnectionBootstrap is only available in macOS 10.14 or newer HOT 9
- There is no typed bind function that takes a unixDomainSocketPath HOT 2
- Edgar
- iPhone
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from swift-nio-transport-services.