comparison libpurple/dnssrv.c @ 25987:c4fd9222dda1

propagate from branch 'im.pidgin.pidgin' (head 303af74a38e7b313d4fb0be4d4054a16cb13d819) to branch 'im.pidgin.cpw.darkrain42.xmpp.bosh' (head 650d82b8a5f0c8860804dd8004cd54badea48e1e)
author Paul Aurich <paul@darkrain42.org>
date Sat, 07 Mar 2009 01:59:40 +0000
parents 1d1d1829de11
children e4a060a1e3de
comparison
equal deleted inserted replaced
25464:0e93bbb7f5ca 25987:c4fd9222dda1
31 #include <arpa/nameser_compat.h> 31 #include <arpa/nameser_compat.h>
32 #endif 32 #endif
33 #ifndef T_SRV 33 #ifndef T_SRV
34 #define T_SRV 33 34 #define T_SRV 33
35 #endif 35 #endif
36 #else 36 #ifndef T_TXT
37 #define T_TXT 16
38 #endif
39 #else /* WIN32 */
37 #include <windns.h> 40 #include <windns.h>
38 /* Missing from the mingw headers */ 41 /* Missing from the mingw headers */
39 #ifndef DNS_TYPE_SRV 42 #ifndef DNS_TYPE_SRV
40 # define DNS_TYPE_SRV 33 43 # define DNS_TYPE_SRV 33
44 #endif
45 #ifndef DNS_TYPE_TXT
46 # define DNS_TYPE_TXT 16
41 #endif 47 #endif
42 #endif 48 #endif
43 49
44 #include "dnssrv.h" 50 #include "dnssrv.h"
45 #include "eventloop.h" 51 #include "eventloop.h"
58 static void (WINAPI *MyDnsRecordListFree) (PDNS_RECORD pRecordList, 64 static void (WINAPI *MyDnsRecordListFree) (PDNS_RECORD pRecordList,
59 DNS_FREE_TYPE FreeType) = NULL; 65 DNS_FREE_TYPE FreeType) = NULL;
60 #endif 66 #endif
61 67
62 struct _PurpleSrvQueryData { 68 struct _PurpleSrvQueryData {
63 PurpleSrvCallback cb; 69 union {
70 PurpleSrvCallback srv;
71 PurpleTxtCallback txt;
72 } cb;
73
64 gpointer extradata; 74 gpointer extradata;
65 guint handle; 75 guint handle;
76 int type;
66 #ifdef _WIN32 77 #ifdef _WIN32
67 GThread *resolver; 78 GThread *resolver;
68 char *query; 79 char *query;
69 char *error_message; 80 char *error_message;
70 GSList *results; 81 GSList *results;
72 int fd_in, fd_out; 83 int fd_in, fd_out;
73 pid_t pid; 84 pid_t pid;
74 #endif 85 #endif
75 }; 86 };
76 87
88 typedef struct _PurpleSrvInternalQuery {
89 int type;
90 char query[256];
91 } PurpleSrvInternalQuery;
92
77 static gint 93 static gint
78 responsecompare(gconstpointer ar, gconstpointer br) 94 responsecompare(gconstpointer ar, gconstpointer br)
79 { 95 {
80 PurpleSrvResponse *a = (PurpleSrvResponse*)ar; 96 PurpleSrvResponse *a = (PurpleSrvResponse*)ar;
81 PurpleSrvResponse *b = (PurpleSrvResponse*)br; 97 PurpleSrvResponse *b = (PurpleSrvResponse*)br;
97 G_GNUC_NORETURN static void 113 G_GNUC_NORETURN static void
98 resolve(int in, int out) 114 resolve(int in, int out)
99 { 115 {
100 GList *ret = NULL; 116 GList *ret = NULL;
101 PurpleSrvResponse *srvres; 117 PurpleSrvResponse *srvres;
118 PurpleTxtResponse *txtres;
102 queryans answer; 119 queryans answer;
103 int size; 120 int size;
104 int qdcount; 121 int qdcount;
105 int ancount; 122 int ancount;
106 guchar *end; 123 guchar *end;
107 guchar *cp; 124 guchar *cp;
108 gchar name[256]; 125 gchar name[256];
109 guint16 type, dlen, pref, weight, port; 126 guint16 type, dlen, pref, weight, port;
110 gchar query[256]; 127 PurpleSrvInternalQuery query;
111 128
112 #ifdef HAVE_SIGNAL_H 129 #ifdef HAVE_SIGNAL_H
113 purple_restore_default_signal_handlers(); 130 purple_restore_default_signal_handlers();
114 #endif 131 #endif
115 132
116 if (read(in, query, 256) <= 0) { 133 if (read(in, &query, sizeof(query)) <= 0) {
117 close(out); 134 close(out);
118 close(in); 135 close(in);
119 _exit(0); 136 _exit(0);
120 } 137 }
121 138
122 size = res_query( query, C_IN, T_SRV, (u_char*)&answer, sizeof( answer)); 139 size = res_query( query.query, C_IN, query.type, (u_char*)&answer, sizeof( answer));
123 140
124 qdcount = ntohs(answer.hdr.qdcount); 141 qdcount = ntohs(answer.hdr.qdcount);
125 ancount = ntohs(answer.hdr.ancount); 142 ancount = ntohs(answer.hdr.ancount);
126
127 cp = (guchar*)&answer + sizeof(HEADER); 143 cp = (guchar*)&answer + sizeof(HEADER);
128 end = (guchar*)&answer + size; 144 end = (guchar*)&answer + size;
129 145
130 /* skip over unwanted stuff */ 146 /* skip over unwanted stuff */
131 while (qdcount-- > 0 && cp < end) { 147 while (qdcount-- > 0 && cp < end) {
136 152
137 while (ancount-- > 0 && cp < end) { 153 while (ancount-- > 0 && cp < end) {
138 size = dn_expand((unsigned char*)&answer, end, cp, name, 256); 154 size = dn_expand((unsigned char*)&answer, end, cp, name, 256);
139 if(size < 0) 155 if(size < 0)
140 goto end; 156 goto end;
141
142 cp += size; 157 cp += size;
143
144 GETSHORT(type,cp); 158 GETSHORT(type,cp);
145 159
146 /* skip ttl and class since we already know it */ 160 /* skip ttl and class since we already know it */
147 cp += 6; 161 cp += 6;
148 162
149 GETSHORT(dlen,cp); 163 GETSHORT(dlen,cp);
150 164 if (query.type == T_SRV) {
151 if (type == T_SRV) {
152 GETSHORT(pref,cp); 165 GETSHORT(pref,cp);
153 166
154 GETSHORT(weight,cp); 167 GETSHORT(weight,cp);
155 168
156 GETSHORT(port,cp); 169 GETSHORT(port,cp);
166 srvres->pref = pref; 179 srvres->pref = pref;
167 srvres->port = port; 180 srvres->port = port;
168 srvres->weight = weight; 181 srvres->weight = weight;
169 182
170 ret = g_list_insert_sorted(ret, srvres, responsecompare); 183 ret = g_list_insert_sorted(ret, srvres, responsecompare);
184 } else if (query.type == T_TXT) {
185 txtres = g_new0(PurpleTxtResponse, 1);
186 strncpy(txtres->content, (gchar*)(++cp), dlen-1);
187 ret = g_list_append(ret, txtres);
188 cp += dlen - 1;
171 } else { 189 } else {
172 cp += dlen; 190 cp += dlen;
173 } 191 }
174 } 192 }
175 193
176 end: 194 end:
177 size = g_list_length(ret); 195 size = g_list_length(ret);
178 write(out, &size, sizeof(int)); 196 write(out, &(query.type), sizeof(query.type));
197 write(out, &size, sizeof(size));
179 while (ret != NULL) 198 while (ret != NULL)
180 { 199 {
181 write(out, ret->data, sizeof(PurpleSrvResponse)); 200 if (query.type == T_SRV) write(out, ret->data, sizeof(PurpleSrvResponse));
201 if (query.type == T_TXT) write(out, ret->data, sizeof(PurpleTxtResponse));
182 g_free(ret->data); 202 g_free(ret->data);
183 ret = g_list_remove(ret, ret->data); 203 ret = g_list_remove(ret, ret->data);
184 } 204 }
185 205
186 close(out); 206 close(out);
191 211
192 static void 212 static void
193 resolved(gpointer data, gint source, PurpleInputCondition cond) 213 resolved(gpointer data, gint source, PurpleInputCondition cond)
194 { 214 {
195 int size; 215 int size;
216 int type;
196 PurpleSrvQueryData *query_data = (PurpleSrvQueryData*)data; 217 PurpleSrvQueryData *query_data = (PurpleSrvQueryData*)data;
197 PurpleSrvResponse *res;
198 PurpleSrvResponse *tmp;
199 int i; 218 int i;
200 PurpleSrvCallback cb = query_data->cb;
201 int status; 219 int status;
202 220
203 if (read(source, &size, sizeof(int)) == sizeof(int)) 221 if (read(source, &type, sizeof(type)) == sizeof(type)) {
204 { 222 if (type == T_SRV) {
205 ssize_t red; 223 PurpleSrvResponse *res;
206 purple_debug_info("dnssrv","found %d SRV entries\n", size); 224 PurpleSrvResponse *tmp;
207 tmp = res = g_new0(PurpleSrvResponse, size); 225 PurpleSrvCallback cb = query_data->cb.srv;
208 for (i = 0; i < size; i++) { 226 if (read(source, &size, sizeof(int)) == sizeof(int)) {
209 red = read(source, tmp++, sizeof(PurpleSrvResponse)); 227 ssize_t red;
210 if (red != sizeof(PurpleSrvResponse)) { 228 purple_debug_info("dnssrv","found %d SRV entries\n", size);
211 purple_debug_error("dnssrv","unable to read srv " 229 tmp = res = g_new0(PurpleSrvResponse, size);
212 "response: %s\n", g_strerror(errno)); 230 for (i = 0; i < size; i++) {
231 red = read(source, tmp++, sizeof(PurpleSrvResponse));
232 if (red != sizeof(PurpleSrvResponse)) {
233 purple_debug_error("dnssrv","unable to read srv "
234 "response: %s\n", g_strerror(errno));
235 size = 0;
236 g_free(res);
237 res = NULL;
238 }
239 }
240 } else {
241 purple_debug_info("dnssrv","found 0 SRV entries; errno is %i\n", errno);
213 size = 0; 242 size = 0;
214 g_free(res);
215 res = NULL; 243 res = NULL;
216 } 244 }
245 cb(res, size, query_data->extradata);
246 } else if (type == T_TXT) {
247 PurpleTxtResponse *res;
248 PurpleTxtResponse *tmp;
249 PurpleTxtCallback cb = query_data->cb.txt;
250 if (read(source, &size, sizeof(int)) == sizeof(int)) {
251 ssize_t red;
252 purple_debug_info("dnssrv","found %d TXT entries\n", size);
253 tmp = res = g_new0(PurpleTxtResponse, size);
254 for (i = 0; i < size; i++) {
255 red = read(source, tmp++, sizeof(PurpleTxtResponse));
256 if (red != sizeof(PurpleTxtResponse)) {
257 purple_debug_error("dnssrv","unable to read txt "
258 "response: %s\n", g_strerror(errno));
259 size = 0;
260 g_free(res);
261 res = NULL;
262 }
263 }
264 } else {
265 purple_debug_info("dnssrv","found 0 TXT entries; errno is %i\n", errno);
266 size = 0;
267 res = NULL;
268 }
269 cb(res, size, query_data->extradata);
270 } else {
271 purple_debug_info("dnssrv","type unknown of DNS result entry; errno is %i\n", errno);
217 } 272 }
218 } 273 }
219 else 274
220 {
221 purple_debug_info("dnssrv","found 0 SRV entries; errno is %i\n", errno);
222 size = 0;
223 res = NULL;
224 }
225
226 cb(res, size, query_data->extradata);
227 waitpid(query_data->pid, &status, 0); 275 waitpid(query_data->pid, &status, 0);
228
229 purple_srv_cancel(query_data); 276 purple_srv_cancel(query_data);
230 } 277 }
231 278
232 #else /* _WIN32 */ 279 #else /* _WIN32 */
233 280
235 282
236 static gboolean 283 static gboolean
237 res_main_thread_cb(gpointer data) 284 res_main_thread_cb(gpointer data)
238 { 285 {
239 PurpleSrvResponse *srvres = NULL; 286 PurpleSrvResponse *srvres = NULL;
287 PurpleTxtResponse *txtres = NULL;
240 int size = 0; 288 int size = 0;
241 PurpleSrvQueryData *query_data = data; 289 PurpleSrvQueryData *query_data = data;
242
243 if(query_data->error_message != NULL) 290 if(query_data->error_message != NULL)
244 purple_debug_error("dnssrv", query_data->error_message); 291 purple_debug_error("dnssrv", query_data->error_message);
245 else { 292 else {
246 PurpleSrvResponse *srvres_tmp = NULL; 293 if (query_data->type == T_SRV) {
247 GSList *lst = query_data->results; 294 PurpleSrvResponse *srvres_tmp = NULL;
248 295 GSList *lst = query_data->results;
249 size = g_slist_length(lst); 296
250 297 size = g_slist_length(lst);
251 if(query_data->cb && size > 0) 298
252 srvres_tmp = srvres = g_new0(PurpleSrvResponse, size); 299 if(query_data->cb.srv && size > 0)
253 while (lst) { 300 srvres_tmp = srvres = g_new0(PurpleSrvResponse, size);
254 if(query_data->cb) 301 while (lst) {
255 memcpy(srvres_tmp++, lst->data, sizeof(PurpleSrvResponse)); 302 if(query_data->cb.srv)
256 g_free(lst->data); 303 memcpy(srvres_tmp++, lst->data, sizeof(PurpleSrvResponse));
257 lst = g_slist_remove(lst, lst->data); 304 g_free(lst->data);
305 lst = g_slist_remove(lst, lst->data);
306 }
307
308 query_data->results = NULL;
309
310 purple_debug_info("dnssrv", "found %d SRV entries\n", size);
311
312 if(query_data->cb.srv) query_data->cb.srv(srvres, size, query_data->extradata);
313 } else if (query_data->type == T_TXT) {
314 PurpleTxtResponse *txtres_tmp = NULL;
315 GSList *lst = query_data->results;
316
317 size = g_slist_length(lst);
318
319 if(query_data->cb.txt && size > 0)
320 txtres_tmp = txtres = g_new0(PurpleTxtResponse, size);
321 while (lst) {
322 if(query_data->cb.txt)
323 memcpy(txtres_tmp++, lst->data, sizeof(PurpleTxtResponse));
324 g_free(lst->data);
325 lst = g_slist_remove(lst, lst->data);
326 }
327
328 query_data->results = NULL;
329
330 purple_debug_info("dnssrv", "found %d TXT entries\n", size);
331
332 if(query_data->cb.txt) query_data->cb.txt(txtres, size, query_data->extradata);
333 } else {
334 purple_debug_error("dnssrv", "unknown query type");
258 } 335 }
259 336 }
260 query_data->results = NULL;
261
262 purple_debug_info("dnssrv", "found %d SRV entries\n", size);
263 }
264
265 if(query_data->cb)
266 query_data->cb(srvres, size, query_data->extradata);
267 337
268 query_data->resolver = NULL; 338 query_data->resolver = NULL;
269 query_data->handle = 0; 339 query_data->handle = 0;
270 340
271 purple_srv_cancel(query_data); 341 purple_srv_cancel(query_data);
275 345
276 static gpointer 346 static gpointer
277 res_thread(gpointer data) 347 res_thread(gpointer data)
278 { 348 {
279 PDNS_RECORD dr = NULL; 349 PDNS_RECORD dr = NULL;
280 int type = DNS_TYPE_SRV; 350 int type;
281 DNS_STATUS ds; 351 DNS_STATUS ds;
282 PurpleSrvQueryData *query_data = data; 352 PurpleSrvQueryData *query_data = data;
283 353 type = query_data->type;
284 ds = MyDnsQuery_UTF8(query_data->query, type, DNS_QUERY_STANDARD, NULL, &dr, NULL); 354 ds = MyDnsQuery_UTF8(query_data->query, type, DNS_QUERY_STANDARD, NULL, &dr, NULL);
285 if (ds != ERROR_SUCCESS) { 355 if (ds != ERROR_SUCCESS) {
286 gchar *msg = g_win32_error_message(ds); 356 gchar *msg = g_win32_error_message(ds);
287 query_data->error_message = g_strdup_printf("Couldn't look up SRV record. %s (%lu).\n", msg, ds); 357 if (type == DNS_TYPE_SRV) {
358 query_data->error_message = g_strdup_printf("Couldn't look up SRV record. %s (%lu).\n", msg, ds);
359 } else if (type == DNS_TYPE_TXT) {
360 query_data->error_message = g_strdup_printf("Couldn't look up TXT record. %s (%lu).\n", msg, ds);
361 }
288 g_free(msg); 362 g_free(msg);
289 } else { 363 } else {
290 PDNS_RECORD dr_tmp; 364 if (type == DNS_TYPE_SRV) {
291 GSList *lst = NULL; 365 PDNS_RECORD dr_tmp;
292 DNS_SRV_DATA *srv_data; 366 GSList *lst = NULL;
293 PurpleSrvResponse *srvres; 367 DNS_SRV_DATA *srv_data;
294 368 PurpleSrvResponse *srvres;
295 for (dr_tmp = dr; dr_tmp != NULL; dr_tmp = dr_tmp->pNext) { 369
296 /* Discard any incorrect entries. I'm not sure if this is necessary */ 370 for (dr_tmp = dr; dr_tmp != NULL; dr_tmp = dr_tmp->pNext) {
297 if (dr_tmp->wType != type || strcmp(dr_tmp->pName, query_data->query) != 0) { 371 /* Discard any incorrect entries. I'm not sure if this is necessary */
298 continue; 372 if (dr_tmp->wType != type || strcmp(dr_tmp->pName, query_data->query) != 0) {
373 continue;
374 }
375
376 srv_data = &dr_tmp->Data.SRV;
377 srvres = g_new0(PurpleSrvResponse, 1);
378 strncpy(srvres->hostname, srv_data->pNameTarget, 255);
379 srvres->hostname[255] = '\0';
380 srvres->pref = srv_data->wPriority;
381 srvres->port = srv_data->wPort;
382 srvres->weight = srv_data->wWeight;
383
384 lst = g_slist_insert_sorted(lst, srvres, responsecompare);
299 } 385 }
300 386
301 srv_data = &dr_tmp->Data.SRV; 387 MyDnsRecordListFree(dr, DnsFreeRecordList);
302 srvres = g_new0(PurpleSrvResponse, 1); 388 query_data->results = lst;
303 strncpy(srvres->hostname, srv_data->pNameTarget, 255); 389 } else if (type == T_TXT) {
304 srvres->hostname[255] = '\0'; 390 #error IMPLEMENTATION MISSING
305 srvres->pref = srv_data->wPriority; 391 } else {
306 srvres->port = srv_data->wPort; 392
307 srvres->weight = srv_data->wWeight;
308
309 lst = g_slist_insert_sorted(lst, srvres, responsecompare);
310 } 393 }
311
312 MyDnsRecordListFree(dr, DnsFreeRecordList);
313 query_data->results = lst;
314 } 394 }
315 395
316 /* back to main thread */ 396 /* back to main thread */
317 /* Note: this should *not* be attached to query_data->handle - it will cause leakage */ 397 /* Note: this should *not* be attached to query_data->handle - it will cause leakage */
318 purple_timeout_add(0, res_main_thread_cb, query_data); 398 purple_timeout_add(0, res_main_thread_cb, query_data);
326 PurpleSrvQueryData * 406 PurpleSrvQueryData *
327 purple_srv_resolve(const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata) 407 purple_srv_resolve(const char *protocol, const char *transport, const char *domain, PurpleSrvCallback cb, gpointer extradata)
328 { 408 {
329 char *query; 409 char *query;
330 PurpleSrvQueryData *query_data; 410 PurpleSrvQueryData *query_data;
411 PurpleSrvInternalQuery internal_query;
331 #ifndef _WIN32 412 #ifndef _WIN32
332 int in[2], out[2]; 413 int in[2], out[2];
333 int pid; 414 int pid;
334 #else 415 #else
335 GError* err = NULL; 416 GError* err = NULL;
373 } 454 }
374 455
375 close(out[1]); 456 close(out[1]);
376 close(in[0]); 457 close(in[0]);
377 458
378 if (write(in[1], query, strlen(query)+1) < 0) 459 internal_query.type = T_SRV;
460 strncpy(internal_query.query, query, 255);
461
462 if (write(in[1], &internal_query, sizeof(internal_query)) < 0)
379 purple_debug_error("dnssrv", "Could not write to SRV resolver\n"); 463 purple_debug_error("dnssrv", "Could not write to SRV resolver\n");
464
380 465
381 query_data = g_new0(PurpleSrvQueryData, 1); 466 query_data = g_new0(PurpleSrvQueryData, 1);
382 query_data->cb = cb; 467 query_data->type = T_SRV;
468 query_data->cb.srv = cb;
383 query_data->extradata = extradata; 469 query_data->extradata = extradata;
384 query_data->pid = pid; 470 query_data->pid = pid;
385 query_data->fd_out = out[0]; 471 query_data->fd_out = out[0];
386 query_data->fd_in = in[1]; 472 query_data->fd_in = in[1];
387 query_data->handle = purple_input_add(out[0], PURPLE_INPUT_READ, resolved, query_data); 473 query_data->handle = purple_input_add(out[0], PURPLE_INPUT_READ, resolved, query_data);
396 "dnsapi.dll", "DnsRecordListFree"); 482 "dnsapi.dll", "DnsRecordListFree");
397 initialized = TRUE; 483 initialized = TRUE;
398 } 484 }
399 485
400 query_data = g_new0(PurpleSrvQueryData, 1); 486 query_data = g_new0(PurpleSrvQueryData, 1);
401 query_data->cb = cb; 487 query_data->type = DNS_TYPE_SRV;
488 query_data->cb.srv = cb;
402 query_data->query = query; 489 query_data->query = query;
403 query_data->extradata = extradata; 490 query_data->extradata = extradata;
404 491
405 if (!MyDnsQuery_UTF8 || !MyDnsRecordListFree) 492 if (!MyDnsQuery_UTF8 || !MyDnsRecordListFree)
406 query_data->error_message = g_strdup("System missing DNS API (Requires W2K+)\n"); 493 query_data->error_message = g_strdup("System missing DNS API (Requires W2K+)\n");
407 else { 494 else {
408 query_data->resolver = g_thread_create(res_thread, query_data, FALSE, &err); 495 query_data->resolver = g_thread_create(res_thread, query_data, FALSE, &err);
409 if (query_data->resolver == NULL) { 496 if (query_data->resolver == NULL) {
410 query_data->error_message = g_strdup_printf("SRV thread create failure: %s\n", (err && err->message) ? err->message : ""); 497 query_data->error_message = g_strdup_printf("SRV thread create failure: %s\n", (err && err->message) ? err->message : "");
498 g_error_free(err);
499 }
500 }
501
502 /* The query isn't going to happen, so finish the SRV lookup now.
503 * Asynchronously call the callback since stuff may not expect
504 * the callback to be called before this returns */
505 if (query_data->error_message != NULL)
506 query_data->handle = purple_timeout_add(0, res_main_thread_cb, query_data);
507
508 return query_data;
509 #endif
510 }
511
512 PurpleSrvQueryData *purple_txt_resolve(const char *owner, const char *domain, PurpleTxtCallback cb, gpointer extradata)
513 {
514 char *query;
515 PurpleSrvQueryData *query_data;
516 PurpleSrvInternalQuery internal_query;
517 #ifndef _WIN32
518 int in[2], out[2];
519 int pid;
520 #else
521 GError* err = NULL;
522 static gboolean initialized = FALSE;
523 #endif
524
525 query = g_strdup_printf("%s.%s", owner, domain);
526 purple_debug_info("dnssrv","querying TXT record for %s\n", query);
527
528 #ifndef _WIN32
529 if(pipe(in) || pipe(out)) {
530 purple_debug_error("dnssrv", "Could not create pipe\n");
531 g_free(query);
532 cb(NULL, 0, extradata);
533 return NULL;
534 }
535
536 pid = fork();
537 if (pid == -1) {
538 purple_debug_error("dnssrv", "Could not create process!\n");
539 cb(NULL, 0, extradata);
540 g_free(query);
541 return NULL;
542 }
543
544 /* Child */
545 if (pid == 0)
546 {
547 g_free(query);
548
549 close(out[0]);
550 close(in[1]);
551 resolve(in[0], out[1]);
552 /* resolve() does not return */
553 }
554
555 close(out[1]);
556 close(in[0]);
557
558 internal_query.type = T_TXT;
559 strncpy(internal_query.query, query, 255);
560
561 if (write(in[1], &internal_query, sizeof(internal_query)) < 0)
562 purple_debug_error("dnssrv", "Could not write to TXT resolver\n");
563
564 query_data = g_new0(PurpleSrvQueryData, 1);
565 query_data->type = T_TXT;
566 query_data->cb.txt = cb;
567 query_data->extradata = extradata;
568 query_data->pid = pid;
569 query_data->fd_out = out[0];
570 query_data->fd_in = in[1];
571 query_data->handle = purple_input_add(out[0], PURPLE_INPUT_READ, resolved, query_data);
572
573 g_free(query);
574
575 return query_data;
576 #else
577 if (!initialized) {
578 MyDnsQuery_UTF8 = (void*) wpurple_find_and_loadproc("dnsapi.dll", "DnsQuery_UTF8");
579 MyDnsRecordListFree = (void*) wpurple_find_and_loadproc(
580 "dnsapi.dll", "DnsRecordListFree");
581 initialized = TRUE;
582 }
583
584 query_data = g_new0(PurpleSrvQueryData, 1);
585 query_data->type = DNS_TYPE_TXT;
586 query_data->cb.txt = cb;
587 query_data->query = query;
588 query_data->extradata = extradata;
589
590 if (!MyDnsQuery_UTF8 || !MyDnsRecordListFree)
591 query_data->error_message = g_strdup("System missing DNS API (Requires W2K+)\n");
592 else {
593 query_data->resolver = g_thread_create(res_thread, query_data, FALSE, &err);
594 if (query_data->resolver == NULL) {
595 query_data->error_message = g_strdup_printf("TXT thread create failure: %s\n", (err && err->message) ? err->message : "");
411 g_error_free(err); 596 g_error_free(err);
412 } 597 }
413 } 598 }
414 599
415 /* The query isn't going to happen, so finish the SRV lookup now. 600 /* The query isn't going to happen, so finish the SRV lookup now.
433 /* 618 /*
434 * It's not really possible to kill a thread. So instead we 619 * It's not really possible to kill a thread. So instead we
435 * just set the callback to NULL and let the DNS lookup 620 * just set the callback to NULL and let the DNS lookup
436 * finish. 621 * finish.
437 */ 622 */
438 query_data->cb = NULL; 623 query_data->cb.srv = NULL;
439 return; 624 return;
440 } 625 }
441 g_free(query_data->query); 626 g_free(query_data->query);
442 g_free(query_data->error_message); 627 g_free(query_data->error_message);
443 #else 628 #else
444 close(query_data->fd_out); 629 close(query_data->fd_out);
445 close(query_data->fd_in); 630 close(query_data->fd_in);
446 #endif 631 #endif
447 g_free(query_data); 632 g_free(query_data);
448 } 633 }
634
635 void
636 purple_txt_cancel(PurpleSrvQueryData *query_data)
637 {
638 purple_srv_cancel(query_data);
639 }