Mercurial > pidgin
comparison libpurple/protocols/bonjour/mdns_howl.c @ 17495:d7b50cac1c7a
This is a patch from Chris Davies to make Bonjour work on Windows using the Apple Bonjour framework. It turns out that the actual DNS-SD library is (3 clause) BSD licensed, so we can use it.
There are a few changes by me, mainly to fix the howl implementation.
Fixes #1117 .
There appear to be a few bugs, but I believe that they were also present previously. I'm hoping to do some more tweaking before the next release.
The howl implementation will eventually be supersceded by a native avahi implementation, so I opted for a somewhat dirty hack to enable it instead of doing something with config.h.
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Tue, 05 Jun 2007 03:38:22 +0000 |
parents | |
children | c96b085ddf5c |
comparison
equal
deleted
inserted
replaced
17488:7e856734b712 | 17495:d7b50cac1c7a |
---|---|
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 "mdns_howl.h" | |
18 | |
19 #include "debug.h" | |
20 #include "buddy.h" | |
21 | |
22 sw_result HOWL_API | |
23 _publish_reply(sw_discovery discovery, sw_discovery_oid oid, | |
24 sw_discovery_publish_status status, sw_opaque extra) | |
25 { | |
26 purple_debug_warning("bonjour", "_publish_reply --> Start\n"); | |
27 | |
28 /* Check the answer from the mDNS daemon */ | |
29 switch (status) | |
30 { | |
31 case SW_DISCOVERY_PUBLISH_STARTED : | |
32 purple_debug_info("bonjour", "_publish_reply --> Service started\n"); | |
33 break; | |
34 case SW_DISCOVERY_PUBLISH_STOPPED : | |
35 purple_debug_info("bonjour", "_publish_reply --> Service stopped\n"); | |
36 break; | |
37 case SW_DISCOVERY_PUBLISH_NAME_COLLISION : | |
38 purple_debug_info("bonjour", "_publish_reply --> Name collision\n"); | |
39 break; | |
40 case SW_DISCOVERY_PUBLISH_INVALID : | |
41 purple_debug_info("bonjour", "_publish_reply --> Service invalid\n"); | |
42 break; | |
43 } | |
44 | |
45 return SW_OKAY; | |
46 } | |
47 | |
48 sw_result HOWL_API | |
49 _resolve_reply(sw_discovery discovery, sw_discovery_oid oid, | |
50 sw_uint32 interface_index, sw_const_string name, | |
51 sw_const_string type, sw_const_string domain, | |
52 sw_ipv4_address address, sw_port port, | |
53 sw_octets text_record, sw_ulong text_record_len, | |
54 sw_opaque extra) | |
55 { | |
56 BonjourBuddy *buddy; | |
57 PurpleAccount *account = (PurpleAccount*)extra; | |
58 /*gchar *txtvers = NULL;*/ | |
59 /*gchar *version = NULL;*/ | |
60 gint address_length = 16; | |
61 sw_text_record_iterator iterator; | |
62 char key[SW_TEXT_RECORD_MAX_LEN]; | |
63 char value[SW_TEXT_RECORD_MAX_LEN]; | |
64 sw_uint32 value_length; | |
65 | |
66 sw_discovery_cancel(discovery, oid); | |
67 | |
68 /* create a buddy record */ | |
69 buddy = bonjour_buddy_new(name, account); | |
70 | |
71 /* Get the ip as a string */ | |
72 buddy->ip = g_malloc(address_length); | |
73 sw_ipv4_address_name(address, buddy->ip, address_length); | |
74 | |
75 buddy->port_p2pj = port; | |
76 | |
77 /* Obtain the parameters from the text_record */ | |
78 if ((text_record_len > 0) && (text_record) && (*text_record != '\0')) | |
79 { | |
80 sw_text_record_iterator_init(&iterator, text_record, text_record_len); | |
81 while (sw_text_record_iterator_next(iterator, key, (sw_octet *)value, &value_length) == SW_OKAY) | |
82 { | |
83 /* Compare the keys with the possible ones and save them on */ | |
84 /* the appropiate place of the buddy_list */ | |
85 if (strcmp(key, "txtvers") == 0) { | |
86 /*txtvers = g_strdup(value);*/ | |
87 } else if (strcmp(key, "version") == 0) { | |
88 /*version = g_strdup(value);*/ | |
89 } else if (strcmp(key, "1st") == 0) { | |
90 g_free(buddy->first); | |
91 buddy->first = g_strdup(value); | |
92 } else if (strcmp(key, "status") == 0) { | |
93 g_free(buddy->status); | |
94 buddy->status = g_strdup(value); | |
95 } else if (strcmp(key, "email") == 0) { | |
96 g_free(buddy->email); | |
97 buddy->email = g_strdup(value); | |
98 } else if (strcmp(key, "last") == 0) { | |
99 g_free(buddy->last); | |
100 buddy->last = g_strdup(value); | |
101 } else if (strcmp(key, "jid") == 0) { | |
102 g_free(buddy->jid); | |
103 buddy->jid = g_strdup(value); | |
104 } else if (strcmp(key, "AIM") == 0) { | |
105 g_free(buddy->AIM); | |
106 buddy->AIM = g_strdup(value); | |
107 } else if (strcmp(key, "vc") == 0) { | |
108 g_free(buddy->vc); | |
109 buddy->vc = g_strdup(value); | |
110 } else if (strcmp(key, "phsh") == 0) { | |
111 g_free(buddy->phsh); | |
112 buddy->phsh = g_strdup(value); | |
113 } else if (strcmp(key, "msg") == 0) { | |
114 g_free(buddy->msg); | |
115 buddy->msg = g_strdup(value); | |
116 } | |
117 } | |
118 } | |
119 | |
120 if (!bonjour_buddy_check(buddy)) | |
121 { | |
122 bonjour_buddy_delete(buddy); | |
123 return SW_DISCOVERY_E_UNKNOWN; | |
124 } | |
125 | |
126 /* Add or update the buddy in our buddy list */ | |
127 bonjour_buddy_add_to_purple(buddy); | |
128 | |
129 /* Free all the temporal strings */ | |
130 /*g_free(txtvers);*/ | |
131 /*g_free(version);*/ | |
132 | |
133 return SW_OKAY; | |
134 } | |
135 | |
136 sw_result HOWL_API | |
137 _browser_reply(sw_discovery discovery, sw_discovery_oid oid, | |
138 sw_discovery_browse_status status, | |
139 sw_uint32 interface_index, sw_const_string name, | |
140 sw_const_string type, sw_const_string domain, | |
141 sw_opaque_t extra) | |
142 { | |
143 sw_discovery_resolve_id rid; | |
144 PurpleAccount *account = (PurpleAccount*)extra; | |
145 PurpleBuddy *gb = NULL; | |
146 | |
147 switch (status) | |
148 { | |
149 case SW_DISCOVERY_BROWSE_INVALID: | |
150 purple_debug_warning("bonjour", "_browser_reply --> Invalid\n"); | |
151 break; | |
152 case SW_DISCOVERY_BROWSE_RELEASE: | |
153 purple_debug_warning("bonjour", "_browser_reply --> Release\n"); | |
154 break; | |
155 case SW_DISCOVERY_BROWSE_ADD_DOMAIN: | |
156 purple_debug_warning("bonjour", "_browser_reply --> Add domain\n"); | |
157 break; | |
158 case SW_DISCOVERY_BROWSE_ADD_DEFAULT_DOMAIN: | |
159 purple_debug_warning("bonjour", "_browser_reply --> Add default domain\n"); | |
160 break; | |
161 case SW_DISCOVERY_BROWSE_REMOVE_DOMAIN: | |
162 purple_debug_warning("bonjour", "_browser_reply --> Remove domain\n"); | |
163 break; | |
164 case SW_DISCOVERY_BROWSE_ADD_SERVICE: | |
165 /* A new peer has joined the network and uses iChat bonjour */ | |
166 purple_debug_info("bonjour", "_browser_reply --> Add service\n"); | |
167 if (g_ascii_strcasecmp(name, account->username) != 0) | |
168 { | |
169 if (sw_discovery_resolve(discovery, interface_index, name, type, | |
170 domain, _resolve_reply, extra, &rid) != SW_OKAY) | |
171 { | |
172 purple_debug_warning("bonjour", "_browser_reply --> Cannot send resolve\n"); | |
173 } | |
174 } | |
175 break; | |
176 case SW_DISCOVERY_BROWSE_REMOVE_SERVICE: | |
177 purple_debug_info("bonjour", "_browser_reply --> Remove service\n"); | |
178 gb = purple_find_buddy((PurpleAccount*)extra, name); | |
179 if (gb != NULL) | |
180 { | |
181 bonjour_buddy_delete(gb->proto_data); | |
182 purple_blist_remove_buddy(gb); | |
183 } | |
184 break; | |
185 case SW_DISCOVERY_BROWSE_RESOLVED: | |
186 purple_debug_info("bonjour", "_browse_reply --> Resolved\n"); | |
187 break; | |
188 default: | |
189 break; | |
190 } | |
191 | |
192 return SW_OKAY; | |
193 } | |
194 | |
195 int | |
196 _mdns_publish(BonjourDnsSd *data, PublishType type) | |
197 { | |
198 sw_text_record dns_data; | |
199 sw_result publish_result = SW_OKAY; | |
200 char portstring[6]; | |
201 | |
202 /* Fill the data for the service */ | |
203 if (sw_text_record_init(&dns_data) != SW_OKAY) | |
204 { | |
205 purple_debug_error("bonjour", "Unable to initialize the data for the mDNS.\n"); | |
206 return -1; | |
207 } | |
208 | |
209 /* Convert the port to a string */ | |
210 snprintf(portstring, sizeof(portstring), "%d", data->port_p2pj); | |
211 | |
212 /* Publish standard records */ | |
213 sw_text_record_add_key_and_string_value(dns_data, "txtvers", data->txtvers); | |
214 sw_text_record_add_key_and_string_value(dns_data, "version", data->version); | |
215 sw_text_record_add_key_and_string_value(dns_data, "1st", data->first); | |
216 sw_text_record_add_key_and_string_value(dns_data, "last", data->last); | |
217 sw_text_record_add_key_and_string_value(dns_data, "port.p2pj", portstring); | |
218 sw_text_record_add_key_and_string_value(dns_data, "phsh", data->phsh); | |
219 sw_text_record_add_key_and_string_value(dns_data, "status", data->status); | |
220 sw_text_record_add_key_and_string_value(dns_data, "vc", data->vc); | |
221 | |
222 /* Publish extra records */ | |
223 if ((data->email != NULL) && (*data->email != '\0')) | |
224 sw_text_record_add_key_and_string_value(dns_data, "email", data->email); | |
225 | |
226 if ((data->jid != NULL) && (*data->jid != '\0')) | |
227 sw_text_record_add_key_and_string_value(dns_data, "jid", data->jid); | |
228 | |
229 if ((data->AIM != NULL) && (*data->AIM != '\0')) | |
230 sw_text_record_add_key_and_string_value(dns_data, "AIM", data->AIM); | |
231 | |
232 if ((data->msg != NULL) && (*data->msg != '\0')) | |
233 sw_text_record_add_key_and_string_value(dns_data, "msg", data->msg); | |
234 | |
235 /* Publish the service */ | |
236 switch (type) | |
237 { | |
238 case PUBLISH_START: | |
239 publish_result = sw_discovery_publish(data->session, 0, data->name, ICHAT_SERVICE, NULL, | |
240 NULL, data->port_p2pj, sw_text_record_bytes(dns_data), sw_text_record_len(dns_data), | |
241 _publish_reply, NULL, &data->session_id); | |
242 break; | |
243 case PUBLISH_UPDATE: | |
244 publish_result = sw_discovery_publish_update(data->session, data->session_id, | |
245 sw_text_record_bytes(dns_data), sw_text_record_len(dns_data)); | |
246 break; | |
247 } | |
248 if (publish_result != SW_OKAY) | |
249 { | |
250 purple_debug_error("bonjour", "Unable to publish or change the status of the _presence._tcp service.\n"); | |
251 return -1; | |
252 } | |
253 | |
254 /* Free the memory used by temp data */ | |
255 sw_text_record_fina(dns_data); | |
256 | |
257 return 0; | |
258 } | |
259 | |
260 void | |
261 _mdns_handle_event(gpointer data, gint source, PurpleInputCondition condition) | |
262 { | |
263 sw_discovery_read_socket((sw_discovery)data); | |
264 } |