Changeset - 1db5be3db8cf
[Not reviewed]
0 1 0
HanzZ - 14 years ago 2011-10-17 21:26:13
hanzz.k@gmail.com
Working libpurple FT again
1 file changed with 14 insertions and 8 deletions:
0 comments (0 inline, 0 general)
backends/libpurple/main.cpp
Show inline comments
 
@@ -1319,533 +1319,539 @@ static PurpleNotifyUiOps notifyUiOps =
 
		NULL,
 
		NULL,
 
		NULL,
 
		NULL,
 
		NULL,
 
		NULL,
 
		notify_user_info,
 
		NULL,
 
		NULL,
 
		NULL,
 
		NULL,
 
		NULL,
 
		NULL
 
};
 

	
 
static PurpleRequestUiOps requestUiOps =
 
{
 
	requestInput,
 
	NULL,
 
	requestAction,
 
	NULL,
 
	NULL,
 
	NULL, //requestClose,
 
	NULL,
 
	NULL,
 
	NULL,
 
	NULL,
 
	NULL
 
};
 

	
 
static void * accountRequestAuth(PurpleAccount *account, const char *remote_user, const char *id, const char *alias, const char *message, gboolean on_list, PurpleAccountRequestAuthorizationCb authorize_cb, PurpleAccountRequestAuthorizationCb deny_cb, void *user_data) {
 
	authRequest *req = new authRequest;
 
	req->authorize_cb = authorize_cb;
 
	req->deny_cb = deny_cb;
 
	req->user_data = user_data;
 
	req->account = account;
 
	req->who = remote_user;
 
	req->mainJID = np->m_accounts[account];
 
	np->m_authRequests[req->mainJID + req->who] = req;
 

	
 
	np->handleAuthorization(req->mainJID, req->who);
 

	
 
	return req;
 
}
 

	
 
static void accountRequestClose(void *data){
 
	authRequest *req = (authRequest *) data;
 
	np->m_authRequests.erase(req->mainJID + req->who);
 
}
 

	
 

	
 
static PurpleAccountUiOps accountUiOps =
 
{
 
	NULL,
 
	NULL,
 
	NULL,
 
	accountRequestAuth,
 
	accountRequestClose,
 
	NULL,
 
	NULL,
 
	NULL,
 
	NULL
 
};
 

	
 
static void XferCreated(PurpleXfer *xfer) {
 
	if (!xfer) {
 
		return;
 
	}
 

	
 
// 	PurpleAccount *account = purple_xfer_get_account(xfer);
 
// 	np->handleFTStart(np->m_accounts[account], xfer->who, xfer, "", xhtml_);
 
}
 

	
 
static void XferDestroyed(PurpleXfer *xfer) {
 
	std::remove(np->m_waitingXfers.begin(), np->m_waitingXfers.end(), xfer);
 
	FTData *ftdata = (FTData *) xfer->ui_data;
 
	if (ftdata && ftdata->timer) {
 
		purple_timeout_remove(ftdata->timer);
 
	}
 
	if (ftdata) {
 
		np->m_xfers.erase(ftdata->id);
 
	}
 
}
 

	
 
static void xferCanceled(PurpleXfer *xfer) {
 
	PurpleAccount *account = purple_xfer_get_account(xfer);
 
	std::string filename(xfer ? purple_xfer_get_filename(xfer) : "");
 
	std::string w = xfer->who;
 
	size_t pos = w.find("/");
 
	if (pos != std::string::npos)
 
		w.erase((int) pos, w.length() - (int) pos);
 

	
 
	FTData *ftdata = (FTData *) xfer->ui_data;
 

	
 
	np->handleFTFinish(np->m_accounts[account], w, filename, purple_xfer_get_size(xfer), ftdata ? ftdata->id : 0);
 
	std::remove(np->m_waitingXfers.begin(), np->m_waitingXfers.end(), xfer);
 
	if (ftdata && ftdata->timer) {
 
		purple_timeout_remove(ftdata->timer);
 
	}
 
	purple_xfer_unref(xfer);
 
}
 

	
 
