Bladeren bron

nghttp2: compatibility with older libnghttp2 versions

Daniel-Constantin Mierla 1 jaar geleden
bovenliggende
commit
6333db8fb1
1 gewijzigde bestanden met toevoegingen van 73 en 22 verwijderingen
  1. 73 22
      src/modules/nghttp2/nghttp2_server.c

+ 73 - 22
src/modules/nghttp2/nghttp2_server.c

@@ -23,6 +23,8 @@
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
  */
 
 
+#include "nghttp2_server.h"
+
 #define OUTPUT_WOULDBLOCK_THRESHOLD (1 << 16)
 #define OUTPUT_WOULDBLOCK_THRESHOLD (1 << 16)
 
 
 #define ARRLEN(x) (sizeof(x) / sizeof(x[0]))
 #define ARRLEN(x) (sizeof(x) / sizeof(x[0]))
@@ -33,8 +35,6 @@
 				sizeof(VALUE) - 1, NGHTTP2_NV_FLAG_NONE      \
 				sizeof(VALUE) - 1, NGHTTP2_NV_FLAG_NONE      \
 	}
 	}
 
 
-#include "nghttp2_server.h"
-
 struct app_context;
 struct app_context;
 typedef struct app_context app_context;
 typedef struct app_context app_context;
 
 
@@ -61,6 +61,23 @@ struct app_context
 	struct event_base *evbase;
 	struct event_base *evbase;
 };
 };
 
 
+static unsigned char next_proto_list[256];
+static size_t next_proto_list_len;
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+static int next_proto_cb(
+		SSL *ssl, const unsigned char **data, unsigned int *len, void *arg)
+{
+	(void)ssl;
+	(void)arg;
+
+	*data = next_proto_list;
+	*len = (unsigned int)next_proto_list_len;
+	return SSL_TLSEXT_ERR_OK;
+}
+#endif /* !OPENSSL_NO_NEXTPROTONEG */
+
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
 static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
 static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
 		unsigned char *outlen, const unsigned char *in, unsigned int inlen,
 		unsigned char *outlen, const unsigned char *in, unsigned int inlen,
 		void *arg)
 		void *arg)
@@ -69,7 +86,7 @@ static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
 	(void)ssl;
 	(void)ssl;
 	(void)arg;
 	(void)arg;
 
 
-	rv = nghttp2_select_alpn(out, outlen, in, inlen);
+	rv = nghttp2_select_next_protocol((unsigned char **)out, outlen, in, inlen);
 
 
 	if(rv != 1) {
 	if(rv != 1) {
 		return SSL_TLSEXT_ERR_NOACK;
 		return SSL_TLSEXT_ERR_NOACK;
@@ -77,6 +94,7 @@ static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
 
 
 	return SSL_TLSEXT_ERR_OK;
 	return SSL_TLSEXT_ERR_OK;
 }
 }
+#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
 
 
 /* Create SSL_CTX. */
 /* Create SSL_CTX. */
 static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file)
 static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file)
@@ -117,7 +135,18 @@ static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file)
 		LM_ERR("Could not read certificate file %s", cert_file);
 		LM_ERR("Could not read certificate file %s", cert_file);
 	}
 	}
 
 
+	next_proto_list[0] = NGHTTP2_PROTO_VERSION_ID_LEN;
+	memcpy(&next_proto_list[1], NGHTTP2_PROTO_VERSION_ID,
+			NGHTTP2_PROTO_VERSION_ID_LEN);
+	next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN;
+
+#ifndef OPENSSL_NO_NEXTPROTONEG
+	SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL);
+#endif /* !OPENSSL_NO_NEXTPROTONEG */
+
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
 	SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, NULL);
 	SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, NULL);
+#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
 
 
 	return ssl_ctx;
 	return ssl_ctx;
 }
 }
