blob: 4157930bf59845f9fb1f923e761f6182935b5a04 [file] [log] [blame]
// 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 <unistd.h>
}
#endif // !defined(OS_WIN)
#include <iostream>
#include <list>
#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<JingleTestClient> {
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<JingleChannel> 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<media::DataBuffer> buffer) {
std::string str(reinterpret_cast<const char*>(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<JingleChannel> 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<scoped_refptr<JingleChannel> > ChannelsList;
scoped_refptr<JingleClient> client_;
ChannelsList channels_;
Lock channels_lock_;
base::WaitableEvent closed_event_;
};
int main(int argc, char** argv) {
if (argc > 2)
std::cerr << "Usage: " << argv[0] << " [<host_jid>]" << 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<JingleTestClient> client = new JingleTestClient();
client->Run(username, auth_token, host_jid);
return 0;
}