Mercurial > pidgin.yaz
comparison libpurple/protocols/bonjour/bonjour_ft.c @ 21465:e489c81e1f6f
Cleanup and fix the socks5 proxy connect address to be correct.
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Tue, 13 Nov 2007 02:20:58 +0000 |
parents | da75dd6c41fb |
children | 7a05b6f84545 |
comparison
equal
deleted
inserted
replaced
21464:577d90f8794e | 21465:e489c81e1f6f |
---|---|
28 #include "buddy.h" | 28 #include "buddy.h" |
29 #include "bonjour.h" | 29 #include "bonjour.h" |
30 #include "bonjour_ft.h" | 30 #include "bonjour_ft.h" |
31 #include "cipher.h" | 31 #include "cipher.h" |
32 | 32 |
33 static PurpleXfer* | |
34 bonjour_si_xfer_find(BonjourData *bd, const char *sid, const char *from); | |
35 static void | |
36 xep_ft_si_offer(PurpleXfer *xfer, const gchar *to); | |
37 static void | |
38 xep_ft_si_result(PurpleXfer *xfer, char *to); | |
39 static void | |
40 xep_ft_si_reject(PurpleXfer *xfer, char *to); | |
41 static void | |
42 xep_ft_si_reject2(BonjourData *bd, const char *to, const char *sid); | |
43 static void | 33 static void |
44 bonjour_bytestreams_init(PurpleXfer *xfer); | 34 bonjour_bytestreams_init(PurpleXfer *xfer); |
45 static void | 35 static void |
46 bonjour_bytestreams_listen(int sock, gpointer data); | |
47 static void | |
48 bonjour_sock5_request_cb(gpointer data, gint source, PurpleInputCondition cond); | |
49 static void | |
50 bonjour_bytestreams_connect(PurpleXfer *xfer); | 36 bonjour_bytestreams_connect(PurpleXfer *xfer); |
51 static void | |
52 bonjour_bytestreams_connect_cb(gpointer data, gint source, const gchar *error_message); | |
53 static void | 37 static void |
54 bonjour_xfer_init(PurpleXfer *xfer); | 38 bonjour_xfer_init(PurpleXfer *xfer); |
55 static void | 39 static void |
56 bonjour_xfer_receive(PurpleConnection *pc, const char *id, const char *from, | 40 bonjour_xfer_receive(PurpleConnection *pc, const char *id, const char *from, |
57 const int filesize, const char *filename, int option); | 41 const int filesize, const char *filename, int option); |
58 static void bonjour_xfer_cancel_send(PurpleXfer *xfer); | |
59 static void bonjour_xfer_request_denied(PurpleXfer *xfer); | |
60 static void bonjour_xfer_cancel_recv(PurpleXfer *xfer); | |
61 static void bonjour_xfer_end(PurpleXfer *xfer); | |
62 static void bonjour_free_xfer(PurpleXfer *xfer); | 42 static void bonjour_free_xfer(PurpleXfer *xfer); |
63 | 43 |
64 /* Look for specific xfer handle */ | 44 /* Look for specific xfer handle */ |
65 static unsigned int next_id = 0; | 45 static unsigned int next_id = 0; |
46 | |
47 static void | |
48 xep_ft_si_reject(PurpleXfer *xfer, char *to) | |
49 { | |
50 xmlnode *error_node = NULL; | |
51 xmlnode *tmp_node = NULL; | |
52 XepIq *iq = NULL; | |
53 XepXfer *xf = NULL; | |
54 | |
55 if(!to || !xfer) | |
56 return; | |
57 xf = xfer->data; | |
58 if(!xf) | |
59 return; | |
60 | |
61 purple_debug_info("Bonjour", "xep file transfer stream initialization error.\n"); | |
62 iq = xep_iq_new(xf->data, XEP_IQ_ERROR, to, xf->sid); | |
63 if(iq == NULL) | |
64 return; | |
65 | |
66 error_node = xmlnode_new_child(iq->node, "error"); | |
67 xmlnode_set_attrib(error_node, "code", "403"); | |
68 xmlnode_set_attrib(error_node, "type", "cancel"); | |
69 | |
70 tmp_node = xmlnode_new_child(error_node, "forbidden"); | |
71 xmlnode_set_namespace(tmp_node, "urn:ietf:params:xml:ns:xmpp-stanzas"); | |
72 | |
73 tmp_node = xmlnode_new_child(error_node, "text"); | |
74 xmlnode_set_namespace(tmp_node, "urn:ietf:params:xml:ns:xmpp-stanzas"); | |
75 xmlnode_insert_data(tmp_node, "Offer Declined", -1); | |
76 | |
77 xep_iq_send_and_free(iq); | |
78 } | |
66 | 79 |
67 static void bonjour_xfer_cancel_send(PurpleXfer *xfer) | 80 static void bonjour_xfer_cancel_send(PurpleXfer *xfer) |
68 { | 81 { |
69 purple_debug_info("Bonjour", "Bonjour-xfer-cancel-send.\n"); | 82 purple_debug_info("Bonjour", "Bonjour-xfer-cancel-send.\n"); |
70 bonjour_free_xfer(xfer); | 83 bonjour_free_xfer(xfer); |
74 { | 87 { |
75 purple_debug_info("Bonjour", "Bonjour-xfer-request-denied.\n"); | 88 purple_debug_info("Bonjour", "Bonjour-xfer-request-denied.\n"); |
76 xep_ft_si_reject(xfer, xfer->who); | 89 xep_ft_si_reject(xfer, xfer->who); |
77 bonjour_free_xfer(xfer); | 90 bonjour_free_xfer(xfer); |
78 } | 91 } |
79 | |
80 | 92 |
81 static void bonjour_xfer_cancel_recv(PurpleXfer *xfer) | 93 static void bonjour_xfer_cancel_recv(PurpleXfer *xfer) |
82 { | 94 { |
83 purple_debug_info("Bonjour", "Bonjour-xfer-cancel-recv.\n"); | 95 purple_debug_info("Bonjour", "Bonjour-xfer-cancel-recv.\n"); |
84 bonjour_free_xfer(xfer); | 96 bonjour_free_xfer(xfer); |
134 XepIq *iq = NULL; | 146 XepIq *iq = NULL; |
135 XepXfer *xf = NULL; | 147 XepXfer *xf = NULL; |
136 BonjourData *bd = NULL; | 148 BonjourData *bd = NULL; |
137 char buf[32]; | 149 char buf[32]; |
138 | 150 |
139 if(!xfer || !to) | |
140 return; | |
141 xf = xfer->data; | 151 xf = xfer->data; |
142 if(!xf) | 152 if(!xf) |
143 return; | 153 return; |
154 | |
144 bd = xf->data; | 155 bd = xf->data; |
145 if(!bd) | 156 if(!bd) |
146 return; | 157 return; |
147 | 158 |
148 purple_debug_info("Bonjour", "xep file transfer stream initialization offer-id=%d.\n", next_id); | 159 purple_debug_info("Bonjour", "xep file transfer stream initialization offer-id=%d.\n", next_id); |
186 if (xf->mode & XEP_IBB) { | 197 if (xf->mode & XEP_IBB) { |
187 option = xmlnode_new_child(field, "option"); | 198 option = xmlnode_new_child(field, "option"); |
188 value = xmlnode_new_child(option, "value"); | 199 value = xmlnode_new_child(option, "value"); |
189 xmlnode_insert_data(value, "http://jabber.org/protocol/ibb", -1); | 200 xmlnode_insert_data(value, "http://jabber.org/protocol/ibb", -1); |
190 } | 201 } |
191 xep_iq_send(iq); | 202 |
192 } | 203 xep_iq_send_and_free(iq); |
193 | 204 } |
194 static void | 205 |
195 xep_ft_si_reject(PurpleXfer *xfer, char *to) | 206 static void |
207 xep_ft_si_reject2(BonjourData *bd, const char *to, const char *sid) | |
196 { | 208 { |
197 xmlnode *error_node = NULL; | 209 xmlnode *error_node = NULL; |
198 xmlnode *forbidden = NULL; | 210 xmlnode *tmp_node = NULL; |
199 xmlnode *text = NULL; | |
200 XepIq *iq = NULL; | 211 XepIq *iq = NULL; |
201 XepXfer *xf = NULL; | 212 |
202 | 213 g_return_if_fail(bd != NULL); |
203 if(!to || !xfer) | 214 |
204 return; | 215 if(!to || !sid) |
205 xf = xfer->data; | |
206 if(!xf) | |
207 return; | 216 return; |
208 | 217 |
209 purple_debug_info("Bonjour", "xep file transfer stream initialization error.\n"); | 218 purple_debug_info("Bonjour", "xep file transfer stream initialization error.\n"); |
210 iq = xep_iq_new(xf->data, XEP_IQ_ERROR, to, xf->sid); | 219 iq = xep_iq_new(bd, XEP_IQ_ERROR, to, sid); |
211 if(iq == NULL) | 220 if(iq == NULL) |
212 return; | 221 return; |
213 | 222 |
214 error_node = xmlnode_new_child(iq->node, "error"); | 223 error_node = xmlnode_new_child(iq->node, "error"); |
215 xmlnode_set_attrib(error_node, "code", "403"); | 224 xmlnode_set_attrib(error_node, "code", "403"); |
216 xmlnode_set_attrib(error_node, "type", "cancel"); | 225 xmlnode_set_attrib(error_node, "type", "cancel"); |
217 | 226 |
218 forbidden = xmlnode_new_child(error_node, "forbidden"); | 227 tmp_node = xmlnode_new_child(error_node, "forbidden"); |
219 xmlnode_set_namespace(forbidden, "urn:ietf:params:xml:ns:xmpp-stanzas"); | 228 xmlnode_set_namespace(tmp_node, "urn:ietf:params:xml:ns:xmpp-stanzas"); |
220 | 229 |
221 text = xmlnode_new_child(error_node, "text"); | 230 tmp_node = xmlnode_new_child(error_node, "text"); |
222 xmlnode_set_namespace(text, "urn:ietf:params:xml:ns:xmpp-stanzas"); | 231 xmlnode_set_namespace(tmp_node, "urn:ietf:params:xml:ns:xmpp-stanzas"); |
223 xmlnode_insert_data(text, "Offer Declined", -1); | 232 xmlnode_insert_data(tmp_node, "Offer Declined", -1); |
224 | 233 |
225 xep_iq_send(iq); | 234 xep_iq_send_and_free(iq); |
226 } | |
227 static void | |
228 xep_ft_si_reject2(BonjourData *bd, const char *to, const char *sid) | |
229 { | |
230 xmlnode *error_node = NULL; | |
231 xmlnode *forbidden = NULL; | |
232 xmlnode *text = NULL; | |
233 XepIq *iq = NULL; | |
234 if(bd == NULL) | |
235 return; | |
236 if(!to || !sid) | |
237 return; | |
238 purple_debug_info("Bonjour", "xep file transfer stream initialization error.\n"); | |
239 iq = xep_iq_new(bd, XEP_IQ_ERROR, to, sid); | |
240 if(iq == NULL) | |
241 return; | |
242 error_node = xmlnode_new_child(iq->node, "error"); | |
243 xmlnode_set_attrib(error_node, "code", "403"); | |
244 xmlnode_set_attrib(error_node, "type", "cancel"); | |
245 | |
246 forbidden = xmlnode_new_child(error_node, "forbidden"); | |
247 xmlnode_set_namespace(forbidden, "urn:ietf:params:xml:ns:xmpp-stanzas"); | |
248 | |
249 text = xmlnode_new_child(error_node, "text"); | |
250 xmlnode_set_namespace(text, "urn:ietf:params:xml:ns:xmpp-stanzas"); | |
251 xmlnode_insert_data(text, "Offer Declined", -1); | |
252 | |
253 xep_iq_send(iq); | |
254 } | 235 } |
255 | 236 |
256 static void | 237 static void |
257 xep_ft_si_result(PurpleXfer *xfer, char *to) | 238 xep_ft_si_result(PurpleXfer *xfer, char *to) |
258 { | 239 { |
289 xmlnode_set_attrib(field, "var", "stream-method"); | 270 xmlnode_set_attrib(field, "var", "stream-method"); |
290 | 271 |
291 value = xmlnode_new_child(field, "value"); | 272 value = xmlnode_new_child(field, "value"); |
292 xmlnode_insert_data(value, "http://jabber.org/protocol/bytestreams", -1); | 273 xmlnode_insert_data(value, "http://jabber.org/protocol/bytestreams", -1); |
293 | 274 |
294 xep_iq_send(iq); | 275 xep_iq_send_and_free(iq); |
295 } | 276 } |
296 | 277 |
297 static void | 278 static void |
298 bonjour_free_xfer(PurpleXfer *xfer) | 279 bonjour_free_xfer(PurpleXfer *xfer) |
299 { | 280 { |
300 XepXfer *xf = NULL; | 281 XepXfer *xf = NULL; |
301 BonjourData *bd = NULL; | 282 BonjourData *bd = NULL; |
283 | |
302 if(xfer == NULL) { | 284 if(xfer == NULL) { |
303 purple_debug_info("Bonjour", "bonjour-free-xfer-null.\n"); | 285 purple_debug_info("Bonjour", "bonjour-free-xfer-null.\n"); |
304 return; | 286 return; |
305 } | 287 } |
288 | |
306 purple_debug_info("Bonjour", "bonjour-free-xfer-%p.\n", xfer); | 289 purple_debug_info("Bonjour", "bonjour-free-xfer-%p.\n", xfer); |
290 | |
307 xf = (XepXfer*)xfer->data; | 291 xf = (XepXfer*)xfer->data; |
308 if(xf != NULL){ | 292 if(xf != NULL) { |
309 bd = (BonjourData*)xf->data; | 293 bd = (BonjourData*)xf->data; |
310 if(bd != NULL){ | 294 if(bd != NULL) { |
311 bd->xfer_lists = g_list_remove(bd->xfer_lists, xfer); | 295 bd->xfer_lists = g_list_remove(bd->xfer_lists, xfer); |
312 purple_debug_info("Bonjour", "B free xfer from lists(%p).\n", bd->xfer_lists); | 296 purple_debug_info("Bonjour", "B free xfer from lists(%p).\n", bd->xfer_lists); |
313 } | 297 } |
314 if (xf->proxy_connection != NULL) | 298 if (xf->proxy_connection != NULL) |
315 purple_proxy_connect_cancel(xf->proxy_connection); | 299 purple_proxy_connect_cancel(xf->proxy_connection); |
320 g_free(xf->buddy_ip); | 304 g_free(xf->buddy_ip); |
321 g_free(xf->sid); | 305 g_free(xf->sid); |
322 g_free(xf); | 306 g_free(xf); |
323 xfer->data = NULL; | 307 xfer->data = NULL; |
324 } | 308 } |
309 | |
325 purple_debug_info("Bonjour", "Need close socket=%d.\n", xfer->fd); | 310 purple_debug_info("Bonjour", "Need close socket=%d.\n", xfer->fd); |
326 } | 311 } |
327 | 312 |
328 PurpleXfer * | 313 PurpleXfer * |
329 bonjour_new_xfer(PurpleConnection *gc, const char *who) | 314 bonjour_new_xfer(PurpleConnection *gc, const char *who) |
330 { | 315 { |
331 PurpleXfer *xfer = NULL; | 316 PurpleXfer *xfer; |
332 XepXfer *xep_xfer = NULL; | 317 XepXfer *xep_xfer = NULL; |
333 BonjourData *bd = NULL; | 318 BonjourData *bd = NULL; |
319 | |
334 if(who == NULL || gc == NULL) | 320 if(who == NULL || gc == NULL) |
335 return xfer; | 321 return NULL; |
336 | 322 |
337 purple_debug_info("Bonjour", "Bonjour-new-xfer to %s.\n", who); | 323 purple_debug_info("Bonjour", "Bonjour-new-xfer to %s.\n", who); |
338 bd = (BonjourData*) gc->proto_data; | 324 bd = (BonjourData*) gc->proto_data; |
339 if(bd == NULL) | 325 if(bd == NULL) |
340 return xfer; | 326 return NULL; |
327 | |
341 /* Build the file transfer handle */ | 328 /* Build the file transfer handle */ |
342 xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who); | 329 xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who); |
343 | 330 xfer->data = xep_xfer = g_new0(XepXfer, 1); |
344 if (xfer) { | 331 xep_xfer->data = bd; |
345 xep_xfer = g_new0(XepXfer, 1); | 332 |
346 if(xep_xfer == NULL){ | 333 purple_debug_info("Bonjour", "Bonjour-new-xfer bd=%p data=%p.\n", bd, xep_xfer->data); |
347 bonjour_free_xfer(xfer); | 334 |
348 return NULL; | 335 xep_xfer->mode = XEP_BYTESTREAMS | XEP_IBB; |
349 } | 336 xep_xfer->sid = NULL; |
350 xep_xfer->data = bd; | 337 |
351 purple_debug_info("Bonjour", "Bonjour-new-xfer bd=%p data=%p.\n", bd, xep_xfer->data); | 338 purple_xfer_set_init_fnc(xfer, bonjour_xfer_init); |
352 xep_xfer->mode = XEP_BYTESTREAMS | XEP_IBB; | 339 purple_xfer_set_cancel_send_fnc(xfer, bonjour_xfer_cancel_send); |
353 xfer->data = xep_xfer; | 340 purple_xfer_set_end_fnc(xfer, bonjour_xfer_end); |
354 xep_xfer->sid = NULL; | 341 |
355 purple_xfer_set_init_fnc(xfer, bonjour_xfer_init); | 342 bd->xfer_lists = g_list_append(bd->xfer_lists, xfer); |
356 purple_xfer_set_cancel_send_fnc(xfer, bonjour_xfer_cancel_send); | 343 |
357 purple_xfer_set_end_fnc(xfer, bonjour_xfer_end); | |
358 bd->xfer_lists = g_list_append(bd->xfer_lists, xfer); | |
359 } | |
360 return xfer; | 344 return xfer; |
361 } | 345 } |
362 | 346 |
363 void | 347 void |
364 bonjour_send_file(PurpleConnection *gc, const char *who, const char *file) | 348 bonjour_send_file(PurpleConnection *gc, const char *who, const char *file) |
382 bonjour_xfer_init(PurpleXfer *xfer) | 366 bonjour_xfer_init(PurpleXfer *xfer) |
383 { | 367 { |
384 PurpleBuddy *buddy = NULL; | 368 PurpleBuddy *buddy = NULL; |
385 BonjourBuddy *bd = NULL; | 369 BonjourBuddy *bd = NULL; |
386 XepXfer *xf = NULL; | 370 XepXfer *xf = NULL; |
387 char buffer[100]; | 371 |
388 if(xfer == NULL) | 372 if(xfer == NULL) |
389 return; | 373 return; |
390 xf = (XepXfer*)xfer->data; | 374 xf = (XepXfer*)xfer->data; |
391 if(xf == NULL) | 375 if(xf == NULL) |
392 return; | 376 return; |
396 /* this buddy is offline. */ | 380 /* this buddy is offline. */ |
397 if (buddy == NULL) | 381 if (buddy == NULL) |
398 return; | 382 return; |
399 | 383 |
400 bd = (BonjourBuddy *)buddy->proto_data; | 384 bd = (BonjourBuddy *)buddy->proto_data; |
401 memcpy(buffer, bd->ip, 20); | |
402 xf->buddy_ip = g_strdup(bd->ip); | 385 xf->buddy_ip = g_strdup(bd->ip); |
403 if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) { | 386 if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) { |
404 /* initiate file transfer, send SI offer. */ | 387 /* initiate file transfer, send SI offer. */ |
405 purple_debug_info("Bonjour", "Bonjour xfer type is PURPLE_XFER_SEND.\n"); | 388 purple_debug_info("Bonjour", "Bonjour xfer type is PURPLE_XFER_SEND.\n"); |
406 xep_ft_si_offer(xfer, xfer->who); | 389 xep_ft_si_offer(xfer, xfer->who); |
427 if(pc == NULL || packet == NULL || pb == NULL) | 410 if(pc == NULL || packet == NULL || pb == NULL) |
428 return; | 411 return; |
429 bd = (BonjourData*) pc->proto_data; | 412 bd = (BonjourData*) pc->proto_data; |
430 if(bd == NULL) | 413 if(bd == NULL) |
431 return; | 414 return; |
415 | |
432 purple_debug_info("Bonjour", "xep-si-parse.\n"); | 416 purple_debug_info("Bonjour", "xep-si-parse.\n"); |
417 | |
433 type = xmlnode_get_attrib(packet, "type"); | 418 type = xmlnode_get_attrib(packet, "type"); |
434 from = pb->name; | 419 from = pb->name; |
435 id = xmlnode_get_attrib(packet, "id"); | 420 id = xmlnode_get_attrib(packet, "id"); |
436 if(type) { | 421 if(type) { |
437 if(!strcmp(type, "set")){ | 422 if(!strcmp(type, "set")){ |
438 si = xmlnode_get_child(packet,"si"); | 423 si = xmlnode_get_child(packet,"si"); |
439 purple_debug_info("Bonjour", "si offer Message type - SET.\n"); | 424 purple_debug_info("Bonjour", "si offer Message type - SET.\n"); |
440 file = xmlnode_get_child(si, "file"); | 425 file = xmlnode_get_child(si, "file"); |
441 /**/ | 426 /**/ |
442 filename = xmlnode_get_attrib(file, "name"); | 427 filename = xmlnode_get_attrib(file, "name"); |
443 if( (filesize_str = xmlnode_get_attrib(file, "size")) != NULL ) | 428 if((filesize_str = xmlnode_get_attrib(file, "size"))) |
444 filesize = atoi(filesize_str); | 429 filesize = atoi(filesize_str); |
445 bonjour_xfer_receive(pc, id, from, filesize, filename, option); | 430 bonjour_xfer_receive(pc, id, from, filesize, filename, option); |
446 } else if(!strcmp(type, "result")){ | 431 } else if(!strcmp(type, "result")){ |
447 si = xmlnode_get_child(packet,"si"); | 432 si = xmlnode_get_child(packet,"si"); |
448 purple_debug_info("Bonjour", "si offer Message type - RESULT.\n"); | 433 purple_debug_info("Bonjour", "si offer Message type - RESULT.\n"); |
475 BonjourData *bd = NULL; | 460 BonjourData *bd = NULL; |
476 PurpleXfer *xfer = NULL; | 461 PurpleXfer *xfer = NULL; |
477 XepXfer *xf = NULL; | 462 XepXfer *xf = NULL; |
478 const char *jid=NULL, *host=NULL, *port=NULL; | 463 const char *jid=NULL, *host=NULL, *port=NULL; |
479 int portnum; | 464 int portnum; |
465 | |
480 if(pc == NULL || packet == NULL || pb == NULL) | 466 if(pc == NULL || packet == NULL || pb == NULL) |
481 return; | 467 return; |
468 | |
482 bd = (BonjourData*) pc->proto_data; | 469 bd = (BonjourData*) pc->proto_data; |
483 if(bd == NULL) | 470 if(bd == NULL) |
484 return; | 471 return; |
472 | |
485 purple_debug_info("Bonjour", "xep-bytestreams-parse.\n"); | 473 purple_debug_info("Bonjour", "xep-bytestreams-parse.\n"); |
474 | |
486 type = xmlnode_get_attrib(packet, "type"); | 475 type = xmlnode_get_attrib(packet, "type"); |
487 from = pb->name; | 476 from = pb->name; |
488 query = xmlnode_get_child(packet,"query"); | 477 query = xmlnode_get_child(packet,"query"); |
489 if(type) { | 478 if(type) { |
490 if(!strcmp(type, "set")){ | 479 if(!strcmp(type, "set")){ |
491 purple_debug_info("Bonjour", "bytestream offer Message type - SET.\n"); | 480 purple_debug_info("Bonjour", "bytestream offer Message type - SET.\n"); |
481 | |
492 id = xmlnode_get_attrib(query, "sid"); | 482 id = xmlnode_get_attrib(query, "sid"); |
493 xfer = bonjour_si_xfer_find(bd, id, from); | 483 xfer = bonjour_si_xfer_find(bd, id, from); |
484 | |
494 if(xfer){ | 485 if(xfer){ |
495 xf = (XepXfer*)xfer->data; | 486 xf = (XepXfer*)xfer->data; |
496 for(streamhost = xmlnode_get_child(query, "streamhost"); | 487 for(streamhost = xmlnode_get_child(query, "streamhost"); |
497 streamhost; | 488 streamhost; |
498 streamhost = xmlnode_get_next_twin(streamhost)) { | 489 streamhost = xmlnode_get_next_twin(streamhost)) { |
490 | |
499 if((jid = xmlnode_get_attrib(streamhost, "jid")) && | 491 if((jid = xmlnode_get_attrib(streamhost, "jid")) && |
500 (host = xmlnode_get_attrib(streamhost, "host")) && | 492 (host = xmlnode_get_attrib(streamhost, "host")) && |
501 (port = xmlnode_get_attrib(streamhost, "port")) && | 493 (port = xmlnode_get_attrib(streamhost, "port")) && |
502 (portnum = atoi(port))) { | 494 (portnum = atoi(port))) { |
495 | |
503 if(!strcmp(host, xf->buddy_ip)) { | 496 if(!strcmp(host, xf->buddy_ip)) { |
504 xf->jid = g_strdup(jid); | 497 xf->jid = g_strdup(jid); |
505 xf->proxy_host = g_strdup(host); | 498 xf->proxy_host = g_strdup(host); |
506 xf->proxy_port = portnum; | 499 xf->proxy_port = portnum; |
507 purple_debug_info("Bonjour", "bytestream offer parse" | 500 purple_debug_info("Bonjour", "bytestream offer parse" |
508 "jid=%s host=%s port=%d.\n", jid, host, portnum); | 501 "jid=%s host=%s port=%d.\n", jid, host, portnum); |
509 bonjour_bytestreams_connect(xfer); | 502 bonjour_bytestreams_connect(xfer); |
503 break; | |
510 } | 504 } |
505 | |
511 } else { | 506 } else { |
512 purple_debug_info("Bonjour", "bytestream offer Message parse error.\n"); | 507 purple_debug_info("Bonjour", "bytestream offer Message parse error.\n"); |
513 } | 508 } |
514 } | 509 } |
515 } else { | 510 } else { |
527 const int filesize, const char *filename, int option) | 522 const int filesize, const char *filename, int option) |
528 { | 523 { |
529 PurpleXfer *xfer = NULL; | 524 PurpleXfer *xfer = NULL; |
530 XepXfer *xf = NULL; | 525 XepXfer *xf = NULL; |
531 BonjourData *bd = NULL; | 526 BonjourData *bd = NULL; |
527 | |
532 if(pc == NULL || id == NULL || from == NULL || filename == NULL) | 528 if(pc == NULL || id == NULL || from == NULL || filename == NULL) |
533 return; | 529 return; |
530 | |
534 bd = (BonjourData*) pc->proto_data; | 531 bd = (BonjourData*) pc->proto_data; |
535 if(bd == NULL) | 532 if(bd == NULL) |
536 return; | 533 return; |
534 | |
537 purple_debug_info("Bonjour", "bonjour-xfer-receive.\n"); | 535 purple_debug_info("Bonjour", "bonjour-xfer-receive.\n"); |
536 | |
538 /* Build the file transfer handle */ | 537 /* Build the file transfer handle */ |
539 xfer = purple_xfer_new(pc->account, PURPLE_XFER_RECEIVE, from); | 538 xfer = purple_xfer_new(pc->account, PURPLE_XFER_RECEIVE, from); |
540 if (xfer) { | 539 xfer->data = xf = g_new0(XepXfer, 1); |
541 xf = g_new0(XepXfer, 1); | 540 xf->data = bd; |
542 xf->data = bd; | 541 purple_xfer_set_filename(xfer, filename); |
543 xfer->data = xf; | 542 xf->sid = g_strdup(id); |
544 purple_xfer_set_filename(xfer, filename); | 543 |
545 xf->sid = g_strdup(id); | 544 if(filesize > 0) |
546 if(filesize > 0) | 545 purple_xfer_set_size(xfer, filesize); |
547 purple_xfer_set_size(xfer, filesize); | 546 purple_xfer_set_init_fnc(xfer, bonjour_xfer_init); |
548 purple_xfer_set_init_fnc(xfer, bonjour_xfer_init); | 547 purple_xfer_set_request_denied_fnc(xfer, bonjour_xfer_request_denied); |
549 purple_xfer_set_request_denied_fnc(xfer, bonjour_xfer_request_denied); | 548 purple_xfer_set_cancel_recv_fnc(xfer, bonjour_xfer_cancel_recv); |
550 purple_xfer_set_cancel_recv_fnc(xfer, bonjour_xfer_cancel_recv); | 549 purple_xfer_set_end_fnc(xfer, bonjour_xfer_end); |
551 purple_xfer_set_end_fnc(xfer, bonjour_xfer_end); | 550 |
552 bd->xfer_lists = g_list_append(bd->xfer_lists, xfer); | 551 bd->xfer_lists = g_list_append(bd->xfer_lists, xfer); |
553 purple_xfer_request(xfer); | 552 |
554 } | 553 purple_xfer_request(xfer); |
555 } | |
556 | |
557 static void | |
558 bonjour_bytestreams_init(PurpleXfer *xfer) | |
559 { | |
560 XepXfer *xf = NULL; | |
561 if(xfer == NULL) | |
562 return; | |
563 purple_debug_info("Bonjour", "Bonjour-bytestreams-init.\n"); | |
564 xf = xfer->data; | |
565 xf->listen_data = purple_network_listen_range(0, 0, SOCK_STREAM, | |
566 bonjour_bytestreams_listen, xfer); | |
567 if (xf->listen_data == NULL) { | |
568 purple_xfer_cancel_local(xfer); | |
569 } | |
570 return; | |
571 } | |
572 | |
573 static void | |
574 bonjour_bytestreams_listen(int sock, gpointer data) | |
575 { | |
576 PurpleXfer *xfer = NULL; | |
577 XepXfer *xf; | |
578 XepIq *iq; | |
579 xmlnode *query, *streamhost; | |
580 char *port; | |
581 char *next_ip = NULL; | |
582 char *local_ip = NULL; | |
583 char token [] = ";"; | |
584 purple_debug_info("Bonjour", "Bonjour-bytestreams-listen. sock=%d.\n", sock); | |
585 if (sock < 0 || data == NULL) { | |
586 /*purple_xfer_cancel_local(xfer);*/ | |
587 return; | |
588 } | |
589 xfer = data; | |
590 xfer->watcher = purple_input_add(sock, PURPLE_INPUT_READ, | |
591 bonjour_sock5_request_cb, xfer); | |
592 xf = (XepXfer*)xfer->data; | |
593 xf->listen_data = NULL; | |
594 /*xf->listen_data = NULL;*/ | |
595 iq = xep_iq_new(xf->data, XEP_IQ_SET, xfer->who, xf->sid); | |
596 query = xmlnode_new_child(iq->node, "query"); | |
597 xmlnode_set_namespace(query, "http://jabber.org/protocol/bytestreams"); | |
598 xmlnode_set_attrib(query, "sid", xf->sid); | |
599 xmlnode_set_attrib(query, "mode", "tcp"); | |
600 local_ip = purple_network_get_my_ip_ext2(sock); | |
601 next_ip = strtok(local_ip, token); | |
602 xfer->local_port = purple_network_get_port_from_fd(sock); | |
603 while(next_ip != NULL) { | |
604 streamhost = xmlnode_new_child(query, "streamhost"); | |
605 xmlnode_set_attrib(streamhost, "jid", xf->sid); | |
606 xmlnode_set_attrib(streamhost, "host", next_ip); | |
607 port = g_strdup_printf("%hu", xfer->local_port); | |
608 xmlnode_set_attrib(streamhost, "port", port); | |
609 g_free(port); | |
610 next_ip = strtok(NULL, token); | |
611 } | |
612 xep_iq_send(iq); | |
613 } | 554 } |
614 | 555 |
615 static void | 556 static void |
616 bonjour_sock5_request_cb(gpointer data, gint source, PurpleInputCondition cond) | 557 bonjour_sock5_request_cb(gpointer data, gint source, PurpleInputCondition cond) |
617 { | 558 { |
618 PurpleXfer *xfer = data; | 559 PurpleXfer *xfer = data; |
619 XepXfer *xf = NULL; | 560 XepXfer *xf = NULL; |
620 int acceptfd; | 561 int acceptfd; |
621 int len = 0; | 562 int len = 0; |
622 if(xfer == NULL ) | 563 |
623 return; | 564 if(xfer == NULL) |
565 return; | |
566 | |
624 xf = xfer->data; | 567 xf = xfer->data; |
625 if(xf == NULL) | 568 if(xf == NULL) |
626 return; | 569 return; |
570 | |
627 switch(xf->sock5_req_state){ | 571 switch(xf->sock5_req_state){ |
628 case 0x00: | 572 case 0x00: |
629 acceptfd = accept (source, NULL, 0); | 573 acceptfd = accept(source, NULL, 0); |
630 if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK )) { | 574 if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { |
631 | 575 |
632 } else if(acceptfd == -1) { | 576 } else if(acceptfd == -1) { |
633 | 577 |
634 } else { | 578 } else { |
635 purple_debug_info("Bonjour", "Conjour-sock5-request-cb. state= %d, accept=%d\n", xf->sock5_req_state, acceptfd); | 579 purple_debug_info("Bonjour", "Conjour-sock5-request-cb. state= %d, accept=%d\n", xf->sock5_req_state, acceptfd); |
722 default: | 666 default: |
723 break; | 667 break; |
724 } | 668 } |
725 return; | 669 return; |
726 } | 670 } |
671 | |
672 static void | |
673 bonjour_bytestreams_listen(int sock, gpointer data) | |
674 { | |
675 PurpleXfer *xfer = data; | |
676 XepXfer *xf; | |
677 XepIq *iq; | |
678 xmlnode *query, *streamhost; | |
679 char *port; | |
680 const char *next_ip; | |
681 const char *local_ip = NULL; | |
682 char token [] = ";"; | |
683 | |
684 purple_debug_info("Bonjour", "Bonjour-bytestreams-listen. sock=%d.\n", sock); | |
685 if (sock < 0 || xfer == NULL) { | |
686 /*purple_xfer_cancel_local(xfer);*/ | |
687 return; | |
688 } | |
689 | |
690 xfer->watcher = purple_input_add(sock, PURPLE_INPUT_READ, | |
691 bonjour_sock5_request_cb, xfer); | |
692 xf = (XepXfer*)xfer->data; | |
693 xf->listen_data = NULL; | |
694 | |
695 iq = xep_iq_new(xf->data, XEP_IQ_SET, xfer->who, xf->sid); | |
696 | |
697 query = xmlnode_new_child(iq->node, "query"); | |
698 xmlnode_set_namespace(query, "http://jabber.org/protocol/bytestreams"); | |
699 xmlnode_set_attrib(query, "sid", xf->sid); | |
700 xmlnode_set_attrib(query, "mode", "tcp"); | |
701 | |
702 xfer->local_port = purple_network_get_port_from_fd(sock); | |
703 | |
704 local_ip = purple_network_get_my_ip_ext2(sock); | |
705 /* cheat a little here - the intent of the "const" attribute is to make it clear that the string doesn't need to be freed */ | |
706 next_ip = strtok((char *)local_ip, token); | |
707 | |
708 while(next_ip != NULL) { | |
709 streamhost = xmlnode_new_child(query, "streamhost"); | |
710 xmlnode_set_attrib(streamhost, "jid", xf->sid); | |
711 xmlnode_set_attrib(streamhost, "host", next_ip); | |
712 port = g_strdup_printf("%hu", xfer->local_port); | |
713 xmlnode_set_attrib(streamhost, "port", port); | |
714 g_free(port); | |
715 next_ip = strtok(NULL, token); | |
716 } | |
717 | |
718 xep_iq_send_and_free(iq); | |
719 } | |
720 | |
721 static void | |
722 bonjour_bytestreams_init(PurpleXfer *xfer) | |
723 { | |
724 XepXfer *xf = NULL; | |
725 if(xfer == NULL) | |
726 return; | |
727 purple_debug_info("Bonjour", "Bonjour-bytestreams-init.\n"); | |
728 xf = xfer->data; | |
729 xf->listen_data = purple_network_listen_range(0, 0, SOCK_STREAM, | |
730 bonjour_bytestreams_listen, xfer); | |
731 if (xf->listen_data == NULL) { | |
732 purple_xfer_cancel_local(xfer); | |
733 } | |
734 return; | |
735 } | |
736 | |
737 static void | |
738 bonjour_bytestreams_connect_cb(gpointer data, gint source, const gchar *error_message) | |
739 { | |
740 PurpleXfer *xfer = data; | |
741 XepXfer *xf = xfer->data; | |
742 | |
743 if(data == NULL || source < 0) | |
744 return; | |
745 | |
746 purple_proxy_info_destroy(xf->proxy_info); | |
747 xf->proxy_connection = NULL; | |
748 xf->proxy_info = NULL; | |
749 /* Here, start the file transfer.*/ | |
750 purple_xfer_start(xfer, source, NULL, -1); | |
751 } | |
752 | |
727 static void | 753 static void |
728 bonjour_bytestreams_connect(PurpleXfer *xfer) | 754 bonjour_bytestreams_connect(PurpleXfer *xfer) |
729 { | 755 { |
730 XepXfer *xf = NULL; | 756 XepXfer *xf = NULL; |
731 char dstaddr[41]; | 757 char dstaddr[41]; |
732 unsigned char hashval[20]; | 758 unsigned char hashval[20]; |
733 char *p = NULL; | 759 char *p = NULL; |
734 int i; | 760 int i; |
761 | |
735 if(xfer == NULL) | 762 if(xfer == NULL) |
736 return; | 763 return; |
764 | |
737 purple_debug_info("Bonjour", "bonjour-bytestreams-connect.\n"); | 765 purple_debug_info("Bonjour", "bonjour-bytestreams-connect.\n"); |
766 | |
738 xf = (XepXfer*)xfer->data; | 767 xf = (XepXfer*)xfer->data; |
739 if(!xf) | 768 if(!xf) |
740 return; | 769 return; |
741 xf->proxy_info = purple_proxy_info_new(); | 770 |
742 if(xf->proxy_info == NULL) | |
743 return; | |
744 p = g_strdup_printf("%s@%s", xf->sid, xfer->who); | 771 p = g_strdup_printf("%s@%s", xf->sid, xfer->who); |
745 purple_cipher_digest_region("sha1", (guchar *)dstaddr, strlen(dstaddr), | 772 purple_cipher_digest_region("sha1", (guchar *)p, strlen(p), |
746 sizeof(hashval), hashval, NULL); | 773 sizeof(hashval), hashval, NULL); |
747 g_free(p); | 774 g_free(p); |
775 | |
748 memset(dstaddr, 0, 41); | 776 memset(dstaddr, 0, 41); |
749 p = dstaddr; | 777 p = dstaddr; |
750 for(i=0; i<20; i++) { | 778 for(i = 0; i < 20; i++, p += 2) |
751 snprintf(p, 3, "%02x", hashval[i]); | 779 snprintf(p, 3, "%02x", hashval[i]); |
752 } | 780 |
781 xf->proxy_info = purple_proxy_info_new(); | |
753 purple_proxy_info_set_type(xf->proxy_info, PURPLE_PROXY_SOCKS5); | 782 purple_proxy_info_set_type(xf->proxy_info, PURPLE_PROXY_SOCKS5); |
754 purple_proxy_info_set_host(xf->proxy_info, xf->proxy_host); | 783 purple_proxy_info_set_host(xf->proxy_info, xf->proxy_host); |
755 purple_proxy_info_set_port(xf->proxy_info, xf->proxy_port); | 784 purple_proxy_info_set_port(xf->proxy_info, xf->proxy_port); |
756 xf->proxy_connection = purple_proxy_connect_socks5(NULL, xf->proxy_info, | 785 xf->proxy_connection = purple_proxy_connect_socks5(NULL, xf->proxy_info, |
757 dstaddr, 0, | 786 dstaddr, 0, |
758 bonjour_bytestreams_connect_cb, xfer); | 787 bonjour_bytestreams_connect_cb, xfer); |
788 | |
759 if(xf->proxy_connection == NULL) { | 789 if(xf->proxy_connection == NULL) { |
760 purple_proxy_info_destroy(xf->proxy_info); | 790 purple_proxy_info_destroy(xf->proxy_info); |
761 xf->proxy_info = NULL; | 791 xf->proxy_info = NULL; |
762 } | 792 } |
763 } | 793 } |
764 | 794 |
765 static void | |
766 bonjour_bytestreams_connect_cb(gpointer data, gint source, const gchar *error_message) | |
767 { | |
768 PurpleXfer *xfer = data; | |
769 XepXfer *xf = xfer->data; | |
770 if(data == NULL || source < 0) | |
771 return; | |
772 purple_proxy_info_destroy(xf->proxy_info); | |
773 xf->proxy_connection = NULL; | |
774 xf->proxy_info = NULL; | |
775 /* Here, start the file transfer.*/ | |
776 purple_xfer_start(xfer, source, NULL, -1); | |
777 } |