Mercurial > pidgin
annotate src/protocols/jabber/si.c @ 13967:99b9b58b19dd
[gaim-migrate @ 16523]
Fix a crazy MSN crash. Basically it's possible to have more than one
slplink associated with a given switchboard, but our code did not
allow for that. I think it happens when you're in a multi-user
chat and you do stuff with multiple users that involves slplinks.
Like maybe file transfer and buddy icon related stuff.
Tracking this down took an ungodly amount of time, but thanks to
Meebo for letting me do it :-)
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 20 Jul 2006 07:31:15 +0000 |
parents | 25e63008d3bb |
children | 10e8eb6a4910 |
rev | line source |
---|---|
7395 | 1 /* |
2 * gaim - Jabber Protocol Plugin | |
3 * | |
4 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com> | |
5 * | |
6 * This program is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12909
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
14 * |
7395 | 15 * GNU General Public License for more details. |
16 * | |
17 * You should have received a copy of the GNU General Public License | |
18 * along with this program; if not, write to the Free Software | |
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
20 * | |
21 */ | |
9030 | 22 |
23 #include "blist.h" | |
24 | |
7395 | 25 #include "internal.h" |
10684
72a5babfa8b4
[gaim-migrate @ 12231]
Luke Schierer <lschiere@pidgin.im>
parents:
10112
diff
changeset
|
26 #include "cipher.h" |
7395 | 27 #include "debug.h" |
28 #include "ft.h" | |
8231
f50c059b6384
[gaim-migrate @ 8954]
Christian Hammond <chipx86@chipx86.com>
parents:
8135
diff
changeset
|
29 #include "network.h" |
7395 | 30 #include "notify.h" |
31 | |
32 #include "buddy.h" | |
8312 | 33 #include "disco.h" |
7395 | 34 #include "jabber.h" |
35 #include "iq.h" | |
36 #include "si.h" | |
37 | |
38 #include "si.h" | |
39 | |
8262 | 40 struct bytestreams_streamhost { |
41 char *jid; | |
42 char *host; | |
43 int port; | |
44 }; | |
45 | |
46 typedef struct _JabberSIXfer { | |
47 JabberStream *js; | |
48 | |
10940 | 49 gboolean accepted; |
50 | |
8262 | 51 char *stream_id; |
52 char *iq_id; | |
53 | |
54 enum { | |
55 STREAM_METHOD_UNKNOWN = 0, | |
56 STREAM_METHOD_BYTESTREAMS = 2 << 1, | |
57 STREAM_METHOD_IBB = 2 << 2, | |
58 STREAM_METHOD_UNSUPPORTED = 2 << 31 | |
59 } stream_method; | |
60 | |
61 GList *streamhosts; | |
62 GaimProxyInfo *gpi; | |
8316 | 63 |
64 char *rxqueue; | |
65 size_t rxlen; | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
66 gsize rxmaxlen; |
8262 | 67 } JabberSIXfer; |
68 | |
69 static GaimXfer* | |
70 jabber_si_xfer_find(JabberStream *js, const char *sid, const char *from) | |
7395 | 71 { |
72 GList *xfers; | |
73 | |
8262 | 74 if(!sid || !from) |
7395 | 75 return NULL; |
76 | |
77 for(xfers = js->file_transfers; xfers; xfers = xfers->next) { | |
78 GaimXfer *xfer = xfers->data; | |
79 JabberSIXfer *jsx = xfer->data; | |
8316 | 80 if(jsx->stream_id && xfer->who && |
81 !strcmp(jsx->stream_id, sid) && !strcmp(xfer->who, from)) | |
7395 | 82 return xfer; |
83 } | |
84 | |
85 return NULL; | |
86 } | |
87 | |
8262 | 88 |
89 static void jabber_si_bytestreams_attempt_connect(GaimXfer *xfer); | |
90 | |
91 static void jabber_si_bytestreams_connect_cb(gpointer data, gint source, GaimInputCondition cond) | |
92 { | |
7395 | 93 GaimXfer *xfer = data; |
94 JabberSIXfer *jsx = xfer->data; | |
8262 | 95 JabberIq *iq; |
96 xmlnode *query, *su; | |
97 struct bytestreams_streamhost *streamhost = jsx->streamhosts->data; | |
7395 | 98 |
8262 | 99 gaim_proxy_info_destroy(jsx->gpi); |
100 | |
101 if(source < 0) { | |
102 jsx->streamhosts = g_list_remove(jsx->streamhosts, streamhost); | |
103 g_free(streamhost->jid); | |
104 g_free(streamhost->host); | |
105 g_free(streamhost); | |
106 jabber_si_bytestreams_attempt_connect(xfer); | |
107 return; | |
108 } | |
109 | |
110 iq = jabber_iq_new_query(jsx->js, JABBER_IQ_RESULT, "http://jabber.org/protocol/bytestreams"); | |
111 xmlnode_set_attrib(iq->node, "to", xfer->who); | |
112 jabber_iq_set_id(iq, jsx->iq_id); | |
113 query = xmlnode_get_child(iq->node, "query"); | |
114 su = xmlnode_new_child(query, "streamhost-used"); | |
115 xmlnode_set_attrib(su, "jid", streamhost->jid); | |
116 | |
117 jabber_iq_send(iq); | |
118 | |
119 gaim_xfer_start(xfer, source, NULL, -1); | |
120 } | |
121 | |
122 static void jabber_si_bytestreams_attempt_connect(GaimXfer *xfer) | |
123 { | |
124 JabberSIXfer *jsx = xfer->data; | |
125 struct bytestreams_streamhost *streamhost; | |
126 char *dstaddr, *p; | |
127 int i; | |
128 unsigned char hashval[20]; | |
129 | |
130 if(!jsx->streamhosts) { | |
131 JabberIq *iq = jabber_iq_new(jsx->js, JABBER_IQ_ERROR); | |
132 xmlnode *error, *condition; | |
133 | |
134 if(jsx->iq_id) | |
135 jabber_iq_set_id(iq, jsx->iq_id); | |
136 | |
137 xmlnode_set_attrib(iq->node, "to", xfer->who); | |
138 error = xmlnode_new_child(iq->node, "error"); | |
139 xmlnode_set_attrib(error, "code", "404"); | |
140 xmlnode_set_attrib(error, "type", "cancel"); | |
141 condition = xmlnode_new_child(error, "condition"); | |
13806 | 142 xmlnode_set_namespace(condition, "urn:ietf:params:xml:ns:xmpp-stanzas"); |
8262 | 143 xmlnode_new_child(condition, "item-not-found"); |
144 | |
145 jabber_iq_send(iq); | |
146 | |
147 gaim_xfer_cancel_local(xfer); | |
148 | |
149 return; | |
150 } | |
151 | |
152 streamhost = jsx->streamhosts->data; | |
7395 | 153 |
8262 | 154 jsx->gpi = gaim_proxy_info_new(); |
155 gaim_proxy_info_set_type(jsx->gpi, GAIM_PROXY_SOCKS5); | |
156 gaim_proxy_info_set_host(jsx->gpi, streamhost->host); | |
157 gaim_proxy_info_set_port(jsx->gpi, streamhost->port); | |
158 | |
159 dstaddr = g_strdup_printf("%s%s%s@%s/%s", jsx->stream_id, xfer->who, jsx->js->user->node, | |
160 jsx->js->user->domain, jsx->js->user->resource); | |
10684
72a5babfa8b4
[gaim-migrate @ 12231]
Luke Schierer <lschiere@pidgin.im>
parents:
10112
diff
changeset
|
161 |
11183 | 162 gaim_cipher_digest_region("sha1", (guchar *)dstaddr, strlen(dstaddr), |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
163 sizeof(hashval), hashval, NULL); |
8262 | 164 g_free(dstaddr); |
165 dstaddr = g_malloc(41); | |
166 p = dstaddr; | |
167 for(i=0; i<20; i++, p+=2) | |
168 snprintf(p, 3, "%02x", hashval[i]); | |
169 | |
170 gaim_proxy_connect_socks5(jsx->gpi, dstaddr, 0, jabber_si_bytestreams_connect_cb, xfer); | |
171 g_free(dstaddr); | |
172 } | |
173 | |
174 void jabber_bytestreams_parse(JabberStream *js, xmlnode *packet) | |
175 { | |
176 GaimXfer *xfer; | |
177 JabberSIXfer *jsx; | |
178 xmlnode *query, *streamhost; | |
179 const char *sid, *from; | |
180 | |
181 if(!(from = xmlnode_get_attrib(packet, "from"))) | |
182 return; | |
183 | |
184 if(!(query = xmlnode_get_child(packet, "query"))) | |
185 return; | |
186 | |
187 if(!(sid = xmlnode_get_attrib(query, "sid"))) | |
188 return; | |
189 | |
190 if(!(xfer = jabber_si_xfer_find(js, sid, from))) | |
191 return; | |
192 | |
193 jsx = xfer->data; | |
10940 | 194 |
195 if(!jsx->accepted) | |
196 return; | |
197 | |
8262 | 198 if(jsx->iq_id) |
199 g_free(jsx->iq_id); | |
200 jsx->iq_id = g_strdup(xmlnode_get_attrib(packet, "id")); | |
201 | |
202 for(streamhost = xmlnode_get_child(query, "streamhost"); streamhost; | |
203 streamhost = xmlnode_get_next_twin(streamhost)) { | |
204 const char *jid, *host, *port; | |
205 int portnum; | |
206 | |
207 if((jid = xmlnode_get_attrib(streamhost, "jid")) && | |
208 (host = xmlnode_get_attrib(streamhost, "host")) && | |
209 (port = xmlnode_get_attrib(streamhost, "port")) && | |
210 (portnum = atoi(port))) { | |
211 struct bytestreams_streamhost *sh = g_new0(struct bytestreams_streamhost, 1); | |
212 sh->jid = g_strdup(jid); | |
213 sh->host = g_strdup(host); | |
214 sh->port = portnum; | |
215 jsx->streamhosts = g_list_append(jsx->streamhosts, sh); | |
216 } | |
217 } | |
218 | |
219 jabber_si_bytestreams_attempt_connect(xfer); | |
7395 | 220 } |
221 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
222 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
223 static void |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
224 jabber_si_xfer_bytestreams_send_read_again_resp_cb(gpointer data, gint source, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
225 GaimInputCondition cond) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
226 { |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
227 GaimXfer *xfer = data; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
228 JabberSIXfer *jsx = xfer->data; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
229 int len; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
230 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
231 len = write(source, jsx->rxqueue + jsx->rxlen, jsx->rxmaxlen - jsx->rxlen); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
232 if (len < 0 && errno == EAGAIN) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
233 return; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
234 else if (len < 0) { |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
235 gaim_input_remove(xfer->watcher); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
236 xfer->watcher = 0; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
237 g_free(jsx->rxqueue); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
238 jsx->rxqueue = NULL; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
239 close(source); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
240 gaim_xfer_cancel_remote(xfer); |
13440 | 241 return; |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
242 } |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
243 jsx->rxlen += len; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
244 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
245 if (jsx->rxlen < jsx->rxmaxlen) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
246 return; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
247 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
248 gaim_input_remove(xfer->watcher); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
249 xfer->watcher = 0; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
250 g_free(jsx->rxqueue); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
251 jsx->rxqueue = NULL; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
252 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
253 gaim_xfer_start(xfer, source, NULL, -1); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
254 } |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
255 |
8312 | 256 static void |
8316 | 257 jabber_si_xfer_bytestreams_send_read_again_cb(gpointer data, gint source, |
8312 | 258 GaimInputCondition cond) |
259 { | |
260 GaimXfer *xfer = data; | |
8316 | 261 JabberSIXfer *jsx = xfer->data; |
8312 | 262 int i; |
8316 | 263 char buffer[256]; |
264 int len; | |
265 char *dstaddr, *p; | |
266 unsigned char hashval[20]; | |
267 const char *host; | |
268 | |
269 gaim_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_read_again_cb\n"); | |
8312 | 270 |
8316 | 271 if(jsx->rxlen < 5) { |
272 gaim_debug_info("jabber", "reading the first 5 bytes\n"); | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
273 len = read(source, buffer, 5 - jsx->rxlen); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
274 if(len < 0 && errno == EAGAIN) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
275 return; |
13786
5ddde4ad1ca2
[gaim-migrate @ 16198]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13492
diff
changeset
|
276 else if(len <= 0) { |
8316 | 277 gaim_input_remove(xfer->watcher); |
278 xfer->watcher = 0; | |
279 close(source); | |
280 gaim_xfer_cancel_remote(xfer); | |
281 return; | |
282 } | |
283 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen); | |
284 memcpy(jsx->rxqueue + jsx->rxlen, buffer, len); | |
285 jsx->rxlen += len; | |
286 return; | |
287 } else if(jsx->rxqueue[0] != 0x05 || jsx->rxqueue[1] != 0x01 || | |
288 jsx->rxqueue[3] != 0x03) { | |
289 gaim_debug_info("jabber", "invalid socks5 stuff\n"); | |
290 gaim_input_remove(xfer->watcher); | |
291 xfer->watcher = 0; | |
292 close(source); | |
293 gaim_xfer_cancel_remote(xfer); | |
294 return; | |
295 } else if(jsx->rxlen - 5 < jsx->rxqueue[4] + 2) { | |
296 gaim_debug_info("jabber", "reading umpteen more bytes\n"); | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
297 len = read(source, buffer, jsx->rxqueue[4] + 5 + 2 - jsx->rxlen); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
298 if(len < 0 && errno == EAGAIN) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
299 return; |
13786
5ddde4ad1ca2
[gaim-migrate @ 16198]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13492
diff
changeset
|
300 else if(len <= 0) { |
8316 | 301 gaim_input_remove(xfer->watcher); |
302 xfer->watcher = 0; | |
303 close(source); | |
304 gaim_xfer_cancel_remote(xfer); | |
305 return; | |
306 } | |
307 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen); | |
308 memcpy(jsx->rxqueue + jsx->rxlen, buffer, len); | |
309 jsx->rxlen += len; | |
310 } | |
8312 | 311 |
8316 | 312 if(jsx->rxlen - 5 < jsx->rxqueue[4] + 2) |
313 return; | |
314 | |
315 gaim_input_remove(xfer->watcher); | |
316 xfer->watcher = 0; | |
8312 | 317 |
8316 | 318 dstaddr = g_strdup_printf("%s%s@%s/%s%s", jsx->stream_id, |
319 jsx->js->user->node, jsx->js->user->domain, | |
320 jsx->js->user->resource, xfer->who); | |
10684
72a5babfa8b4
[gaim-migrate @ 12231]
Luke Schierer <lschiere@pidgin.im>
parents:
10112
diff
changeset
|
321 |
11183 | 322 gaim_cipher_digest_region("sha1", (guchar *)dstaddr, strlen(dstaddr), |
10687
b256ce6b85b8
[gaim-migrate @ 12235]
Etan Reisner <pidgin@unreliablesource.net>
parents:
10684
diff
changeset
|
323 sizeof(hashval), hashval, NULL); |
8316 | 324 g_free(dstaddr); |
325 dstaddr = g_malloc(41); | |
326 p = dstaddr; | |
327 for(i=0; i<20; i++, p+=2) | |
328 snprintf(p, 3, "%02x", hashval[i]); | |
329 | |
330 if(jsx->rxqueue[4] != 40 || strncmp(dstaddr, jsx->rxqueue+5, 40) || | |
331 jsx->rxqueue[45] != 0x00 || jsx->rxqueue[46] != 0x00) { | |
332 gaim_debug_error("jabber", "someone connected with the wrong info!\n"); | |
8312 | 333 close(source); |
334 gaim_xfer_cancel_remote(xfer); | |
335 return; | |
336 } | |
337 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
338 g_free(jsx->rxqueue); |
8838 | 339 host = gaim_network_get_my_ip(jsx->js->fd); |
8316 | 340 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
341 jsx->rxmaxlen = 5 + strlen(host) + 2; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
342 jsx->rxqueue = g_malloc(jsx->rxmaxlen); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
343 jsx->rxlen = 0; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
344 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
345 jsx->rxqueue[0] = 0x05; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
346 jsx->rxqueue[1] = 0x00; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
347 jsx->rxqueue[2] = 0x00; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
348 jsx->rxqueue[3] = 0x03; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
349 jsx->rxqueue[4] = strlen(host); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
350 memcpy(jsx->rxqueue + 5, host, strlen(host)); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
351 jsx->rxqueue[5+strlen(host)] = 0x00; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
352 jsx->rxqueue[6+strlen(host)] = 0x00; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
353 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
354 xfer->watcher = gaim_input_add(source, GAIM_INPUT_WRITE, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
355 jabber_si_xfer_bytestreams_send_read_again_resp_cb, xfer); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
356 jabber_si_xfer_bytestreams_send_read_again_resp_cb(xfer, source, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
357 GAIM_INPUT_WRITE); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
358 } |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
359 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
360 static void |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
361 jabber_si_xfer_bytestreams_send_read_response_cb(gpointer data, gint source, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
362 GaimInputCondition cond) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
363 { |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
364 GaimXfer *xfer = data; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
365 JabberSIXfer *jsx = xfer->data; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
366 int len; |
8316 | 367 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
368 len = write(source, jsx->rxqueue + jsx->rxlen, jsx->rxmaxlen - jsx->rxlen); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
369 if (len < 0 && errno == EAGAIN) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
370 return; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
371 else if (len < 0) { |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
372 gaim_input_remove(xfer->watcher); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
373 xfer->watcher = 0; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
374 g_free(jsx->rxqueue); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
375 jsx->rxqueue = NULL; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
376 close(source); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
377 gaim_xfer_cancel_remote(xfer); |
13492
59ea9ddd408b
[gaim-migrate @ 15868]
Richard Laager <rlaager@wiktel.com>
parents:
13440
diff
changeset
|
378 return; |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
379 } |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
380 jsx->rxlen += len; |
8316 | 381 |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
382 if (jsx->rxlen < jsx->rxmaxlen) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
383 return; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
384 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
385 gaim_input_remove(xfer->watcher); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
386 xfer->watcher = 0; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
387 |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
388 if (jsx->rxqueue[1] == 0x00) { |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
389 xfer->watcher = gaim_input_add(source, GAIM_INPUT_READ, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
390 jabber_si_xfer_bytestreams_send_read_again_cb, xfer); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
391 g_free(jsx->rxqueue); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
392 jsx->rxqueue = NULL; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
393 } else { |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
394 close(source); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
395 gaim_xfer_cancel_remote(xfer); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
396 } |
8316 | 397 } |
398 | |
399 static void | |
400 jabber_si_xfer_bytestreams_send_read_cb(gpointer data, gint source, | |
401 GaimInputCondition cond) | |
402 { | |
403 GaimXfer *xfer = data; | |
404 JabberSIXfer *jsx = xfer->data; | |
405 int i; | |
406 int len; | |
407 char buffer[256]; | |
408 | |
409 gaim_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_read_cb\n"); | |
410 | |
411 xfer->fd = source; | |
412 | |
413 if(jsx->rxlen < 2) { | |
414 gaim_debug_info("jabber", "reading those first two bytes\n"); | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
415 len = read(source, buffer, 2 - jsx->rxlen); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
416 if(len < 0 && errno == EAGAIN) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
417 return; |
13786
5ddde4ad1ca2
[gaim-migrate @ 16198]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13492
diff
changeset
|
418 else if(len <= 0) { |
8316 | 419 gaim_input_remove(xfer->watcher); |
420 xfer->watcher = 0; | |
421 close(source); | |
422 gaim_xfer_cancel_remote(xfer); | |
423 return; | |
424 } | |
425 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen); | |
426 memcpy(jsx->rxqueue + jsx->rxlen, buffer, len); | |
427 jsx->rxlen += len; | |
428 return; | |
429 } else if(jsx->rxlen - 2 < jsx->rxqueue[1]) { | |
430 gaim_debug_info("jabber", "reading the next umpteen bytes\n"); | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
431 len = read(source, buffer, jsx->rxqueue[1] + 2 - jsx->rxlen); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
432 if(len < 0 && errno == EAGAIN) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
433 return; |
13786
5ddde4ad1ca2
[gaim-migrate @ 16198]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13492
diff
changeset
|
434 else if(len <= 0) { |
8316 | 435 gaim_input_remove(xfer->watcher); |
436 xfer->watcher = 0; | |
437 close(source); | |
438 gaim_xfer_cancel_remote(xfer); | |
439 return; | |
440 } | |
441 jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen); | |
442 memcpy(jsx->rxqueue + jsx->rxlen, buffer, len); | |
443 jsx->rxlen += len; | |
444 } | |
445 | |
446 if(jsx->rxlen -2 < jsx->rxqueue[1]) | |
447 return; | |
448 | |
449 gaim_input_remove(xfer->watcher); | |
450 xfer->watcher = 0; | |
451 | |
452 gaim_debug_info("jabber", "checking to make sure we're socks FIVE\n"); | |
453 | |
454 if(jsx->rxqueue[0] != 0x05) { | |
455 close(source); | |
456 gaim_xfer_cancel_remote(xfer); | |
457 return; | |
458 } | |
459 | |
460 gaim_debug_info("jabber", "going to test %hhu different methods\n", jsx->rxqueue[1]); | |
461 | |
462 for(i=0; i<jsx->rxqueue[1]; i++) { | |
463 | |
464 gaim_debug_info("jabber", "testing %hhu\n", jsx->rxqueue[i+2]); | |
465 if(jsx->rxqueue[i+2] == 0x00) { | |
466 g_free(jsx->rxqueue); | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
467 jsx->rxlen = 0; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
468 jsx->rxmaxlen = 2; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
469 jsx->rxqueue = g_malloc(jsx->rxmaxlen); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
470 jsx->rxqueue[0] = 0x05; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
471 jsx->rxqueue[1] = 0x00; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
472 xfer->watcher = gaim_input_add(source, GAIM_INPUT_WRITE, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
473 jabber_si_xfer_bytestreams_send_read_response_cb, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
474 xfer); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
475 jabber_si_xfer_bytestreams_send_read_response_cb(xfer, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
476 source, GAIM_INPUT_WRITE); |
8316 | 477 jsx->rxqueue = NULL; |
478 jsx->rxlen = 0; | |
8312 | 479 return; |
480 } | |
481 } | |
482 | |
8316 | 483 g_free(jsx->rxqueue); |
484 jsx->rxlen = 0; | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
485 jsx->rxmaxlen = 2; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
486 jsx->rxqueue = g_malloc(jsx->rxmaxlen); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
487 jsx->rxqueue[0] = 0x05; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
488 jsx->rxqueue[1] = 0xFF; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
489 xfer->watcher = gaim_input_add(source, GAIM_INPUT_WRITE, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
490 jabber_si_xfer_bytestreams_send_read_response_cb, xfer); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
491 jabber_si_xfer_bytestreams_send_read_response_cb(xfer, |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
492 source, GAIM_INPUT_WRITE); |
8312 | 493 } |
494 | |
495 static void | |
8316 | 496 jabber_si_xfer_bytestreams_send_connected_cb(gpointer data, gint source, |
497 GaimInputCondition cond) | |
498 { | |
499 GaimXfer *xfer = data; | |
500 int acceptfd; | |
501 | |
502 gaim_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_connected_cb\n"); | |
503 | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
504 acceptfd = accept(source, NULL, 0); |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
505 if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
506 return; |
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
507 else if(acceptfd == -1) { |
8316 | 508 gaim_debug_warning("jabber", "accept: %s\n", strerror(errno)); |
509 return; | |
510 } | |
511 | |
512 gaim_input_remove(xfer->watcher); | |
513 close(source); | |
514 | |
515 xfer->watcher = gaim_input_add(acceptfd, GAIM_INPUT_READ, | |
516 jabber_si_xfer_bytestreams_send_read_cb, xfer); | |
517 } | |
518 | |
519 static void | |
12909
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
520 jabber_si_xfer_bytestreams_listen_cb(int sock, gpointer data) |
8312 | 521 { |
12909
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
522 GaimXfer *xfer = data; |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
523 JabberSIXfer *jsx; |
8312 | 524 JabberIq *iq; |
525 xmlnode *query, *streamhost; | |
526 char *jid, *port; | |
12909
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
527 |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
528 if (gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_CANCEL_LOCAL) { |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
529 gaim_xfer_unref(xfer); |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
530 return; |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
531 } |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
532 |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
533 jsx = xfer->data; |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
534 |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
535 gaim_xfer_unref(xfer); |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
536 |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
537 if (sock < 0) { |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
538 gaim_xfer_cancel_local(xfer); |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
539 return; |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
540 } |
8312 | 541 |
542 iq = jabber_iq_new_query(jsx->js, JABBER_IQ_SET, | |
543 "http://jabber.org/protocol/bytestreams"); | |
544 xmlnode_set_attrib(iq->node, "to", xfer->who); | |
545 query = xmlnode_get_child(iq->node, "query"); | |
546 | |
547 xmlnode_set_attrib(query, "sid", jsx->stream_id); | |
548 | |
549 streamhost = xmlnode_new_child(query, "streamhost"); | |
12909
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
550 jid = g_strdup_printf("%s@%s/%s", jsx->js->user->node, |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
551 jsx->js->user->domain, jsx->js->user->resource); |
8312 | 552 xmlnode_set_attrib(streamhost, "jid", jid); |
553 g_free(jid); | |
554 | |
12909
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
555 /* XXX: shouldn't we use the public IP or something? here */ |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
556 xmlnode_set_attrib(streamhost, "host", |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
557 gaim_network_get_my_ip(jsx->js->fd)); |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
558 xfer->local_port = gaim_network_get_port_from_fd(sock); |
8316 | 559 port = g_strdup_printf("%hu", xfer->local_port); |
8312 | 560 xmlnode_set_attrib(streamhost, "port", port); |
561 g_free(port); | |
562 | |
12909
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
563 xfer->watcher = gaim_input_add(sock, GAIM_INPUT_READ, |
8312 | 564 jabber_si_xfer_bytestreams_send_connected_cb, xfer); |
565 | |
566 /* XXX: insert proxies here */ | |
567 | |
568 /* XXX: callback to find out which streamhost they used, or see if they | |
569 * screwed it up */ | |
570 jabber_iq_send(iq); | |
12909
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
571 |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
572 } |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
573 |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
574 static void |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
575 jabber_si_xfer_bytestreams_send_init(GaimXfer *xfer) |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
576 { |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
577 gaim_xfer_ref(xfer); |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
578 |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
579 if(!gaim_network_listen_range(0, 0, SOCK_STREAM, |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
580 jabber_si_xfer_bytestreams_listen_cb, xfer)) { |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
581 gaim_xfer_unref(xfer); |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
582 /* XXX: couldn't open a port, we're fscked */ |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
583 gaim_xfer_cancel_local(xfer); |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
584 return; |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
585 } |
8e3b85fe4a55
[gaim-migrate @ 15262]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
12730
diff
changeset
|
586 |
8312 | 587 } |
588 | |
589 static void jabber_si_xfer_send_method_cb(JabberStream *js, xmlnode *packet, | |
590 gpointer data) | |
591 { | |
592 GaimXfer *xfer = data; | |
593 xmlnode *si, *feature, *x, *field, *value; | |
594 | |
595 if(!(si = xmlnode_get_child_with_namespace(packet, "si", "http://jabber.org/protocol/si"))) { | |
596 gaim_xfer_cancel_remote(xfer); | |
597 return; | |
598 } | |
599 | |
600 if(!(feature = xmlnode_get_child_with_namespace(si, "feature", "http://jabber.org/protocol/feature-neg"))) { | |
601 gaim_xfer_cancel_remote(xfer); | |
602 return; | |
603 } | |
604 | |
605 if(!(x = xmlnode_get_child_with_namespace(feature, "x", "jabber:x:data"))) { | |
606 gaim_xfer_cancel_remote(xfer); | |
607 return; | |
608 } | |
609 | |
610 for(field = xmlnode_get_child(x, "field"); field; field = xmlnode_get_next_twin(field)) { | |
611 const char *var = xmlnode_get_attrib(field, "var"); | |
612 | |
613 if(var && !strcmp(var, "stream-method")) { | |
614 if((value = xmlnode_get_child(field, "value"))) { | |
615 char *val = xmlnode_get_data(value); | |
616 if(val && !strcmp(val, "http://jabber.org/protocol/bytestreams")) { | |
617 jabber_si_xfer_bytestreams_send_init(xfer); | |
618 g_free(val); | |
619 return; | |
620 } | |
621 g_free(val); | |
622 } | |
623 } | |
624 } | |
625 gaim_xfer_cancel_remote(xfer); | |
626 } | |
627 | |
628 static void jabber_si_xfer_send_request(GaimXfer *xfer) | |
629 { | |
630 JabberSIXfer *jsx = xfer->data; | |
631 JabberIq *iq; | |
632 xmlnode *si, *file, *feature, *x, *field, *option, *value; | |
633 char buf[32]; | |
634 | |
635 xfer->filename = g_path_get_basename(xfer->local_filename); | |
636 | |
637 iq = jabber_iq_new(jsx->js, JABBER_IQ_SET); | |
638 xmlnode_set_attrib(iq->node, "to", xfer->who); | |
639 si = xmlnode_new_child(iq->node, "si"); | |
13806 | 640 xmlnode_set_namespace(si, "http://jabber.org/protocol/si"); |
8312 | 641 jsx->stream_id = jabber_get_next_id(jsx->js); |
642 xmlnode_set_attrib(si, "id", jsx->stream_id); | |
643 xmlnode_set_attrib(si, "profile", | |
644 "http://jabber.org/protocol/si/profile/file-transfer"); | |
645 | |
646 file = xmlnode_new_child(si, "file"); | |
13806 | 647 xmlnode_set_namespace(file, |
8312 | 648 "http://jabber.org/protocol/si/profile/file-transfer"); |
649 xmlnode_set_attrib(file, "name", xfer->filename); | |
11656
f9c5480ad0ce
[gaim-migrate @ 13940]
Richard Laager <rlaager@wiktel.com>
parents:
11183
diff
changeset
|
650 g_snprintf(buf, sizeof(buf), "%" G_GSIZE_FORMAT, xfer->size); |
8312 | 651 xmlnode_set_attrib(file, "size", buf); |
652 /* maybe later we'll do hash and date attribs */ | |
653 | |
654 feature = xmlnode_new_child(si, "feature"); | |
13806 | 655 xmlnode_set_namespace(feature, |
8312 | 656 "http://jabber.org/protocol/feature-neg"); |
657 x = xmlnode_new_child(feature, "x"); | |
13806 | 658 xmlnode_set_namespace(x, "jabber:x:data"); |
8312 | 659 xmlnode_set_attrib(x, "type", "form"); |
660 field = xmlnode_new_child(x, "field"); | |
661 xmlnode_set_attrib(field, "var", "stream-method"); | |
662 xmlnode_set_attrib(field, "type", "list-single"); | |
663 option = xmlnode_new_child(field, "option"); | |
664 value = xmlnode_new_child(option, "value"); | |
665 xmlnode_insert_data(value, "http://jabber.org/protocol/bytestreams", | |
666 -1); | |
667 /* | |
668 option = xmlnode_new_child(field, "option"); | |
669 value = xmlnode_new_child(option, "value"); | |
670 xmlnode_insert_data(value, "http://jabber.org/protocol/ibb", -1); | |
671 */ | |
672 | |
673 jabber_iq_set_callback(iq, jabber_si_xfer_send_method_cb, xfer); | |
674 | |
675 jabber_iq_send(iq); | |
676 } | |
677 | |
8316 | 678 static void jabber_si_xfer_free(GaimXfer *xfer) |
8312 | 679 { |
8316 | 680 JabberSIXfer *jsx = xfer->data; |
681 JabberStream *js = jsx->js; | |
682 | |
683 js->file_transfers = g_list_remove(js->file_transfers, xfer); | |
684 | |
685 g_free(jsx->stream_id); | |
686 g_free(jsx->iq_id); | |
687 /* XXX: free other stuff */ | |
13200
33bef17125c2
[gaim-migrate @ 15563]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
13145
diff
changeset
|
688 g_free(jsx->rxqueue); |
8316 | 689 g_free(jsx); |
690 xfer->data = NULL; | |
691 } | |
692 | |
693 static void jabber_si_xfer_cancel_send(GaimXfer *xfer) | |
694 { | |
695 jabber_si_xfer_free(xfer); | |
8312 | 696 gaim_debug(GAIM_DEBUG_INFO, "jabber", "in jabber_si_xfer_cancel_send\n"); |
697 } | |
698 | |
699 | |
13145
bfd7b9e3c705
[gaim-migrate @ 15508]
Richard Laager <rlaager@wiktel.com>
parents:
12936
diff
changeset
|
700 static void jabber_si_xfer_request_denied(GaimXfer *xfer) |
bfd7b9e3c705
[gaim-migrate @ 15508]
Richard Laager <rlaager@wiktel.com>
parents:
12936
diff
changeset
|
701 { |
bfd7b9e3c705
[gaim-migrate @ 15508]
Richard Laager <rlaager@wiktel.com>
parents:
12936
diff
changeset
|
702 jabber_si_xfer_free(xfer); |
bfd7b9e3c705
[gaim-migrate @ 15508]
Richard Laager <rlaager@wiktel.com>
parents:
12936
diff
changeset
|
703 gaim_debug(GAIM_DEBUG_INFO, "jabber", "in jabber_si_xfer_request_denied\n"); |
bfd7b9e3c705
[gaim-migrate @ 15508]
Richard Laager <rlaager@wiktel.com>
parents:
12936
diff
changeset
|
704 } |
bfd7b9e3c705
[gaim-migrate @ 15508]
Richard Laager <rlaager@wiktel.com>
parents:
12936
diff
changeset
|
705 |
bfd7b9e3c705
[gaim-migrate @ 15508]
Richard Laager <rlaager@wiktel.com>
parents:
12936
diff
changeset
|
706 |
8316 | 707 static void jabber_si_xfer_cancel_recv(GaimXfer *xfer) |
8312 | 708 { |
8316 | 709 jabber_si_xfer_free(xfer); |
8312 | 710 gaim_debug(GAIM_DEBUG_INFO, "jabber", "in jabber_si_xfer_cancel_recv\n"); |
711 } | |
712 | |
713 | |
8316 | 714 static void jabber_si_xfer_end(GaimXfer *xfer) |
715 { | |
716 jabber_si_xfer_free(xfer); | |
717 } | |
718 | |
719 | |
8312 | 720 static void jabber_si_xfer_send_disco_cb(JabberStream *js, const char *who, |
721 JabberCapabilities capabilities, gpointer data) | |
722 { | |
723 GaimXfer *xfer = data; | |
724 | |
725 if(capabilities & JABBER_CAP_SI_FILE_XFER) { | |
726 jabber_si_xfer_send_request(xfer); | |
727 } else { | |
728 char *msg = g_strdup_printf(_("Unable to send file to %s, user does not support file transfers"), who); | |
729 gaim_notify_error(js->gc, _("File Send Failed"), | |
730 _("File Send Failed"), msg); | |
731 g_free(msg); | |
732 } | |
733 } | |
734 | |
8262 | 735 static void jabber_si_xfer_init(GaimXfer *xfer) |
736 { | |
737 JabberSIXfer *jsx = xfer->data; | |
738 JabberIq *iq; | |
8312 | 739 if(gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) { |
740 JabberBuddy *jb; | |
741 JabberBuddyResource *jbr = NULL; | |
742 | |
743 jb = jabber_buddy_find(jsx->js, xfer->who, TRUE); | |
744 /* XXX */ | |
745 if(!jb) | |
746 return; | |
8262 | 747 |
8312 | 748 /* XXX: for now, send to the first resource available */ |
749 if(g_list_length(jb->resources) >= 1) { | |
12936
0f3122ce84db
[gaim-migrate @ 15289]
Richard Laager <rlaager@wiktel.com>
parents:
12935
diff
changeset
|
750 char **who_v = g_strsplit(xfer->who, "/", 2); |
8312 | 751 char *who; |
12935
d9c53c5f5912
[gaim-migrate @ 15288]
Richard Laager <rlaager@wiktel.com>
parents:
12909
diff
changeset
|
752 |
8316 | 753 jbr = jabber_buddy_find_resource(jb, NULL); |
12935
d9c53c5f5912
[gaim-migrate @ 15288]
Richard Laager <rlaager@wiktel.com>
parents:
12909
diff
changeset
|
754 who = g_strdup_printf("%s/%s", who_v[0], jbr->name); |
d9c53c5f5912
[gaim-migrate @ 15288]
Richard Laager <rlaager@wiktel.com>
parents:
12909
diff
changeset
|
755 g_strfreev(who_v); |
8312 | 756 g_free(xfer->who); |
757 xfer->who = who; | |
758 jabber_disco_info_do(jsx->js, who, | |
759 jabber_si_xfer_send_disco_cb, xfer); | |
760 } else { | |
761 return; /* XXX: ick */ | |
762 } | |
763 } else { | |
764 xmlnode *si, *feature, *x, *field, *value; | |
8262 | 765 |
8312 | 766 iq = jabber_iq_new(jsx->js, JABBER_IQ_RESULT); |
767 xmlnode_set_attrib(iq->node, "to", xfer->who); | |
768 if(jsx->iq_id) | |
769 jabber_iq_set_id(iq, jsx->iq_id); | |
770 | |
10940 | 771 jsx->accepted = TRUE; |
772 | |
8312 | 773 si = xmlnode_new_child(iq->node, "si"); |
13806 | 774 xmlnode_set_namespace(si, "http://jabber.org/protocol/si"); |
8312 | 775 |
776 feature = xmlnode_new_child(si, "feature"); | |
13806 | 777 xmlnode_set_namespace(feature, "http://jabber.org/protocol/feature-neg"); |
8262 | 778 |
8312 | 779 x = xmlnode_new_child(feature, "x"); |
13806 | 780 xmlnode_set_namespace(x, "jabber:x:data"); |
8343 | 781 xmlnode_set_attrib(x, "type", "submit"); |
8262 | 782 |
8312 | 783 field = xmlnode_new_child(x, "field"); |
784 xmlnode_set_attrib(field, "var", "stream-method"); | |
785 | |
786 value = xmlnode_new_child(field, "value"); | |
787 if(jsx->stream_method & STREAM_METHOD_BYTESTREAMS) | |
788 xmlnode_insert_data(value, "http://jabber.org/protocol/bytestreams", -1); | |
789 /* | |
790 else if(jsx->stream_method & STREAM_METHOD_IBB) | |
8262 | 791 xmlnode_insert_data(value, "http://jabber.org/protocol/ibb", -1); |
792 */ | |
793 | |
8312 | 794 jabber_iq_send(iq); |
795 } | |
8262 | 796 } |
797 | |
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
798 GaimXfer *jabber_si_new_xfer(GaimConnection *gc, const char *who) |
8312 | 799 { |
9030 | 800 JabberStream *js; |
801 | |
8312 | 802 GaimXfer *xfer; |
803 JabberSIXfer *jsx; | |
804 | |
9030 | 805 js = gc->proto_data; |
806 | |
9466 | 807 xfer = gaim_xfer_new(gc->account, GAIM_XFER_SEND, who); |
8262 | 808 |
8312 | 809 xfer->data = jsx = g_new0(JabberSIXfer, 1); |
810 jsx->js = js; | |
8262 | 811 |
8312 | 812 gaim_xfer_set_init_fnc(xfer, jabber_si_xfer_init); |
813 gaim_xfer_set_cancel_send_fnc(xfer, jabber_si_xfer_cancel_send); | |
8316 | 814 gaim_xfer_set_end_fnc(xfer, jabber_si_xfer_end); |
8312 | 815 |
12143
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
816 js->file_transfers = g_list_append(js->file_transfers, xfer); |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
817 |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
818 return xfer; |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
819 } |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
820 |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
821 void jabber_si_xfer_send(GaimConnection *gc, const char *who, const char *file) |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
822 { |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
823 JabberStream *js; |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
824 |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
825 GaimXfer *xfer; |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
826 |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
827 js = gc->proto_data; |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
828 |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
829 if(!gaim_find_buddy(gc->account, who) || !jabber_buddy_find(js, who, FALSE)) |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
830 return; |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
831 |
cbebda5f019c
[gaim-migrate @ 14444]
Richard Laager <rlaager@wiktel.com>
parents:
11656
diff
changeset
|
832 xfer = jabber_si_new_xfer(gc, who); |
8312 | 833 |
9466 | 834 if (file) |
835 gaim_xfer_request_accepted(xfer, file); | |
836 else | |
837 gaim_xfer_request(xfer); | |
8262 | 838 } |
839 | |
840 void jabber_si_parse(JabberStream *js, xmlnode *packet) | |
841 { | |
842 JabberSIXfer *jsx; | |
843 GaimXfer *xfer; | |
844 xmlnode *si, *file, *feature, *x, *field, *option, *value; | |
10939 | 845 const char *stream_id, *filename, *filesize_c, *profile, *from; |
8262 | 846 size_t filesize = 0; |
847 | |
848 if(!(si = xmlnode_get_child(packet, "si"))) | |
849 return; | |
850 | |
851 if(!(profile = xmlnode_get_attrib(si, "profile")) || | |
852 strcmp(profile, "http://jabber.org/protocol/si/profile/file-transfer")) | |
853 return; | |
854 | |
855 if(!(stream_id = xmlnode_get_attrib(si, "id"))) | |
856 return; | |
857 | |
858 if(!(file = xmlnode_get_child(si, "file"))) | |
859 return; | |
860 | |
861 if(!(filename = xmlnode_get_attrib(file, "name"))) | |
862 return; | |
863 | |
864 if((filesize_c = xmlnode_get_attrib(file, "size"))) | |
865 filesize = atoi(filesize_c); | |
866 | |
867 if(!(feature = xmlnode_get_child(si, "feature"))) | |
868 return; | |
869 | |
870 if(!(x = xmlnode_get_child_with_namespace(feature, "x", "jabber:x:data"))) | |
871 return; | |
872 | |
10939 | 873 if(!(from = xmlnode_get_attrib(packet, "from"))) |
874 return; | |
875 | |
876 /* if they've already sent us this file transfer with the same damn id | |
877 * then we're gonna ignore it, until I think of something better to do | |
878 * with it */ | |
879 if((xfer = jabber_si_xfer_find(js, stream_id, from))) | |
880 return; | |
881 | |
8262 | 882 jsx = g_new0(JabberSIXfer, 1); |
883 | |
884 for(field = xmlnode_get_child(x, "field"); field; field = xmlnode_get_next_twin(field)) { | |
885 const char *var = xmlnode_get_attrib(field, "var"); | |
886 if(var && !strcmp(var, "stream-method")) { | |
887 for(option = xmlnode_get_child(field, "option"); option; | |
888 option = xmlnode_get_next_twin(option)) { | |
889 if((value = xmlnode_get_child(option, "value"))) { | |
890 char *val; | |
891 if((val = xmlnode_get_data(value))) { | |
892 if(!strcmp(val, "http://jabber.org/protocol/bytestreams")) { | |
893 jsx->stream_method |= STREAM_METHOD_BYTESTREAMS; | |
894 /* | |
895 } else if(!strcmp(val, "http://jabber.org/protocol/ibb")) { | |
896 jsx->stream_method |= STREAM_METHOD_IBB; | |
897 */ | |
898 } | |
899 g_free(val); | |
900 } | |
901 } | |
902 } | |
903 } | |
904 } | |
905 | |
906 if(jsx->stream_method == STREAM_METHOD_UNKNOWN) { | |
907 g_free(jsx); | |
908 return; | |
909 } | |
910 | |
911 jsx->js = js; | |
912 jsx->stream_id = g_strdup(stream_id); | |
913 jsx->iq_id = g_strdup(xmlnode_get_attrib(packet, "id")); | |
914 | |
10939 | 915 xfer = gaim_xfer_new(js->gc->account, GAIM_XFER_RECEIVE, from); |
8262 | 916 xfer->data = jsx; |
917 | |
918 gaim_xfer_set_filename(xfer, filename); | |
919 if(filesize > 0) | |
920 gaim_xfer_set_size(xfer, filesize); | |
921 | |
922 gaim_xfer_set_init_fnc(xfer, jabber_si_xfer_init); | |
13145
bfd7b9e3c705
[gaim-migrate @ 15508]
Richard Laager <rlaager@wiktel.com>
parents:
12936
diff
changeset
|
923 gaim_xfer_set_request_denied_fnc(xfer, jabber_si_xfer_request_denied); |
8316 | 924 gaim_xfer_set_cancel_recv_fnc(xfer, jabber_si_xfer_cancel_recv); |
925 gaim_xfer_set_end_fnc(xfer, jabber_si_xfer_end); | |
8262 | 926 |
927 js->file_transfers = g_list_append(js->file_transfers, xfer); | |
928 | |
929 gaim_xfer_request(xfer); | |
930 } | |
931 | |
7395 | 932 |