static void fileSendStart(PurpleXfer *xfer) {
 
// 	FiletransferRepeater *repeater = (FiletransferRepeater *) xfer->ui_data;
 
// 	repeater->fileSendStart();
 
}
 

	
 
static void fileRecvStart(PurpleXfer *xfer) {
 
// 	FiletransferRepeater *repeater = (FiletransferRepeater *) xfer->ui_data;
 
// 	repeater->fileRecvStart();
 
	FTData *ftData = (FTData *) xfer->ui_data;
 
	if (ftData->timer == 0) {
 
		ftData->timer = purple_timeout_add(1, ft_ui_ready, xfer);
 
	}
 
}
 

	
 
static void newXfer(PurpleXfer *xfer) {
 
	PurpleAccount *account = purple_xfer_get_account(xfer);
 
	std::string filename(xfer ? purple_xfer_get_filename(xfer) : "");
 
	purple_xfer_ref(xfer);
 
	std::string w = xfer->who;
 
	size_t pos = w.find("/");
 
	if (pos != std::string::npos)
 
		w.erase((int) pos, w.length() - (int) pos);
 

	
 
	FTData *ftdata = new FTData;
 
	ftdata->paused = false;
 
	ftdata->id = 0;
 
	ftdata->timer = 0;
 
	xfer->ui_data = (void *) ftdata;
 

	
 
	np->m_unhandledXfers[np->m_accounts[account] + filename + w] = xfer;
 

	
 
	np->handleFTStart(np->m_accounts[account], w, filename, purple_xfer_get_size(xfer));
 
}
 

	
 
static void XferReceiveComplete(PurpleXfer *xfer) {
 
// 	FiletransferRepeater *repeater = (FiletransferRepeater *) xfer->ui_data;
 
// 	repeater->_tryToDeleteMe();
 
// 	GlooxMessageHandler::instance()->ftManager->handleXferFileReceiveComplete(xfer);
 
	std::remove(np->m_waitingXfers.begin(), np->m_waitingXfers.end(), xfer);
 
	FTData *ftdata = (FTData *) xfer->ui_data;
 
	if (ftdata && ftdata->timer) {
 
		purple_timeout_remove(ftdata->timer);
 
	}
 
	purple_xfer_unref(xfer);
 
}
 

	
 
static void XferSendComplete(PurpleXfer *xfer) {
 
// 	FiletransferRepeater *repeater = (FiletransferRepeater *) xfer->ui_data;
 
// 	repeater->_tryToDeleteMe();
 
	std::remove(np->m_waitingXfers.begin(), np->m_waitingXfers.end(), xfer);
 
	FTData *ftdata = (FTData *) xfer->ui_data;
 
	if (ftdata && ftdata->timer) {
 
		purple_timeout_remove(ftdata->timer);
 
	}
 
	purple_xfer_unref(xfer);
 
}
 

	
 
static gssize XferWrite(PurpleXfer *xfer, const guchar *buffer, gssize size) {
 
	FTData *ftData = (FTData *) xfer->ui_data;
 
	std::string data((const char *) buffer, (size_t) size);
 
// 	std::cout << "xferwrite\n";
 
	if (!ftData->paused) {
 
// 		std::cout << "adding xfer to waitingXfers queue\n";
 
		np->m_waitingXfers.push_back(xfer);
 
	}
 
	np->handleFTData(ftData->id, data);
 
	return size;
 
}
 

	
 
static void XferNotSent(PurpleXfer *xfer, const guchar *buffer, gsize size) {
 
// 	FiletransferRepeater *repeater = (FiletransferRepeater *) xfer->ui_data;
 
// 	repeater->handleDataNotSent(buffer, size);
 
}
 

	
 
