gboolean purpleDNS::Resolve(PurpleDnsQueryData *query_data,
                            PurpleDnsQueryResolvedCallback resolved_cb,
                            PurpleDnsQueryFailedCallback failed_cb)
{
  NS_ENSURE_TRUE(!NS_IsOffline(), false);
  nsCString host(purple_dnsquery_get_host(query_data));
  LOG(("Resolving with moz: %s", host.get()));
  NS_ENSURE_TRUE(sRequests, false);

  nsCOMPtr<nsIDNSService> dns = do_GetService("@mozilla.org/network/dns-service;1");
  nsCOMPtr<nsIDNSRecord> record;
  nsCOMPtr<nsICancelable> cancelable;
  nsCOMPtr<nsIThread> thread = do_GetMainThread();
  nsCOMPtr<purpleDNSRequest> listener;
  listener = new purpleDNSRequest();
  listener->mAccountId = purpleAccountScoper::GetCurrentAccountId();
  listener->query_data = query_data;
  listener->resolved_cb = resolved_cb;
  listener->failed_cb = failed_cb;

  nsresult rv = dns->AsyncResolve(host, 0, listener, thread,
                                  getter_AddRefs(listener->asyncResolv));
  NS_ENSURE_SUCCESS(rv, false);// The request wasn't handled.

  sRequests->AppendObject(listener);
  return true; // We handle the request, libpurple shouldn't try to do it.
}
Example #2
0
static gboolean
dns_main_thread_cb(gpointer d)
{
	ResolverData *data = (ResolverData *) d;
	g_mutex_lock(data->mutex);
	if (data->destroyed) {
		while (data->hosts) {
			data->hosts = g_slist_delete_link(data->hosts, data->hosts);
			/* Free the address */
			g_free(data->hosts->data);
			data->hosts = g_slist_delete_link(data->hosts, data->hosts);
		}
		g_mutex_unlock(data->mutex);
		g_mutex_free(data->mutex);
		delete data;
		return FALSE;
	}
	PurpleDnsQueryData *query_data = data->query_data;
	g_hash_table_remove(query_data_cache, query_data);

	/* We're done, so purple_dnsquery_destroy() shouldn't think it is canceling an in-progress lookup */
// 	query_data->resolver = NULL;

	if (data->error_message != NULL) {
		Log("DNSResolver", "Resolving " << purple_dnsquery_get_host(query_data) << ": Resolving failed: " << data->error_message);
		data->failed_cb(query_data, data->error_message);
	}
	else {
		Log("DNSResolver", "Resolving " << purple_dnsquery_get_host(query_data) << ": Successfully resolved");
		GSList *hosts;
		/* We don't want purple_dns_query_resolved() to free(hosts) */
		hosts = data->hosts;
		data->hosts = NULL;
		data->resolved_cb(query_data, hosts);
	}
	g_mutex_unlock(data->mutex);
	g_mutex_free(data->mutex);
	delete data;

	if (queue) {
		data = (ResolverData *) queue->data;
		queue = g_list_remove(queue, data);
		start_resolver_thread(data);
	}

	return FALSE;
}
Example #3
0
static gboolean start_resolver_thread(ResolverData *data) {
	GError *err = NULL;
	Log("DNSResolver", "Resolving " << purple_dnsquery_get_host(data->query_data) << ": Starting resolver thread.");
	if (g_thread_create(dns_thread, data, FALSE, &err) == NULL) {
		Log("DNSResolver", "Resolving " << purple_dnsquery_get_host(data->query_data) << ": Resolver thread couldn't been started.");
		char message[1024];
		g_snprintf(message, sizeof(message), "Thread creation failure: %s",
				(err && err->message) ? err->message : "Unknown reason");
		g_error_free(err);
		data->failed_cb(data->query_data, message);
		delete data;
		return false;
	}
	else {
		g_hash_table_replace(query_data_cache, data->query_data, data);
	}
	return true;
}
Example #4
0
static gboolean resolve_ip(ResolverData *data) {
	PurpleDnsQueryData *query_data = (PurpleDnsQueryData *) data->query_data;
	struct sockaddr_in sin;
	if (inet_aton(purple_dnsquery_get_host(query_data), &sin.sin_addr)) {
		// The given "hostname" is actually an IP address, so we don't need to do anything.
		Log("DNSResolver", "Resolving " << purple_dnsquery_get_host(query_data) << ": It's IP, don't do anything.");
		GSList *hosts = NULL;
		sin.sin_family = AF_INET;
		sin.sin_port = htons(purple_dnsquery_get_port(query_data));
		hosts = g_slist_append(hosts, GINT_TO_POINTER(sizeof(sin)));
		hosts = g_slist_append(hosts, g_memdup(&sin, sizeof(sin)));
		data->resolved_cb(query_data, hosts);
		delete data;
		return TRUE;
	}

	return FALSE;
}
 */JNIEXPORT jstring JNICALL
