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.
171 lines
6.0 KiB
171 lines
6.0 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.
|
|
|
|
#include "osp/impl/quic/quic_service_common.h"
|
|
|
|
#include <memory>
|
|
#include <utility>
|
|
|
|
#include "util/osp_logging.h"
|
|
|
|
namespace openscreen {
|
|
namespace osp {
|
|
|
|
// static
|
|
std::unique_ptr<QuicProtocolConnection> QuicProtocolConnection::FromExisting(
|
|
Owner* owner,
|
|
QuicConnection* connection,
|
|
ServiceConnectionDelegate* delegate,
|
|
uint64_t endpoint_id) {
|
|
OSP_VLOG << "QUIC stream created for endpoint " << endpoint_id;
|
|
std::unique_ptr<QuicStream> stream = connection->MakeOutgoingStream(delegate);
|
|
auto pc = std::make_unique<QuicProtocolConnection>(owner, endpoint_id,
|
|
stream->id());
|
|
pc->set_stream(stream.get());
|
|
delegate->AddStreamPair(ServiceStreamPair(std::move(stream), pc.get()));
|
|
return pc;
|
|
}
|
|
|
|
QuicProtocolConnection::QuicProtocolConnection(Owner* owner,
|
|
uint64_t endpoint_id,
|
|
uint64_t connection_id)
|
|
: ProtocolConnection(endpoint_id, connection_id), owner_(owner) {}
|
|
|
|
QuicProtocolConnection::~QuicProtocolConnection() {
|
|
if (stream_) {
|
|
stream_->CloseWriteEnd();
|
|
owner_->OnConnectionDestroyed(this);
|
|
stream_ = nullptr;
|
|
}
|
|
}
|
|
|
|
void QuicProtocolConnection::Write(const uint8_t* data, size_t data_size) {
|
|
if (stream_)
|
|
stream_->Write(data, data_size);
|
|
}
|
|
|
|
void QuicProtocolConnection::CloseWriteEnd() {
|
|
if (stream_)
|
|
stream_->CloseWriteEnd();
|
|
}
|
|
|
|
void QuicProtocolConnection::OnClose() {
|
|
if (observer_)
|
|
observer_->OnConnectionClosed(*this);
|
|
}
|
|
|
|
ServiceStreamPair::ServiceStreamPair(
|
|
std::unique_ptr<QuicStream> stream,
|
|
QuicProtocolConnection* protocol_connection)
|
|
: stream(std::move(stream)),
|
|
connection_id(protocol_connection->id()),
|
|
protocol_connection(std::move(protocol_connection)) {}
|
|
ServiceStreamPair::~ServiceStreamPair() = default;
|
|
|
|
ServiceStreamPair::ServiceStreamPair(ServiceStreamPair&& other) noexcept =
|
|
default;
|
|
|
|
ServiceStreamPair& ServiceStreamPair::operator=(
|
|
ServiceStreamPair&& other) noexcept = default;
|
|
|
|
ServiceConnectionDelegate::ServiceConnectionDelegate(ServiceDelegate* parent,
|
|
const IPEndpoint& endpoint)
|
|
: parent_(parent), endpoint_(endpoint) {}
|
|
|
|
ServiceConnectionDelegate::~ServiceConnectionDelegate() {
|
|
void DestroyClosedStreams();
|
|
OSP_DCHECK(streams_.empty());
|
|
}
|
|
|
|
void ServiceConnectionDelegate::AddStreamPair(ServiceStreamPair&& stream_pair) {
|
|
uint64_t stream_id = stream_pair.stream->id();
|
|
streams_.emplace(stream_id, std::move(stream_pair));
|
|
}
|
|
|
|
void ServiceConnectionDelegate::DropProtocolConnection(
|
|
QuicProtocolConnection* connection) {
|
|
auto stream_entry = streams_.find(connection->stream()->id());
|
|
if (stream_entry == streams_.end())
|
|
return;
|
|
stream_entry->second.protocol_connection = nullptr;
|
|
}
|
|
|
|
void ServiceConnectionDelegate::DestroyClosedStreams() {
|
|
closed_streams_.clear();
|
|
}
|
|
|
|
void ServiceConnectionDelegate::OnCryptoHandshakeComplete(
|
|
uint64_t connection_id) {
|
|
endpoint_id_ = parent_->OnCryptoHandshakeComplete(this, connection_id);
|
|
OSP_VLOG << "QUIC connection handshake complete for endpoint "
|
|
<< endpoint_id_;
|
|
}
|
|
|
|
void ServiceConnectionDelegate::OnIncomingStream(
|
|
uint64_t connection_id,
|
|
std::unique_ptr<QuicStream> stream) {
|
|
OSP_VLOG << "Incoming QUIC stream from endpoint " << endpoint_id_;
|
|
pending_connection_->set_stream(stream.get());
|
|
AddStreamPair(
|
|
ServiceStreamPair(std::move(stream), pending_connection_.get()));
|
|
parent_->OnIncomingStream(std::move(pending_connection_));
|
|
}
|
|
|
|
void ServiceConnectionDelegate::OnConnectionClosed(uint64_t connection_id) {
|
|
OSP_VLOG << "QUIC connection closed for endpoint " << endpoint_id_;
|
|
parent_->OnConnectionClosed(endpoint_id_, connection_id);
|
|
}
|
|
|
|
QuicStream::Delegate* ServiceConnectionDelegate::NextStreamDelegate(
|
|
uint64_t connection_id,
|
|
uint64_t stream_id) {
|
|
OSP_DCHECK(!pending_connection_);
|
|
pending_connection_ = std::make_unique<QuicProtocolConnection>(
|
|
parent_, endpoint_id_, stream_id);
|
|
return this;
|
|
}
|
|
|
|
void ServiceConnectionDelegate::OnReceived(QuicStream* stream,
|
|
const char* data,
|
|
size_t data_size) {
|
|
auto stream_entry = streams_.find(stream->id());
|
|
if (stream_entry == streams_.end())
|
|
return;
|
|
ServiceStreamPair& stream_pair = stream_entry->second;
|
|
parent_->OnDataReceived(endpoint_id_, stream_pair.connection_id,
|
|
reinterpret_cast<const uint8_t*>(data), data_size);
|
|
}
|
|
|
|
void ServiceConnectionDelegate::OnClose(uint64_t stream_id) {
|
|
OSP_VLOG << "QUIC stream closed for endpoint " << endpoint_id_;
|
|
auto stream_entry = streams_.find(stream_id);
|
|
if (stream_entry == streams_.end())
|
|
return;
|
|
ServiceStreamPair& stream_pair = stream_entry->second;
|
|
parent_->OnDataReceived(endpoint_id_, stream_pair.connection_id, nullptr, 0);
|
|
if (stream_pair.protocol_connection) {
|
|
stream_pair.protocol_connection->set_stream(nullptr);
|
|
stream_pair.protocol_connection->OnClose();
|
|
}
|
|
// NOTE: If this OnClose is the result of the read end closing when the write
|
|
// end was already closed, there will likely still be a call to OnReceived.
|
|
// We need to delay actually destroying the stream object until the end of the
|
|
// event loop.
|
|
closed_streams_.push_back(std::move(stream_entry->second));
|
|
streams_.erase(stream_entry);
|
|
}
|
|
|
|
ServiceConnectionData::ServiceConnectionData(
|
|
std::unique_ptr<QuicConnection> connection,
|
|
std::unique_ptr<ServiceConnectionDelegate> delegate)
|
|
: connection(std::move(connection)), delegate(std::move(delegate)) {}
|
|
ServiceConnectionData::ServiceConnectionData(ServiceConnectionData&&) noexcept =
|
|
default;
|
|
ServiceConnectionData::~ServiceConnectionData() = default;
|
|
ServiceConnectionData& ServiceConnectionData::operator=(
|
|
ServiceConnectionData&&) noexcept = default;
|
|
|
|
} // namespace osp
|
|
} // namespace openscreen
|