-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
server.cr
89 lines (76 loc) · 2.69 KB
/
server.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
require "socket"
# This class wraps another `::Socket::Server` in an SSL layer.
#
# ```
# require "socket"
# require "openssl"
#
# tcp_server = TCPServer.new(0)
#
# ssl_context = OpenSSL::SSL::Context::Server.new
# ssl_context.certificate_chain = "openssl.crt"
# ssl_context.private_key = "openssl.key"
# ssl_server = OpenSSL::SSL::Server.new(tcp_server, ssl_context)
#
# puts "SSL Server listening on #{tcp_server.local_address}"
# while connection = ssl_server.accept?
# connection.puts "secure message"
# connection.close
# end
# ```
class OpenSSL::SSL::Server
include ::Socket::Server
# Returns the wrapped server socket.
getter wrapped : ::Socket::Server
# Returns the SSL context.
getter context : OpenSSL::SSL::Context::Server
# If `#sync_close?` is `true`, closing this server will
# close the wrapped server.
property? sync_close : Bool
# Returns `true` if this SSL server has been closed.
getter? closed : Bool = false
# Creates a new SSL server wrapping *wrapped*.
#
# *context* configures the SSL options, see `OpenSSL::SSL::Context::Server` for details
def initialize(@wrapped : ::Socket::Server, @context : OpenSSL::SSL::Context::Server = OpenSSL::SSL::Context::Server.new, @sync_close : Bool = true)
end
# Creates a new SSL server wrapping *wrapped* and yields it to the block.
#
# *context* configures the SSL options, see `OpenSSL::SSL::Context::Server` for details
#
# The server is closed after the block returns.
def self.open(wrapped : ::Socket::Server, context : OpenSSL::SSL::Context::Server = OpenSSL::SSL::Context::Server.new, sync_close : Bool = true)
server = new(wrapped, context, sync_close)
begin
yield server
ensure
server.close
end
end
# Implements `::Socket::Server#accept`.
#
# This method calls `@wrapped.accept` and wraps the resulting IO in a SSL socket (`OpenSSL::SSL::Socket::Server`) with `context` configuration.
def accept : OpenSSL::SSL::Socket::Server
OpenSSL::SSL::Socket::Server.new(@wrapped.accept, @context, sync_close: @sync_close)
end
# Implements `::Socket::Server#accept?`.
#
# This method calls `@wrapped.accept?` and wraps the resulting IO in a SSL socket (`OpenSSL::SSL::Socket::Server`) with `context` configuration.
def accept? : OpenSSL::SSL::Socket::Server?
if socket = @wrapped.accept?
OpenSSL::SSL::Socket::Server.new(socket, @context, sync_close: @sync_close)
end
end
# Closes this SSL server.
#
# Propagates to `wrapped` if `sync_close` is `true`.
def close
return if @closed
@closed = true
@wrapped.close if @sync_close
end
# Returns local address of `wrapped`.
def local_address : ::Socket::Address
@wrapped.local_address
end
end