spectrum2/src/networkplugin.cpp

505 lines
14 KiB
C++
Raw Normal View History

2011-05-11 09:20:35 +02:00
/**
* 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"
#include "log4cxx/logger.h"
#include "log4cxx/basicconfigurator.h"
using namespace log4cxx;
static LoggerPtr logger = Logger::getLogger("NetworkPlugin");
2011-05-11 09:20:35 +02:00
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_pingReceived = false;
2011-05-11 09:20:35 +02:00
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));
2011-05-11 09:20:35 +02:00
m_conn->onDisconnected.connect(boost::bind(&NetworkPlugin::handleDisconnected, this));
m_pingTimer = m_factories->getTimerFactory()->createTimer(30000);
m_pingTimer->onTick.connect(boost::bind(&NetworkPlugin::pingTimeout, this));
2011-05-11 09:20:35 +02:00
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) {
2011-05-13 23:37:48 +02:00
pbnetwork::ConversationMessage m;
m.set_username(user);
m.set_buddyname(legacyName);
m.set_message(msg);
m.set_nickname(nickname);
2011-05-13 23:37:48 +02:00
std::string message;
m.SerializeToString(&message);
WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_CONV_MESSAGE);
send(message);
}
void NetworkPlugin::handleAttention(const std::string &user, const std::string &buddyName, const std::string &msg) {
pbnetwork::ConversationMessage m;
m.set_username(user);
m.set_buddyname(buddyName);
m.set_message(msg);
std::string message;
m.SerializeToString(&message);
WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_ATTENTION);
2011-05-13 23:37:48 +02:00
send(message);
}
2011-06-02 09:54:57 +02:00
void NetworkPlugin::handleVCard(const std::string &user, unsigned int id, const std::string &legacyName, const std::string &fullName, const std::string &nickname, const std::string &photo) {
pbnetwork::VCard vcard;
vcard.set_username(user);
vcard.set_buddyname(legacyName);
vcard.set_id(id);
vcard.set_fullname(fullName);
vcard.set_nickname(nickname);
vcard.set_photo(photo);
std::string message;
vcard.SerializeToString(&message);
WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_VCARD);
send(message);
}
2011-05-19 12:46:20 +02:00
void NetworkPlugin::handleSubject(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_ROOM_SUBJECT_CHANGED);
// std::cout << "SENDING MESSAGE\n";
send(message);
}
2011-05-11 09:20:35 +02:00
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::handleBuddyTyping(const std::string &user, const std::string &buddyName) {
pbnetwork::Buddy buddy;
buddy.set_username(user);
buddy.set_buddyname(buddyName);
std::string message;
buddy.SerializeToString(&message);
WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BUDDY_TYPING);
send(message);
}
void NetworkPlugin::handleBuddyTyped(const std::string &user, const std::string &buddyName) {
pbnetwork::Buddy buddy;
buddy.set_username(user);
buddy.set_buddyname(buddyName);
std::string message;
buddy.SerializeToString(&message);
WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BUDDY_TYPED);
send(message);
}
void NetworkPlugin::handleBuddyStoppedTyping(const std::string &user, const std::string &buddyName) {
pbnetwork::Buddy buddy;
buddy.set_username(user);
buddy.set_buddyname(buddyName);
std::string message;
buddy.SerializeToString(&message);
WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BUDDY_STOPPED_TYPING);
send(message);
}
void NetworkPlugin::handleAuthorization(const std::string &user, const std::string &buddyName) {
pbnetwork::Buddy buddy;
buddy.set_username(user);
buddy.set_buddyname(buddyName);
std::string message;
buddy.SerializeToString(&message);
WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_AUTH_REQUEST);
send(message);
}
void NetworkPlugin::handleConnected(const std::string &user) {
std::cout << "LOGIN SENT\n";
pbnetwork::Connected d;
d.set_user(user);
std::string message;
d.SerializeToString(&message);
WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_CONNECTED);
send(message);
}
2011-05-11 09:20:35 +02:00
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);
}
2011-05-19 08:26:09 +02:00
void NetworkPlugin::handleParticipantChanged(const std::string &user, const std::string &nickname, const std::string &room, int flags, int status, const std::string &statusMessage, const std::string &newname) {
2011-05-17 09:44:29 +02:00
pbnetwork::Participant d;
d.set_username(user);
d.set_nickname(nickname);
d.set_room(room);
d.set_flag(flags);
2011-05-19 00:33:38 +02:00
d.set_newname(newname);
2011-05-19 08:26:09 +02:00
d.set_status(status);
d.set_statusmessage(statusMessage);
2011-05-17 09:44:29 +02:00
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) {
2011-05-11 09:20:35 +02:00
if (error) {
LOG4CXX_ERROR(logger, "Connecting error. Exiting");
m_pingTimer->stop();
2011-05-14 10:34:18 +02:00
exit(1);
2011-05-11 09:20:35 +02:00
}
else {
LOG4CXX_INFO(logger, "Connected to NetworkPluginServer");
m_pingTimer->start();
2011-05-11 09:20:35 +02:00
}
}
void NetworkPlugin::handleDisconnected() {
LOG4CXX_INFO(logger, "Disconnected from NetworkPluginServer. Exiting.");
m_pingTimer->stop();
2011-05-14 10:34:18 +02:00
exit(1);
2011-05-11 09:20:35 +02:00
}
void NetworkPlugin::connect() {
LOG4CXX_INFO(logger, "Connecting NetworkPluginServer host " << m_host << " port " << m_port);
2011-05-11 09:20:35 +02:00
m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(m_host), m_port));
}
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());
}
2011-06-12 12:27:57 +02:00
void NetworkPlugin::handleStatusChangedPayload(const std::string &data) {
pbnetwork::Status payload;
if (payload.ParseFromString(data) == false) {
// TODO: ERROR
return;
}
handleStatusChangeRequest(payload.username(), payload.status(), payload.statusmessage());
}
2011-05-14 15:31:29 +02:00
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::handleAttentionPayload(const std::string &data) {
pbnetwork::ConversationMessage payload;
if (payload.ParseFromString(data) == false) {
// TODO: ERROR
return;
}
handleAttentionRequest(payload.username(), payload.buddyname(), payload.message());
}
2011-05-15 15:18:31 +02:00
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());
}
2011-05-18 15:32:54 +02:00
void NetworkPlugin::handleLeaveRoomPayload(const std::string &data) {
pbnetwork::Room payload;
if (payload.ParseFromString(data) == false) {
// TODO: ERROR
return;
}
handleLeaveRoomRequest(payload.username(), payload.room());
}
2011-06-02 09:54:57 +02:00
void NetworkPlugin::handleVCardPayload(const std::string &data) {
pbnetwork::VCard payload;
if (payload.ParseFromString(data) == false) {
// TODO: ERROR
return;
}
2011-06-14 15:45:32 +02:00
if (payload.has_photo()) {
handleVCardUpdatedRequest(payload.username(), payload.photo());
}
else if (!payload.buddyname().empty()) {
handleVCardRequest(payload.username(), payload.buddyname(), payload.id());
}
2011-06-02 09:54:57 +02:00
}
2011-06-09 13:54:09 +02:00
void NetworkPlugin::handleBuddyChangedPayload(const std::string &data) {
pbnetwork::Buddy payload;
if (payload.ParseFromString(data) == false) {
// TODO: ERROR
return;
}
handleBuddyUpdatedRequest(payload.username(), payload.buddyname(), payload.alias(), payload.groups());
}
2011-06-10 10:24:09 +02:00
void NetworkPlugin::handleBuddyRemovedPayload(const std::string &data) {
pbnetwork::Buddy payload;
if (payload.ParseFromString(data) == false) {
// TODO: ERROR
return;
}
handleBuddyRemovedRequest(payload.username(), payload.buddyname(), payload.groups());
}
void NetworkPlugin::handleChatStatePayload(const std::string &data, Swift::ChatState::ChatStateType type) {
pbnetwork::Buddy payload;
if (payload.ParseFromString(data) == false) {
// TODO: ERROR
return;
}
switch(type) {
case Swift::ChatState::Composing:
handleTypingRequest(payload.username(), payload.buddyname());
break;
case Swift::ChatState::Paused:
handleTypedRequest(payload.username(), payload.buddyname());
break;
case Swift::ChatState::Active:
handleStoppedTypingRequest(payload.username(), payload.buddyname());
break;
default:
break;
}
}
void NetworkPlugin::handleDataRead(const Swift::SafeByteArray &data) {
2011-06-08 16:36:30 +02:00
m_data.insert(m_data.end(), data.begin(), data.end());
2011-05-11 09:20:35 +02:00
while (m_data.size() != 0) {
unsigned int expected_size;
2011-05-11 09:20:35 +02:00
if (m_data.size() >= 4) {
expected_size = *((unsigned int*) &m_data[0]);
expected_size = ntohl(expected_size);
2011-05-11 09:20:35 +02:00
if (m_data.size() - 4 < expected_size)
return;
}
else {
return;
}
pbnetwork::WrapperMessage wrapper;
if (wrapper.ParseFromArray(&m_data[4], expected_size) == false) {
m_data.erase(m_data.begin(), m_data.begin() + 4 + expected_size);
2011-05-11 09:20:35 +02:00
return;
}
m_data.erase(m_data.begin(), m_data.begin() + 4 + expected_size);
2011-05-11 09:20:35 +02:00
switch(wrapper.type()) {
case pbnetwork::WrapperMessage_Type_TYPE_LOGIN:
handleLoginPayload(wrapper.payload());
break;
case pbnetwork::WrapperMessage_Type_TYPE_LOGOUT:
handleLogoutPayload(wrapper.payload());
break;
2011-05-13 10:54:03 +02:00
case pbnetwork::WrapperMessage_Type_TYPE_PING:
sendPong();
break;
2011-05-14 15:31:29 +02:00
case pbnetwork::WrapperMessage_Type_TYPE_CONV_MESSAGE:
handleConvMessagePayload(wrapper.payload());
break;
2011-05-15 15:18:31 +02:00
case pbnetwork::WrapperMessage_Type_TYPE_JOIN_ROOM:
handleJoinRoomPayload(wrapper.payload());
break;
2011-05-18 15:32:54 +02:00
case pbnetwork::WrapperMessage_Type_TYPE_LEAVE_ROOM:
handleLeaveRoomPayload(wrapper.payload());
break;
2011-06-02 09:54:57 +02:00
case pbnetwork::WrapperMessage_Type_TYPE_VCARD:
handleVCardPayload(wrapper.payload());
break;
2011-06-09 13:54:09 +02:00
case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED:
handleBuddyChangedPayload(wrapper.payload());
break;
2011-06-10 13:03:19 +02:00
case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_REMOVED:
handleBuddyRemovedPayload(wrapper.payload());
break;
2011-06-12 12:27:57 +02:00
case pbnetwork::WrapperMessage_Type_TYPE_STATUS_CHANGED:
handleStatusChangedPayload(wrapper.payload());
break;
case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_TYPING:
handleChatStatePayload(wrapper.payload(), Swift::ChatState::Composing);
break;
case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_TYPED:
handleChatStatePayload(wrapper.payload(), Swift::ChatState::Paused);
break;
case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_STOPPED_TYPING:
handleChatStatePayload(wrapper.payload(), Swift::ChatState::Active);
break;
case pbnetwork::WrapperMessage_Type_TYPE_ATTENTION:
handleAttentionPayload(wrapper.payload());
break;
2011-05-11 09:20:35 +02:00
default:
return;
}
}
}
void NetworkPlugin::send(const std::string &data) {
char header[4];
*((int*)(header)) = htonl(data.size());
m_conn->write(Swift::createSafeByteArray(std::string(header, 4) + data));
2011-05-11 09:20:35 +02:00
}
2011-05-13 10:54:03 +02:00
void NetworkPlugin::sendPong() {
m_pingReceived = true;
2011-05-13 10:54:03 +02:00
std::string message;
pbnetwork::WrapperMessage wrap;
wrap.set_type(pbnetwork::WrapperMessage_Type_TYPE_PONG);
wrap.SerializeToString(&message);
send(message);
LOG4CXX_INFO(logger, "PONG");
2011-05-13 10:54:03 +02:00
}
void NetworkPlugin::pingTimeout() {
if (m_pingReceived == false) {
LOG4CXX_ERROR(logger, "No PING received for long time (NetworkPluginServer crashed?). Exiting");
exit(1);
}
m_pingReceived = false;
2011-05-27 13:15:21 +02:00
m_pingTimer->start();
}
2011-05-11 09:20:35 +02:00
}