Mercurial > pidgin
annotate src/protocols/bonjour/jabber.c @ 12645:fc28451f5d96
[gaim-migrate @ 14983]
SF Patch #1314512 from Sadrul (who has a patch for everything)
"This patch introduces a flag for protocol plugins that
support offline messages (like Y!M and ICQ). This was
encouraged by the following conversation:
<sadrul> should offline buddies be listed/enabled in
the send-to menu?
<rekkanoryo> i would think only for protocols that
support offline messaging, if it's indicated that the
buddy is offline
-- <snip> --
<Bleeter> sadrul: personally, I'd like to see a
'supports offline' flag of some description
<Bleeter> one could then redirect (via plugins) through
email or alternative methods
<Bleeter> just a thought
<Paco-Paco> yeah, that sounds like a reasonble thing to have
This patch uses this flag to disable the buddies in the
send-to menu who are offline and the protocol doesn't
support offline messages."
I made this make the label insensitive instead of the whole menuitem. This
should address SimGuy's concerns about inconsistency (i.e. you could create a
conversation with someone via the buddy list that you couldn't create via the
Send To menu). I also hacked up some voodoo to show the label as sensitive when
moused-over, as that looks better (given the label-insensitive thing is itself a
hack). I think this works quite well.
BUG NOTE:
This makes more obvious an existing bug. The Send To menu isn't updated when
buddies sign on or off or change status (at least under some circumstances).
We need to fix that anyway, so I'm not going to let it hold up this commit.
Switching tabs will clear it up. I'm thinking we just might want to build the
contents of that menu when it is selected. That would save us a mess of
inefficient signal callbacks that update the Send To menus in open windows all
the time.
AIM NOTE:
This assumes that AIM can't offline message. That's not strictly true. You can
message invisible users on AIM. However, by design, we can't tell when a user
is invisible without resorting to dirty hackery. In practice, this isn't a
problem, as you can still select the AIM user from the menu. And really, how
often will you be choosing the Invisible contact, rather than the user going
Invisible in the middle of a conversation or IMing you while they're Invisible?
JABBER NOTE:
This assumes that Jabber can always offline message. This isn't strictly true.
Sadrul said:
I have updated Jabber according to this link which seems to
talk about how to determine the existence offline-message
support in a server:
http://www.jabber.org/jeps/jep-0013.html#discover
However, jabber.org doesn't seem to send the required
info. So I am not sure about it.
He later said:
I talked to Nathan and he said offline message support is
mostly assumed for most jabber servers. GTalk doesn't yet
support it, but they are working on it. So I have made
jabber to always return TRUE.
If there is truly no way to detect offline messaging capability, then this is
an acceptable solution. We could special case Google Talk because of its
popularity, and remove that later. It's probably not worth it though.
MSN NOTE:
This assumes that MSN can never offline message. That's effectively true, but
to be technically correct, MSN can offline message if there's already a
switchboard conversation open with a user. We could write an offline_message
function in the MSN prpl to detect that, but it'd be of limited usefulness,
especially given that under most circumstances (where this might matter), the
switchboard connection will be closed almost immediately.
CVS NOTE:
I'm writing to share a tragic little story.
I have a PC that I use for Gaim development. One day, I was writing a commit
message on it, when all of a suddent it went berserk. The screen started
flashing, and the whole commit message just disappeared. All of it. And it was
a good commit message! I had to cram and rewrite it really quickly. Needless to
say, my rushed commit message wasn't nearly as good, and I blame the PC for that.
Seriously, though, what kind of version control system loses your commit
message on a broken connection to the server? Stupid!
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Fri, 23 Dec 2005 19:26:04 +0000 |
parents | 488a305f9aff |
children | 495856ce025b |
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 | |
12443 | 221 static gboolean |
11539 | 222 _check_buddy_by_address(gpointer key, gpointer value, gpointer address) |
11477 | 223 { |
11539 | 224 GaimBuddy *gb = (GaimBuddy*)value; |
225 BonjourBuddy *bb = (BonjourBuddy*)gb->proto_data; | |
226 | |
227 if (bb != NULL) | |
228 { | |
11477 | 229 if (g_strcasecmp(bb->ip, (char*)address) == 0) { |
230 return TRUE; | |
231 } else { | |
232 return FALSE; | |
233 } | |
234 } else { | |
11539 | 235 return FALSE; |
11477 | 236 } |
237 } | |
238 | |
12443 | 239 static gint |
11539 | 240 _read_data(gint socket, char **message) |
11477 | 241 { |
11539 | 242 GString *data = g_string_new(""); |
11477 | 243 char parcial_data[512]; |
244 gint total_message_length = 0; | |
245 gint parcial_message_length = 0; | |
246 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
247 /* Read chunks of 512 bytes till the end of the data */ |
11539 | 248 while ((parcial_message_length = recv(socket, parcial_data, 512, 0)) > 0) |
249 { | |
11477 | 250 g_string_append_len(data, parcial_data, parcial_message_length); |
251 total_message_length += parcial_message_length; | |
252 } | |
11539 | 253 |
254 if (parcial_message_length == -1) | |
255 { | |
11823 | 256 gaim_debug_warning("bonjour", "receive error: %s\n", strerror(errno)); |
11477 | 257 if (total_message_length == 0) { |
258 return -1; | |
259 } | |
260 } | |
261 | |
262 *message = data->str; | |
263 g_string_free(data, FALSE); | |
11539 | 264 if (total_message_length != 0) |
265 gaim_debug_info("bonjour", "Receive: -%s- %d bytes\n", *message, total_message_length); | |
266 | |
11477 | 267 return total_message_length; |
268 } | |
269 | |
12443 | 270 static gint |
11539 | 271 _send_data(gint socket, char *message) |
11477 | 272 { |
273 gint message_len = strlen(message); | |
274 gint parcial_sent = 0; | |
11539 | 275 gchar *parcial_message = message; |
276 | |
277 while ((parcial_sent = send(socket, parcial_message, message_len, 0)) < message_len) | |
278 { | |
11477 | 279 if (parcial_sent != -1) { |
280 parcial_message += parcial_sent; | |
281 message_len -= parcial_sent; | |
282 } else { | |
283 return -1; | |
284 } | |
285 } | |
11539 | 286 |
11477 | 287 return strlen(message); |
288 } | |
289 | |
12443 | 290 static void |
11539 | 291 _client_socket_handler(gpointer data, gint socket, GaimInputCondition condition) |
11477 | 292 { |
11539 | 293 char *message = NULL; |
11477 | 294 gint message_length; |
11539 | 295 GaimBuddy *gb = (GaimBuddy*)data; |
296 GaimAccount *account = gb->account; | |
297 GaimConversation *conversation; | |
298 char *closed_conv_message; | |
299 BonjourBuddy *bb = (BonjourBuddy*)gb->proto_data; | |
11477 | 300 gboolean closed_conversation = FALSE; |
301 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
302 /* Read the data from the socket */ |
11477 | 303 if ((message_length = _read_data(socket, &message)) == -1) { |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
304 /* There have been an error reading from the socket */ |
11477 | 305 return; |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
306 } else if (message_length == 0) { /* The other end has closed the socket */ |
11477 | 307 closed_conversation = TRUE; |
308 } else { | |
309 message[message_length] = '\0'; | |
11539 | 310 |
11477 | 311 while (g_ascii_iscntrl(message[message_length - 1])) { |
312 message[message_length - 1] = '\0'; | |
313 message_length--; | |
314 } | |
315 } | |
11539 | 316 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
317 /* Check if the start of the doctype has been received, if not check that the current */ |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
318 /* data is the doctype */ |
11539 | 319 if (!(bb->conversation->start_step_one)) |
320 { | |
321 if (g_str_has_prefix(message, DOCTYPE_DECLARATION)) | |
322 { | |
11477 | 323 bb->conversation->start_step_one = TRUE; |
324 } | |
325 } | |
11539 | 326 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
327 /* 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
|
328 /* data is the start of the stream */ |
11539 | 329 if (!(bb->conversation->start_step_two)) |
330 { | |
11477 | 331 if (g_str_has_suffix(message, STREAM_START)) { |
332 bb->conversation->start_step_two = TRUE; | |
11539 | 333 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
334 /* If we haven't done it yet, we have to sent the start of the stream to the other buddy */ |
11477 | 335 if (!(bb->conversation->stream_started)) { |
336 if (send(bb->conversation->socket, DOCTYPE, strlen(DOCTYPE), 0) == -1) { | |
337 gaim_debug_error("bonjour", "Unable to start a conversation with %s\n", bb->name); | |
338 } | |
339 } | |
340 } | |
341 return; | |
342 } | |
11539 | 343 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
344 /* Check that this is not the end of the conversation */ |
11477 | 345 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
|
346 /* Close the socket, clear the watcher and free memory */ |
11477 | 347 if (bb->conversation != NULL) { |
348 close(bb->conversation->socket); | |
349 gaim_input_remove(bb->conversation->watcher_id); | |
350 g_free(bb->conversation->buddy_name); | |
351 g_free(bb->conversation); | |
352 bb->conversation = NULL; | |
353 } | |
11539 | 354 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
355 /* Inform the user that the conversation has been closed */ |
11498 | 356 conversation = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, gb->name, account); |
11477 | 357 closed_conv_message = g_strconcat(gb->name, " has closed the conversation.", NULL); |
358 gaim_conversation_write(conversation, NULL, closed_conv_message, GAIM_MESSAGE_SYSTEM, time(NULL)); | |
359 } else { | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
360 /* Parse the message to get the data and send to the ui */ |
11477 | 361 _jabber_parse_and_write_message_to_ui(message, account->gc, gb); |
362 } | |
363 } | |
364 | |
12443 | 365 static void |
11539 | 366 _server_socket_handler(gpointer data, int server_socket, GaimInputCondition condition) |
11477 | 367 { |
11539 | 368 GaimBuddy *gb = NULL; |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
369 struct sockaddr_in their_addr; /* connector's address information */ |
11515 | 370 socklen_t sin_size = sizeof(struct sockaddr); |
11477 | 371 int client_socket; |
11539 | 372 BonjourBuddy *bb = NULL; |
373 char *address_text = NULL; | |
374 GaimBuddyList *bl = gaim_get_blist(); | |
11477 | 375 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
376 /* Check that it is a read condition */ |
11477 | 377 if (condition != GAIM_INPUT_READ) { |
378 return; | |
379 } | |
380 | |
11539 | 381 if ((client_socket = accept(server_socket, (struct sockaddr *)&their_addr, &sin_size)) == -1) |
382 { | |
11477 | 383 return; |
384 } | |
385 fcntl(client_socket, F_SETFL, O_NONBLOCK); | |
386 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
387 /* Look for the buddy that has open the conversation and fill information */ |
11477 | 388 address_text = inet_ntoa(their_addr.sin_addr); |
389 gb = (GaimBuddy*)g_hash_table_find(bl->buddies, _check_buddy_by_address, address_text); | |
11539 | 390 if (gb == NULL) |
391 { | |
11477 | 392 gaim_debug_info("bonjour", "We don't like invisible buddies, this is not a superheros comic\n"); |
393 close(client_socket); | |
394 return; | |
395 } | |
396 bb = (BonjourBuddy*)gb->proto_data; | |
397 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
398 /* Check if the conversation has been previously started */ |
11539 | 399 if (bb->conversation == NULL) |
400 { | |
11477 | 401 bb->conversation = g_new(BonjourJabberConversation, 1); |
402 bb->conversation->socket = client_socket; | |
403 bb->conversation->start_step_one = FALSE; | |
404 bb->conversation->start_step_two = FALSE; | |
405 bb->conversation->stream_started = FALSE; | |
406 bb->conversation->buddy_name = g_strdup(gb->name); | |
407 bb->conversation->message_id = 1; | |
11539 | 408 |
11477 | 409 if (bb->conversation->stream_started == FALSE) { |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
410 /* Start the stream */ |
11477 | 411 send(bb->conversation->socket, DOCTYPE, strlen(DOCTYPE), 0); |
412 bb->conversation->stream_started = TRUE; | |
413 } | |
414 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
415 /* Open a watcher for the client socket */ |
11539 | 416 bb->conversation->watcher_id = gaim_input_add(client_socket, GAIM_INPUT_READ, |
11477 | 417 _client_socket_handler, gb); |
418 } else { | |
419 close(client_socket); | |
420 } | |
421 } | |
422 | |
11539 | 423 gint |
424 bonjour_jabber_start(BonjourJabber *data) | |
11477 | 425 { |
426 struct sockaddr_in my_addr; | |
427 int yes = 1; | |
11539 | 428 char *error_message = NULL; |
11477 | 429 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
430 /* Open a listening socket for incoming conversations */ |
11539 | 431 if ((data->socket = socket(PF_INET, SOCK_STREAM, 0)) < 0) |
432 { | |
11477 | 433 gaim_debug_error("bonjour", "Cannot get socket\n"); |
434 error_message = strerror(errno); | |
435 gaim_debug_error("bonjour", "%s\n", error_message); | |
436 gaim_connection_error(data->account->gc, "Cannot open socket"); | |
437 return -1; | |
438 } | |
11539 | 439 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
440 /* Make the socket reusable */ |
11539 | 441 if (setsockopt(data->socket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0) |
442 { | |
11477 | 443 gaim_debug_error("bonjour", "Cannot make socket reusable\n"); |
444 error_message = strerror(errno); | |
445 gaim_debug_error("bonjour", "%s\n", error_message); | |
446 gaim_connection_error(data->account->gc, "Error setting socket options"); | |
447 return -1; | |
448 } | |
449 | |
450 memset(&my_addr, 0, sizeof(struct sockaddr_in)); | |
451 my_addr.sin_family = PF_INET; | |
452 my_addr.sin_port = htons(data->port); | |
11539 | 453 |
454 if (bind(data->socket, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) != 0) | |
455 { | |
11477 | 456 gaim_debug_error("bonjour", "Cannot bind socket\n"); |
457 error_message = strerror(errno); | |
458 gaim_debug_error("bonjour", "%s\n", error_message); | |
459 gaim_connection_error(data->account->gc, "Cannot bind socket to port"); | |
460 return -1; | |
461 } | |
11539 | 462 |
463 if (listen(data->socket, 10) != 0) | |
464 { | |
11477 | 465 gaim_debug_error("bonjour", "Cannot listen to socket\n"); |
466 error_message = strerror(errno); | |
467 gaim_debug_error("bonjour", "%s\n", error_message); | |
468 gaim_connection_error(data->account->gc, "Cannot listen to socket"); | |
469 return -1; | |
470 } | |
471 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
472 #if 0 |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
473 data->socket = gaim_network_listen(data->port); |
11477 | 474 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
475 if (data->socket == -1) |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
476 { |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
477 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
|
478 } |
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
479 #endif |
11477 | 480 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
481 /* Open a watcher in the socket we have just opened */ |
11477 | 482 data->watcher_id = gaim_input_add(data->socket, GAIM_INPUT_READ, _server_socket_handler, data); |
11539 | 483 |
11477 | 484 return 0; |
485 } | |
486 | |
11693 | 487 int |
11539 | 488 bonjour_jabber_send_message(BonjourJabber *data, const gchar *to, const gchar *body) |
11477 | 489 { |
11539 | 490 xmlnode *message_node = NULL; |
491 gchar *message = NULL; | |
11477 | 492 gint message_length = -1; |
11539 | 493 xmlnode *message_body_node = NULL; |
494 xmlnode *message_html_node = NULL; | |
495 xmlnode *message_html_body_node = NULL; | |
496 xmlnode *message_html_body_font_node = NULL; | |
497 xmlnode *message_x_node = NULL; | |
11693 | 498 GaimBuddy *gb = NULL; |
499 BonjourBuddy *bb = NULL; | |
11539 | 500 char *conv_message = NULL; |
501 GaimConversation *conversation = NULL; | |
502 char *message_from_ui = NULL; | |
503 char *stripped_message = NULL; | |
504 | |
11693 | 505 gb = gaim_find_buddy(data->account, to); |
506 if (gb == NULL) | |
507 /* You can not send a message to an offline buddy */ | |
508 return -10000; | |
509 | |
510 bb = (BonjourBuddy *)gb->proto_data; | |
511 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
512 /* Enclose the message from the UI within a "font" node */ |
11477 | 513 message_body_node = xmlnode_new("body"); |
514 stripped_message = gaim_markup_strip_html(body); | |
515 xmlnode_insert_data(message_body_node, stripped_message, strlen(stripped_message)); | |
11539 | 516 |
11477 | 517 message_from_ui = g_strconcat("<font>", body, "</font>", NULL); |
518 message_html_body_font_node = xmlnode_from_str(message_from_ui, strlen(message_from_ui)); | |
11539 | 519 |
11477 | 520 message_html_body_node = xmlnode_new("body"); |
521 xmlnode_insert_child(message_html_body_node, message_html_body_font_node); | |
11539 | 522 |
11477 | 523 message_html_node = xmlnode_new("html"); |
524 xmlnode_set_attrib(message_html_node, "xmlns", "http://www.w3.org/1999/xhtml"); | |
525 xmlnode_insert_child(message_html_node, message_html_body_node); | |
526 | |
527 message_x_node = xmlnode_new("x"); | |
528 xmlnode_set_attrib(message_x_node, "xmlns", "jabber:x:event"); | |
529 xmlnode_insert_child(message_x_node, xmlnode_new("composing")); | |
11539 | 530 |
11477 | 531 message_node = xmlnode_new("message"); |
532 xmlnode_set_attrib(message_node, "to", ((BonjourBuddy*)(gb->proto_data))->name); | |
533 xmlnode_set_attrib(message_node, "type", "chat"); | |
534 xmlnode_insert_child(message_node, message_body_node); | |
535 xmlnode_insert_child(message_node, message_html_node); | |
536 xmlnode_insert_child(message_node, message_x_node); | |
11539 | 537 |
11477 | 538 message = xmlnode_to_str(message_node, &message_length); |
539 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
540 /* Check if there is a previously open conversation */ |
11539 | 541 if (bb->conversation == NULL) |
542 { | |
11477 | 543 bb->conversation = g_new(BonjourJabberConversation, 1); |
544 bb->conversation->socket = _connect_to_buddy(gb);; | |
545 bb->conversation->start_step_one = FALSE; | |
546 bb->conversation->start_step_two = FALSE; | |
547 bb->conversation->stream_started = FALSE; | |
548 bb->conversation->buddy_name = g_strdup(gb->name); | |
11539 | 549 bb->conversation->watcher_id = gaim_input_add(bb->conversation->socket, |
11477 | 550 GAIM_INPUT_READ, _client_socket_handler, gb); |
551 } | |
552 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
553 /* Check if the stream for the conversation has been started */ |
11539 | 554 if (bb->conversation->stream_started == FALSE) |
555 { | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
556 /* Start the stream */ |
11539 | 557 if (send(bb->conversation->socket, DOCTYPE, strlen(DOCTYPE), 0) == -1) |
558 { | |
11477 | 559 gaim_debug_error("bonjour", "Unable to start a conversation\n"); |
11823 | 560 gaim_debug_warning("bonjour", "send error: %s\n", strerror(errno)); |
11477 | 561 conv_message = g_strdup("Unable to send the message, the conversation couldn't be started."); |
11498 | 562 conversation = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, bb->name, data->account); |
11477 | 563 gaim_conversation_write(conversation, NULL, conv_message, GAIM_MESSAGE_SYSTEM, time(NULL)); |
564 close(bb->conversation->socket); | |
565 gaim_input_remove(bb->conversation->watcher_id); | |
11539 | 566 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
567 /* Free all the data related to the conversation */ |
11477 | 568 g_free(bb->conversation->buddy_name); |
569 g_free(bb->conversation); | |
570 bb->conversation = NULL; | |
11693 | 571 return 0; |
11477 | 572 } |
11539 | 573 |
11477 | 574 bb->conversation->stream_started = TRUE; |
575 } | |
11539 | 576 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
577 /* Send the message */ |
11539 | 578 if (_send_data(bb->conversation->socket, message) == -1) |
11693 | 579 return -10000; |
580 | |
581 return 1; | |
11477 | 582 } |
583 | |
11539 | 584 void |
585 bonjour_jabber_close_conversation(BonjourJabber *data, GaimBuddy *gb) | |
11477 | 586 { |
11539 | 587 BonjourBuddy *bb = (BonjourBuddy*)gb->proto_data; |
588 | |
589 if (bb->conversation != NULL) | |
590 { | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
591 /* Send the end of the stream to the other end of the conversation */ |
11477 | 592 send(bb->conversation->socket, STREAM_END, strlen(STREAM_END), 0); |
11539 | 593 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
594 /* Close the socket and remove the watcher */ |
11477 | 595 close(bb->conversation->socket); |
596 gaim_input_remove(bb->conversation->watcher_id); | |
11539 | 597 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
598 /* Free all the data related to the conversation */ |
11477 | 599 g_free(bb->conversation->buddy_name); |
600 g_free(bb->conversation); | |
601 bb->conversation = NULL; | |
602 } | |
603 } | |
604 | |
11539 | 605 void |
606 bonjour_jabber_stop(BonjourJabber *data) | |
11477 | 607 { |
11539 | 608 GaimBuddy *gb = NULL; |
609 BonjourBuddy *bb = NULL; | |
610 GSList *buddies; | |
611 GSList *l; | |
612 | |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
613 /* Close the server socket and remove all the watcher */ |
11477 | 614 close(data->socket); |
615 gaim_input_remove(data->watcher_id); | |
11539 | 616 |
11826
e05778d4f12d
[gaim-migrate @ 14117]
Richard Laager <rlaager@wiktel.com>
parents:
11823
diff
changeset
|
617 /* Close all the sockets and remove all the watchers after sending end streams */ |
11539 | 618 if (data->account->gc != NULL) |
619 { | |
11477 | 620 buddies = gaim_find_buddies(data->account, data->account->username); |
11539 | 621 for (l = buddies; l; l = l->next) |
622 { | |
11477 | 623 gb = (GaimBuddy*)l->data; |
624 bb = (BonjourBuddy*)gb->proto_data; | |
11539 | 625 if (bb->conversation != NULL) |
626 { | |
11477 | 627 send(bb->conversation->socket, STREAM_END, strlen(STREAM_END), 0); |
628 close(bb->conversation->socket); | |
629 gaim_input_remove(bb->conversation->watcher_id); | |
630 } | |
631 } | |
632 g_slist_free(buddies); | |
633 } | |
634 } |