12c01beb4SShuo Chen#include <muduo/net/Buffer.h> 22c01beb4SShuo Chen 32c01beb4SShuo Chen#include <stdio.h> 42c01beb4SShuo Chen 52c01beb4SShuo Chen#include <tls.h> 62c01beb4SShuo Chen 72c01beb4SShuo Chen#include "timer.h" 82c01beb4SShuo Chen 92c01beb4SShuo Chenmuduo::net::Buffer clientOut, serverOut; 10d9e55939SShuo Chenint64_t clientWrite, serverWrite; 112c01beb4SShuo Chen 122c01beb4SShuo Chenssize_t net_read(struct tls *ctx, void *buf, size_t len, void *arg) 132c01beb4SShuo Chen{ 142c01beb4SShuo Chen muduo::net::Buffer* in = ((arg == &clientOut) ? &serverOut : &clientOut); 152c01beb4SShuo Chen if (in->readableBytes() > 0) 162c01beb4SShuo Chen { 172c01beb4SShuo Chen size_t n = std::min(in->readableBytes(), len); 182c01beb4SShuo Chen memcpy(buf, in->peek(), n); 192c01beb4SShuo Chen in->retrieve(n); 202c01beb4SShuo Chen return n; 212c01beb4SShuo Chen } 222c01beb4SShuo Chen else 232c01beb4SShuo Chen { 242c01beb4SShuo Chen return TLS_WANT_POLLIN; 252c01beb4SShuo Chen } 262c01beb4SShuo Chen} 272c01beb4SShuo Chen 282c01beb4SShuo Chenssize_t net_write(struct tls *ctx, const void *buf, size_t len, void *arg) 292c01beb4SShuo Chen{ 302c01beb4SShuo Chen muduo::net::Buffer* out = static_cast<muduo::net::Buffer*>(arg); 31d9e55939SShuo Chen int64_t& wr = (out == &clientOut ? clientWrite : serverWrite); 32d9e55939SShuo Chen wr += len; 332c01beb4SShuo Chen out->append(buf, len); 342c01beb4SShuo Chen return len; 352c01beb4SShuo Chen} 362c01beb4SShuo Chen 372c01beb4SShuo Chenstruct tls* client() 382c01beb4SShuo Chen{ 392c01beb4SShuo Chen struct tls_config* cfg = tls_config_new(); 402c01beb4SShuo Chen assert(cfg != NULL); 412c01beb4SShuo Chen 42cc4062ffSShuo Chen // symlink to libressl/tests/ca.pem 432c01beb4SShuo Chen tls_config_set_ca_file(cfg, "ca.pem"); 442c01beb4SShuo Chen // tls_config_insecure_noverifycert(cfg); 452c01beb4SShuo Chen // tls_config_insecure_noverifyname(cfg); 462c01beb4SShuo Chen 472c01beb4SShuo Chen struct tls* ctx = tls_client(); 482c01beb4SShuo Chen assert(ctx != NULL); 492c01beb4SShuo Chen 502c01beb4SShuo Chen int ret = tls_configure(ctx, cfg); 512c01beb4SShuo Chen assert(ret == 0); 522c01beb4SShuo Chen 532c01beb4SShuo Chen tls_connect_cbs(ctx, net_read, net_write, &clientOut, "Test Server Cert"); 542c01beb4SShuo Chen 552c01beb4SShuo Chen return ctx; 562c01beb4SShuo Chen} 572c01beb4SShuo Chen 582c01beb4SShuo Chenstruct tls* server() 592c01beb4SShuo Chen{ 602c01beb4SShuo Chen struct tls_config* cfg = tls_config_new(); 612c01beb4SShuo Chen assert(cfg != NULL); 622c01beb4SShuo Chen 632c01beb4SShuo Chen int ret = tls_config_set_cert_file(cfg, "server.pem"); 642c01beb4SShuo Chen assert(ret == 0); 652c01beb4SShuo Chen 662c01beb4SShuo Chen ret = tls_config_set_key_file(cfg, "server.pem"); 672c01beb4SShuo Chen assert(ret == 0); 682c01beb4SShuo Chen 69b140ba61SShuo Chen ret = tls_config_set_ecdhecurve(cfg, "prime256v1"); 70b140ba61SShuo Chen assert(ret == 0); 71b140ba61SShuo Chen 722c01beb4SShuo Chen // tls_config_verify_client_optional(cfg); 732c01beb4SShuo Chen struct tls* ctx = tls_server(); 742c01beb4SShuo Chen assert(ctx != NULL); 752c01beb4SShuo Chen 762c01beb4SShuo Chen ret = tls_configure(ctx, cfg); 772c01beb4SShuo Chen assert(ret == 0); 782c01beb4SShuo Chen 792c01beb4SShuo Chen struct tls* conn_ctx = NULL; 802c01beb4SShuo Chen tls_accept_cbs(ctx, &conn_ctx, net_read, net_write, &serverOut); 812c01beb4SShuo Chen return conn_ctx; 822c01beb4SShuo Chen} 832c01beb4SShuo Chen 842c01beb4SShuo ChenTimer tclient, tserver; 852c01beb4SShuo Chen 86cc4062ffSShuo Chenbool handshake(struct tls* cctx, struct tls* sctx) 872c01beb4SShuo Chen{ 882c01beb4SShuo Chen int client_done = false, server_done = false; 892c01beb4SShuo Chen while (!(client_done && server_done)) 902c01beb4SShuo Chen { 912c01beb4SShuo Chen if (!client_done) 922c01beb4SShuo Chen { 932c01beb4SShuo Chen tclient.start(); 942c01beb4SShuo Chen int ret = tls_handshake(cctx); 952c01beb4SShuo Chen tclient.stop(); 962c01beb4SShuo Chen // printf("c %d\n", ret); 972c01beb4SShuo Chen if (ret == 0) 982c01beb4SShuo Chen client_done = true; 992c01beb4SShuo Chen else if (ret == -1) 100cc4062ffSShuo Chen { 101cc4062ffSShuo Chen printf("client handshake failed: %s\n", tls_error(cctx)); 1022c01beb4SShuo Chen break; 103cc4062ffSShuo Chen } 1042c01beb4SShuo Chen } 1052c01beb4SShuo Chen 1062c01beb4SShuo Chen if (!server_done) 1072c01beb4SShuo Chen { 1082c01beb4SShuo Chen tserver.start(); 1092c01beb4SShuo Chen int ret = tls_handshake(sctx); 1102c01beb4SShuo Chen tserver.stop(); 1112c01beb4SShuo Chen // printf("s %d\n", ret); 1122c01beb4SShuo Chen if (ret == 0) 1132c01beb4SShuo Chen server_done = true; 1142c01beb4SShuo Chen else if (ret == -1) 115cc4062ffSShuo Chen { 116cc4062ffSShuo Chen printf("server handshake failed: %s\n", tls_error(sctx)); 1172c01beb4SShuo Chen break; 118cc4062ffSShuo Chen } 1192c01beb4SShuo Chen } 1202c01beb4SShuo Chen } 121cc4062ffSShuo Chen return client_done && server_done; 1222c01beb4SShuo Chen} 1232c01beb4SShuo Chen 124d9e55939SShuo Chenvoid throughput(int block_size, struct tls* cctx, struct tls* sctx) 125d9e55939SShuo Chen{ 126d9e55939SShuo Chen double start = now(); 127d9e55939SShuo Chen int total = 0; 128d9e55939SShuo Chen int batch = 1024; 129d9e55939SShuo Chen char* message = new char[block_size]; 130d9e55939SShuo Chen bzero(message, block_size); 131d9e55939SShuo Chen clientWrite = 0; 132d9e55939SShuo Chen tclient.reset(); 133d9e55939SShuo Chen tserver.reset(); 134d9e55939SShuo Chen while (now() - start < 10) 135d9e55939SShuo Chen { 136d9e55939SShuo Chen for (int i = 0; i < batch; ++i) 137d9e55939SShuo Chen { 138d9e55939SShuo Chen tclient.start(); 139d9e55939SShuo Chen int nw = tls_write(cctx, message, block_size); 140d9e55939SShuo Chen tclient.stop(); 141d9e55939SShuo Chen assert(nw == block_size); 142d9e55939SShuo Chen tserver.start(); 143d9e55939SShuo Chen int nr = tls_read(sctx, message, block_size); 144d9e55939SShuo Chen tserver.stop(); 145d9e55939SShuo Chen assert(nr == block_size); 146d9e55939SShuo Chen } 147d9e55939SShuo Chen total += batch; 148d9e55939SShuo Chen batch *= 2; 149d9e55939SShuo Chen } 150d9e55939SShuo Chen double secs = now() - start; 151d9e55939SShuo Chen // throughput is half of real value, because client and server share one core. 152d9e55939SShuo Chen printf("bs %5d sec %.3f tot %d thr %.1fKB/s wr %.2fB client %.3f server %.3f\n", block_size, secs, total, 153d9e55939SShuo Chen block_size / secs * total / 1024, clientWrite * 1.0 / total, tclient.seconds(), tserver.seconds()); 154926c960eSShuo Chen delete[] message; 155d9e55939SShuo Chen} 156d9e55939SShuo Chen 1572c01beb4SShuo Chenint main(int argc, char* argv[]) 1582c01beb4SShuo Chen{ 1592c01beb4SShuo Chen int ret = tls_init(); 1602c01beb4SShuo Chen assert(ret == 0); 1612c01beb4SShuo Chen 1622c01beb4SShuo Chen struct tls* cctx = client(); 1632c01beb4SShuo Chen struct tls* sctx = server(); 1642c01beb4SShuo Chen 165cc4062ffSShuo Chen const int N = 1000; 1662c01beb4SShuo Chen Timer all, client, server; 1672c01beb4SShuo Chen all.start(); 1682c01beb4SShuo Chen for (int i = 0; i < N; ++i) 1692c01beb4SShuo Chen { 170cc4062ffSShuo Chen if (!handshake(cctx, sctx)) 171cc4062ffSShuo Chen return -1; 1722c01beb4SShuo Chen 1732c01beb4SShuo Chen if (i == 0) 1742c01beb4SShuo Chen printf("cipher %s\n", tls_conn_cipher(cctx)); 1752c01beb4SShuo Chen } 1762c01beb4SShuo Chen all.stop(); 1772c01beb4SShuo Chen printf("%f secs, %f handshakes/sec\n", all.seconds(), N / all.seconds()); 1782c01beb4SShuo Chen printf("client %f secs, server %f secs\n", tclient.seconds(), tserver.seconds()); 179d9e55939SShuo Chen 180cc4062ffSShuo Chen for (int i = 1024 * 16; i >= 1; i /= 4) 181d9e55939SShuo Chen { 182d9e55939SShuo Chen throughput(i, cctx, sctx); 183d9e55939SShuo Chen } 1842c01beb4SShuo Chen} 1852c01beb4SShuo Chen 186