asio: ALPN support
This commit is contained in:
parent
ab1f70dcd7
commit
b89f1f5869
|
@ -23,6 +23,7 @@
|
|||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "asio_client_session_tls_impl.h"
|
||||
#include "asio_common.h"
|
||||
|
||||
namespace nghttp2 {
|
||||
namespace asio_http2 {
|
||||
|
@ -59,6 +60,13 @@ void session_tls_impl::start_connect(tcp::resolver::iterator endpoint_it) {
|
|||
not_connected(ec);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tls_h2_negotiated(socket_)) {
|
||||
not_connected(
|
||||
make_error_code(NGHTTP2_ASIO_ERR_TLS_NO_APP_PROTO_NEGOTIATED));
|
||||
return;
|
||||
}
|
||||
|
||||
connected(endpoint_it);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -56,6 +56,12 @@ configure_tls_context(boost::system::error_code &ec,
|
|||
|
||||
SSL_CTX_set_next_proto_select_cb(ctx, client_select_next_proto_cb, nullptr);
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
auto proto_list = util::get_default_alpn();
|
||||
|
||||
SSL_CTX_set_alpn_protos(ctx, proto_list.data(), proto_list.size());
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,31 @@ boost::system::error_code make_error_code(nghttp2_error ev) {
|
|||
return boost::system::error_code(static_cast<int>(ev), nghttp2_category());
|
||||
}
|
||||
|
||||
class nghttp2_asio_category_impl : public boost::system::error_category {
|
||||
public:
|
||||
const char *name() const noexcept { return "nghttp2_asio"; }
|
||||
std::string message(int ev) const {
|
||||
switch (ev) {
|
||||
case NGHTTP2_ASIO_ERR_NO_ERROR:
|
||||
return "no error";
|
||||
case NGHTTP2_ASIO_ERR_TLS_NO_APP_PROTO_NEGOTIATED:
|
||||
return "tls: no application protocol negotiated";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const boost::system::error_category &nghttp2_asio_category() noexcept {
|
||||
static nghttp2_asio_category_impl cat;
|
||||
return cat;
|
||||
}
|
||||
|
||||
boost::system::error_code make_error_code(nghttp2_asio_error ev) {
|
||||
return boost::system::error_code(static_cast<int>(ev),
|
||||
nghttp2_asio_category());
|
||||
}
|
||||
|
||||
generator_cb string_generator(std::string data) {
|
||||
auto strio = std::make_shared<std::pair<std::string, size_t>>(std::move(data),
|
||||
data.size());
|
||||
|
@ -144,5 +169,23 @@ boost::system::error_code host_service_from_uri(boost::system::error_code &ec,
|
|||
return ec;
|
||||
}
|
||||
|
||||
bool tls_h2_negotiated(ssl_socket &socket) {
|
||||
auto ssl = socket.native_handle();
|
||||
|
||||
const unsigned char *next_proto = nullptr;
|
||||
unsigned int next_proto_len = 0;
|
||||
|
||||
SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
|
||||
if (next_proto == nullptr) {
|
||||
SSL_get0_alpn_selected(ssl, &next_proto, &next_proto_len);
|
||||
}
|
||||
|
||||
if (next_proto == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return util::check_h2_is_selected(next_proto, next_proto_len);
|
||||
}
|
||||
|
||||
} // namespace asio_http2
|
||||
} // namespace nghttp2
|
||||
|
|
|
@ -39,6 +39,8 @@ namespace asio_http2 {
|
|||
|
||||
boost::system::error_code make_error_code(nghttp2_error ev);
|
||||
|
||||
boost::system::error_code make_error_code(nghttp2_asio_error ev);
|
||||
|
||||
generator_cb string_generator(std::string data);
|
||||
|
||||
// Returns generator_cb, which just returns NGHTTP2_ERR_DEFERRED
|
||||
|
@ -58,6 +60,12 @@ void split_path(uri_ref &dst, InputIt first, InputIt last) {
|
|||
dst.raw_query.assign(query_first, last);
|
||||
}
|
||||
|
||||
using boost::asio::ip::tcp;
|
||||
|
||||
using ssl_socket = boost::asio::ssl::stream<tcp::socket>;
|
||||
|
||||
bool tls_h2_negotiated(ssl_socket &socket);
|
||||
|
||||
} // namespace asio_http2
|
||||
|
||||
} // namespace nghttp2
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "asio_server.h"
|
||||
|
||||
#include "asio_server_connection.h"
|
||||
#include "asio_common.h"
|
||||
#include "util.h"
|
||||
|
||||
namespace nghttp2 {
|
||||
|
@ -130,9 +131,15 @@ void server::start_accept(boost::asio::ssl::context &tls_context,
|
|||
new_connection->socket().async_handshake(
|
||||
boost::asio::ssl::stream_base::server,
|
||||
[new_connection](const boost::system::error_code &e) {
|
||||
if (!e) {
|
||||
new_connection->start();
|
||||
if (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tls_h2_negotiated(new_connection->socket())) {
|
||||
return;
|
||||
}
|
||||
|
||||
new_connection->start();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,19 @@ std::vector<unsigned char> &get_alpn_token() {
|
|||
}
|
||||
} // namespace
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
namespace {
|
||||
int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
||||
unsigned char *outlen, const unsigned char *in,
|
||||
unsigned int inlen, void *arg) {
|
||||
if (!util::select_h2(out, outlen, in, inlen)) {
|
||||
return SSL_TLSEXT_ERR_NOACK;
|
||||
}
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
} // namespace
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
|
||||
boost::system::error_code
|
||||
configure_tls_context_easy(boost::system::error_code &ec,
|
||||
boost::asio::ssl::context &tls_context) {
|
||||
|
@ -81,6 +94,11 @@ configure_tls_context_easy(boost::system::error_code &ec,
|
|||
},
|
||||
nullptr);
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
// ALPN selection callback
|
||||
SSL_CTX_set_alpn_select_cb(ctx, alpn_select_proto_cb, nullptr);
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,16 +38,6 @@
|
|||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
namespace boost {
|
||||
namespace system {
|
||||
|
||||
template <> struct is_error_code_enum<nghttp2_error> {
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
|
||||
} // namespace system
|
||||
} // namespace boost
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
namespace asio_http2 {
|
||||
|
@ -132,8 +122,29 @@ boost::system::error_code host_service_from_uri(boost::system::error_code &ec,
|
|||
std::string &service,
|
||||
const std::string &uri);
|
||||
|
||||
enum nghttp2_asio_error {
|
||||
NGHTTP2_ASIO_ERR_NO_ERROR = 0,
|
||||
NGHTTP2_ASIO_ERR_TLS_NO_APP_PROTO_NEGOTIATED = 1,
|
||||
};
|
||||
|
||||
} // namespace asio_http2
|
||||
|
||||
} // namespace nghttp2
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace system {
|
||||
|
||||
template <> struct is_error_code_enum<nghttp2_error> {
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
|
||||
template <> struct is_error_code_enum<nghttp2::asio_http2::nghttp2_asio_error> {
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
|
||||
} // namespace system
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // ASIO_HTTP2_H
|
||||
|
|
Loading…
Reference in New Issue