nghttp2-asio icon indicating copy to clipboard operation
nghttp2-asio copied to clipboard

Integrating nghttp2-asio With Existing HTTP/1.1 Code

Open DragonOsman opened this issue 3 years ago • 2 comments

Like I said elsewhere, I have this server app that I've enabled ALPN in that I want to support HTTP/2 in. I want to use the nghttp2 C++ API directly instead of dropping it in as a reverse proxy. Could you point me to a good example that shows how to do this? And where and what functions should I call from the nghttp2 library to do this?

I have this code in main:

                tcp::acceptor acceptor{ ioc, { address, port } };
		std::cout << "Starting server at " << address << ':' << port << "...\n";
		for (;;)
		{
			// This will receive the new connection
			tcp::socket socket{ ioc };

			// Block until we get a connection
			acceptor.accept(socket);

			// Launch the session, transferring ownership of the socket
			std::thread([=, socket = std::move(socket), &ctx]() mutable {
				do_session(socket, ctx, doc_root, googlekey, currencykey);
			}).detach();
		}

This is how I'm running the server. And I also have this code in do_session:

        // Construct the stream around the socket
	ssl::stream<tcp::socket&> stream{ socket, ctx };

	// call client hello processing function and pass in callback
	auto ssl_ctx{ ctx.native_handle() };
	SSL* ssl{ SSL_new(ssl_ctx) };
	int alert_val{ 1 };
	int* alert{ &alert_val };
	void* arg{};
	SSL_CTX_set_client_hello_cb(ssl_ctx, set_client_hello_cb(ssl, alert, arg), nullptr);

	// Perform the SSL handshake
	stream.handshake(ssl::stream_base::server, ec);
	if (ec)
	{
		std::cerr << "Lines 692 and 693:\n";
		fail(ec, "handshake");
	}

And these are the callbacks passed to the SSL_CTX_set_client_hello_cb and SSL_CTX_set_alpn_select_cb functions, respectively:

SSL_client_hello_cb_fn set_client_hello_cb(SSL* ssl, int* alert, void* arg)
{
	constexpr int ext_type{ TLSEXT_TYPE_application_layer_protocol_negotiation };
	const unsigned char** alpn_str{};
	std::size_t* alpn_str_len{};
	const int alpn_ext_present{ SSL_client_hello_get0_ext(ssl, ext_type, 
		                        alpn_str, alpn_str_len) };
	if (alpn_ext_present == 1)  // 1 means alpn extension is present
	{
		ssl::context ctx{ ssl::context::tlsv13 };
		load_server_certificate(ctx);
		auto* ssl_ctx{ ctx.native_handle() };
		const unsigned char** out{};
		unsigned char* outlen{};
		const unsigned char* in{};
		unsigned inlen{};
		void* arg{};
		SSL_CTX_set_alpn_select_cb(ssl_ctx, 
			set_alpn_cb(ssl, out, outlen, in, inlen, arg), 
			nullptr);

		return reinterpret_cast<SSL_client_hello_cb_fn>(SSL_CLIENT_HELLO_SUCCESS);
	}
	else if (alpn_ext_present == 0)  // 0 means alpn extension isn't present
	{
		return reinterpret_cast<SSL_client_hello_cb_fn>(SSL_CLIENT_HELLO_ERROR);
	}
}

and

SSL_CTX_alpn_select_cb_func set_alpn_cb(SSL* ssl, const unsigned char** out, unsigned char* outlen,
	const unsigned char* in, unsigned int inlen, void* arg)
{
	for (std::size_t i{}; i < inlen; i += 1 + in[i])
	{
		if (in[i + 0] == 2 && in[i + 1] == 'h' && in[i + 2] == '2')
		{
			*out = in + i + 1;
			*outlen = in[i];
		}
	}

	if (out[0][0] == 2 && out[0][1] == 'h' && out[0][2] == '2')
	{
		return reinterpret_cast<SSL_CTX_alpn_select_cb_func>(SSL_TLSEXT_ERR_OK);
	}
	return reinterpret_cast<SSL_CTX_alpn_select_cb_func>(SSL_TLSEXT_ERR_NOACK);
}

Did I do this right? And should I call the nghttp2 functions for HTTP/2 in main or in do_session?

And how come you're not maintaining nghttp2-asio? I mean, the last commit was just 10 days ago, wasn't it?

DragonOsman avatar Aug 02 '22 20:08 DragonOsman

I don't understand what problem you are facing. Have you tried the examples here? I will copy those examples to this repo.

If you are asking if nghttp2 understands HTTP 1.1, this may be relevant to you. nghttp2/nghttp2#585

The maintainers of nghttp2/nghttp2 don't have the resources to maintain this library. So it has been moved here. It's upto the community to take it forward from here.

srinarasi avatar Aug 06 '22 10:08 srinarasi

https://github.com/fantasy-peak/simple_http

nqf avatar May 28 '25 00:05 nqf