Talk: Removes deprecated example apps and moves the server apps to trunk/talk/examples.

BUG=12545067
R=mallinath@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/7159004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@5397 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
henrike@webrtc.org 2014-01-16 16:49:53 +00:00
parent 0af1ffa84d
commit 2ce9a64b75
24 changed files with 3 additions and 3552 deletions

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.google.call</string>
<key>CFBundleName</key>
<string>chat</string>
</dict>
</plist>

View File

@ -1,159 +0,0 @@
/*
* libjingle
* Copyright 2004--2013, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//
// A simple text chat application, largely copied from examples/call.
//
#include <iostream>
#include "talk/base/logging.h"
#include "talk/base/ssladapter.h"
#ifdef OSX
#include "talk/base/maccocoasocketserver.h"
#elif defined(WIN32)
#include "talk/base/win32socketserver.h"
#else
#include "talk/base/physicalsocketserver.h"
#endif
#include "talk/xmpp/constants.h"
#include "talk/xmpp/xmppauth.h"
#include "talk/xmpp/xmppclientsettings.h"
#include "talk/xmpp/xmpppump.h"
#include "talk/xmpp/xmppsocket.h"
#include "talk/examples/chat/chatapp.h"
#include "talk/examples/chat/consoletask.h"
static const int kDefaultPort = 5222;
int main(int argc, char* argv[]) {
// TODO(pmclean): Remove duplication of code with examples/call.
// Set up debugging.
bool debug = true;
if (debug) {
talk_base::LogMessage::LogToDebug(talk_base::LS_VERBOSE);
}
// Set up the crypto subsystem.
talk_base::InitializeSSL();
// Parse username and password, if present.
buzz::Jid jid;
std::string username;
talk_base::InsecureCryptStringImpl pass;
if (argc > 1) {
username = argv[1];
if (argc > 2) {
pass.password() = argv[2];
}
}
// ... else prompt for them
if (username.empty()) {
printf("JID: ");
std::cin >> username;
}
if (username.find('@') == std::string::npos) {
username.append("@localhost");
}
jid = buzz::Jid(username);
if (!jid.IsValid() || jid.node() == "") {
printf("Invalid JID. JIDs should be in the form user@domain\n");
return 1;
}
if (pass.password().empty()) {
buzz::ConsoleTask::SetEcho(false);
printf("Password: ");
std::cin >> pass.password();
buzz::ConsoleTask::SetEcho(true);
printf("\n");
}
// OTP (this can be skipped)
std::string otp_token;
printf("OTP: ");
fflush(stdin);
std::getline(std::cin, otp_token);
// Setup the connection settings.
buzz::XmppClientSettings xcs;
xcs.set_user(jid.node());
xcs.set_resource("chat");
xcs.set_host(jid.domain());
bool allow_plain = false;
xcs.set_allow_plain(allow_plain);
xcs.set_use_tls(buzz::TLS_REQUIRED);
xcs.set_pass(talk_base::CryptString(pass));
if (!otp_token.empty() && *otp_token.c_str() != '\n') {
xcs.set_auth_token(buzz::AUTH_MECHANISM_OAUTH2, otp_token);
}
// Build the server spec
std::string host;
int port;
std::string server = "talk.google.com";
int colon = server.find(':');
if (colon == -1) {
host = server;
port = kDefaultPort;
} else {
host = server.substr(0, colon);
port = atoi(server.substr(colon + 1).c_str());
}
xcs.set_server(talk_base::SocketAddress(host, port));
talk_base::Thread* main_thread = talk_base::Thread::Current();
#if WIN32
// Need to pump messages on our main thread on Windows.
talk_base::Win32Thread w32_thread;
talk_base::ThreadManager::Instance()->SetCurrentThread(&w32_thread);
#elif defined(OSX)
talk_base::MacCocoaSocketServer ss;
talk_base::SocketServerScope ss_scope(&ss);
#else
talk_base::PhysicalSocketServer ss;
#endif
buzz::XmppPump* pump = new buzz::XmppPump();
ChatApp *client = new ChatApp(pump->client(), main_thread);
// Start pumping messages!
pump->DoLogin(xcs, new buzz::XmppSocket(buzz::TLS_REQUIRED), new XmppAuth());
main_thread->Run();
pump->DoDisconnect();
delete client;
return 0;
}

View File

@ -1,252 +0,0 @@
/*
* libjingle
* Copyright 2004--2013, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "talk/examples/chat/chatapp.h"
#include "talk/base/stringencode.h"
#include "talk/examples/chat/consoletask.h"
#include "talk/examples/chat/textchatsendtask.h"
#include "talk/examples/chat/textchatreceivetask.h"
#include "talk/xmpp/presenceouttask.h"
#include "talk/xmpp/presencereceivetask.h"
#ifdef WIN32
#define snprintf _snprintf
#endif
ChatApp::ChatApp(buzz::XmppClient* xmpp_client, talk_base::Thread* main_thread)
: xmpp_client_(xmpp_client),
presence_out_task_(),
presence_receive_task_(),
message_send_task_(),
message_received_task_(),
console_task_(new buzz::ConsoleTask(main_thread)),
ui_state_(STATE_BASE) {
xmpp_client_->SignalStateChange.connect(this, &ChatApp::OnStateChange);
console_task_->TextInputHandler.connect(this, &ChatApp::OnConsoleMessage);
console_task_->Start();
}
ChatApp::~ChatApp() {
if (presence_out_task_ != NULL) {
// Check out
BroadcastPresence(away);
}
}
void ChatApp::Quit() {
talk_base::Thread::Current()->Quit();
}
void ChatApp::OnXmppOpen() {
presence_out_task_.reset(new buzz::PresenceOutTask(xmpp_client_));
presence_receive_task_.reset(new buzz::PresenceReceiveTask(xmpp_client_));
presence_receive_task_->PresenceUpdate.connect(this,
&ChatApp::OnPresenceUpdate);
message_send_task_.reset(new buzz::TextChatSendTask(xmpp_client_));
message_received_task_.reset(new buzz::TextChatReceiveTask(xmpp_client_));
message_received_task_->SignalTextChatReceived.connect(
this, &ChatApp::OnTextMessage);
presence_out_task_->Start();
presence_receive_task_->Start();
message_send_task_->Start();
message_received_task_->Start();
}
void ChatApp::BroadcastPresence(PresenceState state) {
buzz::PresenceStatus status;
status.set_jid(xmpp_client_->jid());
status.set_available(state == online);
status.set_show(state == online ? buzz::PresenceStatus::SHOW_ONLINE
: buzz::PresenceStatus::SHOW_AWAY);
presence_out_task_->Send(status);
}
// UI Stuff
static const char* kMenuChoiceQuit = "0";
static const char* kMenuChoiceRoster = "1";
static const char* kMenuChoiceChat = "2";
static const char* kUIStrings[3][2] = {
{kMenuChoiceQuit, "Quit"},
{kMenuChoiceRoster, "Roster"},
{kMenuChoiceChat, "Send"}};
void ChatApp::PrintMenu() {
char buff[128];
int numMenuItems = sizeof(kUIStrings) / sizeof(kUIStrings[0]);
for (int index = 0; index < numMenuItems; ++index) {
snprintf(buff, sizeof(buff), "%s) %s\n", kUIStrings[index][0],
kUIStrings[index][1]);
console_task_->Print(buff);
}
console_task_->Print("choice:");
}
void ChatApp::PrintRoster() {
int index = 0;
for (RosterList::iterator iter = roster_list_.begin();
iter != roster_list_.end(); ++iter) {
const buzz::Jid& jid = iter->second.jid();
console_task_->Print(
"%d: (*) %s@%s [%s] \n",
index++,
jid.node().c_str(),
jid.domain().c_str(),
jid.resource().c_str());
}
}
void ChatApp::PromptJid() {
PrintRoster();
console_task_->Print("choice:");
}
void ChatApp::PromptChatMessage() {
console_task_->Print(":");
}
bool ChatApp::GetRosterItem(int index, buzz::PresenceStatus* status) {
int found_index = 0;
for (RosterList::iterator iter = roster_list_.begin();
iter != roster_list_.end() && found_index <= index; ++iter) {
if (found_index == index) {
*status = iter->second;
return true;
}
found_index++;
}
return false;
}
void ChatApp::HandleBaseInput(const std::string& message) {
if (message == kMenuChoiceQuit) {
Quit();
} else if (message == kMenuChoiceRoster) {
PrintRoster();
} else if (message == kMenuChoiceChat) {
ui_state_ = STATE_PROMPTJID;
PromptJid();
} else if (message == "") {
PrintMenu();
}
}
void ChatApp::HandleJidInput(const std::string& message) {
if (isdigit(message[0])) {
// It's an index-based roster choice.
int index = 0;
buzz::PresenceStatus status;
if (!talk_base::FromString(message, &index) ||
!GetRosterItem(index, &status)) {
// fail, so drop back
ui_state_ = STATE_BASE;
return;
}
chat_dest_jid_ = status.jid();
} else {
// It's an explicit address.
chat_dest_jid_ = buzz::Jid(message.c_str());
}
ui_state_ = STATE_CHATTING;
PromptChatMessage();
}
void ChatApp::HandleChatInput(const std::string& message) {
if (message == "") {
ui_state_ = STATE_BASE;
PrintMenu();
} else {
message_send_task_->Send(chat_dest_jid_, message);
PromptChatMessage();
}
}
// Connection state notifications
void ChatApp::OnStateChange(buzz::XmppEngine::State state) {
switch (state) {
// Nonexistent state
case buzz::XmppEngine::STATE_NONE:
break;
// Nonexistent state
case buzz::XmppEngine::STATE_START:
break;
// Exchanging stream headers, authenticating and so on.
case buzz::XmppEngine::STATE_OPENING:
break;
// Authenticated and bound.
case buzz::XmppEngine::STATE_OPEN:
OnXmppOpen();
BroadcastPresence(online);
PrintMenu();
break;
// Session closed, possibly due to error.
case buzz::XmppEngine::STATE_CLOSED:
break;
}
}
// Presence Notifications
void ChatApp::OnPresenceUpdate(const buzz::PresenceStatus& status) {
if (status.available()) {
roster_list_[status.jid().Str()] = status;
} else {
RosterList::iterator iter = roster_list_.find(status.jid().Str());
if (iter != roster_list_.end()) {
roster_list_.erase(iter);
}
}
}
// Text message handlers
void ChatApp::OnTextMessage(const buzz::Jid& from, const buzz::Jid& to,
const std::string& message) {
console_task_->Print("%s says: %s\n", from.node().c_str(), message.c_str());
}
void ChatApp::OnConsoleMessage(const std::string &message) {
switch (ui_state_) {
case STATE_BASE:
HandleBaseInput(message);
break;
case STATE_PROMPTJID:
HandleJidInput(message);
break;
case STATE_CHATTING:
HandleChatInput(message);
break;
}
}

View File

@ -1,171 +0,0 @@
/*
* libjingle
* Copyright 2004--2013, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TALK_EXAMPLES_CHAT_CHATAPP_H_
#define TALK_EXAMPLES_CHAT_CHATAPP_H_
#include "talk/base/thread.h"
#include "talk/base/scoped_ptr.h"
#include "talk/xmpp/jid.h"
#include "talk/xmpp/xmppclient.h"
namespace buzz {
class XmppClient;
class PresenceOutTask;
class PresenceReceiveTask;
class TextChatSendTask;
class TextChatReceiveTask;
class ConsoleTask;
class PresenceStatus;
}
// This is an example chat app for libjingle, showing how to use xmpp tasks,
// data, callbacks, etc. It has a simple text-based UI for logging in,
// sending and receiving messages, and printing the roster.
class ChatApp: public sigslot::has_slots<> {
public:
// Arguments:
// xmpp_client Points to the XmppClient for the communication channel
// (typically created by the XmppPump object).
// main_thread Wraps the application's main thread. Subsidiary threads
// for the various tasks will be forked off of this.
ChatApp(buzz::XmppClient* xmpp_client, talk_base::Thread* main_thread);
// Shuts down and releases all of the contained tasks/threads
~ChatApp();
// Shuts down the current thread and quits
void Quit();
private:
//
// Initialization
//
// Called explicitly after the connection to the chat server is established.
void OnXmppOpen();
//
// UI Stuff
//
// Prints the app main menu on the console.
// Called when ui_state_ == STATE_BASE.
void PrintMenu();
// Prints a numbered list of the logged-in user's roster on the console.
void PrintRoster();
// Prints a prompt for the user to enter either the index from the
// roster list of the user they wish to chat with, or a fully-qualified
// (user@server.ext) jid.
// Called when when ui_state_ == STATE_PROMPTJID.
void PromptJid();
// Prints a prompt on the console for the user to enter a message to send.
// Called when when ui_state_ == STATE_CHATTING.
void PromptChatMessage();
// Sends our presence state to the chat server (and on to your roster list).
// Arguments:
// state Specifies the presence state to show.
enum PresenceState {online, away};
void BroadcastPresence(PresenceState state);
// Returns the RosterItem associated with the specified index.
// Just a helper to select a roster item from a numbered list in the UI.
bool GetRosterItem(int index, buzz::PresenceStatus* status);
//
// Input Handling
//
// Receives input when ui_state_ == STATE_BASE. Handles choices from the
// main menu.
void HandleBaseInput(const std::string& message);
// Receives input when ui_state_ == STATE_PROMPTJID. Handles selection
// of a JID to chat to.
void HandleJidInput(const std::string& message);
// Receives input when ui_state_ == STATE_CHATTING. Handles text messages.
void HandleChatInput(const std::string& message);
//
// signal/slot Callbacks
//
// Connected to the XmppClient::SignalStateChange slot. Receives
// notifications of state changes of the connection.
void OnStateChange(buzz::XmppEngine::State state);
// Connected to the PresenceReceiveTask::PresenceUpdate slot.
// Receives status messages for the logged-in user's roster (i.e.
// an initial list from the server and people coming/going).
void OnPresenceUpdate(const buzz::PresenceStatus& status);
// Connected to the TextChatReceiveTask::SignalTextChatReceived slot.
// Called when we receive a text chat from someone else.
void OnTextMessage(const buzz::Jid& from, const buzz::Jid& to,
const std::string& message);
// Receives text input from the console task. This is where any input
// from the user comes in.
// Arguments:
// message What the user typed.
void OnConsoleMessage(const std::string &message);
// The XmppClient object associated with this chat application instance.
buzz::XmppClient* xmpp_client_;
// We send presence information through this object.
talk_base::scoped_ptr<buzz::PresenceOutTask> presence_out_task_;
// We receive others presence information through this object.
talk_base::scoped_ptr<buzz::PresenceReceiveTask> presence_receive_task_;
// We send text messages though this object.
talk_base::scoped_ptr<buzz::TextChatSendTask> message_send_task_;
// We receive messages through this object.
talk_base::scoped_ptr<buzz::TextChatReceiveTask> message_received_task_;
// UI gets drawn and receives input through this task.
talk_base::scoped_ptr< buzz::ConsoleTask> console_task_;
// The list of JIDs for the people in the logged-in users roster.
// RosterList roster_list_;
typedef std::map<std::string, buzz::PresenceStatus> RosterList;
RosterList roster_list_;
// The JID of the user currently being chatted with.
buzz::Jid chat_dest_jid_;
// UI State constants
enum UIState { STATE_BASE, STATE_PROMPTJID, STATE_CHATTING };
UIState ui_state_;
};
#endif // TALK_EXAMPLES_CHAT_CHATAPP_H_

View File

@ -1,177 +0,0 @@
/*
* libjingle
* Copyright 2004--2013, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// TODO(pmclean): Perhaps this should be unified with examples/call/console.cc
// and refactor to talk/base.
#include "talk/examples/chat/consoletask.h"
#define _CRT_SECURE_NO_DEPRECATE 1
#include <stdarg.h>
#ifdef POSIX
#include <signal.h>
#include <termios.h>
#include <unistd.h>
#endif // POSIX
#include <cassert>
#include "talk/base/logging.h"
#ifdef POSIX
static void DoNothing(int unused) {}
#endif
namespace buzz {
ConsoleTask::ConsoleTask(talk_base::Thread *thread) :
client_thread_(thread),
console_thread_(new talk_base::Thread()) {
}
ConsoleTask::~ConsoleTask() {
Stop();
}
void ConsoleTask::Start() {
if (!console_thread_) {
// stdin was closed in Stop(), so we can't restart.
LOG(LS_ERROR) << "Cannot re-start";
return;
}
if (console_thread_->started()) {
LOG(LS_WARNING) << "Already started";
return;
}
console_thread_->Start();
console_thread_->Post(this, MSG_START);
}
void ConsoleTask::Stop() {
if (console_thread_ && console_thread_->started()) {
#ifdef WIN32
CloseHandle(GetStdHandle(STD_INPUT_HANDLE));
#else
close(fileno(stdin));
// This forces the read() in fgets() to return with errno = EINTR. fgets()
// will retry the read() and fail, thus returning.
pthread_kill(console_thread_->GetPThread(), SIGUSR1);
#endif
console_thread_->Stop();
console_thread_.reset();
}
}
void ConsoleTask::SetEcho(bool on) {
#ifdef WIN32
HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
if ((hIn == INVALID_HANDLE_VALUE) || (hIn == NULL))
return;
DWORD mode;
if (!GetConsoleMode(hIn, &mode))
return;
if (on) {
mode = mode | ENABLE_ECHO_INPUT;
} else {
mode = mode & ~ENABLE_ECHO_INPUT;
}
SetConsoleMode(hIn, mode);
#else // MAC & LINUX
const int fd = fileno(stdin);
if (fd == -1) {
return;
}
struct termios tcflags;
if (tcgetattr(fd, &tcflags) == -1) {
return;
}
if (on) {
tcflags.c_lflag |= ECHO;
} else {
tcflags.c_lflag &= ~ECHO;
}
tcsetattr(fd, TCSANOW, &tcflags);
#endif
}
void ConsoleTask::Print(const char* format, ...) {
va_list ap;
va_start(ap, format);
char buf[4096];
int size = vsnprintf(buf, sizeof(buf), format, ap);
assert(size >= 0);
assert(size < static_cast<int>(sizeof(buf)));
buf[size] = '\0';
printf("%s", buf);
fflush(stdout);
va_end(ap);
}
void ConsoleTask::RunConsole() {
char input_buffer[128];
while (fgets(input_buffer, sizeof(input_buffer), stdin) != NULL) {
client_thread_->Post(this, MSG_INPUT,
new talk_base::TypedMessageData<std::string>(input_buffer));
}
}
void ConsoleTask::OnMessage(talk_base::Message *msg) {
switch (msg->message_id) {
case MSG_START:
#ifdef POSIX
// Install a no-op signal so that we can abort RunConsole() by raising
// SIGUSR1.
struct sigaction act;
act.sa_handler = &DoNothing;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (sigaction(SIGUSR1, &act, NULL) < 0) {
LOG(LS_WARNING) << "Can't install signal";
}
#endif
RunConsole();
break;
case MSG_INPUT:
talk_base::TypedMessageData<std::string> *data =
static_cast<talk_base::TypedMessageData<std::string>*>(msg->pdata);
// Trim off the .line-terminator to make processing easier.
std::string parsed_message =
data->data().substr(0, data->data().length() - 1);
TextInputHandler(parsed_message);
break;
}
}
} // namespace buzz

View File

@ -1,92 +0,0 @@
/*
* libjingle
* Copyright 2004--2013, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TALK_EXAMPLES_CHAT_CONSOLETASK_H_
#define TALK_EXAMPLES_CHAT_CONSOLETASK_H_
#include <cstdio>
#include "talk/base/thread.h"
#include "talk/base/sigslot.h"
namespace buzz {
//
// Provides properly threaded console I/O.
//
class ConsoleTask : public talk_base::MessageHandler {
public:
// Arguments:
// thread The main application thread. Input messages get posted through
// this.
explicit ConsoleTask(talk_base::Thread *thread);
// Shuts down the thread associated with this task.
~ConsoleTask();
// Slot for text inputs handler.
sigslot::signal1<const std::string&> TextInputHandler;
// Starts reading lines from the console and passes them to the
// TextInputHandler.
void Start();
// Stops reading lines and shuts down the thread. Cannot be restarted.
void Stop();
// Thread messages (especialy text-input messages) come in through here.
virtual void OnMessage(talk_base::Message *msg);
// printf() style output to the console.
void Print(const char* format, ...);
// Turns on/off the echo of input characters on the console.
// Arguments:
// on If true turns echo on, off otherwise.
static void SetEcho(bool on);
private:
/** Message IDs (for OnMessage()). */
enum {
MSG_START,
MSG_INPUT,
};
// Starts up polling for console input
void RunConsole();
// The main application thread
talk_base::Thread *client_thread_;
// The tread associated with this console object
talk_base::scoped_ptr<talk_base::Thread> console_thread_;
};
} // namespace buzz
#endif // TALK_EXAMPLES_CHAT_CONSOLETASK_H_

