Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrating nghttp2-asio With Existing HTTP/1.1 Code #1

Open
DragonOsman opened this issue Aug 2, 2022 · 1 comment
Open

Integrating nghttp2-asio With Existing HTTP/1.1 Code #1

DragonOsman opened this issue Aug 2, 2022 · 1 comment

Comments

@DragonOsman
Copy link

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?

@srinarasi
Copy link
Collaborator

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants