Changeset - 0b81eb9c233f
[Not reviewed]
0 2 0
Jan Kaluza - 13 years ago 2012-05-23 14:46:06
hanzz.k@gmail.com
More yahoo related stuff
2 files changed with 138 insertions and 20 deletions:
0 comments (0 inline, 0 general)
backends/libyahoo2/main.cpp
Show inline comments
 
@@ -3,46 +3,60 @@
 
#include "transport/networkplugin.h"
 
#include "transport/logging.h"
 

	
 
// Yahoo2
 
#include <yahoo2.h>
 
#include <yahoo2_callbacks.h>
 
#include <stdio.h>
 
#include <stdarg.h>
 
#include <stdlib.h>
 

	
 
// Swiften
 
#include "Swiften/Swiften.h"
 
#include "Swiften/TLS/OpenSSL/OpenSSLContextFactory.h"
 

	
 
// for signal handler
 
#include "unistd.h"
 
#include "signal.h"
 
#include "sys/wait.h"
 
#include "sys/signal.h"
 

	
 
// Boost
 
#include <boost/algorithm/string.hpp>
 
using namespace boost::filesystem;
 
using namespace boost::program_options;
 
using namespace Transport;
 

	
 

	
 
typedef struct {
 
	int handler_tag;
 
	int conn_tag;
 
	void *data;
 
	yahoo_input_condition cond;
 
} yahoo_handler;
 

	
 
typedef struct {
 
	int id;
 
	boost::shared_ptr<Swift::Connection> conn;
 
	std::map<int, boost::shared_ptr<Swift::Connection> > conns;
 
	int conn_tag;
 
	std::map<int, yahoo_handler *> handlers;
 
	std::map<int, std::map<int, yahoo_handler *> > handlers_per_conn;
 
	int handler_tag;
 
	int status;
 
	std::string msg;
 
	std::string buffer;
 
} yahoo_local_account;
 

	
 
static std::string *currently_read_data;
 
static yahoo_local_account *currently_writting_account;
 

	
 
typedef struct {
 
	std::string yahoo_id;
 
	std::string name;
 
	int status;
 
	int away;
 
	std::string msg;
 
	std::string group;
 
} yahoo_account;
 

	
 
