Add small_records.patch and handshake_cutthrough.patch.
See patches/README for additional details.
diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c
index eb56cf9..7d464b4 100644
--- a/ssl/d1_pkt.c
+++ b/ssl/d1_pkt.c
@@ -561,6 +561,21 @@
 			goto f_err;
 			}
 
+		/* If we receive a valid record larger than the current buffer size,
+		 * allocate some memory for it.
+		 */
+		if (rr->length > s->s3->rbuf.len - DTLS1_RT_HEADER_LENGTH)
+			{
+			if ((p=OPENSSL_realloc(s->s3->rbuf.buf, rr->length + DTLS1_RT_HEADER_LENGTH))==NULL)
+				{
+				SSLerr(SSL_F_DTLS1_GET_RECORD,ERR_R_MALLOC_FAILURE);
+				goto err;
+				}
+			s->s3->rbuf.buf=p;
+			s->s3->rbuf.len=rr->length + DTLS1_RT_HEADER_LENGTH;
+			s->packet= &(s->s3->rbuf.buf[0]);
+			}
+
 		s->client_version = version;
 		/* now s->rstate == SSL_ST_READ_BODY */
 		}
@@ -1226,6 +1241,7 @@
 	unsigned int tot,n,nw;
 	int i;
 	unsigned int mtu;
+	unsigned int max_mtu;
 
 	s->rwstate=SSL_NOTHING;
 	tot=s->s3->wnum;
@@ -1240,8 +1256,17 @@
 #endif
 	mtu = s->d1->mtu;
 
-	if (mtu > SSL3_RT_MAX_PLAIN_LENGTH)
-		mtu = SSL3_RT_MAX_PLAIN_LENGTH;
+    if (!(SSL_get_mode(s) & SSL_MODE_SMALL_BUFFERS))
+		{
+		max_mtu = SSL3_RT_MAX_PLAIN_LENGTH;
+		}
+	else
+		{
+		max_mtu = SSL3_RT_DEFAULT_PLAIN_LENGTH;
+		}
+
+	if (mtu > max_mtu)
+		mtu = max_mtu;
 
 	if (n > mtu)
 		nw=mtu;
@@ -1327,7 +1352,9 @@
 			if (prefix_len <= 0)
 				goto err;
 
