Changeset - 457d19d1ec41
[Not reviewed]
0 7 0
HanzZ - 15 years ago 2011-05-19 00:33:38
hanzz.k@gmail.com
Working join/rename
7 files changed with 24 insertions and 13 deletions:
0 comments (0 inline, 0 general)
backends/libircclient-qt/session.cpp
Show inline comments
 
/*
 
 * Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
 
 *
 
 * This example is free, and not covered by LGPL license. There is no
 
 * restriction applied to their modification, redistribution, using and so on.
 
 * You can study them, modify them, use them in your own program - either
 
 * completely or partially. By using it you may give me some credits in your
 
 * program, but you don't have to.
 
 */
 

	
 
#include "session.h"
 
#include <QtCore>
 
#include <iostream>
 

	
 
MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, QObject* parent) : Irc::Session(parent)
 
{
 
	this->np = np;
 
	this->user = user;
 
}
 

	
 
void MyIrcSession::on_connected()
 
{
 
    std::cout << "connected:\n";
 
}
 

	
 
void MyIrcSession::on_disconnected()
 
{
 
    std::cout << "disconnected:\n";
 
}
 

	
 
void MyIrcSession::on_bufferAdded(Irc::Buffer* buffer)
 
{
 
    qDebug() << "buffer added:" << buffer->receiver();
 
}
 

	
 
void MyIrcSession::on_bufferRemoved(Irc::Buffer* buffer)
 
{
 
    qDebug() << "buffer removed:" << buffer->receiver();
 
}
 

	
 
Irc::Buffer* MyIrcSession::createBuffer(const QString& receiver)
 
{
 
    return new MyIrcBuffer(receiver, user, np, this);
 
}
 

	
 
MyIrcBuffer::MyIrcBuffer(const QString& receiver, const std::string &user, NetworkPlugin *np, Irc::Session* parent)
 
    : Irc::Buffer(receiver, parent)
 
{
 
	this->np = np;
 
	this->user = user;
 
    connect(this, SIGNAL(receiverChanged(QString)), SLOT(on_receiverChanged(QString)));
 
    connect(this, SIGNAL(joined(QString)), SLOT(on_joined(QString)));
 
    connect(this, SIGNAL(parted(QString, QString)), SLOT(on_parted(QString, QString)));
 
    connect(this, SIGNAL(quit(QString, QString)), SLOT(on_quit(QString, QString)));
 
    connect(this, SIGNAL(nickChanged(QString, QString)), SLOT(on_nickChanged(QString, QString)));
 
    connect(this, SIGNAL(modeChanged(QString, QString, QString)), SLOT(on_modeChanged(QString, QString, QString)));
 
    connect(this, SIGNAL(topicChanged(QString, QString)), SLOT(on_topicChanged(QString, QString)));
 
    connect(this, SIGNAL(invited(QString, QString, QString)), SLOT(on_invited(QString, QString, QString)));
 
    connect(this, SIGNAL(kicked(QString, QString, QString)), SLOT(on_kicked(QString, QString, QString)));
 
    connect(this, SIGNAL(messageReceived(QString, QString, Irc::Buffer::MessageFlags)),
 
                  SLOT(on_messageReceived(QString, QString, Irc::Buffer::MessageFlags)));
 
    connect(this, SIGNAL(noticeReceived(QString, QString, Irc::Buffer::MessageFlags)),
 
                  SLOT(on_noticeReceived(QString, QString, Irc::Buffer::MessageFlags)));
 
    connect(this, SIGNAL(ctcpRequestReceived(QString, QString, Irc::Buffer::MessageFlags)),
 
                  SLOT(on_ctcpRequestReceived(QString, QString, Irc::Buffer::MessageFlags)));
 
    connect(this, SIGNAL(ctcpReplyReceived(QString, QString, Irc::Buffer::MessageFlags)),
 
                  SLOT(on_ctcpReplyReceived(QString, QString, Irc::Buffer::MessageFlags)));
 
    connect(this, SIGNAL(ctcpActionReceived(QString, QString, Irc::Buffer::MessageFlags)),
 
                  SLOT(on_ctcpActionReceived(QString, QString, Irc::Buffer::MessageFlags)));
 
    connect(this, SIGNAL(numericMessageReceived(QString, uint, QStringList)), SLOT(on_numericMessageReceived(QString, uint, QStringList)));
 
    connect(this, SIGNAL(unknownMessageReceived(QString, QStringList)), SLOT(on_unknownMessageReceived(QString, QStringList)));
 
}
 

	
 
void MyIrcBuffer::on_receiverChanged(const QString& receiver)
 
{
 
    qDebug() << "receiver changed:" << receiver;
 
}
 

	
 
void MyIrcBuffer::on_joined(const QString& origin)
 
