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 24df75e Decouple HTTP/0.9 and HTTP/3
24df75e is described below
commit 24df75e9748f73a4cb8858f6c552909e0406da01
Author: Masaori Koshiba <[email protected]>
AuthorDate: Mon Mar 11 11:20:14 2019 +0900
Decouple HTTP/0.9 and HTTP/3
Add Http09ClientSession and Http09ClientTransaction to clarify HTTP/0.9 and
HTTP/3 code.
HTTP/0.9 and HTTP/3 is completely switched by ALPN (hq-* vs h3-*).
---
proxy/http3/Http09App.cc | 8 +-
proxy/http3/Http09App.h | 4 +-
proxy/http3/Http3App.cc | 4 +-
proxy/http3/Http3ClientSession.cc | 146 ++++---
proxy/http3/Http3ClientSession.h | 64 ++-
proxy/http3/Http3ClientTransaction.cc | 724 +++++++++++++++++++++-------------
proxy/http3/Http3ClientTransaction.h | 92 +++--
7 files changed, 666 insertions(+), 376 deletions(-)
diff --git a/proxy/http3/Http09App.cc b/proxy/http3/Http09App.cc
index f89d0bb..1168b5a 100644
--- a/proxy/http3/Http09App.cc
+++ b/proxy/http3/Http09App.cc
@@ -35,7 +35,7 @@ static constexpr char debug_tag_v[] = "v_quic_simple_app";
Http09App::Http09App(QUICNetVConnection *client_vc, IpAllow::ACL session_acl)
: QUICApplication(client_vc)
{
- this->_client_session = new Http3ClientSession(client_vc);
+ this->_client_session = new Http09ClientSession(client_vc);
this->_client_session->acl = std::move(session_acl);
this->_client_session->new_connection(client_vc, nullptr, nullptr);
@@ -62,8 +62,8 @@ Http09App::main_event_handler(int event, Event *data)
return -1;
}
- QUICStreamId stream_id = stream_io->stream_id();
- Http3ClientTransaction *txn =
this->_client_session->get_transaction(stream_id);
+ QUICStreamId stream_id = stream_io->stream_id();
+ Http09ClientTransaction *txn = static_cast<Http09ClientTransaction
*>(this->_client_session->get_transaction(stream_id));
uint8_t dummy;
switch (event) {
@@ -75,7 +75,7 @@ Http09App::main_event_handler(int event, Event *data)
}
if (stream_io->peek(&dummy, 1)) {
if (txn == nullptr) {
- txn = new Http3ClientTransaction(this->_client_session, stream_io);
+ txn = new Http09ClientTransaction(this->_client_session, stream_io);
SCOPED_MUTEX_LOCK(lock, txn->mutex, this_ethread());
txn->new_transaction();
diff --git a/proxy/http3/Http09App.h b/proxy/http3/Http09App.h
index 1132ef2..b3356a0 100644
--- a/proxy/http3/Http09App.h
+++ b/proxy/http3/Http09App.h
@@ -28,7 +28,7 @@
#include "QUICApplication.h"
class QUICNetVConnection;
-class Http3ClientSession;
+class Http09ClientSession;
/**
* @brief A simple multi-streamed application.
@@ -45,5 +45,5 @@ public:
int main_event_handler(int event, Event *data);
private:
- Http3ClientSession *_client_session = nullptr;
+ Http09ClientSession *_client_session = nullptr;
};
diff --git a/proxy/http3/Http3App.cc b/proxy/http3/Http3App.cc
index 9b034b6..7b34fa2 100644
--- a/proxy/http3/Http3App.cc
+++ b/proxy/http3/Http3App.cc
@@ -196,7 +196,7 @@ 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 =
this->_client_session->get_transaction(stream_id);
+ Http3ClientTransaction *txn = static_cast<Http3ClientTransaction
*>(this->_client_session->get_transaction(stream_id));
if (txn == nullptr) {
txn = new Http3ClientTransaction(this->_client_session, stream_io);
@@ -261,7 +261,7 @@ void
Http3App::_handle_bidi_stream_on_write_ready(int event, QUICStreamIO
*stream_io)
{
QUICStreamId stream_id = stream_io->stream_id();
- Http3ClientTransaction *txn =
this->_client_session->get_transaction(stream_id);
+ Http3ClientTransaction *txn = static_cast<Http3ClientTransaction
*>(this->_client_session->get_transaction(stream_id));
if (txn != nullptr) {
SCOPED_MUTEX_LOCK(lock, txn->mutex, this_ethread());
txn->handleEvent(event);
diff --git a/proxy/http3/Http3ClientSession.cc
b/proxy/http3/Http3ClientSession.cc
index 2038e78..3fdd13d 100644
--- a/proxy/http3/Http3ClientSession.cc
+++ b/proxy/http3/Http3ClientSession.cc
@@ -25,103 +25,134 @@
#include "Http3.h"
-Http3ClientSession::Http3ClientSession(NetVConnection *vc) : _client_vc(vc)
+//
+// HQClientSession
+//
+HQClientSession ::~HQClientSession()
{
- this->_local_qpack = new QPACK(static_cast<QUICNetVConnection *>(vc),
HTTP3_DEFAULT_MAX_HEADER_LIST_SIZE,
- HTTP3_DEFAULT_HEADER_TABLE_SIZE,
HTTP3_DEFAULT_QPACK_BLOCKED_STREAMS);
- this->_remote_qpack = new QPACK(static_cast<QUICNetVConnection *>(vc),
HTTP3_DEFAULT_MAX_HEADER_LIST_SIZE,
- HTTP3_DEFAULT_HEADER_TABLE_SIZE,
HTTP3_DEFAULT_QPACK_BLOCKED_STREAMS);
+ for (HQClientTransaction *t = this->_transaction_list.head; t; t =
static_cast<HQClientTransaction *>(t->link.next)) {
+ delete t;
+ }
}
-Http3ClientSession::~Http3ClientSession()
+void
+HQClientSession::add_transaction(HQClientTransaction *trans)
{
- this->_client_vc = nullptr;
- for (Http3ClientTransaction *t = this->_transaction_list.head; t; t =
static_cast<Http3ClientTransaction *>(t->link.next)) {
- delete t;
+ this->_transaction_list.enqueue(trans);
+
+ return;
+}
+
+HQClientTransaction *
+HQClientSession::get_transaction(QUICStreamId id)
+{
+ for (HQClientTransaction *t = this->_transaction_list.head; t; t =
static_cast<Http3ClientTransaction *>(t->link.next)) {
+ if (t->get_transaction_id() == static_cast<int>(id)) {
+ return t;
+ }
}
- delete this->_local_qpack;
- delete this->_remote_qpack;
+
+ return nullptr;
}
VIO *
-Http3ClientSession::do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf)
+HQClientSession::do_io_read(Continuation *c, int64_t nbytes, MIOBuffer *buf)
{
ink_assert(false);
return nullptr;
}
VIO *
-Http3ClientSession::do_io_write(Continuation *c, int64_t nbytes,
IOBufferReader *buf, bool owner)
+HQClientSession::do_io_write(Continuation *c, int64_t nbytes, IOBufferReader
*buf, bool owner)
{
ink_assert(false);
return nullptr;
}
void
-Http3ClientSession::do_io_close(int lerrno)
+HQClientSession::do_io_close(int lerrno)
{
// TODO
return;
}
void
-Http3ClientSession::do_io_shutdown(ShutdownHowTo_t howto)
+HQClientSession::do_io_shutdown(ShutdownHowTo_t howto)
{
ink_assert(false);
return;
}
void
-Http3ClientSession::reenable(VIO *vio)
+HQClientSession::reenable(VIO *vio)
{
ink_assert(false);
return;
}
void
-Http3ClientSession::destroy()
+HQClientSession::new_connection(NetVConnection *new_vc, MIOBuffer *iobuf,
IOBufferReader *reade)
{
- ink_assert(false);
+ this->con_id = static_cast<QUICConnection
*>(reinterpret_cast<QUICNetVConnection *>(new_vc))->connection_id();
+
return;
}
void
-Http3ClientSession::start()
+HQClientSession::start()
{
ink_assert(false);
return;
}
void
-Http3ClientSession::new_connection(NetVConnection *new_vc, MIOBuffer *iobuf,
IOBufferReader *reade)
+HQClientSession::destroy()
{
- this->con_id = static_cast<QUICConnection
*>(reinterpret_cast<QUICNetVConnection *>(new_vc))->connection_id();
+ ink_assert(false);
+ return;
+}
+void
+HQClientSession::release(ProxyClientTransaction *trans)
+{
return;
}
NetVConnection *
-Http3ClientSession::get_netvc() const
+HQClientSession::get_netvc() const
{
return this->_client_vc;
}
int
-Http3ClientSession::get_transact_count() const
+HQClientSession::get_transact_count() const
{
return 0;
}
-const char *
-Http3ClientSession::get_protocol_string() const
+//
+// Http3ClientSession
+//
+Http3ClientSession::Http3ClientSession(NetVConnection *vc) :
HQClientSession(vc)
{
- return IP_PROTO_TAG_HTTP_QUIC.data();
+ this->_local_qpack = new QPACK(static_cast<QUICNetVConnection *>(vc),
HTTP3_DEFAULT_MAX_HEADER_LIST_SIZE,
+ HTTP3_DEFAULT_HEADER_TABLE_SIZE,
HTTP3_DEFAULT_QPACK_BLOCKED_STREAMS);
+ this->_remote_qpack = new QPACK(static_cast<QUICNetVConnection *>(vc),
HTTP3_DEFAULT_MAX_HEADER_LIST_SIZE,
+ HTTP3_DEFAULT_HEADER_TABLE_SIZE,
HTTP3_DEFAULT_QPACK_BLOCKED_STREAMS);
}
-void
-Http3ClientSession::release(ProxyClientTransaction *trans)
+Http3ClientSession::~Http3ClientSession()
{
- return;
+ this->_client_vc = nullptr;
+ delete this->_local_qpack;
+ delete this->_remote_qpack;
+ super::~HQClientSession();
+}
+
+const char *
+Http3ClientSession::get_protocol_string() const
+{
+ return IP_PROTO_TAG_HTTP_3.data();
}
int
@@ -129,7 +160,7 @@ Http3ClientSession::populate_protocol(std::string_view
*result, int size) const
{
int retval = 0;
if (size > retval) {
- result[retval++] = IP_PROTO_TAG_HTTP_QUIC;
+ result[retval++] = IP_PROTO_TAG_HTTP_3;
if (size > retval) {
retval += super::populate_protocol(result + retval, size - retval);
}
@@ -149,33 +180,54 @@
Http3ClientSession::decrement_current_active_client_connections_stat()
// TODO Implement stats
}
-void
-Http3ClientSession::add_transaction(Http3ClientTransaction *trans)
+QPACK *
+Http3ClientSession::local_qpack()
{
- this->_transaction_list.enqueue(trans);
- return;
+ return this->_local_qpack;
}
-// this->_transaction_list should be map?
-Http3ClientTransaction *
-Http3ClientSession::get_transaction(QUICStreamId id)
+QPACK *
+Http3ClientSession::remote_qpack()
{
- for (Http3ClientTransaction *t = this->_transaction_list.head; t; t =
static_cast<Http3ClientTransaction *>(t->link.next)) {
- if (t->get_transaction_id() == static_cast<int>(id)) {
- return t;
+ return this->_remote_qpack;
+}
+
+//
+// Http09ClientSession
+//
+Http09ClientSession::~Http09ClientSession()
+{
+ this->_client_vc = nullptr;
+ super::~HQClientSession();
+}
+
+const char *
+Http09ClientSession::get_protocol_string() const
+{
+ return IP_PROTO_TAG_HTTP_QUIC.data();
+}
+
+int
+Http09ClientSession::populate_protocol(std::string_view *result, int size)
const
+{
+ int retval = 0;
+ if (size > retval) {
+ result[retval++] = IP_PROTO_TAG_HTTP_QUIC;
+ if (size > retval) {
+ retval += super::populate_protocol(result + retval, size - retval);
}
}
- return nullptr;
+ return retval;
}
-QPACK *
-Http3ClientSession::local_qpack()
+void
+Http09ClientSession::increment_current_active_client_connections_stat()
{
- return this->_local_qpack;
+ // TODO Implement stats
}
-QPACK *
-Http3ClientSession::remote_qpack()
+void
+Http09ClientSession::decrement_current_active_client_connections_stat()
{
- return this->_remote_qpack;
+ // TODO Implement stats
}
diff --git a/proxy/http3/Http3ClientSession.h b/proxy/http3/Http3ClientSession.h
index 8af10b0..996de11 100644
--- a/proxy/http3/Http3ClientSession.h
+++ b/proxy/http3/Http3ClientSession.h
@@ -27,13 +27,13 @@
#include "Http3ClientTransaction.h"
#include "QPACK.h"
-class Http3ClientSession : public ProxyClientSession
+class HQClientSession : public ProxyClientSession
{
public:
- typedef ProxyClientSession super; ///< Parent type.
+ using super = ProxyClientSession; ///< Parent type
- Http3ClientSession(NetVConnection *vc);
- ~Http3ClientSession();
+ HQClientSession(NetVConnection *vc) : _client_vc(vc){};
+ ~HQClientSession();
// Implement VConnection interface
VIO *do_io_read(Continuation *c, int64_t nbytes = INT64_MAX, MIOBuffer *buf
= nullptr) override;
@@ -43,27 +43,63 @@ public:
void reenable(VIO *vio) override;
// Implement ProxyClienSession interface
+ void new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOBufferReader
*reader) override;
void start() override;
void destroy() override;
- void new_connection(NetVConnection *new_vc, MIOBuffer *iobuf, IOBufferReader
*reader) override;
+ void release(ProxyClientTransaction *trans) override;
NetVConnection *get_netvc() const override;
int get_transact_count() const override;
+
+ // HQClientSession
+ void add_transaction(HQClientTransaction *);
+ HQClientTransaction *get_transaction(QUICStreamId);
+
+protected:
+ NetVConnection *_client_vc = nullptr;
+
+private:
+ // this should be unordered map?
+ Queue<HQClientTransaction> _transaction_list;
+};
+
+class Http3ClientSession : public HQClientSession
+{
+public:
+ using super = HQClientSession; ///< Parent type
+
+ Http3ClientSession(NetVConnection *vc);
+ ~Http3ClientSession();
+
+ // ProxyClienSession interface
const char *get_protocol_string() const override;
- void release(ProxyClientTransaction *trans) override;
int populate_protocol(std::string_view *result, int size) const override;
void increment_current_active_client_connections_stat() override;
void decrement_current_active_client_connections_stat() override;
- // Http3ClientSession specific methods
- void add_transaction(Http3ClientTransaction *);
- Http3ClientTransaction *get_transaction(QUICStreamId);
-
QPACK *local_qpack();
QPACK *remote_qpack();
private:
- NetVConnection *_client_vc = nullptr;
- QPACK *_remote_qpack = nullptr; // QPACK for decoding
- QPACK *_local_qpack = nullptr; // QPACK for encoding
- Queue<Http3ClientTransaction> _transaction_list;
+ QPACK *_remote_qpack = nullptr; // QPACK for decoding
+ QPACK *_local_qpack = nullptr; // QPACK for encoding
+};
+
+/**
+ Only for interop. Will be removed.
+ */
+class Http09ClientSession : public HQClientSession
+{
+public:
+ using super = HQClientSession; ///< Parent type
+
+ Http09ClientSession(NetVConnection *vc) : HQClientSession(vc) {}
+ ~Http09ClientSession();
+
+ // ProxyClienSession interface
+ const char *get_protocol_string() const override;
+ int populate_protocol(std::string_view *result, int size) const override;
+ void increment_current_active_client_connections_stat() override;
+ void decrement_current_active_client_connections_stat() override;
+
+private:
};
diff --git a/proxy/http3/Http3ClientTransaction.cc
b/proxy/http3/Http3ClientTransaction.cc
index 849a132..228621b 100644
--- a/proxy/http3/Http3ClientTransaction.cc
+++ b/proxy/http3/Http3ClientTransaction.cc
@@ -53,45 +53,27 @@
// Debug("v_http3_trans", "len=%" PRId64 "\n%s\n", read_len, msg);
// }
-Http3ClientTransaction::Http3ClientTransaction(Http3ClientSession *session,
QUICStreamIO *stream_io)
- : super(), _stream_io(stream_io)
+//
+// HQClientTransaction
+//
+HQClientTransaction::HQClientTransaction(HQClientSession *session,
QUICStreamIO *stream_io) : super(), _stream_io(stream_io)
{
this->mutex = new_ProxyMutex();
this->_thread = this_ethread();
this->set_parent(session);
- this->sm_reader = this->_read_vio_buf.alloc_reader();
- static_cast<Http3ClientSession *>(this->parent)->add_transaction(this);
-
- this->_header_framer = new Http3HeaderFramer(this, &this->_write_vio,
session->local_qpack(), stream_io->stream_id());
- this->_data_framer = new Http3DataFramer(this, &this->_write_vio);
- this->_frame_collector.add_generator(this->_header_framer);
- 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->_data_handler = new Http3StreamDataVIOAdaptor(&this->_read_vio);
-
- this->_frame_dispatcher.add_handler(this->_header_handler);
- this->_frame_dispatcher.add_handler(this->_data_handler);
+ this->sm_reader = this->_read_vio_buf.alloc_reader();
this->_request_header.create(HTTP_TYPE_REQUEST);
-
- SET_HANDLER(&Http3ClientTransaction::state_stream_open);
}
-Http3ClientTransaction::~Http3ClientTransaction()
+HQClientTransaction::~HQClientTransaction()
{
this->_request_header.destroy();
-
- delete this->_header_framer;
- delete this->_data_framer;
- delete this->_header_handler;
- delete this->_data_handler;
}
void
-Http3ClientTransaction::set_active_timeout(ink_hrtime timeout_in)
+HQClientTransaction::set_active_timeout(ink_hrtime timeout_in)
{
if (parent) {
parent->set_active_timeout(timeout_in);
@@ -99,7 +81,7 @@ Http3ClientTransaction::set_active_timeout(ink_hrtime
timeout_in)
}
void
-Http3ClientTransaction::set_inactivity_timeout(ink_hrtime timeout_in)
+HQClientTransaction::set_inactivity_timeout(ink_hrtime timeout_in)
{
if (parent) {
parent->set_inactivity_timeout(timeout_in);
@@ -107,7 +89,7 @@ Http3ClientTransaction::set_inactivity_timeout(ink_hrtime
timeout_in)
}
void
-Http3ClientTransaction::cancel_inactivity_timeout()
+HQClientTransaction::cancel_inactivity_timeout()
{
if (parent) {
parent->cancel_inactivity_timeout();
@@ -115,121 +97,20 @@ Http3ClientTransaction::cancel_inactivity_timeout()
}
void
-Http3ClientTransaction::release(IOBufferReader *r)
+HQClientTransaction::release(IOBufferReader *r)
{
super::release(r);
this->current_reader = nullptr;
}
bool
-Http3ClientTransaction::allow_half_open() const
+HQClientTransaction::allow_half_open() const
{
return false;
}
-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) {
- this->_cross_thread_event = this->_thread->schedule_imm(this, event,
edata);
- }
- return 0;
- }
-
- SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
-
- Event *e = static_cast<Event *>(edata);
- if (e == this->_cross_thread_event) {
- this->_cross_thread_event = nullptr;
- }
-
- switch (event) {
- case VC_EVENT_READ_READY:
- case VC_EVENT_READ_COMPLETE: {
- int64_t len = this->_process_read_vio();
- // if no progress, don't need to signal
- if (len > 0) {
- this->_signal_read_event();
- }
- this->_stream_io->read_reenable();
-
- break;
- }
- case VC_EVENT_WRITE_READY:
- case VC_EVENT_WRITE_COMPLETE: {
- int64_t len = this->_process_write_vio();
- if (len > 0) {
- this->_signal_write_event();
- }
- this->_stream_io->write_reenable();
-
- break;
- }
- case VC_EVENT_EOS:
- case VC_EVENT_ERROR:
- case VC_EVENT_INACTIVITY_TIMEOUT:
- case VC_EVENT_ACTIVE_TIMEOUT: {
- ink_assert(false);
- break;
- }
- case QPACK_EVENT_DECODE_COMPLETE: {
- int res = this->_on_qpack_decode_complete();
- if (res) {
- // If READ_READY event is scheduled, should it be canceled?
- this->_signal_read_event();
- }
- break;
- }
- case QPACK_EVENT_DECODE_FAILED: {
- // FIXME: handle error
- break;
- }
- default:
- Http3TransDebug("Unknown event %d", event);
- ink_assert(false);
- }
-
- return EVENT_DONE;
-}
-
-int
-Http3ClientTransaction::state_stream_closed(int event, void *data)
-{
- Http3TransVDebug("%s (%d)", get_vc_event_name(event), event);
-
- switch (event) {
- case VC_EVENT_READ_READY:
- case VC_EVENT_READ_COMPLETE: {
- // ignore
- break;
- }
- case VC_EVENT_WRITE_READY:
- case VC_EVENT_WRITE_COMPLETE: {
- // ignore
- break;
- }
- case VC_EVENT_EOS:
- case VC_EVENT_ERROR:
- case VC_EVENT_INACTIVITY_TIMEOUT:
- case VC_EVENT_ACTIVE_TIMEOUT: {
- // TODO
- ink_assert(false);
- break;
- }
- default:
- ink_assert(false);
- }
-
- return EVENT_DONE;
-}
-
VIO *
-Http3ClientTransaction::do_io_read(Continuation *c, int64_t nbytes, MIOBuffer
*buf)
+HQClientTransaction::do_io_read(Continuation *c, int64_t nbytes, MIOBuffer
*buf)
{
if (buf) {
this->_read_vio.buffer.writer_for(buf);
@@ -251,7 +132,7 @@ Http3ClientTransaction::do_io_read(Continuation *c, int64_t
nbytes, MIOBuffer *b
}
VIO *
-Http3ClientTransaction::do_io_write(Continuation *c, int64_t nbytes,
IOBufferReader *buf, bool owner)
+HQClientTransaction::do_io_write(Continuation *c, int64_t nbytes,
IOBufferReader *buf, bool owner)
{
if (buf) {
this->_write_vio.buffer.reader_for(buf);
@@ -273,10 +154,8 @@ Http3ClientTransaction::do_io_write(Continuation *c,
int64_t nbytes, IOBufferRea
}
void
-Http3ClientTransaction::do_io_close(int lerrno)
+HQClientTransaction::do_io_close(int lerrno)
{
- SET_HANDLER(&Http3ClientTransaction::state_stream_closed);
-
if (this->_read_event) {
this->_read_event->cancel();
this->_read_event = nullptr;
@@ -301,13 +180,13 @@ Http3ClientTransaction::do_io_close(int lerrno)
}
void
-Http3ClientTransaction::do_io_shutdown(ShutdownHowTo_t howto)
+HQClientTransaction::do_io_shutdown(ShutdownHowTo_t howto)
{
return;
}
void
-Http3ClientTransaction::reenable(VIO *vio)
+HQClientTransaction::reenable(VIO *vio)
{
if (vio->op == VIO::READ) {
int64_t len = this->_process_read_vio();
@@ -326,11 +205,42 @@ Http3ClientTransaction::reenable(VIO *vio)
}
}
+void
+HQClientTransaction::destroy()
+{
+ current_reader = nullptr;
+}
+
+void
+HQClientTransaction::transaction_done()
+{
+ // TODO: start closing transaction
+ return;
+}
+
+int
+HQClientTransaction::get_transaction_id() const
+{
+ return this->_stream_io->stream_id();
+}
+
+void
+HQClientTransaction::increment_client_transactions_stat()
+{
+ // TODO
+}
+
+void
+HQClientTransaction::decrement_client_transactions_stat()
+{
+ // TODO
+}
+
/**
* @brief Replace existing event only if the new event is different than the
inprogress event
*/
Event *
-Http3ClientTransaction::_send_tracked_event(Event *event, int send_event, VIO
*vio)
+HQClientTransaction::_send_tracked_event(Event *event, int send_event, VIO
*vio)
{
if (event != nullptr) {
if (event->callback_event != send_event) {
@@ -346,29 +256,11 @@ Http3ClientTransaction::_send_tracked_event(Event *event,
int send_event, VIO *v
return event;
}
-void
-Http3ClientTransaction::set_read_vio_nbytes(int64_t nbytes)
-{
- this->_read_vio.nbytes = nbytes;
-}
-
-void
-Http3ClientTransaction::set_write_vio_nbytes(int64_t nbytes)
-{
- this->_write_vio.nbytes = nbytes;
-}
-
-void
-Http3ClientTransaction::destroy()
-{
- current_reader = nullptr;
-}
-
/**
* @brief Signal event to this->_read_vio.cont
*/
void
-Http3ClientTransaction::_signal_read_event()
+HQClientTransaction::_signal_read_event()
{
if (this->_read_vio.cont == nullptr || this->_read_vio.op == VIO::NONE) {
return;
@@ -389,7 +281,7 @@ Http3ClientTransaction::_signal_read_event()
* @brief Signal event to this->_write_vio.cont
*/
void
-Http3ClientTransaction::_signal_write_event()
+HQClientTransaction::_signal_write_event()
{
if (this->_write_vio.cont == nullptr || this->_write_vio.op == VIO::NONE) {
return;
@@ -406,93 +298,159 @@ Http3ClientTransaction::_signal_write_event()
Http3TransVDebug("%s (%d)", get_vc_event_name(event), event);
}
-// Convert HTTP/0.9 to HTTP/1.1
-int64_t
-Http3ClientTransaction::_process_read_vio()
+//
+// Http3ClientTransaction
+//
+Http3ClientTransaction::Http3ClientTransaction(Http3ClientSession *session,
QUICStreamIO *stream_io) : super(session, stream_io)
{
- if (this->_read_vio.cont == nullptr || this->_read_vio.op == VIO::NONE) {
- return 0;
- }
+ static_cast<HQClientSession
*>(this->parent)->add_transaction(static_cast<HQClientTransaction *>(this));
+
+ this->_header_framer = new Http3HeaderFramer(this, &this->_write_vio,
session->local_qpack(), stream_io->stream_id());
+ this->_data_framer = new Http3DataFramer(this, &this->_write_vio);
+ this->_frame_collector.add_generator(this->_header_framer);
+ 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->_data_handler = new Http3StreamDataVIOAdaptor(&this->_read_vio);
+
+ this->_frame_dispatcher.add_handler(this->_header_handler);
+ this->_frame_dispatcher.add_handler(this->_data_handler);
+
+ SET_HANDLER(&Http3ClientTransaction::state_stream_open);
+}
+
+Http3ClientTransaction::~Http3ClientTransaction()
+{
+ delete this->_header_framer;
+ delete this->_data_framer;
+ delete this->_header_handler;
+ delete this->_data_handler;
+}
+
+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()) {
- SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
+ // Send on to the owning thread
if (this->_cross_thread_event == nullptr) {
- // Send to the right thread
- this->_cross_thread_event = this->_thread->schedule_imm(this,
VC_EVENT_READ_READY, nullptr);
+ this->_cross_thread_event = this->_thread->schedule_imm(this, event,
edata);
}
return 0;
}
- SCOPED_MUTEX_LOCK(lock, this->_read_vio.mutex, this_ethread());
+ SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
- // Nuke this block when we drop 0.9 support
- if (!this->_protocol_detected) {
- uint8_t start[3];
- if (this->_stream_io->peek(start, 3) < 3) {
- return 0;
- }
- // If the first two bit are 0 and 1, the 3rd byte is type field.
- // Because there is no type value larger than 0x20, we can assume that the
- // request is HTTP/0.9 if the value is larger than 0x20.
- if (0x40 <= start[0] && start[0] < 0x80 && start[2] > 0x20) {
- this->_legacy_request = true;
- }
- this->_protocol_detected = true;
+ Event *e = static_cast<Event *>(edata);
+ if (e == this->_cross_thread_event) {
+ this->_cross_thread_event = nullptr;
}
- if (this->_legacy_request) {
- uint64_t nread = 0;
- MIOBuffer *writer = this->_read_vio.get_writer();
+ switch (event) {
+ case VC_EVENT_READ_READY:
+ case VC_EVENT_READ_COMPLETE: {
+ int64_t len = this->_process_read_vio();
+ // if no progress, don't need to signal
+ if (len > 0) {
+ this->_signal_read_event();
+ }
+ this->_stream_io->read_reenable();
- // Nuke this branch when we drop 0.9 support
- if (!this->_client_req_header_complete) {
- uint8_t buf[4096];
- int len = this->_stream_io->peek(buf, 4096);
- // Check client request is complete or not
- if (len < 2 || buf[len - 1] != '\n') {
- return 0;
- }
- this->_stream_io->consume(len);
- nread += len;
- this->_client_req_header_complete = true;
+ break;
+ }
+ case VC_EVENT_WRITE_READY:
+ case VC_EVENT_WRITE_COMPLETE: {
+ int64_t len = this->_process_write_vio();
+ if (len > 0) {
+ this->_signal_write_event();
+ }
+ this->_stream_io->write_reenable();
- // Check "CRLF" or "LF"
- int n = 2;
- if (buf[len - 2] != '\r') {
- n = 1;
- }
-
- writer->write(buf, len - n);
- // FIXME: Get hostname from SNI?
- const char version[] = " HTTP/1.1\r\nHost: localhost\r\n\r\n";
- writer->write(version, sizeof(version));
- } else {
- uint8_t buf[4096];
- int len;
- while ((len = this->_stream_io->read(buf, 4096)) > 0) {
- nread += len;
- writer->write(buf, len);
- }
+ break;
+ }
+ case VC_EVENT_EOS:
+ case VC_EVENT_ERROR:
+ case VC_EVENT_INACTIVITY_TIMEOUT:
+ case VC_EVENT_ACTIVE_TIMEOUT: {
+ Http3TransVDebug("%s (%d)", get_vc_event_name(event), event);
+ break;
+ }
+ case QPACK_EVENT_DECODE_COMPLETE: {
+ int res = this->_on_qpack_decode_complete();
+ if (res) {
+ // If READ_READY event is scheduled, should it be canceled?
+ this->_signal_read_event();
}
+ break;
+ }
+ case QPACK_EVENT_DECODE_FAILED: {
+ // FIXME: handle error
+ break;
+ }
+ default:
+ Http3TransDebug("Unknown event %d", event);
+ }
- return nread;
- // End of code for HTTP/0.9
- } else {
- // This branch is for HTTP/3
- uint64_t nread = 0;
- this->_frame_dispatcher.on_read_ready(*this->_stream_io, nread);
- return nread;
+ return EVENT_DONE;
+}
+
+int
+Http3ClientTransaction::state_stream_closed(int event, void *data)
+{
+ Http3TransVDebug("%s (%d)", get_vc_event_name(event), event);
+
+ switch (event) {
+ case VC_EVENT_READ_READY:
+ case VC_EVENT_READ_COMPLETE: {
+ // ignore
+ break;
+ }
+ case VC_EVENT_WRITE_READY:
+ case VC_EVENT_WRITE_COMPLETE: {
+ // ignore
+ break;
+ }
+ case VC_EVENT_EOS:
+ case VC_EVENT_ERROR:
+ case VC_EVENT_INACTIVITY_TIMEOUT:
+ case VC_EVENT_ACTIVE_TIMEOUT: {
+ // TODO
+ Http3TransVDebug("%s (%d)", get_vc_event_name(event), event);
+ break;
+ }
+ default:
+ Http3TransDebug("Unknown event %d", event);
}
+
+ return EVENT_DONE;
}
-// FIXME: already defined somewhere?
-static constexpr char http_1_1_version[] = "HTTP/1.1";
+void
+Http3ClientTransaction::do_io_close(int lerrno)
+{
+ SET_HANDLER(&Http3ClientTransaction::state_stream_closed);
+ super::do_io_close(lerrno);
+}
+
+bool
+Http3ClientTransaction::is_response_header_sent() const
+{
+ return this->_header_framer->is_done();
+}
+
+bool
+Http3ClientTransaction::is_response_body_sent() const
+{
+ return this->_data_framer->is_done();
+}
-// Convert HTTP/1.1 to HTTP/0.9
int64_t
-Http3ClientTransaction::_process_write_vio()
+Http3ClientTransaction::_process_read_vio()
{
- if (this->_write_vio.cont == nullptr || this->_write_vio.op == VIO::NONE) {
+ if (this->_read_vio.cont == nullptr || this->_read_vio.op == VIO::NONE) {
return 0;
}
@@ -500,57 +458,40 @@ Http3ClientTransaction::_process_write_vio()
SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
if (this->_cross_thread_event == nullptr) {
// Send to the right thread
- this->_cross_thread_event = this->_thread->schedule_imm(this,
VC_EVENT_WRITE_READY, nullptr);
+ this->_cross_thread_event = this->_thread->schedule_imm(this,
VC_EVENT_READ_READY, nullptr);
}
return 0;
}
- SCOPED_MUTEX_LOCK(lock, this->_write_vio.mutex, this_ethread());
+ SCOPED_MUTEX_LOCK(lock, this->_read_vio.mutex, this_ethread());
- IOBufferReader *reader = this->_write_vio.get_reader();
+ uint64_t nread = 0;
+ this->_frame_dispatcher.on_read_ready(*this->_stream_io, nread);
+ return nread;
+}
- if (this->_legacy_request) {
- // This branch is for HTTP/0.9
- int64_t http_1_1_version_len = sizeof(http_1_1_version) - 1;
+int64_t
+Http3ClientTransaction::_process_write_vio()
+{
+ if (this->_write_vio.cont == nullptr || this->_write_vio.op == VIO::NONE) {
+ return 0;
+ }
- if (reader->is_read_avail_more_than(http_1_1_version_len) &&
- memcmp(reader->start(), http_1_1_version, http_1_1_version_len) == 0) {
- // Skip HTTP/1.1 response headers
- IOBufferBlock *headers = reader->get_current_block();
- int64_t headers_size = headers->read_avail();
- reader->consume(headers_size);
- this->_write_vio.ndone += headers_size;
+ if (this->_thread != this_ethread()) {
+ SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
+ if (this->_cross_thread_event == nullptr) {
+ // Send to the right thread
+ this->_cross_thread_event = this->_thread->schedule_imm(this,
VC_EVENT_WRITE_READY, nullptr);
}
+ return 0;
+ }
- // Write HTTP/1.1 response body
- int64_t bytes_avail = reader->read_avail();
- int64_t total_written = 0;
-
- while (total_written < bytes_avail) {
- int64_t data_len = reader->block_read_avail();
- int64_t bytes_written = this->_stream_io->write(reader, data_len);
- if (bytes_written <= 0) {
- break;
- }
-
- reader->consume(bytes_written);
- this->_write_vio.ndone += bytes_written;
- total_written += bytes_written;
- }
+ SCOPED_MUTEX_LOCK(lock, this->_write_vio.mutex, this_ethread());
- // NOTE: When Chunked Transfer Coding is supported, check ChunkedState of
ChunkedHandler
- // is CHUNK_READ_DONE and set FIN flag
- if (this->_write_vio.ntodo() == 0) {
- // The size of respons to client
- this->_stream_io->write_done();
- }
+ size_t nwritten = 0;
+ this->_frame_collector.on_write_ready(this->_stream_io, nwritten);
- return total_written;
- } else {
- size_t nwritten = 0;
- this->_frame_collector.on_write_ready(this->_stream_io, nwritten);
- return nwritten;
- }
+ return nwritten;
}
// Constant strings for pseudo headers
@@ -624,39 +565,260 @@ Http3ClientTransaction::_on_qpack_decode_complete()
return 1;
}
-void
-Http3ClientTransaction::transaction_done()
+//
+// Http09ClientTransaction
+//
+Http09ClientTransaction::Http09ClientTransaction(Http09ClientSession *session,
QUICStreamIO *stream_io) : super(session, stream_io)
{
- // TODO: start closing transaction
- return;
+ static_cast<HQClientSession
*>(this->parent)->add_transaction(static_cast<HQClientTransaction *>(this));
+
+ SET_HANDLER(&Http09ClientTransaction::state_stream_open);
}
+Http09ClientTransaction::~Http09ClientTransaction() {}
+
int
-Http3ClientTransaction::get_transaction_id() const
+Http09ClientTransaction::state_stream_open(int event, void *edata)
{
- return this->_stream_io->stream_id();
+ // 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) {
+ this->_cross_thread_event = this->_thread->schedule_imm(this, event,
edata);
+ }
+ return 0;
+ }
+
+ SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
+
+ Event *e = static_cast<Event *>(edata);
+ if (e == this->_cross_thread_event) {
+ this->_cross_thread_event = nullptr;
+ }
+
+ switch (event) {
+ case VC_EVENT_READ_READY:
+ case VC_EVENT_READ_COMPLETE: {
+ int64_t len = this->_process_read_vio();
+ // if no progress, don't need to signal
+ if (len > 0) {
+ this->_signal_read_event();
+ }
+ this->_stream_io->read_reenable();
+
+ break;
+ }
+ case VC_EVENT_WRITE_READY:
+ case VC_EVENT_WRITE_COMPLETE: {
+ int64_t len = this->_process_write_vio();
+ if (len > 0) {
+ this->_signal_write_event();
+ }
+ this->_stream_io->write_reenable();
+
+ break;
+ }
+ case VC_EVENT_EOS:
+ case VC_EVENT_ERROR:
+ case VC_EVENT_INACTIVITY_TIMEOUT:
+ case VC_EVENT_ACTIVE_TIMEOUT: {
+ Http3TransDebug("%d", event);
+ break;
+ }
+ default:
+ Http3TransDebug("Unknown event %d", event);
+ }
+
+ return EVENT_DONE;
}
void
-Http3ClientTransaction::increment_client_transactions_stat()
+Http09ClientTransaction::do_io_close(int lerrno)
{
- // TODO
+ SET_HANDLER(&Http09ClientTransaction::state_stream_closed);
+ super::do_io_close(lerrno);
}
-void
-Http3ClientTransaction::decrement_client_transactions_stat()
+int
+Http09ClientTransaction::state_stream_closed(int event, void *data)
{
- // TODO
+ Http3TransVDebug("%s (%d)", get_vc_event_name(event), event);
+
+ switch (event) {
+ case VC_EVENT_READ_READY:
+ case VC_EVENT_READ_COMPLETE: {
+ // ignore
+ break;
+ }
+ case VC_EVENT_WRITE_READY:
+ case VC_EVENT_WRITE_COMPLETE: {
+ // ignore
+ break;
+ }
+ case VC_EVENT_EOS:
+ case VC_EVENT_ERROR:
+ case VC_EVENT_INACTIVITY_TIMEOUT:
+ case VC_EVENT_ACTIVE_TIMEOUT: {
+ // TODO
+ break;
+ }
+ default:
+ Http3TransDebug("Unknown event %d", event);
+ }
+
+ return EVENT_DONE;
}
-bool
-Http3ClientTransaction::is_response_header_sent() const
+// Convert HTTP/0.9 to HTTP/1.1
+int64_t
+Http09ClientTransaction::_process_read_vio()
{
- return this->_header_framer->is_done();
+ if (this->_read_vio.cont == nullptr || this->_read_vio.op == VIO::NONE) {
+ return 0;
+ }
+
+ if (this->_thread != this_ethread()) {
+ SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
+ if (this->_cross_thread_event == nullptr) {
+ // Send to the right thread
+ this->_cross_thread_event = this->_thread->schedule_imm(this,
VC_EVENT_READ_READY, nullptr);
+ }
+ return 0;
+ }
+
+ SCOPED_MUTEX_LOCK(lock, this->_read_vio.mutex, this_ethread());
+
+ // Nuke this block when we drop 0.9 support
+ if (!this->_protocol_detected) {
+ uint8_t start[3];
+ if (this->_stream_io->peek(start, 3) < 3) {
+ return 0;
+ }
+ // If the first two bit are 0 and 1, the 3rd byte is type field.
+ // Because there is no type value larger than 0x20, we can assume that the
+ // request is HTTP/0.9 if the value is larger than 0x20.
+ if (0x40 <= start[0] && start[0] < 0x80 && start[2] > 0x20) {
+ this->_legacy_request = true;
+ }
+ this->_protocol_detected = true;
+ }
+
+ if (this->_legacy_request) {
+ uint64_t nread = 0;
+ MIOBuffer *writer = this->_read_vio.get_writer();
+
+ // Nuke this branch when we drop 0.9 support
+ if (!this->_client_req_header_complete) {
+ uint8_t buf[4096];
+ int len = this->_stream_io->peek(buf, 4096);
+ // Check client request is complete or not
+ if (len < 2 || buf[len - 1] != '\n') {
+ return 0;
+ }
+ this->_stream_io->consume(len);
+ nread += len;
+ this->_client_req_header_complete = true;
+
+ // Check "CRLF" or "LF"
+ int n = 2;
+ if (buf[len - 2] != '\r') {
+ n = 1;
+ }
+
+ writer->write(buf, len - n);
+ // FIXME: Get hostname from SNI?
+ const char version[] = " HTTP/1.1\r\nHost: localhost\r\n\r\n";
+ writer->write(version, sizeof(version));
+ } else {
+ uint8_t buf[4096];
+ int len;
+ while ((len = this->_stream_io->read(buf, 4096)) > 0) {
+ nread += len;
+ writer->write(buf, len);
+ }
+ }
+
+ return nread;
+ // End of code for HTTP/0.9
+ } else {
+ // Ignore malformed data
+ uint8_t buf[4096];
+ int len;
+ uint64_t nread = 0;
+
+ while ((len = this->_stream_io->read(buf, 4096)) > 0) {
+ nread += len;
+ }
+
+ return nread;
+ }
}
-bool
-Http3ClientTransaction::is_response_body_sent() const
+// FIXME: already defined somewhere?
+static constexpr char http_1_1_version[] = "HTTP/1.1";
+
+// Convert HTTP/1.1 to HTTP/0.9
+int64_t
+Http09ClientTransaction::_process_write_vio()
{
- return this->_data_framer->is_done();
+ if (this->_write_vio.cont == nullptr || this->_write_vio.op == VIO::NONE) {
+ return 0;
+ }
+
+ if (this->_thread != this_ethread()) {
+ SCOPED_MUTEX_LOCK(lock, this->mutex, this_ethread());
+ if (this->_cross_thread_event == nullptr) {
+ // Send to the right thread
+ this->_cross_thread_event = this->_thread->schedule_imm(this,
VC_EVENT_WRITE_READY, nullptr);
+ }
+ return 0;
+ }
+
+ SCOPED_MUTEX_LOCK(lock, this->_write_vio.mutex, this_ethread());
+
+ IOBufferReader *reader = this->_write_vio.get_reader();
+
+ if (this->_legacy_request) {
+ // This branch is for HTTP/0.9
+ int64_t http_1_1_version_len = sizeof(http_1_1_version) - 1;
+
+ if (reader->is_read_avail_more_than(http_1_1_version_len) &&
+ memcmp(reader->start(), http_1_1_version, http_1_1_version_len) == 0) {
+ // Skip HTTP/1.1 response headers
+ IOBufferBlock *headers = reader->get_current_block();
+ int64_t headers_size = headers->read_avail();
+ reader->consume(headers_size);
+ this->_write_vio.ndone += headers_size;
+ }
+
+ // Write HTTP/1.1 response body
+ int64_t bytes_avail = reader->read_avail();
+ int64_t total_written = 0;
+
+ while (total_written < bytes_avail) {
+ int64_t data_len = reader->block_read_avail();
+ int64_t bytes_written = this->_stream_io->write(reader, data_len);
+ if (bytes_written <= 0) {
+ break;
+ }
+
+ reader->consume(bytes_written);
+ this->_write_vio.ndone += bytes_written;
+ total_written += bytes_written;
+ }
+
+ // NOTE: When Chunked Transfer Coding is supported, check ChunkedState of
ChunkedHandler
+ // is CHUNK_READ_DONE and set FIN flag
+ if (this->_write_vio.ntodo() == 0) {
+ // The size of respons to client
+ this->_stream_io->write_done();
+ }
+
+ return total_written;
+ } else {
+ // nothing to do
+ return 0;
+ }
}
diff --git a/proxy/http3/Http3ClientTransaction.h
b/proxy/http3/Http3ClientTransaction.h
index 32297d5..9d415ad 100644
--- a/proxy/http3/Http3ClientTransaction.h
+++ b/proxy/http3/Http3ClientTransaction.h
@@ -29,17 +29,19 @@
#include "Http3FrameCollector.h"
class QUICStreamIO;
+class HQClientSession;
+class Http09ClientSession;
class Http3ClientSession;
class Http3HeaderFramer;
class Http3DataFramer;
-class Http3ClientTransaction : public ProxyClientTransaction
+class HQClientTransaction : public ProxyClientTransaction
{
public:
using super = ProxyClientTransaction;
- Http3ClientTransaction(Http3ClientSession *session, QUICStreamIO *stream_io);
- ~Http3ClientTransaction();
+ HQClientTransaction(HQClientSession *session, QUICStreamIO *stream_io);
+ ~HQClientTransaction();
// Implement ProxyClienTransaction interface
void set_active_timeout(ink_hrtime timeout_in) override;
@@ -54,30 +56,23 @@ public:
void decrement_client_transactions_stat() override;
// VConnection interface
- VIO *do_io_read(Continuation *c, int64_t nbytes = INT64_MAX, MIOBuffer *buf
= 0) override;
- VIO *do_io_write(Continuation *c = nullptr, int64_t nbytes = INT64_MAX,
IOBufferReader *buf = 0, bool owner = false) override;
- void do_io_close(int lerrno = -1) override;
- void do_io_shutdown(ShutdownHowTo_t) override;
- void reenable(VIO *) override;
-
- void set_read_vio_nbytes(int64_t nbytes);
- void set_write_vio_nbytes(int64_t nbytes);
-
- // Http3ClientTransaction specific methods
- int state_stream_open(int, void *);
- int state_stream_closed(int event, void *data);
- bool is_response_header_sent() const;
- bool is_response_body_sent() const;
-
-private:
+ virtual VIO *do_io_read(Continuation *c, int64_t nbytes = INT64_MAX,
MIOBuffer *buf = 0) override;
+ virtual VIO *do_io_write(Continuation *c = nullptr, int64_t nbytes =
INT64_MAX, IOBufferReader *buf = 0,
+ bool owner = false) override;
+ virtual void do_io_close(int lerrno = -1) override;
+ virtual void do_io_shutdown(ShutdownHowTo_t) override;
+ virtual void reenable(VIO *) override;
+
+ // HQClientTransaction
+ virtual int state_stream_open(int, void *) = 0;
+ virtual int state_stream_closed(int event, void *data) = 0;
+
+protected:
+ virtual int64_t _process_read_vio() = 0;
+ virtual int64_t _process_write_vio() = 0;
Event *_send_tracked_event(Event *, int, VIO *);
void _signal_read_event();
void _signal_write_event();
- int64_t _process_read_vio();
- int64_t _process_write_vio();
-
- ParseResult _convert_header_from_3_to_1_1(HTTPHdr *hdr);
- int _on_qpack_decode_complete();
EThread *_thread = nullptr;
Event *_cross_thread_event = nullptr;
@@ -91,16 +86,61 @@ private:
Event *_write_event = nullptr;
HTTPHdr _request_header;
+};
+
+class Http3ClientTransaction : public HQClientTransaction
+{
+public:
+ using super = HQClientTransaction;
- // These are for Http3
+ Http3ClientTransaction(Http3ClientSession *session, QUICStreamIO *stream_io);
+ ~Http3ClientTransaction();
+
+ int state_stream_open(int event, void *data) override;
+ int state_stream_closed(int event, void *data) override;
+
+ void do_io_close(int lerrno = -1) override;
+
+ bool is_response_header_sent() const;
+ bool is_response_body_sent() const;
+
+private:
+ int64_t _process_read_vio() override;
+ int64_t _process_write_vio() override;
+
+ ParseResult _convert_header_from_3_to_1_1(HTTPHdr *hdr);
+ int _on_qpack_decode_complete();
+
+ // These are for HTTP/3
Http3FrameDispatcher _frame_dispatcher;
Http3FrameCollector _frame_collector;
Http3FrameGenerator *_header_framer = nullptr;
Http3FrameGenerator *_data_framer = nullptr;
Http3FrameHandler *_header_handler = nullptr;
Http3FrameHandler *_data_handler = nullptr;
+};
+
+/**
+ Only for interop. Will be removed.
+ */
+class Http09ClientTransaction : public HQClientTransaction
+{
+public:
+ using super = HQClientTransaction;
+
+ Http09ClientTransaction(Http09ClientSession *session, QUICStreamIO
*stream_io);
+ ~Http09ClientTransaction();
+
+ int state_stream_open(int event, void *data) override;
+ int state_stream_closed(int event, void *data) override;
+
+ void do_io_close(int lerrno = -1) override;
+
+private:
+ int64_t _process_read_vio() override;
+ int64_t _process_write_vio() override;
- // These are for 0.9 support
+ // These are for HTTP/0.9
bool _protocol_detected = false;
bool _legacy_request = false;
bool _client_req_header_complete = false;