You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
140 lines
5.6 KiB
140 lines
5.6 KiB
// Copyright 2018 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.
|
|
|
|
#ifndef OSP_IMPL_QUIC_QUIC_CLIENT_H_
|
|
#define OSP_IMPL_QUIC_QUIC_CLIENT_H_
|
|
|
|
#include <cstdint>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include "osp/impl/quic/quic_connection_factory.h"
|
|
#include "osp/impl/quic/quic_service_common.h"
|
|
#include "osp/public/protocol_connection_client.h"
|
|
#include "platform/api/task_runner.h"
|
|
#include "platform/api/time.h"
|
|
#include "platform/base/ip_address.h"
|
|
#include "util/alarm.h"
|
|
|
|
namespace openscreen {
|
|
namespace osp {
|
|
|
|
// This class is the default implementation of ProtocolConnectionClient for the
|
|
// library. It manages connections to other endpoints as well as the lifetime
|
|
// of each incoming and outgoing stream. It works in conjunction with a
|
|
// QuicConnectionFactory implementation and MessageDemuxer.
|
|
// QuicConnectionFactory provides the actual ability to make a new QUIC
|
|
// connection with another endpoint. Incoming data is given to the QuicClient
|
|
// by the underlying QUIC implementation (through QuicConnectionFactory) and
|
|
// this is in turn handed to MessageDemuxer for routing CBOR messages.
|
|
//
|
|
// The two most significant methods of this class are Connect and
|
|
// CreateProtocolConnection. Both will return a new QUIC stream to a given
|
|
// endpoint to which the caller can write but the former is allowed to be
|
|
// asynchronous. If there isn't currently a connection to the specified
|
|
// endpoint, Connect will start a connection attempt and store the callback for
|
|
// when the connection completes. CreateProtocolConnection simply returns
|
|
// nullptr if there's no existing connection.
|
|
class QuicClient final : public ProtocolConnectionClient,
|
|
public ServiceConnectionDelegate::ServiceDelegate {
|
|
public:
|
|
QuicClient(MessageDemuxer* demuxer,
|
|
std::unique_ptr<QuicConnectionFactory> connection_factory,
|
|
ProtocolConnectionServiceObserver* observer,
|
|
ClockNowFunctionPtr now_function,
|
|
TaskRunner* task_runner);
|
|
~QuicClient() override;
|
|
|
|
// ProtocolConnectionClient overrides.
|
|
bool Start() override;
|
|
bool Stop() override;
|
|
ConnectRequest Connect(const IPEndpoint& endpoint,
|
|
ConnectionRequestCallback* request) override;
|
|
std::unique_ptr<ProtocolConnection> CreateProtocolConnection(
|
|
uint64_t endpoint_id) override;
|
|
|
|
// QuicProtocolConnection::Owner overrides.
|
|
void OnConnectionDestroyed(QuicProtocolConnection* connection) override;
|
|
|
|
// ServiceConnectionDelegate::ServiceDelegate overrides.
|
|
uint64_t OnCryptoHandshakeComplete(ServiceConnectionDelegate* delegate,
|
|
uint64_t connection_id) override;
|
|
void OnIncomingStream(
|
|
std::unique_ptr<QuicProtocolConnection> connection) override;
|
|
void OnConnectionClosed(uint64_t endpoint_id,
|
|
uint64_t connection_id) override;
|
|
void OnDataReceived(uint64_t endpoint_id,
|
|
uint64_t connection_id,
|
|
const uint8_t* data,
|
|
size_t data_size) override;
|
|
|
|
private:
|
|
struct PendingConnectionData {
|
|
explicit PendingConnectionData(ServiceConnectionData&& data);
|
|
PendingConnectionData(PendingConnectionData&&) noexcept;
|
|
~PendingConnectionData();
|
|
PendingConnectionData& operator=(PendingConnectionData&&) noexcept;
|
|
|
|
ServiceConnectionData data;
|
|
|
|
// Pairs of request IDs and the associated connection callback.
|
|
std::vector<std::pair<uint64_t, ConnectionRequestCallback*>> callbacks;
|
|
};
|
|
|
|
ConnectRequest CreatePendingConnection(const IPEndpoint& endpoint,
|
|
ConnectionRequestCallback* request);
|
|
uint64_t StartConnectionRequest(const IPEndpoint& endpoint,
|
|
ConnectionRequestCallback* request);
|
|
void CloseAllConnections();
|
|
std::unique_ptr<QuicProtocolConnection> MakeProtocolConnection(
|
|
QuicConnection* connection,
|
|
ServiceConnectionDelegate* delegate,
|
|
uint64_t endpoint_id);
|
|
|
|
void CancelConnectRequest(uint64_t request_id) override;
|
|
|
|
// Deletes dead QUIC connections then returns the time interval before this
|
|
// method should be run again.
|
|
void Cleanup();
|
|
|
|
std::unique_ptr<QuicConnectionFactory> connection_factory_;
|
|
|
|
// Maps an IPEndpoint to a generated endpoint ID. This is used to insulate
|
|
// callers from post-handshake changes to a connections actual peer endpoint.
|
|
std::map<IPEndpoint, uint64_t> endpoint_map_;
|
|
|
|
// Value that will be used for the next new endpoint in a Connect call.
|
|
uint64_t next_endpoint_id_ = 0;
|
|
|
|
// Maps request IDs to their callbacks. The callback is paired with the
|
|
// IPEndpoint it originally requested to connect to so cancelling the request
|
|
// can also remove a pending connection.
|
|
std::map<uint64_t, std::pair<IPEndpoint, ConnectionRequestCallback*>>
|
|
request_map_;
|
|
|
|
// Value that will be used for the next new connection request.
|
|
uint64_t next_request_id_ = 1;
|
|
|
|
// Maps endpoint addresses to data about connections that haven't successfully
|
|
// completed the QUIC handshake.
|
|
std::map<IPEndpoint, PendingConnectionData> pending_connections_;
|
|
|
|
// Maps endpoint IDs to data about connections that have successfully
|
|
// completed the QUIC handshake.
|
|
std::map<uint64_t, ServiceConnectionData> connections_;
|
|
|
|
// Connections (endpoint IDs) that need to be destroyed, but have to wait for
|
|
// the next event loop due to the underlying QUIC implementation's way of
|
|
// referencing them.
|
|
std::vector<uint64_t> delete_connections_;
|
|
|
|
Alarm cleanup_alarm_;
|
|
};
|
|
|
|
} // namespace osp
|
|
} // namespace openscreen
|
|
|
|
#endif // OSP_IMPL_QUIC_QUIC_CLIENT_H_
|