Changeset - 2fbd27919c14
[Not reviewed]
0 1 0
HanzZ - 13 years ago 2013-01-28 16:34:15
hanzz.k@gmail.com
Do not try to delete m_proxy if it does not exist
1 file changed with 6 insertions and 4 deletions:
0 comments (0 inline, 0 general)
backends/skype/main.cpp
Show inline comments
 
@@ -417,388 +417,390 @@ void Skype::login() {
 
									"<API>\n"
 
									"<Authorizations>Spectrum</Authorizations>\n"
 
									"<BlockedPrograms></BlockedPrograms>\n"
 
									"</API>\n"
 
								"</UI>\n"
 
							"</config>\n";
 
	g_file_set_contents(std::string(std::string("/tmp/skype/") + m_username + "/" + m_username +"/config.xml").c_str(), config_xml.c_str(), -1, NULL);
 

	
 
	sleep(1);
 
	std::string db_path = std::string("/tmp/skype/") + m_username;
 
	char *db = (char *) malloc(db_path.size() + 1);
 
	strcpy(db, db_path.c_str());
 
	LOG4CXX_INFO(logger,  m_username << ": Spawning new Skype instance dbpath=" << db);
 
	gchar* argv[6] = {"skype", "--disable-cleanlooks", "--pipelogin", "--dbpath", db, 0};
 

	
 
	int fd;
 
	GError *error = NULL;
 
	bool spawned = g_spawn_async_with_pipes(NULL,
 
		argv,
 
		NULL /*envp*/,
 
		G_SPAWN_SEARCH_PATH,
 
		NULL /*child_setup*/,
 
		NULL /*user_data*/,
 
		&m_pid /*child_pid*/,
 
		&fd,
 
		NULL,
 
		&fd_output,
 
		&error);
 

	
 
	if (!spawned) {
 
		LOG4CXX_ERROR(logger, "Error spawning the Skype instance: " << error->message)
 
		np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Error spawning the Skype instance.");
 
		return;
 
	}
 

	
 
	std::string login_data = std::string(m_username + " " + m_password + "\n");
 
	LOG4CXX_INFO(logger,  m_username << ": Login data=" << m_username);
 
	write(fd, login_data.c_str(), login_data.size());
 
	close(fd);
 

	
 
	fcntl (fd_output, F_SETFL, O_NONBLOCK);
 

	
 
	free(db);
 

	
 
	//Initialise threading
 
	dbus_threads_init_default();
 

	
 
	if (m_connection == NULL)
 
	{
 
		LOG4CXX_INFO(logger, "Creating DBUS connection.");
 
		GError *error = NULL;
 
		m_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
 
		if (m_connection == NULL && error != NULL)
 
		{
 
			LOG4CXX_INFO(logger,  m_username << ": Creating DBUS Connection error: " << error->message);
 
			g_error_free(error);
 
			return;
 
		}
 
	}
 

	
 
	sleep(1);
 
	m_timer = g_timeout_add_seconds(1, create_dbus_proxy, this);
 
}
 

	
 