{
 
    qDebug() << "joined:" << receiver() << origin;
 
void MyIrcBuffer::on_joined(const QString& origin) {
 
	qDebug() << "joined:" << receiver() << origin;
 
	np->handleParticipantChanged(user, origin.toStdString(), receiver().toStdString(), 0);
 
}
 

	
 
void MyIrcBuffer::on_parted(const QString& origin, const QString& message)
 
{
 
    qDebug() << "parted:" << receiver() << origin << message;
 
}
 

	
 
void MyIrcBuffer::on_quit(const QString& origin, const QString& message)
 
{
 
    qDebug() << "quit:" << receiver() << origin << message;
 
}
 

	
 
void MyIrcBuffer::on_nickChanged(const QString& origin, const QString& nick)
 
{
 
    qDebug() << "nick changed:" << receiver() << origin << nick;
 
void MyIrcBuffer::on_nickChanged(const QString& origin, const QString& nick) {
 
	qDebug() << "nick changed:" << receiver() << origin << nick;
 
	np->handleParticipantChanged(user, origin.toStdString(), receiver().toStdString(), 0, nick.toStdString());
 
}
 

	
 
void MyIrcBuffer::on_modeChanged(const QString& origin, const QString& mode, const QString& args)
 
{
 
    qDebug() << "mode changed:" << receiver() << origin << mode << args;
 
}
 

	
 
void MyIrcBuffer::on_topicChanged(const QString& origin, const QString& topic)
 
{
 
    qDebug() << "topic changed:" << receiver() << origin << topic;
 
}
 

	
 
void MyIrcBuffer::on_invited(const QString& origin, const QString& receiver, const QString& channel)
 
{
 
    qDebug() << "invited:" << Irc::Buffer::receiver() << origin << receiver << channel;
 
}
 

	
 
void MyIrcBuffer::on_kicked(const QString& origin, const QString& nick, const QString& message)
 
{
 
    qDebug() << "kicked:" << receiver() << origin << nick << message;
 
}
 

	
 
void MyIrcBuffer::on_messageReceived(const QString& origin, const QString& message, Irc::Buffer::MessageFlags flags) {
 
	qDebug() << "message received:" << receiver() << origin << message << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)");
 
	if (!receiver().startsWith("#") && (flags & Irc::Buffer::EchoFlag))
 
		return;
 
	np->handleMessage(user, receiver().toStdString(), message.toStdString(), origin.toStdString());
 
}
 

	
 
void MyIrcBuffer::on_noticeReceived(const QString& origin, const QString& notice, Irc::Buffer::MessageFlags flags)
 
{
 
    qDebug() << "notice received:" << receiver() << origin << notice
 
             << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)");
 
}
 

	
 
void MyIrcBuffer::on_ctcpRequestReceived(const QString& origin, const QString& request, Irc::Buffer::MessageFlags flags)
 
{
 
    qDebug() << "ctcp request received:" << receiver() << origin << request
 
             << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)");
 
}
 

	
 
void MyIrcBuffer::on_ctcpReplyReceived(const QString& origin, const QString& reply, Irc::Buffer::MessageFlags flags)
 
{
 
    qDebug() << "ctcp reply received:" << receiver() << origin << reply
 
             << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)");
 
}
 

	
 
void MyIrcBuffer::on_ctcpActionReceived(const QString& origin, const QString& action, Irc::Buffer::MessageFlags flags)
 
{
 
    qDebug() << "ctcp action received:" << receiver() << origin << action
 
             << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)");
 
}
 

	
 
void MyIrcBuffer::on_numericMessageReceived(const QString& origin, uint code, const QStringList& params)
 
{
 
	switch (code) {
 
		case 353:
 
			QString channel = params.value(2);
 
			QStringList members = params.value(3).split(" ");
 

	
 
			for (int i = 0; i < members.size(); i++) {
 
				np->handleParticipantChanged(user, members.at(i).toStdString(), channel.toStdString(), 0);
 
			}
 
			break;
 
	}
 
    qDebug() << "numeric message received:" << receiver() << origin << code << params;
 
}
 

	
 
void MyIrcBuffer::on_unknownMessageReceived(const QString& origin, const QStringList& params)
 
{
 
    qDebug() << "unknown message received:" << receiver() << origin << params;
 
}
include/transport/conversation.h
Show inline comments
 
