• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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