bool Skype::loadSkypeBuddies() {
 
//	std::string re = "CONNSTATUS OFFLINE";
 
//	while (re == "CONNSTATUS OFFLINE" || re.empty()) {
 
//		sleep(1);
 

	
 
	gchar buffer[1024];
 
	int bytes_read = read(fd_output, buffer, 1023);
 
	if (bytes_read > 0) {
 
		buffer[bytes_read] = 0;
 
		std::string b(buffer);
 
		LOG4CXX_WARN(logger, "Skype wrote this on stdout '" << b << "'");
 
		if (b.find("Incorrect Password") != std::string::npos) {
 
			LOG4CXX_INFO(logger, "Incorrect password, logging out")
 
			np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_FAILED, "Incorrect password");
 
			close(fd_output);
 
			logout();
 
			return FALSE;
 
		}
 
	}
 

	
 
	std::string re = send_command("NAME Spectrum");
 
	if (m_counter++ > 15) {
 
		LOG4CXX_ERROR(logger, "Logging out, because we tried to connect the Skype over DBUS 15 times without success");
 
		np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Skype is not ready. This issue have been logged and admins will check it and try to fix it soon.");
 
		close(fd_output);
 
		logout();
 
		return FALSE;
 
	}
 

	
 
	if (re.empty() || re == "CONNSTATUS OFFLINE" || re == "ERROR 68") {
 
		return TRUE;
 
	}
 

	
 
	close(fd_output);
 

	
 
	if (send_command("PROTOCOL 7") != "PROTOCOL 7") {
 
		LOG4CXX_ERROR(logger, "PROTOCOL 7 failed, logging out");
 
		np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Skype is not ready. This issue have been logged and admins will check it and try to fix it soon.");
 
		logout();
 
		return FALSE;
 
	}
 

	
 
	np->handleConnected(m_user);
 

	
 
	std::map<std::string, std::string> group_map;
 
	std::string groups = send_command("SEARCH GROUPS CUSTOM");
 
	if (groups.find(' ') != std::string::npos) {
 
		groups = groups.substr(groups.find(' ') + 1);
 
		std::vector<std::string> grps;
 
		boost::split(grps, groups, boost::is_any_of(","));
 
		BOOST_FOREACH(std::string grp, grps) {
 
			std::vector<std::string> data;
 
			std::string name = send_command("GET GROUP " + grp + " DISPLAYNAME");
 

	
 
			if (name.find("ERROR") == 0) {
 
				continue;
 
			}
 

	
 
			boost::split(data, name, boost::is_any_of(" "));
 
			name = GET_RESPONSE_DATA(name, "DISPLAYNAME");
 

	
 
			std::string users = send_command("GET GROUP " + data[1] + " USERS");
 
			try {
 
				users = GET_RESPONSE_DATA(users, "USERS");
 
			}
 
			catch (std::out_of_range& oor) {
 
				continue;
 
			}
 
			boost::split(data, users, boost::is_any_of(","));
 
			BOOST_FOREACH(std::string u, data) {
 
				group_map[u] = grp;
 
			}
 
		}
 
	}
 

	
 
	std::string friends = send_command("GET AUTH_CONTACTS_PROFILES");
 

	
 
	char **full_friends_list = g_strsplit((strchr(friends.c_str(), ' ')+1), ";", 0);
 
	if (full_friends_list && full_friends_list[0])
 
	{
 
		//in the format of: username;full name;phone;office phone;mobile phone;
 
		//                  online status;friendly name;voicemail;mood
 
		// (comma-seperated lines, usernames can have comma's)
 

	
 
		for (int i=0; full_friends_list[i] && full_friends_list[i+1] && *full_friends_list[i] != '\0'; i+=8)
 
		{
 
			std::string buddy = full_friends_list[i];
 

	
 
			if (buddy[0] == ',') {
 
				buddy.erase(buddy.begin());
 
			}
 

	
 
			if (buddy.rfind(",") != std::string::npos) {
 
				buddy = buddy.substr(buddy.rfind(","));
 
			}
 

	
 
			if (buddy[0] == ',') {
 
				buddy.erase(buddy.begin());
 
			}
 

	
 
			LOG4CXX_INFO(logger, "Got buddy " << buddy);
 
			std::string st = full_friends_list[i + 5];
 

	
 
			pbnetwork::StatusType status = getStatus(st);
 

	
 
			std::string alias = full_friends_list[i + 6];
 

	
 
			std::string mood_text = "";
 
			if (full_friends_list[i + 8] && *full_friends_list[i + 8] != '\0' && *full_friends_list[i + 8] != ',') {
 
				mood_text = full_friends_list[i + 8];
 
			}
 

	
 
			std::vector<std::string> groups;
 
			if (group_map.find(buddy) != group_map.end()) {
 
				groups.push_back(group_map[buddy]);
 
			}
 
			np->handleBuddyChanged(m_user, buddy, alias, groups, status, mood_text);
 
		}
 
	}
 
	g_strfreev(full_friends_list);
 

	
 
	send_command("SET AUTOAWAY OFF");
 
	send_command("SET USERSTATUS ONLINE");
 
	return FALSE;
 
}
 

	
 