Java_im_pidgin_jpurple_core_dns_DnsQueryData_getHost_1native(JNIEnv *env,
		jobject object)
{
	PurpleDnsQueryData* object_native;

	object_native = getNativeDnsData(env, object);

	return (*env)->NewStringUTF(env, purple_dnsquery_get_host(object_native));
}
Example #6
0
static void destroy(PurpleDnsQueryData *query_data) {
	Log("DNSResolver", "Destroying " << purple_dnsquery_get_host(query_data));
	for (GList *l = queue; l != NULL; l = l->next) {
		ResolverData *data = (ResolverData *) l->data;
		if (data->query_data == query_data) {
			g_mutex_lock(data->mutex);
			g_mutex_unlock(data->mutex);
			g_mutex_free(data->mutex);
			queue = g_list_remove(queue, data);
			break;
		}
	}

	ResolverData *data = (ResolverData *) g_hash_table_lookup(query_data_cache, query_data);
	if (data) {
		Log("DNSResolver", "Destroying " << purple_dnsquery_get_host(query_data) << ": will be destroyed soon...");
		g_mutex_lock(data->mutex);
		data->destroyed = true;
		g_mutex_unlock(data->mutex);
		g_hash_table_remove(query_data_cache, query_data);
	}
}
Example #7
0
static void
skypeweb_close(PurpleConnection *pc)
{
	SkypeWebAccount *sa;
	
	g_return_if_fail(pc != NULL);
	
	sa = purple_connection_get_protocol_data(pc);
	g_return_if_fail(sa != NULL);
	
	purple_timeout_remove(sa->authcheck_timeout);
	purple_timeout_remove(sa->poll_timeout);
	purple_timeout_remove(sa->watchdog_timeout);

	skypeweb_logout(sa);
	purple_signal_disconnect(purple_conversations_get_handle(), "conversation-updated", pc, PURPLE_CALLBACK(skypeweb_mark_conv_seen));
	purple_debug_info("skypeweb", "destroying %d waiting connections\n",
					  g_queue_get_length(sa->waiting_conns));
	
	while (!g_queue_is_empty(sa->waiting_conns))
		skypeweb_connection_destroy(g_queue_pop_tail(sa->waiting_conns));
	g_queue_free(sa->waiting_conns);
	
	purple_debug_info("skypeweb", "destroying %d incomplete connections\n",
			g_slist_length(sa->conns));

	while (sa->conns != NULL)
		skypeweb_connection_destroy(sa->conns->data);
		
	while (sa->dns_queries != NULL) {
		PurpleDnsQueryData *dns_query = sa->dns_queries->data;
		purple_debug_info("skypeweb", "canceling dns query for %s\n",
					purple_dnsquery_get_host(dns_query));
		sa->dns_queries = g_slist_remove(sa->dns_queries, dns_query);
		purple_dnsquery_destroy(dns_query);
	}
	
	g_hash_table_destroy(sa->sent_messages_hash);
	g_hash_table_destroy(sa->cookie_table);
	g_hash_table_destroy(sa->hostname_ip_cache);
	
	g_free(sa->messages_host);
	g_free(sa->skype_token);
	g_free(sa->registration_token);
	g_free(sa->endpoint);
	g_free(sa->username);
	g_free(sa);
}
Example #8
0
static gboolean resolve_host(PurpleDnsQueryData *query_data, PurpleDnsQueryResolvedCallback resolved_cb, PurpleDnsQueryFailedCallback failed_cb) {
	ResolverData *data = new ResolverData;
	data->query_data = query_data;
	data->resolved_cb = resolved_cb;
	data->failed_cb = failed_cb;
	data->error_message = NULL;
	data->hosts = NULL;
	data->destroyed = false;
	data->mutex = g_mutex_new();

	if (!resolve_ip(data)) {
		if (g_hash_table_size(query_data_cache) == 5) {
			Log("DNSResolver", "Resolving " << purple_dnsquery_get_host(query_data) << ": query_data queued.");
			queue = g_list_append(queue, data);
		}
		else {
			return start_resolver_thread(data);
		}
	}

	return TRUE;
}
Example #9
0
static void fb_close(PurpleConnection *pc)
{
	FacebookAccount *fba;
	gchar *postdata;
	GSList *buddies;

	purple_debug_info("facebook", "disconnecting account\n");

	g_return_if_fail(pc != NULL);
	g_return_if_fail(pc->proto_data != NULL);
	
	fba = pc->proto_data;

	if ( fba == NULL )		//VOXOX - JRT - 2009.10.12 - Prevent crash when network is lost or resuming from hibernation.
		return;

	purple_debug_info("facebook", "unloading plugin\n");

	/* destroy blist subsystem */
	fb_blist_destroy(fba);

	/* destroy conversation subsystem */
	fb_conversation_destroy(fba);
	buddies = purple_find_buddies(fba->account, NULL);
	while(buddies) {
		PurpleBuddy *b = buddies->data;
		fb_buddy_free(b);
		buddies = g_slist_delete_link(buddies, buddies);
	}

	/* Tell Facebook that we've logged out. */
	/*
	 * TODO
	 * This doesn't actually work because the request is non-blocking
	 * and we're in the process of logging out.  So we start making a
	 * connection but then libpurple immediately cancels the attempt
	 * and frees everything.
	 *
	 * There are two ways to fix this:
	 * 1. We could make this request, but not pass in fba or reference
	 *    any other data.  The request could complete normally even
	 *    after this account has logged out, since it really doesn't
	 *    need access to the PurpleConnection or the FacebookAccount.
	 *
	 * 2. The close prpl callback could be changed in libpurple so that
	 *    protocol plugins can have a chance to make network requests
	 *    and do other long cleanup operations.  So the call to
	 *    prpl->close() would become asynchronous.  It tells the
	 *    protocol plugin to begin the shutdown sequence, and the
	 *    protocol plugin tells the core when it's finished.
	 */
	if (fba->post_form_id)
		postdata = g_strdup_printf(
				"visibility=false&post_form_id=%s&"
				"fb_dtsg=%s&post_form_id_source=AsyncRequest&"
				"__a=1",
				fba->post_form_id, fba->dtsg);
	else
		postdata = g_strdup("visibility=false");
	fb_post_or_get(fba, FB_METHOD_POST, NULL, "/ajax/chat/settings.php",
			postdata, NULL, NULL, FALSE);
	g_free(postdata);

	if (fba->friend_request_timer) {
		purple_timeout_remove(fba->friend_request_timer);
	}
	if (fba->notifications_timer) {
		purple_timeout_remove(fba->notifications_timer);
	}
	if (fba->new_messages_check_timer) {
		purple_timeout_remove(fba->new_messages_check_timer);
	}
	if (fba->perpetual_messages_timer) {
		purple_timeout_remove(fba->perpetual_messages_timer);
	}

	purple_debug_info("facebook", "destroying %d incomplete connections\n",
			g_slist_length(fba->conns));

	while (fba->conns != NULL)
		fb_connection_destroy(fba->conns->data);

	while (fba->dns_queries != NULL) {
		PurpleDnsQueryData *dns_query = fba->dns_queries->data;
		purple_debug_info("facebook", "canceling dns query for %s\n",
					purple_dnsquery_get_host(dns_query));
		fba->dns_queries = g_slist_remove(fba->dns_queries, dns_query);
		purple_dnsquery_destroy(dns_query);
	}
	
	if (fba->resending_messages != NULL) {
		fb_cancel_resending_messages(fba);
	}

	//VOXOX - JRT - 2009.10.13 - I know we are deleting fba anyway, but since other threads may also be accessing this,
	//							 it helps reduce crashes due to freed memory ptrs.  (There is no thread syncing to control this better).
	g_hash_table_destroy(fba->cookie_table);

	g_hash_table_destroy(fba->hostname_ip_cache);

	g_hash_table_destroy(fba->auth_buddies);

	g_free(fba->post_form_id);
	g_free(fba->dtsg);
	g_free(fba->channel_number);
	g_free(fba->last_status_message);
	g_free(fba->extra_challenge);
	g_free(fba->captcha_session);
	g_free(fba->persist_data);
	g_free(fba);

}
Example #10
0
static gpointer dns_thread(gpointer d) {
	ResolverData *data = (ResolverData *) d;
	PurpleDnsQueryData *query_data;
// #ifdef HAVE_GETADDRINFO
	int rc;
	struct addrinfo hints, *res, *tmp;
	char servname[20];
// #else
// 	struct sockaddr_in sin;
// 	struct hostent *hp;
// #endif
	char *hostname;

	query_data = data->query_data;

// Currently we don't support IDN

// #ifdef USE_IDN
// 	if (!dns_str_is_ascii(purple_dnsquery_get_host(query_data))) {
// 		rc = purple_network_convert_idn_to_ascii(purple_dnsquery_get_host(query_data), &hostname);
// 		if (rc != 0) {
// 			data->error_message = g_strdup_printf(_("Error converting %s "
// 					"to punycode: %d"), purple_dnsquery_get_host(query_data), rc);
// 			/* back to main thread */
// 			purple_timeout_add(0, dns_main_thread_cb, query_data);
// 			return 0;
// 		}
// 	} else /* intentional fallthru */
// #endif
	hostname = g_strdup(purple_dnsquery_get_host(query_data));

// #ifdef HAVE_GETADDRINFO
	g_snprintf(servname, sizeof(servname), "%d", purple_dnsquery_get_port(query_data));
	memset(&hints,0,sizeof(hints));

	/*
	 * This is only used to convert a service
	 * name to a port number. As we know we are
	 * passing a number already, we know this
	 * value will not be really used by the C
	 * library.
	 */
	hints.ai_socktype = SOCK_STREAM;
// #ifdef AI_ADDRCONFIG
// 	hints.ai_flags |= AI_ADDRCONFIG;
// #endif /* AI_ADDRCONFIG */
	if ((rc = getaddrinfo(hostname, servname, &hints, &res)) == 0) {
		tmp = res;
		while(res) {
			data->hosts = g_slist_append(data->hosts,
				GSIZE_TO_POINTER(res->ai_addrlen));
			data->hosts = g_slist_append(data->hosts,
				g_memdup(res->ai_addr, res->ai_addrlen));
			res = res->ai_next;
		}
		freeaddrinfo(tmp);
	} else {
		g_mutex_lock(data->mutex);
		bool destroyed = data->destroyed;
		g_mutex_unlock(data->mutex);
		if (!destroyed) {
			data->error_message = g_strdup_printf("Error resolving %s:\n%s", purple_dnsquery_get_host(query_data), purple_gai_strerror(rc));
		}
	}
// #else
// 	if ((hp = gethostbyname(hostname))) {
// 		memset(&sin, 0, sizeof(struct sockaddr_in));
// 		memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
// 		sin.sin_family = hp->h_addrtype;
// 		sin.sin_port = htons(purple_dnsquery_get_port(query_data));
// 
// 		data->hosts = g_slist_append(data->hosts,
// 				GSIZE_TO_POINTER(sizeof(sin)));
// 		data->hosts = g_slist_append(data->hosts,
// 				g_memdup(&sin, sizeof(sin)));
// 	} else {
// 		data->error_message = g_strdup_printf("Error resolving %s: %d", purple_dnsquery_get_host(query_data), h_errno);
// 	}
// #endif
	g_free(hostname);

	/* back to main thread */
	purple_timeout_add(0, dns_main_thread_cb, data);

	return 0;
}