1#include <muduo/net/Buffer.h> 2 3#include <stdio.h> 4 5#include <tls.h> 6 7#include "timer.h" 8 9muduo::net::Buffer clientOut, serverOut; 10int64_t clientWrite, serverWrite; 11 12ssize_t net_read(struct tls *ctx, void *buf, size_t len, void *arg) 13{ 14 muduo::net::Buffer* in = ((arg == &clientOut) ? &serverOut : &clientOut); 15 if (in->readableBytes() > 0) 16 { 17 size_t n = std::min(in->readableBytes(), len); 18 memcpy(buf, in->peek(), n); 19 in->retrieve(n); 20 return n; 21 } 22 else 23 { 24 return TLS_WANT_POLLIN; 25 } 26} 27 28ssize_t net_write(struct tls *ctx, const void *buf, size_t len, void *arg) 29{ 30 muduo::net::Buffer* out = static_cast<muduo::net::Buffer*>(arg); 31 int64_t& wr = (out == &clientOut ? clientWrite : serverWrite); 32 wr += len; 33 out->append(buf, len); 34 return len; 35} 36 37struct tls* client() 38{ 39 struct tls_config* cfg = tls_config_new(); 40 assert(cfg != NULL); 41 42 // symlink to libressl/tests/ca.pem 43 tls_config_set_ca_file(cfg, "ca.pem"); 44 // tls_config_insecure_noverifycert(cfg); 45 // tls_config_insecure_noverifyname(cfg); 46 47 struct tls* ctx = tls_client(); 48 assert(ctx != NULL); 49 50 int ret = tls_configure(ctx, cfg); 51 assert(ret == 0); 52 53 tls_connect_cbs(ctx, net_read, net_write, &clientOut, "Test Server Cert"); 54 55 return ctx; 56} 57 58struct tls* server() 59{ 60 struct tls_config* cfg = tls_config_new(); 61 assert(cfg != NULL); 62 63 int ret = tls_config_set_cert_file(cfg, "server.pem"); 64 assert(ret == 0); 65 66 ret = tls_config_set_key_file(cfg, "server.pem"); 67 assert(ret == 0); 68 69 ret = tls_config_set_ecdhecurve(cfg, "prime256v1"); 70 assert(ret == 0); 71 72 // tls_config_verify_client_optional(cfg); 73 struct tls* ctx = tls_server(); 74 assert(ctx != NULL); 75 76 ret = tls_configure(ctx, cfg); 77 assert(ret == 0); 78 79 struct tls* conn_ctx = NULL; 80 tls_accept_cbs(ctx, &conn_ctx, net_read, net_write, &serverOut); 81 return conn_ctx; 82} 83 84Timer tclient, tserver; 85 86bool handshake(struct tls* cctx, struct tls* sctx) 87{ 88 int client_done = false, server_done = false; 89 while (!(client_done && server_done)) 90 { 91 if (!client_done) 92 { 93 tclient.start(); 94 int ret = tls_handshake(cctx); 95 tclient.stop(); 96 // printf("c %d\n", ret); 97 if (ret == 0) 98 client_done = true; 99 else if (ret == -1) 100 { 101 printf("client handshake failed: %s\n", tls_error(cctx)); 102 break; 103 } 104 } 105 106 if (!server_done) 107 { 108 tserver.start(); 109 int ret = tls_handshake(sctx); 110 tserver.stop(); 111 // printf("s %d\n", ret); 112 if (ret == 0) 113 server_done = true; 114 else if (ret == -1) 115 { 116 printf("server handshake failed: %s\n", tls_error(sctx)); 117 break; 118 } 119 } 120 } 121 return client_done && server_done; 122} 123 124void throughput(int block_size, struct tls* cctx, struct tls* sctx) 125{ 126 double start = now(); 127 int total = 0; 128 int batch = 1024; 129 char* message = new char[block_size]; 130 bzero(message, block_size); 131 clientWrite = 0; 132 tclient.reset(); 133 tserver.reset(); 134 while (now() - start < 10) 135 { 136 for (int i = 0; i < batch; ++i) 137 { 138 tclient.start(); 139 int nw = tls_write(cctx, message, block_size); 140 tclient.stop(); 141 assert(nw == block_size); 142 tserver.start(); 143 int nr = tls_read(sctx, message, block_size); 144 tserver.stop(); 145 assert(nr == block_size); 146 } 147 total += batch; 148 batch *= 2; 149 } 150 double secs = now() - start; 151 // throughput is half of real value, because client and server share one core. 152 printf("bs %5d sec %.3f tot %d thr %.1fKB/s wr %.2fB client %.3f server %.3f\n", block_size, secs, total, 153 block_size / secs * total / 1024, clientWrite * 1.0 / total, tclient.seconds(), tserver.seconds()); 154 delete[] message; 155} 156 157int main(int argc, char* argv[]) 158{ 159 int ret = tls_init(); 160 assert(ret == 0); 161 162 struct tls* cctx = client(); 163 struct tls* sctx = server(); 164 165 const int N = 1000; 166 Timer all, client, server; 167 all.start(); 168 for (int i = 0; i < N; ++i) 169 { 170 if (!handshake(cctx, sctx)) 171 return -1; 172 173 if (i == 0) 174 printf("cipher %s\n", tls_conn_cipher(cctx)); 175 } 176 all.stop(); 177 printf("%f secs, %f handshakes/sec\n", all.seconds(), N / all.seconds()); 178 printf("client %f secs, server %f secs\n", tclient.seconds(), tserver.seconds()); 179 180 for (int i = 1024 * 16; i >= 1; i /= 4) 181 { 182 throughput(i, cctx, sctx); 183 } 184} 185 186