static gssize XferRead(PurpleXfer *xfer, guchar **buffer, gssize size) {
 
// 	FiletransferRepeater *repeater = (FiletransferRepeater *) xfer->ui_data;
 
// 	int data_size = repeater->getDataToSend(buffer, size);
 
// 	if (data_size == 0)
 
// 		return 0;
 
// 	
 
// 	return data_size;
 
	return 0;
 
}
 

	
 
static PurpleXferUiOps xferUiOps =
 
{
 
	XferCreated,
 
	XferDestroyed,
 
	NULL,
 
	NULL,
 
	xferCanceled,
 
	xferCanceled,
 
	XferWrite,
 
	XferRead,
 
	XferNotSent,
 
	NULL
 
};
 

	
 
static void transport_core_ui_init(void)
 
{
 
	purple_blist_set_ui_ops(&blistUiOps);
 
	purple_accounts_set_ui_ops(&accountUiOps);
 
	purple_notify_set_ui_ops(&notifyUiOps);
 
	purple_request_set_ui_ops(&requestUiOps);
 
	purple_xfers_set_ui_ops(&xferUiOps);
 
	purple_connections_set_ui_ops(&conn_ui_ops);
 
	purple_conversations_set_ui_ops(&conversation_ui_ops);
 
// #ifndef WIN32
 
// 	purple_dnsquery_set_ui_ops(getDNSUiOps());
 
// #endif
 
}
 

	
 
static PurpleCoreUiOps coreUiOps =
 
{
 
	NULL,
 
// 	debug_init,
 
	NULL,
 
	transport_core_ui_init,
 
	NULL,
 
	spectrum_ui_get_info,
 
	NULL,
 
	NULL,
 
	NULL
 
};
 

	
 
static void signed_on(PurpleConnection *gc, gpointer unused) {
 
	PurpleAccount *account = purple_connection_get_account(gc);
 
	np->handleConnected(np->m_accounts[account]);
 
	// force returning of memory chunks allocated by libxml2 to kernel
 
	malloc_trim(0);
 
}
 

	
 
static void printDebug(PurpleDebugLevel level, const char *category, const char *arg_s) {
 
	std::string c("");
 
	std::string args(arg_s);
 
	args.erase(args.size() - 1);
 

	
 
	if (category) {
 
		c.append(category);
 
	}
 

	
 
	c.push_back(':');
 

	
 
	LOG4CXX_INFO(logger_libpurple, c << args);
 
}
 

	
 
/*
 
 * Ops....
 
 */
 
static PurpleDebugUiOps debugUiOps =
 
{
 
	printDebug,
 
	NULL,
 
	NULL,
 
	NULL,
 
	NULL,
 
	NULL
 
};
 

	
 
static void buddyTyping(PurpleAccount *account, const char *who, gpointer null) {
 
	std::string w = purple_normalize(account, who);
 
	size_t pos = w.find("/");
 
	if (pos != std::string::npos)
 
		w.erase((int) pos, w.length() - (int) pos);
 
	np->handleBuddyTyping(np->m_accounts[account], w);
 
}
 

	
 
static void buddyTyped(PurpleAccount *account, const char *who, gpointer null) {
 
	std::string w = purple_normalize(account, who);
 
	size_t pos = w.find("/");
 
	if (pos != std::string::npos)
 
		w.erase((int) pos, w.length() - (int) pos);
 
	np->handleBuddyTyped(np->m_accounts[account], w);
 
}
 

	
 
static void buddyTypingStopped(PurpleAccount *account, const char *who, gpointer null){
 
	std::string w = purple_normalize(account, who);
 
	size_t pos = w.find("/");
 
	if (pos != std::string::npos)
 
		w.erase((int) pos, w.length() - (int) pos);
 
	np->handleBuddyStoppedTyping(np->m_accounts[account], w);
 
}
 

	
 
static void gotAttention(PurpleAccount *account, const char *who, PurpleConversation *conv, guint type) {
 
	std::string w = purple_normalize(account, who);
 
	size_t pos = w.find("/");
 
	if (pos != std::string::npos)
 
		w.erase((int) pos, w.length() - (int) pos);
 
	np->handleAttention(np->m_accounts[account], w, "");
 
}
 

	
 
