src/​examples/​cpp03/​ssl/​server.​cppsrc/​examples/​cpp11/​ssl/​server.​cpp
⋮⋮
1 /​/​1 /​/​
2 /​/​·​server.​cpp2 /​/​·​server.​cpp
3 /​/​·​~~~~~~~~~~3 /​/​·​~~~~~~~~~~
4 /​/​4 /​/​
5 /​/​·​Copyright·​(c)​·​2003-​2022·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​5 /​/​·​Copyright·​(c)​·​2003-​2022·​Christopher·​M.​·​Kohlhoff·​(chris·​at·​kohlhoff·​dot·​com)​
6 /​/​6 /​/​
7 /​/​·​Distributed·​under·​the·​Boost·​Software·​License,​·​Version·​1.​0.​·​(See·​accompanying7 /​/​·​Distributed·​under·​the·​Boost·​Software·​License,​·​Version·​1.​0.​·​(See·​accompanying
8 /​/​·​file·​LICENSE_1_0.​txt·​or·​copy·​at·​http:​/​/​www.​boost.​org/​LICENSE_1_0.​txt)​8 /​/​·​file·​LICENSE_1_0.​txt·​or·​copy·​at·​http:​/​/​www.​boost.​org/​LICENSE_1_0.​txt)​
9 /​/​9 /​/​
10 10
11 #include·​<cstdlib>11 #include·​<cstdlib>
12 #include·​<functional>
12 #include·​<iostream>13 #include·​<iostream>
13 #include·​<boost/​bind/​bind.​hpp>
14 #include·​"asio.​hpp"14 #include·​"asio.​hpp"
15 #include·​"asio/​ssl.​hpp"15 #include·​"asio/​ssl.​hpp"
16 16
17 typedef·​asio:​:​ssl:​:​stream<asio:​:​ip:​:​tcp:​:​socket>·​ssl_socket;​17 using·​asio:​:​ip:​:​tcp;​
18 18
19 class·​session19 class·​session·​:​·​public·​std:​:​enable_shared_from_th​is<session>
20 {20 {
21 public:​21 public:​
22 ·​·​session(asio:​:​io_context&·​io_context,​22 ·​·​session(asio:​:​ssl:​:​stream<tcp:​:​socket>·​socket)​
23 ·​·​·​·​·​·​asio:​:​ssl:​:​context&·​context)​23 ·​·​·​·​:​·​socket_(std:​:​move(socket)​)​
24 ·​·​·​·​:​·​socket_(io_context,​·​context)​
25 ·​·​{24 ·​·​{
26 ·​·​}25 ·​·​}
27 26
28 ·​·​ssl_socket:​:​lowest_layer_type&·​socket()​
29 ·​·​{
30 ·​·​·​·​return·​socket_.​lowest_layer()​;​
31 ·​·​}
32
33 ·​·​void·​start()​27 ·​·​void·​start()​
34 ·​·​{28 ·​·​{
35 ·​·​·​·​socket_.​async_handshake(asio:​:​ssl:​:​stream_base:​:​server,​29 ·​·​·​·​do_handshake()​;​
36 ·​·​·​·​·​·​·​·​boost:​:​bind(&session:​:​handle_handshake,​·​this,​
37 ·​·​·​·​·​·​·​·​·​·​asio:​:​placeholders:​:​error)​)​;​
38 ·​·​}
39
40 ·​·​void·​handle_handshake(cons​t·​asio:​:​error_code&·​error)​
41 ·​·​{
42 ·​·​·​·​if·​(!error)​
43 ·​·​·​·​{
44 ·​·​·​·​·​·​socket_.​async_read_some(asio:​:​buffer(data_,​·​max_length)​,​
45 ·​·​·​·​·​·​·​·​·​·​boost:​:​bind(&session:​:​handle_read,​·​this,​
46 ·​·​·​·​·​·​·​·​·​·​·​·​asio:​:​placeholders:​:​error,​
47 ·​·​·​·​·​·​·​·​·​·​·​·​asio:​:​placeholders:​:​bytes_transferred)​)​;​
48 ·​·​·​·​}
49 ·​·​·​·​else
50 ·​·​·​·​{
51 ·​·​·​·​·​·​delete·​this;​
52 ·​·​·​·​}
53 ·​·​}
54
55 ·​·​void·​handle_read(const·​asio:​:​error_code&·​error,​
56 ·​·​·​·​·​·​size_t·​bytes_transferred)​
57 ·​·​{
58 ·​·​·​·​if·​(!error)​
59 ·​·​·​·​{
60 ·​·​·​·​·​·​asio:​:​async_write(socket_,​
61 ·​·​·​·​·​·​·​·​·​·​asio:​:​buffer(data_,​·​bytes_transferred)​,​
62 ·​·​·​·​·​·​·​·​·​·​boost:​:​bind(&session:​:​handle_write,​·​this,​
63 ·​·​·​·​·​·​·​·​·​·​·​·​asio:​:​placeholders:​:​error)​)​;​
64 ·​·​·​·​}
65 ·​·​·​·​else
66 ·​·​·​·​{
67 ·​·​·​·​·​·​delete·​this;​
68 ·​·​·​·​}
69 ·​·​}30 ·​·​}
70 31
71 ·​·​void·​handle_write(const·​asio:​:​error_code&·​error)​32 private:​
33 ·​·​void·​do_handshake()​
72 ·​·​{34 ·​·​{
73 ·​·​·​·​if·​(!error)​35 ·​·​·​·​auto·​self(shared_from_this​()​)​;​
74 ·​·​·​·​{36 ·​·​·​·​socket_.​async_handshake(asio:​:​ssl:​:​stream_base:​:​server,​·​
75 ·​·​·​·​·​·​socket_.​async_read_some(asio:​:​buffer(data_,​·​max_length)​,​37 ·​·​·​·​·​·​·​·​[this,​·​self](const·​std:​:​error_code&·​error)​
76 ·​·​·​·​·​·​·​·​·​·​boost:​:​bind(&session:​:​handle_read,​·​this,​38 ·​·​·​·​·​·​·​·​{
77 ·​·​·​·​·​·​·​·​·​·​·​·​asio:​:​placeholders:​:​error,​39 ·​·​·​·​·​·​·​·​·​·​if·​(!error)​
78 ·​·​·​·​·​·​·​·​·​·​·​·​asio:​:​placeholders:​:​bytes_transferred)​)​;​40 ·​·​·​·​·​·​·​·​·​·​{
79 ·​·​·​·​}41 ·​·​·​·​·​·​·​·​·​·​·​·​do_read()​;​
80 ·​·​·​·​else42 ·​·​·​·​·​·​·​·​·​·​}
81 ·​·​·​·​{43 ·​·​·​·​·​·​·​·​})​;​
82 ·​·​·​·​·​·​delete·​this;​44 ·​·​}
83 ·​·​·​·​}45
46 ·​·​void·​do_read()​
47 ·​·​{
48 ·​·​·​·​auto·​self(shared_from_this​()​)​;​
49 ·​·​·​·​socket_.​async_read_some(asio:​:​buffer(data_)​,​
50 ·​·​·​·​·​·​·​·​[this,​·​self](const·​std:​:​error_code&·​ec,​·​std:​:​size_t·​length)​
51 ·​·​·​·​·​·​·​·​{
52 ·​·​·​·​·​·​·​·​·​·​if·​(!ec)​
53 ·​·​·​·​·​·​·​·​·​·​{
54 ·​·​·​·​·​·​·​·​·​·​·​·​do_write(length)​;​
55 ·​·​·​·​·​·​·​·​·​·​}
56 ·​·​·​·​·​·​·​·​})​;​
57 ·​·​}
58
59 ·​·​void·​do_write(std:​:​size_t·​length)​
60 ·​·​{
61 ·​·​·​·​auto·​self(shared_from_this​()​)​;​
62 ·​·​·​·​asio:​:​async_write(socket_,​·​asio:​:​buffer(data_,​·​length)​,​
63 ·​·​·​·​·​·​·​·​[this,​·​self](const·​std:​:​error_code&·​ec,​
64 ·​·​·​·​·​·​·​·​·​·​std:​:​size_t·​/​*length*/​)​
65 ·​·​·​·​·​·​·​·​{
66 ·​·​·​·​·​·​·​·​·​·​if·​(!ec)​
67 ·​·​·​·​·​·​·​·​·​·​{
68 ·​·​·​·​·​·​·​·​·​·​·​·​do_read()​;​
69 ·​·​·​·​·​·​·​·​·​·​}
70 ·​·​·​·​·​·​·​·​})​;​
84 ·​·​}71 ·​·​}
85 72
86 private:​73 ·​·​asio:​:​ssl:​:​stream<tcp:​:​socket>·​socket_;​
87 ·​·​ssl_socket·​socket_;​74 ·​·​char·​data_[1024];​
88 ·​·​enum·​{·​max_length·​=·​1024·​};​
89 ·​·​char·​data_[max_length];​
90 };​75 };​
91 76
92 class·​server77 class·​server
93 {78 {
94 public:​79 public:​
95 ·​·​server(asio:​:​io_context&·​io_context,​·​unsigned·​short·​port)​80 ·​·​server(asio:​:​io_context&·​io_context,​·​unsigned·​short·​port)​
96 ·​·​·​·​:​·​io_context_(io_contex​t)​,​81 ·​·​·​·​:​·​acceptor_(io_context,​·​tcp:​:​endpoint(tcp:​:​v4()​,​·​port)​)​,​
97 ·​·​·​·​·​·​acceptor_(io_context,​
98 ·​·​·​·​·​·​·​·​·​·​asio:​:​ip:​:​tcp:​:​endpoint(asio:​:​ip:​:​tcp:​:​v4()​,​·​port)​)​,​
99 ·​·​·​·​·​·​context_(asio:​:​ssl:​:​context:​:​sslv23)​82 ·​·​·​·​·​·​context_(asio:​:​ssl:​:​context:​:​sslv23)​
100 ·​·​{83 ·​·​{
101 ·​·​·​·​context_.​set_options(84 ·​·​·​·​context_.​set_options(
102 ·​·​·​·​·​·​·​·​asio:​:​ssl:​:​context:​:​default_workarounds85 ·​·​·​·​·​·​·​·​asio:​:​ssl:​:​context:​:​default_workarounds
103 ·​·​·​·​·​·​·​·​|·​asio:​:​ssl:​:​context:​:​no_sslv286 ·​·​·​·​·​·​·​·​|·​asio:​:​ssl:​:​context:​:​no_sslv2
104 ·​·​·​·​·​·​·​·​|·​asio:​:​ssl:​:​context:​:​single_dh_use)​;​87 ·​·​·​·​·​·​·​·​|·​asio:​:​ssl:​:​context:​:​single_dh_use)​;​
105 ·​·​·​·​context_.​set_password_callback​(boost:​:​bind(&server:​:​get_password,​·​this)​)​;​88 ·​·​·​·​context_.​set_password_callback​(std:​:​bind(&server:​:​get_password,​·​this)​)​;​
106 ·​·​·​·​context_.​use_certificate_chain​_file("server.​pem")​;​89 ·​·​·​·​context_.​use_certificate_chain​_file("server.​pem")​;​
107 ·​·​·​·​context_.​use_private_key_file(​"server.​pem",​·​asio:​:​ssl:​:​context:​:​pem)​;​90 ·​·​·​·​context_.​use_private_key_file(​"server.​pem",​·​asio:​:​ssl:​:​context:​:​pem)​;​
108 ·​·​·​·​context_.​use_tmp_dh_file("dh40​96.​pem")​;​91 ·​·​·​·​context_.​use_tmp_dh_file("dh40​96.​pem")​;​
109 92
110 ·​·​·​·​start_accept()​;​93 ·​·​·​·​do_accept()​;​
111 ·​·​}94 ·​·​}
112 95
96 private:​
113 ·​·​std:​:​string·​get_password()​·​const97 ·​·​std:​:​string·​get_password()​·​const
114 ·​·​{98 ·​·​{
115 ·​·​·​·​return·​"test";​99 ·​·​·​·​return·​"test";​
116 ·​·​}100 ·​·​}
117 101
118 ·​·​void·​start_accept()​102 ·​·​void·​do_accept()​
119 ·​·​{103 ·​·​{
120 ·​·​·​·​session*·​new_session·​=·​new·​session(io_context_,​·​context_)​;​104 ·​·​·​·​acceptor_.​async_accept(
121 ·​·​·​·​acceptor_.​async_accept(new_sess​ion-​>socket()​,​105 ·​·​·​·​·​·​·​·​[this](const·​std:​:​error_code&·​error,​·​tcp:​:​socket·​socket)​
122 ·​·​·​·​·​·​·​·​boost:​:​bind(&server:​:​handle_accept,​·​this,​·​new_session,​106 ·​·​·​·​·​·​·​·​{
123 ·​·​·​·​·​·​·​·​·​·​asio:​:​placeholders:​:​error)​)​;​107 ·​·​·​·​·​·​·​·​·​·​if·​(!error)​
124 ·​·​}108 ·​·​·​·​·​·​·​·​·​·​{
125 109 ·​·​·​·​·​·​·​·​·​·​·​·​std:​:​make_shared<session>(​
126 ·​·​void·​handle_accept(session​*·​new_session,​110 ·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​asio:​:​ssl:​:​stream<tcp:​:​socket>(
127 ·​·​·​·​·​·​const·​asio:​:​error_code&·​error)​111 ·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​·​std:​:​move(socket)​,​·​context_)​)​-​>start()​;​
128 ·​·​{112 ·​·​·​·​·​·​·​·​·​·​}
129 ·​·​·​·​if·​(!error)​
130 ·​·​·​·​{
131 ·​·​·​·​·​·​new_session-​>start()​;​
132 ·​·​·​·​}
133 ·​·​·​·​else
134 ·​·​·​·​{
135 ·​·​·​·​·​·​delete·​new_session;​
136 ·​·​·​·​}
137 113
138 ·​·​·​·​start_accept()​;​114 ·​·​·​·​·​·​·​·​·​·​do_accept()​;​
115 ·​·​·​·​·​·​·​·​})​;​
139 ·​·​}116 ·​·​}
140 117
141 private:​118 ·​·​tcp:​:​acceptor·​acceptor_;​
142 ·​·​asio:​:​io_context&·​io_context_;​
143 ·​·​asio:​:​ip:​:​tcp:​:​acceptor·​acceptor_;​
144 ·​·​asio:​:​ssl:​:​context·​context_;​119 ·​·​asio:​:​ssl:​:​context·​context_;​
145 };​120 };​
146 121
147 int·​main(int·​argc,​·​char*·​argv[])​122 int·​main(int·​argc,​·​char*·​argv[])​
148 {123 {
149 ·​·​try124 ·​·​try
150 ·​·​{125 ·​·​{
151 ·​·​·​·​if·​(argc·​!=·​2)​126 ·​·​·​·​if·​(argc·​!=·​2)​
152 ·​·​·​·​{127 ·​·​·​·​{
153 ·​·​·​·​·​·​std:​:​cerr·​<<·​"Usage:​·​server·​<port>\n";​128 ·​·​·​·​·​·​std:​:​cerr·​<<·​"Usage:​·​server·​<port>\n";​
154 ·​·​·​·​·​·​return·​1;​129 ·​·​·​·​·​·​return·​1;​
155 ·​·​·​·​}130 ·​·​·​·​}
156 131
157 ·​·​·​·​asio:​:​io_context·​io_context;​132 ·​·​·​·​asio:​:​io_context·​io_context;​
158 133
159 ·​·​·​·​using·​namespace·​std;​·​/​/​·​For·​atoi.​134 ·​·​·​·​using·​namespace·​std;​·​/​/​·​For·​atoi.​
160 ·​·​·​·​server·​s(io_context,​·​atoi(argv[1])​)​;​135 ·​·​·​·​server·​s(io_context,​·​atoi(argv[1])​)​;​
161 136
162 ·​·​·​·​io_context.​run()​;​137 ·​·​·​·​io_context.​run()​;​
163 ·​·​}138 ·​·​}
164 ·​·​catch·​(std:​:​exception&·​e)​139 ·​·​catch·​(std:​:​exception&·​e)​
165 ·​·​{140 ·​·​{
166 ·​·​·​·​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​141 ·​·​·​·​std:​:​cerr·​<<·​"Exception:​·​"·​<<·​e.​what()​·​<<·​"\n";​
167 ·​·​}142 ·​·​}
168 143
169 ·​·​return·​0;​144 ·​·​return·​0;​
170 }145 }