-			if (s->s3->wbuf.len < (size_t)prefix_len + SSL3_RT_MAX_PACKET_SIZE)
+			if (s->s3->wbuf.len < (size_t)prefix_len +
+				((SSL_get_mode(s) & SSL_MODE_SMALL_BUFFERS) ? SSL3_RT_DEFAULT_PACKET_SIZE :
+					SSL3_RT_MAX_PACKET_SIZE))
 				{
 				/* insufficient space */
 				SSLerr(SSL_F_DO_DTLS1_WRITE, ERR_R_INTERNAL_ERROR);
diff --git a/ssl/s23_srvr.c b/ssl/s23_srvr.c
index ba06e7a..468251a 100644
--- a/ssl/s23_srvr.c
+++ b/ssl/s23_srvr.c
@@ -405,8 +405,13 @@
 		v[0] = p[3]; /* == SSL3_VERSION_MAJOR */
 		v[1] = p[4];
 
+/* The SSL2 protocol allows n to be larger, just pick
+ * a reasonable buffer size. */
+#if SSL3_RT_DEFAULT_PACKET_SIZE < 1024*4 - SSL3_RT_DEFAULT_WRITE_OVERHEAD
+#error "SSL3_RT_DEFAULT_PACKET_SIZE is too small."
+#endif
 		n=((p[0]&0x7f)<<8)|p[1];
-		if (n > (1024*4))
+		if (n > SSL3_RT_DEFAULT_PACKET_SIZE - 2)
 			{
 			SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_TOO_LARGE);
 			goto err;
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index 2ecfbb7..d5bb99c 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -594,11 +594,18 @@
 
 	if (s->s3->rbuf.buf == NULL)
 		{
-		if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
-			extra=SSL3_RT_MAX_EXTRA;
+		if (SSL_get_mode(s) & SSL_MODE_SMALL_BUFFERS)
+			{
+			len = SSL3_RT_DEFAULT_PACKET_SIZE;
+			}
 		else
-			extra=0;
-		len = SSL3_RT_MAX_PACKET_SIZE + extra;
+			{
+			if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
+				extra=SSL3_RT_MAX_EXTRA;
+			else
+				extra=0;
+			len = SSL3_RT_MAX_PACKET_SIZE + extra;
+			}
 		if ((p=OPENSSL_malloc(len)) == NULL)
 			goto err;
 		s->s3->rbuf.buf = p;
@@ -607,8 +614,15 @@
 
 	if (s->s3->wbuf.buf == NULL)
 		{
-		len = SSL3_RT_MAX_PACKET_SIZE;
-		len += SSL3_RT_HEADER_LENGTH + 256; /* extra space for empty fragment */
+		if (SSL_get_mode(s) & SSL_MODE_SMALL_BUFFERS)
+			{
+			len = SSL3_RT_DEFAULT_PACKET_SIZE;
+			}
+		else
+			{
+			len = SSL3_RT_MAX_PACKET_SIZE;
+			}
+		len += SSL3_RT_DEFAULT_WRITE_OVERHEAD; /* extra space for empty fragment */
 		if ((p=OPENSSL_malloc(len)) == NULL)
 			goto err;
 		s->s3->wbuf.buf = p;
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 5030848..47dd34f 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -454,14 +454,20 @@
 				}
 			else
 				{
-#ifndef OPENSSL_NO_TLSEXT
-				/* Allow NewSessionTicket if ticket expected */
-				if (s->tlsext_ticket_expected)
-					s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A;
+				if ((SSL_get_mode(s) & SSL_MODE_HANDSHAKE_CUTTHROUGH) && SSL_get_cipher_bits(s, NULL) >= 128)
+					{
+					s->s3->tmp.next_state=SSL3_ST_CUTTHROUGH_COMPLETE;
+					}
 				else
+					{
+#ifndef OPENSSL_NO_TLSEXT
+					/* Allow NewSessionTicket if ticket expected */
+					if (s->tlsext_ticket_expected)
+						s->s3->tmp.next_state=SSL3_ST_CR_SESSION_TICKET_A;
+					else
 #endif
-				
-				s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
+						s->s3->tmp.next_state=SSL3_ST_CR_FINISHED_A;
+					}
 				}
 			s->init_num=0;
 			break;
@@ -512,6 +518,22 @@
 			s->state=s->s3->tmp.next_state;
 			break;
 
+		case SSL3_ST_CUTTHROUGH_COMPLETE:
+#ifndef OPENSSL_NO_TLSEXT
+			/* Allow NewSessionTicket if ticket expected */
+			if (s->tlsext_ticket_expected)
+				s->state=SSL3_ST_CR_SESSION_TICKET_A;
+			else
+#endif
+				s->state=SSL3_ST_CR_FINISHED_A;
+
+			/* Allow application writes to go through.  Note that SSL3_FLAGS_DELAY_CLIENT_FINISHED
+			 * is not supported on cutthrough connections (just for simplicity) */
+			ssl_free_wbio_buffer(s);
+			ret = 1;
+			goto end;
+			/* break; */
+
 		case SSL_ST_OK:
 			/* clean a few things up */
 			ssl3_cleanup_key_block(s);
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c
index 9476dcd..e32174d 100644
--- a/ssl/s3_pkt.c
+++ b/ssl/s3_pkt.c
@@ -250,7 +250,8 @@
 		extra=SSL3_RT_MAX_EXTRA;
 	else
 		extra=0;
-	if (extra != s->s3->rbuf.len - SSL3_RT_MAX_PACKET_SIZE)
+	if (!(SSL_get_mode(s) & SSL_MODE_SMALL_BUFFERS) &&
+		extra != s->s3->rbuf.len - SSL3_RT_MAX_PACKET_SIZE)
 		{
 		/* actually likely an application error: SLS_OP_MICROSOFT_BIG_SSLV3_BUFFER
 		 * set after ssl3_setup_buffers() was done */
@@ -303,6 +304,21 @@
 			goto f_err;
 			}
 
+		/* If we receive a valid record larger than the current buffer size,
+		 * allocate some memory for it.
+		 */
+		if (rr->length > s->s3->rbuf.len - SSL3_RT_HEADER_LENGTH)
+			{
+			if ((p=OPENSSL_realloc(s->s3->rbuf.buf, rr->length + SSL3_RT_HEADER_LENGTH))==NULL)
+				{
+				SSLerr(SSL_F_SSL3_GET_RECORD,ERR_R_INTERNAL_ERROR);
+				goto err;
+				}
+			s->s3->rbuf.buf=p;
+			s->s3->rbuf.len=rr->length + SSL3_RT_HEADER_LENGTH;
+			s->packet= &(s->s3->rbuf.buf[0]);
+			}
+
 		/* now s->rstate == SSL_ST_READ_BODY */
 		}
 
@@ -516,6 +532,7 @@
 	const unsigned char *buf=buf_;
 	unsigned int tot,n,nw;
 	int i;
+    unsigned int max_plain_length;
 
 	s->rwstate=SSL_NOTHING;
 	tot=s->s3->wnum;
@@ -535,8 +552,13 @@
 	n=(len-tot);
 	for (;;)
 		{
-		if (n > SSL3_RT_MAX_PLAIN_LENGTH)
-			nw=SSL3_RT_MAX_PLAIN_LENGTH;
+		if (!(SSL_get_mode(s) & SSL_MODE_SMALL_BUFFERS))
+			max_plain_length = SSL3_RT_MAX_PLAIN_LENGTH;
+		else
+			max_plain_length = SSL3_RT_DEFAULT_PLAIN_LENGTH;
+
+		if (n > max_plain_length)
+			nw = max_plain_length;
 		else
 			nw=n;
 
@@ -620,7 +642,9 @@
 			if (prefix_len <= 0)
 				goto err;
 
-			if (s->s3->wbuf.len < (size_t)prefix_len + SSL3_RT_MAX_PACKET_SIZE)
+			if (s->s3->wbuf.len < (size_t)prefix_len +
+				((SSL_get_mode(s) & SSL_MODE_SMALL_BUFFERS) ? SSL3_RT_DEFAULT_PACKET_SIZE :
+					SSL3_RT_MAX_PACKET_SIZE))
 				{
 				/* insufficient space */
 				SSLerr(SSL_F_DO_SSL3_WRITE, ERR_R_INTERNAL_ERROR);
diff --git a/ssl/ssl.h b/ssl/ssl.h
index ff8a128..0e0bc6e 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -554,7 +554,13 @@
 #define SSL_MODE_AUTO_RETRY 0x00000004L
 /* Don't attempt to automatically build certificate chain */
 #define SSL_MODE_NO_AUTO_CHAIN 0x00000008L
-
+/* Use small read and write buffers: (a) lazy allocate read buffers for
+ * large incoming records, and (b) limit the size of outgoing records. */
+#define SSL_MODE_SMALL_BUFFERS 0x00000010L
+/* When set, clients may send application data before receipt of CCS
+ * and Finished.  This mode enables full-handshakes to 'complete' in
+ * one RTT. */
+#define SSL_MODE_HANDSHAKE_CUTTHROUGH 0x00000020L
 
 /* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value,
  * they cannot be used to clear bits. */
@@ -1095,10 +1101,12 @@
 /* Is the SSL_connection established? */
 #define SSL_get_state(a)		SSL_state(a)
 #define SSL_is_init_finished(a)		(SSL_state(a) == SSL_ST_OK)
-#define SSL_in_init(a)			(SSL_state(a)&SSL_ST_INIT)
+#define SSL_in_init(a)			((SSL_state(a)&SSL_ST_INIT) && \
+                                  !SSL_cutthrough_complete(a))
 #define SSL_in_before(a)		(SSL_state(a)&SSL_ST_BEFORE)
 #define SSL_in_connect_init(a)		(SSL_state(a)&SSL_ST_CONNECT)
 #define SSL_in_accept_init(a)		(SSL_state(a)&SSL_ST_ACCEPT)
+int SSL_cutthrough_complete(const SSL *s);
 
 /* The following 2 states are kept in ssl->rstate when reads fail,
  * you should not need these */
diff --git a/ssl/ssl3.h b/ssl/ssl3.h
index 4b1e2e9..803e13a 100644
--- a/ssl/ssl3.h
+++ b/ssl/ssl3.h
@@ -253,6 +253,9 @@
 #define SSL3_RT_MAX_EXTRA			(16384)
 #endif
 
+/* Default buffer length used for writen records.  Thus a generated record
+ * will contain plaintext no larger than this value. */
+#define SSL3_RT_DEFAULT_PLAIN_LENGTH	2048
 #define SSL3_RT_MAX_PLAIN_LENGTH		16384
 #ifdef OPENSSL_NO_COMP
 #define SSL3_RT_MAX_COMPRESSED_LENGTH	SSL3_RT_MAX_PLAIN_LENGTH
@@ -260,6 +263,12 @@
 #define SSL3_RT_MAX_COMPRESSED_LENGTH	(1024+SSL3_RT_MAX_PLAIN_LENGTH)
 #endif
 #define SSL3_RT_MAX_ENCRYPTED_LENGTH	(1024+SSL3_RT_MAX_COMPRESSED_LENGTH)
+/* Extra space for empty fragment, headers, MAC, and padding. */
+#define SSL3_RT_DEFAULT_WRITE_OVERHEAD  256
+#define SSL3_RT_DEFAULT_PACKET_SIZE     4096 - SSL3_RT_DEFAULT_WRITE_OVERHEAD
+#if SSL3_RT_DEFAULT_PLAIN_LENGTH + SSL3_RT_DEFAULT_WRITE_OVERHEAD > SSL3_RT_DEFAULT_PACKET_SIZE
+#error "Insufficient space allocated for write buffers."
+#endif
 #define SSL3_RT_MAX_PACKET_SIZE		(SSL3_RT_MAX_ENCRYPTED_LENGTH+SSL3_RT_HEADER_LENGTH)
 #define SSL3_RT_MAX_DATA_SIZE			(1024*1024)
 
@@ -447,6 +456,7 @@
 /*client */
 /* extra state */
 #define SSL3_ST_CW_FLUSH		(0x100|SSL_ST_CONNECT)
+#define SSL3_ST_CUTTHROUGH_COMPLETE (0x101|SSL_ST_CONNECT)
 /* write to server */
 #define SSL3_ST_CW_CLNT_HELLO_A		(0x110|SSL_ST_CONNECT)
 #define SSL3_ST_CW_CLNT_HELLO_B		(0x111|SSL_ST_CONNECT)
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 893abff..4c56e7a 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2696,7 +2696,17 @@
 	SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
 	}
 
-
+int SSL_cutthrough_complete(const SSL *s)
+	{
+	return (!s->server &&                 /* cutthrough only applies to clients */
+		!s->hit &&                        /* full-handshake */
+		s->version >= SSL3_VERSION &&
+		s->s3->in_read_app_data == 0 &&   /* cutthrough only applies to write() */
+		(SSL_get_mode((SSL*)s) & SSL_MODE_HANDSHAKE_CUTTHROUGH) &&  /* cutthrough enabled */
+		SSL_get_cipher_bits(s, NULL) >= 128 &&                      /* strong cipher choosen */
+		(s->state == SSL3_ST_CR_SESSION_TICKET_A ||                 /* ready to write app-data*/
+			s->state == SSL3_ST_CR_FINISHED_A));
+	}
 
 #if defined(_WINDLL) && defined(OPENSSL_SYS_WIN16)
 #include "../crypto/bio/bss_file.c"
diff --git a/ssl/ssltest.c b/ssl/ssltest.c
index b09c542..09d3502 100644
--- a/ssl/ssltest.c
+++ b/ssl/ssltest.c
@@ -277,6 +277,8 @@
 	               "                 (default is sect163r2).\n");
 #endif
 	fprintf(stderr," -test_cipherlist - verifies the order of the ssl cipher lists\n");
