Integrating nghttp2-asio With Existing HTTP/1.1 Code
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?
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.
https://github.com/fantasy-peak/simple_http