@@ -240,17 +269,17 @@ static int session_send(http2_session_data *session_data)
 }
 }
 
 
 /* Read the data in the bufferevent and feed them into nghttp2 library
 /* Read the data in the bufferevent and feed them into nghttp2 library
-   function. Invocation of nghttp2_session_mem_recv2() may make
+   function. Invocation of nghttp2_session_mem_recv() may make
    additional pending frames, so call session_send() at the end of the
    additional pending frames, so call session_send() at the end of the
    function. */
    function. */
 static int session_recv(http2_session_data *session_data)
 static int session_recv(http2_session_data *session_data)
 {
 {
-	nghttp2_ssize readlen;
+	ssize_t readlen;
 	struct evbuffer *input = bufferevent_get_input(session_data->bev);
 	struct evbuffer *input = bufferevent_get_input(session_data->bev);
 	size_t datalen = evbuffer_get_length(input);
 	size_t datalen = evbuffer_get_length(input);
 	unsigned char *data = evbuffer_pullup(input, -1);
 	unsigned char *data = evbuffer_pullup(input, -1);
 
 
-	readlen = nghttp2_session_mem_recv2(session_data->session, data, datalen);
+	readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
 	if(readlen < 0) {
 	if(readlen < 0) {
 		LM_ERR("Fatal error: %s", nghttp2_strerror((int)readlen));
 		LM_ERR("Fatal error: %s", nghttp2_strerror((int)readlen));
 		return -1;
 		return -1;
@@ -265,8 +294,8 @@ static int session_recv(http2_session_data *session_data)
 	return 0;
 	return 0;
 }
 }
 
 
-static nghttp2_ssize send_callback(nghttp2_session *session,
-		const uint8_t *data, size_t length, int flags, void *user_data)
+static ssize_t send_callback(nghttp2_session *session, const uint8_t *data,
+		size_t length, int flags, void *user_data)
 {
 {
 	http2_session_data *session_data = (http2_session_data *)user_data;
 	http2_session_data *session_data = (http2_session_data *)user_data;
 	struct bufferevent *bev = session_data->bev;
 	struct bufferevent *bev = session_data->bev;
@@ -279,7 +308,7 @@ static nghttp2_ssize send_callback(nghttp2_session *session,
 		return NGHTTP2_ERR_WOULDBLOCK;
 		return NGHTTP2_ERR_WOULDBLOCK;
 	}
 	}
 	bufferevent_write(bev, data, length);
 	bufferevent_write(bev, data, length);
-	return (nghttp2_ssize)length;
+	return (ssize_t)length;
 }
 }
 
 
 /* Returns nonzero if the string |s| ends with the substring |sub| */
 /* Returns nonzero if the string |s| ends with the substring |sub| */
@@ -338,8 +367,8 @@ static char *percent_decode(const uint8_t *value, size_t valuelen)
 	return res;
 	return res;
 }
 }
 
 
