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. }
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; }
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; }
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)); }
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); } }
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); }
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; }
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); }
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; }