Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Side by Side Diff: remoting/jingle_glue/jingle_client.cc

Issue 3167047: Jingle_glue bugfixes. (Closed)
Patch Set: - Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « remoting/jingle_glue/jingle_client.h ('k') | remoting/jingle_glue/jingle_client_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // TODO(ajwong): We assign and read from a few of the member variables on
6 // two threads. We need to audit this for thread safety.
7
8 #include "remoting/jingle_glue/jingle_client.h" 5 #include "remoting/jingle_glue/jingle_client.h"
9 6
10 #include "base/logging.h" 7 #include "base/logging.h"
11 #include "base/message_loop.h" 8 #include "base/message_loop.h"
12 #include "jingle/notifier/communicator/gaia_token_pre_xmpp_auth.h" 9 #include "jingle/notifier/communicator/gaia_token_pre_xmpp_auth.h"
13 #include "jingle/notifier/communicator/xmpp_socket_adapter.h" 10 #include "jingle/notifier/communicator/xmpp_socket_adapter.h"
14 #include "remoting/jingle_glue/iq_request.h" 11 #include "remoting/jingle_glue/iq_request.h"
15 #include "remoting/jingle_glue/jingle_thread.h" 12 #include "remoting/jingle_glue/jingle_thread.h"
16 #include "remoting/jingle_glue/relay_port_allocator.h" 13 #include "remoting/jingle_glue/relay_port_allocator.h"
17 #include "third_party/libjingle/source/talk/base/asyncsocket.h" 14 #include "third_party/libjingle/source/talk/base/asyncsocket.h"
18 #include "third_party/libjingle/source/talk/base/ssladapter.h" 15 #include "third_party/libjingle/source/talk/base/ssladapter.h"
19 #include "third_party/libjingle/source/talk/p2p/base/sessionmanager.h" 16 #include "third_party/libjingle/source/talk/p2p/base/sessionmanager.h"
17 #include "third_party/libjingle/source/talk/p2p/base/transport.h"
20 #include "third_party/libjingle/source/talk/p2p/client/sessionmanagertask.h" 18 #include "third_party/libjingle/source/talk/p2p/client/sessionmanagertask.h"
21 #ifdef USE_SSL_TUNNEL
22 #include "third_party/libjingle/source/talk/session/tunnel/securetunnelsessioncl ient.h"
23 #endif
24 #include "third_party/libjingle/source/talk/session/tunnel/tunnelsessionclient.h " 19 #include "third_party/libjingle/source/talk/session/tunnel/tunnelsessionclient.h "
25 #include "third_party/libjingle/source/talk/xmpp/prexmppauth.h" 20 #include "third_party/libjingle/source/talk/xmpp/prexmppauth.h"
26 #include "third_party/libjingle/source/talk/xmpp/saslcookiemechanism.h" 21 #include "third_party/libjingle/source/talk/xmpp/saslcookiemechanism.h"
27 22
28 namespace remoting { 23 namespace remoting {
29 24
25 namespace {
26 // A TunnelSessionClient that allows local connections.
27 class LocalTunnelSessionClient : public cricket::TunnelSessionClient {
28 public:
29 LocalTunnelSessionClient(const buzz::Jid& jid,
30 cricket::SessionManager* manager)
31 : TunnelSessionClient(jid, manager) {
32 }
33
34 protected:
35 virtual cricket::TunnelSession* MakeTunnelSession(
36 cricket::Session* session, talk_base::Thread* stream_thread,
37 cricket::TunnelSessionRole role) {
38 session->transport()->set_allow_local_ips(true);
39 return new cricket::TunnelSession(this, session, stream_thread);
40 }
41 };
42 } // namespace
43
30 JingleClient::JingleClient(JingleThread* thread) 44 JingleClient::JingleClient(JingleThread* thread)
31 : client_(NULL), 45 : thread_(thread),
32 thread_(thread), 46 callback_(NULL),
33 state_(CREATED), 47 client_(NULL),
34 callback_(NULL) { 48 state_(START),
49 initialized_(false),
50 closed_(false) {
35 } 51 }
36 52
37 JingleClient::~JingleClient() { 53 JingleClient::~JingleClient() {
38 // JingleClient can be destroyed only after it's closed. 54 AutoLock auto_lock(state_lock_);
39 DCHECK(state_ == CLOSED || state_ == CREATED); 55 DCHECK(!initialized_ || closed_);
40 } 56 }
41 57
42 void JingleClient::Init( 58 void JingleClient::Init(
43 const std::string& username, const std::string& auth_token, 59 const std::string& username, const std::string& auth_token,
44 const std::string& auth_token_service, Callback* callback) { 60 const std::string& auth_token_service, Callback* callback) {
45 DCHECK_NE(username, ""); 61 DCHECK_NE(username, "");
46 DCHECK(callback != NULL);
47 DCHECK(state_ == CREATED);
48 62
49 callback_ = callback; 63 {
64 AutoLock auto_lock(state_lock_);
65 DCHECK(!initialized_ && !closed_);
66 initialized_ = true;
67
68 DCHECK(callback != NULL);
69 callback_ = callback;
70 }
71
50 message_loop()->PostTask( 72 message_loop()->PostTask(
51 FROM_HERE, NewRunnableMethod(this, &JingleClient::DoInitialize, 73 FROM_HERE, NewRunnableMethod(this, &JingleClient::DoInitialize,
52 username, auth_token, auth_token_service)); 74 username, auth_token, auth_token_service));
53 state_ = INITIALIZED;
54 }
55
56 JingleChannel* JingleClient::Connect(const std::string& host_jid,
57 JingleChannel::Callback* callback) {
58 // Ownership if channel is given to DoConnect.
59 scoped_refptr<JingleChannel> channel = new JingleChannel(callback);
60 message_loop()->PostTask(
61 FROM_HERE, NewRunnableMethod(this, &JingleClient::DoConnect,
62 channel, host_jid, callback));
63 return channel;
64 }
65
66 void JingleClient::DoConnect(scoped_refptr<JingleChannel> channel,
67 const std::string& host_jid,
68 JingleChannel::Callback* callback) {
69 DCHECK_EQ(message_loop(), MessageLoop::current());
70
71 talk_base::StreamInterface* stream =
72 tunnel_session_client_->CreateTunnel(buzz::Jid(host_jid), "");
73 DCHECK(stream != NULL);
74
75 channel->Init(thread_, stream, host_jid);
76 }
77
78 void JingleClient::Close() {
79 // Once we are closed we really shouldn't talk to the callback again. In the
80 // case when JingleClient outlives the owner access the callback is not safe.
81 // TODO(hclam): We need to lock to reset callback.
82 callback_ = NULL;
83
84 message_loop()->PostTask(
85 FROM_HERE, NewRunnableMethod(this, &JingleClient::DoClose));
86 }
87
88 void JingleClient::DoClose() {
89 DCHECK_EQ(message_loop(), MessageLoop::current());
90
91 // If we have not yet initialized and the client is already closed then
92 // don't close again.
93 if (state_ == CLOSED)
94 return;
95
96 if (client_) {
97 client_->Disconnect();
98 // Client is deleted by TaskRunner.
99 client_ = NULL;
100 }
101 tunnel_session_client_.reset();
102 port_allocator_.reset();
103 session_manager_.reset();
104 network_manager_.reset();
105 UpdateState(CLOSED);
106 } 75 }
107 76
108 void JingleClient::DoInitialize(const std::string& username, 77 void JingleClient::DoInitialize(const std::string& username,
109 const std::string& auth_token, 78 const std::string& auth_token,
110 const std::string& auth_token_service) { 79 const std::string& auth_token_service) {
111 DCHECK_EQ(message_loop(), MessageLoop::current()); 80 DCHECK_EQ(message_loop(), MessageLoop::current());
112 81
113 buzz::Jid login_jid(username); 82 buzz::Jid login_jid(username);
114 83
115 buzz::XmppClientSettings settings; 84 buzz::XmppClientSettings settings;
(...skipping 15 matching lines...) Expand all
131 client_->Start(); 100 client_->Start();
132 101
133 network_manager_.reset(new talk_base::NetworkManager()); 102 network_manager_.reset(new talk_base::NetworkManager());
134 103
135 RelayPortAllocator* port_allocator = 104 RelayPortAllocator* port_allocator =
136 new RelayPortAllocator(network_manager_.get(), "transp2"); 105 new RelayPortAllocator(network_manager_.get(), "transp2");
137 port_allocator_.reset(port_allocator); 106 port_allocator_.reset(port_allocator);
138 port_allocator->SetJingleInfo(client_); 107 port_allocator->SetJingleInfo(client_);
139 108
140 session_manager_.reset(new cricket::SessionManager(port_allocator_.get())); 109 session_manager_.reset(new cricket::SessionManager(port_allocator_.get()));
141 #ifdef USE_SSL_TUNNEL 110
142 cricket::SecureTunnelSessionClient* session_client =
143 new cricket::SecureTunnelSessionClient(client_->jid(),
144 session_manager_.get());
145 if (!session_client->GenerateIdentity())
146 return false;
147 tunnel_session_client_.reset(session_client);
148 #else // !USE_SSL_TUNNEL
149 tunnel_session_client_.reset( 111 tunnel_session_client_.reset(
150 new cricket::TunnelSessionClient(client_->jid(), 112 new LocalTunnelSessionClient(client_->jid(),
151 session_manager_.get())); 113 session_manager_.get()));
152 #endif // USE_SSL_TUNNEL
153 114
154 cricket::SessionManagerTask* receiver = 115 cricket::SessionManagerTask* receiver =
155 new cricket::SessionManagerTask(client_, session_manager_.get()); 116 new cricket::SessionManagerTask(client_, session_manager_.get());
156 receiver->EnableOutgoingMessages(); 117 receiver->EnableOutgoingMessages();
157 receiver->Start(); 118 receiver->Start();
158 119
159 tunnel_session_client_->SignalIncomingTunnel.connect( 120 tunnel_session_client_->SignalIncomingTunnel.connect(
160 this, &JingleClient::OnIncomingTunnel); 121 this, &JingleClient::OnIncomingTunnel);
161 } 122 }
162 123
124 JingleChannel* JingleClient::Connect(const std::string& host_jid,
125 JingleChannel::Callback* callback) {
126 DCHECK(initialized_ && !closed_);
127
128 // Ownership if channel is given to DoConnect.
129 scoped_refptr<JingleChannel> channel = new JingleChannel(callback);
130 message_loop()->PostTask(
131 FROM_HERE, NewRunnableMethod(this, &JingleClient::DoConnect,
132 channel, host_jid, callback));
133 return channel;
134 }
135
136 void JingleClient::DoConnect(scoped_refptr<JingleChannel> channel,
137 const std::string& host_jid,
138 JingleChannel::Callback* callback) {
139 DCHECK_EQ(message_loop(), MessageLoop::current());
140
141 talk_base::StreamInterface* stream =
142 tunnel_session_client_->CreateTunnel(buzz::Jid(host_jid), "");
143 DCHECK(stream != NULL);
144
145 channel->Init(thread_, stream, host_jid);
146 }
147
148 void JingleClient::Close() {
149 Close(NULL);
150 }
151
152 void JingleClient::Close(Task* closed_task) {
153 {
154 AutoLock auto_lock(state_lock_);
155 // If the client is already closed then don't close again.
156 if (closed_) {
157 if (closed_task)
158 thread_->message_loop()->PostTask(FROM_HERE, closed_task);
159 return;
160 }
161 closed_task_.reset(closed_task);
162 closed_ = true;
163 }
164
165 message_loop()->PostTask(
166 FROM_HERE, NewRunnableMethod(this, &JingleClient::DoClose));
167 }
168
169 void JingleClient::DoClose() {
170 DCHECK_EQ(message_loop(), MessageLoop::current());
171 DCHECK(closed_);
172
173 tunnel_session_client_.reset();
174 session_manager_.reset();
175 port_allocator_.reset();
176 network_manager_.reset();
177
178 if (client_) {
179 client_->Disconnect();
180 // Client is deleted by TaskRunner.
181 client_ = NULL;
182 }
183
184 if (closed_task_.get()) {
185 closed_task_->Run();
186 closed_task_.reset();
187 }
188 }
189
163 std::string JingleClient::GetFullJid() { 190 std::string JingleClient::GetFullJid() {
164 AutoLock auto_lock(full_jid_lock_); 191 AutoLock auto_lock(full_jid_lock_);
165 return full_jid_; 192 return full_jid_;
166 } 193 }
167 194
168 IqRequest* JingleClient::CreateIqRequest() { 195 IqRequest* JingleClient::CreateIqRequest() {
169 return new IqRequest(this); 196 return new IqRequest(this);
170 } 197 }
171 198
172 MessageLoop* JingleClient::message_loop() { 199 MessageLoop* JingleClient::message_loop() {
173 return thread_->message_loop(); 200 return thread_->message_loop();
174 } 201 }
175 202
176 void JingleClient::OnConnectionStateChanged(buzz::XmppEngine::State state) { 203 void JingleClient::OnConnectionStateChanged(buzz::XmppEngine::State state) {
177 switch (state) { 204 switch (state) {
178 case buzz::XmppEngine::STATE_START: 205 case buzz::XmppEngine::STATE_START:
179 UpdateState(INITIALIZED); 206 UpdateState(START);
180 break; 207 break;
181 case buzz::XmppEngine::STATE_OPENING: 208 case buzz::XmppEngine::STATE_OPENING:
182 UpdateState(CONNECTING); 209 UpdateState(CONNECTING);
183 break; 210 break;
184 case buzz::XmppEngine::STATE_OPEN: 211 case buzz::XmppEngine::STATE_OPEN:
185 { 212 {
186 AutoLock auto_lock(full_jid_lock_); 213 AutoLock auto_lock(full_jid_lock_);
187 full_jid_ = client_->jid().Str(); 214 full_jid_ = client_->jid().Str();
188 } 215 }
189 UpdateState(CONNECTED); 216 UpdateState(CONNECTED);
190 break; 217 break;
191 case buzz::XmppEngine::STATE_CLOSED: 218 case buzz::XmppEngine::STATE_CLOSED:
192 UpdateState(CLOSED); 219 UpdateState(CLOSED);
193 break; 220 break;
194 default: 221 default:
195 NOTREACHED(); 222 NOTREACHED();
196 break; 223 break;
197 } 224 }
198 } 225 }
199 226
200 void JingleClient::OnIncomingTunnel( 227 void JingleClient::OnIncomingTunnel(
201 cricket::TunnelSessionClient* client, buzz::Jid jid, 228 cricket::TunnelSessionClient* client, buzz::Jid jid,
202 std::string description, cricket::Session* session) { 229 std::string description, cricket::Session* session) {
203 // Decline connection if we don't have callback. 230 // Must always lock state and check closed_ when calling callback.
204 if (!callback_) { 231 AutoLock auto_lock(state_lock_);
232
233 if (closed_) {
234 // Always reject connection if we are closed.
205 client->DeclineTunnel(session); 235 client->DeclineTunnel(session);
206 return; 236 return;
207 } 237 }
208 238
209 JingleChannel::Callback* channel_callback; 239 JingleChannel::Callback* channel_callback;
210 if (callback_->OnAcceptConnection(this, jid.Str(), &channel_callback)) { 240 if (callback_->OnAcceptConnection(this, jid.Str(), &channel_callback)) {
211 DCHECK(channel_callback != NULL); 241 DCHECK(channel_callback != NULL);
212 talk_base::StreamInterface* stream = client->AcceptTunnel(session); 242 talk_base::StreamInterface* stream = client->AcceptTunnel(session);
213 scoped_refptr<JingleChannel> channel(new JingleChannel(channel_callback)); 243 scoped_refptr<JingleChannel> channel(new JingleChannel(channel_callback));
214 channel->Init(thread_, stream, jid.Str()); 244 channel->Init(thread_, stream, jid.Str());
215 callback_->OnNewConnection(this, channel); 245 callback_->OnNewConnection(this, channel);
216 } else { 246 } else {
217 client->DeclineTunnel(session); 247 client->DeclineTunnel(session);
218 } 248 }
219 } 249 }
220 250
221 void JingleClient::UpdateState(State new_state) { 251 void JingleClient::UpdateState(State new_state) {
222 if (new_state != state_) { 252 if (new_state != state_) {
223 state_ = new_state; 253 state_ = new_state;
224 if (callback_) 254 {
225 callback_->OnStateChange(this, new_state); 255 AutoLock auto_lock(state_lock_);
256 if (!closed_)
257 callback_->OnStateChange(this, new_state);
258 }
226 } 259 }
227 } 260 }
228 261
229 buzz::PreXmppAuth* JingleClient::CreatePreXmppAuth( 262 buzz::PreXmppAuth* JingleClient::CreatePreXmppAuth(
230 const buzz::XmppClientSettings& settings) { 263 const buzz::XmppClientSettings& settings) {
231 buzz::Jid jid(settings.user(), settings.host(), buzz::STR_EMPTY); 264 buzz::Jid jid(settings.user(), settings.host(), buzz::STR_EMPTY);
232 return new notifier::GaiaTokenPreXmppAuth(jid.Str(), settings.auth_cookie(), 265 return new notifier::GaiaTokenPreXmppAuth(jid.Str(), settings.auth_cookie(),
233 settings.token_service()); 266 settings.token_service());
234 } 267 }
235 268
236 } // namespace remoting 269 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/jingle_glue/jingle_client.h ('k') | remoting/jingle_glue/jingle_client_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698