This is an automated email from the ASF dual-hosted git repository. maskit 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 57fe4b2 Send CLOSE_CONNECTION or RST_STREAM when error occurs 57fe4b2 is described below commit 57fe4b2a4981b7ec3126e2094f854c4e589b0c4a Author: Masakazu Kitajo <mas...@apache.org> AuthorDate: Thu Sep 28 17:24:35 2017 +0900 Send CLOSE_CONNECTION or RST_STREAM when error occurs --- iocore/net/P_QUICNetVConnection.h | 19 +++--- iocore/net/QUICNetVConnection.cc | 95 +++++++++++++++++------------ iocore/net/quic/QUICCongestionController.cc | 4 +- iocore/net/quic/QUICCongestionController.h | 2 +- iocore/net/quic/QUICConnection.h | 2 +- iocore/net/quic/QUICFlowController.cc | 10 +-- iocore/net/quic/QUICFlowController.h | 4 +- iocore/net/quic/QUICFrame.cc | 13 ++++ iocore/net/quic/QUICFrame.h | 3 + iocore/net/quic/QUICFrameDispatcher.cc | 10 +-- iocore/net/quic/QUICFrameDispatcher.h | 2 +- iocore/net/quic/QUICFrameHandler.h | 4 +- iocore/net/quic/QUICHandshake.cc | 53 +++++++++------- iocore/net/quic/QUICHandshake.h | 8 +-- iocore/net/quic/QUICLossDetector.cc | 4 +- iocore/net/quic/QUICLossDetector.h | 2 +- iocore/net/quic/QUICStream.cc | 58 +++++++++++------- iocore/net/quic/QUICStream.h | 11 ++-- iocore/net/quic/QUICStreamManager.cc | 28 ++++----- iocore/net/quic/QUICStreamManager.h | 12 ++-- iocore/net/quic/QUICTypes.h | 45 +++++++++++--- 21 files changed, 237 insertions(+), 152 deletions(-) diff --git a/iocore/net/P_QUICNetVConnection.h b/iocore/net/P_QUICNetVConnection.h index 568e420..7db4cd8 100644 --- a/iocore/net/P_QUICNetVConnection.h +++ b/iocore/net/P_QUICNetVConnection.h @@ -177,7 +177,7 @@ public: uint32_t pmtu() override; NetVConnectionContext_t direction() override; SSLNextProtocolSet *next_protocol_set() override; - void close(QUICError error) override; + void close(QUICConnectionErrorUPtr error) override; QUICPacketNumber largest_received_packet_number() override; QUICPacketNumber largest_acked_packet_number() override; @@ -191,7 +191,7 @@ public: // QUICConnection (QUICFrameHandler) std::vector<QUICFrameType> interests() override; - QUICError handle_frame(std::shared_ptr<const QUICFrame> frame) override; + QUICErrorUPtr handle_frame(std::shared_ptr<const QUICFrame> frame) override; private: std::random_device _rnd; @@ -240,20 +240,21 @@ private: QUICPacketUPtr _build_packet(ats_unique_buf buf, size_t len, bool retransmittable, QUICPacketType type = QUICPacketType::UNINITIALIZED); - QUICError _recv_and_ack(const uint8_t *payload, uint16_t size, QUICPacketNumber packet_numm); + QUICErrorUPtr _recv_and_ack(const uint8_t *payload, uint16_t size, QUICPacketNumber packet_numm); - QUICError _state_handshake_process_initial_client_packet(QUICPacketUPtr packet); - QUICError _state_handshake_process_client_cleartext_packet(QUICPacketUPtr packet); - QUICError _state_handshake_process_zero_rtt_protected_packet(QUICPacketUPtr packet); - QUICError _state_connection_established_process_packet(QUICPacketUPtr packet); - QUICError _state_common_receive_packet(); - QUICError _state_common_send_packet(); + QUICErrorUPtr _state_handshake_process_initial_client_packet(QUICPacketUPtr packet); + QUICErrorUPtr _state_handshake_process_client_cleartext_packet(QUICPacketUPtr packet); + QUICErrorUPtr _state_handshake_process_zero_rtt_protected_packet(QUICPacketUPtr packet); + QUICErrorUPtr _state_connection_established_process_packet(QUICPacketUPtr packet); + QUICErrorUPtr _state_common_receive_packet(); + QUICErrorUPtr _state_common_send_packet(); Ptr<ProxyMutex> _packet_transmitter_mutex; Ptr<ProxyMutex> _frame_transmitter_mutex; void _init_flow_control_params(const std::shared_ptr<const QUICTransportParameters> &local_tp, const std::shared_ptr<const QUICTransportParameters> &remote_tp); + void _handle_error(QUICErrorUPtr error); QUICStatelessToken _token; }; diff --git a/iocore/net/QUICNetVConnection.cc b/iocore/net/QUICNetVConnection.cc index c7e1ffb..c0b2848 100644 --- a/iocore/net/QUICNetVConnection.cc +++ b/iocore/net/QUICNetVConnection.cc @@ -287,7 +287,7 @@ QUICNetVConnection::transmit_frame(QUICFrameUPtr frame) } void -QUICNetVConnection::close(QUICError error) +QUICNetVConnection::close(QUICConnectionErrorUPtr error) { if (this->handler == reinterpret_cast<ContinuationHandler>(&QUICNetVConnection::state_connection_closed) || this->handler == reinterpret_cast<ContinuationHandler>(&QUICNetVConnection::state_connection_closing)) { @@ -295,7 +295,7 @@ QUICNetVConnection::close(QUICError error) } else { DebugQUICCon("Enter state_connection_closing"); SET_HANDLER((NetVConnHandler)&QUICNetVConnection::state_connection_closing); - this->transmit_frame(QUICFrameFactory::create_connection_close_frame(error.code, 0, "")); + this->transmit_frame(QUICFrameFactory::create_connection_close_frame(std::move(error))); } } @@ -305,10 +305,10 @@ QUICNetVConnection::interests() return {QUICFrameType::CONNECTION_CLOSE, QUICFrameType::BLOCKED, QUICFrameType::MAX_DATA}; } -QUICError +QUICErrorUPtr QUICNetVConnection::handle_frame(std::shared_ptr<const QUICFrame> frame) { - QUICError error = QUICError(QUICErrorClass::NONE); + QUICErrorUPtr error = QUICErrorUPtr(new QUICNoError()); switch (frame->type()) { case QUICFrameType::MAX_DATA: @@ -367,7 +367,7 @@ QUICNetVConnection::state_pre_handshake(int event, Event *data) int QUICNetVConnection::state_handshake(int event, Event *data) { - QUICError error; + QUICErrorUPtr error = QUICErrorUPtr(new QUICNoError()); switch (event) { case QUIC_EVENT_PACKET_READ_READY: { @@ -388,7 +388,7 @@ QUICNetVConnection::state_handshake(int event, Event *data) break; } default: - error = QUICError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::INTERNAL_ERROR); + error = QUICErrorUPtr(new QUICConnectionError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::INTERNAL_ERROR)); break; } @@ -414,10 +414,8 @@ QUICNetVConnection::state_handshake(int event, Event *data) DebugQUICCon("Unexpected event: %s", QUICDebugNames::quic_event(event)); } - if (error.cls != QUICErrorClass::NONE) { - // TODO: Send error if needed - DebugQUICCon("QUICError: %s (%u), %s (0x%x)", QUICDebugNames::error_class(error.cls), static_cast<unsigned int>(error.cls), - QUICDebugNames::error_code(error.code), static_cast<unsigned int>(error.code)); + if (error->cls != QUICErrorClass::NONE) { + this->_handle_error(std::move(error)); } if (this->_handshake_handler && this->_handshake_handler->is_completed()) { @@ -440,7 +438,7 @@ QUICNetVConnection::state_handshake(int event, Event *data) int QUICNetVConnection::state_connection_established(int event, Event *data) { - QUICError error; + QUICErrorUPtr error = QUICErrorUPtr(new QUICNoError()); switch (event) { case QUIC_EVENT_PACKET_READ_READY: { error = this->_state_common_receive_packet(); @@ -465,9 +463,9 @@ QUICNetVConnection::state_connection_established(int event, Event *data) DebugQUICCon("Unexpected event: %s", QUICDebugNames::quic_event(event)); } - if (error.cls != QUICErrorClass::NONE) { - // TODO: Send error if needed - DebugQUICCon("QUICError: cls=%u, code=0x%x", static_cast<unsigned int>(error.cls), static_cast<unsigned int>(error.code)); + if (error->cls != QUICErrorClass::NONE) { + DebugQUICCon("QUICError: cls=%u, code=0x%x", static_cast<unsigned int>(error->cls), static_cast<unsigned int>(error->code)); + this->_handle_error(std::move(error)); } return EVENT_CONT; @@ -476,7 +474,7 @@ QUICNetVConnection::state_connection_established(int event, Event *data) int QUICNetVConnection::state_connection_closing(int event, Event *data) { - QUICError error; + QUICErrorUPtr error = QUICErrorUPtr(new QUICNoError()); switch (event) { case QUIC_EVENT_PACKET_READ_READY: { error = this->_state_common_receive_packet(); @@ -576,64 +574,65 @@ QUICNetVConnection::largest_acked_packet_number() return this->_loss_detector->largest_acked_packet_number(); } -QUICError +QUICErrorUPtr QUICNetVConnection::_state_handshake_process_initial_client_packet(QUICPacketUPtr packet) { if (packet->size() < MINIMUM_INITIAL_CLIENT_PACKET_SIZE) { DebugQUICCon("Packet size is smaller than the minimum initial client packet size"); - return QUICError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::INTERNAL_ERROR); + // Ignore the packet + return QUICErrorUPtr(new QUICNoError()); } // Start handshake - QUICError error = this->_handshake_handler->start(packet.get(), &this->_packet_factory); + QUICErrorUPtr error = this->_handshake_handler->start(packet.get(), &this->_packet_factory); if (this->_handshake_handler->is_version_negotiated()) { // Check integrity (QUIC-TLS-04: 6.1. Integrity Check Processing) if (packet->has_valid_fnv1a_hash()) { bool should_send_ack; error = this->_frame_dispatcher->receive_frames(packet->payload(), packet->payload_size(), should_send_ack); - if (error.cls != QUICErrorClass::NONE) { + if (error->cls != QUICErrorClass::NONE) { return error; } error = this->_local_flow_controller->update(this->_stream_manager->total_offset_received()); Debug("quic_flow_ctrl", "Connection [%" PRIx64 "] [LOCAL] %" PRIu64 "/%" PRIu64, static_cast<uint64_t>(this->_quic_connection_id), this->_local_flow_controller->current_offset(), this->_local_flow_controller->current_limit()); - if (error.cls != QUICErrorClass::NONE) { + if (error->cls != QUICErrorClass::NONE) { return error; } } else { DebugQUICCon("Invalid FNV-1a hash value"); - return QUICError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::CRYPTOGRAPHIC_ERROR); + // Discard the packet } } return error; } -QUICError +QUICErrorUPtr QUICNetVConnection::_state_handshake_process_client_cleartext_packet(QUICPacketUPtr packet) { - QUICError error = QUICError(QUICErrorClass::NONE); + QUICErrorUPtr error = QUICErrorUPtr(new QUICNoError()); // The payload of this packet contains STREAM frames and could contain PADDING and ACK frames if (packet->has_valid_fnv1a_hash()) { error = this->_recv_and_ack(packet->payload(), packet->payload_size(), packet->packet_number()); } else { DebugQUICCon("Invalid FNV-1a hash value"); - return QUICError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::CRYPTOGRAPHIC_ERROR); + // Discard the packet } return error; } -QUICError +QUICErrorUPtr QUICNetVConnection::_state_handshake_process_zero_rtt_protected_packet(QUICPacketUPtr packet) { // TODO: Decrypt the packet // decrypt(payload, p); // TODO: Not sure what we have to do - return QUICError(QUICErrorClass::NONE); + return QUICErrorUPtr(new QUICNoError()); } -QUICError +QUICErrorUPtr QUICNetVConnection::_state_connection_established_process_packet(QUICPacketUPtr packet) { // TODO: fix size @@ -650,15 +649,15 @@ QUICNetVConnection::_state_connection_established_process_packet(QUICPacketUPtr } else { DebugQUICCon("CRYPTOGRAPHIC Error"); - return QUICError(QUICErrorClass::CRYPTOGRAPHIC); + return QUICConnectionErrorUPtr(new QUICConnectionError(QUICErrorClass::CRYPTOGRAPHIC, QUICErrorCode::CRYPTOGRAPHIC_ERROR)); } } -QUICError +QUICErrorUPtr QUICNetVConnection::_state_common_receive_packet() { - QUICError error; - QUICPacketUPtr p = QUICPacketUPtr(this->_packet_recv_queue.dequeue(), &QUICPacketDeleter::delete_packet); + QUICErrorUPtr error = QUICErrorUPtr(new QUICNoError()); + QUICPacketUPtr p = QUICPacketUPtr(this->_packet_recv_queue.dequeue(), &QUICPacketDeleter::delete_packet); net_activity(this, this_ethread()); switch (p->type()) { @@ -667,13 +666,13 @@ QUICNetVConnection::_state_common_receive_packet() error = this->_state_connection_established_process_packet(std::move(p)); break; default: - error = QUICError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::INTERNAL_ERROR); + error = QUICErrorUPtr(new QUICConnectionError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::INTERNAL_ERROR)); break; } return error; } -QUICError +QUICErrorUPtr QUICNetVConnection::_state_common_send_packet() { this->_packetize_frames(); @@ -688,19 +687,19 @@ QUICNetVConnection::_state_common_send_packet() net_activity(this, this_ethread()); - return QUICError(QUICErrorClass::NONE); + return QUICErrorUPtr(new QUICNoError()); } // Schedule sending BLOCKED frame when offset exceed the limit bool QUICNetVConnection::_is_send_frame_avail_more_than(uint32_t size) { - QUICError error = this->_remote_flow_controller->update((this->_stream_manager->total_offset_sent() + size) / 1024); + QUICErrorUPtr error = this->_remote_flow_controller->update((this->_stream_manager->total_offset_sent() + size) / 1024); Debug("quic_flow_ctrl", "Connection [%" PRIx64 "] [REMOTE] %" PRIu64 "/%" PRIu64, static_cast<uint64_t>(this->_quic_connection_id), this->_remote_flow_controller->current_offset(), this->_remote_flow_controller->current_limit()); - if (error.cls != QUICErrorClass::NONE) { + if (error->cls != QUICErrorClass::NONE) { // Flow Contoroller blocked sending STREAM frame return false; } @@ -792,7 +791,7 @@ QUICNetVConnection::_packetize_frames() } } -QUICError +QUICErrorUPtr QUICNetVConnection::_recv_and_ack(const uint8_t *payload, uint16_t size, QUICPacketNumber packet_num) { if (packet_num > this->_largest_received_packet_number) { @@ -801,17 +800,17 @@ QUICNetVConnection::_recv_and_ack(const uint8_t *payload, uint16_t size, QUICPac bool should_send_ack; - QUICError error; + QUICErrorUPtr error = QUICErrorUPtr(new QUICNoError()); error = this->_frame_dispatcher->receive_frames(payload, size, should_send_ack); - if (error.cls != QUICErrorClass::NONE) { + if (error->cls != QUICErrorClass::NONE) { return error; } error = this->_local_flow_controller->update(this->_stream_manager->total_offset_received()); Debug("quic_flow_ctrl", "Connection [%" PRIx64 "] [LOCAL] %" PRIu64 "/%" PRIu64, static_cast<uint64_t>(this->_quic_connection_id), this->_local_flow_controller->current_offset(), this->_local_flow_controller->current_limit()); - if (error.cls != QUICErrorClass::NONE) { + if (error->cls != QUICErrorClass::NONE) { return error; } // this->_local_flow_controller->forward_limit(); @@ -872,3 +871,19 @@ QUICNetVConnection::_init_flow_control_params(const std::shared_ptr<const QUICTr static_cast<uint64_t>(this->_quic_connection_id), this->_remote_flow_controller->current_offset(), this->_remote_flow_controller->current_limit()); } + +void +QUICNetVConnection::_handle_error(QUICErrorUPtr error) +{ + DebugQUICCon("QUICError: %s (%u), %s (0x%x)", QUICDebugNames::error_class(error->cls), static_cast<unsigned int>(error->cls), + QUICDebugNames::error_code(error->code), static_cast<unsigned int>(error->code)); + if (dynamic_cast<QUICStreamError *>(error.get()) != nullptr) { + // Stream Error + QUICStreamError *serror = static_cast<QUICStreamError *>(error.release()); + serror->stream->reset(QUICStreamErrorUPtr(serror)); + } else { + // Connection Error + QUICConnectionError *cerror = static_cast<QUICConnectionError *>(error.release()); + this->close(QUICConnectionErrorUPtr(cerror)); + } +} diff --git a/iocore/net/quic/QUICCongestionController.cc b/iocore/net/quic/QUICCongestionController.cc index 19939fe..4a0ea79 100644 --- a/iocore/net/quic/QUICCongestionController.cc +++ b/iocore/net/quic/QUICCongestionController.cc @@ -31,10 +31,10 @@ QUICCongestionController::interests() return {QUICFrameType::ACK, QUICFrameType::STREAM}; } -QUICError +QUICErrorUPtr QUICCongestionController::handle_frame(std::shared_ptr<const QUICFrame> frame) { - QUICError error = QUICError(QUICErrorClass::NONE); + QUICErrorUPtr error = QUICErrorUPtr(new QUICNoError()); switch (frame->type()) { case QUICFrameType::STREAM: diff --git a/iocore/net/quic/QUICCongestionController.h b/iocore/net/quic/QUICCongestionController.h index cf8191b..d44b9bf 100644 --- a/iocore/net/quic/QUICCongestionController.h +++ b/iocore/net/quic/QUICCongestionController.h @@ -31,7 +31,7 @@ class QUICCongestionController : public QUICFrameHandler { public: virtual std::vector<QUICFrameType> interests() override; - virtual QUICError handle_frame(std::shared_ptr<const QUICFrame>) override; + virtual QUICErrorUPtr handle_frame(std::shared_ptr<const QUICFrame>) override; private: }; diff --git a/iocore/net/quic/QUICConnection.h b/iocore/net/quic/QUICConnection.h index 6901819..e0bb194 100644 --- a/iocore/net/quic/QUICConnection.h +++ b/iocore/net/quic/QUICConnection.h @@ -55,7 +55,7 @@ public: virtual uint32_t pmtu() = 0; virtual NetVConnectionContext_t direction() = 0; virtual SSLNextProtocolSet *next_protocol_set() = 0; - virtual void close(QUICError error) = 0; + virtual void close(QUICConnectionErrorUPtr error) = 0; virtual QUICPacketNumber largest_received_packet_number() = 0; virtual QUICPacketNumber largest_acked_packet_number() = 0; }; diff --git a/iocore/net/quic/QUICFlowController.cc b/iocore/net/quic/QUICFlowController.cc index e0dcbec..18deeea 100644 --- a/iocore/net/quic/QUICFlowController.cc +++ b/iocore/net/quic/QUICFlowController.cc @@ -40,18 +40,18 @@ QUICFlowController::current_limit() return this->_limit; } -QUICError +QUICErrorUPtr QUICFlowController::update(QUICOffset offset) { if (this->_offset <= offset) { // Assume flow control is not initialized if the limit was 0 if (this->_limit != 0 && offset > this->_limit) { - return QUICError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::FLOW_CONTROL_ERROR); + return QUICErrorUPtr(new QUICConnectionError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::FLOW_CONTROL_ERROR)); } this->_offset = offset; } - return QUICError(QUICErrorClass::NONE); + return QUICErrorUPtr(new QUICNoError()); } void @@ -81,10 +81,10 @@ QUICRemoteFlowController::forward_limit(QUICOffset offset) this->_blocked = false; } -QUICError +QUICErrorUPtr QUICRemoteFlowController::update(QUICOffset offset) { - QUICError error = QUICFlowController::update(offset); + QUICErrorUPtr error = QUICFlowController::update(offset); // Assume flow control is not initialized if the limit was 0 if (this->_limit == 0) { diff --git a/iocore/net/quic/QUICFlowController.h b/iocore/net/quic/QUICFlowController.h index 9badb74..d195728 100644 --- a/iocore/net/quic/QUICFlowController.h +++ b/iocore/net/quic/QUICFlowController.h @@ -33,7 +33,7 @@ class QUICFlowController public: QUICOffset current_offset(); QUICOffset current_limit(); - virtual QUICError update(QUICOffset offset); + virtual QUICErrorUPtr update(QUICOffset offset); virtual void forward_limit(QUICOffset limit); void set_threshold(uint64_t threshold); @@ -51,7 +51,7 @@ class QUICRemoteFlowController : public QUICFlowController { public: QUICRemoteFlowController(uint64_t initial_limit, QUICFrameTransmitter *tx) : QUICFlowController(initial_limit, tx) {} - QUICError update(QUICOffset offset) override; + QUICErrorUPtr update(QUICOffset offset) override; void forward_limit(QUICOffset limit) override; private: diff --git a/iocore/net/quic/QUICFrame.cc b/iocore/net/quic/QUICFrame.cc index 48405bd..0db9d8c 100644 --- a/iocore/net/quic/QUICFrame.cc +++ b/iocore/net/quic/QUICFrame.cc @@ -22,6 +22,7 @@ */ #include "QUICFrame.h" +#include "QUICStream.h" ClassAllocator<QUICStreamFrame> quicStreamFrameAllocator("quicStreamFrameAllocator"); ClassAllocator<QUICAckFrame> quicAckFrameAllocator("quicAckFrameAllocator"); @@ -1333,6 +1334,12 @@ QUICFrameFactory::create_connection_close_frame(QUICErrorCode error_code, uint16 return std::unique_ptr<QUICConnectionCloseFrame, QUICFrameDeleterFunc>(frame, &QUICFrameDeleter::delete_connection_close_frame); } +std::unique_ptr<QUICConnectionCloseFrame, QUICFrameDeleterFunc> +QUICFrameFactory::create_connection_close_frame(QUICConnectionErrorUPtr error) +{ + return QUICFrameFactory::create_connection_close_frame(error->code, strlen(error->msg), error->msg); +} + std::unique_ptr<QUICMaxDataFrame, QUICFrameDeleterFunc> QUICFrameFactory::create_max_data_frame(uint64_t maximum_data) { @@ -1373,6 +1380,12 @@ QUICFrameFactory::create_rst_stream_frame(QUICStreamId stream_id, QUICErrorCode return std::unique_ptr<QUICRstStreamFrame, QUICFrameDeleterFunc>(frame, &QUICFrameDeleter::delete_rst_stream_frame); } +std::unique_ptr<QUICRstStreamFrame, QUICFrameDeleterFunc> +QUICFrameFactory::create_rst_stream_frame(QUICStreamErrorUPtr error) +{ + return QUICFrameFactory::create_rst_stream_frame(error->stream->id(), error->code, error->stream->final_offset()); +} + std::unique_ptr<QUICStopSendingFrame, QUICFrameDeleterFunc> QUICFrameFactory::create_stop_sending_frame(QUICStreamId stream_id, QUICErrorCode error_code) { diff --git a/iocore/net/quic/QUICFrame.h b/iocore/net/quic/QUICFrame.h index ba7841c..15c098c 100644 --- a/iocore/net/quic/QUICFrame.h +++ b/iocore/net/quic/QUICFrame.h @@ -603,6 +603,8 @@ public: */ static std::unique_ptr<QUICConnectionCloseFrame, QUICFrameDeleterFunc> create_connection_close_frame( QUICErrorCode error_code, uint16_t reason_phrase_length, const char *reason_phrase); + static std::unique_ptr<QUICConnectionCloseFrame, QUICFrameDeleterFunc> create_connection_close_frame( + QUICConnectionErrorUPtr error); /* * Creates a MAX_DATA frame. @@ -631,6 +633,7 @@ public: static std::unique_ptr<QUICRstStreamFrame, QUICFrameDeleterFunc> create_rst_stream_frame(QUICStreamId stream_id, QUICErrorCode error_code, QUICOffset final_offset); + static std::unique_ptr<QUICRstStreamFrame, QUICFrameDeleterFunc> create_rst_stream_frame(QUICStreamErrorUPtr error); /* * Creates a STOP_SENDING frame. diff --git a/iocore/net/quic/QUICFrameDispatcher.cc b/iocore/net/quic/QUICFrameDispatcher.cc index 5b87cd1..c23fff1 100644 --- a/iocore/net/quic/QUICFrameDispatcher.cc +++ b/iocore/net/quic/QUICFrameDispatcher.cc @@ -43,13 +43,13 @@ QUICFrameDispatcher::add_handler(QUICFrameHandler *handler) } } -QUICError +QUICErrorUPtr QUICFrameDispatcher::receive_frames(const uint8_t *payload, uint16_t size, bool &should_send_ack) { std::shared_ptr<const QUICFrame> frame(nullptr); - uint16_t cursor = 0; - should_send_ack = false; - QUICError error = QUICError(QUICErrorClass::NONE); + uint16_t cursor = 0; + should_send_ack = false; + QUICErrorUPtr error = QUICErrorUPtr(new QUICNoError()); while (cursor < size) { frame = this->_frame_factory.fast_create(payload + cursor, size - cursor); @@ -72,7 +72,7 @@ QUICFrameDispatcher::receive_frames(const uint8_t *payload, uint16_t size, bool for (auto h : handlers) { error = h->handle_frame(frame); // TODO: is there any case to continue this loop even if error? - if (error.cls != QUICErrorClass::NONE) { + if (error->cls != QUICErrorClass::NONE) { return error; } } diff --git a/iocore/net/quic/QUICFrameDispatcher.h b/iocore/net/quic/QUICFrameDispatcher.h index 0c61f39..397f0d3 100644 --- a/iocore/net/quic/QUICFrameDispatcher.h +++ b/iocore/net/quic/QUICFrameDispatcher.h @@ -33,7 +33,7 @@ public: /* * Returns true if ACK frame should be sent */ - QUICError receive_frames(const uint8_t *payload, uint16_t size, bool &should_send_ack); + QUICErrorUPtr receive_frames(const uint8_t *payload, uint16_t size, bool &should_send_ack); void add_handler(QUICFrameHandler *handler); diff --git a/iocore/net/quic/QUICFrameHandler.h b/iocore/net/quic/QUICFrameHandler.h index 0f2a27f..e857513 100644 --- a/iocore/net/quic/QUICFrameHandler.h +++ b/iocore/net/quic/QUICFrameHandler.h @@ -30,6 +30,6 @@ class QUICFrameHandler { public: virtual ~QUICFrameHandler(){}; - virtual std::vector<QUICFrameType> interests() = 0; - virtual QUICError handle_frame(std::shared_ptr<const QUICFrame> frame) = 0; + virtual std::vector<QUICFrameType> interests() = 0; + virtual QUICErrorUPtr handle_frame(std::shared_ptr<const QUICFrame> frame) = 0; }; diff --git a/iocore/net/quic/QUICHandshake.cc b/iocore/net/quic/QUICHandshake.cc index daa47aa..7c34690 100644 --- a/iocore/net/quic/QUICHandshake.cc +++ b/iocore/net/quic/QUICHandshake.cc @@ -72,13 +72,13 @@ QUICHandshake::~QUICHandshake() SSL_free(this->_ssl); } -QUICError +QUICErrorUPtr QUICHandshake::start(const QUICPacket *initial_packet, QUICPacketFactory *packet_factory) { // Negotiate version if (this->_version_negotiator->status() == QUICVersionNegotiationStatus::NOT_NEGOTIATED) { if (initial_packet->type() != QUICPacketType::CLIENT_INITIAL) { - return QUICError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::INTERNAL_ERROR); + return QUICErrorUPtr(new QUICConnectionError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::PROTOCOL_VIOLATION)); } if (initial_packet->version()) { if (this->_version_negotiator->negotiate(initial_packet) == QUICVersionNegotiationStatus::NEGOTIATED) { @@ -90,10 +90,10 @@ QUICHandshake::start(const QUICPacket *initial_packet, QUICPacketFactory *packet Debug(tag, "Version negotiation failed: %x", initial_packet->version()); } } else { - return QUICError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::INTERNAL_ERROR); + return QUICErrorUPtr(new QUICConnectionError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::PROTOCOL_VIOLATION)); } } - return QUICError(QUICErrorClass::NONE); + return QUICErrorUPtr(new QUICNoError()); } bool @@ -136,7 +136,8 @@ QUICHandshake::set_transport_parameters(std::shared_ptr<QUICTransportParameters> if (tp_in_ch) { // Version revalidation if (this->_version_negotiator->revalidate(tp_in_ch) != QUICVersionNegotiationStatus::REVALIDATED) { - this->_client_qc->close({QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::VERSION_NEGOTIATION_ERROR}); + this->_client_qc->close( + QUICConnectionErrorUPtr(new QUICConnectionError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::VERSION_NEGOTIATION_ERROR))); Debug(tag, "Enter state_closed"); SET_HANDLER(&QUICHandshake::state_closed); return; @@ -168,7 +169,7 @@ QUICHandshake::remote_transport_parameters() int QUICHandshake::state_read_client_hello(int event, Event *data) { - QUICError error; + QUICErrorUPtr error; switch (event) { case VC_EVENT_READ_READY: case VC_EVENT_READ_COMPLETE: { @@ -180,8 +181,13 @@ QUICHandshake::state_read_client_hello(int event, Event *data) break; } - if (error.cls != QUICErrorClass::NONE) { - this->_client_qc->close(error); + if (error->cls != QUICErrorClass::NONE) { + if (dynamic_cast<QUICConnectionError *>(error.get()) != nullptr) { + this->_client_qc->close(QUICConnectionErrorUPtr(static_cast<QUICConnectionError *>(error.release()))); + } else { + this->_client_qc->close( + QUICConnectionErrorUPtr(new QUICConnectionError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::PROTOCOL_VIOLATION))); + } Debug(tag, "Enter state_closed"); SET_HANDLER(&QUICHandshake::state_closed); } @@ -192,7 +198,7 @@ QUICHandshake::state_read_client_hello(int event, Event *data) int QUICHandshake::state_read_client_finished(int event, Event *data) { - QUICError error; + QUICErrorUPtr error = QUICErrorUPtr(new QUICNoError()); switch (event) { case VC_EVENT_READ_READY: case VC_EVENT_READ_COMPLETE: { @@ -204,8 +210,13 @@ QUICHandshake::state_read_client_finished(int event, Event *data) break; } - if (error.cls != QUICErrorClass::NONE) { - this->_client_qc->close(error); + if (error->cls != QUICErrorClass::NONE) { + if (dynamic_cast<QUICConnectionError *>(error.get()) != nullptr) { + this->_client_qc->close(QUICConnectionErrorUPtr(static_cast<QUICConnectionError *>(error.release()))); + } else { + this->_client_qc->close( + QUICConnectionErrorUPtr(new QUICConnectionError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::PROTOCOL_VIOLATION))); + } Debug(tag, "Enter state_closed"); SET_HANDLER(&QUICHandshake::state_closed); } @@ -267,7 +278,7 @@ QUICHandshake::_load_local_transport_parameters() this->_local_transport_parameters = std::unique_ptr<QUICTransportParameters>(tp); } -QUICError +QUICErrorUPtr QUICHandshake::_process_client_hello() { QUICStreamIO *stream_io = this->_find_stream_io(STREAM_ID_FOR_HANDSHAKE); @@ -279,7 +290,7 @@ QUICHandshake::_process_client_hello() if (msg_len <= 0) { Debug(tag, "No message"); - return QUICError(QUICErrorClass::NONE); + return QUICErrorUPtr(new QUICNoError()); } // ----- DEBUG -----> @@ -305,13 +316,13 @@ QUICHandshake::_process_client_hello() stream_io->write_reenable(); stream_io->read_reenable(); - return QUICError(QUICErrorClass::NONE); + return QUICErrorUPtr(new QUICNoError()); } else { - return QUICError(QUICErrorClass::CRYPTOGRAPHIC, QUICErrorCode::TLS_HANDSHAKE_FAILED); + return QUICErrorUPtr(new QUICConnectionError(QUICErrorClass::CRYPTOGRAPHIC, QUICErrorCode::TLS_HANDSHAKE_FAILED)); } } -QUICError +QUICErrorUPtr QUICHandshake::_process_client_finished() { QUICStreamIO *stream_io = this->_find_stream_io(STREAM_ID_FOR_HANDSHAKE); @@ -323,7 +334,7 @@ QUICHandshake::_process_client_finished() if (msg_len <= 0) { Debug(tag, "No message"); - return QUICError(QUICErrorClass::NONE); + return QUICErrorUPtr(new QUICNoError()); } // ----- DEBUG -----> @@ -353,13 +364,13 @@ QUICHandshake::_process_client_finished() stream_io->write_reenable(); stream_io->read_reenable(); - return QUICError(QUICErrorClass::NONE); + return QUICErrorUPtr(new QUICNoError()); } else { - return QUICError(QUICErrorClass::CRYPTOGRAPHIC, QUICErrorCode::TLS_HANDSHAKE_FAILED); + return QUICErrorUPtr(new QUICConnectionError(QUICErrorClass::CRYPTOGRAPHIC, QUICErrorCode::TLS_HANDSHAKE_FAILED)); } } -QUICError +QUICErrorUPtr QUICHandshake::_process_handshake_complete() { QUICCrypto *crypto = this->_crypto; @@ -371,5 +382,5 @@ QUICHandshake::_process_handshake_complete() Debug(tag, "Failed to export Keying Materials"); } - return QUICError(QUICErrorClass::NONE); + return QUICErrorUPtr(new QUICNoError()); } diff --git a/iocore/net/quic/QUICHandshake.h b/iocore/net/quic/QUICHandshake.h index 5d0060a..d74344f 100644 --- a/iocore/net/quic/QUICHandshake.h +++ b/iocore/net/quic/QUICHandshake.h @@ -53,7 +53,7 @@ public: QUICHandshake(QUICConnection *qc, SSL_CTX *ssl_ctx, QUICStatelessToken token); ~QUICHandshake(); - QUICError start(const QUICPacket *initial_packet, QUICPacketFactory *packet_factory); + QUICErrorUPtr start(const QUICPacket *initial_packet, QUICPacketFactory *packet_factory); // States int state_read_client_hello(int event, Event *data); @@ -84,9 +84,9 @@ private: void _load_local_transport_parameters(); - QUICError _process_client_hello(); - QUICError _process_client_finished(); - QUICError _process_handshake_complete(); + QUICErrorUPtr _process_client_hello(); + QUICErrorUPtr _process_client_finished(); + QUICErrorUPtr _process_handshake_complete(); QUICStatelessToken _token; }; diff --git a/iocore/net/quic/QUICLossDetector.cc b/iocore/net/quic/QUICLossDetector.cc index 1662fa7..33d923d 100644 --- a/iocore/net/quic/QUICLossDetector.cc +++ b/iocore/net/quic/QUICLossDetector.cc @@ -81,10 +81,10 @@ QUICLossDetector::interests() return {QUICFrameType::ACK}; } -QUICError +QUICErrorUPtr QUICLossDetector::handle_frame(std::shared_ptr<const QUICFrame> frame) { - QUICError error = QUICError(QUICErrorClass::NONE); + QUICErrorUPtr error = QUICErrorUPtr(new QUICNoError()); switch (frame->type()) { case QUICFrameType::ACK: diff --git a/iocore/net/quic/QUICLossDetector.h b/iocore/net/quic/QUICLossDetector.h index 5b52b55..7313694 100644 --- a/iocore/net/quic/QUICLossDetector.h +++ b/iocore/net/quic/QUICLossDetector.h @@ -46,7 +46,7 @@ public: int event_handler(int event, Event *edata); std::vector<QUICFrameType> interests() override; - virtual QUICError handle_frame(std::shared_ptr<const QUICFrame>) override; + virtual QUICErrorUPtr handle_frame(std::shared_ptr<const QUICFrame>) override; void on_packet_sent(QUICPacketUPtr packet); QUICPacketNumber largest_acked_packet_number(); diff --git a/iocore/net/quic/QUICStream.cc b/iocore/net/quic/QUICStream.cc index 1a9cff2..dd41ff3 100644 --- a/iocore/net/quic/QUICStream.cc +++ b/iocore/net/quic/QUICStream.cc @@ -70,11 +70,18 @@ QUICStream::id() return this->_id; } +QUICOffset +QUICStream::final_offset() +{ + // TODO Return final offset + return 0; +} + int QUICStream::main_event_handler(int event, void *data) { DebugQUICStream("%s", QUICDebugNames::vc_event(event)); - QUICError error; + QUICErrorUPtr error = std::unique_ptr<QUICError>(new QUICNoError()); switch (event) { case VC_EVENT_READ_READY: @@ -104,10 +111,17 @@ QUICStream::main_event_handler(int event, void *data) ink_assert(false); } - if (error.cls != QUICErrorClass::NONE) { - // TODO Send error if needed - DebugQUICStream("QUICError: %s (%u), %s (0x%x)", QUICDebugNames::error_class(error.cls), static_cast<unsigned int>(error.cls), - QUICDebugNames::error_code(error.code), static_cast<unsigned int>(error.code)); + if (error->cls != QUICErrorClass::NONE) { + DebugQUICStream("QUICError: %s (%u), %s (0x%x)", QUICDebugNames::error_class(error->cls), static_cast<unsigned int>(error->cls), + QUICDebugNames::error_code(error->code), static_cast<unsigned int>(error->code)); + if (dynamic_cast<QUICStreamError *>(error.get()) != nullptr) { + // Stream Error + QUICStreamErrorUPtr serror = QUICStreamErrorUPtr(static_cast<QUICStreamError *>(error.get())); + this->reset(std::move(serror)); + } else { + // Connection Error + // TODO Close connection (Does this really happen?) + } } return EVENT_CONT; @@ -281,7 +295,7 @@ QUICStream::_reorder_data() * If the reordering or writting operation is heavy, split out them to read function, * which is called by application via do_io_read() or reenable(). */ -QUICError +QUICErrorUPtr QUICStream::recv(const std::shared_ptr<const QUICStreamFrame> frame) { ink_assert(_id == frame->stream_id()); @@ -289,23 +303,22 @@ QUICStream::recv(const std::shared_ptr<const QUICStreamFrame> frame) // Check stream state - Do this first before accept the frame if (!this->_state.is_allowed_to_receive(*frame)) { - this->reset(); - return QUICError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::INTERNAL_ERROR); + return QUICErrorUPtr(new QUICStreamError(this, QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::STREAM_STATE_ERROR)); } // Flow Control - Even if it's allowed to receive on the state, it may exceed the limit - QUICError error = this->_local_flow_controller->update(frame->offset() + frame->data_length()); + QUICErrorUPtr error = this->_local_flow_controller->update(frame->offset() + frame->data_length()); Debug("quic_flow_ctrl", "Stream [%" PRIx32 "] [%s] [LOCAL] %" PRIu64 "/%" PRIu64, this->_id, QUICDebugNames::stream_state(this->_state), this->_local_flow_controller->current_offset(), this->_local_flow_controller->current_limit()); - if (error.cls != QUICErrorClass::NONE) { + if (error->cls != QUICErrorClass::NONE) { return error; } // Reordering - Some frames may be delayed or be dropped if (this->_recv_offset > frame->offset()) { // Do nothing. Just ignore STREAM frame. - return QUICError(QUICErrorClass::NONE); + return QUICErrorUPtr(new QUICNoError()); } else if (this->_recv_offset == frame->offset()) { this->_write_to_read_vio(frame); this->_reorder_data(); @@ -315,10 +328,10 @@ QUICStream::recv(const std::shared_ptr<const QUICStreamFrame> frame) this->_received_stream_frame_buffer.insert(std::make_pair(frame->offset(), frame)); } - return QUICError(QUICErrorClass::NONE); + return QUICErrorUPtr(new QUICNoError()); } -QUICError +QUICErrorUPtr QUICStream::recv(const std::shared_ptr<const QUICMaxStreamDataFrame> frame) { this->_remote_flow_controller->forward_limit(frame->maximum_stream_data()); @@ -328,25 +341,26 @@ QUICStream::recv(const std::shared_ptr<const QUICMaxStreamDataFrame> frame) this->reenable(&this->_write_vio); - return QUICError(QUICErrorClass::NONE); + return QUICErrorUPtr(new QUICNoError()); } -QUICError +QUICErrorUPtr QUICStream::recv(const std::shared_ptr<const QUICStreamBlockedFrame> frame) { // STREAM_BLOCKED frames are for debugging. Nothing to do here. - return QUICError(QUICErrorClass::NONE); + return QUICErrorUPtr(new QUICNoError()); } /** * @brief Send STREAM DATA from _response_buffer */ -QUICError +QUICErrorUPtr QUICStream::_send() { SCOPED_MUTEX_LOCK(lock, this->_write_vio.mutex, this_ethread()); - QUICError error; + QUICErrorUPtr error = std::unique_ptr<QUICError>(new QUICNoError()); + IOBufferReader *reader = this->_write_vio.get_reader(); int64_t bytes_avail = reader->read_avail(); int64_t total_len = 0; @@ -366,11 +380,11 @@ QUICStream::_send() } } - QUICError error = this->_remote_flow_controller->update(this->_send_offset + len); + error = this->_remote_flow_controller->update(this->_send_offset + len); Debug("quic_flow_ctrl", "Stream [%" PRIx32 "] [%s] [REMOTE] %" PRIu64 "/%" PRIu64, this->_id, QUICDebugNames::stream_state(this->_state), this->_remote_flow_controller->current_offset(), this->_remote_flow_controller->current_limit()); - if (error.cls != QUICErrorClass::NONE) { + if (error->cls != QUICErrorClass::NONE) { break; } @@ -394,9 +408,9 @@ QUICStream::_send() } void -QUICStream::reset() +QUICStream::reset(QUICStreamErrorUPtr error) { - // TODO: Create a RST_STREAM frame and pass it to Stream Manager + this->_tx->transmit_frame(QUICFrameFactory::create_rst_stream_frame(std::move(error))); } void diff --git a/iocore/net/quic/QUICStream.h b/iocore/net/quic/QUICStream.h index d8b476c..bdb78ae 100644 --- a/iocore/net/quic/QUICStream.h +++ b/iocore/net/quic/QUICStream.h @@ -52,6 +52,7 @@ public: int main_event_handler(int event, void *data); QUICStreamId id(); + QUICOffset final_offset(); // Implement VConnection interface. VIO *do_io_read(Continuation *c, int64_t nbytes = INT64_MAX, MIOBuffer *buf = nullptr) override; @@ -60,11 +61,11 @@ public: void do_io_shutdown(ShutdownHowTo_t howto) override; void reenable(VIO *vio) override; - QUICError recv(const std::shared_ptr<const QUICStreamFrame> frame); - QUICError recv(const std::shared_ptr<const QUICMaxStreamDataFrame> frame); - QUICError recv(const std::shared_ptr<const QUICStreamBlockedFrame> frame); + QUICErrorUPtr recv(const std::shared_ptr<const QUICStreamFrame> frame); + QUICErrorUPtr recv(const std::shared_ptr<const QUICMaxStreamDataFrame> frame); + QUICErrorUPtr recv(const std::shared_ptr<const QUICStreamBlockedFrame> frame); - void reset(); + void reset(QUICStreamErrorUPtr error); void shutdown(); size_t nbytes_to_read(); @@ -77,7 +78,7 @@ public: private: QUICStreamState _state; - QUICError _send(); + QUICErrorUPtr _send(); void _write_to_read_vio(const std::shared_ptr<const QUICStreamFrame> &); void _reorder_data(); diff --git a/iocore/net/quic/QUICStreamManager.cc b/iocore/net/quic/QUICStreamManager.cc index ba322ff..2832328 100644 --- a/iocore/net/quic/QUICStreamManager.cc +++ b/iocore/net/quic/QUICStreamManager.cc @@ -85,10 +85,10 @@ QUICStreamManager::set_max_stream_id(QUICStreamId id) } } -QUICError +QUICErrorUPtr QUICStreamManager::handle_frame(std::shared_ptr<const QUICFrame> frame) { - QUICError error = QUICError(QUICErrorClass::NONE); + QUICErrorUPtr error = QUICErrorUPtr(new QUICNoError()); switch (frame->type()) { case QUICFrameType::MAX_STREAM_DATA: @@ -116,34 +116,34 @@ QUICStreamManager::handle_frame(std::shared_ptr<const QUICFrame> frame) return error; } -QUICError +QUICErrorUPtr QUICStreamManager::_handle_frame(const std::shared_ptr<const QUICMaxStreamDataFrame> &frame) { QUICStream *stream = this->_find_or_create_stream(frame->stream_id()); if (stream) { return stream->recv(frame); } else { - return QUICError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::STREAM_ID_ERROR); + return QUICErrorUPtr(new QUICConnectionError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::STREAM_ID_ERROR)); } } -QUICError +QUICErrorUPtr QUICStreamManager::_handle_frame(const std::shared_ptr<const QUICStreamBlockedFrame> &frame) { QUICStream *stream = this->_find_or_create_stream(frame->stream_id()); if (stream) { return stream->recv(frame); } else { - return QUICError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::STREAM_ID_ERROR); + return QUICErrorUPtr(new QUICConnectionError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::STREAM_ID_ERROR)); } } -QUICError +QUICErrorUPtr QUICStreamManager::_handle_frame(const std::shared_ptr<const QUICStreamFrame> &frame) { QUICStream *stream = this->_find_or_create_stream(frame->stream_id()); if (!stream) { - return QUICError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::STREAM_ID_ERROR); + return QUICErrorUPtr(new QUICConnectionError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::STREAM_ID_ERROR)); } QUICApplication *application = this->_app_map->get(frame->stream_id()); @@ -153,7 +153,7 @@ QUICStreamManager::_handle_frame(const std::shared_ptr<const QUICStreamFrame> &f } size_t nbytes_to_read = stream->nbytes_to_read(); - QUICError error = stream->recv(frame); + QUICErrorUPtr error = stream->recv(frame); // Prevent trigger read events multiple times if (nbytes_to_read == 0) { this_ethread()->schedule_imm(application, VC_EVENT_READ_READY, stream); @@ -162,23 +162,23 @@ QUICStreamManager::_handle_frame(const std::shared_ptr<const QUICStreamFrame> &f return error; } -QUICError +QUICErrorUPtr QUICStreamManager::_handle_frame(const std::shared_ptr<const QUICRstStreamFrame> &frame) { QUICStream *stream = this->_find_or_create_stream(frame->stream_id()); if (stream) { // TODO Reset the stream - return QUICError(QUICErrorClass::NONE); + return QUICErrorUPtr(new QUICNoError()); } else { - return QUICError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::STREAM_ID_ERROR); + return QUICErrorUPtr(new QUICConnectionError(QUICErrorClass::QUIC_TRANSPORT, QUICErrorCode::STREAM_ID_ERROR)); } } -QUICError +QUICErrorUPtr QUICStreamManager::_handle_frame(const std::shared_ptr<const QUICMaxStreamIdFrame> &frame) { this->_remote_maximum_stream_id = frame->maximum_stream_id(); - return QUICError(QUICErrorClass::NONE); + return QUICErrorUPtr(new QUICNoError()); } QUICStream * diff --git a/iocore/net/quic/QUICStreamManager.h b/iocore/net/quic/QUICStreamManager.h index 2f664ca..b6ad75f 100644 --- a/iocore/net/quic/QUICStreamManager.h +++ b/iocore/net/quic/QUICStreamManager.h @@ -53,16 +53,16 @@ public: // QUICFrameHandler virtual std::vector<QUICFrameType> interests() override; - virtual QUICError handle_frame(std::shared_ptr<const QUICFrame>) override; + virtual QUICErrorUPtr handle_frame(std::shared_ptr<const QUICFrame>) override; private: QUICStream *_find_or_create_stream(QUICStreamId stream_id); QUICStream *_find_stream(QUICStreamId id); - QUICError _handle_frame(const std::shared_ptr<const QUICStreamFrame> &); - QUICError _handle_frame(const std::shared_ptr<const QUICRstStreamFrame> &); - QUICError _handle_frame(const std::shared_ptr<const QUICMaxStreamDataFrame> &); - QUICError _handle_frame(const std::shared_ptr<const QUICStreamBlockedFrame> &); - QUICError _handle_frame(const std::shared_ptr<const QUICMaxStreamIdFrame> &); + QUICErrorUPtr _handle_frame(const std::shared_ptr<const QUICStreamFrame> &); + QUICErrorUPtr _handle_frame(const std::shared_ptr<const QUICRstStreamFrame> &); + QUICErrorUPtr _handle_frame(const std::shared_ptr<const QUICMaxStreamDataFrame> &); + QUICErrorUPtr _handle_frame(const std::shared_ptr<const QUICStreamBlockedFrame> &); + QUICErrorUPtr _handle_frame(const std::shared_ptr<const QUICMaxStreamIdFrame> &); QUICFrameTransmitter *_tx = nullptr; QUICApplicationMap *_app_map = nullptr; diff --git a/iocore/net/quic/QUICTypes.h b/iocore/net/quic/QUICTypes.h index f3773c3..c2673d9 100644 --- a/iocore/net/quic/QUICTypes.h +++ b/iocore/net/quic/QUICTypes.h @@ -146,20 +146,47 @@ enum class QUICErrorCode : uint32_t { // TODO Add error codes }; -struct QUICError { - QUICError(const QUICErrorClass error_class = QUICErrorClass::NONE, const QUICErrorCode error_code = QUICErrorCode::NO_ERROR, - const char *err_msg = nullptr) - { - cls = error_class; - code = error_code; - msg = err_msg; - }; - +class QUICError +{ +public: + virtual ~QUICError() {} QUICErrorClass cls; QUICErrorCode code; const char *msg; + +protected: + QUICError(const QUICErrorClass error_class = QUICErrorClass::NONE, const QUICErrorCode error_code = QUICErrorCode::NO_ERROR, + const char *error_msg = nullptr) + : cls(error_class), code(error_code), msg(error_msg){}; +}; + +class QUICNoError : public QUICError +{ +public: + QUICNoError() : QUICError() {} +}; + +class QUICConnectionError : public QUICError +{ +public: + QUICConnectionError(const QUICErrorClass error_class, const QUICErrorCode error_code, const char *error_msg = nullptr) + : QUICError(error_class, error_code, error_msg){}; }; +class QUICStream; + +class QUICStreamError : public QUICError +{ +public: + QUICStreamError(QUICStream *s, const QUICErrorClass error_class, const QUICErrorCode error_code, const char *error_msg = nullptr) + : QUICError(error_class, error_code, error_msg), stream(s){}; + QUICStream *stream; +}; + +using QUICErrorUPtr = std::unique_ptr<QUICError>; +using QUICConnectionErrorUPtr = std::unique_ptr<QUICConnectionError>; +using QUICStreamErrorUPtr = std::unique_ptr<QUICStreamError>; + class QUICStatelessToken { public: -- To stop receiving notification emails like this one, please contact ['"commits@trafficserver.apache.org" <commits@trafficserver.apache.org>'].