Skip to content

Commit

Permalink
Support HANDSHAKE_DONE frame
Browse files Browse the repository at this point in the history
  • Loading branch information
maskit committed Jan 23, 2020
1 parent 137451f commit 3e191ce
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 8 deletions.
2 changes: 1 addition & 1 deletion iocore/net/P_QUICNetVConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
#include "quic/QUICPacketFactory.h"
#include "quic/QUICFrame.h"
#include "quic/QUICFrameDispatcher.h"
#include "quic/QUICHandshake.h"
#include "quic/QUICApplication.h"
#include "quic/QUICStream.h"
#include "quic/QUICHandshakeProtocol.h"
Expand Down Expand Up @@ -81,6 +80,7 @@ static constexpr size_t MAX_CIDS_SIZE = 8 + 1 + 8 + 1;

class QUICPacketHandler;
class QUICLossDetector;
class QUICHandshake;

class SSLNextProtocolSet;

Expand Down
1 change: 1 addition & 0 deletions iocore/net/QUICNetVConnection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "QUICGlobals.h"
#include "QUICDebugNames.h"
#include "QUICEvents.h"
#include "QUICHandshake.h"
#include "QUICConfig.h"
#include "QUICIntUtil.h"

Expand Down
2 changes: 2 additions & 0 deletions iocore/net/quic/QUICDebugNames.cc
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ QUICDebugNames::frame_type(QUICFrameType type)
return "RETIRE_CONNECTION_ID";
case QUICFrameType::NEW_TOKEN:
return "NEW_TOKEN";
case QUICFrameType::HANDSHAKE_DONE:
return "HANDSHAKE_DONE";
case QUICFrameType::UNKNOWN:
default:
return "UNKNOWN";
Expand Down
65 changes: 64 additions & 1 deletion iocore/net/quic/QUICFrame.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ QUICFrame::type(const uint8_t *buf)
buf[0] < static_cast<uint8_t>(QUICFrameType::NEW_CONNECTION_ID)) {
return QUICFrameType::STREAMS_BLOCKED;
} else if (static_cast<uint8_t>(QUICFrameType::CONNECTION_CLOSE) <= buf[0] &&
buf[0] < static_cast<uint8_t>(QUICFrameType::UNKNOWN)) {
buf[0] < static_cast<uint8_t>(QUICFrameType::HANDSHAKE_DONE)) {
return QUICFrameType::CONNECTION_CLOSE;
} else {
return static_cast<QUICFrameType>(buf[0]);
Expand Down Expand Up @@ -2723,6 +2723,59 @@ QUICRetireConnectionIdFrame::seq_num() const
return this->_seq_num;
}

//
// HANDSHAKE_DONE frame
//

QUICHandshakeDoneFrame::QUICHandshakeDoneFrame(const uint8_t *buf, size_t len, const QUICPacketR *packet)
: QUICFrame(0, nullptr, packet)
{
this->parse(buf, len, packet);
}

void
QUICHandshakeDoneFrame::parse(const uint8_t *buf, size_t len, const QUICPacketR *packet)
{
this->_reset();
this->_packet = packet;
this->_valid = true;
this->_size = 1;
}

QUICFrameType
QUICHandshakeDoneFrame::type() const
{
return QUICFrameType::HANDSHAKE_DONE;
}

size_t
QUICHandshakeDoneFrame::size() const
{
return 1;
}

Ptr<IOBufferBlock>
QUICHandshakeDoneFrame::to_io_buffer_block(size_t limit) const
{
Ptr<IOBufferBlock> block;
size_t n = 0;

if (limit < this->size()) {
return block;
}

block = make_ptr<IOBufferBlock>(new_IOBufferBlock());
block->alloc(iobuffer_size_to_index(this->size()));
uint8_t *block_start = reinterpret_cast<uint8_t *>(block->start());

// Type
block_start[0] = static_cast<uint8_t>(QUICFrameType::HANDSHAKE_DONE);
n += 1;

block->fill(n);
return block;
}