/**
 
 * XMPP - libpurple transport
 
 *
 
 * Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
 
 *
 
 * This program is free software; you can redistribute it and/or modify
 
 * it under the terms of the GNU General Public License as published by
 
 * the Free Software Foundation; either version 2 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * This program is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU General Public License
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#pragma once
 

	
 
#include <string>
 
#include <algorithm>
 
#include "transport/transport.h"
 

	
 
#include "Swiften/Swiften.h"
 
#include "Swiften/Elements/Message.h"
 

	
 
namespace Transport {
 

	
 
class ConversationManager;
 

	
 
class Conversation {
 
	public:
 
		/// Constructor.
 
		Conversation(ConversationManager *conversationManager, const std::string &legacyName, bool m_muc = false);
 

	
 
		/// Destructor
 
		virtual ~Conversation();
 

	
 
		const std::string &getLegacyName() { return m_legacyName; }
 

	
 
		void handleMessage(boost::shared_ptr<Swift::Message> &message, const std::string &nickname = "");
 
		void handleParticipantChanged(const std::string &nickname, int flag);
 
		void handleParticipantChanged(const std::string &nickname, int flag, const std::string &newname = "");
 
		void setNickname(const std::string &nickname) {
 
			m_nickname = nickname;
 
		}
 

	
 
		virtual void sendMessage(boost::shared_ptr<Swift::Message> &message) = 0;
 

	
 
		ConversationManager *getConversationManager() {
 
			return m_conversationManager;
 
		}
 

	
 
		bool isMUC() {
 
			return m_muc;
 
		}
 

	
 
		void setRoom(const std::string &room) {
 
			m_room = room;
 
		}
 

	
 
		const std::string &getRoom() {
 
			return m_room;
 
		}
 

	
 
	private:
 
		ConversationManager *m_conversationManager;
 
		std::string m_legacyName;
 
		std::string m_nickname;
 
		std::string m_room;
 
		bool m_muc;
 
};
 

	
 
}
include/transport/networkplugin.h
Show inline comments
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
 
 *
 
 * This program is free software; you can redistribute it and/or modify
 
 * it under the terms of the GNU General Public License as published by
 
 * the Free Software Foundation; either version 2 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * This program is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU General Public License
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#pragma once
 

	
 
#include <time.h>
 
#include "Swiften/Swiften.h"
 
#include "Swiften/Presence/PresenceOracle.h"
 
#include "Swiften/Disco/EntityCapsManager.h"
 
#include "Swiften/Network/ConnectionServer.h"
 
#include "Swiften/Network/Connection.h"
 
#include "Swiften/Network/BoostTimerFactory.h"
 
#include "Swiften/Network/BoostNetworkFactories.h"
 
#include "Swiften/Network/BoostIOServiceThread.h"
 
#include "Swiften/Network/Connection.h"
 
#include "storagebackend.h"
 

	
 
namespace Transport {
 

	
 
class NetworkPlugin {
 
	public:
 
		NetworkPlugin(Swift::EventLoop *loop, const std::string &host, int port);
 

	
 
		virtual ~NetworkPlugin();
 

	
 
		void handleBuddyChanged(const std::string &user, const std::string &buddyName, const std::string &alias,
 
			const std::string &groups, int status, const std::string &statusMessage = "", const std::string &iconHash = ""
 
		);
 

	
 
		void handleParticipantChanged(const std::string &user, const std::string &nickname, const std::string &room, int flags);
 
		void handleParticipantChanged(const std::string &user, const std::string &nickname, const std::string &room, int flags, const std::string &newname = "");
 

	
 
		void handleDisconnected(const std::string &user, const std::string &legacyName, int error, const std::string &message);
 

	
 
		void handleMessage(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &nickname = "");
 

	
 
		void handleRoomChanged(const std::string &user, const std::string &room, const std::string &nickname);
 

	
 
		virtual void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) = 0;
 
		virtual void handleLogoutRequest(const std::string &user, const std::string &legacyName) = 0;
 
		virtual void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message) = 0;
 
		virtual void handleJoinRoomRequest(const std::string &/*user*/, const std::string &/*room*/, const std::string &/*nickname*/, const std::string &/*pasword*/) {}
 
		virtual void handleLeaveRoomRequest(const std::string &/*user*/, const std::string &/*room*/) {}
 
		
 

	
 
	private:
 
		void connect();
 
		void handleLoginPayload(const std::string &payload);
 
		void handleLogoutPayload(const std::string &payload);
 
		void handleConvMessagePayload(const std::string &payload);
 
		void handleJoinRoomPayload(const std::string &payload);
 
		void handleLeaveRoomPayload(const std::string &payload);
 
		void handleDataRead(const Swift::ByteArray&);
 
		void handleConnected(bool error);
 
		void handleDisconnected();
 

	
 
		void send(const std::string &data);
 
		void sendPong();
 

	
 
		std::string m_data;
 
		std::string m_host;
 
		int m_port;
 
		Swift::BoostNetworkFactories *m_factories;
 
		Swift::BoostIOServiceThread m_boostIOServiceThread;
 
		boost::shared_ptr<Swift::Connection> m_conn;
 
		Swift::Timer::ref m_reconnectTimer;
 

	
 
};
 

	
 
}
src/conversation.cpp
Show inline comments
 
