| 77 uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullname, |
77 uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *fullname, |
| 78 uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, |
78 uint16_t rrtype, uint16_t rrclass, uint16_t rdlen, const void *rdata, |
| 79 uint32_t ttl, void *context) |
79 uint32_t ttl, void *context) |
| 80 { |
80 { |
| 81 |
81 |
| 82 if (kDNSServiceErr_NoError != errorCode) |
82 if (kDNSServiceErr_NoError != errorCode) { |
| 83 purple_debug_error("bonjour", "record query - callback error.\n"); |
83 purple_debug_error("bonjour", "record query - callback error.\n"); |
| 84 else if (flags & kDNSServiceFlagsAdd) |
84 /* TODO: Probably should remove the buddy when this happens */ |
| 85 { |
85 } else if (flags & kDNSServiceFlagsAdd) { |
| 86 if (rrtype == kDNSServiceType_TXT) { |
86 if (rrtype == kDNSServiceType_TXT) { |
| 87 /* New Buddy */ |
87 /* New Buddy */ |
| 88 BonjourBuddy *buddy = (BonjourBuddy*) context; |
88 BonjourBuddy *bb = (BonjourBuddy*) context; |
| 89 _mdns_parse_text_record(buddy, rdata, rdlen); |
89 _mdns_parse_text_record(bb, rdata, rdlen); |
| 90 bonjour_buddy_add_to_purple(buddy); |
90 bonjour_buddy_add_to_purple(bb, NULL); |
| 91 } else if (rrtype == kDNSServiceType_NULL) { |
91 } else if (rrtype == kDNSServiceType_NULL) { |
| 92 /* Buddy Icon response */ |
92 /* Buddy Icon response */ |
| 93 BonjourBuddy *buddy = (BonjourBuddy*) context; |
93 BonjourBuddy *bb = (BonjourBuddy*) context; |
| 94 Win32BuddyImplData *idata = buddy->mdns_impl_data; |
94 Win32BuddyImplData *idata = bb->mdns_impl_data; |
| 95 |
95 |
| 96 g_return_if_fail(idata != NULL); |
96 g_return_if_fail(idata != NULL); |
| 97 |
97 |
| 98 bonjour_buddy_got_buddy_icon(buddy, rdata, rdlen); |
98 bonjour_buddy_got_buddy_icon(bb, rdata, rdlen); |
| 99 |
99 |
| 100 /* We've got what we need; stop listening */ |
100 /* We've got what we need; stop listening */ |
| 101 purple_input_remove(idata->null_query_handler); |
101 purple_input_remove(idata->null_query_handler); |
| 102 idata->null_query_handler = 0; |
102 idata->null_query_handler = 0; |
| 103 DNSServiceRefDeallocate(idata->null_query); |
103 DNSServiceRefDeallocate(idata->null_query); |
| 108 |
108 |
| 109 static void |
109 static void |
| 110 _mdns_resolve_host_callback(GSList *hosts, gpointer data, const char *error_message) |
110 _mdns_resolve_host_callback(GSList *hosts, gpointer data, const char *error_message) |
| 111 { |
111 { |
| 112 ResolveCallbackArgs* args = (ResolveCallbackArgs*)data; |
112 ResolveCallbackArgs* args = (ResolveCallbackArgs*)data; |
| 113 |
113 BonjourBuddy* bb = args->buddy; |
| 114 if (!hosts || !hosts->data) |
114 |
| |
115 if (!hosts || !hosts->data) { |
| 115 purple_debug_error("bonjour", "host resolution - callback error.\n"); |
116 purple_debug_error("bonjour", "host resolution - callback error.\n"); |
| 116 else { |
117 bonjour_buddy_delete(bb); |
| |
118 } else { |
| 117 struct sockaddr_in *addr = (struct sockaddr_in*)g_slist_nth_data(hosts, 1); |
119 struct sockaddr_in *addr = (struct sockaddr_in*)g_slist_nth_data(hosts, 1); |
| 118 BonjourBuddy* buddy = args->buddy; |
120 Win32BuddyImplData *idata = bb->mdns_impl_data; |
| 119 Win32BuddyImplData *idata = buddy->mdns_impl_data; |
|
| 120 |
121 |
| 121 g_return_if_fail(idata != NULL); |
122 g_return_if_fail(idata != NULL); |
| 122 |
123 |
| 123 buddy->ip = g_strdup(inet_ntoa(addr->sin_addr)); |
124 g_free(bb->ip); |
| |
125 bb->ip = g_strdup(inet_ntoa(addr->sin_addr)); |
| 124 |
126 |
| 125 /* finally, set up the continuous txt record watcher, and add the buddy to purple */ |
127 /* finally, set up the continuous txt record watcher, and add the buddy to purple */ |
| 126 |
128 |
| 127 if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&idata->txt_query, kDNSServiceFlagsLongLivedQuery, |
129 if (kDNSServiceErr_NoError == DNSServiceQueryRecord(&idata->txt_query, kDNSServiceFlagsLongLivedQuery, |
| 128 kDNSServiceInterfaceIndexAny, args->full_service_name, kDNSServiceType_TXT, |
130 kDNSServiceInterfaceIndexAny, args->full_service_name, kDNSServiceType_TXT, |
| 129 kDNSServiceClass_IN, _mdns_record_query_callback, buddy)) { |
131 kDNSServiceClass_IN, _mdns_record_query_callback, bb)) { |
| 130 |
132 |
| 131 purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", buddy->name, buddy->ip, buddy->port_p2pj); |
133 purple_debug_info("bonjour", "Found buddy %s at %s:%d\n", bb->name, bb->ip, bb->port_p2pj); |
| 132 |
134 |
| 133 idata->txt_query_handler = purple_input_add(DNSServiceRefSockFD(idata->txt_query), |
135 idata->txt_query_handler = purple_input_add(DNSServiceRefSockFD(idata->txt_query), |
| 134 PURPLE_INPUT_READ, _mdns_handle_event, idata->txt_query); |
136 PURPLE_INPUT_READ, _mdns_handle_event, idata->txt_query); |
| 135 |
137 |
| 136 bonjour_buddy_add_to_purple(buddy); |
138 bonjour_buddy_add_to_purple(bb, NULL); |
| 137 } else |
139 } else |
| 138 bonjour_buddy_delete(buddy); |
140 bonjour_buddy_delete(bb); |
| 139 |
141 |
| 140 } |
142 } |
| 141 |
143 |
| 142 /* free the hosts list*/ |
144 /* free the hosts list*/ |
| 143 g_slist_free(hosts); |
145 g_slist_free(hosts); |
| 200 static void DNSSD_API |
202 static void DNSSD_API |
| 201 _mdns_service_browse_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, |
203 _mdns_service_browse_callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, |
| 202 DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context) |
204 DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context) |
| 203 { |
205 { |
| 204 PurpleAccount *account = (PurpleAccount*)context; |
206 PurpleAccount *account = (PurpleAccount*)context; |
| 205 PurpleBuddy *gb = NULL; |
207 PurpleBuddy *pb = NULL; |
| 206 |
208 |
| 207 if (kDNSServiceErr_NoError != errorCode) |
209 if (kDNSServiceErr_NoError != errorCode) |
| 208 purple_debug_error("bonjour", "service browser - callback error"); |
210 purple_debug_error("bonjour", "service browser - callback error"); |
| 209 else if (flags & kDNSServiceFlagsAdd) { |
211 else if (flags & kDNSServiceFlagsAdd) { |
| 210 /* A presence service instance has been discovered... check it isn't us! */ |
212 /* A presence service instance has been discovered... check it isn't us! */ |
| 211 if (g_ascii_strcasecmp(serviceName, account->username) != 0) { |
213 if (purple_utf8_strcasecmp(serviceName, account->username) != 0) { |
| 212 /* OK, lets go ahead and resolve it to add to the buddy list */ |
214 /* OK, lets go ahead and resolve it to add to the buddy list */ |
| 213 ResolveCallbackArgs *args = g_new0(ResolveCallbackArgs, 1); |
215 ResolveCallbackArgs *args = g_new0(ResolveCallbackArgs, 1); |
| 214 args->buddy = bonjour_buddy_new(serviceName, account); |
216 args->buddy = bonjour_buddy_new(serviceName, account); |
| 215 |
217 |
| 216 if (kDNSServiceErr_NoError != DNSServiceResolve(&args->resolver, 0, 0, serviceName, regtype, replyDomain, _mdns_service_resolve_callback, args)) { |
218 if (kDNSServiceErr_NoError != DNSServiceResolve(&args->resolver, 0, 0, serviceName, regtype, |
| |
219 replyDomain, _mdns_service_resolve_callback, args)) { |
| 217 bonjour_buddy_delete(args->buddy); |
220 bonjour_buddy_delete(args->buddy); |
| 218 g_free(args); |
221 g_free(args); |
| 219 purple_debug_error("bonjour", "service browser - failed to resolve service.\n"); |
222 purple_debug_error("bonjour", "service browser - failed to resolve service.\n"); |
| 220 } else { |
223 } else { |
| 221 /* get a file descriptor for this service ref, and add it to the input list */ |
224 /* get a file descriptor for this service ref, and add it to the input list */ |
| 224 } |
227 } |
| 225 } |
228 } |
| 226 } else { |
229 } else { |
| 227 /* A peer has sent a goodbye packet, remove them from the buddy list */ |
230 /* A peer has sent a goodbye packet, remove them from the buddy list */ |
| 228 purple_debug_info("bonjour", "service browser - remove notification\n"); |
231 purple_debug_info("bonjour", "service browser - remove notification\n"); |
| 229 gb = purple_find_buddy(account, serviceName); |
232 pb = purple_find_buddy(account, serviceName); |
| 230 if (gb != NULL) { |
233 if (pb != NULL) |
| 231 bonjour_buddy_delete(gb->proto_data); |
234 purple_blist_remove_buddy(pb); |
| 232 purple_blist_remove_buddy(gb); |
|
| 233 } |
|
| 234 } |
235 } |
| 235 } |
236 } |
| 236 |
237 |
| 237 /**************************** |
238 /**************************** |
| 238 * mdns_interface functions * |
239 * mdns_interface functions * |