View File

@ -1,66 +0,0 @@
/*
* libjingle
* Copyright 2004--2013, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "talk/examples/chat/textchatreceivetask.h"
#include "talk/xmpp/constants.h"
namespace buzz {
TextChatReceiveTask::TextChatReceiveTask(XmppTaskParentInterface* parent)
: XmppTask(parent, XmppEngine::HL_TYPE) {
}
TextChatReceiveTask::~TextChatReceiveTask() {
Stop();
}
bool TextChatReceiveTask::HandleStanza(const XmlElement* stanza) {
// Make sure that this stanza is a message
if (stanza->Name() != QN_MESSAGE) {
return false;
}
// see if there is any body
const XmlElement* message_body = stanza->FirstNamed(QN_BODY);
if (message_body == NULL) {
return false;
}
// Looks good, so send the message text along.
SignalTextChatReceived(Jid(stanza->Attr(QN_FROM)), Jid(stanza->Attr(QN_TO)),
message_body->BodyText());
return true;
}
int TextChatReceiveTask::ProcessStart() {
// not queuing messages, so just block.
return STATE_BLOCKED;
}
} // namespace buzz

View File

@ -1,63 +0,0 @@
/*
* libjingle
* Copyright 2004--2013, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TALK_EXAMPLES_CHAT_TEXTCHATRECEIVETASK_H_
#define TALK_EXAMPLES_CHAT_TEXTCHATRECEIVETASK_H_
#include "talk/base/sigslot.h"
#include "talk/xmpp/xmpptask.h"
namespace buzz {
// A class to receive chat messages from the XMPP server.
class TextChatReceiveTask : public XmppTask {
public:
// Arguments:
// parent a reference to task interface associated withe the XMPP client.
explicit TextChatReceiveTask(XmppTaskParentInterface* parent);
// Shuts down the thread associated with this task.
virtual ~TextChatReceiveTask();
// Starts pulling queued status messages and dispatching them to the
// PresenceUpdate() callback.
virtual int ProcessStart();
// Slot for chat message callbacks
sigslot::signal3<const Jid&, const Jid&, const std::string&>
SignalTextChatReceived;
protected:
// Called by the XMPP client when chat stanzas arrive. We pull out the
// interesting parts and send them to the SignalTextCharReceived() slot.
virtual bool HandleStanza(const XmlElement* stanza);
};
} // namespace buzz
#endif // TALK_EXAMPLES_CHAT_TEXTCHATRECEIVETASK_H_

View File

@ -1,81 +0,0 @@
/*
* libjingle
* Copyright 2004--2013, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "talk/examples/chat/textchatsendtask.h"
#include "talk/xmpp/constants.h"
#include "talk/xmpp/xmppclient.h"
namespace buzz {
TextChatSendTask::TextChatSendTask(XmppTaskParentInterface* parent)
: XmppTask(parent) {
}
TextChatSendTask::~TextChatSendTask() {
Stop();
}
XmppReturnStatus TextChatSendTask::Send(const Jid& to,
const std::string& textmessage) {
// Make sure we are actually connected.
if (GetState() != STATE_INIT && GetState() != STATE_START) {
return XMPP_RETURN_BADSTATE;
}
// Put together the chat stanza...
XmlElement* message_stanza = new XmlElement(QN_MESSAGE);
// ... and specify the required attributes...
message_stanza->AddAttr(QN_TO, to.Str());
message_stanza->AddAttr(QN_TYPE, "chat");
message_stanza->AddAttr(QN_LANG, "en");
// ... and fill out the body.
XmlElement* message_body = new XmlElement(QN_BODY);
message_body->AddText(textmessage);
message_stanza->AddElement(message_body);
// Now queue it up.
QueueStanza(message_stanza);
return XMPP_RETURN_OK;
}
int TextChatSendTask::ProcessStart() {
const XmlElement* stanza = NextStanza();
if (stanza == NULL) {
return STATE_BLOCKED;
}
if (SendStanza(stanza) != XMPP_RETURN_OK) {
return STATE_ERROR;
}
return STATE_START;
}
} // namespace buzz

View File

@ -1,56 +0,0 @@
/*
* libjingle
* Copyright 2004--2013, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TALK_EXAMPLES_CHAT_TEXTCHATSENDTASK_H_
#define TALK_EXAMPLES_CHAT_TEXTCHATSENDTASK_H_
#include "talk/xmpp/xmpptask.h"
namespace buzz {
// A class to send chat messages to the XMPP server.
class TextChatSendTask : public XmppTask {
public:
// Arguments:
// parent a reference to task interface associated withe the XMPP client.
explicit TextChatSendTask(XmppTaskParentInterface* parent);
// Shuts down the thread associated with this task.
virtual ~TextChatSendTask();
// Forms the XMPP "chat" stanza with the specified receipient and message
// and queues it up.
XmppReturnStatus Send(const Jid& to, const std::string& message);
// Picks up any "chat" stanzas from our queue and sends them to the server.
virtual int ProcessStart();
};
} // namespace buzz
#endif // TALK_EXAMPLES_CHAT_TEXTCHATSENDTASK_H_

View File

@ -1,715 +0,0 @@
#define _CRT_SECURE_NO_DEPRECATE 1
#include <time.h>
#if defined(POSIX)
#include <unistd.h>
#endif
#include <iomanip>
#include <iostream>
#include <string>
#if HAVE_CONFIG_H
#include "config.h"
#endif // HAVE_CONFIG_H
#include "talk/base/sslconfig.h" // For SSL_USE_*
#if SSL_USE_OPENSSL
#define USE_SSL_TUNNEL
#endif
#include "talk/base/basicdefs.h"
#include "talk/base/common.h"
#include "talk/base/helpers.h"
#include "talk/base/logging.h"
#include "talk/base/ssladapter.h"
#include "talk/base/stringutils.h"
#include "talk/base/thread.h"
#include "talk/p2p/base/sessionmanager.h"
#include "talk/p2p/client/autoportallocator.h"
#include "talk/p2p/client/sessionmanagertask.h"
#include "talk/xmpp/xmppengine.h"
#ifdef USE_SSL_TUNNEL
#include "talk/session/tunnel/securetunnelsessionclient.h"
#endif
#include "talk/session/tunnel/tunnelsessionclient.h"
#include "talk/xmpp/xmppclient.h"
#include "talk/xmpp/xmppclientsettings.h"
#include "talk/xmpp/xmpppump.h"
#include "talk/xmpp/xmppsocket.h"
#ifndef MAX_PATH
#define MAX_PATH 256
#endif
#if defined(_MSC_VER) && (_MSC_VER < 1400)
// The following are necessary to properly link when compiling STL without
// /EHsc, otherwise known as C++ exceptions.
void __cdecl std::_Throw(const std::exception &) {}
std::_Prhand std::_Raise_handler = 0;
#endif
enum {
MSG_LOGIN_COMPLETE = 1,
MSG_LOGIN_FAILED,
MSG_DONE,
};
buzz::Jid gUserJid;
talk_base::InsecureCryptStringImpl gUserPass;
std::string gXmppHost = "talk.google.com";
int gXmppPort = 5222;
buzz::TlsOptions gXmppUseTls = buzz::TLS_REQUIRED;
class DebugLog : public sigslot::has_slots<> {
public:
DebugLog() :
debug_input_buf_(NULL), debug_input_len_(0), debug_input_alloc_(0),
debug_output_buf_(NULL), debug_output_len_(0), debug_output_alloc_(0),
censor_password_(false)
{}
char * debug_input_buf_;
int debug_input_len_;
int debug_input_alloc_;
char * debug_output_buf_;
int debug_output_len_;
int debug_output_alloc_;
bool censor_password_;
void Input(const char * data, int len) {
if (debug_input_len_ + len > debug_input_alloc_) {
char * old_buf = debug_input_buf_;
debug_input_alloc_ = 4096;
while (debug_input_alloc_ < debug_input_len_ + len) {
debug_input_alloc_ *= 2;
}
debug_input_buf_ = new char[debug_input_alloc_];
memcpy(debug_input_buf_, old_buf, debug_input_len_);
delete[] old_buf;
}
memcpy(debug_input_buf_ + debug_input_len_, data, len);
debug_input_len_ += len;
DebugPrint(debug_input_buf_, &debug_input_len_, false);
}
void Output(const char * data, int len) {
if (debug_output_len_ + len > debug_output_alloc_) {
char * old_buf = debug_output_buf_;
debug_output_alloc_ = 4096;
while (debug_output_alloc_ < debug_output_len_ + len) {
debug_output_alloc_ *= 2;
}
debug_output_buf_ = new char[debug_output_alloc_];
memcpy(debug_output_buf_, old_buf, debug_output_len_);
delete[] old_buf;
}
memcpy(debug_output_buf_ + debug_output_len_, data, len);
debug_output_len_ += len;
DebugPrint(debug_output_buf_, &debug_output_len_, true);
}
static bool
IsAuthTag(const char * str, size_t len) {
if (str[0] == '<' && str[1] == 'a' &&
str[2] == 'u' &&
str[3] == 't' &&
str[4] == 'h' &&
str[5] <= ' ') {
std::string tag(str, len);
if (tag.find("mechanism") != std::string::npos)
return true;
}
return false;
}
void
DebugPrint(char * buf, int * plen, bool output) {
int len = *plen;
if (len > 0) {
time_t tim = time(NULL);
struct tm * now = localtime(&tim);
char *time_string = asctime(now);
if (time_string) {
size_t time_len = strlen(time_string);
if (time_len > 0) {
time_string[time_len-1] = 0; // trim off terminating \n
}
}
LOG(INFO) << (output ? "SEND >>>>>>>>>>>>>>>>>>>>>>>>>" : "RECV <<<<<<<<<<<<<<<<<<<<<<<<<")
<< " : " << time_string;
bool indent;
int start = 0, nest = 3;
for (int i = 0; i < len; i += 1) {
if (buf[i] == '>') {
if ((i > 0) && (buf[i-1] == '/')) {
indent = false;
} else if ((start + 1 < len) && (buf[start + 1] == '/')) {
indent = false;
nest -= 2;
} else {
indent = true;
}
// Output a tag
LOG(INFO) << std::setw(nest) << " " << std::string(buf + start, i + 1 - start);
if (indent)
nest += 2;
// Note if it's a PLAIN auth tag
if (IsAuthTag(buf + start, i + 1 - start)) {
censor_password_ = true;
}
// incr
start = i + 1;
}
if (buf[i] == '<' && start < i) {
if (censor_password_) {
LOG(INFO) << std::setw(nest) << " " << "## TEXT REMOVED ##";
censor_password_ = false;
}
else {
LOG(INFO) << std::setw(nest) << " " << std::string(buf + start, i - start);
}
start = i;
}
}
len = len - start;
memcpy(buf, buf + start, len);
*plen = len;
}
}
};
static DebugLog debug_log_;
// Prints out a usage message then exits.
void Usage() {
std::cerr << "Usage:" << std::endl;
std::cerr << " pcp [options] <my_jid> (server mode)" << std::endl;
std::cerr << " pcp [options] <my_jid> <src_file> <dst_full_jid>:<dst_file> (client sending)" << std::endl;
std::cerr << " pcp [options] <my_jid> <src_full_jid>:<src_file> <dst_file> (client rcv'ing)" << std::endl;
std::cerr << " --verbose" << std::endl;
std::cerr << " --xmpp-host=<host>" << std::endl;
std::cerr << " --xmpp-port=<port>" << std::endl;
std::cerr << " --xmpp-use-tls=(true|false)" << std::endl;
exit(1);
}
// Prints out an error message, a usage message, then exits.
void Error(const std::string& msg) {
std::cerr << "error: " << msg << std::endl;
std::cerr << std::endl;
Usage();
}
void FatalError(const std::string& msg) {
std::cerr << "error: " << msg << std::endl;
std::cerr << std::endl;
exit(1);
}
// Determines whether the given string is an option. If so, the name and
// value are appended to the given strings.
bool ParseArg(const char* arg, std::string* name, std::string* value) {
if (strncmp(arg, "--", 2) != 0)
return false;
const char* eq = strchr(arg + 2, '=');
if (eq) {
if (name)
name->append(arg + 2, eq);
if (value)
value->append(eq + 1, arg + strlen(arg));
} else {
if (name)
name->append(arg + 2, arg + strlen(arg));
if (value)
value->clear();
}
return true;
}
int ParseIntArg(const std::string& name, const std::string& value) {
char* end;
long val = strtol(value.c_str(), &end, 10);
if (*end != '\0')
Error(std::string("value of option ") + name + " must be an integer");
return static_cast<int>(val);
}
#ifdef WIN32
#pragma warning(push)
// disable "unreachable code" warning b/c it varies between dbg and opt
#pragma warning(disable: 4702)
#endif
bool ParseBoolArg(const std::string& name, const std::string& value) {
if (value == "true")
return true;
else if (value == "false")
return false;
else {
Error(std::string("value of option ") + name + " must be true or false");
return false;
}
}
#ifdef WIN32
#pragma warning(pop)
#endif
void ParseFileArg(const char* arg, buzz::Jid* jid, std::string* file) {
const char* sep = strchr(arg, ':');
if (!sep) {
*file = arg;
} else {
buzz::Jid jid_arg(std::string(arg, sep-arg));
if (jid_arg.IsBare())
Error("A full JID is required for the source or destination arguments.");
*jid = jid_arg;
*file = std::string(sep+1);
}
}
void SetConsoleEcho(bool on) {
#ifdef WIN32
HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
if ((hIn == INVALID_HANDLE_VALUE) || (hIn == NULL))
return;
DWORD mode;
if (!GetConsoleMode(hIn, &mode))
return;
if (on) {
mode = mode | ENABLE_ECHO_INPUT;
} else {
mode = mode & ~ENABLE_ECHO_INPUT;
}
SetConsoleMode(hIn, mode);
#else
int re;
if (on)
re = system("stty echo");
else
re = system("stty -echo");
if (-1 == re)
return;
#endif
}
// Fills in a settings object with the values from the arguments.
buzz::XmppClientSettings LoginSettings() {
buzz::XmppClientSettings xcs;
xcs.set_user(gUserJid.node());
xcs.set_host(gUserJid.domain());
xcs.set_resource("pcp");
xcs.set_pass(talk_base::CryptString(gUserPass));
talk_base::SocketAddress server(gXmppHost, gXmppPort);
xcs.set_server(server);
xcs.set_use_tls(gXmppUseTls);
return xcs;
}
// Runs the current thread until a message with the given ID is seen.
uint32 Loop(const std::vector<uint32>& ids) {
talk_base::Message msg;
while (talk_base::Thread::Current()->Get(&msg)) {
if (msg.phandler == NULL) {
if (std::find(ids.begin(), ids.end(), msg.message_id) != ids.end())
return msg.message_id;
std::cout << "orphaned message: " << msg.message_id;
continue;
}
talk_base::Thread::Current()->Dispatch(&msg);
}
return 0;
}
#ifdef WIN32
#pragma warning(disable:4355)
#endif
class CustomXmppPump : public buzz::XmppPumpNotify, public buzz::XmppPump {
public:
CustomXmppPump() : XmppPump(this), server_(false) { }
void Serve(cricket::TunnelSessionClient* client) {
client->SignalIncomingTunnel.connect(this,
&CustomXmppPump::OnIncomingTunnel);
server_ = true;
}
void OnStateChange(buzz::XmppEngine::State state) {
switch (state) {
case buzz::XmppEngine::STATE_START:
std::cout << "connecting..." << std::endl;
break;
case buzz::XmppEngine::STATE_OPENING:
std::cout << "logging in..." << std::endl;
break;
case buzz::XmppEngine::STATE_OPEN:
std::cout << "logged in..." << std::endl;
talk_base::Thread::Current()->Post(NULL, MSG_LOGIN_COMPLETE);
break;
case buzz::XmppEngine::STATE_CLOSED:
std::cout << "logged out..." << std::endl;
talk_base::Thread::Current()->Post(NULL, MSG_LOGIN_FAILED);
break;
}
}
void OnIncomingTunnel(cricket::TunnelSessionClient* client, buzz::Jid jid,
std::string description, cricket::Session* session) {
std::cout << "IncomingTunnel from " << jid.Str()
<< ": " << description << std::endl;
if (!server_ || file_) {
client->DeclineTunnel(session);
return;
}
std::string filename;
bool send;
if (strncmp(description.c_str(), "send:", 5) == 0) {
send = true;
} else if (strncmp(description.c_str(), "recv:", 5) == 0) {
send = false;
} else {
client->DeclineTunnel(session);
return;
}
filename = description.substr(5);
talk_base::StreamInterface* stream = client->AcceptTunnel(session);
if (!ProcessStream(stream, filename, send))
talk_base::Thread::Current()->Post(NULL, MSG_DONE);
// TODO: There is a potential memory leak, however, since the PCP
// app doesn't work right now, I can't verify the fix actually works, so
// comment out the following line until we fix the PCP app.
// delete stream;
}
bool ProcessStream(talk_base::StreamInterface* stream,
const std::string& filename, bool send) {
ASSERT(file_);
sending_ = send;
file_.reset(new talk_base::FileStream);
buffer_len_ = 0;
int err;
if (!file_->Open(filename.c_str(), sending_ ? "rb" : "wb", &err)) {
std::cerr << "Error opening <" << filename << ">: "
<< std::strerror(err) << std::endl;
return false;
}
stream->SignalEvent.connect(this, &CustomXmppPump::OnStreamEvent);
if (stream->GetState() == talk_base::SS_CLOSED) {
std::cerr << "Failed to establish P2P tunnel" << std::endl;
return false;
}
if (stream->GetState() == talk_base::SS_OPEN) {
OnStreamEvent(stream,
talk_base::SE_OPEN | talk_base::SE_READ | talk_base::SE_WRITE, 0);
}
return true;
}
void OnStreamEvent(talk_base::StreamInterface* stream, int events,
int error) {
if (events & talk_base::SE_CLOSE) {
if (error == 0) {
std::cout << "Tunnel closed normally" << std::endl;
} else {
std::cout << "Tunnel closed with error: " << error << std::endl;
}
Cleanup(stream);
return;
}
if (events & talk_base::SE_OPEN) {
std::cout << "Tunnel connected" << std::endl;
}
talk_base::StreamResult result;
size_t count;
if (sending_ && (events & talk_base::SE_WRITE)) {
LOG(LS_VERBOSE) << "Tunnel SE_WRITE";
while (true) {
size_t write_pos = 0;
while (write_pos < buffer_len_) {
result = stream->Write(buffer_ + write_pos, buffer_len_ - write_pos,
&count, &error);
if (result == talk_base::SR_SUCCESS) {
write_pos += count;
continue;
}
if (result == talk_base::SR_BLOCK) {
buffer_len_ -= write_pos;
memmove(buffer_, buffer_ + write_pos, buffer_len_);
LOG(LS_VERBOSE) << "Tunnel write block";
return;
}
if (result == talk_base::SR_EOS) {
std::cout << "Tunnel closed unexpectedly on write" << std::endl;
} else {
std::cout << "Tunnel write error: " << error << std::endl;
}
Cleanup(stream);
return;
}
buffer_len_ = 0;
while (buffer_len_ < sizeof(buffer_)) {
result = file_->Read(buffer_ + buffer_len_,
sizeof(buffer_) - buffer_len_,
&count, &error);
if (result == talk_base::SR_SUCCESS) {
buffer_len_ += count;
continue;
}
if (result == talk_base::SR_EOS) {
if (buffer_len_ > 0)
break;
std::cout << "End of file" << std::endl;
// A hack until we have friendly shutdown
Cleanup(stream, true);
return;
} else if (result == talk_base::SR_BLOCK) {
std::cout << "File blocked unexpectedly on read" << std::endl;
} else {
std::cout << "File read error: " << error << std::endl;
}
Cleanup(stream);
return;
}
}
}
if (!sending_ && (events & talk_base::SE_READ)) {
LOG(LS_VERBOSE) << "Tunnel SE_READ";
while (true) {
buffer_len_ = 0;
while (buffer_len_ < sizeof(buffer_)) {
result = stream->Read(buffer_ + buffer_len_,
sizeof(buffer_) - buffer_len_,
&count, &error);
if (result == talk_base::SR_SUCCESS) {
buffer_len_ += count;
continue;
}
if (result == talk_base::SR_BLOCK) {
if (buffer_len_ > 0)
break;
LOG(LS_VERBOSE) << "Tunnel read block";
return;
}
if (result == talk_base::SR_EOS) {
std::cout << "Tunnel closed unexpectedly on read" << std::endl;
} else {
std::cout << "Tunnel read error: " << error << std::endl;
}
Cleanup(stream);
return;
}
size_t write_pos = 0;
while (write_pos < buffer_len_) {
result = file_->Write(buffer_ + write_pos, buffer_len_ - write_pos,
&count, &error);
if (result == talk_base::SR_SUCCESS) {
write_pos += count;
continue;
}
if (result == talk_base::SR_EOS) {
std::cout << "File closed unexpectedly on write" << std::endl;
} else if (result == talk_base::SR_BLOCK) {
std::cout << "File blocked unexpectedly on write" << std::endl;
} else {
std::cout << "File write error: " << error << std::endl;
}
Cleanup(stream);
return;
}
}
}
}
void Cleanup(talk_base::StreamInterface* stream, bool delay = false) {
LOG(LS_VERBOSE) << "Closing";
stream->Close();
file_.reset();
if (!server_) {
if (delay)
talk_base::Thread::Current()->PostDelayed(2000, NULL, MSG_DONE);
else
talk_base::Thread::Current()->Post(NULL, MSG_DONE);
}
}
private:
bool server_, sending_;
talk_base::scoped_ptr<talk_base::FileStream> file_;
char buffer_[1024 * 64];
size_t buffer_len_;
};
int main(int argc, char **argv) {
talk_base::LogMessage::LogThreads();
talk_base::LogMessage::LogTimestamps();
// TODO: Default the username to the current users's name.
// Parse the arguments.
int index = 1;
while (index < argc) {
std::string name, value;
if (!ParseArg(argv[index], &name, &value))
break;
if (name == "help") {
Usage();
} else if (name == "verbose") {
talk_base::LogMessage::LogToDebug(talk_base::LS_VERBOSE);
} else if (name == "xmpp-host") {
gXmppHost = value;
} else if (name == "xmpp-port") {
gXmppPort = ParseIntArg(name, value);
} else if (name == "xmpp-use-tls") {
gXmppUseTls = ParseBoolArg(name, value)?
buzz::TLS_REQUIRED : buzz::TLS_DISABLED;
} else {
Error(std::string("unknown option: ") + name);
}
index += 1;
}
if (index >= argc)
Error("bad arguments");
gUserJid = buzz::Jid(argv[index++]);
if (!gUserJid.IsValid())
Error("bad arguments");
char path[MAX_PATH];
#if WIN32
GetCurrentDirectoryA(MAX_PATH, path);
#else
if (NULL == getcwd(path, MAX_PATH))
Error("Unable to get current path");
#endif
std::cout << "Directory: " << std::string(path) << std::endl;
buzz::Jid gSrcJid;
buzz::Jid gDstJid;
std::string gSrcFile;
std::string gDstFile;
bool as_server = true;
if (index + 2 == argc) {
ParseFileArg(argv[index], &gSrcJid, &gSrcFile);
ParseFileArg(argv[index+1], &gDstJid, &gDstFile);
if(gSrcJid.Str().empty() == gDstJid.Str().empty())
Error("Exactly one of source JID or destination JID must be empty.");
as_server = false;
} else if (index != argc) {
Error("bad arguments");
}
std::cout << "Password: ";
SetConsoleEcho(false);
std::cin >> gUserPass.password();
SetConsoleEcho(true);
std::cout << std::endl;
talk_base::InitializeSSL();
// Log in.
CustomXmppPump pump;
pump.client()->SignalLogInput.connect(&debug_log_, &DebugLog::Input);
pump.client()->SignalLogOutput.connect(&debug_log_, &DebugLog::Output);
pump.DoLogin(LoginSettings(), new buzz::XmppSocket(gXmppUseTls), 0);
//new XmppAuth());
// Wait until login succeeds.
std::vector<uint32> ids;
ids.push_back(MSG_LOGIN_COMPLETE);
ids.push_back(MSG_LOGIN_FAILED);
if (MSG_LOGIN_FAILED == Loop(ids))
FatalError("Failed to connect");
{
talk_base::scoped_ptr<buzz::XmlElement> presence(
new buzz::XmlElement(buzz::QN_PRESENCE));
presence->AddElement(new buzz::XmlElement(buzz::QN_PRIORITY));
presence->AddText("-1", 1);
pump.SendStanza(presence.get());
}
std::string user_jid_str = pump.client()->jid().Str();
std::cout << "Logged in as " << user_jid_str << std::endl;
// Prepare the random number generator.
talk_base::InitRandom(user_jid_str.c_str(), user_jid_str.size());
// Create the P2P session manager.
talk_base::BasicNetworkManager network_manager;
AutoPortAllocator allocator(&network_manager, "pcp_agent");
allocator.SetXmppClient(pump.client());
cricket::SessionManager session_manager(&allocator);
#ifdef USE_SSL_TUNNEL
cricket::SecureTunnelSessionClient session_client(pump.client()->jid(),
&session_manager);
if (!session_client.GenerateIdentity())
FatalError("Failed to generate SSL identity");
#else // !USE_SSL_TUNNEL
cricket::TunnelSessionClient session_client(pump.client()->jid(),
&session_manager);
#endif // USE_SSL_TUNNEL
cricket::SessionManagerTask *receiver =
new cricket::SessionManagerTask(pump.client(), &session_manager);
receiver->EnableOutgoingMessages();
receiver->Start();
bool success = true;
// Establish the appropriate connection.
if (as_server) {
pump.Serve(&session_client);
} else {
talk_base::StreamInterface* stream = NULL;
std::string filename;
bool sending;
if (gSrcJid.Str().empty()) {
std::string message("recv:");
message.append(gDstFile);
stream = session_client.CreateTunnel(gDstJid, message);
filename = gSrcFile;
sending = true;
} else {
std::string message("send:");
message.append(gSrcFile);
stream = session_client.CreateTunnel(gSrcJid, message);
filename = gDstFile;
sending = false;
}
success = pump.ProcessStream(stream, filename, sending);
}
if (success) {
// Wait until the copy is done.
ids.clear();
ids.push_back(MSG_DONE);
ids.push_back(MSG_LOGIN_FAILED);
Loop(ids);
}
// Log out.
pump.DoDisconnect();
return 0;
}

View File

@ -1,736 +0,0 @@
/*
* libjingle
* Copyright 2006, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include "libjingleplus.h"
#ifdef WIN32
#include "talk/base/win32socketserver.h"
#endif
#include "talk/base/physicalsocketserver.h"
#include "talk/base/logging.h"
#include "talk/examples/login/xmppauth.h"
#include "talk/examples/login/xmppsocket.h"
#include "talk/examples/login/xmpppump.h"
#include "presencepushtask.h"
#include "talk/app/status.h"
#include "talk/app/message.h"
#include "rostertask.h"
#include "talk/app/iqtask.h"
#include "talk/app/presenceouttask.h"
#include "talk/app/receivemessagetask.h"
#include "talk/app/rostersettask.h"
#include "talk/app/sendmessagetask.h"
enum {
MSG_START,
// main thread to worker
MSG_LOGIN,
MSG_DISCONNECT,
MSG_SEND_PRESENCE,
MSG_SEND_DIRECTED_PRESENCE,
MSG_SEND_DIRECTED_MUC_PRESENCE,
MSG_SEND_XMPP_MESSAGE,
MSG_SEND_XMPP_IQ,
MSG_UPDATE_ROSTER_ITEM,
MSG_REMOVE_ROSTER_ITEM,
// worker thread to main thread
MSG_STATE_CHANGE,
MSG_STATUS_UPDATE,
MSG_STATUS_ERROR,
MSG_ROSTER_REFRESH_STARTED,
MSG_ROSTER_REFRESH_FINISHED,
MSG_ROSTER_ITEM_UPDATED,
MSG_ROSTER_ITEM_REMOVED,
MSG_ROSTER_SUBSCRIBE,
MSG_ROSTER_UNSUBSCRIBE,
MSG_ROSTER_SUBSCRIBED,
MSG_ROSTER_UNSUBSCRIBED,
MSG_INCOMING_MESSAGE,
MSG_IQ_COMPLETE,
MSG_XMPP_INPUT,
MSG_XMPP_OUTPUT
};
class LibjinglePlusWorker : public talk_base::MessageHandler,
public XmppPumpNotify,
public sigslot::has_slots<> {
public:
LibjinglePlusWorker(LibjinglePlus *ljp, LibjinglePlusNotify *notify) :
worker_thread_(NULL), ljp_(ljp), notify_(notify),
ppt_(NULL), rmt_(NULL), rt_(NULL), is_test_login_(false) {
main_thread_.reset(new talk_base::AutoThread());
#ifdef WIN32
ss_.reset(new talk_base::Win32SocketServer(main_thread_.get()));
main_thread_->set_socketserver(ss_.get());
#endif
pump_.reset(new XmppPump(this));
pump_->client()->SignalLogInput.connect(this, &LibjinglePlusWorker::OnInputDebug);
pump_->client()->SignalLogOutput.connect(this, &LibjinglePlusWorker::OnOutputDebug);
//pump_->client()->SignalStateChange.connect(this, &LibjinglePlusWorker::OnStateChange);
}
~LibjinglePlusWorker() {
if (worker_thread_) {
worker_thread_->Send(this, MSG_DISCONNECT);
delete worker_thread_;
}
}
virtual void OnMessage(talk_base::Message *msg) {
switch (msg->message_id) {
case MSG_START:
LoginW();
break;
case MSG_DISCONNECT:
DisconnectW();
break;
case MSG_SEND_XMPP_MESSAGE:
SendXmppMessageW(static_cast<SendMessageData*>(msg->pdata)->m_);
delete msg->pdata;
break;
case MSG_SEND_XMPP_IQ:
SendXmppIqW(static_cast<SendIqData*>(msg->pdata)->to_jid_,
static_cast<SendIqData*>(msg->pdata)->is_get_,
static_cast<SendIqData*>(msg->pdata)->xml_element_);
delete msg->pdata;
break;
case MSG_SEND_PRESENCE:
SendPresenceW(static_cast<SendPresenceData*>(msg->pdata)->s_);
delete msg->pdata;
break;
case MSG_SEND_DIRECTED_PRESENCE:
SendDirectedPresenceW(static_cast<SendDirectedPresenceData*>(msg->pdata)->j_,
static_cast<SendDirectedPresenceData*>(msg->pdata)->s_);
delete msg->pdata;
break;
case MSG_SEND_DIRECTED_MUC_PRESENCE:
SendDirectedMUCPresenceW(static_cast<SendDirectedMUCPresenceData*>(msg->pdata)->j_,
static_cast<SendDirectedMUCPresenceData*>(msg->pdata)->s_,
static_cast<SendDirectedMUCPresenceData*>(msg->pdata)->un_,
static_cast<SendDirectedMUCPresenceData*>(msg->pdata)->ac_,
static_cast<SendDirectedMUCPresenceData*>(msg->pdata)->am_,
static_cast<SendDirectedMUCPresenceData*>(msg->pdata)->role_);
delete msg->pdata;
break;
case MSG_UPDATE_ROSTER_ITEM:
UpdateRosterItemW(static_cast<UpdateRosterItemData*>(msg->pdata)->jid_,
static_cast<UpdateRosterItemData*>(msg->pdata)->n_,
static_cast<UpdateRosterItemData*>(msg->pdata)->g_,
static_cast<UpdateRosterItemData*>(msg->pdata)->grt_);
delete msg->pdata;
break;
case MSG_REMOVE_ROSTER_ITEM:
RemoveRosterItemW(static_cast<JidData*>(msg->pdata)->jid_);
delete msg->pdata;
break;
case MSG_STATUS_UPDATE:
OnStatusUpdateW(static_cast<SendPresenceData*>(msg->pdata)->s_);
delete msg->pdata;
break;
case MSG_STATUS_ERROR:
OnStatusErrorW(static_cast<StatusErrorData*>(msg->pdata)->stanza_);
delete msg->pdata;
break;
case MSG_STATE_CHANGE:
OnStateChangeW(static_cast<StateChangeData*>(msg->pdata)->s_);
delete msg->pdata;
break;
case MSG_ROSTER_REFRESH_STARTED:
OnRosterRefreshStartedW();
break;
case MSG_ROSTER_REFRESH_FINISHED:
OnRosterRefreshFinishedW();
break;
case MSG_ROSTER_ITEM_UPDATED:
OnRosterItemUpdatedW(static_cast<RosterItemData*>(msg->pdata)->ri_);
delete msg->pdata;
break;
case MSG_ROSTER_ITEM_REMOVED:
OnRosterItemRemovedW(static_cast<RosterItemData*>(msg->pdata)->ri_);
delete msg->pdata;
break;
case MSG_ROSTER_SUBSCRIBE:
OnRosterSubscribeW(static_cast<JidData*>(msg->pdata)->jid_);
delete msg->pdata;
break;
case MSG_ROSTER_UNSUBSCRIBE:
OnRosterUnsubscribeW(static_cast<JidData*>(msg->pdata)->jid_);
delete msg->pdata;
break;
case MSG_ROSTER_SUBSCRIBED:
OnRosterSubscribedW(static_cast<JidData*>(msg->pdata)->jid_);
delete msg->pdata;
break;
case MSG_ROSTER_UNSUBSCRIBED:
OnRosterUnsubscribedW(static_cast<JidData*>(msg->pdata)->jid_);
delete msg->pdata;
break;
case MSG_INCOMING_MESSAGE:
OnIncomingMessageW(static_cast<XmppMessageData*>(msg->pdata)->m_);
delete msg->pdata;
break;
case MSG_IQ_COMPLETE:
OnIqCompleteW(static_cast<IqCompleteData*>(msg->pdata)->success_,
static_cast<IqCompleteData*>(msg->pdata)->stanza_);
delete msg->pdata;
break;
case MSG_XMPP_OUTPUT:
OnOutputDebugW(static_cast<StringData*>(msg->pdata)->s_);
delete msg->pdata;
break;
case MSG_XMPP_INPUT:
OnInputDebugW(static_cast<StringData*>(msg->pdata)->s_);
delete msg->pdata;
break;
}
}
void Login(const std::string &jid, const std::string &password,
const std::string &machine_address, bool is_test, bool cookie_auth) {
is_test_login_ = is_test;
xcs_.set_user(jid);
if (cookie_auth) {
xcs_.set_auth_cookie(password);
} else {
talk_base::InsecureCryptStringImpl pass;
pass.password() = password;
xcs_.set_pass(talk_base::CryptString(pass));
}
xcs_.set_host(is_test ? "google.com" : "gmail.com");
xcs_.set_resource("libjingleplus");
xcs_.set_server(talk_base::SocketAddress(machine_address, 5222));
xcs_.set_use_tls(!is_test);
if (is_test) {
xcs_.set_allow_plain(true);
}
worker_thread_ = new talk_base::Thread(&pss_);
worker_thread_->Start();
worker_thread_->Send(this, MSG_START);
}
void SendXmppMessage(const buzz::XmppMessage &m) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
worker_thread_->Post(this, MSG_SEND_XMPP_MESSAGE, new SendMessageData(m));
}
void SendXmppIq(const buzz::Jid &to_jid, bool is_get,
const buzz::XmlElement *xml_element) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
worker_thread_->Post(this, MSG_SEND_XMPP_IQ,
new SendIqData(to_jid, is_get, xml_element));
}
void SendPresence(const buzz::Status & s) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
worker_thread_->Post(this, MSG_SEND_PRESENCE, new SendPresenceData(s));
}
void SendDirectedPresence (const buzz::Jid &j, const buzz::Status &s) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
worker_thread_->Post(this, MSG_SEND_DIRECTED_PRESENCE, new SendDirectedPresenceData(j,s));
}
void SendDirectedMUCPresence(const buzz::Jid &j, const buzz::Status &s,
const std::string &un, const std::string &ac,
const std::string &am, const std::string &role) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
worker_thread_->Post(this, MSG_SEND_DIRECTED_MUC_PRESENCE, new SendDirectedMUCPresenceData(j,s,un,ac,am, role));
}
void UpdateRosterItem(const buzz::Jid & jid, const std::string & name,
const std::vector<std::string> & groups, buzz::GrType grt) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
worker_thread_->Post(this, MSG_UPDATE_ROSTER_ITEM, new UpdateRosterItemData(jid,name,groups,grt));
}
void RemoveRosterItemW(const buzz::Jid &jid) {
buzz::RosterSetTask *rst = new buzz::RosterSetTask(pump_.get()->client());
rst->Remove(jid);
rst->Start();
}
void RemoveRosterItem(const buzz::Jid &jid) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
worker_thread_->Post(this, MSG_REMOVE_ROSTER_ITEM, new JidData(jid));
}
void DoCallbacks() {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
talk_base::Message m;
while (main_thread_->Get(&m, 0)) {
main_thread_->Dispatch(&m);
}
}
private:
struct UpdateRosterItemData : public talk_base::MessageData {
UpdateRosterItemData(const buzz::Jid &jid, const std::string &name,
const std::vector<std::string> &groups, buzz::GrType grt) :
jid_(jid), n_(name), g_(groups), grt_(grt) {}
buzz::Jid jid_;
std::string n_;
std::vector<std::string> g_;
buzz::GrType grt_;
};
void UpdateRosterItemW(const buzz::Jid &jid, const std::string &name,
const std::vector<std::string> &groups, buzz::GrType grt) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
buzz::RosterSetTask *rst = new buzz::RosterSetTask(pump_.get()->client());
rst->Update(jid, name, groups, grt);
rst->Start();
}
struct StringData : public talk_base::MessageData {
StringData(std::string s) : s_(s) {}
std::string s_;
};
void OnInputDebugW(const std::string &data) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
if (notify_)
notify_->OnXmppInput(data);
}
void OnInputDebug(const char *data, int len) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
main_thread_->Post(this, MSG_XMPP_INPUT, new StringData(std::string(data,len)));
if (notify_)
notify_->WakeupMainThread();
}
void OnOutputDebugW(const std::string &data) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
if (notify_)
notify_->OnXmppOutput(data);
}
void OnOutputDebug(const char *data, int len) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
main_thread_->Post(this, MSG_XMPP_OUTPUT, new StringData(std::string(data,len)));
if (notify_)
notify_->WakeupMainThread();
}
struct StateChangeData : public talk_base::MessageData {
StateChangeData(buzz::XmppEngine::State state) : s_(state) {}
buzz::XmppEngine::State s_;
};
void OnStateChange(buzz::XmppEngine::State state) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
switch (state) {
case buzz::XmppEngine::STATE_OPEN:
ppt_ = new buzz::PresencePushTask(pump_.get()->client());
ppt_->SignalStatusUpdate.connect(this,
&LibjinglePlusWorker::OnStatusUpdate);
ppt_->SignalStatusError.connect(this,
&LibjinglePlusWorker::OnStatusError);
ppt_->Start();
rmt_ = new buzz::ReceiveMessageTask(pump_.get()->client(), buzz::XmppEngine::HL_ALL);
rmt_->SignalIncomingMessage.connect(this, &LibjinglePlusWorker::OnIncomingMessage);
rmt_->Start();
rt_ = new buzz::RosterTask(pump_.get()->client());
rt_->SignalRosterItemUpdated.connect(this, &LibjinglePlusWorker::OnRosterItemUpdated);
rt_->SignalRosterItemRemoved.connect(this, &LibjinglePlusWorker::OnRosterItemRemoved);
rt_->SignalSubscribe.connect(this, &LibjinglePlusWorker::OnRosterSubscribe);
rt_->SignalUnsubscribe.connect(this, &LibjinglePlusWorker::OnRosterUnsubscribe);
rt_->SignalSubscribed.connect(this, &LibjinglePlusWorker::OnRosterSubscribed);
rt_->SignalUnsubscribed.connect(this, &LibjinglePlusWorker::OnRosterUnsubscribed);
rt_->SignalRosterRefreshStarted.connect(this, &LibjinglePlusWorker::OnRosterRefreshStarted);
rt_->SignalRosterRefreshFinished.connect(this, &LibjinglePlusWorker::OnRosterRefreshFinished);
rt_->Start();
rt_->RefreshRosterNow();
break;
}
main_thread_->Post(this, MSG_STATE_CHANGE, new StateChangeData(state));
if (notify_)
notify_->WakeupMainThread();
}
void OnStateChangeW(buzz::XmppEngine::State state) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
if (notify_)
notify_->OnStateChange(state);
}
struct RosterItemData : public talk_base::MessageData {
RosterItemData(const buzz::RosterItem &ri) : ri_(ri) {}
buzz::RosterItem ri_;
};
void OnRosterItemUpdatedW(const buzz::RosterItem &ri) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
if (notify_)
notify_->OnRosterItemUpdated(ri);
}
void OnRosterItemUpdated(const buzz::RosterItem &ri, bool huh) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
main_thread_->Post(this, MSG_ROSTER_ITEM_UPDATED, new RosterItemData(ri));
if (notify_)
notify_->WakeupMainThread();
}
void OnRosterItemRemovedW(const buzz::RosterItem &ri) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
if (notify_)
notify_->OnRosterItemRemoved(ri);
}
void OnRosterItemRemoved(const buzz::RosterItem &ri) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
main_thread_->Post(this, MSG_ROSTER_ITEM_REMOVED, new RosterItemData(ri));
if (notify_)
notify_->WakeupMainThread();
}
struct JidData : public talk_base::MessageData {
JidData(const buzz::Jid& jid) : jid_(jid) {}
const buzz::Jid jid_;
};
void OnRosterSubscribeW(const buzz::Jid& jid) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
if (notify_)
notify_->OnRosterSubscribe(jid);
}
void OnRosterSubscribe(const buzz::Jid& jid) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
main_thread_->Post(this, MSG_ROSTER_SUBSCRIBE, new JidData(jid));
if (notify_)
notify_->WakeupMainThread();
}
void OnRosterUnsubscribeW(const buzz::Jid &jid) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
if (notify_)
notify_->OnRosterUnsubscribe(jid);
}
void OnRosterUnsubscribe(const buzz::Jid &jid) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
main_thread_->Post(this, MSG_ROSTER_UNSUBSCRIBE, new JidData(jid));
if (notify_)
notify_->WakeupMainThread();
}
void OnRosterSubscribedW(const buzz::Jid &jid) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
if (notify_)
notify_->OnRosterSubscribed(jid);
}
void OnRosterSubscribed(const buzz::Jid &jid) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
main_thread_->Post(this, MSG_ROSTER_SUBSCRIBED, new JidData(jid));
if (notify_)
notify_->WakeupMainThread();
}
void OnRosterUnsubscribedW(const buzz::Jid &jid) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
if (notify_)
notify_->OnRosterUnsubscribed(jid);
}
void OnRosterUnsubscribed(const buzz::Jid &jid) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
main_thread_->Post(this, MSG_ROSTER_UNSUBSCRIBED, new JidData(jid));
if (notify_)
notify_->WakeupMainThread();
}
void OnRosterRefreshStartedW() {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
if (notify_)
notify_->OnRosterRefreshStarted();
}
void OnRosterRefreshStarted() {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
main_thread_->Post(this, MSG_ROSTER_REFRESH_STARTED);
if (notify_)
notify_->WakeupMainThread();
}
void OnRosterRefreshFinishedW() {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
if (notify_)
notify_->OnRosterRefreshFinished();
}
void OnRosterRefreshFinished() {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
main_thread_->Post(this, MSG_ROSTER_REFRESH_FINISHED);
if (notify_)
notify_->WakeupMainThread();
}
struct XmppMessageData : talk_base::MessageData {
XmppMessageData(const buzz::XmppMessage &m) : m_(m) {}
buzz::XmppMessage m_;
};
void OnIncomingMessageW(const buzz::XmppMessage &msg) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
if (notify_)
notify_->OnMessage(msg);
}
void OnIncomingMessage(const buzz::XmppMessage &msg) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
main_thread_->Post(this, MSG_INCOMING_MESSAGE, new XmppMessageData(msg));
if (notify_)
notify_->WakeupMainThread();
}
void OnStatusUpdateW (const buzz::Status &status) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
if (notify_)
notify_->OnStatusUpdate(status);
}
void OnStatusUpdate (const buzz::Status &status) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
main_thread_->Post(this, MSG_STATUS_UPDATE, new SendPresenceData(status));
if (notify_)
notify_->WakeupMainThread();
}
struct StatusErrorData : talk_base::MessageData {
StatusErrorData(const buzz::XmlElement &stanza) : stanza_(stanza) {}
buzz::XmlElement stanza_;
};
void OnStatusErrorW (const buzz::XmlElement &stanza) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
if (notify_)
notify_->OnStatusError(stanza);
}
void OnStatusError (const buzz::XmlElement &stanza) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
main_thread_->Post(this, MSG_STATUS_ERROR, new StatusErrorData(stanza));
if (notify_)
notify_->WakeupMainThread();
}
void LoginW() {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
XmppSocket* socket = new XmppSocket(true);
pump_->DoLogin(xcs_, socket, is_test_login_ ? NULL : new XmppAuth());
socket->SignalCloseEvent.connect(this,
&LibjinglePlusWorker::OnXmppSocketClose);
}
void DisconnectW() {
assert(talk_base::ThreadManager::CurrentThread() == worker_thread_);
pump_->DoDisconnect();
}
void SendXmppMessageW(const buzz::XmppMessage &m) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
buzz::SendMessageTask * smt = new buzz::SendMessageTask(pump_.get()->client());
smt->Send(m);
smt->Start();
}
void SendXmppIqW(const buzz::Jid &to_jid, bool is_get,
const buzz::XmlElement *xml_element) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
buzz::IqTask *iq_task = new buzz::IqTask(pump_.get()->client(),
is_get, to_jid, const_cast<buzz::XmlElement *>(xml_element));
iq_task->SignalDone.connect(this, &LibjinglePlusWorker::OnIqComplete);
iq_task->Start();
}
struct IqCompleteData : public talk_base::MessageData {
IqCompleteData(bool success, const buzz::XmlElement *stanza) :
success_(success), stanza_(*stanza) {}
bool success_;
buzz::XmlElement stanza_;
};
void OnIqCompleteW(bool success, const buzz::XmlElement& stanza) {
assert(talk_base::ThreadManager::CurrentThread() != worker_thread_);
if (notify_)
notify_->OnIqDone(success, stanza);
}
void OnIqComplete(bool success, const buzz::XmlElement *stanza) {
assert(talk_base::ThreadManager::CurrentThread() == worker_thread_);
main_thread_->Post(this, MSG_IQ_COMPLETE,
new IqCompleteData(success, stanza));
if (notify_)
notify_->WakeupMainThread();
}
void SendPresenceW(const buzz::Status & s) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
buzz::PresenceOutTask *pot = new buzz::PresenceOutTask(pump_.get()->client());
pot->Send(s);
pot->Start();
}
void SendDirectedMUCPresenceW(const buzz::Jid & j, const buzz::Status & s,
const std::string &user_nick, const std::string &api_capability,
const std::string &api_message, const std::string &role) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
buzz::PresenceOutTask *pot = new buzz::PresenceOutTask(pump_.get()->client());
pot->SendDirectedMUC(j,s,user_nick,api_capability,api_message, role);
pot->Start();
}
void SendDirectedPresenceW(const buzz::Jid & j, const buzz::Status & s) {
assert (talk_base::ThreadManager::CurrentThread() == worker_thread_);
buzz::PresenceOutTask *pot = new buzz::PresenceOutTask(pump_.get()->client());
pot->SendDirected(j,s);
pot->Start();
}
void OnXmppSocketClose(int error) {
notify_->OnSocketClose(error);
}
struct SendMessageData : public talk_base::MessageData {
SendMessageData(const buzz::XmppMessage &m) : m_(m) {}
buzz::XmppMessage m_;
};
struct SendIqData : public talk_base::MessageData {
SendIqData(const buzz::Jid &jid, bool is_get, const buzz::XmlElement *m)
: to_jid_(jid), is_get_(is_get), xml_element_(m) {}
buzz::Jid to_jid_;
bool is_get_;
const buzz::XmlElement *xml_element_;
};
struct SendPresenceData : public talk_base::MessageData {
SendPresenceData(const buzz::Status &s) : s_(s) {}
buzz::Status s_;
};
struct SendDirectedPresenceData : public talk_base::MessageData {
SendDirectedPresenceData(const buzz::Jid &j, const buzz::Status &s) : j_(j), s_(s) {}
buzz::Jid j_;
buzz::Status s_;
};
struct SendDirectedMUCPresenceData : public talk_base::MessageData {
SendDirectedMUCPresenceData(const buzz::Jid &j, const buzz::Status &s,
const std::string &un, const std::string &ac,
const std::string &am, const std::string &role)
: j_(j), s_(s), un_(un), ac_(ac), am_(am), role_(role) {}
buzz::Jid j_;
buzz::Status s_;
std::string un_;
std::string ac_;
std::string am_;
std::string role_;
};
talk_base::scoped_ptr<talk_base::Win32SocketServer> ss_;
talk_base::scoped_ptr<talk_base::Thread> main_thread_;
talk_base::Thread *worker_thread_;
LibjinglePlus *ljp_;
LibjinglePlusNotify *notify_;
buzz::XmppClientSettings xcs_;
talk_base::PhysicalSocketServer pss_;
talk_base::scoped_ptr<XmppPump> pump_;
buzz::PresencePushTask * ppt_;
buzz::ReceiveMessageTask * rmt_;
buzz::RosterTask * rt_;
bool is_test_login_;
};
LibjinglePlus::LibjinglePlus(LibjinglePlusNotify *notify)
{
worker_ = new LibjinglePlusWorker(this, notify);
}
LibjinglePlus::~LibjinglePlus()
{
delete worker_;
worker_ = NULL;
}
void LibjinglePlus::Login(const std::string &jid,
const std::string &password,
const std::string &machine_address,
bool is_test, bool cookie_auth) {
worker_->Login(jid, password, machine_address, is_test, cookie_auth);
}
void LibjinglePlus::SendPresence(const buzz::Status & s) {
worker_->SendPresence(s);
}
void LibjinglePlus::SendDirectedPresence(const buzz::Jid & j, const buzz::Status & s) {
worker_->SendDirectedPresence(j,s);
}
void LibjinglePlus::SendDirectedMUCPresence(const buzz::Jid & j,
const buzz::Status & s, const std::string &user_nick,
const std::string &api_capability, const std::string &api_message,
const std::string &role) {
worker_->SendDirectedMUCPresence(j,s,user_nick,api_capability,api_message,
role);
}
void LibjinglePlus::SendXmppMessage(const buzz::XmppMessage & m) {
worker_->SendXmppMessage(m);
}
void LibjinglePlus::SendXmppIq(const buzz::Jid &to_jid, bool is_get,
const buzz::XmlElement *iq_element) {
worker_->SendXmppIq(to_jid, is_get, iq_element);
}
void LibjinglePlus::DoCallbacks() {
worker_->DoCallbacks();
}

View File

@ -1,154 +0,0 @@
/*
* libjingle
* Copyright 2006, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// LibjinglePlus is a class that connects to Google Talk, creates
// some common tasks, and emits signals when things change
#ifndef LIBJINGLEPLUS_H__
#define LIBJINGLEPLUS_H__
#include "talk/base/basicdefs.h"
#include "talk/app/rosteritem.h"
#include "talk/app/message.h"
#include "talk/app/status.h"
#include "talk/xmpp/xmppengine.h"
#include "talk/base/scoped_ptr.h"
class LibjinglePlusWorker;
class LibjinglePlusNotify {
public:
virtual ~LibjinglePlusNotify() {}
/* Libjingle+ works on its own thread. It will call WakeupMainThread
* when it has something to report. The main thread should then wake up,
* and call DoCallbacks on the LibjinglePlus object.
*
* This function gets called from libjingle+'s worker thread. All other
* methods in LibjinglePlusNotify get called from the thread you call
* DoCallbacks() on.
*
* If running on Windows, libjingle+ will use Windows messages to generate
* callbacks from the main thread, and you don't need to do anything here.
*/
virtual void WakeupMainThread() = 0;
/* Connection */
/* Called when the connection state changes */
virtual void OnStateChange(buzz::XmppEngine::State) = 0;
/* Called when the socket closes */
virtual void OnSocketClose(int error_code) = 0;
/* Called when XMPP is being sent or received. Used for debugging */
virtual void OnXmppOutput(const std::string &output) = 0;
virtual void OnXmppInput(const std::string &input) = 0;
/* Presence */
/* Called when someone's Status is updated */
virtual void OnStatusUpdate(const buzz::Status &status) = 0;
/* Called when a status update results in an error */
virtual void OnStatusError(const buzz::XmlElement &stanza) = 0;
/* Called with an IQ return code */
virtual void OnIqDone(bool success, const buzz::XmlElement &stanza) = 0;
/* Message */
/* Called when a message comes in. */
virtual void OnMessage(const buzz::XmppMessage &message) = 0;
/* Roster */
/* Called when we start refreshing the roster */
virtual void OnRosterRefreshStarted() = 0;
/* Called when we have the entire roster */
virtual void OnRosterRefreshFinished() = 0;
/* Called when an item on the roster is created or updated */
virtual void OnRosterItemUpdated(const buzz::RosterItem &ri) = 0;
/* Called when an item on the roster is removed */
virtual void OnRosterItemRemoved(const buzz::RosterItem &ri) = 0;
/* Subscriptions */
virtual void OnRosterSubscribe(const buzz::Jid &jid) = 0;
virtual void OnRosterUnsubscribe(const buzz::Jid &jid) = 0;
virtual void OnRosterSubscribed(const buzz::Jid &jid) = 0;
virtual void OnRosterUnsubscribed(const buzz::Jid &jid) = 0;
};
class LibjinglePlus
{
public:
/* Provide the constructor with your interface. */
LibjinglePlus(LibjinglePlusNotify *notify);
~LibjinglePlus();
/* Logs in and starts doing stuff
*
* If cookie_auth is true, password must be a Gaia SID. Otherwise,
* it should be the user's password
*/
void Login(const std::string &username, const std::string &password,
const std::string &machine_address, bool is_test, bool cookie_auth);
/* Set Presence */
void SendPresence(const buzz::Status & s);
void SendDirectedPresence(const buzz::Jid & j, const buzz::Status & s);
void SendDirectedMUCPresence(const buzz::Jid & j, const buzz::Status & s,
const std::string &user_nick, const std::string &api_capability,
const std::string &api_message, const std::string &role);
/* Send Message */
void SendXmppMessage(const buzz::XmppMessage & m);
/* Send IQ */
void SendXmppIq(const buzz::Jid &to_jid, bool is_get,
const buzz::XmlElement *iq_element);
/* Set Roster */
void UpdateRosterItem(const buzz::Jid & jid, const std::string & name,
const std::vector<std::string> & groups, buzz::GrType grt);
void RemoveRosterItem(const buzz::Jid &jid);
/* Call this from the thread you want to receive callbacks on. Typically, this will be called
* after your WakeupMainThread() notify function is called.
*
* On Windows, libjingle+ will trigger its callback from the Windows message loop, and
* you needn't call this yourself.
*/
void DoCallbacks();
private:
void LoginInternal(const std::string &jid, const std::string &password,
const std::string &machine_address, bool is_test);
LibjinglePlusWorker *worker_;
};
#endif // LIBJINGLE_PLUS_H__

