comparison src/dnssrv.c @ 11395:f0e03a3ca3b5

[gaim-migrate @ 13626] Now this actually works! Also some whitespace cleanup. committer: Tailor Script <tailor@pidgin.im>
author Daniel Atallah <daniel.atallah@gmail.com>
date Wed, 31 Aug 2005 21:02:39 +0000
parents bdeace860555
children d678a37c16d9
comparison
equal deleted inserted replaced
11394:54934c165625 11395:f0e03a3ca3b5
46 #ifndef _WIN32 46 #ifndef _WIN32
47 typedef union { 47 typedef union {
48 HEADER hdr; 48 HEADER hdr;
49 u_char buf[1024]; 49 u_char buf[1024];
50 } queryans; 50 } queryans;
51 #else
52 static DNS_STATUS (*MyDnsQuery_UTF8) (
53 PCSTR lpstrName, WORD wType, DWORD fOptions,
54 PIP4_ARRAY aipServers, PDNS_RECORD* ppQueryResultsSet,
55 PVOID* pReserved) = NULL;
56 static void (*MyDnsRecordListFree) (PDNS_RECORD pRecordList,
57 DNS_FREE_TYPE FreeType) = NULL;
51 #endif 58 #endif
52 59
53 struct resdata { 60 struct resdata {
54 SRVCallback cb; 61 SRVCallback cb;
55 gpointer extradata; 62 gpointer extradata;
56 #ifndef _WIN32 63 #ifndef _WIN32
57 guint handle; 64 guint handle;
58 #else 65 #else
59 DNS_STATUS (*DnsQuery) (PCSTR lpstrName, WORD wType, DWORD fOptions,
60 PIP4_ARRAY aipServers, PDNS_RECORD* ppQueryResultsSet, PVOID* pReserved);
61 void (*DnsRecordListFree) (PDNS_RECORD pRecordList, DNS_FREE_TYPE FreeType);
62 char *query; 66 char *query;
63 char *errmsg; 67 char *errmsg;
64 GSList *results; 68 GSList *results;
65 #endif 69 #endif
66 }; 70 };
100 size = res_query( query, C_IN, T_SRV, (u_char*)&answer, sizeof( answer)); 104 size = res_query( query, C_IN, T_SRV, (u_char*)&answer, sizeof( answer));
101 105
102 qdcount = ntohs(answer.hdr.qdcount); 106 qdcount = ntohs(answer.hdr.qdcount);
103 ancount = ntohs(answer.hdr.ancount); 107 ancount = ntohs(answer.hdr.ancount);
104 108
105 109
106 cp = (guchar*)&answer + sizeof(HEADER); 110 cp = (guchar*)&answer + sizeof(HEADER);
107 end = (guchar*)&answer + size; 111 end = (guchar*)&answer + size;
108 112
109 /* skip over unwanted stuff */ 113 /* skip over unwanted stuff */
110 while (qdcount-- > 0 && cp < end) { 114 while (qdcount-- > 0 && cp < end) {
117 size = dn_expand((unsigned char*)&answer, end, cp, name, 256); 121 size = dn_expand((unsigned char*)&answer, end, cp, name, 256);
118 if(size < 0) 122 if(size < 0)
119 goto end; 123 goto end;
120 124
121 cp += size; 125 cp += size;
122 126
123 NS_GET16(type,cp); 127 NS_GET16(type,cp);
124 cp += 6; /* skip ttl and class since we already know it */ 128 cp += 6; /* skip ttl and class since we already know it */
125 129
126 NS_GET16(dlen,cp); 130 NS_GET16(dlen,cp);
127 131
141 srvres = g_new0(struct srv_response,1); 145 srvres = g_new0(struct srv_response,1);
142 strcpy(srvres->hostname, name); 146 strcpy(srvres->hostname, name);
143 srvres->pref = pref; 147 srvres->pref = pref;
144 srvres->port = port; 148 srvres->port = port;
145 srvres->weight = weight; 149 srvres->weight = weight;
146 150
147 ret = g_list_insert_sorted(ret, srvres, responsecompare); 151 ret = g_list_insert_sorted(ret, srvres, responsecompare);
148 } else { 152 } else {
149 cp += dlen; 153 cp += dlen;
150 } 154 }
151 } 155 }
158 } 162 }
159 163
160 /* Should the resolver be reused? 164 /* Should the resolver be reused?
161 * There is most likely only 1 SRV queries per prpl... 165 * There is most likely only 1 SRV queries per prpl...
162 */ 166 */
163 _exit(0); 167 _exit(0);
164 } 168 }
165 169
166 static void resolved(gpointer data, gint source, GaimInputCondition cond) { 170 static void resolved(gpointer data, gint source, GaimInputCondition cond) {
167 int size; 171 int size;
168 struct resdata *rdata = (struct resdata*)data; 172 struct resdata *rdata = (struct resdata*)data;
198 struct srv_response *srvres_tmp; 202 struct srv_response *srvres_tmp;
199 GSList *lst = rdata->results; 203 GSList *lst = rdata->results;
200 204
201 size = g_slist_length(rdata->results); 205 size = g_slist_length(rdata->results);
202 206
203 gaim_debug_info("srv","found %d SRV entries\n", size);
204
205 srvres_tmp = srvres = g_malloc0(sizeof(struct srv_response) * size); 207 srvres_tmp = srvres = g_malloc0(sizeof(struct srv_response) * size);
206 while (lst) { 208 while (lst) {
207 memcpy(srvres_tmp++, lst->data, sizeof(struct srv_response)); 209 memcpy(srvres_tmp++, lst->data, sizeof(struct srv_response));
208 g_free(lst->data); 210 g_free(lst->data);
209 lst = g_slist_remove(lst, lst->data); 211 lst = g_slist_remove(lst, lst->data);
210 } 212 }
211 213
212 rdata->results = lst; 214 rdata->results = lst;
213 } 215 }
214 216
217 gaim_debug_info("srv", "found %d SRV entries\n", size);
218
215 rdata->cb(srvres, size, rdata->extradata); 219 rdata->cb(srvres, size, rdata->extradata);
216 220
217 g_free(rdata->query); 221 g_free(rdata->query);
218 g_free(rdata); 222 g_free(rdata);
219 223
220 return FALSE; 224 return FALSE;
221 } 225 }
222 226
223 static gpointer res_thread(gpointer data) { 227 static gpointer res_thread(gpointer data) {
224 DNS_RECORD *dr = NULL, *dr_tmp; 228 DNS_RECORD *dr = NULL;
225 GSList *lst = NULL; 229 GSList *lst = NULL;
226 struct srv_response *srvres; 230 struct srv_response *srvres;
227 DNS_SRV_DATA *srv_data; 231 DNS_SRV_DATA *srv_data;
228 int type = DNS_TYPE_SRV; 232 int type = DNS_TYPE_SRV;
229 DNS_STATUS ds; 233 DNS_STATUS ds;
230 struct resdata *rdata = data; 234 struct resdata *rdata = data;
231 235
232 ds = rdata->DnsQuery(rdata->query, type, DNS_QUERY_STANDARD, NULL, &dr, NULL); 236 ds = MyDnsQuery_UTF8(rdata->query, type, DNS_QUERY_STANDARD, NULL, &dr, NULL);
233 if (ds != ERROR_SUCCESS) { 237 if (ds != ERROR_SUCCESS) {
234 rdata->errmsg = g_strdup_printf("Couldn't look up SRV record. Error = %d\n", (int) ds); 238 rdata->errmsg = g_strdup_printf("Couldn't look up SRV record. Error = %d\n", (int) ds);
235 } else { 239 } else {
236 dr_tmp = dr; 240 DNS_RECORD *dr_tmp = dr;
237 while (dr_tmp != NULL) { 241 while (dr_tmp != NULL) {
238
239 /* Discard any incorrect entries. I'm not sure if this is necessary */ 242 /* Discard any incorrect entries. I'm not sure if this is necessary */
240 if (dr_tmp->wType != type || strcmp(dr_tmp->pName, rdata->query) != 0) { 243 if (dr_tmp->wType != type || strcmp(dr_tmp->pName, rdata->query) != 0) {
244 dr_tmp = dr_tmp->pNext;
241 continue; 245 continue;
242 } 246 }
243 247
244 srv_data = &dr_tmp->Data.SRV; 248 srv_data = &dr_tmp->Data.SRV;
245 srvres = g_new0(struct srv_response, 1); 249 srvres = g_new0(struct srv_response, 1);
249 srvres->port = srv_data->wPort; 253 srvres->port = srv_data->wPort;
250 srvres->weight = srv_data->wWeight; 254 srvres->weight = srv_data->wWeight;
251 255
252 lst = g_slist_insert_sorted(lst, srvres, responsecompare); 256 lst = g_slist_insert_sorted(lst, srvres, responsecompare);
253 257
254 dr_tmp = dr->pNext; 258 dr_tmp = dr_tmp->pNext;
255 } 259 }
256 260
257 rdata->DnsRecordListFree(dr, DnsFreeRecordList); 261 MyDnsRecordListFree(dr, DnsFreeRecordList);
258 rdata->results = lst; 262 rdata->results = lst;
259 } 263 }
260 264
261 /* back to main thread */ 265 /* back to main thread */
262 g_idle_add(res_main_thread_cb, rdata); 266 g_idle_add(res_main_thread_cb, rdata);
295 resolve(in[0], out[1]); 299 resolve(in[0], out[1]);
296 } 300 }
297 301
298 close(out[1]); 302 close(out[1]);
299 close(in[0]); 303 close(in[0]);
300 304
301 if(write(in[1], query, strlen(query)+1)<0) { 305 if(write(in[1], query, strlen(query)+1)<0) {
302 gaim_debug_error("srv", "Could not write to SRV resolver\n"); 306 gaim_debug_error("srv", "Could not write to SRV resolver\n");
303 } 307 }
304 rdata = g_new0(struct resdata,1); 308 rdata = g_new0(struct resdata,1);
305 rdata->cb = cb; 309 rdata->cb = cb;
310 #else 314 #else
311 GError* err = NULL; 315 GError* err = NULL;
312 316
313 static gboolean initialized = FALSE; 317 static gboolean initialized = FALSE;
314 318
315 static DNS_STATUS (*MyDnsQuery_UTF) (
316 PCSTR lpstrName, WORD wType, DWORD fOptions, PIP4_ARRAY aipServers,
317 PDNS_RECORD* ppQueryResultsSet, PVOID* pReserved) = NULL;
318 static void (*MyDnsRecordListFree) (PDNS_RECORD pRecordList, DNS_FREE_TYPE FreeType) = NULL;
319
320 gaim_debug_info("srv","querying SRV record for %s\n", query); 319 gaim_debug_info("srv","querying SRV record for %s\n", query);
321 320
322 if (!initialized) { 321 if (!initialized) {
323 MyDnsQuery_UTF = (void*) wgaim_find_and_loadproc("dnsapi.dll", "DnsQuery_UTF"); 322 MyDnsQuery_UTF8 = (void*) wgaim_find_and_loadproc("dnsapi.dll", "DnsQuery_UTF8");
324 MyDnsRecordListFree = (void*) wgaim_find_and_loadproc( 323 MyDnsRecordListFree = (void*) wgaim_find_and_loadproc(
325 "dnsapi.dll", "DnsRecordListFree"); 324 "dnsapi.dll", "DnsRecordListFree");
326 initialized = TRUE; 325 initialized = TRUE;
327 } 326 }
328 327
329 328 if (!MyDnsQuery_UTF8 || !MyDnsRecordListFree) {
330 if (!MyDnsQuery_UTF || !MyDnsRecordListFree) {
331 gaim_debug_error("srv", "System missing DNS API (Requires W2K+)\n"); 329 gaim_debug_error("srv", "System missing DNS API (Requires W2K+)\n");
332 g_free(query); 330 g_free(query);
333 cb(NULL, 0, extradata); 331 cb(NULL, 0, extradata);
334 return; 332 return;
335 } 333 }
336 334
337 rdata = g_new0(struct resdata, 1); 335 rdata = g_new0(struct resdata, 1);
338 rdata->DnsQuery = MyDnsQuery_UTF;
339 rdata->DnsRecordListFree = MyDnsRecordListFree;
340 rdata->cb = cb; 336 rdata->cb = cb;
341 rdata->query = query; 337 rdata->query = query;
338 rdata->extradata = extradata;
342 339
343 if (!g_thread_create(res_thread, rdata, FALSE, &err)) { 340 if (!g_thread_create(res_thread, rdata, FALSE, &err)) {
344 rdata->errmsg = g_strdup_printf("SRV thread create failure: %s\n", err ? err->message : ""); 341 rdata->errmsg = g_strdup_printf("SRV thread create failure: %s\n", err ? err->message : "");
345 g_error_free(err); 342 g_error_free(err);
346 res_main_thread_cb(rdata); 343 res_main_thread_cb(rdata);