-static nghttp2_ssize file_read_callback(nghttp2_session *session,
-		int32_t stream_id, uint8_t *buf, size_t length, uint32_t *data_flags,
+static ssize_t file_read_callback(nghttp2_session *session, int32_t stream_id,
+		uint8_t *buf, size_t length, uint32_t *data_flags,
 		nghttp2_data_source *source, void *user_data)
 		nghttp2_data_source *source, void *user_data)
 {
 {
 	int fd = source->fd;
 	int fd = source->fd;
@@ -356,18 +385,18 @@ static nghttp2_ssize file_read_callback(nghttp2_session *session,
 	if(r == 0) {
 	if(r == 0) {
 		*data_flags |= NGHTTP2_DATA_FLAG_EOF;
 		*data_flags |= NGHTTP2_DATA_FLAG_EOF;
 	}
 	}
-	return (nghttp2_ssize)r;
+	return r;
 }
 }
 
 
 static int send_response(nghttp2_session *session, int32_t stream_id,
 static int send_response(nghttp2_session *session, int32_t stream_id,
 		nghttp2_nv *nva, size_t nvlen, int fd)
 		nghttp2_nv *nva, size_t nvlen, int fd)
 {
 {
 	int rv;
 	int rv;
-	nghttp2_data_provider2 data_prd;
+	nghttp2_data_provider data_prd;
 	data_prd.source.fd = fd;
 	data_prd.source.fd = fd;
 	data_prd.read_callback = file_read_callback;
 	data_prd.read_callback = file_read_callback;
 
 
-	rv = nghttp2_submit_response2(session, stream_id, nva, nvlen, &data_prd);
+	rv = nghttp2_submit_response(session, stream_id, nva, nvlen, &data_prd);
 	if(rv != 0) {
 	if(rv != 0) {
 		LM_ERR("Fatal error: %s", nghttp2_strerror(rv));
 		LM_ERR("Fatal error: %s", nghttp2_strerror(rv));
 		return -1;
 		return -1;
@@ -528,7 +557,7 @@ static int on_frame_recv_callback(
 				stream_data = nghttp2_session_get_stream_user_data(
 				stream_data = nghttp2_session_get_stream_user_data(
 						session, frame->hd.stream_id);
 						session, frame->hd.stream_id);
 				/* For DATA and HEADERS frame, this callback may be called after
 				/* For DATA and HEADERS frame, this callback may be called after
-				   on_stream_close_callback. Check that stream still alive. */
+         on_stream_close_callback. Check that stream still alive. */
 				if(!stream_data) {
 				if(!stream_data) {
 					return 0;
 					return 0;
 				}
 				}
@@ -563,7 +592,7 @@ static void initialize_nghttp2_session(http2_session_data *session_data)
 
 
 	nghttp2_session_callbacks_new(&callbacks);
 	nghttp2_session_callbacks_new(&callbacks);
 
 
-	nghttp2_session_callbacks_set_send_callback2(callbacks, send_callback);
+	nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
 
 
 	nghttp2_session_callbacks_set_on_frame_recv_callback(
 	nghttp2_session_callbacks_set_on_frame_recv_callback(
 			callbacks, on_frame_recv_callback);
 			callbacks, on_frame_recv_callback);
@@ -647,14 +676,22 @@ static void eventcb(struct bufferevent *bev, short events, void *ptr)
 		SSL *ssl;
 		SSL *ssl;
 		(void)bev;
 		(void)bev;
 
 
-		LM_ERR("%s connected\n", session_data->client_addr);
+		fprintf(stderr, "%s connected\n", session_data->client_addr);
 
 
 		ssl = bufferevent_openssl_get_ssl(session_data->bev);
 		ssl = bufferevent_openssl_get_ssl(session_data->bev);
 
 
-		SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
+#ifndef OPENSSL_NO_NEXTPROTONEG
+		SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
+#endif /* !OPENSSL_NO_NEXTPROTONEG */
+#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) {
 		if(alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
-			LM_ERR("%s h2 is not negotiated\n", session_data->client_addr);
+			fprintf(stderr, "%s h2 is not negotiated\n",
+					session_data->client_addr);
 			delete_http2_session_data(session_data);
 			delete_http2_session_data(session_data);
 			return;
 			return;
 		}
 		}
@@ -670,11 +707,11 @@ static void eventcb(struct bufferevent *bev, short events, void *ptr)
 		return;
 		return;
 	}
 	}
 	if(events & BEV_EVENT_EOF) {
 	if(events & BEV_EVENT_EOF) {
-		LM_ERR("%s EOF\n", session_data->client_addr);
+		fprintf(stderr, "%s EOF\n", session_data->client_addr);
 	} else if(events & BEV_EVENT_ERROR) {
 	} else if(events & BEV_EVENT_ERROR) {
-		LM_ERR("%s network error\n", session_data->client_addr);
+		fprintf(stderr, "%s network error\n", session_data->client_addr);
 	} else if(events & BEV_EVENT_TIMEOUT) {
 	} else if(events & BEV_EVENT_TIMEOUT) {
-		LM_ERR("%s timeout\n", session_data->client_addr);
+		fprintf(stderr, "%s timeout\n", session_data->client_addr);
 	}
 	}
 	delete_http2_session_data(session_data);
 	delete_http2_session_data(session_data);
 }
 }
@@ -745,6 +782,19 @@ int nghttp2_server_run(void)
 	act.sa_handler = SIG_IGN;
 	act.sa_handler = SIG_IGN;
 	sigaction(SIGPIPE, &act, NULL);
 	sigaction(SIGPIPE, &act, NULL);
 
 
+#if OPENSSL_VERSION_NUMBER >= 0x1010000fL
+	/* No explicit initialization is required. */
+#elif defined(OPENSSL_IS_BORINGSSL)
+	CRYPTO_library_init();
+#else  /* !(OPENSSL_VERSION_NUMBER >= 0x1010000fL) &&                          \
+          !defined(OPENSSL_IS_BORINGSSL) */
+	OPENSSL_config(NULL);
+	SSL_load_error_strings();
+	SSL_library_init();
+	OpenSSL_add_all_algorithms();
+#endif /* !(OPENSSL_VERSION_NUMBER >= 0x1010000fL) &&                          \
+          !defined(OPENSSL_IS_BORINGSSL) */
+
 	ssl_ctx = create_ssl_ctx(
 	ssl_ctx = create_ssl_ctx(
 			_nghttp2_tls_private_key.s, _nghttp2_tls_public_key.s);
 			_nghttp2_tls_private_key.s, _nghttp2_tls_public_key.s);
 	evbase = event_base_new();
 	evbase = event_base_new();
@@ -756,5 +806,6 @@ int nghttp2_server_run(void)
 	event_base_free(evbase);
 	event_base_free(evbase);
 	SSL_CTX_free(ssl_ctx);
 	SSL_CTX_free(ssl_ctx);
 
 
+
 	return 0;
 	return 0;
 }
 }