View File

@ -1,201 +0,0 @@
/*
* libjingle
* Copyright 2004--2005, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "talk/base/stringencode.h"
#include "presencepushtask.h"
#include "talk/xmpp/constants.h"
#include <sstream>
namespace buzz {
// string helper functions -----------------------------------------------------
static bool
IsXmlSpace(int ch) {
return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
}
static bool
ListContainsToken(const std::string & list, const std::string & token) {
size_t i = list.find(token);
if (i == std::string::npos || token.empty())
return false;
bool boundary_before = (i == 0 || IsXmlSpace(list[i - 1]));
bool boundary_after = (i == list.length() - token.length() || IsXmlSpace(list[i + token.length()]));
return boundary_before && boundary_after;
}
bool
PresencePushTask::HandleStanza(const XmlElement * stanza) {
if (stanza->Name() != QN_PRESENCE)
return false;
if (stanza->HasAttr(QN_TYPE) && stanza->Attr(QN_TYPE) != STR_UNAVAILABLE) {
if (stanza->Attr(QN_TYPE) == STR_ERROR) {
// Pass on the error.
const XmlElement* error_xml_elem = stanza->FirstNamed(QN_ERROR);
if (!error_xml_elem) {
return false;
}
SignalStatusError(*error_xml_elem);
return true;
}
}
QueueStanza(stanza);
return true;
}
static bool IsUtf8FirstByte(int c) {
return (((c)&0x80)==0) || // is single byte
((unsigned char)((c)-0xc0)<0x3e); // or is lead byte
}
int
PresencePushTask::ProcessStart() {
const XmlElement * stanza = NextStanza();
if (stanza == NULL)
return STATE_BLOCKED;
Status s;
s.set_jid(Jid(stanza->Attr(QN_FROM)));
if (stanza->Attr(QN_TYPE) == STR_UNAVAILABLE) {
s.set_available(false);
SignalStatusUpdate(s);
}
else {
s.set_available(true);
const XmlElement * status = stanza->FirstNamed(QN_STATUS);
if (status != NULL) {
s.set_status(status->BodyText());
// Truncate status messages longer than 300 bytes
if (s.status().length() > 300) {
size_t len = 300;
// Be careful not to split legal utf-8 chars in half
while (!IsUtf8FirstByte(s.status()[len]) && len > 0) {
len -= 1;
}
std::string truncated(s.status(), 0, len);
s.set_status(truncated);
}
}
const XmlElement * priority = stanza->FirstNamed(QN_PRIORITY);
if (priority != NULL) {
int pri;
if (talk_base::FromString(priority->BodyText(), &pri)) {
s.set_priority(pri);
}
}
const XmlElement * show = stanza->FirstNamed(QN_SHOW);
if (show == NULL || show->FirstChild() == NULL) {
s.set_show(Status::SHOW_ONLINE);
}
else {
if (show->BodyText() == "away") {
s.set_show(Status::SHOW_AWAY);
}
else if (show->BodyText() == "xa") {
s.set_show(Status::SHOW_XA);
}
else if (show->BodyText() == "dnd") {
s.set_show(Status::SHOW_DND);
}
else if (show->BodyText() == "chat") {
s.set_show(Status::SHOW_CHAT);
}
else {
s.set_show(Status::SHOW_ONLINE);
}
}
const XmlElement * caps = stanza->FirstNamed(QN_CAPS_C);
if (caps != NULL) {
std::string node = caps->Attr(QN_NODE);
std::string ver = caps->Attr(QN_VER);
std::string exts = caps->Attr(QN_EXT);
s.set_know_capabilities(true);
std::string capability;
std::stringstream ss(exts);
while (ss >> capability) {
s.AddCapability(capability);
}
s->set_caps_node(node);
s->set_version(ver);
}
const XmlElement* delay = stanza->FirstNamed(kQnDelayX);
if (delay != NULL) {
// Ideally we would parse this according to the Psuedo ISO-8601 rules
// that are laid out in JEP-0082:
// http://www.jabber.org/jeps/jep-0082.html
std::string stamp = delay->Attr(kQnStamp);
s.set_sent_time(stamp);
}
const XmlElement *nick = stanza->FirstNamed(kQnNickname);
if (nick) {
std::string user_nick = nick->BodyText();
s.set_user_nick(user_nick);
}
const XmlElement *plugin = stanza->FirstNamed(QN_PLUGIN);
if (plugin) {
const XmlElement *api_cap = plugin->FirstNamed(QN_CAPABILITY);
if (api_cap) {
const std::string &api_capability = api_cap->BodyText();
s.set_api_capability(api_capability);
}
const XmlElement *api_msg = plugin->FirstNamed(QN_DATA);
if (api_msg) {
const std::string &api_message = api_msg->BodyText();
s.set_api_message(api_message);
}
}
const XmlElement* data_x = stanza->FirstNamed(QN_MUC_USER_X);
if (data_x != NULL) {
const XmlElement* item = data_x->FirstNamed(QN_MUC_USER_ITEM);
if (item != NULL) {
s.set_muc_role(item->Attr(QN_ROLE));
}
}
SignalStatusUpdate(s);
}
return STATE_START;
}
}

View File

@ -1,53 +0,0 @@
/*
* libjingle
* Copyright 2004--2005, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _PRESENCEPUSHTASK_H_
#define _PRESENCEPUSHTASK_H_
#include "talk/xmpp/xmppengine.h"
#include "talk/xmpp/xmpptask.h"
#include "talk/base/sigslot.h"
#include "talk/app/status.h"
namespace buzz {
class PresencePushTask : public XmppTask {
public:
PresencePushTask(Task * parent) : XmppTask(parent, XmppEngine::HL_TYPE) {}
virtual int ProcessStart();
sigslot::signal1<const Status &>SignalStatusUpdate;
sigslot::signal1<const XmlElement &> SignalStatusError;
protected:
virtual bool HandleStanza(const XmlElement * stanza);
};
}
#endif

View File

@ -1,218 +0,0 @@
/*
* libjingle
* Copyright 2004--2005, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "rostertask.h"
#include "talk/xmpp/constants.h"
#include "talk/base/stream.h"
#undef WIN32
#ifdef WIN32
#include "talk/app/win32/offlineroster.h"
#endif
namespace buzz {
class RosterTask::RosterGetTask : public XmppTask {
public:
RosterGetTask(Task * parent) : XmppTask(parent, XmppEngine::HL_SINGLE),
done_(false) {}
virtual int ProcessStart();
virtual int ProcessResponse();
protected:
virtual bool HandleStanza(const XmlElement * stanza);
bool done_;
};
//==============================================================================
// RosterTask
//==============================================================================
void RosterTask::RefreshRosterNow() {
RosterGetTask* get_task = new RosterGetTask(this);
ResumeTimeout();
get_task->Start();
}
void RosterTask::TranslateItems(const XmlElement * rosterQueryResult) {
#if defined(FEATURE_ENABLE_PSTN)
#ifdef WIN32
// We build up a list of contacts which have had information persisted offline.
// we'll remove items from this list if we get a buzz::SUBSCRIBE_REMOVE
// subscription. After updating all the items from the server, we'll then
// update (and merge) any roster items left in our map of offline items
XmlElement *el_local = OfflineRoster::RetrieveOfflineRoster(GetClient()->jid());
std::map<buzz::Jid, RosterItem> jid_to_item;
if (el_local) {
for (XmlElement *el_item = el_local->FirstNamed(QN_ROSTER_ITEM);
el_item != NULL;
el_item = el_item->NextNamed(QN_ROSTER_ITEM)) {
RosterItem roster_item;
roster_item.FromXml(el_item);
jid_to_item[roster_item.jid()] = roster_item;
}
}
#endif // WIN32
#endif // FEATURE_ENABLE_PSTN
const XmlElement * xml_item;
for (xml_item = rosterQueryResult->FirstNamed(QN_ROSTER_ITEM);
xml_item != NULL; xml_item = xml_item->NextNamed(QN_ROSTER_ITEM)) {
RosterItem roster_item;
roster_item.FromXml(xml_item);
if (roster_item.subscription() == buzz::SUBSCRIBE_REMOVE) {
SignalRosterItemRemoved(roster_item);
#if defined(FEATURE_ENABLE_PSTN)
#ifdef WIN32
std::map<buzz::Jid, RosterItem>::iterator it =
jid_to_item.find(roster_item.jid());
if (it != jid_to_item.end())
jid_to_item.erase(it);
#endif
#endif
} else {
SignalRosterItemUpdated(roster_item, false);
}
}
#if defined(FEATURE_ENABLE_PSTN)
#ifdef WIN32
for (std::map<buzz::Jid, RosterItem>::iterator it = jid_to_item.begin();
it != jid_to_item.end(); ++it) {
SignalRosterItemUpdated(it->second, true);
}
#endif
#endif
}
int RosterTask::ProcessStart() {
const XmlElement * stanza = NextStanza();
if (stanza == NULL)
return STATE_BLOCKED;
if (stanza->Name() == QN_IQ) {
SuspendTimeout();
bool result = (stanza->Attr(QN_TYPE) == STR_RESULT);
if (result)
SignalRosterRefreshStarted();
TranslateItems(stanza->FirstNamed(QN_ROSTER_QUERY));
if (result)
SignalRosterRefreshFinished();
} else if (stanza->Name() == QN_PRESENCE) {
Jid jid(stanza->Attr(QN_FROM));
std::string type = stanza->Attr(QN_TYPE);
if (type == "subscribe")
SignalSubscribe(jid);
else if (type == "unsubscribe")
SignalUnsubscribe(jid);
else if (type == "subscribed")
SignalSubscribed(jid);
else if (type == "unsubscribed")
SignalUnsubscribed(jid);
}
return STATE_START;
}
bool RosterTask::HandleStanza(const XmlElement * stanza) {
if (!MatchRequestIq(stanza, STR_SET, QN_ROSTER_QUERY)) {
// Not a roster IQ. Look for a presence instead
if (stanza->Name() != QN_PRESENCE)
return false;
if (!stanza->HasAttr(QN_TYPE))
return false;
std::string type = stanza->Attr(QN_TYPE);
if (type == "subscribe" || type == "unsubscribe" ||
type == "subscribed" || type == "unsubscribed") {
QueueStanza(stanza);
return true;
}
return false;
}
// only respect roster push from the server
Jid from(stanza->Attr(QN_FROM));
if (from != JID_EMPTY &&
!from.BareEquals(GetClient()->jid()) &&
from != Jid(GetClient()->jid().domain()))
return false;
XmlElement * result = MakeIqResult(stanza);
result->AddElement(new XmlElement(QN_ROSTER_QUERY, true));
SendStanza(result);
QueueStanza(stanza);
return true;
}
//==============================================================================
// RosterTask::RosterGetTask
//==============================================================================
int RosterTask::RosterGetTask::ProcessStart() {
talk_base::scoped_ptr<XmlElement> get(MakeIq(STR_GET, JID_EMPTY, task_id()));
get->AddElement(new XmlElement(QN_ROSTER_QUERY, true));
get->AddAttr(QN_XMLNS_GR, NS_GR, 1);
get->AddAttr(QN_GR_EXT, "2", 1);
get->AddAttr(QN_GR_INCLUDE, "all", 1);
if (SendStanza(get.get()) != XMPP_RETURN_OK) {
return STATE_ERROR;
}
return STATE_RESPONSE;
}
int RosterTask::RosterGetTask::ProcessResponse() {
if (done_)
return STATE_DONE;
return STATE_BLOCKED;
}
bool RosterTask::RosterGetTask::HandleStanza(const XmlElement * stanza) {
if (!MatchResponseIq(stanza, JID_EMPTY, task_id()))
return false;
if (stanza->Attr(QN_TYPE) != STR_RESULT)
return false;
// Queue the stanza with the parent so these don't get handled out of order
RosterTask* parent = static_cast<RosterTask*>(GetParent());
parent->QueueStanza(stanza);
// Wake ourselves so we can go into the done state
done_ = true;
Wake();
return true;
}
}

View File

@ -1,72 +0,0 @@
/*
* libjingle
* Copyright 2004--2005, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _PHONE_CLIENT_ROSTERTASK_H_
#define _PHONE_CLIENT_ROSTERTASK_H_
#include "talk/xmpp/xmppclient.h"
#include "talk/xmpp/xmpptask.h"
#include "talk/app/rosteritem.h"
#include "talk/base/sigslot.h"
namespace buzz {
class RosterTask : public XmppTask {
public:
RosterTask(Task * parent) :
XmppTask(parent, XmppEngine::HL_TYPE) {}
// Roster items removed or updated. This can come from a push or a get
sigslot::signal2<const RosterItem &, bool> SignalRosterItemUpdated;
sigslot::signal1<const RosterItem &> SignalRosterItemRemoved;
// Subscription messages
sigslot::signal1<const Jid &> SignalSubscribe;
sigslot::signal1<const Jid &> SignalUnsubscribe;
sigslot::signal1<const Jid &> SignalSubscribed;
sigslot::signal1<const Jid &> SignalUnsubscribed;
// Roster get
void RefreshRosterNow();
sigslot::signal0<> SignalRosterRefreshStarted;
sigslot::signal0<> SignalRosterRefreshFinished;
virtual int ProcessStart();
protected:
void TranslateItems(const XmlElement *rosterQueryResult);
virtual bool HandleStanza(const XmlElement * stanza);
// Inner class for doing the roster get
class RosterGetTask;
friend class RosterGetTask;
};
}
#endif // _PHONE_CLIENT_ROSTERTASK_H_

View File

@ -1,119 +0,0 @@
/*
* libjingle
* Copyright 2006, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <string>
#include "talk/base/thread.h"
#include "talk/libjingle-plus/libjingleplus.h"
#include "talk/libjingle-plus/testutil/libjingleplus_test_notifier.h"
#if defined(_MSC_VER) && (_MSC_VER < 1400)
void __cdecl std::_Throw(const std::exception &) {}
std::_Prhand std::_Raise_handler =0;
#endif
void SetConsoleEcho(bool on) {
#ifdef WIN32
HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
if ((hIn == INVALID_HANDLE_VALUE) || (hIn == NULL))
return;
DWORD mode;
if (!GetConsoleMode(hIn, &mode))
return;
if (on) {
mode = mode | ENABLE_ECHO_INPUT;
} else {
mode = mode & ~ENABLE_ECHO_INPUT;
}
SetConsoleMode(hIn, mode);
#else
if (on)
system("stty echo");
else
system("stty -echo");
#endif
}
int main (int argc, char **argv)
{
std::string username;
std::string password;
bool gaia = false;
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-gaia"))
gaia = true;
}
std::cout << "Username: ";
std::cin >> username;
std::cout << (gaia ? "Gaia cookie: " : "Password: ");
SetConsoleEcho(false);
std::cin >> password;
SetConsoleEcho(true);
// Create a LibjinglePlus object and give it the notifier interface
LibjinglePlus ljp(new Notifier);
// Login
ljp.Login(username, password, "talk.google.com", false, gaia);
buzz::Status s;
s.set_available(true);
s.set_show(buzz::Status::SHOW_ONLINE);
s.set_status("I'm online.");
buzz::XmppMessage m;
m.set_to(buzz::Jid(username + "@gmail.com"));
m.set_body("What's up?");
// Typically, you would wait for WakeupMainThread to be called, and then call
// DoCallbacks. Because I have nothing else to do on the main thread, I'm just going
// to do a few things after 10 seconds and then poll every 2ms.
Sleep(10000);
// ljp.DoCallbacks();
ljp.SendPresence(s);
ljp.SendXmppMessage(m);
#ifdef WIN32
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
DispatchMessage(&msg);
}
#else
for (;;) {
ljp.DoCallbacks();
Sleep(2);
}
#endif
}

View File

@ -1,101 +0,0 @@
/*
* libjingle
* Copyright 2006, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <string>
#include "talk/libjingle-plus/libjingleplus.h"
class Notifier : virtual public LibjinglePlusNotify {
virtual void OnStateChange(buzz::XmppEngine::State state) {
std::cout << "State change: " << state << std::endl;
}
virtual void OnSocketClose(int error_code) {
std::cout << "Socket close: " << error_code << std::endl;
}
virtual void OnXmppOutput(const std::string &output) {
std::cout << ">>>>>>>>" << std::endl << output << std::endl << ">>>>>>>>" << std::endl;
}
virtual void OnXmppInput(const std::string &input) {
std::cout << "<<<<<<<<" << std::endl << input << std::endl << "<<<<<<<<" << std::endl;
}
virtual void OnStatusUpdate(const buzz::Status &status) {
std::string from = status.jid().Str();
std::cout << from << " - " << status.status() << std::endl;
}
virtual void OnStatusError(const buzz::XmlElement &stanza) {
}
virtual void OnIqDone(bool success, const buzz::XmlElement &stanza) {
}
virtual void OnMessage(const buzz::XmppMessage &m) {
if (m.body() != "")
std::cout << m.from().Str() << ": " << m.body() << std::endl;
}
void OnRosterItemUpdated(const buzz::RosterItem &ri) {
std::cout << "Roster item: " << ri.jid().Str() << std::endl;
}
virtual void OnRosterItemRemoved(const buzz::RosterItem &ri) {
std::cout << "Roster item removed: " << ri.jid().Str() << std::endl;
}
virtual void OnRosterSubscribe(const buzz::Jid& jid) {
std::cout << "Subscribing: " << jid.Str() << std::endl;
}
virtual void OnRosterUnsubscribe(const buzz::Jid &jid) {
std::cout << "Unsubscribing: " <<jid.Str() << std::endl;
}
virtual void OnRosterSubscribed(const buzz::Jid &jid) {
std::cout << "Subscribed: " << jid.Str() << std::endl;
}
virtual void OnRosterUnsubscribed(const buzz::Jid &jid) {
std::cout << "Unsubscribed: " << jid.Str() << std::endl;
}
virtual void OnRosterRefreshStarted() {
std::cout << "Refreshing roster." << std::endl;
}
virtual void OnRosterRefreshFinished() {
std::cout << "Roster refreshed." << std::endl;
}
virtual void WakeupMainThread() {
}
};

View File

@ -1,52 +0,0 @@
/*
* libjingle
* Copyright 2006, Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "testing/base/gunit.h"
#include "talk/libjingle-plus/libjingleplus.h"
#include "talk/libjingle-plus/testutil/libjingleplus_test_notifier.h"
#if defined(_MSC_VER) && (_MSC_VER < 1400)
void __cdecl std::_Throw(const std::exception &) {}
std::_Prhand std::_Raise_handler =0;
#endif
namespace talk_base {
TEST(LibjingleTest, ConstructDestruct) {
for (int i = 0; i < 5; ++i) {
LibjinglePlus *libjingleplus = new LibjinglePlus(new Notifier);
libjingleplus->Login("eaterleaver0", "Buzzt3st", "talk.google.com", false, false);
delete libjingleplus;
}
}
}
int main(int argc, char** argv) {
testing::ParseGUnitFlags(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -51,7 +51,7 @@
'libjingle.gyp:libjingle_p2p',
],
'sources': [
'p2p/base/relayserver_main.cc',
'examples/relayserver/relayserver_main.cc',
],
}, # target relayserver
{
@ -62,7 +62,7 @@
'libjingle.gyp:libjingle_p2p',
],
'sources': [
'p2p/base/stunserver_main.cc',
'examples/stunserver/stunserver_main.cc',
],
}, # target stunserver
{
@ -73,7 +73,7 @@
'libjingle.gyp:libjingle_p2p',
],
'sources': [
'p2p/base/turnserver_main.cc',
'examples/turnserver/turnserver_main.cc',
],
}, # target turnserver
{