blob: 9cb581d47b7fd48a970181e6663c7bdcbe4f1c36 [file] [log] [blame]
// Copyright (c) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cstdint>
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_endpoint.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_session.h"
#include "net/third_party/quiche/src/quic/quartc/quartc_stream.h"
namespace quic {
class QuartcMultiplexer;
// A single, multiplexed send channel within a Quartc session. A send channel
// wraps send-side operations with an outgoing multiplex id.
class QuartcSendChannel {
class Delegate {
virtual ~Delegate() = default;
// Called when a message with |datagram_id| is sent by this channel.
virtual void OnMessageSent(int64_t datagram_id) = 0;
// Called when a message sent on this channel with |datagram_id| is acked.
// |receive_timestamp| indicates when the peer received this message,
// according to the peer's clock.
virtual void OnMessageAcked(int64_t datagram_id,
QuicTime receive_timestamp) = 0;
// Called when a message sent on this channel with |datagram_id| is lost.
virtual void OnMessageLost(int64_t datagram_id) = 0;
QuartcSendChannel(QuartcMultiplexer* multiplexer,
uint64_t id,
QuicBufferAllocator* allocator,
Delegate* delegate);
virtual ~QuartcSendChannel() = default;
// Creates a new, outgoing stream on this channel.
// Automatically writes the channel id to the start of the stream. The caller
// SHOULD create a |ScopedPacketFlusher| before calling this function to
// prevent the channel id from being sent by itself.
QuartcStream* CreateOutgoingBidirectionalStream();
// Writes |message| to the session. Prepends the channel's send id before any
// following message data.
bool SendOrQueueMessage(QuicMemSliceSpan message, int64_t datagram_id);
// Gets the current largest message payload for this channel. Returns the
// largest payload size supported by the session minus overhead required to
// encode this channel's send id.
QuicPacketLength GetCurrentLargestMessagePayload() const;
// The following are called by the multiplexer to deliver message
// notifications. The |datagram_id| passed to these is unique per-message,
// and must be translated back to the sender's chosen datagram_id.
void OnMessageSent(int64_t datagram_id);
void OnMessageAcked(int64_t datagram_id, QuicTime receive_timestamp);
void OnMessageLost(int64_t datagram_id);
void OnSessionCreated(QuartcSession* session);
// Creates a mem slice containing a varint-62 encoded channel id.
QuicMemSlice EncodeChannelId();
QuartcMultiplexer* const multiplexer_;
const uint64_t id_;
const QuicVariableLengthIntegerLength encoded_length_;
QuicBufferAllocator* const allocator_;
Delegate* const delegate_;
QuartcSession* session_;
// Map of multiplexer-chosen to user/caller-specified datagram ids. The user
// may specify any number as a datagram's id. This number does not have to be
// unique across channels (nor even within a single channel). In order
// to demux sent, acked, and lost messages, the multiplexer assigns a globally
// unique id to each message. This map is used to restore the original caller
// datagram id before issuing callbacks.
QuicUnorderedMap<int64_t, int64_t> multiplexer_to_user_datagram_ids_;
// A single, multiplexed receive channel within a Quartc session. A receive
// channel is a delegate which accepts incoming streams and datagrams on one (or
// more) channel ids.
class QuartcReceiveChannel {
virtual ~QuartcReceiveChannel() = default;
// Called when a new incoming stream arrives on this channel.
virtual void OnIncomingStream(uint64_t channel_id, QuartcStream* stream) = 0;
// Called when a message is recieved by this channel.
virtual void OnMessageReceived(uint64_t channel_id,
QuicStringPiece message) = 0;
// Delegate for session-wide events.
class QuartcSessionEventDelegate {
virtual ~QuartcSessionEventDelegate() = default;
virtual void OnSessionCreated(QuartcSession* session) = 0;
virtual void OnCryptoHandshakeComplete() = 0;
virtual void OnConnectionWritable() = 0;
virtual void OnCongestionControlChange(QuicBandwidth bandwidth_estimate,
QuicBandwidth pacing_rate,
QuicTime::Delta latest_rtt) = 0;
virtual void OnConnectionClosed(const QuicConnectionCloseFrame& frame,
ConnectionCloseSource source) = 0;
// A multiplexer capable of sending and receiving data on multiple channels.
class QuartcMultiplexer : public QuartcEndpoint::Delegate,
public QuartcStream::Delegate {
// Creates a new multiplexer. |session_delegate| handles all session-wide
// events, while |default_receive_channel| handles incoming data on unknown
// or unregistered channel ids. Neither |session_delegate| nor
// |default_receive_channel| may be nullptr, and both must outlive the
// multiplexer.
QuartcMultiplexer(QuicBufferAllocator* allocator,
QuartcSessionEventDelegate* session_delegate,
QuartcReceiveChannel* default_receive_channel);
// Creates a new send channel. The channel is owned by the multiplexer, and
// references to it must not outlive the multiplexer.
QuartcSendChannel* CreateSendChannel(uint64_t channel_id,
QuartcSendChannel::Delegate* delegate);
// Registers a receiver for incoming data on |channel_id|.
void RegisterReceiveChannel(uint64_t channel_id,
QuartcReceiveChannel* channel);
// Allocates a datagram id to |channel|.
int64_t AllocateDatagramId(QuartcSendChannel* channel);
// QuartcEndpoint::Delegate overrides.
void OnSessionCreated(QuartcSession* session) override;
// QuartcSession::Delegate overrides.
void OnCryptoHandshakeComplete() override;
void OnConnectionWritable() override;
void OnIncomingStream(QuartcStream* stream) override;
void OnCongestionControlChange(QuicBandwidth bandwidth_estimate,
QuicBandwidth pacing_rate,
QuicTime::Delta latest_rtt) override;
void OnConnectionClosed(const QuicConnectionCloseFrame& frame,
ConnectionCloseSource source) override;
void OnMessageReceived(QuicStringPiece message) override;
void OnMessageSent(int64_t datagram_id) override;
void OnMessageAcked(int64_t datagram_id, QuicTime receive_timestamp) override;
void OnMessageLost(int64_t datagram_id) override;
// QuartcStream::Delegate overrides.
size_t OnReceived(QuartcStream* stream,
iovec* iov,
size_t iov_length,
bool fin) override;
void OnClose(QuartcStream* stream) override;
void OnBufferChanged(QuartcStream* stream) override;
QuicBufferAllocator* const allocator_;
QuartcSessionEventDelegate* const session_delegate_;
QuartcSession* session_ = nullptr;
std::vector<std::unique_ptr<QuartcSendChannel>> send_channels_;
QuicUnorderedMap<uint64_t, QuartcReceiveChannel*> receive_channels_;
QuartcReceiveChannel* default_receive_channel_ = nullptr;
int64_t next_datagram_id_ = 1;
QuicUnorderedMap<int64_t, QuartcSendChannel*> send_channels_by_datagram_id_;
} // namespace quic