comparison src/dnssrv.c @ 11379:51c189755f1d

[gaim-migrate @ 13605] Make the NTLM and dnssrv stuff compile on win32. This hasn't been tested very much (i.e. at all). When something starts using this stuff it'll get some testing love. committer: Tailor Script <tailor@pidgin.im>
author Daniel Atallah <daniel.atallah@gmail.com>
date Wed, 31 Aug 2005 00:00:31 +0000
parents c84c35ee8202
children e0f42900de12
comparison
equal deleted inserted replaced
11378:3c88e4519fd1 11379:51c189755f1d
1 /** 1 /**
2 * @file srvresolve.c 2 * @file dnssrv.c
3 * 3 *
4 * gaim 4 * gaim
5 * 5 *
6 * Copyright (C) 2005 Thomas Butter <butter@uni-mannheim.de> 6 * Copyright (C) 2005 Thomas Butter <butter@uni-mannheim.de>
7 * 7 *
18 * You should have received a copy of the GNU General Public License 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 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 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */ 21 */
22 #include <glib.h> 22 #include <glib.h>
23 #ifndef _WIN32
23 #include <resolv.h> 24 #include <resolv.h>
24 #include <stdlib.h> 25 #include <stdlib.h>
25 #include <arpa/nameser_compat.h> 26 #include <arpa/nameser_compat.h>
26 #ifndef T_SRV 27 #ifndef T_SRV
27 #define T_SRV 33 28 #define T_SRV 33
29 #endif
30 #else
31 #include "win32dep.h"
32 #include <windns.h>
33 /* Missing from the mingw headers */
34 #ifndef DNS_TYPE_SRV
35 # define DNS_TYPE_SRV 33
36 #endif
28 #endif 37 #endif
29 38
30 #include "dnssrv.h" 39 #include "dnssrv.h"
31 #include <stdio.h> 40 #include <stdio.h>
32 #include <unistd.h> 41 #include <unistd.h>
33 #include <string.h> 42 #include <string.h>
34 #include "eventloop.h" 43 #include "eventloop.h"
35 #include "debug.h" 44 #include "debug.h"
36 45
46 #ifndef _WIN32
37 typedef union { 47 typedef union {
38 HEADER hdr; 48 HEADER hdr;
39 u_char buf[1024]; 49 u_char buf[1024];
40 } queryans; 50 } queryans;
51 #endif
41 52
42 struct resdata { 53 struct resdata {
43 SRVCallback cb; 54 SRVCallback cb;
55 #ifndef _WIN32
44 guint handle; 56 guint handle;
57 #else
58 DNS_STATUS (*DnsQuery) (PCSTR lpstrName, WORD wType, DWORD fOptions,
59 PIP4_ARRAY aipServers, PDNS_RECORD* ppQueryResultsSet, PVOID* pReserved);
60 void (*DnsRecordListFree) (PDNS_RECORD pRecordList, DNS_FREE_TYPE FreeType);
61 char *query;
62 char *errmsg;
63 GSList *results;
64 #endif
45 }; 65 };
46 66
47 static gint responsecompare(gconstpointer ar, gconstpointer br) { 67 static gint responsecompare(gconstpointer ar, gconstpointer br) {
48 struct srv_response *a = (struct srv_response*)ar; 68 struct srv_response *a = (struct srv_response*)ar;
49 struct srv_response *b = (struct srv_response*)br; 69 struct srv_response *b = (struct srv_response*)br;
57 } 77 }
58 if(a->pref < b->pref) 78 if(a->pref < b->pref)
59 return -1; 79 return -1;
60 return 1; 80 return 1;
61 } 81 }
62 82 #ifndef _WIN32
63 static void resolve(int in, int out) { 83 static void resolve(int in, int out) {
64 GList *ret = NULL; 84 GList *ret = NULL;
65 struct srv_response *srvres; 85 struct srv_response *srvres;
66 queryans answer; 86 queryans answer;
67 int size; 87 int size;
159 cb(res, size); 179 cb(res, size);
160 gaim_input_remove(rdata->handle); 180 gaim_input_remove(rdata->handle);
161 g_free(rdata); 181 g_free(rdata);
162 } 182 }
163 183
184 #else /* _WIN32 */
185
186 /** The Jabber Server code was inspiration for parts of this. */
187
188 static gboolean res_main_thread_cb(gpointer data) {
189 struct srv_response *srvres = NULL;
190 int size = 0;
191 struct resdata *rdata = data;
192
193 if (rdata->errmsg != NULL) {
194 gaim_debug_error("srv", rdata->errmsg);
195 g_free(rdata->errmsg);
196 } else {
197 struct srv_response *srvres_tmp;
198 GSList *lst = rdata->results;
199
200 size = g_slist_length(rdata->results);
201
202 gaim_debug_info("srv","found %d SRV entries\n", size);
203
204 srvres_tmp = srvres = g_malloc0(sizeof(struct srv_response) * size);
205 while (lst) {
206 memcpy(srvres_tmp++, lst->data, sizeof(struct srv_response));
207 g_free(lst->data);
208 lst = g_slist_remove(lst, lst->data);
209 }
210
211 rdata->results = lst;
212 }
213
214 rdata->cb(srvres, size);
215
216 g_free(rdata->query);
217 g_free(rdata);
218
219 return FALSE;
220 }
221
222 static gpointer res_thread(gpointer data) {
223 DNS_RECORD *dr = NULL, *dr_tmp;
224 GSList *lst = NULL;
225 struct srv_response *srvres;
226 DNS_SRV_DATA *srv_data;
227 int type = DNS_TYPE_SRV;
228 DNS_STATUS ds;
229 struct resdata *rdata = data;
230
231 ds = rdata->DnsQuery(rdata->query, type, DNS_QUERY_STANDARD, NULL, &dr, NULL);
232 if (ds != ERROR_SUCCESS) {
233 rdata->errmsg = g_strdup_printf("Couldn't look up SRV record. Error = %d\n", (int) ds);
234 } else {
235 dr_tmp = dr;
236 while (dr_tmp != NULL) {
237
238 /* Discard any incorrect entries. I'm not sure if this is necessary */
239 if (dr_tmp->wType != type || strcmp(dr_tmp->pName, rdata->query) != 0) {
240 continue;
241 }
242
243 srv_data = &dr_tmp->Data.SRV;
244 srvres = g_new0(struct srv_response, 1);
245 strncpy(srvres->hostname, srv_data->pNameTarget, 255);
246 srvres->hostname[255] = '\0';
247 srvres->pref = srv_data->wPriority;
248 srvres->port = srv_data->wPort;
249 srvres->weight = srv_data->wWeight;
250
251 lst = g_slist_insert_sorted(lst, srvres, responsecompare);
252
253 dr_tmp = dr->pNext;
254 }
255
256 rdata->DnsRecordListFree(dr, DnsFreeRecordList);
257 rdata->results = lst;
258 }
259
260 /* back to main thread */
261 g_idle_add(res_main_thread_cb, rdata);
262
263 return 0;
264 }
265
266 #endif
267
164 void gaim_srv_resolve(char *protocol, char *transport, char *domain, SRVCallback cb) { 268 void gaim_srv_resolve(char *protocol, char *transport, char *domain, SRVCallback cb) {
165 char *query = g_strdup_printf("_%s._%s.%s",protocol, transport, domain); 269 char *query = g_strdup_printf("_%s._%s.%s",protocol, transport, domain);
270 struct resdata *rdata;
271 #ifndef _WIN32
166 int in[2], out[2]; 272 int in[2], out[2];
167 int pid; 273 int pid;
168 struct resdata *rdata; 274 gaim_debug_info("srv","querying SRV record for %s\n", query);
169 gaim_debug_info("dnssrv","querying SRV record for %s\n",query);
170 if(pipe(in) || pipe(out)) { 275 if(pipe(in) || pipe(out)) {
171 gaim_debug_error("srv", "Could not create pipe\n"); 276 gaim_debug_error("srv", "Could not create pipe\n");
172 g_free(query); 277 g_free(query);
173 cb(NULL, 0); 278 cb(NULL, 0);
174 return; 279 return;
196 gaim_debug_error("srv", "Could not write to SRV resolver\n"); 301 gaim_debug_error("srv", "Could not write to SRV resolver\n");
197 } 302 }
198 rdata = g_new0(struct resdata,1); 303 rdata = g_new0(struct resdata,1);
199 rdata->cb = cb; 304 rdata->cb = cb;
200 rdata->handle = gaim_input_add(out[0], GAIM_INPUT_READ, resolved, rdata); 305 rdata->handle = gaim_input_add(out[0], GAIM_INPUT_READ, resolved, rdata);
306
201 g_free(query); 307 g_free(query);
202 } 308 #else
309 GError* err = NULL;
310
311 static gboolean initialized = FALSE;
312
313 static DNS_STATUS (*MyDnsQuery_UTF) (
314 PCSTR lpstrName, WORD wType, DWORD fOptions, PIP4_ARRAY aipServers,
315 PDNS_RECORD* ppQueryResultsSet, PVOID* pReserved) = NULL;
316 static void (*MyDnsRecordListFree) (PDNS_RECORD pRecordList, DNS_FREE_TYPE FreeType) = NULL;
317
318 gaim_debug_info("srv","querying SRV record for %s\n", query);
319
320 if (!initialized) {
321 MyDnsQuery_UTF = (void*) wgaim_find_and_loadproc("dnsapi.dll", "DnsQuery_UTF");
322 MyDnsRecordListFree = (void*) wgaim_find_and_loadproc(
323 "dnsapi.dll", "DnsRecordListFree");
324 initialized = TRUE;
325 }
326
327
328 if (!MyDnsQuery_UTF || !MyDnsRecordListFree) {
329 gaim_debug_error("srv", "System missing DNS API (Requires W2K+)\n");
330 g_free(query);
331 cb(NULL, 0);
332 return;
333 }
334
335 rdata = g_new0(struct resdata, 1);
336 rdata->DnsQuery = MyDnsQuery_UTF;
337 rdata->DnsRecordListFree = MyDnsRecordListFree;
338 rdata->cb = cb;
339 rdata->query = query;
340
341 if (!g_thread_create(res_thread, rdata, FALSE, &err)) {
342 rdata->errmsg = g_strdup_printf("SRV thread create failure: %s\n", err ? err->message : "");
343 g_error_free(err);
344 res_main_thread_cb(rdata);
345 }
346 #endif
347 }
348