loop-libressl.cc revision 926c960e
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
4542b85340SShuo Chen  tls_config_verify_client_optional(cfg);
4642b85340SShuo Chen  struct tls* ctx = tls_server();
4742b85340SShuo Chen  assert(ctx != NULL);
4842b85340SShuo Chen
4942b85340SShuo Chen  ret = tls_configure(ctx, cfg);
5042b85340SShuo Chen  assert(ret == 0);
5142b85340SShuo Chen
5242b85340SShuo Chen  struct tls* sctx = NULL;
5323a62999SShuo Chen  ret = tls_accept_socket(ctx, &sctx, sockfd);
5423a62999SShuo Chen  assert(ret == 0 && sctx != NULL);
5542b85340SShuo Chen
5623a62999SShuo Chen  return sctx;
5723a62999SShuo Chen}
5823a62999SShuo Chen
59926c960eSShuo Chen// only works for non-blocking sockets
6023a62999SShuo Chenbool handshake(struct tls* cctx, struct tls* sctx)
6123a62999SShuo Chen{
6223a62999SShuo Chen  int client_done = false, server_done = false;
6323a62999SShuo Chen
6423a62999SShuo Chen  while (!(client_done && server_done))
6523a62999SShuo Chen  {
6623a62999SShuo Chen    if (!client_done)
6723a62999SShuo Chen    {
6823a62999SShuo Chen      int ret = tls_handshake(cctx);
69926c960eSShuo Chen      // printf("c %d\n", ret);
7023a62999SShuo Chen      if (ret == 0)
7123a62999SShuo Chen        client_done = true;
7223a62999SShuo Chen      else if (ret == -1)
7323a62999SShuo Chen      {
7423a62999SShuo Chen        printf("client handshake failed: %s\n", tls_error(cctx));
7523a62999SShuo Chen        break;
7623a62999SShuo Chen      }
7723a62999SShuo Chen    }
7823a62999SShuo Chen
7923a62999SShuo Chen    if (!server_done)
8023a62999SShuo Chen    {
8123a62999SShuo Chen      int ret = tls_handshake(sctx);
82926c960eSShuo Chen      // printf("s %d\n", ret);
8323a62999SShuo Chen      if (ret == 0)
8423a62999SShuo Chen        server_done = true;
8523a62999SShuo Chen      else if (ret == -1)
8623a62999SShuo Chen      {
8723a62999SShuo Chen        printf("server handshake failed: %s\n", tls_error(cctx));
8823a62999SShuo Chen        break;
8923a62999SShuo Chen      }
9023a62999SShuo Chen    }
9123a62999SShuo Chen  }
9223a62999SShuo Chen
9323a62999SShuo Chen  return client_done && server_done;
9423a62999SShuo Chen}
9523a62999SShuo Chen
96926c960eSShuo Chenvoid setBlockingIO(int fd)
97926c960eSShuo Chen{
98926c960eSShuo Chen  int flags = fcntl(fd, F_GETFL, 0);
99926c960eSShuo Chen  if (flags > 0)
100926c960eSShuo Chen  {
101926c960eSShuo Chen    printf("set blocking IO for %d\n", fd);
102926c960eSShuo Chen    fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
103926c960eSShuo Chen  }
104926c960eSShuo Chen}
105926c960eSShuo Chen
106926c960eSShuo Chenconst int N = 500;
107926c960eSShuo Chen
108926c960eSShuo Chenstruct Trial
109926c960eSShuo Chen{
110926c960eSShuo Chen  int blocks, block_size;
111926c960eSShuo Chen};
112926c960eSShuo Chen
113926c960eSShuo Chenvoid client_thread(struct tls* ctx)
114926c960eSShuo Chen{
115926c960eSShuo Chen  Timer t;
116926c960eSShuo Chen  t.start();
117926c960eSShuo Chen  for (int i = 0; i < N; ++i)
118926c960eSShuo Chen  {
119926c960eSShuo Chen    int ret = tls_handshake(ctx);
120926c960eSShuo Chen    if (ret != 0)
121926c960eSShuo Chen      printf("client err = %d\n", ret);
122926c960eSShuo Chen  }
123926c960eSShuo Chen  t.stop();
124926c960eSShuo Chen  printf("client %f secs, %f handshakes/sec\n", t.seconds(), N / t.seconds());
125926c960eSShuo Chen  while (true)
126926c960eSShuo Chen  {
127926c960eSShuo Chen    Trial trial = { 0, 0 };
128926c960eSShuo Chen
129926c960eSShuo Chen    int nr = tls_read(ctx, &trial, sizeof trial);
130926c960eSShuo Chen    if (nr == 0)
131926c960eSShuo Chen      break;
132926c960eSShuo Chen    assert(nr == sizeof trial);
133926c960eSShuo Chen    // printf("client read bs %d nb %d\n", trial.block_size, trial.blocks);
134926c960eSShuo Chen    if (trial.block_size == 0)
135926c960eSShuo Chen      break;
136926c960eSShuo Chen    char* buf = new char[trial.block_size];
137926c960eSShuo Chen    for (int i = 0; i < trial.blocks; ++i)
138926c960eSShuo Chen    {
139926c960eSShuo Chen      nr = tls_read(ctx, buf, trial.block_size);
140926c960eSShuo Chen      assert(nr == trial.block_size);
141926c960eSShuo Chen    }
142926c960eSShuo Chen    int64_t ack = static_cast<int64_t>(trial.blocks) * trial.block_size;
143926c960eSShuo Chen    int nw = tls_write(ctx, &ack, sizeof ack);
144926c960eSShuo Chen    assert(nw == sizeof ack);
145926c960eSShuo Chen    delete[] buf;
146926c960eSShuo Chen  }
147926c960eSShuo Chen  printf("client done\n");
148926c960eSShuo Chen  tls_close(ctx);
149926c960eSShuo Chen  tls_free(ctx);
150926c960eSShuo Chen}
151926c960eSShuo Chen
152926c960eSShuo Chenvoid send(int block_size, struct tls* ctx)
153926c960eSShuo Chen{
154926c960eSShuo Chen  double start = now();
155926c960eSShuo Chen  int total = 0;
156926c960eSShuo Chen  int blocks = 1024;
157926c960eSShuo Chen  char* message = new char[block_size];
158926c960eSShuo Chen  bzero(message, block_size);
159926c960eSShuo Chen  Timer t;
160926c960eSShuo Chen  while (now() - start < 10)
161926c960eSShuo Chen  {
162926c960eSShuo Chen    Trial trial = { blocks, block_size };
163926c960eSShuo Chen    int nw = tls_write(ctx, &trial, sizeof trial);
164926c960eSShuo Chen    assert(nw == sizeof trial);
165926c960eSShuo Chen    t.start();
166926c960eSShuo Chen    for (int i = 0; i < blocks; ++i)
167926c960eSShuo Chen    {
168926c960eSShuo Chen      nw = tls_write(ctx, message, block_size);
169926c960eSShuo Chen      if (nw != block_size)
170926c960eSShuo Chen        printf("bs %d nw %d\n", block_size, nw);
171926c960eSShuo Chen      assert(nw == block_size);
172926c960eSShuo Chen    }
173926c960eSShuo Chen    t.stop();
174926c960eSShuo Chen    int64_t ack = 0;
175926c960eSShuo Chen    int nr = tls_read(ctx, &ack, sizeof ack);
176926c960eSShuo Chen    assert(nr == sizeof ack);
177926c960eSShuo Chen    assert(ack == static_cast<int64_t>(blocks) * block_size);
178926c960eSShuo Chen    total += blocks;
179926c960eSShuo Chen    blocks *= 2;
180926c960eSShuo Chen  }
181926c960eSShuo Chen  double secs = now() - start;
182926c960eSShuo Chen  printf("bs %5d sec %.3f tot %d thr %.1fKB/s wr cpu %.3f\n", block_size, secs, total,
183926c960eSShuo Chen         block_size / secs * total / 1024, t.seconds());
184926c960eSShuo Chen  delete[] message;
185926c960eSShuo Chen}
186926c960eSShuo Chen
18723a62999SShuo Chenint main(int argc, char* argv[])
18823a62999SShuo Chen{
18923a62999SShuo Chen  int ret = tls_init();
19042b85340SShuo Chen  assert(ret == 0);
19142b85340SShuo Chen
19223a62999SShuo Chen  int fds[2];
19323a62999SShuo Chen  socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fds);
19423a62999SShuo Chen
19523a62999SShuo Chen  struct tls* cctx = client(fds[0]);
19623a62999SShuo Chen  struct tls* sctx = server(fds[1]);
19742b85340SShuo Chen
19823a62999SShuo Chen  if (handshake(cctx, sctx))
19923a62999SShuo Chen    printf("cipher %s\n", tls_conn_cipher(cctx));
200926c960eSShuo Chen
201926c960eSShuo Chen  setBlockingIO(fds[0]);
202926c960eSShuo Chen  setBlockingIO(fds[1]);
203926c960eSShuo Chen  muduo::Thread thr(boost::bind(client_thread, cctx), "clientThread");
204926c960eSShuo Chen  thr.start();
205926c960eSShuo Chen
206926c960eSShuo Chen  {
207926c960eSShuo Chen  Timer t;
208926c960eSShuo Chen  t.start();
209926c960eSShuo Chen  for (int i = 0; i < N; ++i)
210926c960eSShuo Chen  {
211926c960eSShuo Chen    int ret = tls_handshake(sctx);
212926c960eSShuo Chen    if (ret != 0)
213926c960eSShuo Chen      printf("server err = %d\n", ret);
214926c960eSShuo Chen  }
215926c960eSShuo Chen  t.stop();
216926c960eSShuo Chen  printf("server %f secs, %f handshakes/sec\n", t.seconds(), N / t.seconds());
217926c960eSShuo Chen  }
218926c960eSShuo Chen
219926c960eSShuo Chen  for (int i = 1; i <= 1024 * 16; i *= 2)
220926c960eSShuo Chen  {
221926c960eSShuo Chen    send(i, sctx);
222926c960eSShuo Chen  }
223926c960eSShuo Chen  tls_close(sctx);
224926c960eSShuo Chen  shutdown(fds[1], SHUT_RDWR);
225926c960eSShuo Chen  tls_free(sctx);
226926c960eSShuo Chen
227926c960eSShuo Chen  thr.join();
22842b85340SShuo Chen}
229