From e2a29e310366698987079aa96395678a031c4ae5 Mon Sep 17 00:00:00 2001 From: Jakub Adam Date: Sat, 11 Sep 2010 18:52:33 +0200 Subject: [PATCH] dnsquery: added option to resolve DNS A records Whole backend code reworked for general usage. --- src/api/sipe-backend.h | 18 ++++-- src/api/sipe-core.h | 12 ---- src/core/sip-transport.c | 48 ++++++++------- src/core/sipe-core-private.h | 2 + src/purple/purple-dnsquery.c | 136 ++++++++++++++++++++++++++++++++++--------- src/purple/purple-plugin.c | 2 - src/purple/purple-private.h | 2 - 7 files changed, 153 insertions(+), 67 deletions(-) diff --git a/src/api/sipe-backend.h b/src/api/sipe-backend.h index 70f0aa68..f11c5867 100644 --- a/src/api/sipe-backend.h +++ b/src/api/sipe-backend.h @@ -154,10 +154,20 @@ gboolean sipe_backend_connection_is_valid(struct sipe_core_public *sipe_public); /** DNS QUERY ****************************************************************/ -void sipe_backend_dns_query(struct sipe_core_public *sipe_public, - const gchar *protocol, - const gchar *transport, - const gchar *domain); +typedef void (*sipe_dns_resolved_cb)(gpointer data, const gchar *hostname, guint port); + +struct sipe_dns_query *sipe_backend_dns_query_srv(const gchar *protocol, + const gchar *transport, + const gchar *domain, + sipe_dns_resolved_cb callback, + gpointer data); + +struct sipe_dns_query *sipe_backend_dns_query_a(const gchar *hostname, + int port, + sipe_dns_resolved_cb callback, + gpointer data); + +void sipe_backend_dns_query_cancel(struct sipe_dns_query *query); /** FILE TRANSFER ************************************************************/ void sipe_backend_ft_error(struct sipe_file_transfer *ft, diff --git a/src/api/sipe-core.h b/src/api/sipe-core.h index d5b30cd5..8c3c7595 100644 --- a/src/api/sipe-core.h +++ b/src/api/sipe-core.h @@ -241,18 +241,6 @@ void sipe_core_transport_sip_connect(struct sipe_core_public *sipe_public, void sipe_core_transport_sip_keepalive(struct sipe_core_public *sipe_public); /** - * DNS SRV resolved hook - * - * @param sipe_public - * @param hostname SIP server hostname - * @param port SIP server port - */ -void sipe_core_dns_resolved(struct sipe_core_public *sipe_public, - const gchar *hostname, - guint port); -void sipe_core_dns_resolve_failure(struct sipe_core_public *sipe_public); - -/** * Create a new chat */ void sipe_core_chat_create(struct sipe_core_public *sipe_public, guint id, diff --git a/src/core/sip-transport.c b/src/core/sip-transport.c index c8627945..e95ebbf3 100644 --- a/src/core/sip-transport.c +++ b/src/core/sip-transport.c @@ -1272,6 +1272,10 @@ void sip_transport_disconnect(struct sipe_core_private *sipe_private) sipe_private->transport = NULL; sipe_private->service_data = NULL; + + if (sipe_private->dns_query) + sipe_backend_dns_query_cancel(sipe_private->dns_query); + } guint sip_transport_port(struct sipe_core_private *sipe_private) @@ -1598,6 +1602,24 @@ static const struct sip_service_data *services[] = { service_tcp /* SIPE_TRANSPORT_TCP */ }; +static void sipe_core_dns_resolved(struct sipe_core_public *sipe_public, + const gchar *hostname, guint port) +{ + struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE; + + sipe_private->dns_query = NULL; + + if (hostname) { + SIPE_DEBUG_INFO("sipe_core_dns_resolved - SRV hostname: %s port: %d", + hostname, port); + sipe_server_register(sipe_private, + sipe_private->service_data->type, + g_strdup(hostname), port); + } else { + resolve_next_service(SIPE_CORE_PRIVATE, NULL); + } +} + static void resolve_next_service(struct sipe_core_private *sipe_private, const struct sip_service_data *start) { @@ -1624,26 +1646,12 @@ static void resolve_next_service(struct sipe_core_private *sipe_private, } /* Try to resolve next service */ - sipe_backend_dns_query(SIPE_CORE_PUBLIC, - sipe_private->service_data->protocol, - sipe_private->service_data->transport, - sipe_private->public.sip_domain); -} - -void sipe_core_dns_resolved(struct sipe_core_public *sipe_public, - const gchar *hostname, guint port) -{ - struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE; - SIPE_DEBUG_INFO("sipe_core_dns_resolved - SRV hostname: %s port: %d", - hostname, port); - sipe_server_register(sipe_private, - sipe_private->service_data->type, - g_strdup(hostname), port); -} - -void sipe_core_dns_resolve_failure(struct sipe_core_public *sipe_public) -{ - resolve_next_service(SIPE_CORE_PRIVATE, NULL); + sipe_private->dns_query = sipe_backend_dns_query_srv( + sipe_private->service_data->protocol, + sipe_private->service_data->transport, + sipe_private->public.sip_domain, + (sipe_dns_resolved_cb) sipe_core_dns_resolved, + SIPE_CORE_PUBLIC); } void sipe_core_transport_sip_connect(struct sipe_core_public *sipe_public, diff --git a/src/core/sipe-core-private.h b/src/core/sipe-core-private.h index 1f4feb47..c96bb032 100644 --- a/src/core/sipe-core-private.h +++ b/src/core/sipe-core-private.h @@ -69,6 +69,8 @@ struct sipe_core_private { /* @TODO: move to purple backend when menu code moves */ GSList *blist_menu_containers; + struct sipe_dns_query *dns_query; + /* the original data structure*/ struct sipe_account_data *temporary; }; diff --git a/src/purple/purple-dnsquery.c b/src/purple/purple-dnsquery.c index cf716788..02d16d05 100644 --- a/src/purple/purple-dnsquery.c +++ b/src/purple/purple-dnsquery.c @@ -20,48 +20,130 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifdef _WIN32 +#include +#else +#include +#include +#endif + #include "glib.h" +#include "dnsquery.h" #include "dnssrv.h" #include "sipe-backend.h" -#include "sipe-core.h" -#include "purple-private.h" +struct sipe_dns_query { + enum { + A, + SRV + } type; + sipe_dns_resolved_cb callback; + gpointer extradata; + gpointer purple_query_data; +}; -static void dns_srv_response(PurpleSrvResponse *resp, - int results, - gpointer data) +static void dns_a_response(GSList *hosts, + struct sipe_dns_query *query, + const char *error_message) { - struct sipe_backend_private *purple_private = data; + char ipstr[INET6_ADDRSTRLEN]; + struct sockaddr *addr; + const void *addrdata; + int port; - /* data no longer needed and free'd by libpurple */ - purple_private->dns_query = NULL; + if (error_message || !g_slist_next(hosts)) { + query->callback(query->extradata, NULL, 0); + g_slist_free(hosts); + return; + } - /* find the host to connect to */ - if (results) { - sipe_core_dns_resolved(purple_private->public, - resp->hostname, - resp->port); - g_free(resp); + addr = g_slist_next(hosts)->data; + if (addr->sa_family == AF_INET6) { + addrdata = &((struct sockaddr_in6 *) addr)->sin6_addr; + port = ((struct sockaddr_in6 *) addr)->sin6_port; } else { - sipe_core_dns_resolve_failure(purple_private->public); + addrdata = &((struct sockaddr_in *) addr)->sin_addr; + port = ((struct sockaddr_in *) addr)->sin_port; } + + inet_ntop(addr->sa_family, addrdata, ipstr, sizeof (ipstr)); + + query->callback(query->extradata, ipstr, port); + + for (; hosts; hosts = g_slist_delete_link(hosts, hosts)) { + // Free the addrlen, no data in this link + hosts = g_slist_delete_link(hosts, hosts); + // Free the address + g_free(hosts->data); + } + + g_free(query); +} + +struct sipe_dns_query *sipe_backend_dns_query_a(const gchar *hostname, + int port, + sipe_dns_resolved_cb callback, + gpointer data) +{ + struct sipe_dns_query *query = g_new(struct sipe_dns_query, 1); + query->type = A; + query->callback = callback; + query->extradata = data; + query->purple_query_data = purple_dnsquery_a(hostname, + port, + (PurpleDnsQueryConnectFunction) dns_a_response, + query); + + return query; } -void sipe_backend_dns_query(struct sipe_core_public *sipe_public, - const gchar *protocol, - const gchar *transport, - const gchar *domain) + +static void dns_srv_response(PurpleSrvResponse *resp, + int results, + struct sipe_dns_query *query) +{ + if (results) + query->callback(query->extradata, resp->hostname, resp->port); + else + query->callback(query->extradata, NULL, 0); + + g_free(query); + g_free(resp); +} + +struct sipe_dns_query *sipe_backend_dns_query_srv(const gchar *protocol, + const gchar *transport, + const gchar *domain, + sipe_dns_resolved_cb callback, + gpointer data) { - struct sipe_backend_private *purple_private = sipe_public->backend_private; - - /* Try to resolve next service */ - purple_private->dns_query = purple_srv_resolve(protocol, - transport, - domain, - dns_srv_response, - purple_private); + struct sipe_dns_query *query = g_new(struct sipe_dns_query, 1); + query->type = SRV; + query->callback = callback; + query->extradata = data; + query->purple_query_data = purple_srv_resolve(protocol, + transport, + domain, + (PurpleSrvCallback) dns_srv_response, + query); + + return query; +} + +void sipe_backend_dns_query_cancel(struct sipe_dns_query *query) +{ + switch (query->type) { + case A: + purple_dnsquery_destroy(query->purple_query_data); + break; + case SRV: + purple_srv_cancel(query->purple_query_data); + break; + } + + g_free(query); } /* diff --git a/src/purple/purple-plugin.c b/src/purple/purple-plugin.c index 9249d5d9..61fca4ca 100644 --- a/src/purple/purple-plugin.c +++ b/src/purple/purple-plugin.c @@ -328,8 +328,6 @@ static void sipe_close(PurpleConnection *gc) sipe_core_deallocate(sipe_public); - if (purple_private->dns_query) - purple_srv_cancel(purple_private->dns_query); if (purple_private->roomlist_map) g_hash_table_destroy(purple_private->roomlist_map); g_free(purple_private); diff --git a/src/purple/purple-private.h b/src/purple/purple-private.h index 56860ba4..29f286e6 100644 --- a/src/purple/purple-private.h +++ b/src/purple/purple-private.h @@ -25,14 +25,12 @@ struct sipe_core_public; struct _PurpleAccount; struct _PurpleConnection; struct _PurpleRoomlist; -struct _PurpleSrvQueryData; struct _PurpleXfer; struct sipe_backend_private { struct sipe_core_public *public; struct _PurpleConnection *gc; struct _PurpleAccount *account; - struct _PurpleSrvQueryData *dns_query; struct _PurpleRoomlist *roomlist; GHashTable *roomlist_map; /* name -> uri */ time_t last_keepalive; -- 2.11.4.GIT