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_connection_impl.h"
6
7 #include <limits>
8 #include <memory>
9
10 #include "absl/types/optional.h"
11 #include "osp/impl/quic/quic_connection_factory_impl.h"
12 #include "platform/base/error.h"
13 #include "third_party/chromium_quic/src/net/third_party/quic/platform/impl/quic_chromium_clock.h"
14 #include "util/osp_logging.h"
15 #include "util/trace_logging.h"
16
17 namespace openscreen {
18 namespace osp {
19
UdpTransport(UdpSocket * socket,const IPEndpoint & destination)20 UdpTransport::UdpTransport(UdpSocket* socket, const IPEndpoint& destination)
21 : socket_(socket), destination_(destination) {
22 OSP_DCHECK(socket_);
23 }
24
25 UdpTransport::UdpTransport(UdpTransport&&) noexcept = default;
26 UdpTransport::~UdpTransport() = default;
27
28 UdpTransport& UdpTransport::operator=(UdpTransport&&) noexcept = default;
29
Write(const char * buffer,size_t buffer_length,const PacketInfo & info)30 int UdpTransport::Write(const char* buffer,
31 size_t buffer_length,
32 const PacketInfo& info) {
33 TRACE_SCOPED(TraceCategory::kQuic, "UdpTransport::Write");
34 socket_->SendMessage(buffer, buffer_length, destination_);
35 OSP_DCHECK_LE(buffer_length,
36 static_cast<size_t>(std::numeric_limits<int>::max()));
37 return static_cast<int>(buffer_length);
38 }
39
QuicStreamImpl(QuicStream::Delegate * delegate,::quic::QuartcStream * stream)40 QuicStreamImpl::QuicStreamImpl(QuicStream::Delegate* delegate,
41 ::quic::QuartcStream* stream)
42 : QuicStream(delegate, stream->id()), stream_(stream) {
43 stream_->SetDelegate(this);
44 }
45
46 QuicStreamImpl::~QuicStreamImpl() = default;
47
Write(const uint8_t * data,size_t data_size)48 void QuicStreamImpl::Write(const uint8_t* data, size_t data_size) {
49 TRACE_SCOPED(TraceCategory::kQuic, "QuicStreamImpl::Write");
50 OSP_DCHECK(!stream_->write_side_closed());
51 stream_->WriteOrBufferData(
52 ::quic::QuicStringPiece(reinterpret_cast<const char*>(data), data_size),
53 false, nullptr);
54 }
55
CloseWriteEnd()56 void QuicStreamImpl::CloseWriteEnd() {
57 TRACE_SCOPED(TraceCategory::kQuic, "QuicStreamImpl::CloseWriteEnd");
58 if (!stream_->write_side_closed())
59 stream_->FinishWriting();
60 }
61
OnReceived(::quic::QuartcStream * stream,const char * data,size_t data_size)62 void QuicStreamImpl::OnReceived(::quic::QuartcStream* stream,
63 const char* data,
64 size_t data_size) {
65 TRACE_SCOPED(TraceCategory::kQuic, "QuicStreamImpl::OnReceived");
66 delegate_->OnReceived(this, data, data_size);
67 }
68
OnClose(::quic::QuartcStream * stream)69 void QuicStreamImpl::OnClose(::quic::QuartcStream* stream) {
70 TRACE_SCOPED(TraceCategory::kQuic, "QuicStreamImpl::OnClose");
71 delegate_->OnClose(stream->id());
72 }
73
OnBufferChanged(::quic::QuartcStream * stream)74 void QuicStreamImpl::OnBufferChanged(::quic::QuartcStream* stream) {}
75
76 // Passes a received UDP packet to the QUIC implementation. If this contains
77 // any stream data, it will be passed automatically to the relevant
78 // QuicStream::Delegate objects.
OnRead(UdpSocket * socket,ErrorOr<UdpPacket> data)79 void QuicConnectionImpl::OnRead(UdpSocket* socket, ErrorOr<UdpPacket> data) {
80 TRACE_SCOPED(TraceCategory::kQuic, "QuicConnectionImpl::OnRead");
81 if (data.is_error()) {
82 TRACE_SET_RESULT(data.error());
83 return;
84 }
85
86 session_->OnTransportReceived(
87 reinterpret_cast<const char*>(data.value().data()), data.value().size());
88 }
89
OnSendError(UdpSocket * socket,Error error)90 void QuicConnectionImpl::OnSendError(UdpSocket* socket, Error error) {
91 // TODO(crbug.com/openscreen/67): Implement this method.
92 OSP_UNIMPLEMENTED();
93 }
94
OnError(UdpSocket * socket,Error error)95 void QuicConnectionImpl::OnError(UdpSocket* socket, Error error) {
96 // TODO(crbug.com/openscreen/67): Implement this method.
97 OSP_UNIMPLEMENTED();
98 }
99
QuicConnectionImpl(QuicConnectionFactoryImpl * parent_factory,QuicConnection::Delegate * delegate,std::unique_ptr<UdpTransport> udp_transport,std::unique_ptr<::quic::QuartcSession> session)100 QuicConnectionImpl::QuicConnectionImpl(
101 QuicConnectionFactoryImpl* parent_factory,
102 QuicConnection::Delegate* delegate,
103 std::unique_ptr<UdpTransport> udp_transport,
104 std::unique_ptr<::quic::QuartcSession> session)
105 : QuicConnection(delegate),
106 parent_factory_(parent_factory),
107 session_(std::move(session)),
108 udp_transport_(std::move(udp_transport)) {
109 TRACE_SCOPED(TraceCategory::kQuic, "QuicConnectionImpl::QuicConnectionImpl");
110 session_->SetDelegate(this);
111 session_->OnTransportCanWrite();
112 session_->StartCryptoHandshake();
113 }
114
115 QuicConnectionImpl::~QuicConnectionImpl() = default;
116
MakeOutgoingStream(QuicStream::Delegate * delegate)117 std::unique_ptr<QuicStream> QuicConnectionImpl::MakeOutgoingStream(
118 QuicStream::Delegate* delegate) {
119 TRACE_SCOPED(TraceCategory::kQuic, "QuicConnectionImpl::MakeOutgoingStream");
120 ::quic::QuartcStream* stream = session_->CreateOutgoingDynamicStream();
121 return std::make_unique<QuicStreamImpl>(delegate, stream);
122 }
123
Close()124 void QuicConnectionImpl::Close() {
125 TRACE_SCOPED(TraceCategory::kQuic, "QuicConnectionImpl::Close");
126 session_->CloseConnection("closed");
127 }
128
OnCryptoHandshakeComplete()129 void QuicConnectionImpl::OnCryptoHandshakeComplete() {
130 TRACE_SCOPED(TraceCategory::kQuic,
131 "QuicConnectionImpl::OnCryptoHandshakeComplete");
132 delegate_->OnCryptoHandshakeComplete(session_->connection_id());
133 }
134
OnIncomingStream(::quic::QuartcStream * stream)135 void QuicConnectionImpl::OnIncomingStream(::quic::QuartcStream* stream) {
136 TRACE_SCOPED(TraceCategory::kQuic, "QuicConnectionImpl::OnIncomingStream");
137 auto public_stream = std::make_unique<QuicStreamImpl>(
138 delegate_->NextStreamDelegate(session_->connection_id(), stream->id()),
139 stream);
140 streams_.push_back(public_stream.get());
141 delegate_->OnIncomingStream(session_->connection_id(),
142 std::move(public_stream));
143 }
144
OnConnectionClosed(::quic::QuicErrorCode error_code,const::quic::QuicString & error_details,::quic::ConnectionCloseSource source)145 void QuicConnectionImpl::OnConnectionClosed(
146 ::quic::QuicErrorCode error_code,
147 const ::quic::QuicString& error_details,
148 ::quic::ConnectionCloseSource source) {
149 TRACE_SCOPED(TraceCategory::kQuic, "QuicConnectionImpl::OnConnectionClosed");
150 parent_factory_->OnConnectionClosed(this);
151 delegate_->OnConnectionClosed(session_->connection_id());
152 }
153
154 } // namespace osp
155 } // namespace openscreen
156