Remove the stats block in SSL_CTX.

Within the library, only ssl_update_cache read them, so add a dedicated field
to replace that use.

The APIs have a handful of uninteresting callers so I've left them in for now,
but they now always return zero.

Change-Id: Ie4e36fd4ab18f9bff544541d042bf3c098a46933
Reviewed-on: https://boringssl-review.googlesource.com/4101
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index c19211e..d8b3862 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -702,6 +702,10 @@
   struct ssl_session_st *session_cache_head;
   struct ssl_session_st *session_cache_tail;
 
+  /* handshakes_since_cache_flush is the number of successful handshakes since
+   * the last cache flush. */
+  int handshakes_since_cache_flush;
+
   /* This can have one of 2 values, ored together,
    * SSL_SESS_CACHE_CLIENT,
    * SSL_SESS_CACHE_SERVER,
@@ -725,26 +729,6 @@
   SSL_SESSION *(*get_session_cb)(struct ssl_st *ssl, uint8_t *data, int len,
                                  int *copy);
 
-  /* TODO(agl): remove the stats stuff. */
-  struct {
-    int sess_connect;             /* SSL new conn - started */
-    int sess_connect_renegotiate; /* SSL reneg - requested */
-    int sess_connect_good;        /* SSL new conne/reneg - finished */
-    int sess_accept;              /* SSL new accept - started */
-    int sess_accept_renegotiate;  /* SSL reneg - requested */
-    int sess_accept_good;         /* SSL accept/reneg - finished */
-    int sess_miss;                /* session lookup misses  */
-    int sess_timeout;             /* reuse attempt on timeouted session */
-    int sess_cache_full;          /* session removed due to full cache */
-    int sess_hit;                 /* session reuse actually done */
-    int sess_cb_hit;              /* session-id that was not
-                                   * in the cache was
-                                   * passed back via the callback.  This
-                                   * indicates that the application is
-                                   * supplying session-id's from other
-                                   * processes - spooky :-) */
-  } stats;
-
   int references;
 
   /* if defined, these override the X509_verify_cert() calls */
diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c
index 3c3e0b4..4dbba35 100644
--- a/ssl/d1_clnt.c
+++ b/ssl/d1_clnt.c
@@ -156,7 +156,6 @@
       case SSL_ST_RENEGOTIATE:
         s->renegotiate = 1;
         s->state = SSL_ST_CONNECT;
-        s->ctx->stats.sess_connect_renegotiate++;
       /* break */
       case SSL_ST_CONNECT:
       case SSL_ST_BEFORE | SSL_ST_CONNECT:
@@ -184,7 +183,6 @@
         /* don't push the buffering BIO quite yet */
 
         s->state = SSL3_ST_CW_CLNT_HELLO_A;
-        s->ctx->stats.sess_connect++;
         s->init_num = 0;
         s->d1->send_cookie = 0;
         s->hit = 0;
@@ -477,12 +475,8 @@
         s->new_session = 0;
 
         ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
-        if (s->hit) {
-          s->ctx->stats.sess_hit++;
-        }
 
         ret = 1;
-        s->ctx->stats.sess_connect_good++;
 
         if (cb != NULL) {
           cb(s, SSL_CB_HANDSHAKE_DONE, 1);
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index 0a4dc47..01f5cbf 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -198,11 +198,9 @@
           }
 
           s->state = SSL3_ST_SR_CLNT_HELLO_A;
-          s->ctx->stats.sess_accept++;
         } else {
           /* s->state == SSL_ST_RENEGOTIATE, * we will just send a
            * HelloRequest */
-          s->ctx->stats.sess_accept_renegotiate++;
           s->state = SSL3_ST_SW_HELLO_REQ_A;
         }
 
@@ -491,8 +489,6 @@
 
           ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
 
-          s->ctx->stats.sess_accept_good++;
-
           if (cb != NULL) {
             cb(s, SSL_CB_HANDSHAKE_DONE, 1);
           }
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index b9154ab..71cc4c7 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -195,7 +195,6 @@
       case SSL_ST_RENEGOTIATE:
         s->renegotiate = 1;
         s->state = SSL_ST_CONNECT;
-        s->ctx->stats.sess_connect_renegotiate++;
         /* fallthrough */
       case SSL_ST_CONNECT:
       case SSL_ST_BEFORE | SSL_ST_CONNECT:
@@ -230,7 +229,6 @@
         }
 
         s->state = SSL3_ST_CW_CLNT_HELLO_A;
-        s->ctx->stats.sess_connect++;
         s->init_num = 0;
         break;
 
@@ -551,13 +549,9 @@
         s->s3->tmp.in_false_start = 0;
 
         ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
-        if (s->hit) {
-          s->ctx->stats.sess_hit++;
-        }
 
         ret = 1;
         /* s->server=0; */
-        s->ctx->stats.sess_connect_good++;
 
         if (cb != NULL) {
           cb(s, SSL_CB_HANDSHAKE_DONE, 1);
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index a2fc6b6..a3256d7 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -242,7 +242,6 @@
           goto end;
         }
 
-        s->ctx->stats.sess_accept_renegotiate++;
         s->state = SSL3_ST_SW_HELLO_REQ_A;
         break;
 
@@ -309,7 +308,6 @@
           }
           s->state = SSL3_ST_SR_CLNT_HELLO_A;
         }
-        s->ctx->stats.sess_accept++;
         break;
 
       case SSL3_ST_SR_INITIAL_BYTES:
@@ -655,8 +653,6 @@
 
           ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
 
