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