// 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 "build/build_config.h" #if !defined(OS_WIN) extern "C" { #include } #endif // !defined(OS_WIN) #include #include #include "base/at_exit.h" #include "base/nss_util.h" #include "base/time.h" #include "media/base/data_buffer.h" #include "remoting/base/constants.h" #include "remoting/jingle_glue/jingle_channel.h" #include "remoting/jingle_glue/jingle_client.h" #include "remoting/jingle_glue/jingle_thread.h" using remoting::JingleClient; using remoting::JingleChannel; using remoting::kChromotingTokenServiceName; class JingleTestClient : public JingleChannel::Callback, public JingleClient::Callback, public base::RefCountedThreadSafe { public: JingleTestClient() : closed_event_(true, false) { } virtual ~JingleTestClient() {} void Run(const std::string& username, const std::string& auth_token, const std::string& host_jid) { remoting::JingleThread jingle_thread; jingle_thread.Start(); client_ = new JingleClient(&jingle_thread); client_->Init(username, auth_token, kChromotingTokenServiceName, this); if (host_jid != "") { scoped_refptr channel = client_->Connect(host_jid, this); channels_.push_back(channel); } while (true) { std::string line; std::getline(std::cin, line); { AutoLock auto_lock(channels_lock_); // Broadcast message to all clients. for (ChannelsList::iterator it = channels_.begin(); it != channels_.end(); ++it) { uint8* buf = new uint8[line.length()]; memcpy(buf, line.c_str(), line.length()); (*it)->Write(new media::DataBuffer(buf, line.length())); } } if (line == "exit") break; } while (!channels_.empty()) { closed_event_.Reset(); channels_.front()->Close( NewRunnableMethod(this, &JingleTestClient::OnClosed)); // Wait until channel is closed. If it is not closed within 0.1 seconds // continue closing everything else. closed_event_.TimedWait(base::TimeDelta::FromMilliseconds(100)); channels_.pop_front(); } client_->Close(); jingle_thread.Stop(); } // JingleChannel::Callback interface. void OnStateChange(JingleChannel* channel, JingleChannel::State state) { LOG(INFO) << "State of " << channel->jid() << " changed to " << state; } void OnPacketReceived(JingleChannel* channel, scoped_refptr buffer) { std::string str(reinterpret_cast(buffer->GetData()), buffer->GetDataSize()); std::cout << "(" << channel->jid() << "): " << str << std::endl; } // JingleClient::Callback interface. void OnStateChange(JingleClient* client, JingleClient::State state) { if (state == JingleClient::CONNECTED) { std::cerr << "Connected as " << client->GetFullJid() << std::endl; } else if (state == JingleClient::CLOSED) { std::cerr << "Connection closed" << std::endl; } } bool OnAcceptConnection(JingleClient* client, const std::string& jid, JingleChannel::Callback** callback) { std::cerr << "Accepting new connection from " << jid << std::endl; *callback = this; return true; } void OnNewConnection(JingleClient* client, scoped_refptr channel) { std::cerr << "Connected to " << channel->jid() << std::endl; AutoLock auto_lock(channels_lock_); channels_.push_back(channel); } void OnClosed() { closed_event_.Signal(); } private: typedef std::list > ChannelsList; scoped_refptr client_; ChannelsList channels_; Lock channels_lock_; base::WaitableEvent closed_event_; }; int main(int argc, char** argv) { if (argc > 2) std::cerr << "Usage: " << argv[0] << " []" << std::endl; base::AtExitManager exit_manager; base::EnsureNSPRInit(); base::EnsureNSSInit(); std::string host_jid = argc == 2 ? argv[1] : ""; std::string username; std::cout << "JID: "; std::cin >> username; std::string auth_token; std::cout << "Auth token: "; std::cin >> auth_token; scoped_refptr client = new JingleTestClient(); client->Run(username, auth_token, host_jid); return 0; }