Mercurial > pidgin
annotate src/protocols/bonjour/dns_sd.c @ 13909:8264f52a1142
[gaim-migrate @ 16406]
More of sf patch #1490646, from Jonty Wareing & Jono Cole
"The screen name + hostname of the sending user is sent
in the outgoing jabber message, fixing a sporadic
problem with iChat.
The port in use has been fixed to the one described in
the Bonjour specification and can no longer be changed
in the prpl preferences - modifiying this just stops
the client from being able to start a chat.
The option for a buddy icon has been removed for now as
no code actually uses it yet - we plan to change this
in the future.
This update also introduces automatic local port retry
for up to ten attempts if the port is in
use (e.g. if multiple instances of gaim are running)."
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Mon, 03 Jul 2006 00:37:41 +0000 |
parents | b986b6e2441b |
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 } |