You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by ma...@apache.org on 2019/04/09 07:16:20 UTC
[trafficserver] branch quic-latest updated: Add HTTP/3 support to
traffic_quic cmd
This is an automated email from the ASF dual-hosted git repository.
masaori pushed a commit to branch quic-latest
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/quic-latest by this push:
new 41c06df Add HTTP/3 support to traffic_quic cmd
41c06df is described below
commit 41c06df698844c80d2dd146b8ce5fb7cc5853c91
Author: Masaori Koshiba <ma...@gmail.com>
AuthorDate: Fri Apr 5 10:12:57 2019 +0900
Add HTTP/3 support to traffic_quic cmd
---
iocore/net/I_NetVConnection.h | 6 +
iocore/net/QUICNetVConnection.cc | 3 +-
iocore/net/quic/QUICConfig.cc | 13 +-
iocore/net/quic/QUICTLS.h | 2 +-
iocore/net/quic/QUICTLS_openssl.cc | 5 +-
proxy/http2/HTTP2.cc | 8 ++
proxy/http3/Http3App.cc | 59 ++++++---
proxy/http3/Http3App.h | 16 ++-
proxy/http3/Http3ClientTransaction.cc | 60 ++++++---
proxy/http3/Http3ClientTransaction.h | 3 +-
proxy/http3/Http3HeaderFramer.cc | 52 ++------
proxy/http3/Http3HeaderVIOAdaptor.cc | 7 +-
src/traffic_quic/Makefile.inc | 66 +++++-----
src/traffic_quic/quic_client.cc | 237 ++++++++++++++++++++++++++--------
src/traffic_quic/quic_client.h | 47 ++++++-
src/traffic_quic/traffic_quic.cc | 105 +++++++++++++--
16 files changed, 489 insertions(+), 200 deletions(-)
diff --git a/iocore/net/I_NetVConnection.h b/iocore/net/I_NetVConnection.h
index 786c7af..1dedc0d 100644
--- a/iocore/net/I_NetVConnection.h
+++ b/iocore/net/I_NetVConnection.h
@@ -179,6 +179,10 @@ struct NetVCOptions {
EventType etype;
+ /** ALPN protocol-lists. The format is OpenSSL protocol-lists format (vector of 8-bit length-prefixed, byte strings)
+ https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_alpn_protos.html
+ */
+ std::string_view alpn_protos;
/** Server name to use for SNI data on an outbound connection.
*/
ats_scoped_str sni_servername;
@@ -224,6 +228,7 @@ struct NetVCOptions {
NetVCOptions() { reset(); }
~NetVCOptions() {}
+
/** Set the SNI server name.
A local copy is made of @a name.
*/
@@ -240,6 +245,7 @@ struct NetVCOptions {
}
return *this;
}
+
self &
set_ssl_servername(const char *name)
{
diff --git a/iocore/net/QUICNetVConnection.cc b/iocore/net/QUICNetVConnection.cc
index 1e25171..bcc581d 100644
--- a/iocore/net/QUICNetVConnection.cc
+++ b/iocore/net/QUICNetVConnection.cc
@@ -2236,7 +2236,8 @@ QUICNetVConnection::_setup_handshake_protocol(SSL_CTX *ctx)
{
// Initialize handshake protocol specific stuff
// For QUICv1 TLS is the only option
- QUICTLS *tls = new QUICTLS(this->_pp_key_info, ctx, this->direction(), this->_quic_config->session_file());
+ QUICTLS *tls =
+ new QUICTLS(this->_pp_key_info, ctx, this->direction(), this->options, this->_quic_config->session_file());
SSL_set_ex_data(tls->ssl_handle(), QUIC::ssl_quic_qc_index, static_cast<QUICConnection *>(this));
return tls;
}
diff --git a/iocore/net/quic/QUICConfig.cc b/iocore/net/quic/QUICConfig.cc
index 139df1a..4314caa 100644
--- a/iocore/net/quic/QUICConfig.cc
+++ b/iocore/net/quic/QUICConfig.cc
@@ -35,11 +35,6 @@
#define QUICConfDebug(fmt, ...) Debug("quic_conf", fmt, ##__VA_ARGS__)
-// OpenSSL protocol-lists format (vector of 8-bit length-prefixed, byte strings)
-// https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_alpn_protos.html
-// Should be integrate with IP_PROTO_TAG_HTTP_QUIC in ts/ink_inet.h ?
-using namespace std::literals;
-static constexpr std::string_view QUIC_ALPN_PROTO_LIST("\5hq-18"sv);
int QUICConfig::_config_id = 0;
int QUICConfigParams::_connection_table_size = 65521;
@@ -74,16 +69,14 @@ quic_new_ssl_ctx()
return ssl_ctx;
}
+/**
+ ALPN and SNI should be set to SSL object with NETVC_OPTIONS
+ **/
static SSL_CTX *
quic_init_client_ssl_ctx(const QUICConfigParams *params)
{
SSL_CTX *ssl_ctx = quic_new_ssl_ctx();
- if (SSL_CTX_set_alpn_protos(ssl_ctx, reinterpret_cast<const unsigned char *>(QUIC_ALPN_PROTO_LIST.data()),
- QUIC_ALPN_PROTO_LIST.size()) != 0) {
- Error("SSL_CTX_set_alpn_protos failed");
- }
-
if (params->client_supported_groups() != nullptr) {
if (SSL_CTX_set1_groups_list(ssl_ctx, params->client_supported_groups()) != 1) {
Error("SSL_CTX_set1_groups_list failed");
diff --git a/iocore/net/quic/QUICTLS.h b/iocore/net/quic/QUICTLS.h
index 5e8d13d..5a2ac56 100644
--- a/iocore/net/quic/QUICTLS.h
+++ b/iocore/net/quic/QUICTLS.h
@@ -40,7 +40,7 @@ class QUICTLS : public QUICHandshakeProtocol
{
public:
QUICTLS(QUICPacketProtectionKeyInfo &pp_key_info, SSL_CTX *ssl_ctx, NetVConnectionContext_t nvc_ctx,
- const char *session_file = nullptr);
+ const NetVCOptions &netvc_options, const char *session_file = nullptr);
~QUICTLS();
// TODO: integrate with _early_data_processed
diff --git a/iocore/net/quic/QUICTLS_openssl.cc b/iocore/net/quic/QUICTLS_openssl.cc
index d9951fe..d6d9842 100644
--- a/iocore/net/quic/QUICTLS_openssl.cc
+++ b/iocore/net/quic/QUICTLS_openssl.cc
@@ -329,13 +329,16 @@ QUICTLS::update_key_materials_on_key_cb(int name, const uint8_t *secret, size_t
}
QUICTLS::QUICTLS(QUICPacketProtectionKeyInfo &pp_key_info, SSL_CTX *ssl_ctx, NetVConnectionContext_t nvc_ctx,
- const char *session_file)
+ const NetVCOptions &netvc_options, const char *session_file)
: QUICHandshakeProtocol(pp_key_info), _session_file(session_file), _ssl(SSL_new(ssl_ctx)), _netvc_context(nvc_ctx)
{
ink_assert(this->_netvc_context != NET_VCONNECTION_UNSET);
if (this->_netvc_context == NET_VCONNECTION_OUT) {
SSL_set_connect_state(this->_ssl);
+
+ SSL_set_alpn_protos(this->_ssl, reinterpret_cast<const unsigned char *>(netvc_options.alpn_protos.data()), netvc_options.alpn_protos.size());
+ SSL_set_tlsext_host_name(this->_ssl, netvc_options.sni_servername.get());
} else {
SSL_set_accept_state(this->_ssl);
}
diff --git a/proxy/http2/HTTP2.cc b/proxy/http2/HTTP2.cc
index e1a0a4e..b5c1e81 100644
--- a/proxy/http2/HTTP2.cc
+++ b/proxy/http2/HTTP2.cc
@@ -477,6 +477,11 @@ http2_convert_header_from_2_to_1_1(HTTPHdr *headers)
headers->field_delete(HTTP2_VALUE_AUTHORITY, HTTP2_LEN_AUTHORITY);
headers->field_delete(HTTP2_VALUE_PATH, HTTP2_LEN_PATH);
} else {
+ // Set HTTP Version 1.1
+ int32_t version = HTTP_VERSION(1, 1);
+ http_hdr_version_set(headers->m_http, version);
+
+ // Set status from :status
int status_len;
const char *status;
@@ -521,6 +526,9 @@ http2_generate_h2_header_from_1_1(HTTPHdr *headers, HTTPHdr *h2_headers)
int value_len;
// Add ':authority' header field
+ // TODO: remove host/Host header
+ // [RFC 7540] 8.1.2.3. Clients that generate HTTP/2 requests directly SHOULD use the ":authority" pseudo-header field instead of
+ // the Host header field.
field = h2_headers->field_create(HTTP2_VALUE_AUTHORITY, HTTP2_LEN_AUTHORITY);
value = headers->host_get(&value_len);
if (headers->is_port_in_header()) {
diff --git a/proxy/http3/Http3App.cc b/proxy/http3/Http3App.cc
index 8b53cbd..1174e39 100644
--- a/proxy/http3/Http3App.cc
+++ b/proxy/http3/Http3App.cc
@@ -37,13 +37,13 @@ static constexpr char debug_tag_v[] = "v_http3";
Http3App::Http3App(QUICNetVConnection *client_vc, IpAllow::ACL session_acl) : QUICApplication(client_vc)
{
- this->_client_session = new Http3ClientSession(client_vc);
- this->_client_session->acl = std::move(session_acl);
- this->_client_session->new_connection(client_vc, nullptr, nullptr);
+ this->_ssn = new Http3ClientSession(client_vc);
+ this->_ssn->acl = std::move(session_acl);
+ this->_ssn->new_connection(client_vc, nullptr, nullptr);
this->_qc->stream_manager()->set_default_application(this);
- this->_settings_handler = new Http3SettingsHandler(this->_client_session);
+ this->_settings_handler = new Http3SettingsHandler(this->_ssn);
this->_control_stream_dispatcher.add_handler(this->_settings_handler);
this->_settings_framer = new Http3SettingsFramer(client_vc->get_context());
@@ -54,7 +54,7 @@ Http3App::Http3App(QUICNetVConnection *client_vc, IpAllow::ACL session_acl) : QU
Http3App::~Http3App()
{
- delete this->_client_session;
+ delete this->_ssn;
delete this->_settings_handler;
delete this->_settings_framer;
}
@@ -71,15 +71,16 @@ Http3App::start()
this->_handle_uni_stream_on_write_ready(VC_EVENT_WRITE_READY, this->_local_control_stream);
}
- error = this->create_uni_stream(stream_id, Http3StreamType::QPACK_ENCODER);
- if (error == nullptr) {
- this->_handle_uni_stream_on_write_ready(VC_EVENT_WRITE_READY, this->_find_stream_io(stream_id));
- }
+ // TODO: Open uni streams for QPACK when dynamic table is used
+ // error = this->create_uni_stream(stream_id, Http3StreamType::QPACK_ENCODER);
+ // if (error == nullptr) {
+ // this->_handle_uni_stream_on_write_ready(VC_EVENT_WRITE_READY, this->_find_stream_io(stream_id));
+ // }
- error = this->create_uni_stream(stream_id, Http3StreamType::QPACK_DECODER);
- if (error == nullptr) {
- this->_handle_uni_stream_on_write_ready(VC_EVENT_WRITE_READY, this->_find_stream_io(stream_id));
- }
+ // error = this->create_uni_stream(stream_id, Http3StreamType::QPACK_DECODER);
+ // if (error == nullptr) {
+ // this->_handle_uni_stream_on_write_ready(VC_EVENT_WRITE_READY, this->_find_stream_io(stream_id));
+ // }
}
int
@@ -113,6 +114,12 @@ Http3App::main_event_handler(int event, Event *data)
}
break;
case VC_EVENT_EOS:
+ if (stream_io->is_bidirectional()) {
+ this->_handle_bidi_stream_on_eos(event, stream_io);
+ } else {
+ this->_handle_uni_stream_on_eos(event, stream_io);
+ }
+ break;
case VC_EVENT_ERROR:
case VC_EVENT_INACTIVITY_TIMEOUT:
case VC_EVENT_ACTIVE_TIMEOUT:
@@ -196,10 +203,10 @@ Http3App::_handle_bidi_stream_on_read_ready(int event, QUICStreamIO *stream_io)
uint8_t dummy;
if (stream_io->peek(&dummy, 1)) {
QUICStreamId stream_id = stream_io->stream_id();
- Http3ClientTransaction *txn = static_cast<Http3ClientTransaction *>(this->_client_session->get_transaction(stream_id));
+ Http3ClientTransaction *txn = static_cast<Http3ClientTransaction *>(this->_ssn->get_transaction(stream_id));
if (txn == nullptr) {
- txn = new Http3ClientTransaction(this->_client_session, stream_io);
+ txn = new Http3ClientTransaction(this->_ssn, stream_io);
SCOPED_MUTEX_LOCK(lock, txn->mutex, this_ethread());
txn->new_transaction();
@@ -237,20 +244,32 @@ Http3App::_handle_uni_stream_on_write_ready(int /* event */, QUICStreamIO *strea
}
void
+Http3App::_handle_bidi_stream_on_eos(int /* event */, QUICStreamIO *stream_io)
+{
+ // TODO: handle eos
+}
+
+void
+Http3App::_handle_uni_stream_on_eos(int /* event */, QUICStreamIO *stream_io)
+{
+ // TODO: handle eos
+}
+
+void
Http3App::_set_qpack_stream(Http3StreamType type, QUICStreamIO *stream_io)
{
// Change app to QPACK from Http3
if (type == Http3StreamType::QPACK_ENCODER) {
if (this->_qc->direction() == NET_VCONNECTION_IN) {
- this->_client_session->remote_qpack()->set_encoder_stream(stream_io);
+ this->_ssn->remote_qpack()->set_encoder_stream(stream_io);
} else {
- this->_client_session->local_qpack()->set_encoder_stream(stream_io);
+ this->_ssn->local_qpack()->set_encoder_stream(stream_io);
}
} else if (type == Http3StreamType::QPACK_DECODER) {
if (this->_qc->direction() == NET_VCONNECTION_IN) {
- this->_client_session->local_qpack()->set_decoder_stream(stream_io);
+ this->_ssn->local_qpack()->set_decoder_stream(stream_io);
} else {
- this->_client_session->remote_qpack()->set_decoder_stream(stream_io);
+ this->_ssn->remote_qpack()->set_decoder_stream(stream_io);
}
} else {
ink_abort("unkown stream type");
@@ -261,7 +280,7 @@ void
Http3App::_handle_bidi_stream_on_write_ready(int event, QUICStreamIO *stream_io)
{
QUICStreamId stream_id = stream_io->stream_id();
- Http3ClientTransaction *txn = static_cast<Http3ClientTransaction *>(this->_client_session->get_transaction(stream_id));
+ Http3ClientTransaction *txn = static_cast<Http3ClientTransaction *>(this->_ssn->get_transaction(stream_id));
if (txn != nullptr) {
SCOPED_MUTEX_LOCK(lock, txn->mutex, this_ethread());
txn->handleEvent(event);
diff --git a/proxy/http3/Http3App.h b/proxy/http3/Http3App.h
index 87d2f26..e4a31c0 100644
--- a/proxy/http3/Http3App.h
+++ b/proxy/http3/Http3App.h
@@ -44,23 +44,29 @@ class Http3App : public QUICApplication
{
public:
Http3App(QUICNetVConnection *client_vc, IpAllow::ACL session_acl);
- ~Http3App();
+ virtual ~Http3App();
- void start();
- int main_event_handler(int event, Event *data);
+ virtual void start();
+ virtual int main_event_handler(int event, Event *data);
// TODO: Return StreamIO. It looks bother that coller have to look up StreamIO by stream id.
// Why not create_bidi_stream ?
QUICConnectionErrorUPtr create_uni_stream(QUICStreamId &new_stream_id, Http3StreamType type);
+protected:
+ // TODO: create Http3Session
+ Http3ClientSession *_ssn = nullptr;
+
private:
void _handle_uni_stream_on_read_ready(int event, QUICStreamIO *stream_io);
- void _handle_bidi_stream_on_read_ready(int event, QUICStreamIO *stream_io);
void _handle_uni_stream_on_write_ready(int event, QUICStreamIO *stream_io);
+ void _handle_uni_stream_on_eos(int event, QUICStreamIO *stream_io);
+ void _handle_bidi_stream_on_read_ready(int event, QUICStreamIO *stream_io);
void _handle_bidi_stream_on_write_ready(int event, QUICStreamIO *stream_io);
+ void _handle_bidi_stream_on_eos(int event, QUICStreamIO *stream_io);
+
void _set_qpack_stream(Http3StreamType type, QUICStreamIO *stream_io);
- Http3ClientSession *_client_session = nullptr;
Http3FrameHandler *_settings_handler = nullptr;
Http3FrameGenerator *_settings_framer = nullptr;
diff --git a/proxy/http3/Http3ClientTransaction.cc b/proxy/http3/Http3ClientTransaction.cc
index 228621b..42467c0 100644
--- a/proxy/http3/Http3ClientTransaction.cc
+++ b/proxy/http3/Http3ClientTransaction.cc
@@ -64,12 +64,20 @@ HQClientTransaction::HQClientTransaction(HQClientSession *session, QUICStreamIO
this->set_parent(session);
this->sm_reader = this->_read_vio_buf.alloc_reader();
- this->_request_header.create(HTTP_TYPE_REQUEST);
+
+ HTTPType http_type = HTTP_TYPE_UNKNOWN;
+ if (this->direction() == NET_VCONNECTION_OUT) {
+ http_type = HTTP_TYPE_RESPONSE;
+ } else {
+ http_type = HTTP_TYPE_REQUEST;
+ }
+
+ this->_header.create(http_type);
}
HQClientTransaction::~HQClientTransaction()
{
- this->_request_header.destroy();
+ this->_header.destroy();
}
void
@@ -236,6 +244,12 @@ HQClientTransaction::decrement_client_transactions_stat()
// TODO
}
+NetVConnectionContext_t
+HQClientTransaction::direction() const
+{
+ return this->parent->get_netvc()->get_context();
+}
+
/**
* @brief Replace existing event only if the new event is different than the inprogress event
*/
@@ -311,7 +325,7 @@ Http3ClientTransaction::Http3ClientTransaction(Http3ClientSession *session, QUIC
this->_frame_collector.add_generator(this->_data_framer);
// this->_frame_collector.add_generator(this->_push_controller);
- this->_header_handler = new Http3HeaderVIOAdaptor(&this->_request_header, session->remote_qpack(), this, stream_io->stream_id());
+ this->_header_handler = new Http3HeaderVIOAdaptor(&this->_header, session->remote_qpack(), this, stream_io->stream_id());
this->_data_handler = new Http3StreamDataVIOAdaptor(&this->_read_vio);
this->_frame_dispatcher.add_handler(this->_header_handler);
@@ -332,8 +346,6 @@ int
Http3ClientTransaction::state_stream_open(int event, void *edata)
{
// TODO: should check recursive call?
- Http3TransVDebug("%s (%d)", get_vc_event_name(event), event);
-
if (this->_thread != this_ethread()) {
// Send on to the owning thread
if (this->_cross_thread_event == nullptr) {
@@ -352,6 +364,7 @@ Http3ClientTransaction::state_stream_open(int event, void *edata)
switch (event) {
case VC_EVENT_READ_READY:
case VC_EVENT_READ_COMPLETE: {
+ Http3TransVDebug("%s (%d)", get_vc_event_name(event), event);
int64_t len = this->_process_read_vio();
// if no progress, don't need to signal
if (len > 0) {
@@ -363,7 +376,9 @@ Http3ClientTransaction::state_stream_open(int event, void *edata)
}
case VC_EVENT_WRITE_READY:
case VC_EVENT_WRITE_COMPLETE: {
+ Http3TransVDebug("%s (%d)", get_vc_event_name(event), event);
int64_t len = this->_process_write_vio();
+ // if no progress, don't need to signal
if (len > 0) {
this->_signal_write_event();
}
@@ -379,6 +394,7 @@ Http3ClientTransaction::state_stream_open(int event, void *edata)
break;
}
case QPACK_EVENT_DECODE_COMPLETE: {
+ Http3TransVDebug("%s (%d)", "QPACK_EVENT_DECODE_COMPLETE", event);
int res = this->_on_qpack_decode_complete();
if (res) {
// If READ_READY event is scheduled, should it be canceled?
@@ -387,6 +403,7 @@ Http3ClientTransaction::state_stream_open(int event, void *edata)
break;
}
case QPACK_EVENT_DECODE_FAILED: {
+ Http3TransVDebug("%s (%d)", "QPACK_EVENT_DECODE_FAILED", event);
// FIXME: handle error
break;
}
@@ -506,20 +523,22 @@ Http3ClientTransaction::_convert_header_from_3_to_1_1(HTTPHdr *hdrs)
{
// TODO: do HTTP/3 specific convert, if there
- // Dirty hack to bypass checks
- MIMEField *field;
- if ((field = hdrs->field_find(HTTP3_VALUE_SCHEME, HTTP3_LEN_SCHEME)) == nullptr) {
- char value_s[] = "https";
- MIMEField *scheme_field = hdrs->field_create(HTTP3_VALUE_SCHEME, HTTP3_LEN_SCHEME);
- scheme_field->value_set(hdrs->m_heap, hdrs->m_mime, value_s, sizeof(value_s) - 1);
- hdrs->field_attach(scheme_field);
- }
+ if (http_hdr_type_get(hdrs->m_http) == HTTP_TYPE_REQUEST) {
+ // Dirty hack to bypass checks
+ MIMEField *field;
+ if ((field = hdrs->field_find(HTTP3_VALUE_SCHEME, HTTP3_LEN_SCHEME)) == nullptr) {
+ char value_s[] = "https";
+ MIMEField *scheme_field = hdrs->field_create(HTTP3_VALUE_SCHEME, HTTP3_LEN_SCHEME);
+ scheme_field->value_set(hdrs->m_heap, hdrs->m_mime, value_s, sizeof(value_s) - 1);
+ hdrs->field_attach(scheme_field);
+ }
- if ((field = hdrs->field_find(HTTP3_VALUE_AUTHORITY, HTTP3_LEN_AUTHORITY)) == nullptr) {
- char value_a[] = "localhost";
- MIMEField *authority_field = hdrs->field_create(HTTP3_VALUE_AUTHORITY, HTTP3_LEN_AUTHORITY);
- authority_field->value_set(hdrs->m_heap, hdrs->m_mime, value_a, sizeof(value_a) - 1);
- hdrs->field_attach(authority_field);
+ if ((field = hdrs->field_find(HTTP3_VALUE_AUTHORITY, HTTP3_LEN_AUTHORITY)) == nullptr) {
+ char value_a[] = "localhost";
+ MIMEField *authority_field = hdrs->field_create(HTTP3_VALUE_AUTHORITY, HTTP3_LEN_AUTHORITY);
+ authority_field->value_set(hdrs->m_heap, hdrs->m_mime, value_a, sizeof(value_a) - 1);
+ hdrs->field_attach(authority_field);
+ }
}
return http2_convert_header_from_2_to_1_1(hdrs);
@@ -528,8 +547,9 @@ Http3ClientTransaction::_convert_header_from_3_to_1_1(HTTPHdr *hdrs)
int
Http3ClientTransaction::_on_qpack_decode_complete()
{
- ParseResult res = this->_convert_header_from_3_to_1_1(&this->_request_header);
+ ParseResult res = this->_convert_header_from_3_to_1_1(&this->_header);
if (res == PARSE_RESULT_ERROR) {
+ Http3TransDebug("PARSE_RESULT_ERROR");
return -1;
}
@@ -554,7 +574,7 @@ Http3ClientTransaction::_on_qpack_decode_complete()
writer->add_block();
block = writer->get_current_block();
}
- done = this->_request_header.print(block->start(), block->write_avail(), &bufindex, &tmp);
+ done = this->_header.print(block->end(), block->write_avail(), &bufindex, &tmp);
dumpoffset += bufindex;
writer->fill(bufindex);
if (!done) {
diff --git a/proxy/http3/Http3ClientTransaction.h b/proxy/http3/Http3ClientTransaction.h
index 2d16663..a6fe36b 100644
--- a/proxy/http3/Http3ClientTransaction.h
+++ b/proxy/http3/Http3ClientTransaction.h
@@ -66,6 +66,7 @@ public:
// HQClientTransaction
virtual int state_stream_open(int, void *) = 0;
virtual int state_stream_closed(int event, void *data) = 0;
+ NetVConnectionContext_t direction() const;
protected:
virtual int64_t _process_read_vio() = 0;
@@ -85,7 +86,7 @@ protected:
Event *_read_event = nullptr;
Event *_write_event = nullptr;
- HTTPHdr _request_header;
+ HTTPHdr _header; ///< HTTP header buffer for decoding
};
class Http3ClientTransaction : public HQClientTransaction
diff --git a/proxy/http3/Http3HeaderFramer.cc b/proxy/http3/Http3HeaderFramer.cc
index 6bda091..1d493f5 100644
--- a/proxy/http3/Http3HeaderFramer.cc
+++ b/proxy/http3/Http3HeaderFramer.cc
@@ -70,60 +70,31 @@ Http3HeaderFramer::is_done() const
return this->_sent_all_data;
}
-const char *HTTP3_VALUE_STATUS = ":status";
-const unsigned HTTP3_LEN_STATUS = countof(":status") - 1;
-static size_t HTTP3_LEN_STATUS_VALUE_STR = 3;
-
-// Copy code from http2_generate_h2_header_from_1_1(h1_hdrs, h3_hdrs);
void
Http3HeaderFramer::_convert_header_from_1_1_to_3(HTTPHdr *h3_hdrs, HTTPHdr *h1_hdrs)
{
- // Add ':status' header field
- char status_str[HTTP3_LEN_STATUS_VALUE_STR + 1];
- snprintf(status_str, sizeof(status_str), "%d", h1_hdrs->status_get());
- MIMEField *status_field = h3_hdrs->field_create(HTTP3_VALUE_STATUS, HTTP3_LEN_STATUS);
- status_field->value_set(h3_hdrs->m_heap, h3_hdrs->m_mime, status_str, HTTP3_LEN_STATUS_VALUE_STR);
- h3_hdrs->field_attach(status_field);
-
- // Copy headers
- // Intermediaries SHOULD remove connection-specific header fields.
- MIMEFieldIter field_iter;
- for (MIMEField *field = h1_hdrs->iter_get_first(&field_iter); field != nullptr; field = h1_hdrs->iter_get_next(&field_iter)) {
- const char *name;
- int name_len;
- const char *value;
- int value_len;
- name = field->name_get(&name_len);
- if ((name_len == MIME_LEN_CONNECTION && strncasecmp(name, MIME_FIELD_CONNECTION, name_len) == 0) ||
- (name_len == MIME_LEN_KEEP_ALIVE && strncasecmp(name, MIME_FIELD_KEEP_ALIVE, name_len) == 0) ||
- (name_len == MIME_LEN_PROXY_CONNECTION && strncasecmp(name, MIME_FIELD_PROXY_CONNECTION, name_len) == 0) ||
- (name_len == MIME_LEN_TRANSFER_ENCODING && strncasecmp(name, MIME_FIELD_TRANSFER_ENCODING, name_len) == 0) ||
- (name_len == MIME_LEN_UPGRADE && strncasecmp(name, MIME_FIELD_UPGRADE, name_len) == 0)) {
- continue;
- }
- MIMEField *newfield;
- name = field->name_get(&name_len);
- newfield = h3_hdrs->field_create(name, name_len);
- value = field->value_get(&value_len);
- newfield->value_set(h3_hdrs->m_heap, h3_hdrs->m_mime, value, value_len);
- h3_hdrs->field_attach(newfield);
- }
+ http2_generate_h2_header_from_1_1(h1_hdrs, h3_hdrs);
}
void
Http3HeaderFramer::_generate_header_block()
{
// Prase response header and generate header block
- int bytes_used = 0;
- // TODO Use HTTP_TYPE_REQUEST if this is for requests
- this->_header.create(HTTP_TYPE_RESPONSE);
- int parse_result = this->_header.parse_resp(&this->_http_parser, this->_source_vio->get_reader(), &bytes_used, false);
+ int bytes_used = 0;
+ ParseResult parse_result = PARSE_RESULT_ERROR;
+
+ if (this->_transaction->direction() == NET_VCONNECTION_OUT) {
+ this->_header.create(HTTP_TYPE_REQUEST);
+ parse_result = this->_header.parse_req(&this->_http_parser, this->_source_vio->get_reader(), &bytes_used, false);
+ } else {
+ this->_header.create(HTTP_TYPE_RESPONSE);
+ parse_result = this->_header.parse_resp(&this->_http_parser, this->_source_vio->get_reader(), &bytes_used, false);
+ }
this->_source_vio->ndone += this->_header.length_get();
switch (parse_result) {
case PARSE_RESULT_DONE: {
HTTPHdr h3_hdr;
- h3_hdr.create(HTTP_TYPE_RESPONSE);
this->_convert_header_from_1_1_to_3(&h3_hdr, &this->_header);
this->_header_block = new_MIOBuffer();
@@ -135,6 +106,7 @@ Http3HeaderFramer::_generate_header_block()
case PARSE_RESULT_CONT:
break;
default:
+ Debug("http3_trans", "Ignore ivalid headers");
break;
}
}
diff --git a/proxy/http3/Http3HeaderVIOAdaptor.cc b/proxy/http3/Http3HeaderVIOAdaptor.cc
index c2e4414..6a55ae7 100644
--- a/proxy/http3/Http3HeaderVIOAdaptor.cc
+++ b/proxy/http3/Http3HeaderVIOAdaptor.cc
@@ -49,11 +49,12 @@ Http3HeaderVIOAdaptor::handle_frame(std::shared_ptr<const Http3Frame> frame)
if (res == 0) {
// When decoding is not blocked, continuation should be called directly?
} else if (res == 1) {
- // Decoding is blocked. Callback will be fired.
+ // Decoding is blocked.
+ Debug("http3", "Decoding is blocked. DecodeRequest is scheduled");
} else if (res < 0) {
- // error
+ Debug("http3", "Error on decoding header (%d)", res);
} else {
- // should not be here
+ ink_abort("should not be here");
}
return Http3ErrorUPtr(new Http3NoError());
diff --git a/src/traffic_quic/Makefile.inc b/src/traffic_quic/Makefile.inc
index b9291db..18b466f 100644
--- a/src/traffic_quic/Makefile.inc
+++ b/src/traffic_quic/Makefile.inc
@@ -19,39 +19,45 @@ bin_PROGRAMS += traffic_quic/traffic_quic
traffic_quic_traffic_quic_CPPFLAGS = \
$(AM_CPPFLAGS) \
- $(iocore_include_dirs) \
- -I$(abs_top_srcdir)/lib \
- -I$(abs_top_srcdir)/lib/records \
- -I$(abs_top_srcdir)/mgmt \
- -I$(abs_top_srcdir)/mgmt/utils \
- -I$(abs_top_srcdir)/proxy \
- -I$(abs_top_srcdir)/proxy/hdrs \
- -I$(abs_top_srcdir)/proxy/http \
- -I$(abs_top_srcdir)/proxy/logging \
- -I$(abs_top_srcdir)/proxy/shared \
- $(TS_INCLUDES) \
- @OPENSSL_INCLUDES@
+ $(iocore_include_dirs) \
+ -I$(abs_top_srcdir)/lib \
+ -I$(abs_top_srcdir)/lib/records \
+ -I$(abs_top_srcdir)/mgmt \
+ -I$(abs_top_srcdir)/mgmt/utils \
+ -I$(abs_top_srcdir)/proxy \
+ -I$(abs_top_srcdir)/proxy/hdrs \
+ -I$(abs_top_srcdir)/proxy/http \
+ -I$(abs_top_srcdir)/proxy/http/remap \
+ -I$(abs_top_srcdir)/proxy/http3 \
+ -I$(abs_top_srcdir)/proxy/logging \
+ -I$(abs_top_srcdir)/proxy/shared \
+ $(TS_INCLUDES) \
+ @OPENSSL_INCLUDES@
traffic_quic_traffic_quic_LDFLAGS = \
- $(AM_LDFLAGS) \
- @OPENSSL_LDFLAGS@
+ $(AM_LDFLAGS) \
+ @OPENSSL_LDFLAGS@
traffic_quic_traffic_quic_SOURCES = \
- traffic_quic/quic_client.cc \
- traffic_quic/traffic_quic.cc
+ traffic_quic/quic_client.cc \
+ traffic_quic/traffic_quic.cc
traffic_quic_traffic_quic_LDADD = \
- $(top_builddir)/iocore/net/libinknet.a \
- $(top_builddir)/iocore/aio/libinkaio.a \
- $(top_builddir)/iocore/net/quic/libquic.a \
- $(top_builddir)/iocore/eventsystem/libinkevent.a \
- $(top_builddir)/mgmt/libmgmt_p.la \
- $(top_builddir)/lib/records/librecords_p.a \
- $(top_builddir)/src/tscore/libtscore.la \
- $(top_builddir)/src/tscpp/util/libtscpputil.la \
- $(top_builddir)/lib/tsconfig/libtsconfig.la \
- $(top_builddir)/proxy/ParentSelectionStrategy.o \
- @HWLOC_LIBS@ \
- @YAMLCPP_LIBS@ \
- @OPENSSL_LIBS@ \
- @LIBPCRE@
+ $(top_builddir)/iocore/net/libinknet.a \
+ $(top_builddir)/iocore/aio/libinkaio.a \
+ $(top_builddir)/iocore/net/quic/libquic.a \
+ $(top_builddir)/iocore/eventsystem/libinkevent.a \
+ $(top_builddir)/mgmt/libmgmt_p.la \
+ $(top_builddir)/lib/records/librecords_p.a \
+ $(top_builddir)/src/tscore/libtscore.la \
+ $(top_builddir)/src/tscpp/util/libtscpputil.la \
+ $(top_builddir)/lib/tsconfig/libtsconfig.la \
+ $(top_builddir)/proxy/ParentSelectionStrategy.o \
+ $(top_builddir)/proxy/libproxy.a \
+ $(top_builddir)/proxy/hdrs/libhdrs.a \
+ $(top_builddir)/proxy/http2/libhttp2.a \
+ $(top_builddir)/proxy/http3/libhttp3.a \
+ @HWLOC_LIBS@ \
+ @YAMLCPP_LIBS@ \
+ @OPENSSL_LIBS@ \
+ @LIBPCRE@
diff --git a/src/traffic_quic/quic_client.cc b/src/traffic_quic/quic_client.cc
index d2eb7e0..47560fc 100644
--- a/src/traffic_quic/quic_client.cc
+++ b/src/traffic_quic/quic_client.cc
@@ -25,6 +25,17 @@
#include <iostream>
#include <fstream>
+#include <string_view>
+
+#include "Http3ClientSession.h"
+#include "Http3ClientTransaction.h"
+
+// OpenSSL protocol-lists format (vector of 8-bit length-prefixed, byte strings)
+// https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_alpn_protos.html
+// Should be integrate with IP_PROTO_TAG_HTTP_QUIC in ts/ink_inet.h ?
+using namespace std::literals;
+static constexpr std::string_view HQ_ALPN_PROTO_LIST("\5hq-18"sv);
+static constexpr std::string_view H3_ALPN_PROTO_LIST("\5h3-18"sv);
QUICClient::QUICClient(const QUICClientConfig *config) : Continuation(new_ProxyMutex()), _config(config)
{
@@ -55,6 +66,13 @@ QUICClient::start(int, void *)
return EVENT_DONE;
}
+ std::string_view alpn_protos;
+ if (this->_config->http3) {
+ alpn_protos = H3_ALPN_PROTO_LIST;
+ } else {
+ alpn_protos = HQ_ALPN_PROTO_LIST;
+ }
+
for (struct addrinfo *info = this->_remote_addr_info; info != nullptr; info = info->ai_next) {
NetVCOptions opt;
opt.ip_proto = NetVCOptions::USE_UDP;
@@ -62,6 +80,8 @@ QUICClient::start(int, void *)
opt.etype = ET_NET;
opt.socket_recv_bufsize = 1048576;
opt.socket_send_bufsize = 1048576;
+ opt.alpn_protos = alpn_protos;
+ opt.set_sni_servername(this->_config->addr, strnlen(this->_config->addr, 1023));
SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
@@ -83,8 +103,19 @@ QUICClient::state_http_server_open(int event, void *data)
Debug("quic_client", "start proxy server ssn/txn");
QUICNetVConnection *conn = static_cast<QUICNetVConnection *>(data);
- QUICClientApp *app = new QUICClientApp(conn, this->_config);
- app->start(this->_config->path);
+
+ if (this->_config->http0_9) {
+ Http09ClientApp *app = new Http09ClientApp(conn, this->_config);
+ app->start();
+ } else if (this->_config->http3) {
+ // TODO: see what server session is doing with IpAllow::ACL
+ IpAllow::ACL session_acl;
+ Http3ClientApp *app = new Http3ClientApp(conn, std::move(session_acl), this->_config);
+ SCOPED_MUTEX_LOCK(lock, app->mutex, this_ethread());
+ app->start();
+ } else {
+ ink_abort("invalid config");
+ }
break;
}
@@ -104,20 +135,20 @@ QUICClient::state_http_server_open(int event, void *data)
}
//
-// QUICClientApp
+// Http09ClientApp
//
-#define QUICClientAppDebug(fmt, ...) Debug("quic_client_app", "[%s] " fmt, this->_qc->cids().data(), ##__VA_ARGS__)
-#define QUICClientAppVDebug(fmt, ...) Debug("v_quic_client_app", "[%s] " fmt, this->_qc->cids().data(), ##__VA_ARGS__)
+#define Http09ClientAppDebug(fmt, ...) Debug("quic_client_app", "[%s] " fmt, this->_qc->cids().data(), ##__VA_ARGS__)
+#define Http09ClientAppVDebug(fmt, ...) Debug("v_quic_client_app", "[%s] " fmt, this->_qc->cids().data(), ##__VA_ARGS__)
-QUICClientApp::QUICClientApp(QUICNetVConnection *qvc, const QUICClientConfig *config) : QUICApplication(qvc), _config(config)
+Http09ClientApp::Http09ClientApp(QUICNetVConnection *qvc, const QUICClientConfig *config) : QUICApplication(qvc), _config(config)
{
this->_qc->stream_manager()->set_default_application(this);
- SET_HANDLER(&QUICClientApp::main_event_handler);
+ SET_HANDLER(&Http09ClientApp::main_event_handler);
}
void
-QUICClientApp::start(const char *path)
+Http09ClientApp::start()
{
if (this->_config->output[0] != 0x0) {
this->_filename = this->_config->output;
@@ -128,15 +159,11 @@ QUICClientApp::start(const char *path)
std::ofstream f_stream(this->_filename, std::ios::binary | std::ios::trunc);
}
- if (this->_config->http3) {
- this->_start_http_3_session(path);
- } else {
- this->_start_http_09_session(path);
- }
+ this->_do_http_request();
}
void
-QUICClientApp::_start_http_09_session(const char *path)
+Http09ClientApp::_do_http_request()
{
QUICStreamId stream_id;
QUICConnectionErrorUPtr error = this->_qc->stream_manager()->create_bidi_stream(stream_id);
@@ -148,44 +175,9 @@ QUICClientApp::_start_http_09_session(const char *path)
// TODO: move to transaction
char request[1024] = {0};
- int request_len = snprintf(request, sizeof(request), "GET %s\r\n", path);
-
- QUICClientAppDebug("\n%s", request);
-
- QUICStreamIO *stream_io = this->_find_stream_io(stream_id);
-
- stream_io->write(reinterpret_cast<uint8_t *>(request), request_len);
- stream_io->write_done();
- stream_io->write_reenable();
-}
-
-void
-QUICClientApp::_start_http_3_session(const char *path)
-{
- QUICConnectionErrorUPtr error;
-
- QUICStreamId settings_stream_id;
- error = this->_qc->stream_manager()->create_uni_stream(settings_stream_id);
-
- if (error != nullptr) {
- Error("%s", error->msg);
- ink_abort("Could not create uni stream : %s", error->msg);
- }
- // TODO: send settings frame
-
- QUICStreamId stream_id;
- error = this->_qc->stream_manager()->create_bidi_stream(stream_id);
-
- if (error != nullptr) {
- Error("%s", error->msg);
- ink_abort("Could not create bidi stream : %s", error->msg);
- }
-
- // TODO: move to transaction
- char request[1024] = {0};
- int request_len = snprintf(request, sizeof(request), "GET %s\r\n", path);
+ int request_len = snprintf(request, sizeof(request), "GET %s\r\n", this->_config->path);
- QUICClientAppDebug("\n%s", request);
+ Http09ClientAppDebug("\n%s", request);
QUICStreamIO *stream_io = this->_find_stream_io(stream_id);
@@ -195,15 +187,15 @@ QUICClientApp::_start_http_3_session(const char *path)
}
int
-QUICClientApp::main_event_handler(int event, Event *data)
+Http09ClientApp::main_event_handler(int event, Event *data)
{
- QUICClientAppVDebug("%s (%d)", get_vc_event_name(event), event);
+ Http09ClientAppVDebug("%s (%d)", get_vc_event_name(event), event);
VIO *vio = reinterpret_cast<VIO *>(data);
QUICStreamIO *stream_io = this->_find_stream_io(vio);
if (stream_io == nullptr) {
- QUICClientAppDebug("Unknown Stream");
+ Http09ClientAppDebug("Unknown Stream");
return -1;
}
@@ -253,3 +245,140 @@ QUICClientApp::main_event_handler(int event, Event *data)
return EVENT_CONT;
}
+
+//
+// Http3ClientApp
+//
+Http3ClientApp::Http3ClientApp(QUICNetVConnection *qvc, IpAllow::ACL session_acl, const QUICClientConfig *config)
+ : super(qvc, std::move(session_acl)), _config(config)
+{
+}
+
+Http3ClientApp::~Http3ClientApp()
+{
+ free_MIOBuffer(this->_req_buf);
+ this->_req_buf = nullptr;
+
+ free_MIOBuffer(this->_resp_buf);
+ this->_resp_buf = nullptr;
+
+ delete this->_resp_handler;
+}
+
+void
+Http3ClientApp::start()
+{
+ this->_req_buf = new_MIOBuffer();
+ this->_resp_buf = new_MIOBuffer();
+ IOBufferReader *resp_buf_reader = _resp_buf->alloc_reader();
+
+ this->_resp_handler = new RespHandler(this->_config, resp_buf_reader);
+
+ super::start();
+ this->_do_http_request();
+}
+
+void
+Http3ClientApp::_do_http_request()
+{
+ QUICConnectionErrorUPtr error;
+ QUICStreamId stream_id;
+ error = this->_qc->stream_manager()->create_bidi_stream(stream_id);
+ if (error != nullptr) {
+ Error("%s", error->msg);
+ ink_abort("Could not create bidi stream : %s", error->msg);
+ }
+
+ QUICStreamIO *stream_io = this->_find_stream_io(stream_id);
+
+ // TODO: create Http3ServerTransaction
+ Http3ClientTransaction *txn = new Http3ClientTransaction(this->_ssn, stream_io);
+ SCOPED_MUTEX_LOCK(lock, txn->mutex, this_ethread());
+
+ // TODO: fix below issue with H2 origin conn stuff
+ // Do not call ProxyClientTransaction::new_transaction(), but need to setup txn - e.g. do_io_write / do_io_read
+ VIO *read_vio = txn->do_io_read(this->_resp_handler, INT64_MAX, this->_resp_buf);
+ this->_resp_handler->set_read_vio(read_vio);
+
+ // Write HTTP Request to write_vio
+ char request[1024] = {0};
+ std::string format;
+ if (this->_config->path[0] == '/') {
+ format = "GET https://%s%s HTTP/1.1\r\n\r\n";
+ } else {
+ format = "GET https://%s/%s HTTP/1.1\r\n\r\n";
+ }
+
+ int request_len = snprintf(request, sizeof(request), format.c_str(), this->_config->addr, this->_config->path);
+
+ Http09ClientAppDebug("\n%s", request);
+
+ // TODO: check write avail size
+ int64_t nbytes = this->_req_buf->write(request, request_len);
+ IOBufferReader *buf_start = this->_req_buf->alloc_reader();
+ txn->do_io_write(this, nbytes, buf_start);
+}
+
+//
+// Response Handler
+//
+RespHandler::RespHandler(const QUICClientConfig *config, IOBufferReader *reader)
+ : Continuation(new_ProxyMutex()), _config(config), _reader(reader)
+{
+ if (this->_config->output[0] != 0x0) {
+ this->_filename = this->_config->output;
+ }
+
+ if (this->_filename) {
+ // Destroy contents if file already exists
+ std::ofstream f_stream(this->_filename, std::ios::binary | std::ios::trunc);
+ }
+
+ SET_HANDLER(&RespHandler::main_event_handler);
+}
+
+void
+RespHandler::set_read_vio(VIO *vio)
+{
+ this->_read_vio = vio;
+}
+
+int
+RespHandler::main_event_handler(int event, Event *data)
+{
+ Debug("v_http3", "%s", get_vc_event_name(event));
+ switch (event) {
+ case VC_EVENT_READ_READY:
+ case VC_EVENT_READ_COMPLETE: {
+ std::streambuf *default_stream = nullptr;
+ std::ofstream f_stream;
+
+ if (this->_filename) {
+ default_stream = std::cout.rdbuf();
+ f_stream = std::ofstream(this->_filename, std::ios::binary | std::ios::app);
+ std::cout.rdbuf(f_stream.rdbuf());
+ }
+
+ uint8_t buf[8192] = {0};
+ int64_t nread;
+ while ((nread = this->_reader->read(buf, sizeof(buf))) > 0) {
+ std::cout.write(reinterpret_cast<char *>(buf), nread);
+ this->_read_vio->ndone += nread;
+ }
+ std::cout.flush();
+
+ if (this->_filename) {
+ f_stream.close();
+ std::cout.rdbuf(default_stream);
+ }
+
+ break;
+ }
+ case VC_EVENT_WRITE_READY:
+ case VC_EVENT_WRITE_COMPLETE:
+ default:
+ break;
+ }
+
+ return EVENT_CONT;
+}
diff --git a/src/traffic_quic/quic_client.h b/src/traffic_quic/quic_client.h
index fe66740..5a2a950 100644
--- a/src/traffic_quic/quic_client.h
+++ b/src/traffic_quic/quic_client.h
@@ -29,19 +29,35 @@
#include "P_QUICNetProcessor.h"
#include "QUICApplication.h"
+#include "Http3App.h"
// TODO: add quic version option
+// TODO: add host header option (also should be used for SNI)
struct QUICClientConfig {
char addr[1024] = "127.0.0.1";
char output[1024] = {0};
char port[16] = "4433";
char path[1018] = "/";
- char debug_tags[1024] = "quic|vv_quic_crypto";
+ char debug_tags[1024] = "quic|vv_quic_crypto|http3|qpack";
int close = false;
int http0_9 = true;
int http3 = false;
};
+class RespHandler : public Continuation
+{
+public:
+ RespHandler(const QUICClientConfig *config, IOBufferReader *reader);
+ int main_event_handler(int event, Event *data);
+ void set_read_vio(VIO *vio);
+
+private:
+ const QUICClientConfig *_config = nullptr;
+ const char *_filename = nullptr;
+ IOBufferReader *_reader = nullptr;
+ VIO *_read_vio = nullptr;
+};
+
class QUICClient : public Continuation
{
public:
@@ -56,18 +72,37 @@ private:
struct addrinfo *_remote_addr_info = nullptr;
};
-class QUICClientApp : public QUICApplication
+class Http09ClientApp : public QUICApplication
{
public:
- QUICClientApp(QUICNetVConnection *qvc, const QUICClientConfig *config);
+ Http09ClientApp(QUICNetVConnection *qvc, const QUICClientConfig *config);
- void start(const char *path);
+ void start();
int main_event_handler(int event, Event *data);
private:
- void _start_http_09_session(const char *path);
- void _start_http_3_session(const char *path);
+ void _do_http_request();
const QUICClientConfig *_config = nullptr;
const char *_filename = nullptr;
};
+
+class Http3ClientApp : public Http3App
+{
+public:
+ using super = Http3App;
+
+ Http3ClientApp(QUICNetVConnection *qvc, IpAllow::ACL session_acl, const QUICClientConfig *config);
+ ~Http3ClientApp();
+
+ void start() override;
+
+private:
+ void _do_http_request();
+
+ RespHandler *_resp_handler = nullptr;
+ const QUICClientConfig *_config = nullptr;
+
+ MIOBuffer *_req_buf = nullptr;
+ MIOBuffer *_resp_buf = nullptr;
+};
diff --git a/src/traffic_quic/traffic_quic.cc b/src/traffic_quic/traffic_quic.cc
index 551bb50..9ac59b5 100644
--- a/src/traffic_quic/traffic_quic.cc
+++ b/src/traffic_quic/traffic_quic.cc
@@ -27,6 +27,11 @@
#include "tscore/I_Version.h"
#include "RecordsConfig.h"
+#include "URL.h"
+#include "MIME.h"
+#include "HTTP.h"
+#include "HuffmanCodec.h"
+#include "Http3Config.h"
#include "diags.h"
#include "quic_client.h"
@@ -95,6 +100,14 @@ main(int argc, const char **argv)
udpNet.start(1, stacksize);
quic_NetProcessor.start(-1, stacksize);
+ // Same to init_http_header(); in traffic_server.cc
+ url_init();
+ mime_init();
+ http_init();
+ hpack_huffman_init();
+
+ Http3Config::startup();
+
QUICClient client(&config);
eventProcessor.schedule_in(&client, 1, ET_NET);
@@ -168,6 +181,7 @@ Log::trace_out(sockaddr const *, unsigned short, char const *, ...)
}
#include "InkAPIInternal.h"
+
int
APIHook::invoke(int, void *)
{
@@ -190,6 +204,24 @@ APIHooks::get() const
}
void
+APIHooks::clear()
+{
+ ink_abort("do not call stub");
+}
+
+void
+APIHooks::append(INKContInternal *)
+{
+ ink_abort("do not call stub");
+}
+
+void
+APIHooks::prepend(INKContInternal *)
+{
+ ink_abort("do not call stub");
+}
+
+void
ConfigUpdateCbTable::invoke(const char * /* name ATS_UNUSED */)
{
ink_release_assert(false);
@@ -227,19 +259,76 @@ HttpRequestData::get_client_ip()
SslAPIHooks *ssl_hooks = nullptr;
StatPagesManager statPagesManager;
-#include "ProcessManager.h"
-inkcoreapi ProcessManager *pmgmt = nullptr;
+#include "HttpDebugNames.h"
+const char *
+HttpDebugNames::get_api_hook_name(TSHttpHookID t)
+{
+ return "dummy";
+}
+
+#include "HttpSM.h"
+HttpSM::HttpSM() : Continuation(nullptr), vc_table(this) {}
+
+void
+HttpSM::cleanup()
+{
+ ink_abort("do not call stub");
+}
+
+void
+HttpSM::destroy()
+{
+ ink_abort("do not call stub");
+}
+
+void
+HttpSM::set_next_state()
+{
+ ink_abort("do not call stub");
+}
+
+void
+HttpSM::handle_api_return()
+{
+ ink_abort("do not call stub");
+}
int
-BaseManager::registerMgmtCallback(int, const MgmtCallback &)
+HttpSM::kill_this_async_hook(int /* event ATS_UNUSED */, void * /* data ATS_UNUSED */)
{
- ink_assert(false);
- return 0;
+ return EVENT_DONE;
}
void
-ProcessManager::signalManager(int, char const *, int)
+HttpSM::attach_client_session(ProxyClientTransaction *, IOBufferReader *)
+{
+ ink_abort("do not call stub");
+}
+
+void
+HttpSM::init()
+{
+ ink_abort("do not call stub");
+}
+
+ClassAllocator<HttpSM> httpSMAllocator("httpSMAllocator");
+HttpAPIHooks *http_global_hooks;
+
+HttpVCTable::HttpVCTable(HttpSM *) {}
+
+PostDataBuffers::~PostDataBuffers() {}
+
+#include "HttpTunnel.h"
+HttpTunnel::HttpTunnel() : Continuation(nullptr) {}
+HttpTunnelConsumer::HttpTunnelConsumer() {}
+HttpTunnelProducer::HttpTunnelProducer() {}
+ChunkedHandler::ChunkedHandler() {}
+
+#include "HttpCacheSM.h"
+HttpCacheSM::HttpCacheSM() {}
+
+HttpCacheAction::HttpCacheAction() : sm(nullptr) {}
+void
+HttpCacheAction::cancel(Continuation *c)
{
- ink_assert(false);
- return;
}