1926c960eSShuo Chen#include "timer.h" 2926c960eSShuo Chen#include "thread/Thread.h" 3926c960eSShuo Chen#include <boost/bind.hpp> 4926c960eSShuo Chen 542b85340SShuo Chen#include <assert.h> 6926c960eSShuo Chen#include <fcntl.h> 742b85340SShuo Chen#include <stdio.h> 842b85340SShuo Chen#include <sys/types.h> 942b85340SShuo Chen#include <sys/socket.h> 1042b85340SShuo Chen 1142b85340SShuo Chen#include <tls.h> 1242b85340SShuo Chen 1323a62999SShuo Chenstruct tls* client(int sockfd) 1442b85340SShuo Chen{ 1542b85340SShuo Chen struct tls_config* cfg = tls_config_new(); 1642b85340SShuo Chen assert(cfg != NULL); 1742b85340SShuo Chen 1842b85340SShuo Chen tls_config_set_ca_file(cfg, "ca.pem"); 1942b85340SShuo Chen // tls_config_insecure_noverifycert(cfg); 2042b85340SShuo Chen // tls_config_insecure_noverifyname(cfg); 2142b85340SShuo Chen 2242b85340SShuo Chen struct tls* ctx = tls_client(); 2342b85340SShuo Chen assert(ctx != NULL); 2442b85340SShuo Chen 2542b85340SShuo Chen int ret = tls_configure(ctx, cfg); 2642b85340SShuo Chen assert(ret == 0); 2742b85340SShuo Chen 2823a62999SShuo Chen ret = tls_connect_socket(ctx, sockfd, "Test Server Cert"); 2923a62999SShuo Chen assert(ret == 0); 3023a62999SShuo Chen 3142b85340SShuo Chen return ctx; 3242b85340SShuo Chen} 3342b85340SShuo Chen 3423a62999SShuo Chenstruct tls* server(int sockfd) 3542b85340SShuo Chen{ 3642b85340SShuo Chen struct tls_config* cfg = tls_config_new(); 3742b85340SShuo Chen assert(cfg != NULL); 3842b85340SShuo Chen 3923a62999SShuo Chen int ret = tls_config_set_cert_file(cfg, "server.pem"); 4042b85340SShuo Chen assert(ret == 0); 4142b85340SShuo Chen 4223a62999SShuo Chen ret = tls_config_set_key_file(cfg, "server.pem"); 4342b85340SShuo Chen assert(ret == 0); 4442b85340SShuo Chen 45b140ba61SShuo Chen ret = tls_config_set_ecdhecurve(cfg, "prime256v1"); 46b140ba61SShuo Chen assert(ret == 0); 47b140ba61SShuo Chen 48b140ba61SShuo Chen // tls_config_verify_client_optional(cfg); 4942b85340SShuo Chen struct tls* ctx = tls_server(); 5042b85340SShuo Chen assert(ctx != NULL); 5142b85340SShuo Chen 5242b85340SShuo Chen ret = tls_configure(ctx, cfg); 5342b85340SShuo Chen assert(ret == 0); 5442b85340SShuo Chen 5542b85340SShuo Chen struct tls* sctx = NULL; 5623a62999SShuo Chen ret = tls_accept_socket(ctx, &sctx, sockfd); 5723a62999SShuo Chen assert(ret == 0 && sctx != NULL); 5842b85340SShuo Chen 5923a62999SShuo Chen return sctx; 6023a62999SShuo Chen} 6123a62999SShuo Chen 62926c960eSShuo Chen// only works for non-blocking sockets 6323a62999SShuo Chenbool handshake(struct tls* cctx, struct tls* sctx) 6423a62999SShuo Chen{ 6523a62999SShuo Chen int client_done = false, server_done = false; 6623a62999SShuo Chen 6723a62999SShuo Chen while (!(client_done && server_done)) 6823a62999SShuo Chen { 6923a62999SShuo Chen if (!client_done) 7023a62999SShuo Chen { 7123a62999SShuo Chen int ret = tls_handshake(cctx); 72926c960eSShuo Chen // printf("c %d\n", ret); 7323a62999SShuo Chen if (ret == 0) 7423a62999SShuo Chen client_done = true; 7523a62999SShuo Chen else if (ret == -1) 7623a62999SShuo Chen { 7723a62999SShuo Chen printf("client handshake failed: %s\n", tls_error(cctx)); 7823a62999SShuo Chen break; 7923a62999SShuo Chen } 8023a62999SShuo Chen } 8123a62999SShuo Chen 8223a62999SShuo Chen if (!server_done) 8323a62999SShuo Chen { 8423a62999SShuo Chen int ret = tls_handshake(sctx); 85926c960eSShuo Chen // printf("s %d\n", ret); 8623a62999SShuo Chen if (ret == 0) 8723a62999SShuo Chen server_done = true; 8823a62999SShuo Chen else if (ret == -1) 8923a62999SShuo Chen { 90cc4062ffSShuo Chen printf("server handshake failed: %s\n", tls_error(sctx)); 9123a62999SShuo Chen break; 9223a62999SShuo Chen } 9323a62999SShuo Chen } 9423a62999SShuo Chen } 9523a62999SShuo Chen 9623a62999SShuo Chen return client_done && server_done; 9723a62999SShuo Chen} 9823a62999SShuo Chen 99926c960eSShuo Chenvoid setBlockingIO(int fd) 100926c960eSShuo Chen{ 101926c960eSShuo Chen int flags = fcntl(fd, F_GETFL, 0); 102926c960eSShuo Chen if (flags > 0) 103926c960eSShuo Chen { 104926c960eSShuo Chen printf("set blocking IO for %d\n", fd); 105926c960eSShuo Chen fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); 106926c960eSShuo Chen } 107926c960eSShuo Chen} 108926c960eSShuo Chen 109926c960eSShuo Chenconst int N = 500; 110926c960eSShuo Chen 111926c960eSShuo Chenstruct Trial 112926c960eSShuo Chen{ 113926c960eSShuo Chen int blocks, block_size; 114926c960eSShuo Chen}; 115926c960eSShuo Chen 116926c960eSShuo Chenvoid client_thread(struct tls* ctx) 117926c960eSShuo Chen{ 118926c960eSShuo Chen Timer t; 119926c960eSShuo Chen t.start(); 120926c960eSShuo Chen for (int i = 0; i < N; ++i) 121926c960eSShuo Chen { 122926c960eSShuo Chen int ret = tls_handshake(ctx); 123926c960eSShuo Chen if (ret != 0) 124926c960eSShuo Chen printf("client err = %d\n", ret); 125926c960eSShuo Chen } 126926c960eSShuo Chen t.stop(); 127926c960eSShuo Chen printf("client %f secs, %f handshakes/sec\n", t.seconds(), N / t.seconds()); 128926c960eSShuo Chen while (true) 129926c960eSShuo Chen { 130926c960eSShuo Chen Trial trial = { 0, 0 }; 131926c960eSShuo Chen 132926c960eSShuo Chen int nr = tls_read(ctx, &trial, sizeof trial); 133926c960eSShuo Chen if (nr == 0) 134926c960eSShuo Chen break; 135926c960eSShuo Chen assert(nr == sizeof trial); 136926c960eSShuo Chen // printf("client read bs %d nb %d\n", trial.block_size, trial.blocks); 137926c960eSShuo Chen if (trial.block_size == 0) 138926c960eSShuo Chen break; 139926c960eSShuo Chen char* buf = new char[trial.block_size]; 140926c960eSShuo Chen for (int i = 0; i < trial.blocks; ++i) 141926c960eSShuo Chen { 142926c960eSShuo Chen nr = tls_read(ctx, buf, trial.block_size); 143926c960eSShuo Chen assert(nr == trial.block_size); 144926c960eSShuo Chen } 145926c960eSShuo Chen int64_t ack = static_cast<int64_t>(trial.blocks) * trial.block_size; 146926c960eSShuo Chen int nw = tls_write(ctx, &ack, sizeof ack); 147926c960eSShuo Chen assert(nw == sizeof ack); 148926c960eSShuo Chen delete[] buf; 149926c960eSShuo Chen } 150926c960eSShuo Chen printf("client done\n"); 151926c960eSShuo Chen tls_close(ctx); 152926c960eSShuo Chen tls_free(ctx); 153926c960eSShuo Chen} 154926c960eSShuo Chen 155926c960eSShuo Chenvoid send(int block_size, struct tls* ctx) 156926c960eSShuo Chen{ 157926c960eSShuo Chen double start = now(); 158926c960eSShuo Chen int total = 0; 159926c960eSShuo Chen int blocks = 1024; 160926c960eSShuo Chen char* message = new char[block_size]; 161926c960eSShuo Chen bzero(message, block_size); 162926c960eSShuo Chen Timer t; 163926c960eSShuo Chen while (now() - start < 10) 164926c960eSShuo Chen { 165926c960eSShuo Chen Trial trial = { blocks, block_size }; 166926c960eSShuo Chen int nw = tls_write(ctx, &trial, sizeof trial); 167926c960eSShuo Chen assert(nw == sizeof trial); 168926c960eSShuo Chen t.start(); 169926c960eSShuo Chen for (int i = 0; i < blocks; ++i) 170926c960eSShuo Chen { 171926c960eSShuo Chen nw = tls_write(ctx, message, block_size); 172926c960eSShuo Chen if (nw != block_size) 173926c960eSShuo Chen printf("bs %d nw %d\n", block_size, nw); 174926c960eSShuo Chen assert(nw == block_size); 175926c960eSShuo Chen } 176926c960eSShuo Chen t.stop(); 177926c960eSShuo Chen int64_t ack = 0; 178926c960eSShuo Chen int nr = tls_read(ctx, &ack, sizeof ack); 179926c960eSShuo Chen assert(nr == sizeof ack); 180926c960eSShuo Chen assert(ack == static_cast<int64_t>(blocks) * block_size); 181926c960eSShuo Chen total += blocks; 182926c960eSShuo Chen blocks *= 2; 183926c960eSShuo Chen } 184926c960eSShuo Chen double secs = now() - start; 185926c960eSShuo Chen printf("bs %5d sec %.3f tot %d thr %.1fKB/s wr cpu %.3f\n", block_size, secs, total, 186926c960eSShuo Chen block_size / secs * total / 1024, t.seconds()); 187926c960eSShuo Chen delete[] message; 188926c960eSShuo Chen} 189926c960eSShuo Chen 19023a62999SShuo Chenint main(int argc, char* argv[]) 19123a62999SShuo Chen{ 19223a62999SShuo Chen int ret = tls_init(); 19342b85340SShuo Chen assert(ret == 0); 19442b85340SShuo Chen 19523a62999SShuo Chen int fds[2]; 19623a62999SShuo Chen socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fds); 19723a62999SShuo Chen 19823a62999SShuo Chen struct tls* cctx = client(fds[0]); 19923a62999SShuo Chen struct tls* sctx = server(fds[1]); 20042b85340SShuo Chen 20123a62999SShuo Chen if (handshake(cctx, sctx)) 20223a62999SShuo Chen printf("cipher %s\n", tls_conn_cipher(cctx)); 203cc4062ffSShuo Chen else 204cc4062ffSShuo Chen return -1; 205926c960eSShuo Chen 206926c960eSShuo Chen setBlockingIO(fds[0]); 207926c960eSShuo Chen setBlockingIO(fds[1]); 208926c960eSShuo Chen muduo::Thread thr(boost::bind(client_thread, cctx), "clientThread"); 209926c960eSShuo Chen thr.start(); 210926c960eSShuo Chen 211926c960eSShuo Chen { 212926c960eSShuo Chen Timer t; 213926c960eSShuo Chen t.start(); 214926c960eSShuo Chen for (int i = 0; i < N; ++i) 215926c960eSShuo Chen { 216926c960eSShuo Chen int ret = tls_handshake(sctx); 217926c960eSShuo Chen if (ret != 0) 218926c960eSShuo Chen printf("server err = %d\n", ret); 219926c960eSShuo Chen } 220926c960eSShuo Chen t.stop(); 221926c960eSShuo Chen printf("server %f secs, %f handshakes/sec\n", t.seconds(), N / t.seconds()); 222926c960eSShuo Chen } 223926c960eSShuo Chen 224cc4062ffSShuo Chen for (int i = 1024 * 16; i >= 1; i /= 4) 225926c960eSShuo Chen { 226926c960eSShuo Chen send(i, sctx); 227926c960eSShuo Chen } 228926c960eSShuo Chen tls_close(sctx); 229926c960eSShuo Chen shutdown(fds[1], SHUT_RDWR); 230926c960eSShuo Chen tls_free(sctx); 231926c960eSShuo Chen 232926c960eSShuo Chen thr.join(); 23342b85340SShuo Chen} 234