| Index: remoting/jingle_glue/jingle_client.cc
|
| ===================================================================
|
| --- remoting/jingle_glue/jingle_client.cc (revision 0)
|
| +++ remoting/jingle_glue/jingle_client.cc (revision 0)
|
| @@ -0,0 +1,227 @@
|
| +// Copyright (c) 2010 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 "remoting/jingle_glue/jingle_client.h"
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/waitable_event.h"
|
| +#include "base/message_loop.h"
|
| +#include "chrome/common/net/notifier/communicator/xmpp_socket_adapter.h"
|
| +#include "remoting/jingle_glue/jingle_thread.h"
|
| +#include "remoting/jingle_glue/relay_port_allocator.h"
|
| +#include "talk/base/asyncsocket.h"
|
| +#include "talk/base/ssladapter.h"
|
| +#include "talk/p2p/base/sessionmanager.h"
|
| +#include "talk/p2p/client/sessionmanagertask.h"
|
| +#ifdef USE_SSL_TUNNEL
|
| +#include "talk/session/tunnel/securetunnelsessionclient.h"
|
| +#endif
|
| +#include "talk/session/tunnel/tunnelsessionclient.h"
|
| +
|
| +namespace remoting {
|
| +
|
| +JingleClient::JingleClient()
|
| + : callback_(NULL),
|
| + state_(START) { }
|
| +
|
| +JingleClient::~JingleClient() {
|
| + // JingleClient can be destroyed only after it's closed.
|
| + DCHECK(state_ == CLOSED);
|
| +}
|
| +
|
| +void JingleClient::Init(const std::string& username,
|
| + const std::string& password,
|
| + Callback* callback) {
|
| + DCHECK(username != "");
|
| + DCHECK(callback != NULL);
|
| + DCHECK(thread_ == NULL); // Init() can be called only once.
|
| +
|
| + callback_ = callback;
|
| +
|
| + username_ = username;
|
| + password_ = password;
|
| +
|
| + thread_.reset(new JingleThread());
|
| + thread_->Start();
|
| + thread_->message_loop()->PostTask(
|
| + FROM_HERE, NewRunnableMethod(this, &JingleClient::DoInitialize));
|
| +}
|
| +
|
| +class JingleClient::ConnectRequest {
|
| + public:
|
| + ConnectRequest()
|
| + : completed_event_(true, false) { }
|
| +
|
| + JingleChannel* Wait() {
|
| + completed_event_.Wait();
|
| + return channel_;
|
| + };
|
| +
|
| + void Done(JingleChannel* channel) {
|
| + channel_ = channel;
|
| + completed_event_.Signal();
|
| + };
|
| +
|
| + private:
|
| + base::WaitableEvent completed_event_;
|
| + JingleChannel* channel_;
|
| +};
|
| +
|
| +JingleChannel* JingleClient::Connect(const std::string& host_jid,
|
| + JingleChannel::Callback* callback) {
|
| + ConnectRequest request;
|
| + thread_->message_loop()->PostTask(
|
| + FROM_HERE, NewRunnableMethod(this, &JingleClient::DoConnect,
|
| + &request, host_jid, callback));
|
| + return request.Wait();
|
| +}
|
| +
|
| +void JingleClient::DoConnect(ConnectRequest* request,
|
| + const std::string& host_jid,
|
| + JingleChannel::Callback* callback) {
|
| + talk_base::StreamInterface* stream =
|
| + tunnel_session_client_->CreateTunnel(buzz::Jid(host_jid), "");
|
| + DCHECK(stream != NULL);
|
| +
|
| + JingleChannel* channel = new JingleChannel(callback);
|
| + channel->Init(thread_.get(), stream, host_jid);
|
| + request->Done(channel);
|
| +}
|
| +
|
| +void JingleClient::Close() {
|
| + DCHECK(thread_ != NULL); // Close() be called only after Init().
|
| + message_loop()->PostTask(
|
| + FROM_HERE, NewRunnableMethod(this, &JingleClient::DoClose));
|
| + thread_->Stop();
|
| + thread_.reset(NULL);
|
| +}
|
| +
|
| +void JingleClient::DoClose() {
|
| + client_->Disconnect();
|
| + // Client is deleted by TaskRunner.
|
| + client_ = NULL;
|
| + tunnel_session_client_.reset();
|
| + port_allocator_.reset();
|
| + session_manager_.reset();
|
| + network_manager_.reset();
|
| + UpdateState(CLOSED);
|
| +}
|
| +
|
| +void JingleClient::DoInitialize() {
|
| + buzz::Jid login_jid(username_);
|
| + talk_base::InsecureCryptStringImpl password;
|
| + password.password() = password_;
|
| +
|
| + buzz::XmppClientSettings xcs;
|
| + xcs.set_user(login_jid.node());
|
| + xcs.set_host(login_jid.domain());
|
| + xcs.set_resource("chromoting");
|
| + xcs.set_use_tls(true);
|
| + xcs.set_pass(talk_base::CryptString(password));
|
| + xcs.set_server(talk_base::SocketAddress("talk.google.com", 5222));
|
| +
|
| + client_ = new buzz::XmppClient(thread_->task_pump());
|
| + client_->SignalStateChange.connect(
|
| + this, &JingleClient::OnConnectionStateChanged);
|
| +
|
| + buzz::AsyncSocket* socket =
|
| + new notifier::XmppSocketAdapter(xcs, false);
|
| +
|
| + client_->Connect(xcs, "", socket, NULL);
|
| + client_->Start();
|
| +
|
| + network_manager_.reset(new talk_base::NetworkManager());
|
| +
|
| + RelayPortAllocator* port_allocator =
|
| + new RelayPortAllocator(network_manager_.get(), "transp2");
|
| + port_allocator_.reset(port_allocator);
|
| + port_allocator->SetJingleInfo(client_);
|
| +
|
| + session_manager_.reset(new cricket::SessionManager(port_allocator_.get()));
|
| +#ifdef USE_SSL_TUNNEL
|
| + cricket::SecureTunnelSessionClient* session_client =
|
| + new cricket::SecureTunnelSessionClient(client_->jid(),
|
| + session_manager_.get());
|
| + if (!session_client->GenerateIdentity())
|
| + return false;
|
| + tunnel_session_client_.reset(session_client);
|
| +#else // !USE_SSL_TUNNEL
|
| + tunnel_session_client_.reset(
|
| + new cricket::TunnelSessionClient(client_->jid(),
|
| + session_manager_.get()));
|
| +#endif // USE_SSL_TUNNEL
|
| +
|
| + receiver_ = new cricket::SessionManagerTask(client_, session_manager_.get());
|
| + receiver_->EnableOutgoingMessages();
|
| + receiver_->Start();
|
| +
|
| + tunnel_session_client_->SignalIncomingTunnel.connect(
|
| + this, &JingleClient::OnIncomingTunnel);
|
| +}
|
| +
|
| +std::string JingleClient::GetFullJid() {
|
| + AutoLock auto_lock(full_jid_lock_);
|
| + return full_jid_;
|
| +}
|
| +
|
| +MessageLoop* JingleClient::message_loop() {
|
| + if (thread_ == NULL) {
|
| + return NULL;
|
| + }
|
| + return thread_->message_loop();
|
| +}
|
| +
|
| +void JingleClient::OnConnectionStateChanged(buzz::XmppEngine::State state) {
|
| + switch (state) {
|
| + case buzz::XmppEngine::STATE_START:
|
| + UpdateState(START);
|
| + break;
|
| + case buzz::XmppEngine::STATE_OPENING:
|
| + UpdateState(CONNECTING);
|
| + break;
|
| + case buzz::XmppEngine::STATE_OPEN:
|
| + {
|
| + AutoLock auto_lock(full_jid_lock_);
|
| + full_jid_ = client_->jid().Str();
|
| + }
|
| + UpdateState(CONNECTED);
|
| + break;
|
| + case buzz::XmppEngine::STATE_CLOSED:
|
| + UpdateState(CLOSED);
|
| + break;
|
| + }
|
| +}
|
| +
|
| +void JingleClient::OnIncomingTunnel(
|
| + cricket::TunnelSessionClient* client, buzz::Jid jid,
|
| + std::string description, cricket::Session* session) {
|
| + // Decline connection if we don't have callback.
|
| + if (!callback_) {
|
| + client->DeclineTunnel(session);
|
| + return;
|
| + }
|
| +
|
| + JingleChannel::Callback* channel_callback;
|
| + if (callback_->OnAcceptConnection(this, jid.Str(), &channel_callback)) {
|
| + DCHECK(channel_callback != NULL);
|
| + talk_base::StreamInterface* stream =
|
| + client->AcceptTunnel(session);
|
| + scoped_refptr<JingleChannel> channel(new JingleChannel(channel_callback));
|
| + channel->Init(thread_.get(), stream, jid.Str());
|
| + callback_->OnNewConnection(this, channel);
|
| + } else {
|
| + client->DeclineTunnel(session);
|
| + return;
|
| + }
|
| +}
|
| +
|
| +void JingleClient::UpdateState(State new_state) {
|
| + if (new_state != state_) {
|
| + state_ = new_state;
|
| + if (callback_)
|
| + callback_->OnStateChange(this, new_state);
|
| + }
|
| +}
|
| +
|
| +} // namespace remoting
|
|
|
| Property changes on: remoting/jingle_glue/jingle_client.cc
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|