blob: 4d27dfd120b0ef0bed1bbca59985890ceaf1215a [file] [log] [blame]
/*
* 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();
}