| 46 xfer->type = type; |
47 xfer->type = type; |
| 47 xfer->account = account; |
48 xfer->account = account; |
| 48 xfer->who = g_strdup(who); |
49 xfer->who = g_strdup(who); |
| 49 xfer->ui_ops = gaim_xfers_get_ui_ops(); |
50 xfer->ui_ops = gaim_xfers_get_ui_ops(); |
| 50 |
51 |
| 51 xfer->local_ip = g_strdup(gaim_xfers_get_ip_for_account(account)); |
|
| 52 |
|
| 53 ui_ops = gaim_xfer_get_ui_ops(xfer); |
52 ui_ops = gaim_xfer_get_ui_ops(xfer); |
| 54 |
53 |
| 55 if (ui_ops != NULL && ui_ops->new_xfer != NULL) |
54 if (ui_ops != NULL && ui_ops->new_xfer != NULL) |
| 56 ui_ops->new_xfer(xfer); |
55 ui_ops->new_xfer(xfer); |
| 57 |
56 |
| 278 |
276 |
| 279 return ((double)gaim_xfer_get_bytes_sent(xfer) / |
277 return ((double)gaim_xfer_get_bytes_sent(xfer) / |
| 280 (double)gaim_xfer_get_size(xfer)); |
278 (double)gaim_xfer_get_size(xfer)); |
| 281 } |
279 } |
| 282 |
280 |
| 283 const char * |
|
| 284 gaim_xfer_get_local_ip(const GaimXfer *xfer) |
|
| 285 { |
|
| 286 g_return_val_if_fail(xfer != NULL, NULL); |
|
| 287 |
|
| 288 return xfer->local_ip; |
|
| 289 } |
|
| 290 |
|
| 291 unsigned int |
281 unsigned int |
| 292 gaim_xfer_get_local_port(const GaimXfer *xfer) |
282 gaim_xfer_get_local_port(const GaimXfer *xfer) |
| 293 { |
283 { |
| 294 g_return_val_if_fail(xfer != NULL, -1); |
284 g_return_val_if_fail(xfer != NULL, -1); |
| 295 |
285 |
| 392 |
382 |
| 393 xfer->ops.request_denied = fnc; |
383 xfer->ops.request_denied = fnc; |
| 394 } |
384 } |
| 395 |
385 |
| 396 void |
386 void |
| 397 gaim_xfer_set_read_fnc(GaimXfer *xfer, size_t (*fnc)(char **, GaimXfer *)) |
387 gaim_xfer_set_read_fnc(GaimXfer *xfer, ssize_t (*fnc)(char **, GaimXfer *)) |
| 398 { |
388 { |
| 399 g_return_if_fail(xfer != NULL); |
389 g_return_if_fail(xfer != NULL); |
| 400 |
390 |
| 401 xfer->ops.read = fnc; |
391 xfer->ops.read = fnc; |
| 402 } |
392 } |
| 403 |
393 |
| 404 void |
394 void |
| 405 gaim_xfer_set_write_fnc(GaimXfer *xfer, |
395 gaim_xfer_set_write_fnc(GaimXfer *xfer, |
| 406 size_t (*fnc)(const char *, size_t, GaimXfer *)) |
396 ssize_t (*fnc)(const char *, size_t, GaimXfer *)) |
| 407 { |
397 { |
| 408 g_return_if_fail(xfer != NULL); |
398 g_return_if_fail(xfer != NULL); |
| 409 |
399 |
| 410 xfer->ops.write = fnc; |
400 xfer->ops.write = fnc; |
| 411 } |
401 } |
| 449 g_return_if_fail(xfer != NULL); |
439 g_return_if_fail(xfer != NULL); |
| 450 |
440 |
| 451 xfer->ops.cancel_recv = fnc; |
441 xfer->ops.cancel_recv = fnc; |
| 452 } |
442 } |
| 453 |
443 |
| 454 size_t |
444 ssize_t |
| 455 gaim_xfer_read(GaimXfer *xfer, char **buffer) |
445 gaim_xfer_read(GaimXfer *xfer, char **buffer) |
| 456 { |
446 { |
| 457 size_t s, r; |
447 ssize_t s, r; |
| 458 |
448 |
| 459 g_return_val_if_fail(xfer != NULL, 0); |
449 g_return_val_if_fail(xfer != NULL, 0); |
| 460 g_return_val_if_fail(buffer != NULL, 0); |
450 g_return_val_if_fail(buffer != NULL, 0); |
| 461 |
451 |
| 462 if (gaim_xfer_get_size(xfer) == 0) |
452 if (gaim_xfer_get_size(xfer) == 0) |
| 476 } |
466 } |
| 477 |
467 |
| 478 return r; |
468 return r; |
| 479 } |
469 } |
| 480 |
470 |
| 481 size_t |
471 ssize_t |
| 482 gaim_xfer_write(GaimXfer *xfer, const char *buffer, size_t size) |
472 gaim_xfer_write(GaimXfer *xfer, const char *buffer, size_t size) |
| 483 { |
473 { |
| 484 size_t r, s; |
474 ssize_t r, s; |
| 485 |
475 |
| 486 g_return_val_if_fail(xfer != NULL, 0); |
476 g_return_val_if_fail(xfer != NULL, 0); |
| 487 g_return_val_if_fail(buffer != NULL, 0); |
477 g_return_val_if_fail(buffer != NULL, 0); |
| 488 g_return_val_if_fail(size != 0, 0); |
478 g_return_val_if_fail(size != 0, 0); |
| 489 |
479 |
| 490 s = MIN(gaim_xfer_get_bytes_remaining(xfer), size); |
480 s = MIN(gaim_xfer_get_bytes_remaining(xfer), size); |
| 491 |
481 |
| 492 if (xfer->ops.write != NULL) |
482 if (xfer->ops.write != NULL) { |
| 493 r = (xfer->ops.write)(buffer, s, xfer); |
483 r = (xfer->ops.write)(buffer, s, xfer); |
| 494 else |
484 } else { |
| 495 r = write(xfer->fd, buffer, s); |
485 r = write(xfer->fd, buffer, s); |
| |
486 if ((gaim_xfer_get_bytes_sent(xfer)+r) >= gaim_xfer_get_size(xfer)) |
| |
487 gaim_xfer_set_completed(xfer, TRUE); |
| |
488 } |
| 496 |
489 |
| 497 return r; |
490 return r; |
| 498 } |
491 } |
| 499 |
492 |
| 500 static void |
493 static void |
| 505 char *buffer = NULL; |
498 char *buffer = NULL; |
| 506 size_t r; |
499 size_t r; |
| 507 |
500 |
| 508 if (condition & GAIM_INPUT_READ) { |
501 if (condition & GAIM_INPUT_READ) { |
| 509 r = gaim_xfer_read(xfer, &buffer); |
502 r = gaim_xfer_read(xfer, &buffer); |
| 510 if (r > 0) |
503 if (r > 0) { |
| 511 fwrite(buffer, 1, r, xfer->dest_fp); |
504 fwrite(buffer, 1, r, xfer->dest_fp); |
| |
505 } else { |
| |
506 gaim_xfer_cancel_remote(xfer); |
| |
507 return; |
| |
508 } |
| 512 } |
509 } |
| 513 else { |
510 else { |
| 514 size_t s = MIN(gaim_xfer_get_bytes_remaining(xfer), 4096); |
511 size_t s = MIN(gaim_xfer_get_bytes_remaining(xfer), 4096); |
| 515 |
512 |
| 516 buffer = g_malloc0(s); |
513 buffer = g_malloc0(s); |
| 518 fread(buffer, 1, s, xfer->dest_fp); |
515 fread(buffer, 1, s, xfer->dest_fp); |
| 519 |
516 |
| 520 /* Write as much as we're allowed to. */ |
517 /* Write as much as we're allowed to. */ |
| 521 r = gaim_xfer_write(xfer, buffer, s); |
518 r = gaim_xfer_write(xfer, buffer, s); |
| 522 |
519 |
| 523 if (r < s) { |
520 if (r == -1) { |
| |
521 gaim_xfer_cancel_remote(xfer); |
| |
522 g_free(buffer); |
| |
523 return; |
| |
524 } else if (r < s) { |
| 524 /* We have to seek back in the file now. */ |
525 /* We have to seek back in the file now. */ |
| 525 fseek(xfer->dest_fp, r - s, SEEK_CUR); |
526 fseek(xfer->dest_fp, r - s, SEEK_CUR); |
| 526 } |
527 } |
| 527 } |
528 } |
| 528 |
529 |
| 763 } |
764 } |
| 764 |
765 |
| 765 /************************************************************************** |
766 /************************************************************************** |
| 766 * File Transfer Subsystem API |
767 * File Transfer Subsystem API |
| 767 **************************************************************************/ |
768 **************************************************************************/ |
| 768 void |
|
| 769 gaim_xfers_set_local_ip(const char *ip) |
|
| 770 { |
|
| 771 g_return_if_fail(ip != NULL); |
|
| 772 |
|
| 773 gaim_prefs_set_string("/core/ft/public_ip", ip); |
|
| 774 } |
|
| 775 |
|
| 776 const char * |
|
| 777 gaim_xfers_get_local_ip(void) |
|
| 778 { |
|
| 779 const char *ip; |
|
| 780 |
|
| 781 ip = gaim_prefs_get_string("/core/ft/public_ip"); |
|
| 782 |
|
| 783 if (ip == NULL || *ip == '\0') |
|
| 784 return NULL; |
|
| 785 |
|
| 786 return ip; |
|
| 787 } |
|
| 788 |
|
| 789 const char * |
|
| 790 gaim_xfers_get_local_system_ip(void) |
|
| 791 { |
|
| 792 struct hostent *host; |
|
| 793 char localhost[129]; |
|
| 794 long unsigned add; |
|
| 795 static char ip[46]; |
|
| 796 |
|
| 797 if (gethostname(localhost, 128) < 0) |
|
| 798 return NULL; |
|
| 799 |
|
| 800 if ((host = gethostbyname(localhost)) == NULL) |
|
| 801 return NULL; |
|
| 802 |
|
| 803 memcpy(&add, host->h_addr_list[0], 4); |
|
| 804 add = htonl(add); |
|
| 805 |
|
| 806 g_snprintf(ip, 16, "%lu.%lu.%lu.%lu", |
|
| 807 ((add >> 24) & 255), |
|
| 808 ((add >> 16) & 255), |
|
| 809 ((add >> 8) & 255), |
|
| 810 add & 255); |
|
| 811 |
|
| 812 return ip; |
|
| 813 } |
|
| 814 |
|
| 815 const char * |
|
| 816 gaim_xfers_get_ip_for_account(const GaimAccount *account) |
|
| 817 { |
|
| 818 g_return_val_if_fail(account != NULL, NULL); |
|
| 819 |
|
| 820 if (gaim_account_get_public_ip(account) != NULL) |
|
| 821 return gaim_account_get_public_ip(account); |
|
| 822 else if (gaim_xfers_get_local_ip() != NULL) |
|
| 823 return gaim_xfers_get_local_ip(); |
|
| 824 else |
|
| 825 return gaim_xfers_get_local_system_ip(); |
|
| 826 } |
|
| 827 |
|
| 828 void |
|
| 829 gaim_xfers_init(void) |
|
| 830 { |
|
| 831 gaim_prefs_add_none("/core/ft"); |
|
| 832 gaim_prefs_add_string("/core/ft/public_ip", ""); |
|
| 833 } |
|
| 834 |
769 |
| 835 void |
770 void |
| 836 gaim_xfers_set_ui_ops(GaimXferUiOps *ops) |
771 gaim_xfers_set_ui_ops(GaimXferUiOps *ops) |
| 837 { |
772 { |
| 838 xfer_ui_ops = ops; |
773 xfer_ui_ops = ops; |