Add an ability to set the SSL read buffer size

This capability is required for read pipelining. We will only read in as
many records as will fit in the read buffer (and the network can provide
in one go). The bigger the buffer the more records we can process in
parallel.

Reviewed-by: Tim Hudson <tjh@openssl.org>
diff --git a/apps/s_client.c b/apps/s_client.c
index c6af293..27c8be8 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -656,7 +656,7 @@
     OPT_CHAINCAFILE, OPT_VERIFYCAFILE, OPT_NEXTPROTONEG, OPT_ALPN,
     OPT_SERVERINFO, OPT_STARTTLS, OPT_SERVERNAME,
     OPT_USE_SRTP, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, OPT_SMTPHOST,
-    OPT_ASYNC, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES,
+    OPT_ASYNC, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_READ_BUF,
     OPT_V_ENUM,
     OPT_X_ENUM,
     OPT_S_ENUM,
@@ -766,6 +766,8 @@
      "Size used to split data for encrypt/decrypt pipelines"},
     {"max_pipelines", OPT_MAX_PIPELINES, 'n',
      "Maximum number of encrypt/decrypt pipelines to be used"},
+    {"read_buf", OPT_READ_BUF, 'n',
+     "Default read buffer size to be used for connections"},
     OPT_S_OPTIONS,
     OPT_V_OPTIONS,
     OPT_X_OPTIONS,
@@ -896,6 +898,7 @@
     int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM;
     int starttls_proto = PROTO_OFF, crl_format = FORMAT_PEM, crl_download = 0;
     int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending;
+    int read_buf_len = 0;
     int fallback_scsv = 0;
     long socket_mtu = 0, randamt = 0;
     OPTION_CHOICE o;
@@ -1393,6 +1396,9 @@
         case OPT_MAX_PIPELINES:
             max_pipelines = atoi(opt_arg());
             break;
+        case OPT_READ_BUF:
+            read_buf_len = atoi(opt_arg());
+            break;
         }
     }
     argc = opt_num_rest();
@@ -1573,6 +1579,10 @@
         SSL_CTX_set_max_pipelines(ctx, max_pipelines);
     }
 
+    if (read_buf_len > 0) {
+        SSL_CTX_set_default_read_buffer_len(ctx, read_buf_len);
+    }
+
     if (!config_ctx(cctx, ssl_args, ctx))
         goto end;
 
diff --git a/apps/s_server.c b/apps/s_server.c
index f544be1..22e9175 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -809,8 +809,8 @@
     OPT_QUIET, OPT_BRIEF, OPT_NO_DHE,
     OPT_NO_RESUME_EPHEMERAL, OPT_PSK_HINT, OPT_PSK, OPT_SRPVFILE,
     OPT_SRPUSERSEED, OPT_REV, OPT_WWW, OPT_UPPER_WWW, OPT_HTTP, OPT_ASYNC,
-    OPT_SSL_CONFIG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_SSL3,
-    OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1,
+    OPT_SSL_CONFIG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES, OPT_READ_BUF,
+    OPT_SSL3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1,
     OPT_DTLS1_2, OPT_TIMEOUT, OPT_MTU, OPT_CHAIN, OPT_LISTEN,
     OPT_ID_PREFIX, OPT_RAND, OPT_SERVERNAME, OPT_SERVERNAME_FATAL,
     OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN,
@@ -946,6 +946,8 @@
      "Size used to split data for encrypt/decrypt pipelines"},
     {"max_pipelines", OPT_MAX_PIPELINES, 'n',
      "Maximum number of encrypt/decrypt pipelines to be used"},
+    {"read_buf", OPT_READ_BUF, 'n',
+     "Default read buffer size to be used for connections"},
     OPT_S_OPTIONS,
     OPT_V_OPTIONS,
     OPT_X_OPTIONS,
@@ -1049,6 +1051,7 @@
     X509 *s_cert2 = NULL;
     tlsextctx tlsextcbp = { NULL, NULL, SSL_TLSEXT_ERR_ALERT_WARNING };
     const char *ssl_config = NULL;
+    int read_buf_len = 0;
 #ifndef OPENSSL_NO_NEXTPROTONEG
     const char *next_proto_neg_in = NULL;
     tlsextnextprotoctx next_proto = { NULL, 0 };
@@ -1521,6 +1524,10 @@
         case OPT_MAX_PIPELINES:
             max_pipelines = atoi(opt_arg());
             break;
+        case OPT_READ_BUF:
+            read_buf_len = atoi(opt_arg());
+            break;
+
         }
     }
     argc = opt_num_rest();
@@ -1753,6 +1760,10 @@
         SSL_CTX_set_max_pipelines(ctx, max_pipelines);
     }
 
+    if (read_buf_len > 0) {
+        SSL_CTX_set_default_read_buffer_len(ctx, read_buf_len);
+    }
+
 #ifndef OPENSSL_NO_SRTP
     if (srtp_profiles != NULL) {
         /* Returns 0 on success! */
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 43d59a6..94ea5ee 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1808,6 +1808,9 @@
 # define SSL_set_max_pipelines(ssl,m) \
         SSL_ctrl(ssl,SSL_CTRL_SET_MAX_PIPELINES,m,NULL)
 
+void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len);
+void SSL_set_default_read_buffer_len(SSL *s, size_t len);
+
      /* NB: the keylength is only applicable when is_export is true */
 # ifndef OPENSSL_NO_DH
 void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c