+	fprintf(stderr," -c_small_records - enable client side use of small SSL record buffers\n");
+	fprintf(stderr," -s_small_records - enable server side use of small SSL record buffers\n");
 	}
 
 static void print_details(SSL *c_ssl, const char *prefix)
@@ -431,6 +433,9 @@
 #ifdef OPENSSL_FIPS
 	int fips_mode=0;
 #endif
+	int ssl_mode = 0;
+	int c_small_records=0;
+	int s_small_records=0;
 
 	verbose = 0;
 	debug = 0;
@@ -619,6 +624,14 @@
 			{
 			test_cipherlist = 1;
 			}
+		else if (strcmp(*argv, "-c_small_records") == 0)
+			{
+			c_small_records = 1;
+			}
+		else if (strcmp(*argv, "-s_small_records") == 0)
+			{
+			s_small_records = 1;
+			}
 		else
 			{
 			fprintf(stderr,"unknown option %s\n",*argv);
@@ -755,6 +768,21 @@
 		SSL_CTX_set_cipher_list(s_ctx,cipher);
 		}
 
+	ssl_mode = 0;
+	if (c_small_records)
+		{
+		ssl_mode = SSL_CTX_get_mode(c_ctx);
+		ssl_mode |= SSL_MODE_SMALL_BUFFERS;
+		SSL_CTX_set_mode(c_ctx, ssl_mode);
+		}
+	ssl_mode = 0;
+	if (s_small_records)
+		{
+		ssl_mode = SSL_CTX_get_mode(s_ctx);
+		ssl_mode |= SSL_MODE_SMALL_BUFFERS;
+		SSL_CTX_set_mode(s_ctx, ssl_mode);
+		}
+
 #ifndef OPENSSL_NO_DH
 	if (!no_dhe)
 		{