-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.hpp
128 lines (107 loc) · 3.8 KB
/
server.hpp
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
#include <arpa/inet.h>
#include <assert.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <chrono>
#include <iostream>
#include "net.hpp"
using namespace std;
using namespace chrono;
class Server {
private:
virtual void handle(string msg, SSL *ssl) = 0;
SSL_CTX *create_context() {
const SSL_METHOD *method;
SSL_CTX *ctx;
method = TLS_server_method();
ctx = SSL_CTX_new(method);
if (!ctx) {
perror("Unable to create SSL context");
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
return ctx;
}
void configure_context(SSL_CTX *ctx) {
/* Set the key and cert */
if (SSL_CTX_use_certificate_file(ctx, "cert.pem", SSL_FILETYPE_PEM) <=
0) {
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
if (SSL_CTX_use_PrivateKey_file(ctx, "key.pem", SSL_FILETYPE_PEM) <=
0) {
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
}
public:
Server() {}
void run(string ip, double time_period) {
int listen_fd = socket(PF_INET, SOCK_STREAM, 0);
int sock_opt;
assert(setsockopt(listen_fd, SOL_SOCKET,
TCP_NODELAY | SO_REUSEADDR | SO_REUSEPORT, &sock_opt,
sizeof(sock_opt)) >= 0);
struct sockaddr_in servaddr = string_to_struct_addr(ip);
assert(bind(listen_fd, (sockaddr *)&servaddr, sizeof(servaddr)) >= 0);
assert(listen(listen_fd, 100) >= 0);
// create and configure SSL context
SSL_CTX *ctx = create_context();
configure_context(ctx);
system_clock::time_point total_start, total_end;
bool started = false;
int handled_task = 0;
bool found = false;
system_clock::time_point start, end;
while (true) {
// accept for one connection
struct sockaddr_in clientaddr;
socklen_t clientaddrlen = sizeof(clientaddr);
int client_fd = accept(listen_fd, (struct sockaddr *)&clientaddr,
&clientaddrlen);
// establish tls connection
SSL *ssl = SSL_new(ctx);
SSL_set_fd(ssl, client_fd);
assert(SSL_accept(ssl) > 0);
string recv_msg;
start = system_clock::now();
if (!recvMsg(ssl, recv_msg)) {
cout << "receive msg fail\n";
continue;
}
if (!started) {
total_start = system_clock::now();
started = true;
}
// invoke handler function of server class
handle(recv_msg, ssl);
end = system_clock::now();
cout << "server handle time: "
<< duration_cast<std::chrono::duration<double>>(end - start)
.count()
<< endl;
handled_task++;
total_end = system_clock::now();
cout << "elapsed time: "
<< duration_cast<std::chrono::duration<double>>(total_end -
total_start)
.count()
<< ", handled task: " << handled_task << endl;
if (!found && duration_cast<std::chrono::duration<double>>(
total_end - total_start)
.count() > time_period) {
cout << "FOUND throughput " << handled_task << " per "
<< time_period << "s" << endl;
found = true;
}
SSL_shutdown(ssl);
SSL_free(ssl);
close(client_fd);
}
}
};