1 // Copyright 2019 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 "cast/common/channel/cast_socket_message_port.h"
6 
7 #include <utility>
8 
9 #include "cast/common/channel/message_util.h"
10 #include "cast/common/channel/proto/cast_channel.pb.h"
11 #include "cast/common/channel/virtual_connection.h"
12 #include "cast/common/channel/virtual_connection_manager.h"
13 
14 namespace openscreen {
15 namespace cast {
16 
CastSocketMessagePort(VirtualConnectionRouter * router)17 CastSocketMessagePort::CastSocketMessagePort(VirtualConnectionRouter* router)
18     : router_(router) {}
19 
~CastSocketMessagePort()20 CastSocketMessagePort::~CastSocketMessagePort() {
21   ResetClient();
22 }
23 
24 // NOTE: we assume here that this message port is already the client for
25 // the passed in socket, so leave the socket's client unchanged. However,
26 // since sockets should map one to one with receiver sessions, we reset our
27 // client. The consumer of this message port should call SetClient with the new
28 // message port client after setting the socket.
SetSocket(WeakPtr<CastSocket> socket)29 void CastSocketMessagePort::SetSocket(WeakPtr<CastSocket> socket) {
30   ResetClient();
31   socket_ = socket;
32 }
33 
GetSocketId()34 int CastSocketMessagePort::GetSocketId() {
35   return ToCastSocketId(socket_.get());
36 }
37 
SetClient(MessagePort::Client * client,std::string client_sender_id)38 void CastSocketMessagePort::SetClient(MessagePort::Client* client,
39                                       std::string client_sender_id) {
40   ResetClient();
41 
42   client_ = client;
43   client_sender_id_ = std::move(client_sender_id);
44   router_->AddHandlerForLocalId(client_sender_id_, this);
45 }
46 
ResetClient()47 void CastSocketMessagePort::ResetClient() {
48   if (!client_) {
49     return;
50   }
51 
52   client_ = nullptr;
53   router_->RemoveHandlerForLocalId(client_sender_id_);
54   router_->manager()->RemoveConnectionsByLocalId(
55       client_sender_id_, VirtualConnection::CloseReason::kClosedBySelf);
56   client_sender_id_.clear();
57 }
58 
PostMessage(const std::string & destination_sender_id,const std::string & message_namespace,const std::string & message)59 void CastSocketMessagePort::PostMessage(
60     const std::string& destination_sender_id,
61     const std::string& message_namespace,
62     const std::string& message) {
63   if (!client_) {
64     OSP_DLOG_WARN << "Not posting message due to nullptr client_";
65     return;
66   }
67 
68   if (!socket_) {
69     client_->OnError(Error::Code::kAlreadyClosed);
70     return;
71   }
72 
73   VirtualConnection connection{client_sender_id_, destination_sender_id,
74                                socket_->socket_id()};
75   if (!router_->manager()->GetConnectionData(connection)) {
76     router_->manager()->AddConnection(connection,
77                                       VirtualConnection::AssociatedData{});
78   }
79 
80   const Error send_error = router_->Send(
81       std::move(connection), MakeSimpleUTF8Message(message_namespace, message));
82   if (!send_error.ok()) {
83     client_->OnError(std::move(send_error));
84   }
85 }
86 
OnMessage(VirtualConnectionRouter * router,CastSocket * socket,::cast::channel::CastMessage message)87 void CastSocketMessagePort::OnMessage(VirtualConnectionRouter* router,
88                                       CastSocket* socket,
89                                       ::cast::channel::CastMessage message) {
90   OSP_DCHECK(router == router_);
91   OSP_DCHECK(!socket || socket_.get() == socket);
92   OSP_DVLOG << "Received a cast socket message";
93   if (!client_) {
94     OSP_DLOG_WARN << "Dropping message due to nullptr client_";
95     return;
96   }
97 
98   client_->OnMessage(message.source_id(), message.namespace_(),
99                      message.payload_utf8());
100 }
101 
102 }  // namespace cast
103 }  // namespace openscreen
104