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.
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
#include "asio_client_session_tls_impl.h"
|
#include "asio_client_session_tls_impl.h"
|
||||||
|
#include "asio_common.h"
|
||||||
|
|
||||||
namespace nghttp2 {
|
namespace nghttp2 {
|
||||||
namespace asio_http2 {
|
namespace asio_http2 {
|
||||||
|
@ -59,6 +60,13 @@ void session_tls_impl::start_connect(tcp::resolver::iterator endpoint_it) {
|
||||||
not_connected(ec);
|
not_connected(ec);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!tls_h2_negotiated(socket_)) {
|
||||||
|
not_connected(
|
||||||
|
make_error_code(NGHTTP2_ASIO_ERR_TLS_NO_APP_PROTO_NEGOTIATED));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
connected(endpoint_it);
|
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);
|
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;
|
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());
|
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) {
|
generator_cb string_generator(std::string data) {
|
||||||
auto strio = std::make_shared<std::pair<std::string, size_t>>(std::move(data),
|
auto strio = std::make_shared<std::pair<std::string, size_t>>(std::move(data),
|
||||||
data.size());
|
data.size());
|
||||||
|
@ -144,5 +169,23 @@ boost::system::error_code host_service_from_uri(boost::system::error_code &ec,
|
||||||
return 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 asio_http2
|
||||||
} // namespace nghttp2
|
} // 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_error ev);
|
||||||
|
|
||||||
|
boost::system::error_code make_error_code(nghttp2_asio_error ev);
|
||||||
|
|
||||||
generator_cb string_generator(std::string data);
|
generator_cb string_generator(std::string data);
|
||||||
|
|
||||||
// Returns generator_cb, which just returns NGHTTP2_ERR_DEFERRED
|
// 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);
|
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 asio_http2
|
||||||
|
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "asio_server.h"
|
#include "asio_server.h"
|
||||||
|
|
||||||
#include "asio_server_connection.h"
|
#include "asio_server_connection.h"
|
||||||
|
#include "asio_common.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
namespace nghttp2 {
|
namespace nghttp2 {
|
||||||
|
@ -130,9 +131,15 @@ void server::start_accept(boost::asio::ssl::context &tls_context,
|
||||||
new_connection->socket().async_handshake(
|
new_connection->socket().async_handshake(
|
||||||
boost::asio::ssl::stream_base::server,
|
boost::asio::ssl::stream_base::server,
|
||||||
[new_connection](const boost::system::error_code &e) {
|
[new_connection](const boost::system::error_code &e) {
|
||||||
if (!e) {
|
if (e) {
|
||||||
new_connection->start();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!tls_h2_negotiated(new_connection->socket())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_connection->start();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,19 @@ std::vector<unsigned char> &get_alpn_token() {
|
||||||
}
|
}
|
||||||
} // namespace
|
} // 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
|
boost::system::error_code
|
||||||
configure_tls_context_easy(boost::system::error_code &ec,
|
configure_tls_context_easy(boost::system::error_code &ec,
|
||||||
boost::asio::ssl::context &tls_context) {
|
boost::asio::ssl::context &tls_context) {
|
||||||
|
@ -81,6 +94,11 @@ configure_tls_context_easy(boost::system::error_code &ec,
|
||||||
},
|
},
|
||||||
nullptr);
|
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;
|
return ec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,16 +38,6 @@
|
||||||
|
|
||||||
#include <nghttp2/nghttp2.h>
|
#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 nghttp2 {
|
||||||
|
|
||||||
namespace asio_http2 {
|
namespace asio_http2 {
|
||||||
|
@ -132,8 +122,29 @@ boost::system::error_code host_service_from_uri(boost::system::error_code &ec,
|
||||||
std::string &service,
|
std::string &service,
|
||||||
const std::string &uri);
|
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 asio_http2
|
||||||
|
|
||||||
} // namespace nghttp2
|
} // 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
|
#endif // ASIO_HTTP2_H
|
||||||
|
|
Loading…
Reference in New Issue