comparison libpurple/protocols/bonjour/bonjour_ft.c @ 21466:7a05b6f84545

Don't map the port used for bonjour file transfers externally. This adds a new function that will go away in 3.0.0 when we can modify purple_network_do_listen to take an additional parameter.
author Daniel Atallah <daniel.atallah@gmail.com>
date Tue, 13 Nov 2007 04:29:06 +0000
parents e489c81e1f6f
children 3d70e3ec8a47
comparison
equal deleted inserted replaced
21465:e489c81e1f6f 21466:7a05b6f84545
56 return; 56 return;
57 xf = xfer->data; 57 xf = xfer->data;
58 if(!xf) 58 if(!xf)
59 return; 59 return;
60 60
61 purple_debug_info("Bonjour", "xep file transfer stream initialization error.\n"); 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); 62 iq = xep_iq_new(xf->data, XEP_IQ_ERROR, to, xf->sid);
63 if(iq == NULL) 63 if(iq == NULL)
64 return; 64 return;
65 65
66 error_node = xmlnode_new_child(iq->node, "error"); 66 error_node = xmlnode_new_child(iq->node, "error");
77 xep_iq_send_and_free(iq); 77 xep_iq_send_and_free(iq);
78 } 78 }
79 79
80 static void bonjour_xfer_cancel_send(PurpleXfer *xfer) 80 static void bonjour_xfer_cancel_send(PurpleXfer *xfer)
81 { 81 {
82 purple_debug_info("Bonjour", "Bonjour-xfer-cancel-send.\n"); 82 purple_debug_info("bonjour", "Bonjour-xfer-cancel-send.\n");
83 bonjour_free_xfer(xfer); 83 bonjour_free_xfer(xfer);
84 } 84 }
85 85
86 static void bonjour_xfer_request_denied(PurpleXfer *xfer) 86 static void bonjour_xfer_request_denied(PurpleXfer *xfer)
87 { 87 {
88 purple_debug_info("Bonjour", "Bonjour-xfer-request-denied.\n"); 88 purple_debug_info("bonjour", "Bonjour-xfer-request-denied.\n");
89 xep_ft_si_reject(xfer, xfer->who); 89 xep_ft_si_reject(xfer, xfer->who);
90 bonjour_free_xfer(xfer); 90 bonjour_free_xfer(xfer);
91 } 91 }
92 92
93 static void bonjour_xfer_cancel_recv(PurpleXfer *xfer) 93 static void bonjour_xfer_cancel_recv(PurpleXfer *xfer)
94 { 94 {
95 purple_debug_info("Bonjour", "Bonjour-xfer-cancel-recv.\n"); 95 purple_debug_info("bonjour", "Bonjour-xfer-cancel-recv.\n");
96 bonjour_free_xfer(xfer); 96 bonjour_free_xfer(xfer);
97 } 97 }
98 98
99 99
100 static void bonjour_xfer_end(PurpleXfer *xfer) 100 static void bonjour_xfer_end(PurpleXfer *xfer)
101 { 101 {
102 purple_debug_info("Bonjour", "Bonjour-xfer-end.\n"); 102 purple_debug_info("bonjour", "Bonjour-xfer-end.\n");
103 bonjour_free_xfer(xfer); 103 bonjour_free_xfer(xfer);
104 } 104 }
105 105
106 static PurpleXfer* 106 static PurpleXfer*
107 bonjour_si_xfer_find(BonjourData *bd, const char *sid, const char *from) 107 bonjour_si_xfer_find(BonjourData *bd, const char *sid, const char *from)
111 XepXfer *xf = NULL; 111 XepXfer *xf = NULL;
112 112
113 if(!sid || !from || !bd) 113 if(!sid || !from || !bd)
114 return NULL; 114 return NULL;
115 115
116 purple_debug_info("Bonjour", "Look for sid=%s from=%s xferlists.\n", 116 purple_debug_info("bonjour", "Look for sid=%s from=%s xferlists.\n",
117 sid, from); 117 sid, from);
118 118
119 for(xfers = bd->xfer_lists; xfers; xfers = xfers->next) { 119 for(xfers = bd->xfer_lists; xfers; xfers = xfers->next) {
120 xfer = xfers->data; 120 xfer = xfers->data;
121 if(xfer == NULL) 121 if(xfer == NULL)
126 if(xf->sid && xfer->who && !strcmp(xf->sid, sid) && 126 if(xf->sid && xfer->who && !strcmp(xf->sid, sid) &&
127 !strcmp(xfer->who, from)) 127 !strcmp(xfer->who, from))
128 return xfer; 128 return xfer;
129 } 129 }
130 130
131 purple_debug_info("Bonjour", "Look for xfer list fail\n"); 131 purple_debug_info("bonjour", "Look for xfer list fail\n");
132 132
133 return NULL; 133 return NULL;
134 } 134 }
135 135
136 static void 136 static void
154 154
155 bd = xf->data; 155 bd = xf->data;
156 if(!bd) 156 if(!bd)
157 return; 157 return;
158 158
159 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);
160 160
161 /* Assign stream id. */ 161 /* Assign stream id. */
162 memset(buf, 0, 32); 162 memset(buf, 0, 32);
163 g_snprintf(buf, sizeof(buf), "%u", next_id++); 163 g_snprintf(buf, sizeof(buf), "%u", next_id++);
164 iq = xep_iq_new(xf->data, XEP_IQ_SET, to, buf); 164 iq = xep_iq_new(xf->data, XEP_IQ_SET, to, buf);
213 g_return_if_fail(bd != NULL); 213 g_return_if_fail(bd != NULL);
214 214
215 if(!to || !sid) 215 if(!to || !sid)
216 return; 216 return;
217 217
218 purple_debug_info("Bonjour", "xep file transfer stream initialization error.\n"); 218 purple_debug_info("bonjour", "xep file transfer stream initialization error.\n");
219 iq = xep_iq_new(bd, XEP_IQ_ERROR, to, sid); 219 iq = xep_iq_new(bd, XEP_IQ_ERROR, to, sid);
220 if(iq == NULL) 220 if(iq == NULL)
221 return; 221 return;
222 222
223 error_node = xmlnode_new_child(iq->node, "error"); 223 error_node = xmlnode_new_child(iq->node, "error");
249 return; 249 return;
250 xf = xfer->data; 250 xf = xfer->data;
251 if(!xf) 251 if(!xf)
252 return; 252 return;
253 253
254 purple_debug_info("Bonjour", "xep file transfer stream initialization result.\n"); 254 purple_debug_info("bonjour", "xep file transfer stream initialization result.\n");
255 iq = xep_iq_new(xf->data, XEP_IQ_RESULT, to, xf->sid); 255 iq = xep_iq_new(xf->data, XEP_IQ_RESULT, to, xf->sid);
256 if(iq == NULL) 256 if(iq == NULL)
257 return; 257 return;
258 258
259 si_node = xmlnode_new_child(iq->node, "si"); 259 si_node = xmlnode_new_child(iq->node, "si");
280 { 280 {
281 XepXfer *xf = NULL; 281 XepXfer *xf = NULL;
282 BonjourData *bd = NULL; 282 BonjourData *bd = NULL;
283 283
284 if(xfer == NULL) { 284 if(xfer == NULL) {
285 purple_debug_info("Bonjour", "bonjour-free-xfer-null.\n"); 285 purple_debug_info("bonjour", "bonjour-free-xfer-null.\n");
286 return; 286 return;
287 } 287 }
288 288
289 purple_debug_info("Bonjour", "bonjour-free-xfer-%p.\n", xfer); 289 purple_debug_info("bonjour", "bonjour-free-xfer-%p.\n", xfer);
290 290
291 xf = (XepXfer*)xfer->data; 291 xf = (XepXfer*)xfer->data;
292 if(xf != NULL) { 292 if(xf != NULL) {
293 bd = (BonjourData*)xf->data; 293 bd = (BonjourData*)xf->data;
294 if(bd != NULL) { 294 if(bd != NULL) {
295 bd->xfer_lists = g_list_remove(bd->xfer_lists, xfer); 295 bd->xfer_lists = g_list_remove(bd->xfer_lists, xfer);
296 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);
297 } 297 }
298 if (xf->proxy_connection != NULL) 298 if (xf->proxy_connection != NULL)
299 purple_proxy_connect_cancel(xf->proxy_connection); 299 purple_proxy_connect_cancel(xf->proxy_connection);
300 if (xf->listen_data != NULL) 300 if (xf->listen_data != NULL)
301 purple_network_listen_cancel(xf->listen_data); 301 purple_network_listen_cancel(xf->listen_data);
305 g_free(xf->sid); 305 g_free(xf->sid);
306 g_free(xf); 306 g_free(xf);
307 xfer->data = NULL; 307 xfer->data = NULL;
308 } 308 }
309 309
310 purple_debug_info("Bonjour", "Need close socket=%d.\n", xfer->fd); 310 purple_debug_info("bonjour", "Need close socket=%d.\n", xfer->fd);
311 } 311 }
312 312
313 PurpleXfer * 313 PurpleXfer *
314 bonjour_new_xfer(PurpleConnection *gc, const char *who) 314 bonjour_new_xfer(PurpleConnection *gc, const char *who)
315 { 315 {
318 BonjourData *bd = NULL; 318 BonjourData *bd = NULL;
319 319
320 if(who == NULL || gc == NULL) 320 if(who == NULL || gc == NULL)
321 return NULL; 321 return NULL;
322 322
323 purple_debug_info("Bonjour", "Bonjour-new-xfer to %s.\n", who); 323 purple_debug_info("bonjour", "Bonjour-new-xfer to %s.\n", who);
324 bd = (BonjourData*) gc->proto_data; 324 bd = (BonjourData*) gc->proto_data;
325 if(bd == NULL) 325 if(bd == NULL)
326 return NULL; 326 return NULL;
327 327
328 /* Build the file transfer handle */ 328 /* Build the file transfer handle */
329 xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who); 329 xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who);
330 xfer->data = xep_xfer = g_new0(XepXfer, 1); 330 xfer->data = xep_xfer = g_new0(XepXfer, 1);
331 xep_xfer->data = bd; 331 xep_xfer->data = bd;
332 332
333 purple_debug_info("Bonjour", "Bonjour-new-xfer bd=%p data=%p.\n", bd, xep_xfer->data); 333 purple_debug_info("bonjour", "Bonjour-new-xfer bd=%p data=%p.\n", bd, xep_xfer->data);
334 334
335 xep_xfer->mode = XEP_BYTESTREAMS | XEP_IBB; 335 xep_xfer->mode = XEP_BYTESTREAMS | XEP_IBB;
336 xep_xfer->sid = NULL; 336 xep_xfer->sid = NULL;
337 337
338 purple_xfer_set_init_fnc(xfer, bonjour_xfer_init); 338 purple_xfer_set_init_fnc(xfer, bonjour_xfer_init);
349 { 349 {
350 350
351 PurpleXfer *xfer = NULL; 351 PurpleXfer *xfer = NULL;
352 if(gc == NULL || who == NULL) 352 if(gc == NULL || who == NULL)
353 return; 353 return;
354 purple_debug_info("Bonjour", "Bonjour-send-file to=%s.\n", who); 354 purple_debug_info("bonjour", "Bonjour-send-file to=%s.\n", who);
355 xfer = bonjour_new_xfer(gc, who); 355 xfer = bonjour_new_xfer(gc, who);
356 if(xfer == NULL) 356 if(xfer == NULL)
357 return; 357 return;
358 if (file) 358 if (file)
359 purple_xfer_request_accepted(xfer, file); 359 purple_xfer_request_accepted(xfer, file);
372 if(xfer == NULL) 372 if(xfer == NULL)
373 return; 373 return;
374 xf = (XepXfer*)xfer->data; 374 xf = (XepXfer*)xfer->data;
375 if(xf == NULL) 375 if(xf == NULL)
376 return; 376 return;
377 purple_debug_info("Bonjour", "Bonjour-xfer-init.\n"); 377 purple_debug_info("bonjour", "Bonjour-xfer-init.\n");
378 378
379 buddy = purple_find_buddy(xfer->account, xfer->who); 379 buddy = purple_find_buddy(xfer->account, xfer->who);
380 /* this buddy is offline. */ 380 /* this buddy is offline. */
381 if (buddy == NULL) 381 if (buddy == NULL)
382 return; 382 return;
383 383
384 bd = (BonjourBuddy *)buddy->proto_data; 384 bd = (BonjourBuddy *)buddy->proto_data;
385 xf->buddy_ip = g_strdup(bd->ip); 385 xf->buddy_ip = g_strdup(bd->ip);
386 if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) { 386 if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
387 /* initiate file transfer, send SI offer. */ 387 /* initiate file transfer, send SI offer. */
388 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");
389 xep_ft_si_offer(xfer, xfer->who); 389 xep_ft_si_offer(xfer, xfer->who);
390 390
391 } else { 391 } else {
392 /* accept file transfer request, send SI result. */ 392 /* accept file transfer request, send SI result. */
393 xep_ft_si_result(xfer, xfer->who); 393 xep_ft_si_result(xfer, xfer->who);
394 purple_debug_info("Bonjour", "Bonjour xfer type is PURPLE_XFER_RECEIVE.\n"); 394 purple_debug_info("bonjour", "Bonjour xfer type is PURPLE_XFER_RECEIVE.\n");
395 } 395 }
396 return; 396 return;
397 } 397 }
398 398
399 399
411 return; 411 return;
412 bd = (BonjourData*) pc->proto_data; 412 bd = (BonjourData*) pc->proto_data;
413 if(bd == NULL) 413 if(bd == NULL)
414 return; 414 return;
415 415
416 purple_debug_info("Bonjour", "xep-si-parse.\n"); 416 purple_debug_info("bonjour", "xep-si-parse.\n");
417 417
418 type = xmlnode_get_attrib(packet, "type"); 418 type = xmlnode_get_attrib(packet, "type");
419 from = pb->name; 419 from = pb->name;
420 id = xmlnode_get_attrib(packet, "id"); 420 id = xmlnode_get_attrib(packet, "id");
421 if(type) { 421 if(type) {
422 if(!strcmp(type, "set")){ 422 if(!strcmp(type, "set")){
423 si = xmlnode_get_child(packet,"si"); 423 si = xmlnode_get_child(packet,"si");
424 purple_debug_info("Bonjour", "si offer Message type - SET.\n"); 424 purple_debug_info("bonjour", "si offer Message type - SET.\n");
425 file = xmlnode_get_child(si, "file"); 425 file = xmlnode_get_child(si, "file");
426 /**/ 426 /**/
427 filename = xmlnode_get_attrib(file, "name"); 427 filename = xmlnode_get_attrib(file, "name");
428 if((filesize_str = xmlnode_get_attrib(file, "size"))) 428 if((filesize_str = xmlnode_get_attrib(file, "size")))
429 filesize = atoi(filesize_str); 429 filesize = atoi(filesize_str);
430 bonjour_xfer_receive(pc, id, from, filesize, filename, option); 430 bonjour_xfer_receive(pc, id, from, filesize, filename, option);
431 } else if(!strcmp(type, "result")){ 431 } else if(!strcmp(type, "result")){
432 si = xmlnode_get_child(packet,"si"); 432 si = xmlnode_get_child(packet,"si");
433 purple_debug_info("Bonjour", "si offer Message type - RESULT.\n"); 433 purple_debug_info("bonjour", "si offer Message type - RESULT.\n");
434 xfer = bonjour_si_xfer_find(bd, id, from); 434 xfer = bonjour_si_xfer_find(bd, id, from);
435 if(xfer == NULL){ 435 if(xfer == NULL){
436 purple_debug_info("Bonjour", "xfer find fail.\n"); 436 purple_debug_info("bonjour", "xfer find fail.\n");
437 xep_ft_si_reject2((BonjourData *)pc->proto_data, from, id); 437 xep_ft_si_reject2((BonjourData *)pc->proto_data, from, id);
438 } else { 438 } else {
439 bonjour_bytestreams_init(xfer); 439 bonjour_bytestreams_init(xfer);
440 } 440 }
441 } else if(!strcmp(type, "error")){ 441 } else if(!strcmp(type, "error")){
442 purple_debug_info("Bonjour", "si offer Message type - ERROR.\n"); 442 purple_debug_info("bonjour", "si offer Message type - ERROR.\n");
443 xfer = bonjour_si_xfer_find(bd, id, from); 443 xfer = bonjour_si_xfer_find(bd, id, from);
444 if(xfer == NULL){ 444 if(xfer == NULL){
445 purple_debug_info("Bonjour", "xfer find fail.\n"); 445 purple_debug_info("bonjour", "xfer find fail.\n");
446 } else { 446 } else {
447 purple_xfer_cancel_remote(xfer); 447 purple_xfer_cancel_remote(xfer);
448 } 448 }
449 } else { 449 } else {
450 purple_debug_info("Bonjour", "si offer Message type - Unknown-%d.\n", type); 450 purple_debug_info("bonjour", "si offer Message type - Unknown-%d.\n", type);
451 } 451 }
452 } 452 }
453 } 453 }
454 454
455 void 455 void
468 468
469 bd = (BonjourData*) pc->proto_data; 469 bd = (BonjourData*) pc->proto_data;
470 if(bd == NULL) 470 if(bd == NULL)
471 return; 471 return;
472 472
473 purple_debug_info("Bonjour", "xep-bytestreams-parse.\n"); 473 purple_debug_info("bonjour", "xep-bytestreams-parse.\n");
474 474
475 type = xmlnode_get_attrib(packet, "type"); 475 type = xmlnode_get_attrib(packet, "type");
476 from = pb->name; 476 from = pb->name;
477 query = xmlnode_get_child(packet,"query"); 477 query = xmlnode_get_child(packet,"query");
478 if(type) { 478 if(type) {
479 if(!strcmp(type, "set")){ 479 if(!strcmp(type, "set")){
480 purple_debug_info("Bonjour", "bytestream offer Message type - SET.\n"); 480 purple_debug_info("bonjour", "bytestream offer Message type - SET.\n");
481 481
482 id = xmlnode_get_attrib(query, "sid"); 482 id = xmlnode_get_attrib(query, "sid");
483 xfer = bonjour_si_xfer_find(bd, id, from); 483 xfer = bonjour_si_xfer_find(bd, id, from);
484 484
485 if(xfer){ 485 if(xfer){
495 495
496 if(!strcmp(host, xf->buddy_ip)) { 496 if(!strcmp(host, xf->buddy_ip)) {
497 xf->jid = g_strdup(jid); 497 xf->jid = g_strdup(jid);
498 xf->proxy_host = g_strdup(host); 498 xf->proxy_host = g_strdup(host);
499 xf->proxy_port = portnum; 499 xf->proxy_port = portnum;
500 purple_debug_info("Bonjour", "bytestream offer parse" 500 purple_debug_info("bonjour", "bytestream offer parse"
501 "jid=%s host=%s port=%d.\n", jid, host, portnum); 501 "jid=%s host=%s port=%d.\n", jid, host, portnum);
502 bonjour_bytestreams_connect(xfer); 502 bonjour_bytestreams_connect(xfer);
503 break; 503 break;
504 } 504 }
505 505
506 } else { 506 } else {
507 purple_debug_info("Bonjour", "bytestream offer Message parse error.\n"); 507 purple_debug_info("bonjour", "bytestream offer Message parse error.\n");
508 } 508 }
509 } 509 }
510 } else { 510 } else {
511 511
512 } 512 }
513 513
514 } else { 514 } else {
515 purple_debug_info("Bonjour", "bytestream offer Message type - Unknown-%d.\n", type); 515 purple_debug_info("bonjour", "bytestream offer Message type - Unknown-%d.\n", type);
516 } 516 }
517 } 517 }
518 } 518 }
519 519
520 static void 520 static void
530 530
531 bd = (BonjourData*) pc->proto_data; 531 bd = (BonjourData*) pc->proto_data;
532 if(bd == NULL) 532 if(bd == NULL)
533 return; 533 return;
534 534
535 purple_debug_info("Bonjour", "bonjour-xfer-receive.\n"); 535 purple_debug_info("bonjour", "bonjour-xfer-receive.\n");
536 536
537 /* Build the file transfer handle */ 537 /* Build the file transfer handle */
538 xfer = purple_xfer_new(pc->account, PURPLE_XFER_RECEIVE, from); 538 xfer = purple_xfer_new(pc->account, PURPLE_XFER_RECEIVE, from);
539 xfer->data = xf = g_new0(XepXfer, 1); 539 xfer->data = xf = g_new0(XepXfer, 1);
540 xf->data = bd; 540 xf->data = bd;
574 if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { 574 if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
575 575
576 } else if(acceptfd == -1) { 576 } else if(acceptfd == -1) {
577 577
578 } else { 578 } else {
579 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);
580 purple_input_remove(xfer->watcher); 580 purple_input_remove(xfer->watcher);
581 close(source); 581 close(source);
582 xfer->watcher = purple_input_add(acceptfd, PURPLE_INPUT_READ, 582 xfer->watcher = purple_input_add(acceptfd, PURPLE_INPUT_READ,
583 bonjour_sock5_request_cb, xfer); 583 bonjour_sock5_request_cb, xfer);
584 xf->sock5_req_state++; 584 xf->sock5_req_state++;
679 char *port; 679 char *port;
680 const char *next_ip; 680 const char *next_ip;
681 const char *local_ip = NULL; 681 const char *local_ip = NULL;
682 char token [] = ";"; 682 char token [] = ";";
683 683
684 purple_debug_info("Bonjour", "Bonjour-bytestreams-listen. sock=%d.\n", sock); 684 purple_debug_info("bonjour", "Bonjour-bytestreams-listen. sock=%d.\n", sock);
685 if (sock < 0 || xfer == NULL) { 685 if (sock < 0 || xfer == NULL) {
686 /*purple_xfer_cancel_local(xfer);*/ 686 /*purple_xfer_cancel_local(xfer);*/
687 return; 687 return;
688 } 688 }
689 689
722 bonjour_bytestreams_init(PurpleXfer *xfer) 722 bonjour_bytestreams_init(PurpleXfer *xfer)
723 { 723 {
724 XepXfer *xf = NULL; 724 XepXfer *xf = NULL;
725 if(xfer == NULL) 725 if(xfer == NULL)
726 return; 726 return;
727 purple_debug_info("Bonjour", "Bonjour-bytestreams-init.\n"); 727 purple_debug_info("bonjour", "Bonjour-bytestreams-init.\n");
728 xf = xfer->data; 728 xf = xfer->data;
729 purple_network_listen_map_external(FALSE);
729 xf->listen_data = purple_network_listen_range(0, 0, SOCK_STREAM, 730 xf->listen_data = purple_network_listen_range(0, 0, SOCK_STREAM,
730 bonjour_bytestreams_listen, xfer); 731 bonjour_bytestreams_listen, xfer);
732 purple_network_listen_map_external(TRUE);
731 if (xf->listen_data == NULL) { 733 if (xf->listen_data == NULL) {
732 purple_xfer_cancel_local(xfer); 734 purple_xfer_cancel_local(xfer);
733 } 735 }
734 return; 736 return;
735 } 737 }
760 int i; 762 int i;
761 763
762 if(xfer == NULL) 764 if(xfer == NULL)
763 return; 765 return;
764 766
765 purple_debug_info("Bonjour", "bonjour-bytestreams-connect.\n"); 767 purple_debug_info("bonjour", "bonjour-bytestreams-connect.\n");
766 768
767 xf = (XepXfer*)xfer->data; 769 xf = (XepXfer*)xfer->data;
768 if(!xf) 770 if(!xf)
769 return; 771 return;
770 772