// 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_connection_impl.h" #include #include #include "absl/types/optional.h" #include "osp/impl/quic/quic_connection_factory_impl.h" #include "platform/base/error.h" #include "third_party/chromium_quic/src/net/third_party/quic/platform/impl/quic_chromium_clock.h" #include "util/osp_logging.h" #include "util/trace_logging.h" namespace openscreen { namespace osp { UdpTransport::UdpTransport(UdpSocket* socket, const IPEndpoint& destination) : socket_(socket), destination_(destination) { OSP_DCHECK(socket_); } UdpTransport::UdpTransport(UdpTransport&&) noexcept = default; UdpTransport::~UdpTransport() = default; UdpTransport& UdpTransport::operator=(UdpTransport&&) noexcept = default; int UdpTransport::Write(const char* buffer, size_t buffer_length, const PacketInfo& info) { TRACE_SCOPED(TraceCategory::kQuic, "UdpTransport::Write"); socket_->SendMessage(buffer, buffer_length, destination_); OSP_DCHECK_LE(buffer_length, static_cast(std::numeric_limits::max())); return static_cast(buffer_length); } QuicStreamImpl::QuicStreamImpl(QuicStream::Delegate* delegate, ::quic::QuartcStream* stream) : QuicStream(delegate, stream->id()), stream_(stream) { stream_->SetDelegate(this); } QuicStreamImpl::~QuicStreamImpl() = default; void QuicStreamImpl::Write(const uint8_t* data, size_t data_size) { TRACE_SCOPED(TraceCategory::kQuic, "QuicStreamImpl::Write"); OSP_DCHECK(!stream_->write_side_closed()); stream_->WriteOrBufferData( ::quic::QuicStringPiece(reinterpret_cast(data), data_size), false, nullptr); } void QuicStreamImpl::CloseWriteEnd() { TRACE_SCOPED(TraceCategory::kQuic, "QuicStreamImpl::CloseWriteEnd"); if (!stream_->write_side_closed()) stream_->FinishWriting(); } void QuicStreamImpl::OnReceived(::quic::QuartcStream* stream, const char* data, size_t data_size) { TRACE_SCOPED(TraceCategory::kQuic, "QuicStreamImpl::OnReceived"); delegate_->OnReceived(this, data, data_size); } void QuicStreamImpl::OnClose(::quic::QuartcStream* stream) { TRACE_SCOPED(TraceCategory::kQuic, "QuicStreamImpl::OnClose"); delegate_->OnClose(stream->id()); } void QuicStreamImpl::OnBufferChanged(::quic::QuartcStream* stream) {} // Passes a received UDP packet to the QUIC implementation. If this contains // any stream data, it will be passed automatically to the relevant // QuicStream::Delegate objects. void QuicConnectionImpl::OnRead(UdpSocket* socket, ErrorOr data) { TRACE_SCOPED(TraceCategory::kQuic, "QuicConnectionImpl::OnRead"); if (data.is_error()) { TRACE_SET_RESULT(data.error()); return; } session_->OnTransportReceived( reinterpret_cast(data.value().data()), data.value().size()); } void QuicConnectionImpl::OnSendError(UdpSocket* socket, Error error) { // TODO(crbug.com/openscreen/67): Implement this method. OSP_UNIMPLEMENTED(); } void QuicConnectionImpl::OnError(UdpSocket* socket, Error error) { // TODO(crbug.com/openscreen/67): Implement this method. OSP_UNIMPLEMENTED(); } QuicConnectionImpl::QuicConnectionImpl( QuicConnectionFactoryImpl* parent_factory, QuicConnection::Delegate* delegate, std::unique_ptr udp_transport, std::unique_ptr<::quic::QuartcSession> session) : QuicConnection(delegate), parent_factory_(parent_factory), session_(std::move(session)), udp_transport_(std::move(udp_transport)) { TRACE_SCOPED(TraceCategory::kQuic, "QuicConnectionImpl::QuicConnectionImpl"); session_->SetDelegate(this); session_->OnTransportCanWrite(); session_->StartCryptoHandshake(); } QuicConnectionImpl::~QuicConnectionImpl() = default; std::unique_ptr QuicConnectionImpl::MakeOutgoingStream( QuicStream::Delegate* delegate) { TRACE_SCOPED(TraceCategory::kQuic, "QuicConnectionImpl::MakeOutgoingStream"); ::quic::QuartcStream* stream = session_->CreateOutgoingDynamicStream(); return std::make_unique(delegate, stream); } void QuicConnectionImpl::Close() { TRACE_SCOPED(TraceCategory::kQuic, "QuicConnectionImpl::Close"); session_->CloseConnection("closed"); } void QuicConnectionImpl::OnCryptoHandshakeComplete() { TRACE_SCOPED(TraceCategory::kQuic, "QuicConnectionImpl::OnCryptoHandshakeComplete"); delegate_->OnCryptoHandshakeComplete(session_->connection_id()); } void QuicConnectionImpl::OnIncomingStream(::quic::QuartcStream* stream) { TRACE_SCOPED(TraceCategory::kQuic, "QuicConnectionImpl::OnIncomingStream"); auto public_stream = std::make_unique( delegate_->NextStreamDelegate(session_->connection_id(), stream->id()), stream); streams_.push_back(public_stream.get()); delegate_->OnIncomingStream(session_->connection_id(), std::move(public_stream)); } void QuicConnectionImpl::OnConnectionClosed( ::quic::QuicErrorCode error_code, const ::quic::QuicString& error_details, ::quic::ConnectionCloseSource source) { TRACE_SCOPED(TraceCategory::kQuic, "QuicConnectionImpl::OnConnectionClosed"); parent_factory_->OnConnectionClosed(this); delegate_->OnConnectionClosed(session_->connection_id()); } } // namespace osp } // namespace openscreen