/**
 
 * XMPP - libpurple transport
 
 *
 
 * Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
 
 *
 
 * This program is free software; you can redistribute it and/or modify
 
 * it under the terms of the GNU General Public License as published by
 
 * the Free Software Foundation; either version 2 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * This program is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU General Public License
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#include <iostream>
 
#include "transport/conversation.h"
 
#include "transport/conversationmanager.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/buddy.h"
 
#include "transport/rostermanager.h"
 

	
 
namespace Transport {
 

	
 
Conversation::Conversation(ConversationManager *conversationManager, const std::string &legacyName, bool isMUC) : m_conversationManager(conversationManager) {
 
	m_legacyName = legacyName;
 
	m_conversationManager->setConversation(this);
 
	m_muc = isMUC;
 
}
 

	
 
Conversation::~Conversation() {
 
	m_conversationManager->unsetConversation(this);
 
}
 

	
 
void Conversation::handleMessage(boost::shared_ptr<Swift::Message> &message, const std::string &nickname) {
 
	if (m_muc) {
 
		message->setType(Swift::Message::Groupchat);
 
	}
 
	else {
 
		message->setType(Swift::Message::Chat);
 
	}
 
	if (message->getType() != Swift::Message::Groupchat) {
 
		
 
		message->setTo(m_conversationManager->getUser()->getJID().toBare());
 
		// normal message
 
		if (nickname.empty()) {
 
			Buddy *buddy = m_conversationManager->getUser()->getRosterManager()->getBuddy(m_legacyName);
 
			if (buddy) {
 
				std::cout << m_legacyName << " 222222\n";
 
				message->setFrom(buddy->getJID());
 
			}
 
			else {
 
				std::cout << m_legacyName << " 1111111\n";
 
				// TODO: escape from and setFrom
 
			}
 
		}
 
		// PM message
 
		else {
 
			if (m_room.empty()) {
 
				message->setFrom(Swift::JID(nickname, m_conversationManager->getComponent()->getJID().toBare(), "user"));
 
			}
 
			else {
 
				message->setFrom(Swift::JID(m_room, m_conversationManager->getComponent()->getJID().toBare(), nickname));
 
			}
 
		}
 
		m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message);
 
	}
 
	else {
 
		message->setTo(m_conversationManager->getUser()->getJID().toString());
 
		message->setFrom(Swift::JID(m_legacyName, m_conversationManager->getComponent()->getJID().toBare(), nickname));
 
		m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message);
 
	}
 
}
 

	
 
void Conversation::handleParticipantChanged(const std::string &nick, int flag) {
 
void Conversation::handleParticipantChanged(const std::string &nick, int flag, const std::string &newname) {
 
	std::string nickname = nick;
 
	if (nickname.find("@") == 0) {
 
		nickname = nickname.substr(1);
 
	}
 
	Swift::Presence::ref presence = Swift::Presence::create();
 
 	presence->setFrom(Swift::JID(m_legacyName, m_conversationManager->getComponent()->getJID().toBare(), nickname));
 
	presence->setTo(m_conversationManager->getUser()->getJID().toString());
 
	presence->setType(Swift::Presence::Available);
 

	
 
	Swift::MUCUserPayload *p = new Swift::MUCUserPayload ();
 
	if (m_nickname == nickname) {
 
		Swift::MUCUserPayload::StatusCode c;
 
		c.code = 110;
 
		p->addStatusCode(c);
 
	}
 
	p->addItem(Swift::MUCUserPayload::Item(Swift::MUCOccupant::Member, Swift::MUCOccupant::Participant));
 

	
 
	Swift::MUCUserPayload::Item item(Swift::MUCOccupant::Member, Swift::MUCOccupant::Participant);
 
	if (!newname.empty()) {
 
		item.nick = newname;
 
		Swift::MUCUserPayload::StatusCode c;
 
		c.code = 303;
 
		p->addStatusCode(c);
 
	}
 

	
 
	p->addItem(item);
 

	
 
	presence->addPayload(boost::shared_ptr<Swift::Payload>(p));
 
	m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence);
 
}
 

	
 
}
src/networkplugin.cpp
Show inline comments
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
 
 *
 
 * This program is free software; you can redistribute it and/or modify
 
 * it under the terms of the GNU General Public License as published by
 
 * the Free Software Foundation; either version 2 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * This program is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU General Public License
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#include "transport/networkplugin.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/storagebackend.h"
 
#include "transport/rostermanager.h"
 
#include "transport/usermanager.h"
 
#include "transport/conversationmanager.h"
 
#include "Swiften/Swiften.h"
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Elements/StreamError.h"
 
#include "pbnetwork.pb.h"
 

	
 
namespace Transport {
 

	
 
#define WRAP(MESSAGE, TYPE) 	pbnetwork::WrapperMessage wrap; \
 
	wrap.set_type(TYPE); \
 
	wrap.set_payload(MESSAGE); \
 
	wrap.SerializeToString(&MESSAGE);
 

	
 
NetworkPlugin::NetworkPlugin(Swift::EventLoop *loop, const std::string &host, int port) {
 
	m_factories = new Swift::BoostNetworkFactories(loop);
 
	m_host = host;
 
	m_port = port;
 
	m_conn = m_factories->getConnectionFactory()->createConnection();
 
	m_conn->onDataRead.connect(boost::bind(&NetworkPlugin::handleDataRead, this, _1));
 
	m_conn->onConnectFinished.connect(boost::bind(&NetworkPlugin::handleConnected, this, _1));
 
	m_conn->onDisconnected.connect(boost::bind(&NetworkPlugin::handleDisconnected, this));
 

	
 
	m_reconnectTimer = m_factories->getTimerFactory()->createTimer(1000);
 
	m_reconnectTimer->onTick.connect(boost::bind(&NetworkPlugin::connect, this)); 
 
	connect();
 
}
 

	
 
NetworkPlugin::~NetworkPlugin() {
 
	delete m_factories;
 
}
 

	
 
void NetworkPlugin::handleMessage(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &nickname) {
 
	pbnetwork::ConversationMessage m;
 
	m.set_username(user);
 
	m.set_buddyname(legacyName);
 
	m.set_message(msg);
 
	m.set_nickname(nickname);
 

	
 
	std::string message;
 
	m.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_CONV_MESSAGE);
 
// 	std::cout << "SENDING MESSAGE\n";
 

	
 
	send(message);
 
}
 

	
 
void NetworkPlugin::handleBuddyChanged(const std::string &user, const std::string &buddyName, const std::string &alias,
 
			const std::string &groups, int status, const std::string &statusMessage, const std::string &iconHash) {
 
	pbnetwork::Buddy buddy;
 
	buddy.set_username(user);
 
	buddy.set_buddyname(buddyName);
 
	buddy.set_alias(alias);
 
	buddy.set_groups(groups);
 
	buddy.set_status(status);
 
	buddy.set_statusmessage(statusMessage);
 
	buddy.set_iconhash(iconHash);
 

	
 
	std::string message;
 
	buddy.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED);
 

	
 
	send(message);
 
}
 

	
 
void NetworkPlugin::handleDisconnected(const std::string &user, const std::string &legacyName, int error, const std::string &msg) {
 
	pbnetwork::Disconnected d;
 
	d.set_user(user);
 
	d.set_name(legacyName);
 
	d.set_error(error);
 
	d.set_message(msg);
 

	
 
	std::string message;
 
	d.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_DISCONNECTED);
 

	
 
	send(message);
 
}
 

	
 
void NetworkPlugin::handleParticipantChanged(const std::string &user, const std::string &nickname, const std::string &room, int flags) {
 
void NetworkPlugin::handleParticipantChanged(const std::string &user, const std::string &nickname, const std::string &room, int flags, const std::string &newname) {
 
	pbnetwork::Participant d;
 
	d.set_username(user);
 
	d.set_nickname(nickname);
 
	d.set_room(room);
 
	d.set_flag(flags);
 
	d.set_newname(newname);
 

	
 
	std::string message;
 
	d.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_PARTICIPANT_CHANGED);
 

	
 
	send(message);
 
}
 

	
 
void NetworkPlugin::handleRoomChanged(const std::string &user, const std::string &r, const std::string &nickname) {
 
	pbnetwork::Room room;
 
	room.set_username(user);
 
	room.set_nickname(nickname);
 
	room.set_room(r);
 
	room.set_password("");
 

	
 
	std::string message;
 
	room.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_ROOM_NICKNAME_CHANGED);
 
 
 
	send(message);
 
}
 

	
 
void NetworkPlugin::handleConnected(bool error) {
 
	if (error) {
 
		std::cout << "Connecting error\n";
 
// 		m_reconnectTimer->start();
 
		exit(1);
 
	}
 
	else {
 
		std::cout << "Connected\n";
 
		m_reconnectTimer->stop();
 
	}
 
}
 

	
 
void NetworkPlugin::handleDisconnected() {
 
	std::cout << "Disconnected\n";
 
// 	m_reconnectTimer->start();
 
	exit(1);
 
}
 

	
 
void NetworkPlugin::connect() {
 
	std::cout << "Trying to connect the server\n";
 
	m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(m_host), m_port));
 
	m_reconnectTimer->stop();
 
}
 

	
 
void NetworkPlugin::handleLoginPayload(const std::string &data) {
 
	pbnetwork::Login payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 
	handleLoginRequest(payload.user(), payload.legacyname(), payload.password());
 
}
 

	
 
void NetworkPlugin::handleLogoutPayload(const std::string &data) {
 
	pbnetwork::Logout payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 
	handleLogoutRequest(payload.user(), payload.legacyname());
 
}
 

	
 
void NetworkPlugin::handleConvMessagePayload(const std::string &data) {
 
	pbnetwork::ConversationMessage payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	handleMessageSendRequest(payload.username(), payload.buddyname(), payload.message());
 
}
 

	
 
void NetworkPlugin::handleJoinRoomPayload(const std::string &data) {
 
	pbnetwork::Room payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	handleJoinRoomRequest(payload.username(), payload.room(), payload.nickname(), payload.password());
 
}
 

	
 
void NetworkPlugin::handleLeaveRoomPayload(const std::string &data) {
 
	pbnetwork::Room payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	handleLeaveRoomRequest(payload.username(), payload.room());
 
}
 

	
 
void NetworkPlugin::handleDataRead(const Swift::ByteArray &data) {
 
	long expected_size = 0;
 
	m_data += data.toString();
 
// 	std::cout << "received data; size = " << m_data.size() << "\n";
 
	while (m_data.size() != 0) {
 
		if (m_data.size() >= 4) {
 
			expected_size = (((((m_data[0] << 8) | m_data[1]) << 8) | m_data[2]) << 8) | m_data[3];
 
// 			std::cout << "expected_size=" << expected_size << "\n";
 
			if (m_data.size() - 4 < expected_size)
 
				return;
 
		}
 
		else {
 
			return;
 
		}
 

	
 
		std::string msg = m_data.substr(4, expected_size);
 
		m_data.erase(0, 4 + expected_size);
 

	
 
		pbnetwork::WrapperMessage wrapper;
 
		if (wrapper.ParseFromString(msg) == false) {
 
			// TODO: ERROR
 
			return;
 
		}
 

	
 
		switch(wrapper.type()) {
 
			case pbnetwork::WrapperMessage_Type_TYPE_LOGIN:
 
				handleLoginPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_LOGOUT:
 
				handleLogoutPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_PING:
 
				sendPong();
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_CONV_MESSAGE:
 
				handleConvMessagePayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_JOIN_ROOM:
 
				handleJoinRoomPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_LEAVE_ROOM:
 
				handleLeaveRoomPayload(wrapper.payload());
 
				break;
 
			default:
 
				return;
 
		}
 
	}
 
}
 

	
 
void NetworkPlugin::send(const std::string &data) {
 
	std::string header("    ");
 
// 	std::cout << data.size() << "\n";
 
	boost::int32_t size = data.size();
 
	for (int i = 0; i != 4; ++i) {
 
		header.at(i) = static_cast<char>(size >> (8 * (3 - i)));
 
// 		std::cout << std::hex << (int) header.at(i) << "\n";
 
	}
 

	
 
	m_conn->write(Swift::ByteArray(header + data));
 
}
 

	
 
void NetworkPlugin::sendPong() {
 
	std::string message;
 
	pbnetwork::WrapperMessage wrap;
 
	wrap.set_type(pbnetwork::WrapperMessage_Type_TYPE_PONG);
 
	wrap.SerializeToString(&message);
 

	
 
	send(message);
 
// 	std::cout << "SENDING PONG\n";
 
}
 

	
 
}
src/networkpluginserver.cpp
Show inline comments
 
@@ -21,397 +21,397 @@
 
#include "transport/networkpluginserver.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/storagebackend.h"
 
#include "transport/rostermanager.h"
 
#include "transport/usermanager.h"
 
#include "transport/conversationmanager.h"
 
#include "transport/localbuddy.h"
 
#include "transport/config.h"
 
#include "transport/conversation.h"
 
#include "Swiften/Swiften.h"
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Elements/StreamError.h"
 
#include "pbnetwork.pb.h"
 
#include "sys/wait.h"
 
#include "sys/signal.h"
 

	
 
namespace Transport {
 

	
 
class NetworkConversation : public Conversation {
 
	public:
 
		NetworkConversation(ConversationManager *conversationManager, const std::string &legacyName, bool muc = false) : Conversation(conversationManager, legacyName, muc) {
 
		}
 

	
 
		void sendMessage(boost::shared_ptr<Swift::Message> &message) {
 
			onMessageToSend(this, message);
 
		}
 

	
 
		boost::signal<void (NetworkConversation *, boost::shared_ptr<Swift::Message> &)> onMessageToSend;
 
};
 

	
 
class NetworkFactory : public Factory {
 
	public:
 
		NetworkFactory(NetworkPluginServer *nps) {
 
			m_nps = nps;
 
		}
 
		
 
		Conversation *createConversation(ConversationManager *conversationManager, const std::string &legacyName) {
 
			NetworkConversation *nc = new NetworkConversation(conversationManager, legacyName);
 
			nc->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, m_nps, _1, _2));
 
			return nc;
 
		}
 

	
 
		Buddy *createBuddy(RosterManager *rosterManager, const BuddyInfo &buddyInfo) {
 
			return new LocalBuddy(rosterManager, -1);
 
		}
 
	private:
 
		NetworkPluginServer *m_nps;
 
};
 

	
 
#define WRAP(MESSAGE, TYPE) 	pbnetwork::WrapperMessage wrap; \
 
	wrap.set_type(TYPE); \
 
	wrap.set_payload(MESSAGE); \
 
	wrap.SerializeToString(&MESSAGE);
 
	
 
static int exec_(const char *path, const char *host, const char *port, const char *config) {
 
// 	char *argv[] = {(char*)script_name, '\0'}; 
 
	int status = 0;
 
	pid_t pid = fork();
 
	if ( pid == 0 ) {
 
		// child process
 
		execlp(path, path, "--host", host, "--port", port, config, NULL);
 
		exit(1);
 
	} else if ( pid < 0 ) {
 
		// fork failed
 
		status = -1;
 
	}
 
	return status;
 
}
 

	
 
static void SigCatcher(int n) {
 
	wait3(NULL,WNOHANG,NULL);
 
}
 

	
 
static void handleBuddyPayload(LocalBuddy *buddy, const pbnetwork::Buddy &payload) {
 
	buddy->setName(payload.buddyname());
 
	buddy->setAlias(payload.alias());
 
	std::vector<std::string> groups;
 
	groups.push_back(payload.groups());
 
	buddy->setGroups(groups);
 
	buddy->setStatus(Swift::StatusShow((Swift::StatusShow::Type) payload.status()), payload.statusmessage());
 
	buddy->setIconHash(payload.iconhash());
 
}
 

	
 
NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, UserManager *userManager) {
 
	m_userManager = userManager;
 
	m_config = config;
 
	component->m_factory = new NetworkFactory(this);
 
	m_pongReceived = false;
 
	m_userManager->onUserCreated.connect(boost::bind(&NetworkPluginServer::handleUserCreated, this, _1));
 
	m_userManager->onUserDestroyed.connect(boost::bind(&NetworkPluginServer::handleUserDestroyed, this, _1));
 

	
 
	m_pingTimer = component->getFactories()->getTimerFactory()->createTimer(10000);
 
	m_pingTimer->onTick.connect(boost::bind(&NetworkPluginServer::pingTimeout, this)); 
 

	
 
	m_server = component->getFactories()->getConnectionFactory()->createConnectionServer(10000);
 
	m_server->onNewConnection.connect(boost::bind(&NetworkPluginServer::handleNewClientConnection, this, _1));
 
	m_server->start();
 

	
 
	signal(SIGCHLD, SigCatcher);
 

	
 
	exec_(CONFIG_STRING(m_config, "service.backend").c_str(), "localhost", "10000", m_config->getConfigFile().c_str());
 
}
 

	
 
NetworkPluginServer::~NetworkPluginServer() {
 
	m_pingTimer->stop();
 
}
 

	
 
void NetworkPluginServer::handleNewClientConnection(boost::shared_ptr<Swift::Connection> c) {
 
	if (m_client) {
 
		c->disconnect();
 
	}
 
	m_client = c;
 
	m_pongReceived = false;
 
	
 

	
 
	c->onDisconnected.connect(boost::bind(&NetworkPluginServer::handleSessionFinished, this, c));
 
	c->onDataRead.connect(boost::bind(&NetworkPluginServer::handleDataRead, this, c, _1));
 
	sendPing();
 
	m_pingTimer->start();
 
}
 

	
 
void NetworkPluginServer::handleSessionFinished(boost::shared_ptr<Swift::Connection> c) {
 
	if (c == m_client) {
 
		m_client.reset();
 
	}
 
	m_pingTimer->stop();
 
	exec_(CONFIG_STRING(m_config, "service.backend").c_str(), "localhost", "10000", m_config->getConfigFile().c_str());
 
}
 

	
 
void NetworkPluginServer::handleConnectedPayload(const std::string &data) {
 
	pbnetwork::Connected payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 
// 	std::cout << payload.name() << "\n";
 
}
 

	
 
void NetworkPluginServer::handleDisconnectedPayload(const std::string &data) {
 
	pbnetwork::Disconnected payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	User *user = m_userManager->getUser(payload.user());
 
	if (!user)
 
		return;
 

	
 
	user->handleDisconnected(payload.message());
 
}
 

	
 
void NetworkPluginServer::handleBuddyChangedPayload(const std::string &data) {
 
	pbnetwork::Buddy payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	User *user = m_userManager->getUser(payload.username());
 
	if (!user)
 
		return;
 

	
 
	LocalBuddy *buddy = (LocalBuddy *) user->getRosterManager()->getBuddy(payload.buddyname());
 
	if (buddy) {
 
		handleBuddyPayload(buddy, payload);
 
		buddy->buddyChanged();
 
	}
 
	else {
 
		buddy = new LocalBuddy(user->getRosterManager(), -1);
 
		handleBuddyPayload(buddy, payload);
 
		user->getRosterManager()->setBuddy(buddy);
 
	}
 
}
 

	
 
void NetworkPluginServer::handleParticipantChangedPayload(const std::string &data) {
 
	pbnetwork::Participant payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	User *user = m_userManager->getUser(payload.username());
 
	if (!user)
 
		return;
 

	
 
	NetworkConversation *conv = (NetworkConversation *) user->getConversationManager()->getConversation(payload.room());
 
	if (!conv) {
 
		return;
 
	}
 

	
 
	conv->handleParticipantChanged(payload.nickname(), payload.flag());
 
	conv->handleParticipantChanged(payload.nickname(), payload.flag(), payload.newname());
 

	
 
// 	LocalBuddy *buddy = (LocalBuddy *) user->getRosterManager()->getBuddy(payload.buddyname());
 
// 	if (buddy) {
 
// 		handleBuddyPayload(buddy, payload);
 
// 		buddy->buddyChanged();
 
// 	}
 
// 	else {
 
// 		buddy = new LocalBuddy(user->getRosterManager(), -1);
 
// 		handleBuddyPayload(buddy, payload);
 
// 		user->getRosterManager()->setBuddy(buddy);
 
// 	}
 
	std::cout << payload.nickname() << "\n";
 
// 	std::cout << payload.nickname() << "\n";
 
}
 

	
 
void NetworkPluginServer::handleRoomChangedPayload(const std::string &data) {
 
	pbnetwork::Room payload;
 
	if (payload.ParseFromString(data) == false) {
 
		return;
 
	}
 

	
 
	User *user = m_userManager->getUser(payload.username());
 
	if (!user)
 
		return;
 

	
 
	NetworkConversation *conv = (NetworkConversation *) user->getConversationManager()->getConversation(payload.room());
 
	if (!conv) {
 
		return;
 
	}
 

	
 
	conv->setNickname(payload.nickname());
 
}
 

	
 
void NetworkPluginServer::handleConvMessagePayload(const std::string &data) {
 
	pbnetwork::ConversationMessage payload;
 
// 	std::cout << "payload...\n";
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 
// 	std::cout << "payload 2...\n";
 
	User *user = m_userManager->getUser(payload.username());
 
	if (!user)
 
		return;
 

	
 
	boost::shared_ptr<Swift::Message> msg(new Swift::Message());
 
	msg->setBody(payload.message());
 

	
 
	NetworkConversation *conv = (NetworkConversation *) user->getConversationManager()->getConversation(payload.buddyname());
 
	if (!conv) {
 
		conv = new NetworkConversation(user->getConversationManager(), payload.buddyname());
 
		conv->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, this, _1, _2));
 
	}
 

	
 
	conv->handleMessage(msg, payload.nickname());
 
}
 

	
 
void NetworkPluginServer::handleDataRead(boost::shared_ptr<Swift::Connection> c, const Swift::ByteArray &data) {
 
	long expected_size = 0;
 
	m_data += data.toString();
 
// 	std::cout << "received data; size = " << m_data.size() << "\n";
 
	while (m_data.size() != 0) {
 
		if (m_data.size() >= 4) {
 
			unsigned char * head = (unsigned char*) m_data.c_str();
 
			expected_size = (((((*head << 8) | *(head + 1)) << 8) | *(head + 2)) << 8) | *(head + 3);
 
			//expected_size = m_data[0];
 
// 			std::cout << "expected_size=" << expected_size << "\n";
 
			if (m_data.size() - 4 < expected_size)
 
				return;
 
		}
 
		else {
 
			return;
 
		}
 

	
 
		std::string msg = m_data.substr(4, expected_size);
 
		m_data.erase(0, 4 + expected_size);
 

	
 
		pbnetwork::WrapperMessage wrapper;
 
		if (wrapper.ParseFromString(msg) == false) {
 
			// TODO: ERROR
 
			return;
 
		}
 

	
 
		switch(wrapper.type()) {
 
			case pbnetwork::WrapperMessage_Type_TYPE_CONNECTED:
 
				handleConnectedPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_DISCONNECTED:
 
				handleDisconnectedPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED:
 
				handleBuddyChangedPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_CONV_MESSAGE:
 
				handleConvMessagePayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_PONG:
 
				m_pongReceived = true;
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_PARTICIPANT_CHANGED:
 
				handleParticipantChangedPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_ROOM_NICKNAME_CHANGED:
 
				handleRoomChangedPayload(wrapper.payload());
 
				break;
 
			default:
 
				return;
 
		}
 
	}
 
}
 

	
 
void NetworkPluginServer::send(boost::shared_ptr<Swift::Connection> &c, const std::string &data) {
 
	std::string header("    ");
 
	for (int i = 0; i != 4; ++i)
 
		header.at(i) = static_cast<char>(data.size() >> (8 * (3 - i)));
 
	
 
	c->write(Swift::ByteArray(header + data));
 
}
 

	
 
void NetworkPluginServer::pingTimeout() {
 
	std::cout << "pingtimeout\n";
 
	if (m_pongReceived) {
 
		sendPing();
 
		m_pingTimer->start();
 
	}
 
	else {
 
		exec_(CONFIG_STRING(m_config, "service.backend").c_str(), "localhost", "10000", m_config->getConfigFile().c_str());
 
	}
 
}
 

	
 
void NetworkPluginServer::handleUserCreated(User *user) {
 
// 	UserInfo userInfo = user->getUserInfo();
 
	user->onReadyToConnect.connect(boost::bind(&NetworkPluginServer::handleUserReadyToConnect, this, user));
 
	user->onRoomJoined.connect(boost::bind(&NetworkPluginServer::handleRoomJoined, this, user, _1, _2, _3));
 
	user->onRoomLeft.connect(boost::bind(&NetworkPluginServer::handleRoomLeft, this, user, _1));
 
}
 

	
 
void NetworkPluginServer::handleUserReadyToConnect(User *user) {
 
	UserInfo userInfo = user->getUserInfo();
 

	
 
	pbnetwork::Login login;
 
	login.set_user(user->getJID().toBare());
 
	login.set_legacyname(userInfo.uin);
 
	login.set_password(userInfo.password);
 

	
 
	std::string message;
 
	login.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_LOGIN);
 

	
 
	send(m_client, message);
 
}
 

	
 
void NetworkPluginServer::handleRoomJoined(User *user, const std::string &r, const std::string &nickname, const std::string &password) {
 
	UserInfo userInfo = user->getUserInfo();
 

	
 
	pbnetwork::Room room;
 
	room.set_username(user->getJID().toBare());
 
	room.set_nickname(nickname);
 
	room.set_room(r);
 
	room.set_password(password);
 

	
 
	std::string message;
 
	room.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_JOIN_ROOM);
 
 
 
	send(m_client, message);
 

	
 
	NetworkConversation *conv = new NetworkConversation(user->getConversationManager(), r, true);
 
	conv->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, this, _1, _2));
 
	conv->setNickname(nickname);
 
}
 

	
 
void NetworkPluginServer::handleRoomLeft(User *user, const std::string &r) {
 
	UserInfo userInfo = user->getUserInfo();
 

	
 
	pbnetwork::Room room;
 
	room.set_username(user->getJID().toBare());
 
	room.set_nickname("");
 
	room.set_room(r);
 
	room.set_password("");
 

	
 
	std::string message;
 
	room.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_LEAVE_ROOM);
 
 
 
	send(m_client, message);
 

	
 
	NetworkConversation *conv = (NetworkConversation *) user->getConversationManager()->getConversation(r);
 
	if (!conv) {
 
		return;
 
	}
 

	
 
	delete conv;
 
}
 

	
 
void NetworkPluginServer::handleUserDestroyed(User *user) {
 
	UserInfo userInfo = user->getUserInfo();
 

	
 
	pbnetwork::Logout logout;
 
	logout.set_user(user->getJID().toBare());
 
	logout.set_legacyname(userInfo.uin);
 

	
src/pbnetwork.proto
Show inline comments
 
package pbnetwork;
 

	
 
message Connected {
 
	required string user = 1;
 
	required string name = 2;
 
}
 

	
 
message Disconnected {
 
	required string user = 1;
 
	required string name = 2;
 
	required int32 error = 3;
 
	optional string message = 4;
 
}
 

	
 
message Login {
 
	required string user = 1;
 
	required string legacyName = 2;
 
	required string password = 3;
 
}
 

	
 
message Logout {
 
	required string user = 1;
 
	required string legacyName = 2;
 
}
 

	
 
message Buddy {
 
	required string userName = 1;
 
	required string buddyName = 2;
 
	required string alias = 3;
 
	required string groups = 4;
 
	required int32 status = 5;
 
	optional string statusMessage = 6;
 
	optional string iconHash = 7;
 
}
 

	
 
message ConversationMessage {
 
	required string userName = 1;
 
	required string buddyName = 2;
 
	required string message = 3;
 
	optional string nickname = 4;
 
}
 

	
 
message Room {
 
	required string userName = 1;
 
	required string nickname = 2;
 
	required string room = 3;
 
	optional string password = 4;
 
}
 

	
 
message Participant {
 
	required string userName = 1;
 
	required string room = 2;
 
	required string nickname = 3;
 
	required int32 flag = 4;
 
	optional string newname = 5;
 
}
 

	
 
message WrapperMessage {
 
	enum Type { 
 
		TYPE_CONNECTED 				= 1;
 
		TYPE_DISCONNECTED 			= 2;
 
		TYPE_LOGIN 					= 3;
 
		TYPE_LOGOUT 				= 4;
 
		TYPE_BUDDY_CHANGED			= 6;
 
		TYPE_BUDDY_REMOVED			= 7;
 
		TYPE_CONV_MESSAGE			= 8;
 
		TYPE_PING					= 9;
 
		TYPE_PONG					= 10;
 
		TYPE_JOIN_ROOM				= 11;
 
		TYPE_LEAVE_ROOM				= 12;
 
		TYPE_PARTICIPANT_CHANGED	= 13;
 
		TYPE_PARTICIPANT_LEFT		= 14;
 
		TYPE_ROOM_NICKNAME_CHANGED	= 15;
 
	}
 
	required Type type = 1;
 
	optional bytes payload = 2;
 
}
 
;
 
\ No newline at end of file
0 comments (0 inline, 0 general)