Mercurial > pidgin.yaz
annotate src/protocols/bonjour/jabber.c @ 13902:425e0f861e88
[gaim-migrate @ 16390]
A small part of sf patch #1490646, from Jonty Wareing & Jono Cole
"Fix & Enhance the Bonjour prpl"
"Several instances of "magic strings" have been replaced
with proper XML parsing code in the Bonjour prpl,
allowing it to communicate with other Gaim clients (a
misplaced space in one of the strings prevented this),
and every other Bonjour chat client we can find.
A fair amount of completely redundant code was also
stripped, which in combination with the proper XML
parsing allows the client to be far more flexible about
Jabber errors in other clients."
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Sat, 01 Jul 2006 22:32:20 +0000 |
parents | 47c3d00713af |
children | 8264f52a1142 |
rev | line source |
---|---|
11477 | 1 /* |
2 * gaim - Bonjour Protocol Plugin | |
3 * | |
4 * Gaim is the legal property of its developers, whose names are too numerous | |
5 * to list here. Please refer to the COPYRIGHT file distributed with this | |
6 * source distribution. | |
7 * | |
8 * This program is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * This program is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License | |
19 * along with this program; if not, write to the Free Software | |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 */ | |
11688
1fd2a974379f
[gaim-migrate @ 13974]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11539
diff
changeset
|
22 #ifndef _WIN32 |
11477 | 23 #include <sys/socket.h> |
24 #include <netinet/in.h> | |
25 #include <arpa/inet.h> | |
11688
1fd2a974379f
[gaim-migrate @ 13974]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11539
diff
changeset
|
26 #else |
1fd2a974379f
[gaim-migrate @ 13974]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11539
diff
changeset
|
27 #include "libc_interface.h" |
1fd2a974379f
[gaim-migrate @ 13974]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11539
diff
changeset
|
28 #endif |
1fd2a974379f
[gaim-migrate @ 13974]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11539
diff
changeset
|
29 #include <sys/types.h> |
11477 | 30 #include <glib.h> |
31 #include <glib/gprintf.h> | |
32 #include <unistd.h> | |
33 #include <fcntl.h> | |
34 | |
35 #include "network.h" | |
36 #include "eventloop.h" | |
37 #include "connection.h" | |
38 #include "blist.h" | |
39 #include "xmlnode.h" | |
40 #include "debug.h" | |
41 #include "notify.h" | |
42 #include "util.h" | |
43 | |
44 #include "jabber.h" | |
45 #include "bonjour.h" | |
46 #include "buddy.h" | |
47 | |
12443 | 48 static gint |
11539 | 49 _connect_to_buddy(GaimBuddy *gb) |
11477 | 50 { |
51 gint socket_fd; | |
52 gint retorno = 0; | |
53 struct sockaddr_in buddy_address; | |
11539 | 54 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
55 /* Create a socket and make it non-blocking */ |
11477 | 56 socket_fd = socket(PF_INET, SOCK_STREAM, 0); |
11539 | 57 |
11477 | 58 buddy_address.sin_family = PF_INET; |
59 buddy_address.sin_port = htons(((BonjourBuddy*)(gb->proto_data))->port_p2pj); | |
60 inet_aton(((BonjourBuddy*)(gb->proto_data))->ip, &(buddy_address.sin_addr)); | |
61 memset(&(buddy_address.sin_zero), '\0', 8); | |
11539 | 62 |
11477 | 63 retorno = connect(socket_fd, (struct sockaddr*)&buddy_address, sizeof(struct sockaddr)); |
64 if (retorno == -1) { | |
11823 | 65 gaim_debug_warning("bonjour", "connect error: %s\n", strerror(errno)); |
11477 | 66 } |
67 fcntl(socket_fd, F_SETFL, O_NONBLOCK); | |
68 | |
69 return socket_fd; | |
70 } | |
71 | |
12443 | 72 #if 0 /* this isn't used anywhere... */ |
73 static const char * | |
11539 | 74 _font_size_gaim_to_ichat(int size) |
11477 | 75 { |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
76 switch (size) { |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
77 case 1: |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
78 return "8"; |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
79 case 2: |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
80 return "10"; |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
81 case 3: |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
82 return "12"; |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
83 case 4: |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
84 return "14"; |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
85 case 5: |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
86 return "17"; |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
87 case 6: |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
88 return "21"; |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
89 case 7: |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
90 return "24"; |
11477 | 91 } |
11539 | 92 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
93 return "12"; |
11477 | 94 } |
12443 | 95 #endif |
11477 | 96 |
12443 | 97 static const char * |
11539 | 98 _font_size_ichat_to_gaim(int size) |
11477 | 99 { |
100 if (size > 24) { | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
101 return "7"; |
11539 | 102 } else if (size >= 21) { |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
103 return "6"; |
11539 | 104 } else if (size >= 17) { |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
105 return "5"; |
11539 | 106 } else if (size >= 14) { |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
107 return "4"; |
11539 | 108 } else if (size >= 12) { |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
109 return "3"; |
11539 | 110 } else if (size >= 10) { |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
111 return "2"; |
11477 | 112 } |
113 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
114 return "1"; |
11477 | 115 } |
12443 | 116 static void |
11539 | 117 _jabber_parse_and_write_message_to_ui(char *message, GaimConnection *connection, GaimBuddy *gb) |
11477 | 118 { |
11539 | 119 xmlnode *body_node = NULL; |
120 char *body = NULL; | |
121 xmlnode *html_node = NULL; | |
11477 | 122 gboolean isHTML = FALSE; |
11539 | 123 xmlnode *html_body_node = NULL; |
124 const char *ichat_balloon_color = NULL; | |
125 const char *ichat_text_color = NULL; | |
126 xmlnode *html_body_font_node = NULL; | |
127 const char *font_face = NULL; | |
128 const char *font_size = NULL; | |
129 const char *font_color = NULL; | |
130 char *html_body = NULL; | |
131 xmlnode *events_node = NULL; | |
11477 | 132 gboolean composing_event = FALSE; |
133 gint garbage = -1; | |
11539 | 134 xmlnode *message_node = NULL; |
11477 | 135 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
136 /* Parsing of the message */ |
11477 | 137 message_node = xmlnode_from_str(message, strlen(message)); |
138 if (message_node == NULL) { | |
139 return; | |
140 } | |
11539 | 141 |
11477 | 142 body_node = xmlnode_get_child(message_node, "body"); |
143 if (body_node != NULL) { | |
144 body = xmlnode_get_data(body_node); | |
145 } else { | |
146 return; | |
147 } | |
11539 | 148 |
11477 | 149 html_node = xmlnode_get_child(message_node, "html"); |
11539 | 150 if (html_node != NULL) |
151 { | |
11477 | 152 isHTML = TRUE; |
153 html_body_node = xmlnode_get_child(html_node, "body"); | |
11539 | 154 if (html_body_node != NULL) |
155 { | |
11477 | 156 ichat_balloon_color = xmlnode_get_attrib(html_body_node, "ichatballooncolor"); |
157 ichat_text_color = xmlnode_get_attrib(html_body_node, "ichattextcolor"); | |
158 html_body_font_node = xmlnode_get_child(html_body_node, "font"); | |
11539 | 159 if (html_body_font_node != NULL) |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
160 { /* Types of messages sent by iChat */ |
11477 | 161 font_face = xmlnode_get_attrib(html_body_font_node, "face"); |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
162 /* The absolute iChat font sizes should be converted to 1..7 range */ |
11477 | 163 font_size = xmlnode_get_attrib(html_body_font_node, "ABSZ"); |
11539 | 164 if (font_size != NULL) |
165 { | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
166 font_size = _font_size_ichat_to_gaim(atoi(font_size)); |
11477 | 167 } |
168 font_color = xmlnode_get_attrib(html_body_font_node, "color"); | |
169 html_body = xmlnode_get_data(html_body_font_node); | |
11539 | 170 if (html_body == NULL) |
171 { | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
172 /* This is the kind of formated messages that Gaim creates */ |
11477 | 173 html_body = xmlnode_to_str(html_body_font_node, &garbage); |
174 } | |
175 } else { | |
176 isHTML = FALSE; | |
177 } | |
178 } else { | |
179 isHTML = FALSE; | |
180 } | |
11539 | 181 |
11477 | 182 } |
11539 | 183 |
11477 | 184 events_node = xmlnode_get_child_with_namespace(message_node, "x", "jabber:x:event"); |
11539 | 185 if (events_node != NULL) |
186 { | |
187 if (xmlnode_get_child(events_node, "composing") != NULL) | |
188 { | |
11477 | 189 composing_event = TRUE; |
190 } | |
11539 | 191 if (xmlnode_get_child(events_node, "id") != NULL) |
192 { | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
193 /* The user is just typing */ |
11477 | 194 xmlnode_free(message_node); |
195 g_free(body); | |
196 g_free(html_body); | |
197 return; | |
198 } | |
199 } | |
11539 | 200 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
201 /* Compose the message */ |
11539 | 202 if (isHTML) |
203 { | |
11477 | 204 if (font_face == NULL) font_face = "Helvetica"; |
205 if (font_size == NULL) font_size = "3"; | |
206 if (ichat_text_color == NULL) ichat_text_color = "#000000"; | |
207 if (ichat_balloon_color == NULL) ichat_balloon_color = "#FFFFFF"; | |
11539 | 208 body = g_strconcat("<font face='", font_face, "' size='", font_size, "' color='", ichat_text_color, |
11477 | 209 "' back='", ichat_balloon_color, "'>", html_body, "</font>", NULL); |
210 } | |
11539 | 211 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
212 /* Send the message to the UI */ |
11477 | 213 serv_got_im(connection, gb->name, body, 0, time(NULL)); |
11539 | 214 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
215 /* Free all the strings and nodes (the attributes are freed with their nodes) */ |
11477 | 216 xmlnode_free(message_node); |
217 g_free(body); | |
218 g_free(html_body); | |
219 } | |
220 | |
12708 | 221 struct _check_buddy_by_address_t { |
222 char *address; | |
223 GaimBuddy **gb; | |
13900 | 224 BonjourJabber *bj; |
12708 | 225 }; |
226 | |
227 static void | |
228 _check_buddy_by_address(gpointer key, gpointer value, gpointer data) | |
11477 | 229 { |
11539 | 230 GaimBuddy *gb = (GaimBuddy*)value; |
13900 | 231 BonjourBuddy *bb; |
232 struct _check_buddy_by_address_t *cbba; | |
233 | |
234 gb = value; | |
235 cbba = data; | |
11539 | 236 |
13900 | 237 /* |
238 * If the current GaimBuddy's data is not null and the GaimBuddy's account | |
239 * is the same as the account requesting the check then continue to determine | |
240 * whether the buddies IP matches the target IP. | |
241 */ | |
242 if (cbba->bj->account == gb->account) | |
243 { | |
244 bb = gb->proto_data; | |
245 if ((bb != NULL) && (g_strcasecmp(bb->ip, cbba->address) == 0)) | |
246 *(cbba->gb) = gb; | |
11477 | 247 } |
248 } | |
249 | |
12443 | 250 static gint |
11539 | 251 _read_data(gint socket, char **message) |
11477 | 252 { |
11539 | 253 GString *data = g_string_new(""); |
13006
e19c59a6ff11
[gaim-migrate @ 15359]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12733
diff
changeset
|
254 char partial_data[512]; |
11477 | 255 gint total_message_length = 0; |
13006
e19c59a6ff11
[gaim-migrate @ 15359]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12733
diff
changeset
|
256 gint partial_message_length = 0; |
11477 | 257 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
258 /* Read chunks of 512 bytes till the end of the data */ |
13006
e19c59a6ff11
[gaim-migrate @ 15359]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12733
diff
changeset
|
259 while ((partial_message_length = recv(socket, partial_data, 512, 0)) > 0) |
11539 | 260 { |
13006
e19c59a6ff11
[gaim-migrate @ 15359]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12733
diff
changeset
|
261 g_string_append_len(data, partial_data, partial_message_length); |
e19c59a6ff11
[gaim-migrate @ 15359]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12733
diff
changeset
|
262 total_message_length += partial_message_length; |
11477 | 263 } |
11539 | 264 |
13006
e19c59a6ff11
[gaim-migrate @ 15359]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12733
diff
changeset
|
265 if (partial_message_length == -1) |
11539 | 266 { |
11823 | 267 gaim_debug_warning("bonjour", "receive error: %s\n", strerror(errno)); |
11477 | 268 if (total_message_length == 0) { |
269 return -1; | |
270 } | |
271 } | |
272 | |
273 *message = data->str; | |
274 g_string_free(data, FALSE); | |
11539 | 275 if (total_message_length != 0) |
276 gaim_debug_info("bonjour", "Receive: -%s- %d bytes\n", *message, total_message_length); | |
277 | |
11477 | 278 return total_message_length; |
279 } | |
280 | |
12443 | 281 static gint |
11539 | 282 _send_data(gint socket, char *message) |
11477 | 283 { |
284 gint message_len = strlen(message); | |
13006
e19c59a6ff11
[gaim-migrate @ 15359]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12733
diff
changeset
|
285 gint partial_sent = 0; |
e19c59a6ff11
[gaim-migrate @ 15359]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12733
diff
changeset
|
286 gchar *partial_message = message; |
11539 | 287 |
13006
e19c59a6ff11
[gaim-migrate @ 15359]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12733
diff
changeset
|
288 while ((partial_sent = send(socket, partial_message, message_len, 0)) < message_len) |
11539 | 289 { |
13006
e19c59a6ff11
[gaim-migrate @ 15359]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12733
diff
changeset
|
290 if (partial_sent != -1) { |
e19c59a6ff11
[gaim-migrate @ 15359]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12733
diff
changeset
|
291 partial_message += partial_sent; |
e19c59a6ff11
[gaim-migrate @ 15359]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12733
diff
changeset
|
292 message_len -= partial_sent; |
11477 | 293 } else { |
294 return -1; | |
295 } | |
296 } | |
11539 | 297 |
11477 | 298 return strlen(message); |
299 } | |
300 | |
12443 | 301 static void |
11539 | 302 _client_socket_handler(gpointer data, gint socket, GaimInputCondition condition) |
11477 | 303 { |
11539 | 304 char *message = NULL; |
11477 | 305 gint message_length; |
11539 | 306 GaimBuddy *gb = (GaimBuddy*)data; |
307 GaimAccount *account = gb->account; | |
308 GaimConversation *conversation; | |
309 char *closed_conv_message; | |
310 BonjourBuddy *bb = (BonjourBuddy*)gb->proto_data; | |
11477 | 311 gboolean closed_conversation = FALSE; |
13902 | 312 xmlnode *message_node = NULL; |
11477 | 313 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
314 /* Read the data from the socket */ |
11477 | 315 if ((message_length = _read_data(socket, &message)) == -1) { |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
316 /* There have been an error reading from the socket */ |
11477 | 317 return; |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
318 } else if (message_length == 0) { /* The other end has closed the socket */ |
11477 | 319 closed_conversation = TRUE; |
320 } else { | |
321 message[message_length] = '\0'; | |
11539 | 322 |
11477 | 323 while (g_ascii_iscntrl(message[message_length - 1])) { |
324 message[message_length - 1] = '\0'; | |
325 message_length--; | |
326 } | |
327 } | |
11539 | 328 |
13902 | 329 /* Parse the message into an XMLnode for analysis */ |
330 message_node = xmlnode_from_str(message, strlen(message)); | |
11539 | 331 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
332 /* Check if the start of the stream has been received, if not check that the current */ |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
333 /* data is the start of the stream */ |
13902 | 334 if (!(bb->conversation->stream_started)) |
11539 | 335 { |
13902 | 336 /* Check if this is the start of the stream */ |
337 if ((message_node != NULL) && | |
338 g_ascii_strcasecmp(xmlnode_get_attrib(message_node, "xmlns"), "jabber:client") && | |
339 (xmlnode_get_attrib(message_node,"xmlns:stream") != NULL)) | |
340 { | |
341 bb->conversation->stream_started = TRUE; | |
342 } | |
343 else | |
344 { | |
345 /* TODO: This needs to be nonblocking! */ | |
346 if (send(bb->conversation->socket, DOCTYPE, strlen(DOCTYPE), 0) == -1) | |
347 { | |
348 gaim_debug_error("bonjour", "Unable to start a conversation with %s\n", bb->name); | |
349 } | |
350 else | |
351 { | |
352 bb->conversation->stream_started = TRUE; | |
11477 | 353 } |
354 } | |
355 } | |
11539 | 356 |
13902 | 357 /* |
358 * Check that this is not the end of the conversation. This is | |
359 * using a magic string, but xmlnode won't play nice when just | |
360 * parsing an end tag | |
361 */ | |
11477 | 362 if (g_str_has_prefix(message, STREAM_END) || (closed_conversation == TRUE)) { |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
363 /* Close the socket, clear the watcher and free memory */ |
11477 | 364 if (bb->conversation != NULL) { |
365 close(bb->conversation->socket); | |
366 gaim_input_remove(bb->conversation->watcher_id); | |
367 g_free(bb->conversation->buddy_name); | |
368 g_free(bb->conversation); | |
369 bb->conversation = NULL; | |
370 } | |
11539 | 371 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
372 /* Inform the user that the conversation has been closed */ |
11498 | 373 conversation = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, gb->name, account); |
13266 | 374 closed_conv_message = g_strdup_printf(_("%s has closed the conversation."), gb->name); |
11477 | 375 gaim_conversation_write(conversation, NULL, closed_conv_message, GAIM_MESSAGE_SYSTEM, time(NULL)); |
13266 | 376 g_free(closed_conv_message); |
11477 | 377 } else { |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
378 /* Parse the message to get the data and send to the ui */ |
11477 | 379 _jabber_parse_and_write_message_to_ui(message, account->gc, gb); |
380 } | |
13902 | 381 |
382 xmlnode_free(message_node); | |
11477 | 383 } |
384 | |
12443 | 385 static void |
11539 | 386 _server_socket_handler(gpointer data, int server_socket, GaimInputCondition condition) |
11477 | 387 { |
11539 | 388 GaimBuddy *gb = NULL; |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
389 struct sockaddr_in their_addr; /* connector's address information */ |
11515 | 390 socklen_t sin_size = sizeof(struct sockaddr); |
11477 | 391 int client_socket; |
11539 | 392 BonjourBuddy *bb = NULL; |
13900 | 393 BonjourJabber *bj = data; |
11539 | 394 char *address_text = NULL; |
395 GaimBuddyList *bl = gaim_get_blist(); | |
12733 | 396 struct _check_buddy_by_address_t *cbba; |
11477 | 397 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
398 /* Check that it is a read condition */ |
11477 | 399 if (condition != GAIM_INPUT_READ) { |
400 return; | |
401 } | |
402 | |
11539 | 403 if ((client_socket = accept(server_socket, (struct sockaddr *)&their_addr, &sin_size)) == -1) |
404 { | |
11477 | 405 return; |
406 } | |
407 fcntl(client_socket, F_SETFL, O_NONBLOCK); | |
408 | |
13900 | 409 /* Look for the buddy that has opened the conversation and fill information */ |
11477 | 410 address_text = inet_ntoa(their_addr.sin_addr); |
12733 | 411 cbba = g_new0(struct _check_buddy_by_address_t, 1); |
12708 | 412 cbba->address = address_text; |
413 cbba->gb = &gb; | |
13900 | 414 cbba->bj = bj; |
13249 | 415 g_hash_table_foreach(bl->buddies, _check_buddy_by_address, cbba); |
12708 | 416 g_free(cbba); |
11539 | 417 if (gb == NULL) |
418 { | |
11477 | 419 gaim_debug_info("bonjour", "We don't like invisible buddies, this is not a superheros comic\n"); |
420 close(client_socket); | |
421 return; | |
422 } | |
423 bb = (BonjourBuddy*)gb->proto_data; | |
424 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
425 /* Check if the conversation has been previously started */ |
11539 | 426 if (bb->conversation == NULL) |
427 { | |
11477 | 428 bb->conversation = g_new(BonjourJabberConversation, 1); |
429 bb->conversation->socket = client_socket; | |
430 bb->conversation->stream_started = FALSE; | |
431 bb->conversation->buddy_name = g_strdup(gb->name); | |
432 bb->conversation->message_id = 1; | |
11539 | 433 |
11477 | 434 if (bb->conversation->stream_started == FALSE) { |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
435 /* Start the stream */ |
11477 | 436 send(bb->conversation->socket, DOCTYPE, strlen(DOCTYPE), 0); |
437 bb->conversation->stream_started = TRUE; | |
438 } | |
439 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
440 /* Open a watcher for the client socket */ |
11539 | 441 bb->conversation->watcher_id = gaim_input_add(client_socket, GAIM_INPUT_READ, |
11477 | 442 _client_socket_handler, gb); |
443 } else { | |
444 close(client_socket); | |
445 } | |
446 } | |
447 | |
11539 | 448 gint |
449 bonjour_jabber_start(BonjourJabber *data) | |
11477 | 450 { |
451 struct sockaddr_in my_addr; | |
452 int yes = 1; | |
453 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
454 /* Open a listening socket for incoming conversations */ |
11539 | 455 if ((data->socket = socket(PF_INET, SOCK_STREAM, 0)) < 0) |
456 { | |
13266 | 457 gaim_debug_error("bonjour", "Cannot open socket: %s\n", strerror(errno)); |
458 gaim_connection_error(data->account->gc, _("Cannot open socket")); | |
11477 | 459 return -1; |
460 } | |
11539 | 461 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
462 /* Make the socket reusable */ |
11539 | 463 if (setsockopt(data->socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0) |
464 { | |
13266 | 465 gaim_debug_error("bonjour", "Error setting socket options: %s\n", strerror(errno)); |
466 gaim_connection_error(data->account->gc, _("Error setting socket options")); | |
11477 | 467 return -1; |
468 } | |
469 | |
470 memset(&my_addr, 0, sizeof(struct sockaddr_in)); | |
471 my_addr.sin_family = PF_INET; | |
472 my_addr.sin_port = htons(data->port); | |
11539 | 473 |
474 if (bind(data->socket, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) != 0) | |
475 { | |
13266 | 476 gaim_debug_error("bonjour", "Cannot bind socket: %s\n", strerror(errno)); |
477 gaim_connection_error(data->account->gc, _("Cannot bind socket to port")); | |
11477 | 478 return -1; |
479 } | |
11539 | 480 |
481 if (listen(data->socket, 10) != 0) | |
482 { | |
13266 | 483 gaim_debug_error("bonjour", "Cannot listen on socket: %s\n", strerror(errno)); |
484 gaim_connection_error(data->account->gc, _("Cannot listen on socket")); | |
11477 | 485 return -1; |
486 } | |
487 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
488 #if 0 |
12730
d5b8f4dc1622
[gaim-migrate @ 15074]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12708
diff
changeset
|
489 /* TODO: Why isn't this being used? */ |
d5b8f4dc1622
[gaim-migrate @ 15074]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12708
diff
changeset
|
490 data->socket = gaim_network_listen(data->port, SOCK_STREAM); |
11477 | 491 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
492 if (data->socket == -1) |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
493 { |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
494 gaim_debug_error("bonjour", "No se ha podido crear el socket\n"); |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
495 } |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
496 #endif |
11477 | 497 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
498 /* Open a watcher in the socket we have just opened */ |
11477 | 499 data->watcher_id = gaim_input_add(data->socket, GAIM_INPUT_READ, _server_socket_handler, data); |
11539 | 500 |
11477 | 501 return 0; |
502 } | |
503 | |
11693 | 504 int |
11539 | 505 bonjour_jabber_send_message(BonjourJabber *data, const gchar *to, const gchar *body) |
11477 | 506 { |
11539 | 507 xmlnode *message_node = NULL; |
508 gchar *message = NULL; | |
11477 | 509 gint message_length = -1; |
11539 | 510 xmlnode *message_body_node = NULL; |
511 xmlnode *message_html_node = NULL; | |
512 xmlnode *message_html_body_node = NULL; | |
513 xmlnode *message_html_body_font_node = NULL; | |
514 xmlnode *message_x_node = NULL; | |
11693 | 515 GaimBuddy *gb = NULL; |
516 BonjourBuddy *bb = NULL; | |
11539 | 517 char *conv_message = NULL; |
518 GaimConversation *conversation = NULL; | |
519 char *message_from_ui = NULL; | |
520 char *stripped_message = NULL; | |
521 | |
11693 | 522 gb = gaim_find_buddy(data->account, to); |
523 if (gb == NULL) | |
524 /* You can not send a message to an offline buddy */ | |
525 return -10000; | |
526 | |
527 bb = (BonjourBuddy *)gb->proto_data; | |
528 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
529 /* Enclose the message from the UI within a "font" node */ |
11477 | 530 message_body_node = xmlnode_new("body"); |
531 stripped_message = gaim_markup_strip_html(body); | |
532 xmlnode_insert_data(message_body_node, stripped_message, strlen(stripped_message)); | |
11539 | 533 |
11477 | 534 message_from_ui = g_strconcat("<font>", body, "</font>", NULL); |
535 message_html_body_font_node = xmlnode_from_str(message_from_ui, strlen(message_from_ui)); | |
11539 | 536 |
11477 | 537 message_html_body_node = xmlnode_new("body"); |
538 xmlnode_insert_child(message_html_body_node, message_html_body_font_node); | |
11539 | 539 |
11477 | 540 message_html_node = xmlnode_new("html"); |
541 xmlnode_set_attrib(message_html_node, "xmlns", "http://www.w3.org/1999/xhtml"); | |
542 xmlnode_insert_child(message_html_node, message_html_body_node); | |
543 | |
544 message_x_node = xmlnode_new("x"); | |
545 xmlnode_set_attrib(message_x_node, "xmlns", "jabber:x:event"); | |
546 xmlnode_insert_child(message_x_node, xmlnode_new("composing")); | |
11539 | 547 |
11477 | 548 message_node = xmlnode_new("message"); |
549 xmlnode_set_attrib(message_node, "to", ((BonjourBuddy*)(gb->proto_data))->name); | |
550 xmlnode_set_attrib(message_node, "type", "chat"); | |
551 xmlnode_insert_child(message_node, message_body_node); | |
552 xmlnode_insert_child(message_node, message_html_node); | |
553 xmlnode_insert_child(message_node, message_x_node); | |
11539 | 554 |
11477 | 555 message = xmlnode_to_str(message_node, &message_length); |
556 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
557 /* Check if there is a previously open conversation */ |
11539 | 558 if (bb->conversation == NULL) |
559 { | |
11477 | 560 bb->conversation = g_new(BonjourJabberConversation, 1); |
13006
e19c59a6ff11
[gaim-migrate @ 15359]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12733
diff
changeset
|
561 bb->conversation->socket = _connect_to_buddy(gb); |
11477 | 562 bb->conversation->stream_started = FALSE; |
563 bb->conversation->buddy_name = g_strdup(gb->name); | |
11539 | 564 bb->conversation->watcher_id = gaim_input_add(bb->conversation->socket, |
13902 | 565 GAIM_INPUT_READ, _client_socket_handler, gb); |
11477 | 566 } |
567 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
568 /* Check if the stream for the conversation has been started */ |
11539 | 569 if (bb->conversation->stream_started == FALSE) |
570 { | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
571 /* Start the stream */ |
11539 | 572 if (send(bb->conversation->socket, DOCTYPE, strlen(DOCTYPE), 0) == -1) |
573 { | |
11477 | 574 gaim_debug_error("bonjour", "Unable to start a conversation\n"); |
11823 | 575 gaim_debug_warning("bonjour", "send error: %s\n", strerror(errno)); |
13266 | 576 conv_message = g_strdup(_("Unable to send the message, the conversation couldn't be started.")); |
11498 | 577 conversation = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, bb->name, data->account); |
11477 | 578 gaim_conversation_write(conversation, NULL, conv_message, GAIM_MESSAGE_SYSTEM, time(NULL)); |
579 close(bb->conversation->socket); | |
580 gaim_input_remove(bb->conversation->watcher_id); | |
11539 | 581 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
582 /* Free all the data related to the conversation */ |
11477 | 583 g_free(bb->conversation->buddy_name); |
584 g_free(bb->conversation); | |
585 bb->conversation = NULL; | |
11693 | 586 return 0; |
11477 | 587 } |
11539 | 588 |
11477 | 589 bb->conversation->stream_started = TRUE; |
590 } | |
11539 | 591 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
592 /* Send the message */ |
11539 | 593 if (_send_data(bb->conversation->socket, message) == -1) |
11693 | 594 return -10000; |
595 | |
596 return 1; | |
11477 | 597 } |
598 | |
11539 | 599 void |
600 bonjour_jabber_close_conversation(BonjourJabber *data, GaimBuddy *gb) | |
11477 | 601 { |
11539 | 602 BonjourBuddy *bb = (BonjourBuddy*)gb->proto_data; |
603 | |
604 if (bb->conversation != NULL) | |
605 { | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
606 /* Send the end of the stream to the other end of the conversation */ |
11477 | 607 send(bb->conversation->socket, STREAM_END, strlen(STREAM_END), 0); |
11539 | 608 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
609 /* Close the socket and remove the watcher */ |
11477 | 610 close(bb->conversation->socket); |
611 gaim_input_remove(bb->conversation->watcher_id); | |
11539 | 612 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
613 /* Free all the data related to the conversation */ |
11477 | 614 g_free(bb->conversation->buddy_name); |
615 g_free(bb->conversation); | |
616 bb->conversation = NULL; | |
617 } | |
618 } | |
619 | |
11539 | 620 void |
621 bonjour_jabber_stop(BonjourJabber *data) | |
11477 | 622 { |
11539 | 623 GaimBuddy *gb = NULL; |
624 BonjourBuddy *bb = NULL; | |
625 GSList *buddies; | |
626 GSList *l; | |
627 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
628 /* Close the server socket and remove all the watcher */ |
11477 | 629 close(data->socket); |
630 gaim_input_remove(data->watcher_id); | |
11539 | 631 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
632 /* Close all the sockets and remove all the watchers after sending end streams */ |
11539 | 633 if (data->account->gc != NULL) |
634 { | |
11477 | 635 buddies = gaim_find_buddies(data->account, data->account->username); |
11539 | 636 for (l = buddies; l; l = l->next) |
637 { | |
11477 | 638 gb = (GaimBuddy*)l->data; |
639 bb = (BonjourBuddy*)gb->proto_data; | |
11539 | 640 if (bb->conversation != NULL) |
641 { | |
11477 | 642 send(bb->conversation->socket, STREAM_END, strlen(STREAM_END), 0); |
643 close(bb->conversation->socket); | |
644 gaim_input_remove(bb->conversation->watcher_id); | |
645 } | |
646 } | |
647 g_slist_free(buddies); | |
648 } | |
649 } |