1 // Copyright 2013 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 "remoting/signaling/delegating_signal_strategy.h"
6 
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/rand_util.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/threading/thread_task_runner_handle.h"
13 #include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
14 #include "third_party/libjingle_xmpp/xmpp/constants.h"
15 
16 namespace remoting {
17 
DelegatingSignalStrategy(const SignalingAddress & local_address,scoped_refptr<base::SingleThreadTaskRunner> client_task_runner,const IqCallback & send_iq_callback)18 DelegatingSignalStrategy::DelegatingSignalStrategy(
19     const SignalingAddress& local_address,
20     scoped_refptr<base::SingleThreadTaskRunner> client_task_runner,
21     const IqCallback& send_iq_callback)
22     : local_address_(local_address),
23       delegate_task_runner_(base::ThreadTaskRunnerHandle::Get()),
24       client_task_runner_(client_task_runner),
25       send_iq_callback_(send_iq_callback) {
26   incoming_iq_callback_ =
27       base::BindRepeating(&OnIncomingMessageFromDelegate,
28                           weak_factory_.GetWeakPtr(), client_task_runner_);
29 }
30 
31 DelegatingSignalStrategy::~DelegatingSignalStrategy() = default;
32 
33 DelegatingSignalStrategy::IqCallback
GetIncomingMessageCallback()34 DelegatingSignalStrategy::GetIncomingMessageCallback() {
35   return incoming_iq_callback_;
36 }
37 
38 // static
OnIncomingMessageFromDelegate(base::WeakPtr<DelegatingSignalStrategy> weak_ptr,scoped_refptr<base::SingleThreadTaskRunner> client_task_runner,const std::string & message)39 void DelegatingSignalStrategy::OnIncomingMessageFromDelegate(
40     base::WeakPtr<DelegatingSignalStrategy> weak_ptr,
41     scoped_refptr<base::SingleThreadTaskRunner> client_task_runner,
42     const std::string& message) {
43   if (client_task_runner->BelongsToCurrentThread()) {
44     weak_ptr->OnIncomingMessage(message);
45     return;
46   }
47 
48   client_task_runner->PostTask(
49       FROM_HERE, base::BindOnce(&DelegatingSignalStrategy::OnIncomingMessage,
50                                 weak_ptr, message));
51 }
52 
OnIncomingMessage(const std::string & message)53 void DelegatingSignalStrategy::OnIncomingMessage(const std::string& message) {
54   DCHECK(client_task_runner_->BelongsToCurrentThread());
55   std::unique_ptr<jingle_xmpp::XmlElement> stanza(jingle_xmpp::XmlElement::ForStr(message));
56   if (!stanza.get()) {
57     LOG(WARNING) << "Malformed XMPP stanza received: " << message;
58     return;
59   }
60 
61   for (auto& listener : listeners_) {
62     if (listener.OnSignalStrategyIncomingStanza(stanza.get()))
63       break;
64   }
65 }
66 
Connect()67 void DelegatingSignalStrategy::Connect() {
68   DCHECK(client_task_runner_->BelongsToCurrentThread());
69   for (auto& observer : listeners_)
70     observer.OnSignalStrategyStateChange(CONNECTED);
71 }
72 
Disconnect()73 void DelegatingSignalStrategy::Disconnect() {
74   DCHECK(client_task_runner_->BelongsToCurrentThread());
75 }
76 
GetState() const77 SignalStrategy::State DelegatingSignalStrategy::GetState() const {
78   DCHECK(client_task_runner_->BelongsToCurrentThread());
79   return CONNECTED;
80 }
81 
GetError() const82 SignalStrategy::Error DelegatingSignalStrategy::GetError() const {
83   DCHECK(client_task_runner_->BelongsToCurrentThread());
84   return OK;
85 }
86 
GetLocalAddress() const87 const SignalingAddress& DelegatingSignalStrategy::GetLocalAddress() const {
88   DCHECK(client_task_runner_->BelongsToCurrentThread());
89   return local_address_;
90 }
91 
AddListener(Listener * listener)92 void DelegatingSignalStrategy::AddListener(Listener* listener) {
93   DCHECK(client_task_runner_->BelongsToCurrentThread());
94   listeners_.AddObserver(listener);
95 }
96 
RemoveListener(Listener * listener)97 void DelegatingSignalStrategy::RemoveListener(Listener* listener) {
98   DCHECK(client_task_runner_->BelongsToCurrentThread());
99   listeners_.RemoveObserver(listener);
100 }
101 
SendStanza(std::unique_ptr<jingle_xmpp::XmlElement> stanza)102 bool DelegatingSignalStrategy::SendStanza(
103     std::unique_ptr<jingle_xmpp::XmlElement> stanza) {
104   DCHECK(client_task_runner_->BelongsToCurrentThread());
105   GetLocalAddress().SetInMessage(stanza.get(), SignalingAddress::FROM);
106   delegate_task_runner_->PostTask(
107       FROM_HERE, base::BindOnce(send_iq_callback_, stanza->Str()));
108   return true;
109 }
110 
SendMessage(const SignalingAddress & destination_address,const ftl::ChromotingMessage & message)111 bool DelegatingSignalStrategy::SendMessage(
112     const SignalingAddress& destination_address,
113     const ftl::ChromotingMessage& message) {
114   DCHECK(client_task_runner_->BelongsToCurrentThread());
115   NOTIMPLEMENTED();
116   return false;
117 }
118 
GetNextId()119 std::string DelegatingSignalStrategy::GetNextId() {
120   return base::NumberToString(base::RandUint64());
121 }
122 
123 }  // namespace remoting
124