//
// UNKNOWN
//
Expand Down Expand Up @@ -2823,6 +2876,9 @@ QUICFrameFactory::create(uint8_t *buf, const uint8_t *src, size_t len, const QUI
case QUICFrameType::RETIRE_CONNECTION_ID:
new (buf) QUICRetireConnectionIdFrame(src, len, packet);
return reinterpret_cast<QUICFrame *>(buf);
case QUICFrameType::HANDSHAKE_DONE:
new (buf) QUICHandshakeDoneFrame(src, len, packet);
return reinterpret_cast<QUICFrame *>(buf);
default:
// Unknown frame
Debug("quic_frame_factory", "Unknown frame type %x", src[0]);
Expand Down Expand Up @@ -3025,6 +3081,13 @@ QUICFrameFactory::create_retire_connection_id_frame(uint8_t *buf, uint64_t seq_n
return reinterpret_cast<QUICRetireConnectionIdFrame *>(buf);
}

QUICHandshakeDoneFrame *
QUICFrameFactory::create_handshake_done_frame(uint8_t *buf, QUICFrameId id, QUICFrameGenerator *owner)
{
new (buf) QUICHandshakeDoneFrame(id, owner);
return reinterpret_cast<QUICHandshakeDoneFrame *>(buf);
}

QUICFrameId
QUICFrameInfo::id() const
{
Expand Down
20 changes: 20 additions & 0 deletions iocore/net/quic/QUICFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,21 @@ class QUICRetireConnectionIdFrame : public QUICFrame
uint64_t _seq_num = 0;
};

//
// HANDSHAKE_DONE
//

class QUICHandshakeDoneFrame : public QUICFrame
{
public:
QUICHandshakeDoneFrame(QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr) : QUICFrame(id, owner) {}
QUICHandshakeDoneFrame(const uint8_t *buf, size_t len, const QUICPacketR *packet = nullptr);
virtual QUICFrameType type() const override;
virtual size_t size() const override;
virtual Ptr<IOBufferBlock> to_io_buffer_block(size_t limit) const override;
virtual void parse(const uint8_t *buf, size_t len, const QUICPacketR *packet) override;
};

//
// UNKNOWN
//
Expand Down Expand Up @@ -871,6 +886,11 @@ class QUICFrameFactory
*/
static QUICPaddingFrame *create_padding_frame(uint8_t *buf, size_t size, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr);

/*
* Creates a HANDSHAKE_DONE frame
*/
static QUICHandshakeDoneFrame *create_handshake_done_frame(uint8_t *buf, QUICFrameId id = 0, QUICFrameGenerator *owner = nullptr);

private:
// FIXME Actual number of frame types is several but some of the values are not sequential.
QUICFrame *_reusable_frames[256] = {nullptr};
Expand Down
49 changes: 45 additions & 4 deletions iocore/net/quic/QUICHandshake.cc
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,16 @@ QUICHandshake::is_completed() const
return this->_hs_protocol->is_handshake_finished();
}

bool
QUICHandshake::is_confirmed() const
{
if (this->_qc->direction() == NET_VCONNECTION_IN) {
return this->is_completed();
} else {
return this->_is_handshake_done_received;
}
}