void Skype::logout() {
 
	if (m_pid != 0) {
 
		send_command("SET USERSTATUS INVISIBLE");
 
		send_command("SET USERSTATUS OFFLINE");
 
		sleep(2);
 
		g_object_unref(m_proxy);
 
		if (m_proxy) {
 
			send_command("SET USERSTATUS INVISIBLE");
 
			send_command("SET USERSTATUS OFFLINE");
 
			sleep(2);
 
			g_object_unref(m_proxy);
 
		}
 
		LOG4CXX_INFO(logger,  m_username << ": Terminating Skype instance (SIGTERM)");
 
		kill((int) m_pid, SIGTERM);
 
		// Give skype a chance
 
		sleep(2);
 
		LOG4CXX_INFO(logger,  m_username << ": Killing Skype instance (SIGKILL)");
 
		kill((int) m_pid, SIGKILL);
 
		m_pid = 0;
 
	}
 
}
 

	
 
std::string Skype::send_command(const std::string &message) {
 
	GError *error = NULL;
 
	gchar *str = NULL;
 
// 			int message_num;
 
// 			gchar error_return[30];
 

	
 
	LOG4CXX_INFO(logger, "Sending: '" << message << "'");
 
	if (!dbus_g_proxy_call (m_proxy, "Invoke", &error, G_TYPE_STRING, message.c_str(), G_TYPE_INVALID,
 
						G_TYPE_STRING, &str, G_TYPE_INVALID))
 
	{
 
			if (error && error->message)
 
			{
 
			LOG4CXX_INFO(logger,  m_username << ": DBUS Error: " << error->message);
 
			g_error_free(error);
 
			return "";
 
		} else {
 
			LOG4CXX_INFO(logger,  m_username << ": DBUS no response");
 
			return "";
 
		}
 

	
 
	}
 
	if (str != NULL)
 
	{
 
		LOG4CXX_INFO(logger,  m_username << ": DBUS:'" << str << "'");
 
	}
 
	return str ? std::string(str) : std::string();
 
}
 

	
 
