changeset 8273:cb75f194f1f0 quic

Implemented sending HANDSHAKE_DONE frame after handshake. This makes it possible to switch to draft 27 by default.
author Vladimir Homutov <vl@nginx.com>
date Tue, 24 Mar 2020 11:59:14 +0300
parents 7f0981be07c4
children ee53bfd8f9ed
files src/event/ngx_event_quic.c src/event/ngx_event_quic.h src/event/ngx_event_quic_transport.c
diffstat 3 files changed, 43 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/event/ngx_event_quic.c
+++ b/src/event/ngx_event_quic.c
@@ -964,9 +964,10 @@ static ngx_int_t
 ngx_quic_handle_crypto_frame(ngx_connection_t *c, ngx_quic_header_t *pkt,
     ngx_quic_crypto_frame_t *f)
 {
-    int              sslerr;
-    ssize_t          n;
-    ngx_ssl_conn_t  *ssl_conn;
+    int                sslerr;
+    ssize_t            n;
+    ngx_ssl_conn_t    *ssl_conn;
+    ngx_quic_frame_t  *frame;
 
     if (f->offset != 0x0) {
         ngx_log_error(NGX_LOG_INFO, c->log, 0,
@@ -1012,6 +1013,17 @@ ngx_quic_handle_crypto_frame(ngx_connect
 
         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0,
                         "handshake completed successfully");
+
+        frame = ngx_pcalloc(c->pool, sizeof(ngx_quic_frame_t));
+        if (frame == NULL) {
+            return NGX_ERROR;
+        }
+
+        /* 12.4 Frames and frame types, figure 8 */
+        frame->level = ssl_encryption_application;
+        frame->type = NGX_QUIC_FT_HANDSHAKE_DONE;
+        ngx_sprintf(frame->info, "HANDSHAKE DONE on handshake completed");
+        ngx_quic_queue_frame(c->quic, frame);
     }
 
     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
--- a/src/event/ngx_event_quic.h
+++ b/src/event/ngx_event_quic.h
@@ -11,7 +11,7 @@
 #include <ngx_event_openssl.h>
 
 
-#define NGX_QUIC_DRAFT_VERSION               24
+#define NGX_QUIC_DRAFT_VERSION               27
 #define NGX_QUIC_VERSION  (0xff000000 + NGX_QUIC_DRAFT_VERSION)
 
 #define NGX_QUIC_MAX_SHORT_HEADER            25
--- a/src/event/ngx_event_quic_transport.c
+++ b/src/event/ngx_event_quic_transport.c
@@ -66,6 +66,7 @@ static u_char *ngx_quic_copy_bytes(u_cha
 static size_t ngx_quic_create_ack(u_char *p, ngx_quic_ack_frame_t *ack);
 static size_t ngx_quic_create_crypto(u_char *p,
     ngx_quic_crypto_frame_t *crypto);
+static size_t ngx_quic_create_hs_done(u_char *p);
 static size_t ngx_quic_create_stream(u_char *p, ngx_quic_stream_frame_t *sf);
 static size_t ngx_quic_create_max_streams(u_char *p,
     ngx_quic_max_streams_frame_t *ms);
@@ -882,14 +883,18 @@ ngx_quic_parse_frame(ngx_quic_header_t *
 
         break;
 
-    /* TODO: implement parsing for all frames below */
+    case NGX_QUIC_FT_HANDSHAKE_DONE:
+        /* only sent by server, not by client */
+        goto not_allowed;
+
     case NGX_QUIC_FT_NEW_TOKEN:
-    case NGX_QUIC_FT_HANDSHAKE_DONE:
 
         if (!ngx_quic_short_pkt(flags)) {
             goto not_allowed;
         }
 
+        /* TODO: implement */
+
         ngx_log_error(NGX_LOG_ERR, pkt->log, 0,
                       "unimplemented frame type 0x%xi in packet", f->type);
 
@@ -1065,6 +1070,9 @@ ngx_quic_create_frame(u_char *p, u_char 
     case NGX_QUIC_FT_CRYPTO:
         return ngx_quic_create_crypto(p, &f->u.crypto);
 
+    case NGX_QUIC_FT_HANDSHAKE_DONE:
+        return ngx_quic_create_hs_done(p);
+
     case NGX_QUIC_FT_STREAM0:
     case NGX_QUIC_FT_STREAM1:
     case NGX_QUIC_FT_STREAM2:
@@ -1148,6 +1156,23 @@ ngx_quic_create_crypto(u_char *p, ngx_qu
 
 
 static size_t
+ngx_quic_create_hs_done(u_char *p)
+{
+    u_char  *start;
+
+    if (p == NULL) {
+        return ngx_quic_varint_len(NGX_QUIC_FT_HANDSHAKE_DONE);
+    }
+
+    start = p;
+
+    ngx_quic_build_int(&p, NGX_QUIC_FT_HANDSHAKE_DONE);
+
+    return p - start;
+}
+
+
+static size_t
 ngx_quic_create_stream(u_char *p, ngx_quic_stream_frame_t *sf)
 {
     size_t   len;