From 6fe071ca8d9dafecceeb9aa8d6f9e46e8146aeff Mon Sep 17 00:00:00 2001
From: huitema <huitema@huitema.net>
Date: Thu, 22 Nov 2018 16:57:45 -0800
Subject: [PATCH] Introduce a server false start state.

---
 picoquic/logger.c   | 3 +++
 picoquic/packet.c   | 5 ++++-
 picoquic/picoquic.h | 1 +
 picoquic/sender.c   | 5 +++++
 picoquic/tls_api.c  | 3 ++-
 5 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/picoquic/logger.c b/picoquic/logger.c
index ac35a300..f7f6098b 100644
--- a/picoquic/logger.c
+++ b/picoquic/logger.c
@@ -185,6 +185,9 @@ char const* picoquic_log_state_name(picoquic_state_enum state)
     case picoquic_state_server_almost_ready:
         state_name = "server_almost_ready";
         break;
+    case picoquic_state_server_false_start:
+        state_name = "server_false_start";
+        break;
     case picoquic_state_client_ready:
         state_name = "client_ready";
         break;
diff --git a/picoquic/packet.c b/picoquic/packet.c
index 7f0788f0..33bd6b60 100644
--- a/picoquic/packet.c
+++ b/picoquic/packet.c
@@ -1107,6 +1107,7 @@ int picoquic_incoming_client_handshake(
 if (cnx->cnx_state == picoquic_state_server_init
     || cnx->cnx_state == picoquic_state_server_handshake
     || cnx->cnx_state == picoquic_state_server_almost_ready
+    || cnx->cnx_state == picoquic_state_server_false_start
     || cnx->cnx_state == picoquic_state_server_ready) {
     if (picoquic_compare_connection_id(&ph->srce_cnx_id, &cnx->path[0]->remote_cnxid) != 0) {
         ret = PICOQUIC_ERROR_CNXID_CHECK;
@@ -1173,7 +1174,9 @@ int picoquic_incoming_0rtt(
         picoquic_compare_connection_id(&ph->dest_cnx_id, &cnx->path[0]->local_cnxid) == 0) ||
         picoquic_compare_connection_id(&ph->srce_cnx_id, &cnx->path[0]->remote_cnxid) != 0) {
         ret = PICOQUIC_ERROR_CNXID_CHECK;
-    } else if (cnx->cnx_state == picoquic_state_server_almost_ready || cnx->cnx_state == picoquic_state_server_ready) {
+    } else if (cnx->cnx_state == picoquic_state_server_almost_ready || 
+        cnx->cnx_state == picoquic_state_server_false_start ||
+        cnx->cnx_state == picoquic_state_server_ready) {
         if (ph->vn != picoquic_supported_versions[cnx->version_index].version) {
             ret = picoquic_connection_error(cnx, PICOQUIC_TRANSPORT_PROTOCOL_VIOLATION, 0);
         } else {
diff --git a/picoquic/picoquic.h b/picoquic/picoquic.h
index a3c1c00f..5de47b88 100644
--- a/picoquic/picoquic.h
+++ b/picoquic/picoquic.h
@@ -114,6 +114,7 @@ typedef enum {
     picoquic_state_handshake_failure,
     picoquic_state_client_almost_ready,
     picoquic_state_server_almost_ready,
+    picoquic_state_server_false_start,
     picoquic_state_client_ready,
     picoquic_state_server_ready,
     picoquic_state_disconnecting,
diff --git a/picoquic/sender.c b/picoquic/sender.c
index eafe598a..9f909c55 100644
--- a/picoquic/sender.c
+++ b/picoquic/sender.c
@@ -1961,6 +1961,10 @@ int picoquic_prepare_packet_ready(picoquic_cnx_t* cnx, picoquic_path_t * path_x,
     uint32_t send_buffer_min_max = (send_buffer_max > path_x->send_mtu) ? path_x->send_mtu : (uint32_t)send_buffer_max;
     uint64_t next_wake_time = cnx->latest_progress_time + PICOQUIC_MICROSEC_SILENCE_MAX * (2 - cnx->client_mode);
 
+    if (cnx->cnx_state == picoquic_state_server_false_start &&
+        cnx->crypto_context[3].aead_decrypt != NULL) {
+        cnx->cnx_state = picoquic_state_server_ready;
+    }
 
     /* Verify first that there is no need for retransmit or ack
      * on initial or handshake context. This does not deal with EOED packets,
@@ -2306,6 +2310,7 @@ int picoquic_prepare_segment(picoquic_cnx_t* cnx, picoquic_path_t * path_x, pico
         case picoquic_state_server_handshake:
             ret = picoquic_prepare_packet_server_init(cnx, path_x, packet, current_time, send_buffer, send_buffer_max, send_length);
             break;
+        case picoquic_state_server_false_start:
         case picoquic_state_client_ready:
         case picoquic_state_server_ready:
             ret = picoquic_prepare_packet_ready(cnx, path_x, packet, current_time, send_buffer, send_buffer_max, send_length);
diff --git a/picoquic/tls_api.c b/picoquic/tls_api.c
index 73a2deb3..85e4b1e9 100644
--- a/picoquic/tls_api.c
+++ b/picoquic/tls_api.c
@@ -1814,7 +1814,7 @@ int picoquic_tls_stream_process(picoquic_cnx_t* cnx)
                 case picoquic_state_server_init:
                 case picoquic_state_server_handshake:
                     /* If client authentication is activated, the client sends the certificates with its `Finished` packet.
-                       The server does not send any further packets, so, we can switch into ready state here.
+                       The server does not send any further packets, so, we can switch into false start state here.
                     */
                     if (data_pushed == 0 && ((ptls_context_t*)cnx->quic->tls_master_ctx)->require_client_authentication == 1) {
                         cnx->cnx_state = picoquic_state_server_ready;
@@ -1829,6 +1829,7 @@ int picoquic_tls_stream_process(picoquic_cnx_t* cnx)
                 case picoquic_state_handshake_failure:
                 case picoquic_state_client_ready:
                 case picoquic_state_server_almost_ready:
+                case picoquic_state_server_false_start:
                 case picoquic_state_server_ready:
                 case picoquic_state_disconnecting:
                 case picoquic_state_closing_received:
-- 
GitLab