index 91b8205..83f5cf5 100644
--- a/ssl/record/rec_layer_s3.c
+++ b/ssl/record/rec_layer_s3.c
@@ -241,6 +241,16 @@
     return num;
 }
 
+void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len)
+{
+    ctx->default_read_buf_len = len;
+}
+
+void SSL_set_default_read_buffer_len(SSL *s, size_t len)
+{
+    SSL3_BUFFER_set_default_len(RECORD_LAYER_get_rbuf(&s->rlayer), len);
+}
+
 const char *SSL_rstate_string_long(const SSL *s)
 {
     const char *str;
diff --git a/ssl/record/record.h b/ssl/record/record.h
index 000fc85..a1febc5 100644
--- a/ssl/record/record.h
+++ b/ssl/record/record.h
@@ -118,6 +118,8 @@
 typedef struct ssl3_buffer_st {
     /* at least SSL3_RT_MAX_PACKET_SIZE bytes, see ssl3_setup_buffers() */
     unsigned char *buf;
+    /* default buffer size (or 0 if no default set) */
+    size_t default_len;
     /* buffer size */
     size_t len;
     /* where to 'copy from' */
diff --git a/ssl/record/record_locl.h b/ssl/record/record_locl.h
index e5d2784..f1f5bbc 100644
--- a/ssl/record/record_locl.h
+++ b/ssl/record/record_locl.h
@@ -162,6 +162,7 @@
 #define SSL3_BUFFER_set_offset(b, o)        ((b)->offset = (o))
 #define SSL3_BUFFER_add_offset(b, o)        ((b)->offset += (o))
 #define SSL3_BUFFER_is_initialised(b)       ((b)->buf != NULL)
+#define SSL3_BUFFER_set_default_len(b, l)   ((b)->default_len = (l))
 
 void SSL3_BUFFER_clear(SSL3_BUFFER *b);
 void SSL3_BUFFER_set_data(SSL3_BUFFER *b, const unsigned char *d, int n);
diff --git a/ssl/record/ssl3_buffer.c b/ssl/record/ssl3_buffer.c
index 576533c..53ae0f4 100644
--- a/ssl/record/ssl3_buffer.c
+++ b/ssl/record/ssl3_buffer.c
@@ -120,16 +120,13 @@
 }
 
 /*
- * Clear the contents of an SSL3_BUFFER but retain any memory allocated
+ * Clear the contents of an SSL3_BUFFER but retain any memory allocated. Also
+ * retains the default_len setting
  */
 void SSL3_BUFFER_clear(SSL3_BUFFER *b)
 {
-    unsigned char *buf = b->buf;
-    size_t len = b->len;
-
-    memset(b, 0, sizeof(*b));
-    b->buf = buf;
-    b->len = len;
+    b->offset = 0;
+    b->left = 0;
 }
 
 void SSL3_BUFFER_release(SSL3_BUFFER *b)
@@ -162,6 +159,8 @@
         if (ssl_allow_compression(s))
             len += SSL3_RT_MAX_COMPRESSED_OVERHEAD;
 #endif
+        if (b->default_len > len)
+            len = b->default_len;
         if ((p = OPENSSL_malloc(len)) == NULL)
             goto err;
         b->buf = p;
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 92734ea..4df8339 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -674,6 +674,8 @@
     s->max_pipelines = ctx->max_pipelines;
     if (s->max_pipelines > 1)
         RECORD_LAYER_set_read_ahead(&s->rlayer, 1);
+    if (ctx->default_read_buf_len > 0)
+        SSL_set_default_read_buffer_len(s, ctx->default_read_buf_len);
 
     CRYPTO_add(&ctx->references, 1, CRYPTO_LOCK_SSL_CTX);
     s->ctx = ctx;
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index aa3e0a3..064c22c 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -843,6 +843,9 @@
     /* Up to how many pipelines should we use? If 0 then 1 is assumed */
     unsigned int max_pipelines;
 
+    /* The default read buffer length to use (0 means not set) */
+    size_t default_read_buf_len;
+
 #  ifndef OPENSSL_NO_ENGINE
     /*
      * Engine to pass requests for client certs to
diff --git a/util/libssl.num b/util/libssl.num
index f1f2dd1..3ba959d 100644
--- a/util/libssl.num
+++ b/util/libssl.num
@@ -381,3 +381,5 @@
 SSL_get0_peer_scts                      381	1_1_0	EXIST::FUNCTION:CT
 SSL_CTX_set_ct_validation_callback      382	1_1_0	EXIST::FUNCTION:CT
 SSL_CTX_get_ct_validation_callback      383	1_1_0	EXIST::FUNCTION:CT
+SSL_set_default_read_buffer_len         384	1_1_0	EXIST::FUNCTION:
+SSL_CTX_set_default_read_buffer_len     385	1_1_0	EXIST::FUNCTION: