diff --git a/examples/libevent-client.c b/examples/libevent-client.c index 7061e78b..8fbef879 100644 --- a/examples/libevent-client.c +++ b/examples/libevent-client.c @@ -322,6 +322,11 @@ static SSL_CTX *create_ssl_ctx(void) { SSL_OP_NO_COMPRESSION | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL); + +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3); +#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L + return ssl_ctx; } @@ -475,7 +480,27 @@ static void eventcb(struct bufferevent *bev, short events, void *ptr) { if (events & BEV_EVENT_CONNECTED) { int fd = bufferevent_getfd(bev); int val = 1; + const unsigned char *alpn = NULL; + unsigned int alpnlen = 0; + SSL *ssl; + fprintf(stderr, "Connected\n"); + + ssl = bufferevent_openssl_get_ssl(session_data->bev); + + SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen); +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + if (alpn == NULL) { + SSL_get0_alpn_selected(ssl, &alpn, &alpnlen); + } +#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L + + if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) { + fprintf(stderr, "h2 is not negotiated\n"); + delete_http2_session_data(session_data); + return; + } + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val)); initialize_nghttp2_session(session_data); send_client_connection_header(session_data); diff --git a/examples/libevent-server.c b/examples/libevent-server.c index 3a9ddfbc..09f52f99 100644 --- a/examples/libevent-server.c +++ b/examples/libevent-server.c @@ -116,6 +116,22 @@ static int next_proto_cb(SSL *s _U_, const unsigned char **data, return SSL_TLSEXT_ERR_OK; } +#if OPENSSL_VERSION_NUMBER >= 0x10002000L +static int alpn_select_proto_cb(SSL *ssl _U_, const unsigned char **out, + unsigned char *outlen, const unsigned char *in, + unsigned int inlen, void *arg _U_) { + int rv; + + rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in, inlen); + + if (rv != 1) { + return SSL_TLSEXT_ERR_NOACK; + } + + return SSL_TLSEXT_ERR_OK; +} +#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L + /* Create SSL_CTX. */ static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) { SSL_CTX *ssl_ctx; @@ -152,6 +168,11 @@ static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) { next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN; SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL); + +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, NULL); +#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L + return ssl_ctx; } @@ -640,11 +661,31 @@ static void writecb(struct bufferevent *bev, void *ptr) { static void eventcb(struct bufferevent *bev _U_, short events, void *ptr) { http2_session_data *session_data = (http2_session_data *)ptr; if (events & BEV_EVENT_CONNECTED) { + const unsigned char *alpn = NULL; + unsigned int alpnlen = 0; + SSL *ssl; + fprintf(stderr, "%s connected\n", session_data->client_addr); + ssl = bufferevent_openssl_get_ssl(session_data->bev); + + SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen); +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + if (alpn == NULL) { + SSL_get0_alpn_selected(ssl, &alpn, &alpnlen); + } +#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L + + if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) { + fprintf(stderr, "%s h2 is not negotiated\n", session_data->client_addr); + delete_http2_session_data(session_data); + return; + } + initialize_nghttp2_session(session_data); - if (send_server_connection_header(session_data) != 0) { + if (send_server_connection_header(session_data) != 0 || + session_send(session_data) != 0) { delete_http2_session_data(session_data); return; }