import PackageDescription
let package = Package(
dependencies: [
.Package(url: "https://github.com/VeniceX/TCPSSL.git", majorVersion: 0, minor: 8)
]
)
In this example we'll build a simple "reverse-echo" client and server that utilizes a secure SSL socket for sending and receiving messages.
The client connects to a server available at serverFQDN:8443 and sends a string. It then waits for a response from the server and then exits.
import TCPSSL
guard Process.arguments.count == 3 else {
print("Usage: client serverFQDN string")
exit(0)
}
let serverFQDN = Process.arguments[1]
let sendData = Data(Process.arguments[2])
do {
let connection = try TCPSSLConnection(host:serverFQDN, port:8443)
try connection.open()
try connection.send(sendData)
let data = try connection.receive(upTo:256, timingOut:.never)
} catch {
print("Client error: \(error)")
}
serverFQDN is the fully qualified domain name of the server to which the client is connecting. For example, server.yourdomain.org
.
The server listens for client SSL connections on port 8443. Once a secure connection is established with the client the server reads a string sent from the server, reverses it, and then replies back to the client.
import TCPSSL
import Foundation
guard Process.arguments.count == 4 else {
print("Usage: server certificatePath keyPath certificateChainPath")
exit(0)
}
let certificatePath = Process.arguments[1]
let keyPath = Process.arguments[2]
let certificateChainPath = Process.arguments[3]
do {
let sslServer = try TCPSSLServer(port:8443,
certificate:certificatePath,
privateKey:keyPath,
certificateChain:certificateChainPath)
while true {
do {
let connection = try sslServer.accept(timingOut:.never)
co {
do {
let data = try connection.receive(upTo:256)
let reversed = String(String(data).characters.reversed())
try connection.send(Data(reversed), timingOut:.never)
} catch let dataError {
print("Client connection error: \(dataError)")
}
}
} catch {
print("Server accept error: \(error)")
}
}
} catch let serverError {
print("Error: \(serverError)")
}
The SSL-based TCP server requires at a minimum a certificate and key, and will likely require a certificate chain (also referred to as a bundle).
It is important to note that the TCPSSL implementation does not allow self-signed certificates, and that the client will match the server certificate's CommonName
against the FQDN it connected to.
Server
# .build/debug/server ssl/bundle.crt ssl/server.yourdomain.key ssl/bundle.crt
Listening for connections
Client connected
Client data received: Hello world!
Sending data: !dlrow olleH
Client
.build/debug/client server.yourdomain.org "Hello world\!"
Sending: Hello world!
Received: !dlrow olleH
TCPSSL utilizes Zewo/OpenSSL and as such requires the Homebrew version of OpenSSL installed:
brew install homebrew/versions/openssl101
brew link openssl --force
Linux requires both libgnutls-dev
and libssl-dev
packages to be installed. On Debian variants this can be accomplished with:
apt-get install libgnutls-dev
apt-get install libssl-dev
If you need any help you can join our Slack and go to the #help channel. Or you can create a Github issue in our main repository. When stating your issue be sure to add enough details, specify what module is causing the problem and reproduction steps.
The entire Zewo code base is licensed under MIT. By contributing to Zewo you are contributing to an open and engaged community of brilliant Swift programmers. Join us on Slack to get to know us!
This project is released under the MIT license. See LICENSE for details.