-          s->ctx->stats.sess_accept_good++;
-
           if (cb != NULL) {
             cb(s, SSL_CB_HANDSHAKE_DONE, 1);
           }
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index cbe0b1e..d723d33 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1144,37 +1144,19 @@
       return lh_SSL_SESSION_num_items(ctx->sessions);
 
     case SSL_CTRL_SESS_CONNECT:
-      return ctx->stats.sess_connect;
-
     case SSL_CTRL_SESS_CONNECT_GOOD:
-      return ctx->stats.sess_connect_good;
-
     case SSL_CTRL_SESS_CONNECT_RENEGOTIATE:
-      return ctx->stats.sess_connect_renegotiate;
-
     case SSL_CTRL_SESS_ACCEPT:
-      return ctx->stats.sess_accept;
-
     case SSL_CTRL_SESS_ACCEPT_GOOD:
-      return ctx->stats.sess_accept_good;
-
     case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE:
-      return ctx->stats.sess_accept_renegotiate;
-
     case SSL_CTRL_SESS_HIT:
-      return ctx->stats.sess_hit;
-
     case SSL_CTRL_SESS_CB_HIT:
-      return ctx->stats.sess_cb_hit;
-
     case SSL_CTRL_SESS_MISSES:
-      return ctx->stats.sess_miss;
-
     case SSL_CTRL_SESS_TIMEOUTS:
-      return ctx->stats.sess_timeout;
-
     case SSL_CTRL_SESS_CACHE_FULL:
-      return ctx->stats.sess_cache_full;
+      /* Statistics are no longer supported.
+       * TODO(davidben): Try to remove the accessors altogether. */
+      return 0;
 
     case SSL_CTRL_OPTIONS:
       return ctx->options |= larg;
@@ -1797,8 +1779,6 @@
   ret->get_session_cb = 0;
   ret->generate_session_id = 0;
 
-  memset((char *)&ret->stats, 0, sizeof(ret->stats));
-
   ret->references = 1;
   ret->quiet_shutdown = 0;
 
@@ -2164,31 +2144,38 @@
 }
 
 void ssl_update_cache(SSL *s, int mode) {
-  int i;
-
-  /* If the session_id_length is 0, we are not supposed to cache it, and it
-   * would be rather hard to do anyway :-) */
+  /* Never cache sessions with empty session IDs. */
   if (s->session->session_id_length == 0) {
     return;
   }
 
-  i = s->initial_ctx->session_cache_mode;
-  if ((i & mode) && !s->hit &&
-      ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE) ||
-       SSL_CTX_add_session(s->initial_ctx, s->session)) &&
-      s->initial_ctx->new_session_cb != NULL) {
-    if (!s->initial_ctx->new_session_cb(s, SSL_SESSION_up_ref(s->session))) {
+  SSL_CTX *ctx = s->initial_ctx;
+  if ((ctx->session_cache_mode & mode) == mode && !s->hit &&
+      ((ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE) ||
+       SSL_CTX_add_session(ctx, s->session)) &&
+      ctx->new_session_cb != NULL) {
+    /* Note: |new_session_cb| is called whether the internal session cache is
+     * used or not. */
+    if (!ctx->new_session_cb(s, SSL_SESSION_up_ref(s->session))) {
       SSL_SESSION_free(s->session);
     }
   }
 
-  /* auto flush every 255 connections */
-  if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && ((i & mode) == mode)) {
-    if ((((mode & SSL_SESS_CACHE_CLIENT)
-              ? s->initial_ctx->stats.sess_connect_good
-              : s->initial_ctx->stats.sess_accept_good) &
-         0xff) == 0xff) {
-      SSL_CTX_flush_sessions(s->initial_ctx, (unsigned long)time(NULL));
+  if (!(ctx->session_cache_mode & SSL_SESS_CACHE_NO_AUTO_CLEAR) &&
+      !(ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_STORE) &&
+      (ctx->session_cache_mode & mode) == mode) {
+    /* Automatically flush the internal session cache every 255 connections. */
+    int flush_cache = 0;
+    CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
+    ctx->handshakes_since_cache_flush++;
+    if (ctx->handshakes_since_cache_flush >= 255) {
+      flush_cache = 1;
+      ctx->handshakes_since_cache_flush = 0;
+    }
+    CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
+
+    if (flush_cache) {
+      SSL_CTX_flush_sessions(ctx, (unsigned long)time(NULL));
     }
   }
 }
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index 72e161b..343d0a6 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -417,9 +417,6 @@
     ret = SSL_SESSION_up_ref(lh_SSL_SESSION_retrieve(s->initial_ctx->sessions,
                                                      &data));
     CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
-    if (ret == NULL) {
-      s->initial_ctx->stats.sess_miss++;
-    }
   }
 
   if (try_session_cache && ret == NULL &&
@@ -434,7 +431,6 @@
          * unwind the stack and figure out the session asynchronously. */
         return PENDING_SESSION;
       }
-      s->initial_ctx->stats.sess_cb_hit++;
 
       /* Increment reference count now if the session callback asks us to do so
        * (note that if the session structures returned by the callback are
@@ -485,7 +481,6 @@
 
   if (ret->timeout < (long)(time(NULL) - ret->time)) {
     /* timeout */
-    s->initial_ctx->stats.sess_timeout++;
     if (try_session_cache) {
       /* session was from the cache, so remove it */
       SSL_CTX_remove_session(s->initial_ctx, ret);
@@ -493,8 +488,6 @@
     goto err;
   }
 
-  s->initial_ctx->stats.sess_hit++;
-
   if (s->session != NULL) {
     SSL_SESSION_free(s->session);
   }
@@ -565,7 +558,6 @@
         if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) {
           break;
         }
-        ctx->stats.sess_cache_full++;
       }
     }
   }