static bool initPurple() {
 
	bool ret;
 

	
 
	purple_util_set_user_dir("./");
 
	remove("./accounts.xml");
 
	remove("./blist.xml");
 

	
 
// 	if (m_configuration.logAreas & LOG_AREA_PURPLE)
 
		purple_debug_set_ui_ops(&debugUiOps);
 
		purple_debug_set_verbose(true);
 

	
 
	purple_core_set_ui_ops(&coreUiOps);
 
	if (KEYFILE_STRING("service", "eventloop") == "libev") {
 
		LOG4CXX_INFO(logger, "Will use libev based event loop");
 
	}
 
	else {
 
		LOG4CXX_INFO(logger, "Will use glib based event loop");
 
	}
 
	purple_eventloop_set_ui_ops(getEventLoopUiOps(KEYFILE_STRING("service", "eventloop") == "libev"));
 

	
 
	ret = purple_core_init("spectrum");
 
	if (ret) {
 
		static int blist_handle;
 
		static int conversation_handle;
 

	
 
		purple_set_blist(purple_blist_new());
 
		purple_blist_load();
 

	
 
		purple_prefs_load();
 

	
 
		/* Good default preferences */
 
		/* The combination of these two settings mean that libpurple will never
 
		 * (of its own accord) set all the user accounts idle.
 
		 */
 
		purple_prefs_set_bool("/purple/away/away_when_idle", false);
 
		/*
 
		 * This must be set to something not "none" for idle reporting to work
 
		 * for, e.g., the OSCAR prpl. We don't implement the UI ops, so this is
 
		 * okay for now.
 
		 */
 
		purple_prefs_set_string("/purple/away/idle_reporting", "system");
 

	
 
		/* Disable all logging */
 
		purple_prefs_set_bool("/purple/logging/log_ims", false);
 
		purple_prefs_set_bool("/purple/logging/log_chats", false);
 
		purple_prefs_set_bool("/purple/logging/log_system", false);
 

	
 

	
 
// 		purple_signal_connect(purple_conversations_get_handle(), "received-im-msg", &conversation_handle, PURPLE_CALLBACK(newMessageReceived), NULL);
 
		purple_signal_connect(purple_conversations_get_handle(), "buddy-typing", &conversation_handle, PURPLE_CALLBACK(buddyTyping), NULL);
 
		purple_signal_connect(purple_conversations_get_handle(), "buddy-typed", &conversation_handle, PURPLE_CALLBACK(buddyTyped), NULL);
 
		purple_signal_connect(purple_conversations_get_handle(), "buddy-typing-stopped", &conversation_handle, PURPLE_CALLBACK(buddyTypingStopped), NULL);
 
		purple_signal_connect(purple_blist_get_handle(), "buddy-privacy-changed", &conversation_handle, PURPLE_CALLBACK(buddyPrivacyChanged), NULL);
 
		purple_signal_connect(purple_conversations_get_handle(), "got-attention", &conversation_handle, PURPLE_CALLBACK(gotAttention), NULL);
 
		purple_signal_connect(purple_connections_get_handle(), "signed-on", &blist_handle,PURPLE_CALLBACK(signed_on), NULL);
 
// 		purple_signal_connect(purple_blist_get_handle(), "buddy-removed", &blist_handle,PURPLE_CALLBACK(buddyRemoved), NULL);
 
// 		purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", &blist_handle,PURPLE_CALLBACK(buddySignedOn), NULL);
 
// 		purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", &blist_handle,PURPLE_CALLBACK(buddySignedOff), NULL);
 
// 		purple_signal_connect(purple_blist_get_handle(), "buddy-status-changed", &blist_handle,PURPLE_CALLBACK(buddyStatusChanged), NULL);
 
		purple_signal_connect(purple_blist_get_handle(), "blist-node-removed", &blist_handle,PURPLE_CALLBACK(NodeRemoved), NULL);
 
// 		purple_signal_connect(purple_conversations_get_handle(), "chat-topic-changed", &conversation_handle, PURPLE_CALLBACK(conv_chat_topic_changed), NULL);
 
		static int xfer_handle;
 
		purple_signal_connect(purple_xfers_get_handle(), "file-send-start", &xfer_handle, PURPLE_CALLBACK(fileSendStart), NULL);
 
		purple_signal_connect(purple_xfers_get_handle(), "file-recv-start", &xfer_handle, PURPLE_CALLBACK(fileRecvStart), NULL);
 
		purple_signal_connect(purple_xfers_get_handle(), "file-recv-request", &xfer_handle, PURPLE_CALLBACK(newXfer), NULL);
 
		purple_signal_connect(purple_xfers_get_handle(), "file-recv-complete", &xfer_handle, PURPLE_CALLBACK(XferReceiveComplete), NULL);
 
		purple_signal_connect(purple_xfers_get_handle(), "file-send-complete", &xfer_handle, PURPLE_CALLBACK(XferSendComplete), NULL);
 
// 
 
// 		purple_commands_init();
 

	
 
	}
 
	return ret;
 
}
 

	
 
