1 /**
2  * @file telepathy-dnsquery.c
3  *
4  * pidgin-sipe
5  *
6  * Copyright (C) 2012-2017 SIPE Project <http://sipe.sourceforge.net/>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22 
23 #include <glib.h>
24 #include <gio/gio.h>
25 
26 #include "sipe-backend.h"
27 #include "sipe-common.h"
28 
29 struct sipe_dns_query {
30 	sipe_dns_resolved_cb  callback;
31 	gpointer	      extradata;
32 	guint                 port;
33 	GCancellable         *cancel;
34 };
35 
dns_srv_response(GObject * resolver,GAsyncResult * result,gpointer data)36 static void dns_srv_response(GObject *resolver,
37 			     GAsyncResult *result,
38 			     gpointer data)
39 {
40 	GError *error  = NULL;
41 	GList *targets = g_resolver_lookup_service_finish(G_RESOLVER(resolver),
42 							  result,
43 							  &error);
44 	struct sipe_dns_query *query = data;
45 
46 	if (targets) {
47 		GSrvTarget *target = targets->data;
48 		query->callback(query->extradata,
49 				g_srv_target_get_hostname(target),
50 				g_srv_target_get_port(target));
51 		g_resolver_free_targets(targets);
52 	} else {
53 		SIPE_DEBUG_INFO("dns_srv_response: failed: %s",
54 				error ? error->message : "UNKNOWN");
55 		if (error)
56 			g_error_free(error);
57 		if (query->callback)
58 			query->callback(query->extradata, NULL, 0);
59 	}
60 	g_object_unref(query->cancel);
61 	g_free(query);
62 }
63 
sipe_backend_dns_query_srv(SIPE_UNUSED_PARAMETER struct sipe_core_public * sipe_public,const gchar * protocol,const gchar * transport,const gchar * domain,sipe_dns_resolved_cb callback,gpointer data)64 struct sipe_dns_query *sipe_backend_dns_query_srv(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,
65 						  const gchar *protocol,
66 						  const gchar *transport,
67 						  const gchar *domain,
68 						  sipe_dns_resolved_cb callback,
69 						  gpointer data)
70 {
71 	struct sipe_dns_query *query = g_new0(struct sipe_dns_query, 1);
72 	GResolver *resolver          = g_resolver_get_default();
73 
74 	SIPE_DEBUG_INFO("sipe_backend_dns_query_srv: %s/%s/%s",
75 			protocol, transport, domain);
76 
77 	query->callback  = callback;
78 	query->extradata = data;
79 	query->cancel    = g_cancellable_new();
80 	g_resolver_lookup_service_async(resolver,
81 					protocol, transport, domain,
82 					query->cancel,
83 					dns_srv_response,
84 					query);
85 
86 	g_object_unref(resolver);
87 	return(query);
88 }
89 
dns_a_response(GObject * resolver,GAsyncResult * result,gpointer data)90 static void dns_a_response(GObject *resolver,
91 			   GAsyncResult *result,
92 			   gpointer data)
93 {
94 	GError *error    = NULL;
95 	GList *addresses = g_resolver_lookup_by_name_finish(G_RESOLVER(resolver),
96 							    result,
97 							    &error);
98 	struct sipe_dns_query *query = data;
99 
100 	if (addresses) {
101 		GInetAddress *address  = addresses->data;
102 		gchar        *ipstr    = g_inet_address_to_string(address);
103 		query->callback(query->extradata, ipstr, query->port);
104 		g_free(ipstr);
105 		g_resolver_free_addresses(addresses);
106 	} else {
107 		SIPE_DEBUG_INFO("dns_a_response: failed: %s",
108 				error ? error->message : "UNKNOWN");
109 		if (error)
110 			g_error_free(error);
111 		if (query->callback)
112 			query->callback(query->extradata, NULL, 0);
113 	}
114 	g_object_unref(query->cancel);
115 	g_free(query);
116 }
117 
sipe_backend_dns_query_a(SIPE_UNUSED_PARAMETER struct sipe_core_public * sipe_public,const gchar * hostname,guint port,sipe_dns_resolved_cb callback,gpointer data)118 struct sipe_dns_query *sipe_backend_dns_query_a(SIPE_UNUSED_PARAMETER struct sipe_core_public *sipe_public,
119 						const gchar *hostname,
120 						guint port,
121 						sipe_dns_resolved_cb callback,
122 						gpointer data)
123 {
124 	struct sipe_dns_query *query = g_new0(struct sipe_dns_query, 1);
125 	GResolver *resolver          = g_resolver_get_default();
126 
127 	SIPE_DEBUG_INFO("sipe_backend_dns_query_a: %s", hostname);
128 
129 	query->callback  = callback;
130 	query->extradata = data;
131 	query->port      = port;
132 	query->cancel    = g_cancellable_new();
133 	g_resolver_lookup_by_name_async(resolver,
134 					hostname,
135 					query->cancel,
136 					dns_a_response,
137 					query);
138 
139 	g_object_unref(resolver);
140 	return(query);
141 }
142 
sipe_backend_dns_query_cancel(struct sipe_dns_query * query)143 void sipe_backend_dns_query_cancel(struct sipe_dns_query *query)
144 {
145 	/* callback is invalid now, do no longer call! */
146 	query->callback = NULL;
147 	g_cancellable_cancel(query->cancel);
148 }
149 
150 /*
151   Local Variables:
152   mode: c
153   c-file-style: "bsd"
154   indent-tabs-mode: t
155   tab-width: 8
156   End:
157 */
158