Mercurial > pidgin.yaz
comparison libpurple/protocols/bonjour/mdns_win32.c @ 31017:014a58e994da
Use DNSServiceGetAddrInfo() from dns_sd.h to resolve the IP for remote bonjour
users on Win32 instead of the libpurple resolving API. This way, we make sure
we're using the same interface as we received the presence notification on.
There is also some debug message improvement and using constants instead of
magic numbers in this commit.
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Mon, 04 Oct 2010 00:35:26 +0000 |
parents | 927e01ad06ae |
children | 9c8b28dc6656 |
comparison
equal
deleted
inserted
replaced
31016:cc05402eb2ba | 31017:014a58e994da |
---|---|
23 #include "debug.h" | 23 #include "debug.h" |
24 | 24 |
25 #include "buddy.h" | 25 #include "buddy.h" |
26 #include "mdns_interface.h" | 26 #include "mdns_interface.h" |
27 #include "dns_sd_proxy.h" | 27 #include "dns_sd_proxy.h" |
28 #include "dnsquery.h" | |
29 #include "mdns_common.h" | 28 #include "mdns_common.h" |
30 | 29 |
31 static GSList *pending_buddies = NULL; | 30 static GSList *pending_buddies = NULL; |
32 | 31 |
33 typedef struct _dnssd_service_ref_handler { | 32 typedef struct _dnssd_service_ref_handler { |
63 DnsSDServiceRefHandlerData *resolver_query; | 62 DnsSDServiceRefHandlerData *resolver_query; |
64 PurpleAccount *account; | 63 PurpleAccount *account; |
65 BonjourBuddy *bb; | 64 BonjourBuddy *bb; |
66 Win32SvcResolverData *res_data; | 65 Win32SvcResolverData *res_data; |
67 gchar *full_service_name; | 66 gchar *full_service_name; |
68 PurpleDnsQueryData *dns_query; | |
69 } ResolveCallbackArgs; | 67 } ResolveCallbackArgs; |
70 | 68 |
71 | 69 |
72 static gint | 70 static gint |
73 _find_resolver_data(gconstpointer a, gconstpointer b) { | 71 _find_resolver_data(gconstpointer a, gconstpointer b) { |
133 uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, | 131 uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, |
134 uint32_t ttl, void *context) | 132 uint32_t ttl, void *context) |
135 { | 133 { |
136 | 134 |
137 if (errorCode != kDNSServiceErr_NoError) { | 135 if (errorCode != kDNSServiceErr_NoError) { |
138 purple_debug_error("bonjour", "record query - callback error.\n"); | 136 purple_debug_error("bonjour", "record query - callback error (%d).\n", errorCode); |
139 /* TODO: Probably should remove the buddy when this happens */ | 137 /* TODO: Probably should remove the buddy when this happens */ |
140 } else if (flags & kDNSServiceFlagsAdd) { | 138 } else if (flags & kDNSServiceFlagsAdd) { |
141 if (rrtype == kDNSServiceType_TXT) { | 139 if (rrtype == kDNSServiceType_TXT) { |
142 /* New Buddy */ | 140 /* New Buddy */ |
143 BonjourBuddy *bb = (BonjourBuddy*) context; | 141 BonjourBuddy *bb = (BonjourBuddy*) context; |
159 idata->null_query = NULL; | 157 idata->null_query = NULL; |
160 } | 158 } |
161 } | 159 } |
162 } | 160 } |
163 | 161 |
164 static void | 162 static void DNSSD_API |
165 _mdns_resolve_host_callback(GSList *hosts, gpointer data, const char *error_message) | 163 _mdns_resolve_host_callback(DNSServiceRef sdRef, DNSServiceFlags flags, |
164 uint32_t interfaceIndex, DNSServiceErrorType errorCode, | |
165 const char *hostname, const struct sockaddr *address, | |
166 uint32_t ttl, void *context) | |
166 { | 167 { |
167 ResolveCallbackArgs *args = (ResolveCallbackArgs*) data; | 168 ResolveCallbackArgs *args = (ResolveCallbackArgs*) context; |
168 Win32BuddyImplData *idata = args->bb->mdns_impl_data; | 169 Win32BuddyImplData *idata = args->bb->mdns_impl_data; |
169 gboolean delete_buddy = FALSE; | 170 gboolean delete_buddy = FALSE; |
170 PurpleBuddy *pb = NULL; | 171 PurpleBuddy *pb = NULL; |
172 | |
173 purple_input_remove(args->resolver_query->input_handler); | |
174 DNSServiceRefDeallocate(args->resolver_query->sdRef); | |
175 g_free(args->resolver_query); | |
176 args->resolver_query = NULL; | |
171 | 177 |
172 if ((pb = purple_find_buddy(args->account, args->res_data->name))) { | 178 if ((pb = purple_find_buddy(args->account, args->res_data->name))) { |
173 if (pb->proto_data != args->bb) { | 179 if (pb->proto_data != args->bb) { |
174 purple_debug_error("bonjour", "Found purple buddy for %s not matching bonjour buddy record.", | 180 purple_debug_error("bonjour", "Found purple buddy for %s not matching bonjour buddy record.", |
175 args->res_data->name); | 181 args->res_data->name); |
179 } else if (g_slist_find(pending_buddies, args->bb) == NULL) { | 185 } else if (g_slist_find(pending_buddies, args->bb) == NULL) { |
180 purple_debug_error("bonjour", "host resolution - complete, but buddy no longer pending.\n"); | 186 purple_debug_error("bonjour", "host resolution - complete, but buddy no longer pending.\n"); |
181 goto cleanup; | 187 goto cleanup; |
182 } | 188 } |
183 | 189 |
184 if (!hosts || !hosts->data) { | 190 if (errorCode != kDNSServiceErr_NoError) { |
185 purple_debug_error("bonjour", "host resolution - callback error.\n"); | 191 purple_debug_error("bonjour", "host resolution - callback error (%d).\n", errorCode); |
186 delete_buddy = TRUE; | 192 delete_buddy = TRUE; |
187 } else { | 193 } else { |
188 struct sockaddr_in *addr = g_slist_nth_data(hosts, 1); | |
189 DNSServiceErrorType errorCode; | |
190 DNSServiceRef txt_query_sr; | 194 DNSServiceRef txt_query_sr; |
191 | 195 |
192 /* finally, set up the continuous txt record watcher, and add the buddy to purple */ | 196 /* finally, set up the continuous txt record watcher, and add the buddy to purple */ |
193 errorCode = DNSServiceQueryRecord(&txt_query_sr, kDNSServiceFlagsLongLivedQuery, | 197 errorCode = DNSServiceQueryRecord(&txt_query_sr, kDNSServiceFlagsLongLivedQuery, |
194 kDNSServiceInterfaceIndexAny, args->full_service_name, kDNSServiceType_TXT, | 198 kDNSServiceInterfaceIndexAny, args->full_service_name, kDNSServiceType_TXT, |
195 kDNSServiceClass_IN, _mdns_record_query_callback, args->bb); | 199 kDNSServiceClass_IN, _mdns_record_query_callback, args->bb); |
196 if (errorCode == kDNSServiceErr_NoError) { | 200 if (errorCode == kDNSServiceErr_NoError) { |
197 const char *ip = inet_ntoa(addr->sin_addr); | 201 const char *ip = inet_ntoa(((struct sockaddr_in *) address)->sin_addr); |
198 | 202 |
199 purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", args->bb->name, ip, args->bb->port_p2pj); | 203 purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", args->bb->name, ip, args->bb->port_p2pj); |
200 | 204 |
201 args->bb->ips = g_slist_prepend(args->bb->ips, g_strdup(ip)); | 205 args->bb->ips = g_slist_prepend(args->bb->ips, g_strdup(ip)); |
202 args->res_data->ip = args->bb->ips->data; | 206 args->res_data->ip = args->bb->ips->data; |
215 } | 219 } |
216 | 220 |
217 } | 221 } |
218 | 222 |
219 cleanup: | 223 cleanup: |
220 | |
221 /* free the hosts list*/ | |
222 while (hosts != NULL) { | |
223 hosts = g_slist_remove(hosts, hosts->data); | |
224 g_free(hosts->data); | |
225 hosts = g_slist_remove(hosts, hosts->data); | |
226 } | |
227 | 224 |
228 if (delete_buddy) { | 225 if (delete_buddy) { |
229 idata->resolvers = g_slist_remove(idata->resolvers, args->res_data); | 226 idata->resolvers = g_slist_remove(idata->resolvers, args->res_data); |
230 _cleanup_resolver_data(args->res_data); | 227 _cleanup_resolver_data(args->res_data); |
231 | 228 |
257 Win32BuddyImplData *idata = args->bb->mdns_impl_data; | 254 Win32BuddyImplData *idata = args->bb->mdns_impl_data; |
258 | 255 |
259 /* remove the input fd and destroy the service ref */ | 256 /* remove the input fd and destroy the service ref */ |
260 purple_input_remove(args->resolver_query->input_handler); | 257 purple_input_remove(args->resolver_query->input_handler); |
261 DNSServiceRefDeallocate(args->resolver_query->sdRef); | 258 DNSServiceRefDeallocate(args->resolver_query->sdRef); |
259 | |
260 if (errorCode != kDNSServiceErr_NoError) | |
261 purple_debug_error("bonjour", "service resolver - callback error. (%d)\n", errorCode); | |
262 else { | |
263 DNSServiceRef getaddrinfo_sr; | |
264 /* set more arguments, and start the host resolver */ | |
265 errorCode = DNSServiceGetAddrInfo(&getaddrinfo_sr, 0, interfaceIndex, | |
266 kDNSServiceProtocol_IPv4, hosttarget, _mdns_resolve_host_callback, args); | |
267 if (errorCode != kDNSServiceErr_NoError) | |
268 purple_debug_error("bonjour", "service resolver - host resolution failed.\n"); | |
269 else { | |
270 args->resolver_query->sdRef = getaddrinfo_sr; | |
271 args->resolver_query->input_handler = purple_input_add(DNSServiceRefSockFD(getaddrinfo_sr), | |
272 PURPLE_INPUT_READ, _mdns_handle_event, args->resolver_query); | |
273 args->full_service_name = g_strdup(fullname); | |
274 | |
275 /* TODO: Should this be per resolver? */ | |
276 args->bb->port_p2pj = ntohs(port); | |
277 | |
278 /* We don't want to hit the cleanup code */ | |
279 return; | |
280 } | |
281 } | |
282 | |
283 /* If we get this far, clean up */ | |
284 | |
262 g_free(args->resolver_query); | 285 g_free(args->resolver_query); |
263 args->resolver_query = NULL; | 286 args->resolver_query = NULL; |
264 | |
265 if (errorCode != kDNSServiceErr_NoError) | |
266 purple_debug_error("bonjour", "service resolver - callback error.\n"); | |
267 else { | |
268 /* set more arguments, and start the host resolver */ | |
269 | |
270 if ((args->dns_query = | |
271 purple_dnsquery_a(hosttarget, port, _mdns_resolve_host_callback, args)) != NULL) { | |
272 | |
273 args->full_service_name = g_strdup(fullname); | |
274 | |
275 /* TODO: Should this be per resolver? */ | |
276 args->bb->port_p2pj = ntohs(port); | |
277 | |
278 /* We don't want to hit the cleanup code */ | |
279 return; | |
280 } else | |
281 purple_debug_error("bonjour", "service resolver - host resolution failed.\n"); | |
282 } | |
283 | |
284 /* If we get this far, clean up */ | |
285 | 287 |
286 idata->resolvers = g_slist_remove(idata->resolvers, args->res_data); | 288 idata->resolvers = g_slist_remove(idata->resolvers, args->res_data); |
287 _cleanup_resolver_data(args->res_data); | 289 _cleanup_resolver_data(args->res_data); |
288 | 290 |
289 /* If this was the last resolver, remove the buddy */ | 291 /* If this was the last resolver, remove the buddy */ |
332 | 334 |
333 purple_debug_info("bonjour", "Received new record for '%s' on iface %u (%s, %s)\n", | 335 purple_debug_info("bonjour", "Received new record for '%s' on iface %u (%s, %s)\n", |
334 serviceName, interfaceIndex, regtype ? regtype : "", | 336 serviceName, interfaceIndex, regtype ? regtype : "", |
335 replyDomain ? replyDomain : ""); | 337 replyDomain ? replyDomain : ""); |
336 | 338 |
337 resErrorCode = DNSServiceResolve(&resolver_sr, 0, 0, serviceName, regtype, | 339 resErrorCode = DNSServiceResolve(&resolver_sr, 0, interfaceIndex, serviceName, regtype, |
338 replyDomain, _mdns_service_resolve_callback, args); | 340 replyDomain, _mdns_service_resolve_callback, args); |
339 if (resErrorCode == kDNSServiceErr_NoError) { | 341 if (resErrorCode == kDNSServiceErr_NoError) { |
340 GSList *tmp = pending_buddies; | 342 GSList *tmp = pending_buddies; |
341 PurpleBuddy *pb; | 343 PurpleBuddy *pb; |
342 BonjourBuddy* bb = NULL; | 344 BonjourBuddy* bb = NULL; |
481 DNSServiceRef presence_sr; | 483 DNSServiceRef presence_sr; |
482 | 484 |
483 switch (type) { | 485 switch (type) { |
484 case PUBLISH_START: | 486 case PUBLISH_START: |
485 purple_debug_info("bonjour", "Registering presence on port %d\n", data->port_p2pj); | 487 purple_debug_info("bonjour", "Registering presence on port %d\n", data->port_p2pj); |
486 errorCode = DNSServiceRegister(&presence_sr, 0, 0, purple_account_get_username(data->account), LINK_LOCAL_RECORD_NAME, | 488 errorCode = DNSServiceRegister(&presence_sr, kDNSServiceInterfaceIndexAny, |
489 0, purple_account_get_username(data->account), LINK_LOCAL_RECORD_NAME, | |
487 NULL, NULL, htons(data->port_p2pj), TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), | 490 NULL, NULL, htons(data->port_p2pj), TXTRecordGetLength(&dns_data), TXTRecordGetBytesPtr(&dns_data), |
488 _mdns_service_register_callback, NULL); | 491 _mdns_service_register_callback, NULL); |
489 break; | 492 break; |
490 | 493 |
491 case PUBLISH_UPDATE: | 494 case PUBLISH_UPDATE: |
520 Win32SessionImplData *idata = data->mdns_impl_data; | 523 Win32SessionImplData *idata = data->mdns_impl_data; |
521 DNSServiceRef browser_sr; | 524 DNSServiceRef browser_sr; |
522 | 525 |
523 g_return_val_if_fail(idata != NULL, FALSE); | 526 g_return_val_if_fail(idata != NULL, FALSE); |
524 | 527 |
525 errorCode = DNSServiceBrowse(&browser_sr, 0, 0, LINK_LOCAL_RECORD_NAME, NULL, | 528 errorCode = DNSServiceBrowse(&browser_sr, 0, kDNSServiceInterfaceIndexAny, |
526 _mdns_service_browse_callback, data->account); | 529 LINK_LOCAL_RECORD_NAME, NULL,_mdns_service_browse_callback, |
530 data->account); | |
527 if (errorCode == kDNSServiceErr_NoError) { | 531 if (errorCode == kDNSServiceErr_NoError) { |
528 idata->browser_query = g_new(DnsSDServiceRefHandlerData, 1); | 532 idata->browser_query = g_new(DnsSDServiceRefHandlerData, 1); |
529 idata->browser_query->sdRef = browser_sr; | 533 idata->browser_query->sdRef = browser_sr; |
530 idata->browser_query->account = data->account; | 534 idata->browser_query->account = data->account; |
531 idata->browser_query->input_handler = purple_input_add(DNSServiceRefSockFD(browser_sr), | 535 idata->browser_query->input_handler = purple_input_add(DNSServiceRefSockFD(browser_sr), |