Mercurial > pidgin.yaz
annotate src/protocols/bonjour/dns_sd.c @ 13910:6c907830a45f
[gaim-migrate @ 16408]
Get rid of an assertion failure that I hit
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Mon, 03 Jul 2006 01:39:51 +0000 |
parents | 8264f52a1142 |
children |
rev | line source |
---|---|
11477 | 1 /* |
2 * This program is free software; you can redistribute it and/or modify | |
3 * it under the terms of the GNU General Public License as published by | |
4 * the Free Software Foundation; either version 2 of the License, or | |
5 * (at your option) any later version. | |
6 * | |
7 * This program is distributed in the hope that it will be useful, | |
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
10 * GNU Library General Public License for more details. | |
11 * | |
12 * You should have received a copy of the GNU General Public License | |
13 * along with this program; if not, write to the Free Software | |
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
15 */ | |
16 | |
17 #include <string.h> | |
18 | |
19 #include "dns_sd.h" | |
20 #include "bonjour.h" | |
21 #include "buddy.h" | |
22 #include "debug.h" | |
23 | |
11829
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
24 /* Private functions */ |
11477 | 25 |
11539 | 26 static sw_result HOWL_API |
27 _publish_reply(sw_discovery discovery, sw_discovery_oid oid, | |
28 sw_discovery_publish_status status, sw_opaque extra) | |
11477 | 29 { |
11539 | 30 gaim_debug_warning("bonjour", "_publish_reply --> Start\n"); |
31 | |
11829
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
32 /* Check the answer from the mDNS daemon */ |
11539 | 33 switch (status) |
34 { | |
11477 | 35 case SW_DISCOVERY_PUBLISH_STARTED : |
36 gaim_debug_info("bonjour", "_publish_reply --> Service started\n"); | |
37 break; | |
38 case SW_DISCOVERY_PUBLISH_STOPPED : | |
39 gaim_debug_info("bonjour", "_publish_reply --> Service stopped\n"); | |
40 break; | |
41 case SW_DISCOVERY_PUBLISH_NAME_COLLISION : | |
42 gaim_debug_info("bonjour", "_publish_reply --> Name collision\n"); | |
43 break; | |
44 case SW_DISCOVERY_PUBLISH_INVALID : | |
45 gaim_debug_info("bonjour", "_publish_reply --> Service invalid\n"); | |
46 break; | |
47 } | |
11539 | 48 |
11477 | 49 return SW_OKAY; |
50 } | |
51 | |
11539 | 52 static sw_result HOWL_API |
53 _resolve_reply(sw_discovery discovery, sw_discovery_oid oid, | |
54 sw_uint32 interface_index, sw_const_string name, | |
55 sw_const_string type, sw_const_string domain, | |
56 sw_ipv4_address address, sw_port port, | |
57 sw_octets text_record, sw_ulong text_record_len, | |
58 sw_opaque extra) | |
11477 | 59 { |
11539 | 60 BonjourBuddy *buddy; |
61 GaimAccount *account = (GaimAccount*)extra; | |
62 gchar *txtvers = NULL; | |
63 gchar *version = NULL; | |
64 gchar *first = NULL; | |
65 gchar *phsh = NULL; | |
66 gchar *status = NULL; | |
67 gchar *email = NULL; | |
68 gchar *last = NULL; | |
69 gchar *jid = NULL; | |
70 gchar *AIM = NULL; | |
71 gchar *vc = NULL; | |
72 gchar *msg = NULL; | |
11477 | 73 gint address_length = 16; |
11539 | 74 gchar *ip = NULL; |
11477 | 75 sw_text_record_iterator iterator; |
11498 | 76 char key[SW_TEXT_RECORD_MAX_LEN]; |
77 char value[SW_TEXT_RECORD_MAX_LEN]; | |
11477 | 78 sw_uint32 value_length; |
79 | |
80 sw_discovery_cancel(discovery, oid); | |
11539 | 81 |
11829
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
82 /* Get the ip as a string */ |
11477 | 83 ip = malloc(address_length); |
84 sw_ipv4_address_name(address, ip, address_length); | |
85 | |
11829
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
86 /* Obtain the parameters from the text_record */ |
11539 | 87 if ((text_record_len > 0) && (text_record) && (*text_record != '\0')) |
88 { | |
11477 | 89 sw_text_record_iterator_init(&iterator, text_record, text_record_len); |
11539 | 90 while (sw_text_record_iterator_next(iterator, key, (sw_octet *)value, &value_length) == SW_OKAY) |
91 { | |
11829
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
92 /* Compare the keys with the possible ones and save them on */ |
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
93 /* the appropiate place of the buddy_list */ |
11477 | 94 if (strcmp(key, "txtvers") == 0) { |
95 txtvers = g_strdup(value); | |
96 } else if (strcmp(key, "version") == 0) { | |
97 version = g_strdup(value); | |
98 } else if (strcmp(key, "1st") == 0) { | |
99 first = g_strdup(value); | |
100 } else if (strcmp(key, "status") == 0) { | |
101 status = g_strdup(value); | |
102 } else if (strcmp(key, "email") == 0) { | |
103 email = g_strdup(value); | |
104 } else if (strcmp(key, "last") == 0) { | |
105 last = g_strdup(value); | |
106 } else if (strcmp(key, "jid") == 0) { | |
107 jid = g_strdup(value); | |
108 } else if (strcmp(key, "AIM") == 0) { | |
109 AIM = g_strdup(value); | |
110 } else if (strcmp(key, "vc") == 0) { | |
111 vc = g_strdup(value); | |
112 } else if (strcmp(key, "phsh") == 0) { | |
113 phsh = g_strdup(value); | |
114 } else if (strcmp(key, "msg") == 0) { | |
115 msg = g_strdup(value); | |
116 } | |
117 } | |
118 } | |
119 | |
11829
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
120 /* Put the parameters of the text_record in a buddy and add the buddy to */ |
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
121 /* the buddy list */ |
13909 | 122 buddy = bonjour_buddy_new(name, first, port, phsh, |
11539 | 123 status, email, last, jid, AIM, vc, ip, msg); |
124 | |
125 if (bonjour_buddy_check(buddy) == FALSE) | |
126 { | |
13649 | 127 bonjour_buddy_delete(buddy); |
11477 | 128 return SW_DISCOVERY_E_UNKNOWN; |
129 } | |
11539 | 130 |
11496 | 131 /* Add or update the buddy in our buddy list */ |
132 bonjour_buddy_add_to_gaim(account, buddy); | |
11539 | 133 |
11829
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
134 /* Free all the temporal strings */ |
11477 | 135 g_free(txtvers); |
136 g_free(version); | |
137 g_free(first); | |
138 g_free(last); | |
139 g_free(status); | |
140 g_free(email); | |
141 g_free(jid); | |
142 g_free(AIM); | |
143 g_free(vc); | |
144 g_free(phsh); | |
145 g_free(msg); | |
11539 | 146 |
11477 | 147 return SW_OKAY; |
148 } | |
149 | |
11539 | 150 static sw_result HOWL_API |
151 _browser_reply(sw_discovery discovery, sw_discovery_oid oid, | |
152 sw_discovery_browse_status status, | |
153 sw_uint32 interface_index, sw_const_string name, | |
154 sw_const_string type, sw_const_string domain, | |
155 sw_opaque_t extra) | |
11477 | 156 { |
157 sw_discovery_resolve_id rid; | |
11539 | 158 GaimAccount *account = (GaimAccount*)extra; |
159 GaimBuddy *gb = NULL; | |
160 | |
161 switch (status) | |
162 { | |
11477 | 163 case SW_DISCOVERY_BROWSE_INVALID: |
164 gaim_debug_warning("bonjour", "_browser_reply --> Invalid\n"); | |
165 break; | |
166 case SW_DISCOVERY_BROWSE_RELEASE: | |
167 gaim_debug_warning("bonjour", "_browser_reply --> Release\n"); | |
168 break; | |
169 case SW_DISCOVERY_BROWSE_ADD_DOMAIN: | |
170 gaim_debug_warning("bonjour", "_browser_reply --> Add domain\n"); | |
171 break; | |
172 case SW_DISCOVERY_BROWSE_ADD_DEFAULT_DOMAIN: | |
173 gaim_debug_warning("bonjour", "_browser_reply --> Add default domain\n"); | |
174 break; | |
175 case SW_DISCOVERY_BROWSE_REMOVE_DOMAIN: | |
176 gaim_debug_warning("bonjour", "_browser_reply --> Remove domain\n"); | |
177 break; | |
178 case SW_DISCOVERY_BROWSE_ADD_SERVICE: | |
13909 | 179 /* A new peer has joined the network and uses iChat bonjour */ |
11477 | 180 gaim_debug_info("bonjour", "_browser_reply --> Add service\n"); |
11539 | 181 if (g_ascii_strcasecmp(name, account->username) != 0) |
182 { | |
183 if (sw_discovery_resolve(discovery, interface_index, name, type, | |
184 domain, _resolve_reply, extra, &rid) != SW_OKAY) | |
185 { | |
11477 | 186 gaim_debug_warning("bonjour", "_browser_reply --> Cannot send resolve\n"); |
187 } | |
188 } | |
189 break; | |
190 case SW_DISCOVERY_BROWSE_REMOVE_SERVICE: | |
191 gaim_debug_info("bonjour", "_browser_reply --> Remove service\n"); | |
192 gb = gaim_find_buddy((GaimAccount*)extra, name); | |
11539 | 193 if (gb != NULL) |
194 { | |
11477 | 195 bonjour_buddy_delete(gb->proto_data); |
196 gaim_blist_remove_buddy(gb); | |
197 } | |
198 break; | |
199 case SW_DISCOVERY_BROWSE_RESOLVED: | |
200 gaim_debug_info("bonjour", "_browse_reply --> Resolved\n"); | |
201 break; | |
202 default: | |
203 break; | |
204 } | |
11539 | 205 |
11477 | 206 return SW_OKAY; |
207 } | |
208 | |
11677 | 209 static int |
11539 | 210 _dns_sd_publish(BonjourDnsSd *data, PublishType type) |
11477 | 211 { |
212 sw_text_record dns_data; | |
11773
92cf092f194e
[gaim-migrate @ 14064]
Gary Kramlich <grim@reaperworld.com>
parents:
11678
diff
changeset
|
213 sw_result publish_result = SW_OKAY; |
13909 | 214 char portstring[6]; |
11477 | 215 |
11829
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
216 /* Fill the data for the service */ |
11539 | 217 if (sw_text_record_init(&dns_data) != SW_OKAY) |
218 { | |
11927 | 219 gaim_debug_error("bonjour", "Unable to initialize the data for the mDNS.\n"); |
11477 | 220 return -1; |
221 } | |
222 | |
13909 | 223 /* Convert the port to a string */ |
224 snprintf(portstring, sizeof(portstring), "%d", data->port_p2pj); | |
225 | |
226 /* Publish standard records */ | |
11477 | 227 sw_text_record_add_key_and_string_value(dns_data, "txtvers", data->txtvers); |
228 sw_text_record_add_key_and_string_value(dns_data, "version", data->version); | |
229 sw_text_record_add_key_and_string_value(dns_data, "1st", data->first); | |
230 sw_text_record_add_key_and_string_value(dns_data, "last", data->last); | |
13909 | 231 sw_text_record_add_key_and_string_value(dns_data, "port.p2pj", portstring); |
11477 | 232 sw_text_record_add_key_and_string_value(dns_data, "phsh", data->phsh); |
233 sw_text_record_add_key_and_string_value(dns_data, "status", data->status); | |
234 sw_text_record_add_key_and_string_value(dns_data, "vc", data->vc); | |
13906 | 235 |
13909 | 236 /* Publish extra records */ |
13906 | 237 if ((data->email != NULL) && (*data->email != '\0')) |
238 sw_text_record_add_key_and_string_value(dns_data, "email", data->email); | |
239 | |
240 if ((data->jid != NULL) && (*data->jid != '\0')) | |
241 sw_text_record_add_key_and_string_value(dns_data, "jid", data->jid); | |
242 | |
243 if ((data->AIM != NULL) && (*data->AIM != '\0')) | |
244 sw_text_record_add_key_and_string_value(dns_data, "AIM", data->AIM); | |
245 | |
246 if ((data->msg != NULL) && (*data->msg != '\0')) | |
247 sw_text_record_add_key_and_string_value(dns_data, "msg", data->msg); | |
11477 | 248 |
11829
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
249 /* Publish the service */ |
11539 | 250 switch (type) |
251 { | |
11477 | 252 case PUBLISH_START: |
12104 | 253 publish_result = sw_discovery_publish(data->session, 0, data->name, ICHAT_SERVICE, NULL, |
11539 | 254 NULL, data->port_p2pj, sw_text_record_bytes(dns_data), sw_text_record_len(dns_data), |
12104 | 255 _publish_reply, NULL, &data->session_id); |
11477 | 256 break; |
257 case PUBLISH_UPDATE: | |
12104 | 258 publish_result = sw_discovery_publish_update(data->session, data->session_id, |
11477 | 259 sw_text_record_bytes(dns_data), sw_text_record_len(dns_data)); |
260 break; | |
261 } | |
11539 | 262 if (publish_result != SW_OKAY) |
263 { | |
13909 | 264 gaim_debug_error("bonjour", "Unable to publish or change the status of the _presence._tcp service.\n"); |
11477 | 265 return -1; |
266 } | |
267 | |
11829
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
268 /* Free the memory used by temp data */ |
11477 | 269 sw_text_record_fina(dns_data); |
270 | |
271 return 0; | |
272 } | |
273 | |
11678 | 274 static void |
275 _dns_sd_handle_packets(gpointer data, gint source, GaimInputCondition condition) | |
11477 | 276 { |
12104 | 277 sw_discovery_read_socket((sw_discovery)data); |
11477 | 278 } |
279 | |
11829
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
280 /* End private functions */ |
11477 | 281 |
282 /** | |
283 * Allocate space for the dns-sd data. | |
284 */ | |
11539 | 285 BonjourDnsSd * |
286 bonjour_dns_sd_new() | |
11477 | 287 { |
12035
52eaf0f0db4c
[gaim-migrate @ 14328]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11927
diff
changeset
|
288 BonjourDnsSd *data = g_new0(BonjourDnsSd, 1); |
11539 | 289 |
11477 | 290 return data; |
291 } | |
292 | |
293 /** | |
294 * Deallocate the space of the dns-sd data. | |
295 */ | |
11539 | 296 void |
297 bonjour_dns_sd_free(BonjourDnsSd *data) | |
11477 | 298 { |
11496 | 299 g_free(data->first); |
300 g_free(data->last); | |
301 g_free(data->email); | |
11477 | 302 g_free(data); |
303 } | |
304 | |
305 /** | |
306 * Send a new dns-sd packet updating our status. | |
307 */ | |
11539 | 308 void |
309 bonjour_dns_sd_send_status(BonjourDnsSd *data, const char *status, const char *status_message) | |
11477 | 310 { |
11496 | 311 g_free(data->status); |
312 g_free(data->msg); | |
11477 | 313 |
314 data->status = g_strdup(status); | |
315 data->msg = g_strdup(status_message); | |
316 | |
11829
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
317 /* Update our text record with the new status */ |
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
318 _dns_sd_publish(data, PUBLISH_UPDATE); /* <--We must control the errors */ |
11477 | 319 } |
320 | |
321 /** | |
11496 | 322 * Advertise our presence within the dns-sd daemon and start browsing |
323 * for other bonjour peers. | |
11477 | 324 */ |
11927 | 325 gboolean |
11539 | 326 bonjour_dns_sd_start(BonjourDnsSd *data) |
327 { | |
11678 | 328 GaimAccount *account; |
329 GaimConnection *gc; | |
11477 | 330 gint dns_sd_socket; |
331 sw_discovery_oid session_id; | |
11539 | 332 |
11678 | 333 account = data->account; |
334 gc = gaim_account_get_connection(account); | |
335 | |
11927 | 336 /* Initialize the dns-sd data and session */ |
12104 | 337 if (sw_discovery_init(&data->session) != SW_OKAY) |
11539 | 338 { |
11927 | 339 gaim_debug_error("bonjour", "Unable to initialize an mDNS session.\n"); |
13063 | 340 |
341 /* In Avahi, sw_discovery_init frees data->session but doesn't clear it */ | |
342 data->session = NULL; | |
343 | |
11927 | 344 return FALSE; |
11477 | 345 } |
11539 | 346 |
11829
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
347 /* Publish our bonjour IM client at the mDNS daemon */ |
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
348 _dns_sd_publish(data, PUBLISH_START); /* <--We must control the errors */ |
11539 | 349 |
11829
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
350 /* Advise the daemon that we are waiting for connections */ |
12104 | 351 if (sw_discovery_browse(data->session, 0, ICHAT_SERVICE, NULL, _browser_reply, |
11539 | 352 data->account, &session_id) != SW_OKAY) |
353 { | |
11477 | 354 gaim_debug_error("bonjour", "Unable to get service."); |
11927 | 355 return FALSE; |
11477 | 356 } |
11539 | 357 |
11829
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
358 /* Get the socket that communicates with the mDNS daemon and bind it to a */ |
4669e7461968
[gaim-migrate @ 14120]
Richard Laager <rlaager@wiktel.com>
parents:
11773
diff
changeset
|
359 /* callback that will handle the dns_sd packets */ |
12104 | 360 dns_sd_socket = sw_discovery_socket(data->session); |
11678 | 361 gc->inpa = gaim_input_add(dns_sd_socket, GAIM_INPUT_READ, |
362 _dns_sd_handle_packets, data->session); | |
11927 | 363 |
364 return TRUE; | |
11477 | 365 } |
366 | |
367 /** | |
368 * Unregister the "_presence._tcp" service at the mDNS daemon. | |
369 */ | |
11927 | 370 void |
11539 | 371 bonjour_dns_sd_stop(BonjourDnsSd *data) |
11477 | 372 { |
11678 | 373 GaimAccount *account; |
374 GaimConnection *gc; | |
375 | |
11927 | 376 if (data->session == NULL) |
377 return; | |
378 | |
12104 | 379 sw_discovery_cancel(data->session, data->session_id); |
11539 | 380 |
11678 | 381 account = data->account; |
382 gc = gaim_account_get_connection(account); | |
383 gaim_input_remove(gc->inpa); | |
12093 | 384 |
385 g_free(data->session); | |
386 data->session = NULL; | |
11477 | 387 } |