bool
QUICHandshake::is_stateless_retry_enabled() const
{
Expand Down Expand Up @@ -299,6 +309,7 @@ QUICHandshake::interests()
{
return {
QUICFrameType::CRYPTO,
QUICFrameType::HANDSHAKE_DONE,
};
}

Expand All @@ -309,8 +320,15 @@ QUICHandshake::handle_frame(QUICEncryptionLevel level, const QUICFrame &frame)
switch (frame.type()) {
case QUICFrameType::CRYPTO:
error = this->_crypto_streams[static_cast<int>(level)].recv(static_cast<const QUICCryptoFrame &>(frame));
if (error != nullptr) {
return error;
if (error == nullptr) {
error = this->do_handshake();
}
break;
case QUICFrameType::HANDSHAKE_DONE:
if (this->_qc->direction() == NET_VCONNECTION_IN) {
error = std::make_unique<QUICConnectionError>(QUICTransErrorCode::PROTOCOL_VIOLATION);
} else {
this->_is_handshake_done_received = true;
}
break;
default:
Expand All @@ -319,7 +337,7 @@ QUICHandshake::handle_frame(QUICEncryptionLevel level, const QUICFrame &frame)
break;
}

return this->do_handshake();
return error;
}

bool
Expand All @@ -329,7 +347,8 @@ QUICHandshake::will_generate_frame(QUICEncryptionLevel level, size_t current_pac
return false;
}

return this->_crypto_streams[static_cast<int>(level)].will_generate_frame(level, current_packet_size, ack_eliciting, seq_num);
return (this->_qc->direction() == NET_VCONNECTION_IN && !this->_is_handshake_done_sent) ||
this->_crypto_streams[static_cast<int>(level)].will_generate_frame(level, current_packet_size, ack_eliciting, seq_num);
}

QUICFrame *
Expand All @@ -339,8 +358,23 @@ QUICHandshake::generate_frame(uint8_t *buf, QUICEncryptionLevel level, uint64_t
QUICFrame *frame = nullptr;

if (this->_is_level_matched(level)) {
// CRYPTO
frame = this->_crypto_streams[static_cast<int>(level)].generate_frame(buf, level, connection_credit, maximum_frame_size,
current_packet_size, seq_num);
if (frame) {
return frame;
}
}

if (level == QUICEncryptionLevel::ONE_RTT) {
// HANDSHAKE_DONE
if (!this->_is_handshake_done_sent && this->is_completed()) {
frame = QUICFrameFactory::create_handshake_done_frame(buf, this->_issue_frame_id(), this);
}
if (frame) {
this->_is_handshake_done_sent = true;
return frame;
}
}

return frame;
Expand Down Expand Up @@ -525,3 +559,10 @@ QUICHandshake::_is_level_matched(QUICEncryptionLevel level)
{
return true;
}

void
QUICHandshake::_on_frame_lost(QUICFrameInformationUPtr &info)
{
ink_assert(info->type == QUICFrameType::HANDSHAKE_DONE);
this->_is_handshake_done_sent = false;
}
7 changes: 7 additions & 0 deletions iocore/net/quic/QUICHandshake.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class QUICHandshake : public QUICFrameHandler, public QUICFrameGenerator

bool is_version_negotiated() const;
bool is_completed() const;
bool is_confirmed() const;
bool is_stateless_retry_enabled() const;
bool has_remote_tp() const;

Expand All @@ -103,4 +104,10 @@ class QUICHandshake : public QUICFrameHandler, public QUICFrameGenerator
std::shared_ptr<const QUICTransportParameters> _remote_transport_parameters = nullptr;

void _abort_handshake(QUICTransErrorCode code);

bool _is_handshake_done_sent = false;
bool _is_handshake_done_received = false;

// QUICFrameGenerator
void _on_frame_lost(QUICFrameInformationUPtr &info) override;
};
1 change: 0 additions & 1 deletion iocore/net/quic/QUICTransportParameters.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
#include "QUICIntUtil.h"
#include "QUICTransportParameters.h"
#include "QUICConnection.h"
#include "QUICHandshake.h"
#include "QUICDebugNames.h"
#include "QUICTLS.h"
#include "QUICTypes.h"
Expand Down
3 changes: 2 additions & 1 deletion iocore/net/quic/QUICTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ enum class QUICFrameType : uint8_t {
PATH_CHALLENGE,
PATH_RESPONSE,
CONNECTION_CLOSE, // 0x1c - 0x1d
UNKNOWN = 0x1e,
HANDSHAKE_DONE = 0x1e,
UNKNOWN = 0x1f,
};

enum class QUICVersionNegotiationStatus {
Expand Down

0 comments on commit 3e191ce

Please sign in to comment.