1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "osp/impl/quic/quic_service_common.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "util/osp_logging.h"
11
12 namespace openscreen {
13 namespace osp {
14
15 // static
FromExisting(Owner * owner,QuicConnection * connection,ServiceConnectionDelegate * delegate,uint64_t endpoint_id)16 std::unique_ptr<QuicProtocolConnection> QuicProtocolConnection::FromExisting(
17 Owner* owner,
18 QuicConnection* connection,
19 ServiceConnectionDelegate* delegate,
20 uint64_t endpoint_id) {
21 OSP_VLOG << "QUIC stream created for endpoint " << endpoint_id;
22 std::unique_ptr<QuicStream> stream = connection->MakeOutgoingStream(delegate);
23 auto pc = std::make_unique<QuicProtocolConnection>(owner, endpoint_id,
24 stream->id());
25 pc->set_stream(stream.get());
26 delegate->AddStreamPair(ServiceStreamPair(std::move(stream), pc.get()));
27 return pc;
28 }
29
QuicProtocolConnection(Owner * owner,uint64_t endpoint_id,uint64_t connection_id)30 QuicProtocolConnection::QuicProtocolConnection(Owner* owner,
31 uint64_t endpoint_id,
32 uint64_t connection_id)
33 : ProtocolConnection(endpoint_id, connection_id), owner_(owner) {}
34
~QuicProtocolConnection()35 QuicProtocolConnection::~QuicProtocolConnection() {
36 if (stream_) {
37 stream_->CloseWriteEnd();
38 owner_->OnConnectionDestroyed(this);
39 stream_ = nullptr;
40 }
41 }
42
Write(const uint8_t * data,size_t data_size)43 void QuicProtocolConnection::Write(const uint8_t* data, size_t data_size) {
44 if (stream_)
45 stream_->Write(data, data_size);
46 }
47
CloseWriteEnd()48 void QuicProtocolConnection::CloseWriteEnd() {
49 if (stream_)
50 stream_->CloseWriteEnd();
51 }
52
OnClose()53 void QuicProtocolConnection::OnClose() {
54 if (observer_)
55 observer_->OnConnectionClosed(*this);
56 }
57
ServiceStreamPair(std::unique_ptr<QuicStream> stream,QuicProtocolConnection * protocol_connection)58 ServiceStreamPair::ServiceStreamPair(
59 std::unique_ptr<QuicStream> stream,
60 QuicProtocolConnection* protocol_connection)
61 : stream(std::move(stream)),
62 connection_id(protocol_connection->id()),
63 protocol_connection(std::move(protocol_connection)) {}
64 ServiceStreamPair::~ServiceStreamPair() = default;
65
66 ServiceStreamPair::ServiceStreamPair(ServiceStreamPair&& other) noexcept =
67 default;
68
69 ServiceStreamPair& ServiceStreamPair::operator=(
70 ServiceStreamPair&& other) noexcept = default;
71
ServiceConnectionDelegate(ServiceDelegate * parent,const IPEndpoint & endpoint)72 ServiceConnectionDelegate::ServiceConnectionDelegate(ServiceDelegate* parent,
73 const IPEndpoint& endpoint)
74 : parent_(parent), endpoint_(endpoint) {}
75
~ServiceConnectionDelegate()76 ServiceConnectionDelegate::~ServiceConnectionDelegate() {
77 void DestroyClosedStreams();
78 OSP_DCHECK(streams_.empty());
79 }
80
AddStreamPair(ServiceStreamPair && stream_pair)81 void ServiceConnectionDelegate::AddStreamPair(ServiceStreamPair&& stream_pair) {
82 uint64_t stream_id = stream_pair.stream->id();
83 streams_.emplace(stream_id, std::move(stream_pair));
84 }
85
DropProtocolConnection(QuicProtocolConnection * connection)86 void ServiceConnectionDelegate::DropProtocolConnection(
87 QuicProtocolConnection* connection) {
88 auto stream_entry = streams_.find(connection->stream()->id());
89 if (stream_entry == streams_.end())
90 return;
91 stream_entry->second.protocol_connection = nullptr;
92 }
93
DestroyClosedStreams()94 void ServiceConnectionDelegate::DestroyClosedStreams() {
95 closed_streams_.clear();
96 }
97
OnCryptoHandshakeComplete(uint64_t connection_id)98 void ServiceConnectionDelegate::OnCryptoHandshakeComplete(
99 uint64_t connection_id) {
100 endpoint_id_ = parent_->OnCryptoHandshakeComplete(this, connection_id);
101 OSP_VLOG << "QUIC connection handshake complete for endpoint "
102 << endpoint_id_;
103 }
104
OnIncomingStream(uint64_t connection_id,std::unique_ptr<QuicStream> stream)105 void ServiceConnectionDelegate::OnIncomingStream(
106 uint64_t connection_id,
107 std::unique_ptr<QuicStream> stream) {
108 OSP_VLOG << "Incoming QUIC stream from endpoint " << endpoint_id_;
109 pending_connection_->set_stream(stream.get());
110 AddStreamPair(
111 ServiceStreamPair(std::move(stream), pending_connection_.get()));
112 parent_->OnIncomingStream(std::move(pending_connection_));
113 }
114
OnConnectionClosed(uint64_t connection_id)115 void ServiceConnectionDelegate::OnConnectionClosed(uint64_t connection_id) {
116 OSP_VLOG << "QUIC connection closed for endpoint " << endpoint_id_;
117 parent_->OnConnectionClosed(endpoint_id_, connection_id);
118 }
119
NextStreamDelegate(uint64_t connection_id,uint64_t stream_id)120 QuicStream::Delegate* ServiceConnectionDelegate::NextStreamDelegate(
121 uint64_t connection_id,
122 uint64_t stream_id) {
123 OSP_DCHECK(!pending_connection_);
124 pending_connection_ = std::make_unique<QuicProtocolConnection>(
125 parent_, endpoint_id_, stream_id);
126 return this;
127 }
128
OnReceived(QuicStream * stream,const char * data,size_t data_size)129 void ServiceConnectionDelegate::OnReceived(QuicStream* stream,
130 const char* data,
131 size_t data_size) {
132 auto stream_entry = streams_.find(stream->id());
133 if (stream_entry == streams_.end())
134 return;
135 ServiceStreamPair& stream_pair = stream_entry->second;
136 parent_->OnDataReceived(endpoint_id_, stream_pair.connection_id,
137 reinterpret_cast<const uint8_t*>(data), data_size);
138 }
139
OnClose(uint64_t stream_id)140 void ServiceConnectionDelegate::OnClose(uint64_t stream_id) {
141 OSP_VLOG << "QUIC stream closed for endpoint " << endpoint_id_;
142 auto stream_entry = streams_.find(stream_id);
143 if (stream_entry == streams_.end())
144 return;
145 ServiceStreamPair& stream_pair = stream_entry->second;
146 parent_->OnDataReceived(endpoint_id_, stream_pair.connection_id, nullptr, 0);
147 if (stream_pair.protocol_connection) {
148 stream_pair.protocol_connection->set_stream(nullptr);
149 stream_pair.protocol_connection->OnClose();
150 }
151 // NOTE: If this OnClose is the result of the read end closing when the write
152 // end was already closed, there will likely still be a call to OnReceived.
153 // We need to delay actually destroying the stream object until the end of the
154 // event loop.
155 closed_streams_.push_back(std::move(stream_entry->second));
156 streams_.erase(stream_entry);
157 }
158
ServiceConnectionData(std::unique_ptr<QuicConnection> connection,std::unique_ptr<ServiceConnectionDelegate> delegate)159 ServiceConnectionData::ServiceConnectionData(
160 std::unique_ptr<QuicConnection> connection,
161 std::unique_ptr<ServiceConnectionDelegate> delegate)
162 : connection(std::move(connection)), delegate(std::move(delegate)) {}
163 ServiceConnectionData::ServiceConnectionData(ServiceConnectionData&&) noexcept =
164 default;
165 ServiceConnectionData::~ServiceConnectionData() = default;
166 ServiceConnectionData& ServiceConnectionData::operator=(
167 ServiceConnectionData&&) noexcept = default;
168
169 } // namespace osp
170 } // namespace openscreen
171