typedef struct {
 
	int id;
 
@@ -57,109 +71,164 @@ typedef struct {
 
DEFINE_LOGGER(logger, "Yahoo2");
 

	
 
// eventloop
 
Swift::SimpleEventLoop *loop_;
 

	
 
// Plugin
 
class YahooPlugin;
 
YahooPlugin * np = NULL;
 

	
 
class YahooPlugin : public NetworkPlugin {
 
	public:
 
		Swift::BoostNetworkFactories *m_factories;
 
		Swift::OpenSSLContextFactory *m_sslFactory;
 
		Swift::TLSConnectionFactory *m_tlsFactory;
 
		Swift::BoostIOServiceThread m_boostIOServiceThread;
 
		boost::shared_ptr<Swift::Connection> m_conn;
 

	
 
		YahooPlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() {
 
			this->config = config;
 
			m_factories = new Swift::BoostNetworkFactories(loop);
 
			m_sslFactory = new Swift::OpenSSLContextFactory();
 
			m_tlsFactory = new Swift::TLSConnectionFactory(m_sslFactory, m_factories->getConnectionFactory());
 
			m_conn = m_factories->getConnectionFactory()->createConnection();
 
			m_conn->onDataRead.connect(boost::bind(&YahooPlugin::_handleDataRead, this, _1));
 
			m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(host), port));
 

	
 
			LOG4CXX_INFO(logger, "Starting the plugin.");
 
		}
 

	
 
		// NetworkPlugin uses this method to send the data to networkplugin server
 
		void sendData(const std::string &string) {
 
			m_conn->write(Swift::createSafeByteArray(string));
 
		}
 

	
 
		// This method has to call handleDataRead with all received data from network plugin server
 
		void _handleDataRead(boost::shared_ptr<Swift::SafeByteArray> data) {
 
			std::string d(data->begin(), data->end());
 
			handleDataRead(d);
 
		}
 

	
 
		void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
 
			yahoo_local_account *account = new yahoo_local_account;
 
			account->conn_tag = 1;
 
			account->handler_tag = 1;
 
			m_users[user] = account;
 

	
 
			account->id = yahoo_init_with_attributes(legacyName.c_str(), password.c_str(), 
 
					"local_host", "",
 
					"pager_port", 5050,
 
					NULL);
 
			m_ids[account->id] = user;
 

	
 
			account->status = YAHOO_STATUS_OFFLINE;
 
			LOG4CXX_INFO(logger, user << ": Logging in the user as " << legacyName << " with id=" << account->id);
 
			yahoo_login(account->id, YAHOO_STATUS_AVAILABLE);
 

	
 

	
 
		}
 

	
 
		void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
 
		}
 

	
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "") {
 
			LOG4CXX_INFO(logger, "Sending message from " << user << " to " << legacyName << ".");
 
			if (legacyName == "echo") {
 
				handleMessage(user, legacyName, message);
 
			}
 
		}
 

	
 
		void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
 
			LOG4CXX_INFO(logger, user << ": Added buddy " << buddyName << ".");
 
			handleBuddyChanged(user, buddyName, alias, groups, pbnetwork::STATUS_ONLINE);
 
		}
 

	
 
		void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
 

	
 
		}
 

	
 
		void _yahoo_connect_finished(yahoo_local_account *account, yahoo_connect_callback callback, void *data, bool error) {
 
		yahoo_local_account *getAccount(int id) {
 
			return m_users[m_ids[id]];
 
		}
 

	
 
		void _yahoo_connect_finished(yahoo_local_account *account, yahoo_connect_callback callback, void *data, int conn_tag, bool error) {
 
			if (error) {
 
				LOG4CXX_ERROR(logger, "Connection error!");
 
				callback(NULL, 0, data);
 
// 				np->handleDisconnected(user, 0, "Connection error.");
 
			}
 
			else {
 
				callback(account->conn.get(), 0, data);
 
				LOG4CXX_INFO(logger, "Connected");
 
				// We will have dangling pointer here, but we can't pass boost::shared_ptr here...
 
				callback((void *) conn_tag, 0, data);
 
			}
 
		}
 

	
 
		void _yahoo_data_read(yahoo_local_account *account, boost::shared_ptr<Swift::SafeByteArray> data) {
 
		void _yahoo_data_read(yahoo_local_account *account, int conn_tag, boost::shared_ptr<Swift::SafeByteArray> data) {
 
			// yahoo_read_ready calls ext_yahoo_read(...) in a loop, so we just have to choose proper buffer from which will
 
			// that method read. We do that by static currently_read_data pointer.
 
			std::string d(data->begin(), data->end());
 
			currently_read_data = &d;
 
			yahoo_read_ready(account->id, account->conn.get(), NULL);
 

	
 
			LOG4CXX_INFO(logger, "data to read");
 
			for (std::map<int, yahoo_handler *>::iterator it = account->handlers_per_conn[conn_tag].begin(); it != account->handlers_per_conn[conn_tag].end(); it++) {
 
				if (it->second->cond == YAHOO_INPUT_READ) {
 
					LOG4CXX_INFO(logger, "found handler");
 
					std::string cpy(d);
 
					currently_read_data = &cpy;
 
					yahoo_read_ready(account->id, (void *) conn_tag, it->second->data);
 
				}
 
			}
 
		}
 

	
 
		void _yahoo_data_written(yahoo_local_account *account, int conn_tag) {
 
			LOG4CXX_INFO(logger, "data written");
 
			currently_writting_account = account;
 
			for (std::map<int, yahoo_handler *>::iterator it = account->handlers_per_conn[conn_tag].begin(); it != account->handlers_per_conn[conn_tag].end(); it++) {
 
				if (it->second->cond == YAHOO_INPUT_WRITE) {
 
					yahoo_write_ready(account->id, (void *) conn_tag, it->second->data);
 
				}
 
			}
 
		}
 

	
 
		int _yahoo_connect_async(int id, const char *host, int port, yahoo_connect_callback callback, void *data, int use_ssl) {
 
			yahoo_local_account *account = m_users[m_ids[id]];
 
			yahoo_local_account *account = getAccount(id);
 
			if (!account) {
 
				LOG4CXX_ERROR(logger, "Unknown account id=" << id);
 
				return -1;
 
			}
 

	
 
			account->conn = m_factories->getConnectionFactory()->createConnection();
 
			m_conn->onConnectFinished.connect(boost::bind(&YahooPlugin::_yahoo_connect_finished, this, account, callback, data, _1));
 
			m_conn->onDataRead.connect(boost::bind(&YahooPlugin::_yahoo_data_read, this, account, _1));
 
			account->conn->connect(Swift::HostAddressPort(Swift::HostAddress(host), port));
 
			return 0;
 
// boost::asio::io_service io_service;
 
// boost::asio::ip::tcp::resolver resolver(io_service);
 
// boost::asio::ip::tcp::resolver::query query(values[1], "");
 
// for(boost::asio::ip::tcp::resolver::iterator i = resolver.resolve(query);
 
//                             i != boost::asio::ip::tcp::resolver::iterator();
 
//                             ++i)
 
// {
 
//     boost::asio::ip::tcp::endpoint end = *i;
 
//     std::cout << end.address() << ' ';
 
// }
 
// std::cout << '\n';
 

	
 

	
 
			LOG4CXX_INFO(logger, m_ids[id] << ": Connecting " << host << ":" << port);
 
			int tag = account->conn_tag++;
 
			if (use_ssl) {
 
				account->conns[tag] = m_tlsFactory->createConnection();
 
			}
 
			else {
 
				account->conns[tag] = m_factories->getConnectionFactory()->createConnection();
 
			}
 
			account->conns[tag]->onConnectFinished.connect(boost::bind(&YahooPlugin::_yahoo_connect_finished, this, account, callback, data, tag, _1));
 
			account->conns[tag]->onDataRead.connect(boost::bind(&YahooPlugin::_yahoo_data_read, this, account, tag, _1));
 
			account->conns[tag]->onDataWritten.connect(boost::bind(&YahooPlugin::_yahoo_data_written, this, account, tag));
 
			account->conns[tag]->connect(Swift::HostAddressPort(Swift::HostAddress("67.195.187.249"), port));
 
			return tag;
 
		}
 

	
 
	private:
 
		Config *config;
 
		std::map<std::string, yahoo_local_account *> m_users;
 
		std::map<int, std::string> m_ids;
 
};
 

	
 
static void spectrum_sigchld_handler(int sig)
 
{
 
	int status;
 
	pid_t pid;
 
@@ -271,24 +340,25 @@ static void ext_yahoo_webcam_invite(int id, const char *me, const char *from) {
 
}
 

	
 
static void ext_yahoo_webcam_invite_reply(int id, const char *me, const char *from, int accept) {
 
}
 

	
 
static void ext_yahoo_system_message(int id, const char *me, const char *who, const char *msg) {
 
}
 

	
 
static void ext_yahoo_got_cookies(int id) {
 
}
 

	
 
static void ext_yahoo_login_response(int id, int succ, const char *url) {
 
	LOG4CXX_INFO(logger, "login_response");
 
// 	char buff[1024];
 
// 
 
// 	if(succ == YAHOO_LOGIN_OK) {
 
// 		ylad->status = yahoo_current_status(id);
 
// 		print_message(("logged in"));
 
// 		return;
 
// 		
 
// 	} else if(succ == YAHOO_LOGIN_UNAME) {
 
// 
 
// 		snprintf(buff, sizeof(buff), "Could not log into Yahoo service - username not recognised.  Please verify that your username is correctly typed.");
 
// 	} else if(succ == YAHOO_LOGIN_PASSWD) {
 
// 
 
@@ -344,42 +414,88 @@ static void ext_yahoo_error(int id, const char *_err, int fatal, int num) {
 
			msg += err + "server connection error %s";
 
			break;
 
	}
 
	LOG4CXX_ERROR(logger, msg);
 
// 	if(fatal)
 
// 		yahoo_logout();
 
}
 

	
 
static int ext_yahoo_connect(const char *host, int port) {
 
	return -1;
 
}
 

	
 
static int ext_yahoo_add_handler(int id, void *d, yahoo_input_condition cond, void *data) {
 
static int ext_yahoo_add_handler(int id, void *fd, yahoo_input_condition cond, void *data) {
 
	yahoo_local_account *account = np->getAccount(id);
 
	if (!account) {
 
		return -1;
 
	}
 

	
 
	LOG4CXX_INFO(logger, "Adding handler " << cond);
 

	
 
	int conn_tag = (unsigned long) fd;
 
	yahoo_handler *handler = new yahoo_handler;
 

	
 
	handler->conn_tag = conn_tag;
 
	handler->handler_tag = account->handler_tag++;
 
	handler->data = data;
 
	handler->cond = cond;
 

	
 
	if (cond == YAHOO_INPUT_WRITE) {
 
		yahoo_local_account *old = currently_writting_account;
 
		currently_writting_account = account;
 
		yahoo_write_ready(id, fd, data);
 
		currently_writting_account = old;
 
	}
 

	
 
	account->handlers[handler->handler_tag] = handler;
 
	account->handlers_per_conn[conn_tag][handler->handler_tag] = handler;
 

	
 
	return handler->handler_tag;
 
}
 

	
 
static void ext_yahoo_remove_handler(int id, int tag) {
 
	yahoo_local_account *account = np->getAccount(id);
 
	if (!account) {
 
		return;
 
	}
 

	
 
	if (account->handlers.find(tag) == account->handlers.end()) {
 
		return;
 
	}
 

	
 
	yahoo_handler *handler = account->handlers[tag];
 
	account->handlers.erase(tag);
 
	account->handlers_per_conn[handler->conn_tag].erase(tag);
 
	delete handler;
 
}
 

	
 
static int ext_yahoo_write(void *_conn, char *buf, int len) {
 
static int ext_yahoo_write(void *fd, char *buf, int len) {
 
	LOG4CXX_INFO(logger, "Writting " << len);
 

	
 
	int conn_tag = (unsigned long) fd;
 

	
 
	yahoo_local_account *account = currently_writting_account;
 

	
 
	std::string string(buf, len);
 
	Swift::Connection *conn = (Swift::Connection *) _conn;
 
	conn->write(Swift::createSafeByteArray(string));
 
	account->conns[conn_tag]->write(Swift::createSafeByteArray(string));
 

	
 
	return len;
 
}
 

	
 
static int ext_yahoo_read(void *fd, char *buf, int len) {
 
	if (currently_read_data->size() < len) {
 
		len = currently_read_data->size();
 
	}
 
	strncpy(buf, currently_read_data->c_str(), len);
 
	LOG4CXX_INFO(logger, "Reading " << len);
 
	memcpy(buf, currently_read_data->c_str(), len);
 
	currently_read_data->erase(0, len);
 
	return len;
 
}
 

	
 
static void ext_yahoo_close(void *fd) {
 
}
 

	
 
static int ext_yahoo_connect_async(int id, const char *host, int port, yahoo_connect_callback callback, void *data, int use_ssl) {
 
	return np->_yahoo_connect_async(id, host, port, callback, data, use_ssl);
 
}
 

	
 
static void ext_yahoo_got_file(int id, const char *me, const char *who, const char *msg, const char *fname, unsigned long fesize, char *trid) {
 
@@ -532,23 +648,25 @@ int main (int argc, char* argv[]) {
 

	
 

	
 
	if (argc < 5) {
 
		return 1;
 
	}
 

	
 
	Config config;
 
	if (!config.load(argv[5])) {
 
		std::cerr << "Can't open " << argv[1] << " configuration file.\n";
 
		return 1;
 
	}
 

	
 
	Swift::logging=true;
 
	Logging::initBackendLogging(&config);
 

	
 
	register_callbacks();
 
	yahoo_set_log_level(YAHOO_LOG_DEBUG);
 

	
 
	Swift::SimpleEventLoop eventLoop;
 
	loop_ = &eventLoop;
 
	np = new YahooPlugin(&config, &eventLoop, host, port);
 
	loop_->run();
 

	
 
	return 0;
 
}
spectrum/src/sample.cfg
Show inline comments
 
@@ -4,25 +4,25 @@ password = secret
 
server = 127.0.0.1
 
port = 5222
 
server_mode = 1
 
backend_host=localhost
 
pidfile=./test.pid
 
# < this option doesn't work yet
 
#backend_port=10001
 
#admin_jid=admin@localhost
 
admin_password=test
 
#cert=server.pfx #patch to PKCS#12 certificate
 
#cert_password=test #password to that certificate if any
 
users_per_backend=10
 
backend=../..//backends/swiften/spectrum2_swiften_backend
 
backend=../..//backends/libyahoo2/spectrum2_libyahoo2_backend
 
#backend=../../backends/template/template_backend.py
 
#protocol=prpl-jabber
 
protocol=prpl-msn
 
#protocol=any
 
#protocol=prpl-icq
 
working_dir=./
 

	
 
[backend]
 
#default_avatar=catmelonhead.jpg
 
#no_vcard_fetch=true
 

	
 
[logging]
0 comments (0 inline, 0 general)