class TLSSocket < IO
A TLS connection over a TCP connection: TLSSocket.connect makes a
client's, TLSSocket.accept a server's. Every IO method works on it,
so whatever takes an IO takes it.
sock = TCPSocket.new("example.com", 443)
tls = TLSSocket.connect(sock, "example.com")
tls.write("GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n")
puts tls.gets
tls.close
Class methods
def self.connect(socket: TCPSocket, server_name: String, config: TLS::Config = …) -> TLSSocket
Takes socket over and runs the TLS handshake with its peer, as
server_name (the name sent as SNI and the one its certificate is
verified against; an IP address is allowed). When it returns, the
handshake is done. socket is closed for the program from then on:
its descriptor belongs to the TLSSocket. Only the calling task
waits; Task.timeout and cancel interrupt the handshake, closing
the connection. Raises TLS::CertificateError when the peer's
certificate is refused, TLS::Error for another failure.
def self.accept(socket: TCPSocket, config: TLS::ServerConfig) -> TLSSocket
Takes socket (an accepted connection) over and runs the TLS
handshake with its peer as the server, as config says. As connect
does: when it returns, the handshake is done, socket is closed for
the program, only the calling task waits, and Task.timeout and
cancel interrupt it, closing the connection. Raises TLS::Error
when the handshake fails (the client refused the certificate, spoke
something else than TLS, shared no protocol version), and the
socket's SystemCallError or IOError when the connection does (a
reset); the connection is closed. The same as
config.accept(socket).
config = TLS::ServerConfig.new(certificate: File.read("server.pem"),
private_key: File.read("server.key"))
listener = TCPServer.new("0.0.0.0", 8443)
loop do
sock = listener.accept
Task.spawn do
tls = TLSSocket.accept(sock, config)
tls.puts "hello"
tls.close
end
end
Methods
def alpn -> String?
The protocol agreed on by ALPN ("h2", "http/1.1"), nil when none
was.
def peer_certificate -> Bytes?
The peer's certificate (DER), nil when it sent none (a server's peer sends none: client certificates are not asked for).
def verified? -> Bool
Whether the peer was authenticated by its certificate: false with
verify: false in the config, and on the server's side (no client
certificate is asked for).
def server_name -> String?
The server's name: the one given to connect; on the server's side,
the one the client sent (SNI), nil when it sent none.