static void spectrum_sigchld_handler(int sig)
 
{
 
	int status;
 
	pid_t pid;
 

	
 
	do {
 
		pid = waitpid(-1, &status, WNOHANG);
 
	} while (pid != 0 && pid != (pid_t)-1);
 

	
 
	if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
 
		char errmsg[BUFSIZ];
 
		snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
 
		perror(errmsg);
 
	}
 
}
 

	
 
static void transportDataReceived(gpointer data, gint source, PurpleInputCondition cond) {
 
	char buffer[65535];
 
	char *ptr = buffer;
 
	ssize_t n = read(source, ptr, sizeof(buffer));
 
	if (n <= 0) {
 
		LOG4CXX_INFO(logger, "Diconnecting from spectrum2 server");
 
		exit(errno);
 
	if (cond & PURPLE_INPUT_READ) {
 
		char buffer[65535];
 
		char *ptr = buffer;
 
		ssize_t n = read(source, ptr, sizeof(buffer));
 
		if (n <= 0) {
 
			LOG4CXX_INFO(logger, "Diconnecting from spectrum2 server");
 
			exit(errno);
 
		}
 
		std::string d = std::string(buffer, n);
 
		np->handleDataRead(d);
 
	}
 
	else {
 
		np->readyForData();
 
	}
 
	std::string d = std::string(buffer, n);
 
	np->handleDataRead(d);
 
}
 

	
 
int main(int argc, char **argv) {
 
	GError *error = NULL;
 
	GOptionContext *context;
 
	context = g_option_context_new("config_file_name or profile name");
 
	g_option_context_add_main_entries(context, options_entries, "");
 
	if (!g_option_context_parse (context, &argc, &argv, &error)) {
 
		std::cout << "option parsing failed: " << error->message << "\n";
 
		return -1;
 
	}
 

	
 
	if (ver) {
 
// 		std::cout << VERSION << "\n";
 
		std::cout << "verze\n";
 
		g_option_context_free(context);
 
		return 0;
 
	}
 

	
 
	if (argc != 2) {
 
#ifdef WIN32
 
		std::cout << "Usage: spectrum.exe <configuration_file.cfg>\n";
 
#else
 

	
 
#if GLIB_CHECK_VERSION(2,14,0)
 
	std::cout << g_option_context_get_help(context, FALSE, NULL);
 
#else
 
	std::cout << "Usage: spectrum <configuration_file.cfg>\n";
 
	std::cout << "See \"man spectrum\" for more info.\n";
 
#endif
 
		
 
#endif
 
	}
 
	else {
 
#ifndef WIN32
 
		signal(SIGPIPE, SIG_IGN);
 

	
 
		if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
 
			std::cout << "SIGCHLD handler can't be set\n";
 
			g_option_context_free(context);
 
			return -1;
 
		}
 
// 
 
// 		if (signal(SIGINT, spectrum_sigint_handler) == SIG_ERR) {
 
// 			std::cout << "SIGINT handler can't be set\n";
 
// 			g_option_context_free(context);
 
// 			return -1;
 
// 		}
 
// 
 
// 		if (signal(SIGTERM, spectrum_sigterm_handler) == SIG_ERR) {
 
// 			std::cout << "SIGTERM handler can't be set\n";
 
// 			g_option_context_free(context);
 
// 			return -1;
 
// 		}
 
// 
 
// 		struct sigaction sa;
 
// 		memset(&sa, 0, sizeof(sa)); 
 
// 		sa.sa_handler = spectrum_sighup_handler;
 
// 		if (sigaction(SIGHUP, &sa, NULL)) {
 
// 			std::cout << "SIGHUP handler can't be set\n";
 
// 			g_option_context_free(context);
 
// 			return -1;
 
//		}
 
#endif
 
		keyfile = g_key_file_new ();
 
		if (!g_key_file_load_from_file (keyfile, argv[1], (GKeyFileFlags) 0, 0)) {
 
			std::cout << "Can't open " << argv[1] << " configuration file.\n";
 
			return 1;
 
		}
 

	
 
		if (KEYFILE_STRING("logging", "backend_config").empty()) {
 
			LoggerPtr root = log4cxx::Logger::getRootLogger();
 
			root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
 
		}
 
		else {
 
			log4cxx::helpers::Properties p;
 
			log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(KEYFILE_STRING("logging", "backend_config"));
 

	
 
			p.load(istream);
 
			p.setProperty("pid", stringOf(getpid()));
 
			p.setProperty("jid", KEYFILE_STRING("service", "jid"));
 
			log4cxx::PropertyConfigurator::configure(p);
 
		}
 

	
 
		initPurple();
 

	
 
		int portno = port;
 
		struct sockaddr_in serv_addr;
 

	
 
		m_sock = socket(AF_INET, SOCK_STREAM, 0);
 
		memset((char *) &serv_addr, 0, sizeof(serv_addr));
 
		serv_addr.sin_family = AF_INET;
 
		serv_addr.sin_port = htons(portno);
 

	
 
		hostent *hos;  // Resolve name
 
		if ((hos = gethostbyname(host)) == NULL) {
 
			// strerror() will not work for gethostbyname() and hstrerror() 
 
			// is supposedly obsolete
 
			exit(1);
 
		}
 
		serv_addr.sin_addr.s_addr = *((unsigned long *) hos->h_addr_list[0]);
 

	
 
		if (connect(m_sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
 
			close(m_sock);
 
			m_sock = 0;
 
		}
 

	
 
		int flags = fcntl(m_sock, F_GETFL);
 
		flags |= O_NONBLOCK;
 
		fcntl(m_sock, F_SETFL, flags);
 

	
 
		purple_input_add(m_sock, PURPLE_INPUT_READ, &transportDataReceived, NULL);
 
		purple_input_add(m_sock, PURPLE_INPUT_WRITE, &transportDataReceived, NULL);
 

	
 
		np = new SpectrumNetworkPlugin(host, port);
 
		bool libev = KEYFILE_STRING("service", "eventloop") == "libev";
 

	
 
		GMainLoop *m_loop;
 
#ifdef WITH_LIBEVENT
 
		if (!libev) {
 
			m_loop = g_main_loop_new(NULL, FALSE);
 
		}
 
		else {
 
			event_init();
 
		}
 
#endif
 
		m_loop = g_main_loop_new(NULL, FALSE);
 

	
 
		if (m_loop) {
 
			g_main_loop_run(m_loop);
 
		}
 
#ifdef WITH_LIBEVENT
 
		else {
 
			event_loop(0);
 
		}
 
#endif
 
	}
 

	
 
	g_option_context_free(context);
 
	return 0;
 
}
0 comments (0 inline, 0 general)