Merge branch 'master' of git://github.com/hanzz/libtransport into twitter-backend

This commit is contained in:
Sarang Bharadwaj 2012-06-15 15:45:39 +05:30
commit 0f3b28fded
12 changed files with 130 additions and 16 deletions

View file

@ -13,13 +13,25 @@ Version 2.0.0-beta3 (2012-XX-XX):
* Added Munin plugin (Thanks to Askovpen).
* Added support for more admin_jid JIDs (Thanks to Askovpen).
* Fixed allowed_servers option.
* Show error in server-mode when server port is already used.
* Fixed bug when backend could freeze on exit.
* Options from config file can now be set also using command line like
--service.jid=domain.tld .
* Do not send password in IQ-get registration response.
Libpurple:
* prpl-gg: Fetch the contact list properly (#252).
* Added support for prpl-novell as it was in spectrum1.
Skype:
* Log more errors.
Libyahoo2:
* Added new Yahoo backend based on libyahoo2.
Swiften:
* Added new XMPP backend based on Swiften library.
Backend API:
* Added Python NetworkPlugin class, so it is now easier to write backends
in Python (Thanks to Sarang).

View file

@ -78,7 +78,7 @@ int main (int argc, char* argv[]) {
Swift::QtEventLoop eventLoop;
if (config.getUnregistered().find("service.irc_server") == config.getUnregistered().end()) {
if (!CONFIG_HAS_KEY(&config, "service.irc_server")) {
np = new IRCNetworkPlugin(&config, &eventLoop, host, port);
}
else {

View file

@ -10,13 +10,19 @@ DEFINE_LOGGER(logger, "SingleIRCNetworkPlugin");
SingleIRCNetworkPlugin::SingleIRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port) {
this->config = config;
m_server = config->getUnregistered().find("service.irc_server")->second;
if (CONFIG_HAS_KEY(config, "service.irc_server")) {
m_server = CONFIG_STRING(config, "service.irc_server");
}
else {
LOG4CXX_ERROR(logger, "No [service] irc_server defined, exiting...");
exit(-1);
}
m_socket = new QTcpSocket();
m_socket->connectToHost(FROM_UTF8(host), port);
connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData()));
if (config->getUnregistered().find("service.irc_identify") != config->getUnregistered().end()) {
m_identify = config->getUnregistered().find("service.irc_identify")->second;
if (CONFIG_HAS_KEY(config, "service.irc_identify")) {
m_identify = CONFIG_STRING(config, "service.irc_identify");
}
else {
m_identify = "NickServ identify $name $password";

View file

@ -124,8 +124,8 @@ class SMSNetworkPlugin : public NetworkPlugin {
void handleSMSDir() {
std::string dir = "/var/spool/sms/incoming/";
if (config->getUnregistered().find("backend.incoming_dir") != config->getUnregistered().end()) {
dir = config->getUnregistered().find("backend.incoming_dir")->second;
if (CONFIG_HAS_KEY(config, "backend.incoming_dir")) {
dir = CONFIG_STRING(config, "backend.incoming_dir");
}
LOG4CXX_INFO(logger, "Checking directory " << dir << " for incoming SMS.");

View file

@ -77,7 +77,7 @@ class Config {
bool reload();
bool hasKey(const std::string &key) {
return m_variables.find(key) != m_variables.end();
return m_variables.find(key) != m_variables.end() || m_unregistered.find(key) != m_unregistered.end();
}
/// Returns value of variable defined by key.
@ -85,16 +85,15 @@ class Config {
/// For variables in sections you can use "section.variable" key format.
/// \param key config variable name
const boost::program_options::variable_value &operator[] (const std::string &key) {
return m_variables[key];
if (m_variables.find(key) != m_variables.end()) {
return m_variables[key];
}
return m_unregistered[key];
}
/// Returns path to config file from which data were loaded.
const std::string &getConfigFile() { return m_file; }
const std::map<std::string, std::string> &getUnregistered() {
return m_unregistered;
}
/// This signal is emitted when config is loaded/reloaded.
boost::signal<void ()> onConfigReloaded;
@ -102,7 +101,7 @@ class Config {
int m_argc;
char **m_argv;
Variables m_variables;
std::map<std::string, std::string> m_unregistered;
std::map<std::string, boost::program_options::variable_value> m_unregistered;
std::string m_file;
};

View file

@ -75,6 +75,11 @@ class NetworkPlugin {
bool blocked = false
);
/// Call this method when buddy is removed from legacy network contact list.
/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
/// \param buddyName Name of legacy network buddy. (eg. "user2@gmail.com")
void handleBuddyRemoved(const std::string &user, const std::string &buddyName);
/// Call this function when participant in room changed.
/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
/// \param nickname Nickname of participant. If participant renamed, this is old name of participant. (eg. "HanzZ")

View file

@ -89,6 +89,7 @@ class NetworkPluginServer {
void handleConnectedPayload(const std::string &payload);
void handleDisconnectedPayload(const std::string &payload);
void handleBuddyChangedPayload(const std::string &payload);
void handleBuddyRemovedPayload(const std::string &payload);
void handleConvMessagePayload(const std::string &payload, bool subject = false);
void handleParticipantChangedPayload(const std::string &payload);
void handleRoomChangedPayload(const std::string &payload);

View file

@ -69,6 +69,10 @@ class RosterManager {
/// \param buddy Buddy.
void unsetBuddy(Buddy *buddy);
/// Removes buddy from this roster, sends proper XML to XMPP side and deletes it.
/// \param name Buddy name.
void removeBuddy(const std::string &name);
Buddy *getBuddy(const std::string &name);
void setStorageBackend(StorageBackend *storageBackend);
@ -107,7 +111,11 @@ class RosterManager {
void sendBuddyRosterPush(Buddy *buddy);
void sendBuddyRosterRemove(Buddy *buddy);
void sendBuddySubscribePresence(Buddy *buddy);
void sendBuddyUnsubscribePresence(Buddy *buddy);
void sendCurrentPresences(const Swift::JID &to);

View file

@ -165,6 +165,19 @@ void NetworkPlugin::handleBuddyChanged(const std::string &user, const std::strin
send(message);
}
void NetworkPlugin::handleBuddyRemoved(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_REMOVED);
send(message);
}
void NetworkPlugin::handleBuddyTyping(const std::string &user, const std::string &buddyName) {
pbnetwork::Buddy buddy;
buddy.set_username(user);

View file

@ -195,7 +195,7 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
BOOST_FOREACH(option &opt, parsed.options) {
if (opt.unregistered) {
m_unregistered[opt.string_key] = opt.value[0];
m_unregistered[opt.string_key] = variable_value(opt.value[0], false);
}
else if (opt.value[0].find("$jid") != std::string::npos) {
boost::replace_all(opt.value[0], "$jid", jid);

View file

@ -264,6 +264,7 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U
LOG4CXX_INFO(logger, "Listening on host " << CONFIG_STRING(m_config, "service.backend_host") << " port " << CONFIG_STRING(m_config, "service.backend_port"));
unsigned long pid = exec_(CONFIG_STRING(m_config, "service.backend"), CONFIG_STRING(m_config, "service.backend_host").c_str(), CONFIG_STRING(m_config, "service.backend_port").c_str(), m_config->getConfigFile().c_str());
LOG4CXX_INFO(logger, "Tried to spawn first backend with pid " << pid);
LOG4CXX_INFO(logger, "Backend should now connect to Spectrum2 instance. Spectrum2 won't accept any connection before backend connects");
#ifndef _WIN32
@ -509,8 +510,6 @@ void NetworkPluginServer::handleBuddyChangedPayload(const std::string &data) {
if (!user)
return;
LOG4CXX_INFO(logger, "HANDLE BUDDY CHANGED " << payload.buddyname() << "-" << payload.alias());
LocalBuddy *buddy = (LocalBuddy *) user->getRosterManager()->getBuddy(payload.buddyname());
if (buddy) {
handleBuddyPayload(buddy, payload);
@ -524,6 +523,20 @@ void NetworkPluginServer::handleBuddyChangedPayload(const std::string &data) {
}
}
void NetworkPluginServer::handleBuddyRemovedPayload(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;
user->getRosterManager()->removeBuddy(payload.buddyname());
}
void NetworkPluginServer::handleParticipantChangedPayload(const std::string &data) {
pbnetwork::Participant payload;
if (payload.ParseFromString(data) == false) {
@ -828,6 +841,9 @@ void NetworkPluginServer::handleDataRead(Backend *c, boost::shared_ptr<Swift::Sa
case pbnetwork::WrapperMessage_Type_TYPE_FT_DATA:
handleFTDataPayload(c, wrapper.payload());
break;
case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_REMOVED:
handleBuddyRemovedPayload(wrapper.payload());
break;
default:
return;
}

View file

@ -99,6 +99,46 @@ void RosterManager::setBuddy(Buddy *buddy) {
setBuddyCallback(buddy);
}
void RosterManager::removeBuddy(const std::string &name) {
Buddy *buddy = getBuddy(name);
if (!buddy) {
LOG4CXX_WARN(logger, m_user->getJID().toString() << ": Tried to remove unknown buddy " << name);
return;
}
if (m_component->inServerMode() || m_remoteRosterRequest) {
sendBuddyRosterRemove(buddy);
}
else {
sendBuddyUnsubscribePresence(buddy);
}
unsetBuddy(buddy);
delete buddy;
}
void RosterManager::sendBuddyRosterRemove(Buddy *buddy) {
Swift::RosterPayload::ref p = Swift::RosterPayload::ref(new Swift::RosterPayload());
Swift::RosterItemPayload item;
item.setJID(buddy->getJID().toBare());
item.setSubscription(Swift::RosterItemPayload::Remove);
p->addItem(item);
// In server mode we have to send pushes to all resources, but in gateway-mode we send it only to bare JID
if (m_component->inServerMode()) {
std::vector<Swift::Presence::ref> presences = m_component->getPresenceOracle()->getAllPresence(m_user->getJID().toBare());
BOOST_FOREACH(Swift::Presence::ref presence, presences) {
Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, presence->getFrom(), m_component->getIQRouter());
request->send();
}
}
else {
Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, m_user->getJID().toBare(), m_component->getIQRouter());
request->send();
}
}
void RosterManager::sendBuddyRosterPush(Buddy *buddy) {
// user can't receive anything in server mode if he's not logged in.
// He will ask for roster later (handled in rosterreponsder.cpp)
@ -142,6 +182,20 @@ void RosterManager::sendBuddyRosterPush(Buddy *buddy) {
}
}
void RosterManager::sendBuddyUnsubscribePresence(Buddy *buddy) {
Swift::Presence::ref response = Swift::Presence::create();
response->setTo(m_user->getJID());
response->setFrom(buddy->getJID());
response->setType(Swift::Presence::Unsubscribe);
m_component->getStanzaChannel()->sendPresence(response);
response = Swift::Presence::create();
response->setTo(m_user->getJID());
response->setFrom(buddy->getJID());
response->setType(Swift::Presence::Unsubscribed);
m_component->getStanzaChannel()->sendPresence(response);
}
void RosterManager::sendBuddySubscribePresence(Buddy *buddy) {
Swift::Presence::ref response = Swift::Presence::create();
response->setTo(m_user->getJID());