-
Notifications
You must be signed in to change notification settings - Fork 2
/
ssl.cpp
executable file
·143 lines (121 loc) · 3.62 KB
/
ssl.cpp
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "net_service.h"
#include "ssl_socket.h"
#include <iostream>
#include <stdio.h>
class ssl_client
{
public:
ssl_client(iocp::service &service, ssl::context &ctx): socket_(ctx, service), addr(0U) {}
iocp::ssl_socket &socket() { return socket_; }
static void connect(void *tp, const iocp::error_code &ec)
{
ssl_client *client = static_cast<ssl_client *>(tp);
client->socket_.asyn_connect(client->addr, client->port, &ssl_client::on_connect, client);
}
static void on_connect(void *tp, const iocp::error_code &ec)
{
ssl_client *client = static_cast<ssl_client *>(tp);
puts("connected");
if (ec) {
std::cout << ec.to_string() << std::endl;
}
else {
client->socket_.asyn_handshake(ssl::client, &ssl_client::on_handshake, client);
}
}
static void on_handshake(void *tp, const iocp::error_code &ec)
{
ssl_client *client = static_cast<ssl_client *>(tp);
puts("client hanshaked");
if (ec) {
std::cout << ec.to_string() << std::endl;
}
else {
client->socket_.asyn_send("hello", 5, &ssl_client::on_send, client);
}
}
static void on_send(void *tp, const iocp::error_code &ec, size_t bytes_transferred)
{
ssl_client *client = static_cast<ssl_client *>(tp);
if (ec) {
std::cout << ec.to_string() << std::endl;
}
else {
//client->socket_.shutdown(); // TODO:
}
}
iocp::address addr;
unsigned short port;
private:
iocp::ssl_socket socket_;
};
class ssl_server
{
public:
ssl_server(iocp::service &service, ssl::context &ctx): socket_(ctx, service) {}
iocp::ssl_socket &socket() { return socket_; }
void handshake()
{
socket_.asyn_handshake(ssl::server, &ssl_server::on_handshake, this);
}
static void on_handshake(void *tp, const iocp::error_code &ec)
{
ssl_server *server = static_cast<ssl_server *>(tp);
puts("server handshaked");
if (ec) {
std::cout << ec.to_string() << std::endl;
}
else {
server->socket_.asyn_recv(server->buf_, 5, &ssl_server::on_recv, server);
}
}
static void on_recv(void *tp, const iocp::error_code &ec, size_t bytes_transferred, char *buf)
{
ssl_server *server = static_cast<ssl_server *>(tp);
if (ec) {
std::cout << ec.to_string() << std::endl;
}
else {
printf("%.*s\n", (int)bytes_transferred, buf);
//server->socket_.shutdown(); // TODO: shutdown
}
}
private:
iocp::ssl_socket socket_;
char buf_[5];
};
void on_ssl_accept(void *acceptor_point, const iocp::error_code &ec, void *socket_point)
{
ssl_server *server = static_cast<ssl_server *>(socket_point);
puts("accepted");
if (ec) {
std::cout << ec.to_string() << std::endl;
}
else {
server->handshake();
}
}
void ssl_example()
{
ssl::init(); // don't forget
ssl::context server_ctx(ssl::sslv23_server), client_ctx(ssl::sslv23_client);
server_ctx.use_certificate_file("chain.pem", ssl::pem);
server_ctx.use_rsa_private_key_file("privkey.pem", ssl::pem);
iocp::service svr;
iocp::acceptor acceptor(svr);
// iocp::address(0U) or iocp::address("0.0.0.0") alse work
iocp::error_code ec = acceptor.bind_and_listen(iocp::address::any, 60000, 10);
if (ec) {
std::cout << ec.to_string() << std::endl;
return;
}
ssl_server server(svr, server_ctx);
acceptor.asyn_accept(server.socket(), &server, on_ssl_accept, &acceptor);
ssl_client client(svr, client_ctx);
client.addr = iocp::address::loopback;
client.port = 60000;
client.socket().service().post(&ssl_client::connect, &client);
size_t result = svr.run(ec);
std::cout << "finished " << result << " operations" << std::endl;
std::cout << ec.to_string() << std::endl;
}