static void handle_skype_message(std::string &message, Skype *sk) {
 
	std::vector<std::string> cmd;
 
	boost::split(cmd, message, boost::is_any_of(" "));
 

	
 
	if (cmd[0] == "USER") {
 
		if (cmd[1] == sk->getUsername()) {
 
			return;
 
		}
 

	
 
		if (cmd[2] == "ONLINESTATUS") {
 
			if (cmd[3] == "SKYPEOUT" || cmd[3] == "UNKNOWN") {
 
				return;
 
			}
 
			else {
 
				pbnetwork::StatusType status = getStatus(cmd[3]);
 
				GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT");
 
				GET_PROPERTY(alias, "USER", cmd[1], "FULLNAME");
 

	
 
				std::vector<std::string> groups;
 
				np->handleBuddyChanged(sk->getUser(), cmd[1], alias, groups, status, mood_text);
 
			}
 
		}
 
		else if (cmd[2] == "MOOD_TEXT") {
 
			GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS");
 
			pbnetwork::StatusType status = getStatus(st);
 

	
 
			std::string mood_text = GET_RESPONSE_DATA(message, "MOOD_TEXT");
 

	
 
			std::vector<std::string> groups;
 
			np->handleBuddyChanged(sk->getUser(), cmd[1], "", groups, status, mood_text);
 
		}
 
		else if (cmd[2] == "BUDDYSTATUS" && cmd[3] == "3") {
 
			GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT");
 
			GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS");
 
			pbnetwork::StatusType status = getStatus(st);
 

	
 
			std::vector<std::string> groups;
 
			np->handleBuddyChanged(sk->getUser(), cmd[1], "", groups, status, mood_text);
 
		}
 
		else if (cmd[2] == "FULLNAME") {
 
			GET_PROPERTY(alias, "USER", cmd[1], "FULLNAME");
 
			GET_PROPERTY(mood_text, "USER", cmd[1], "MOOD_TEXT");
 
			GET_PROPERTY(st, "USER", cmd[1], "ONLINESTATUS");
 
			pbnetwork::StatusType status = getStatus(st);
 

	
 
			std::vector<std::string> groups;
 
			np->handleBuddyChanged(sk->getUser(), cmd[1], alias, groups, status, mood_text);
 
		}
 
		else if(cmd[2] == "RECEIVEDAUTHREQUEST") {
 
			np->handleAuthorization(sk->getUser(), cmd[1]);
 
		}
 
	}
 
	else if (cmd[0] == "CHATMESSAGE") {
 
		if (cmd[3] == "RECEIVED") {
 
			GET_PROPERTY(body, "CHATMESSAGE", cmd[1], "BODY");
 
			GET_PROPERTY(from_handle, "CHATMESSAGE", cmd[1], "FROM_HANDLE");
 

	
 
			if (from_handle == sk->getUsername())
 
				return;
 

	
 
			np->handleMessage(sk->getUser(), from_handle, body);
 

	
 
			sk->send_command("SET CHATMESSAGE " + cmd[1] + " SEEN");
 
		}
 
	}
 
	else if (cmd[0] == "CALL") {
 
		// CALL 884 STATUS RINGING
 
		if (cmd[2] == "STATUS") {
 
			if (cmd[3] == "RINGING" || cmd[3] == "MISSED") {
 
				// handle only incoming calls
 
				GET_PROPERTY(type, "CALL", cmd[1], "TYPE");
 
				if (type.find("INCOMING") != 0) {
 
					return;
 
				}
 

	
 
				GET_PROPERTY(from, "CALL", cmd[1], "PARTNER_HANDLE");
 
				GET_PROPERTY(dispname, "CALL", cmd[1], "PARTNER_DISPNAME");
 

	
 
				if (cmd[3] == "RINGING") {
 
					np->handleMessage(sk->getUser(), from, "User " + dispname + " is calling you.");
 
				}
 
				else {
 
					np->handleMessage(sk->getUser(), from, "You have missed call from user " + dispname + ".");
 
				}
 
			}
 
		}
 
	}
 
}
 

	
 
DBusHandlerResult skype_notify_handler(DBusConnection *connection, DBusMessage *message, gpointer user_data) {
 
	DBusMessageIter iterator;
 
	gchar *message_temp;
 
	DBusMessage *temp_message;
 
	
 
	temp_message = dbus_message_ref(message);
 
	dbus_message_iter_init(temp_message, &iterator);
 
	if (dbus_message_iter_get_arg_type(&iterator) != DBUS_TYPE_STRING)
 
	{
 
		dbus_message_unref(message);
 
		return (DBusHandlerResult) FALSE;
 
	}
 
	
 
	do {
 
		dbus_message_iter_get_basic(&iterator, &message_temp);
 
		std::string m(message_temp);
 
		LOG4CXX_INFO(logger,"DBUS message: " << m);
 
		handle_skype_message(m, (Skype *) user_data);
 
	} while(dbus_message_iter_has_next(&iterator) && dbus_message_iter_next(&iterator));
 
	
 
	dbus_message_unref(message);
 
	
 
	return DBUS_HANDLER_RESULT_HANDLED;
 
}
 

	
 
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 int create_socket(const char *host, int portno) {
 
	struct sockaddr_in serv_addr;
 
	
 
	int 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
 
		Logging::shutdownLogging();
 
		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;
0 comments (0 inline, 0 general)