// Copyright 2019 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 "cast/common/public/cast_socket.h" #include "cast/common/channel/message_framer.h" #include "cast/common/channel/proto/cast_channel.pb.h" #include "util/osp_logging.h" namespace openscreen { namespace cast { using ::cast::channel::CastMessage; using message_serialization::DeserializeResult; CastSocket::CastSocket(std::unique_ptr connection, Client* client) : connection_(std::move(connection)), client_(client), socket_id_(g_next_socket_id_++) { OSP_DCHECK(client); connection_->SetClient(this); } CastSocket::~CastSocket() { connection_->SetClient(nullptr); } Error CastSocket::Send(const CastMessage& message) { if (state_ == State::kError) { return Error::Code::kSocketClosedFailure; } const ErrorOr> out = message_serialization::Serialize(message); if (!out) { return out.error(); } if (!connection_->Send(out.value().data(), out.value().size())) { return Error::Code::kAgain; } return Error::Code::kNone; } void CastSocket::SetClient(Client* client) { OSP_DCHECK(client); client_ = client; } std::array CastSocket::GetSanitizedIpAddress() { IPEndpoint remote = connection_->GetRemoteEndpoint(); std::array result; uint8_t bytes[16]; if (remote.address.IsV4()) { remote.address.CopyToV4(bytes); result[0] = bytes[2]; result[1] = bytes[3]; } else { remote.address.CopyToV6(bytes); result[0] = bytes[14]; result[1] = bytes[15]; } return result; } void CastSocket::OnError(TlsConnection* connection, Error error) { state_ = State::kError; client_->OnError(this, error); } void CastSocket::OnRead(TlsConnection* connection, std::vector block) { read_buffer_.insert(read_buffer_.end(), block.begin(), block.end()); // NOTE: Read as many messages as possible out of |read_buffer_| since we only // get one callback opportunity for this. do { ErrorOr message_or_error = message_serialization::TryDeserialize( absl::Span(&read_buffer_[0], read_buffer_.size())); if (!message_or_error) { return; } read_buffer_.erase(read_buffer_.begin(), read_buffer_.begin() + message_or_error.value().length); client_->OnMessage(this, std::move(message_or_error.value().message)); } while (!read_buffer_.empty()); } int CastSocket::g_next_socket_id_ = 1; } // namespace cast } // namespace openscreen