comparison src/protocols/oscar/ft.c @ 3771:765769211688

[gaim-migrate @ 3910] More FT cleanups by Wil Mahan. Thanks, Wil. committer: Tailor Script <tailor@pidgin.im>
author Rob Flynn <gaim@robflynn.com>
date Sun, 20 Oct 2002 23:46:56 +0000
parents b32474e522fa
children 07283934dedd
comparison
equal deleted inserted replaced
3770:a72e303e6f5c 3771:765769211688
7 7
8 #ifdef HAVE_CONFIG_H 8 #ifdef HAVE_CONFIG_H
9 #include <config.h> 9 #include <config.h>
10 #endif 10 #endif
11 #include <aim.h> 11 #include <aim.h>
12
13 12
14 #ifndef _WIN32 13 #ifndef _WIN32
15 #include <netdb.h> 14 #include <netdb.h>
16 #include <sys/socket.h> 15 #include <sys/socket.h>
17 #include <netinet/in.h> 16 #include <netinet/in.h>
23 22
24 #ifdef _WIN32 23 #ifdef _WIN32
25 #include "win32dep.h" 24 #include "win32dep.h"
26 #endif 25 #endif
27 26
28 27 #define AIM_OFT_PROTO_OFFER 0x0101
29 /* TODO: 28 #define AIM_OFT_PROTO_ACCEPT 0x0202
30 o look for memory leaks.. there's going to be shitloads, i'm sure. 29 #define AIM_OFT_PROTO_RESUME 0x0205
31 */ 30 #define AIM_OFT_PROTO_RESUMEACCEPT 0x0207
31 #define AIM_OFT_PROTO_ACK 0x0204
32
33 struct aim_filetransfer_priv {
34 char sn[MAXSNLEN+1];
35 char cookie[8];
36 char ip[30];
37 int state;
38 struct aim_fileheader_t fh;
39 };
32 40
33 struct aim_directim_intdata { 41 struct aim_directim_intdata {
34 fu8_t cookie[8]; 42 fu8_t cookie[8];
35 char sn[MAXSNLEN+1]; 43 char sn[MAXSNLEN+1];
36 char ip[22]; 44 char ip[22];
37 }; 45 };
38 46
39 static int listenestablish(fu16_t portnum); 47 static int listenestablish(fu16_t portnum);
40 static struct aim_fileheader_t *aim_oft_getfh(unsigned char *hdr); 48 static struct aim_fileheader_t *aim_oft_getfh(unsigned char *hdr);
49 static const char *oft_basename(const char *name);
41 50
42 /** 51 /**
43 * aim_handlerendconnect - call this to accept OFT connections and set up the required structures 52 * aim_handlerendconnect - call this to accept OFT connections and set up the required structures
44 * @sess: the session 53 * @sess: the session
45 * @cur: the conn the incoming connection is on 54 * @cur: the conn the incoming connection is on
89 98
90 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE))) 99 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE)))
91 ret = userfunc(sess, NULL, newconn, cur); 100 ret = userfunc(sess, NULL, newconn, cur);
92 101
93 } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) { 102 } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) {
103 #if 0
94 struct aim_filetransfer_priv *priv; 104 struct aim_filetransfer_priv *priv;
95 aim_rxcallback_t userfunc; 105 aim_rxcallback_t userfunc;
96 106
97 newconn->priv = cur->priv; 107 newconn->priv = cur->priv;
98 cur->priv = NULL; 108 cur->priv = NULL;
100 110
101 snprintf(priv->ip, sizeof(priv->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port)); 111 snprintf(priv->ip, sizeof(priv->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port));
102 112
103 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE))) 113 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE)))
104 ret = userfunc(sess, NULL, newconn, cur); 114 ret = userfunc(sess, NULL, newconn, cur);
115 #endif
105 } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_SENDFILE) { 116 } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_SENDFILE) {
106 struct aim_filetransfer_priv *ft; 117 struct aim_filetransfer_priv *ft;
107 aim_rxcallback_t userfunc; 118 aim_rxcallback_t userfunc;
108 119
109 /* The new conn automatically inherits the priv value 120 /* The new conn automatically inherits the internal value
110 * of cur. */ 121 * of cur. */
111 cur->priv = NULL; 122 cur->internal = NULL;
112 ft = (struct aim_filetransfer_priv *)newconn->priv; 123 ft = (struct aim_filetransfer_priv *)newconn->internal;
113 124
114 snprintf(ft->ip, sizeof(ft->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port)); 125 snprintf(ft->ip, sizeof(ft->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port));
115 126
116 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE))) 127 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_SENDFILEINITIATE)))
117 ret = userfunc(sess, NULL, newconn, cur); 128 ret = userfunc(sess, NULL, newconn, cur);
118 } else { 129 } else {
119 faimdprintf(sess, 1,"Got a Connection on a listener that's not Rendezvous Closing conn.\n"); 130 faimdprintf(sess, 1,"Got a Connection on a listener that's not Rendezvous Closing conn.\n");
120 aim_conn_close(newconn); 131 aim_conn_close(newconn);
121 ret = -1; 132 ret = -1;
367 aim_conn_t *newconn; 378 aim_conn_t *newconn;
368 aim_msgcookie_t *cookie; 379 aim_msgcookie_t *cookie;
369 struct aim_filetransfer_priv *ft; 380 struct aim_filetransfer_priv *ft;
370 int listenfd; 381 int listenfd;
371 382
372 /* Due to other limitations, we can only initiate one 383 /* XXX allow different ports */
373 * sendfile transfer at a time, so it seems safe to
374 * restrict the listener to a single port. -- wtm
375 */
376 fu16_t port = 4443; 384 fu16_t port = 4443;
377 fu8_t localip[4]; 385 fu8_t localip[4];
378 fu8_t ck[8]; 386 fu8_t ck[8];
379 387
380 if (getlocalip(localip) == -1) 388 if (getlocalip(localip) == -1)
381 return NULL; 389 return NULL;
382 390
383 if ((listenfd = listenestablish(port)) == -1) 391 if ((listenfd = listenestablish(port)) == -1)
384 return NULL; 392 return NULL;
385 393
386 { 394 aim_request_sendfile(sess, destsn, oft_basename(filename),
387 /* XXX */ 395 numfiles, totsize, localip, port, ck);
388 char *basename = g_path_get_basename(filename);
389 aim_request_sendfile(sess, destsn, basename,
390 numfiles, totsize, localip, port, ck);
391 g_free(basename);
392 }
393 396
394 cookie = (aim_msgcookie_t *)calloc(1, sizeof(aim_msgcookie_t)); 397 cookie = (aim_msgcookie_t *)calloc(1, sizeof(aim_msgcookie_t));
395 memcpy(cookie->cookie, ck, 8); 398 memcpy(cookie->cookie, ck, 8);
396 cookie->type = AIM_COOKIETYPE_OFTSEND; 399 cookie->type = AIM_COOKIETYPE_OFTSEND;
397 memcpy(cookret, ck, 8); 400 memcpy(cookret, ck, 8);
415 memcpy(ft->cookie, ck, 8); 418 memcpy(ft->cookie, ck, 8);
416 strncpy(ft->sn, destsn, sizeof(ft->sn)); 419 strncpy(ft->sn, destsn, sizeof(ft->sn));
417 420
418 newconn->fd = listenfd; 421 newconn->fd = listenfd;
419 newconn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE; 422 newconn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE;
420 newconn->priv = ft; 423 newconn->internal = ft;
421 newconn->lastactivity = time(NULL); 424 newconn->lastactivity = time(NULL);
422 425
423 faimdprintf(sess, 2,"faim: listening (fd = %d, unconnected)\n", newconn->fd); 426 faimdprintf(sess, 2,"faim: listening (fd = %d, unconnected)\n", newconn->fd);
424 427
425 return newconn; 428 return newconn;
610 613
611 aim_putcap(&newpacket->data, rendid); 614 aim_putcap(&newpacket->data, rendid);
612 aim_tx_enqueue(sess, newpacket); 615 aim_tx_enqueue(sess, newpacket);
613 616
614 617
615 g_snprintf(addr, sizeof(addr), "%s:%d", ip, port); 618 snprintf(addr, sizeof(addr), "%s:%d", ip, port);
616 newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS, addr); 619 newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS, addr);
617 620
618 if (newconn->status & AIM_CONN_STATUS_CONNERR) { 621 if (newconn->status & AIM_CONN_STATUS_CONNERR) {
619 return NULL; 622 return NULL;
620 } 623 }
629 632
630 memcpy(priv->cookie, cookie, 8); 633 memcpy(priv->cookie, cookie, 8);
631 priv->state = 0; 634 priv->state = 0;
632 strncpy(priv->sn, sn, MAXSNLEN); 635 strncpy(priv->sn, sn, MAXSNLEN);
633 strncpy(priv->ip, ip, sizeof(priv->ip)); 636 strncpy(priv->ip, ip, sizeof(priv->ip));
634 newconn->priv = (void *)priv; 637 newconn->internal = (void *)priv;
635 638
636 faimdprintf(sess, 2, "faim: connected to peer (fd = %d)\n", newconn->fd); 639 faimdprintf(sess, 2, "faim: connected to peer (fd = %d)\n", newconn->fd);
637 640
638 if (rendid == AIM_CAPS_GETFILE) { 641 if (rendid == AIM_CAPS_GETFILE) {
639 return NULL; /* This should never happen for now. -- wtm */ 642 return NULL; /* This should never happen for now. -- wtm */
1055 } 1058 }
1056 1059
1057 static void connclose_sendfile(aim_session_t *sess, aim_conn_t *conn) 1060 static void connclose_sendfile(aim_session_t *sess, aim_conn_t *conn)
1058 { 1061 {
1059 aim_msgcookie_t *cook; 1062 aim_msgcookie_t *cook;
1060 struct aim_filetransfer_priv *priv = (struct aim_filetransfer_priv *)conn->priv; 1063 struct aim_filetransfer_priv *priv = (struct aim_filetransfer_priv *)conn->internal;
1061 1064
1062 cook = aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTSEND); 1065 cook = aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTSEND);
1063 aim_cookie_free(sess, cook); 1066 aim_cookie_free(sess, cook);
1064 1067
1065 return; 1068 return;
1066 } 1069 }
1067 1070
1068 static void connkill_sendfile(aim_session_t *sess, aim_conn_t *conn) 1071 static void connkill_sendfile(aim_session_t *sess, aim_conn_t *conn)
1069 { 1072 {
1070 /* XXX we don't free conn->priv here because it is currently 1073 free(conn->internal);
1071 * freed in the caller. If that ever changes, we should
1072 * free it here. -- wtm
1073 */
1074 conn->priv = NULL;
1075 1074
1076 return; 1075 return;
1077 } 1076 }
1078 1077
1079 static void connclose_getfile(aim_session_t *sess, aim_conn_t *conn) 1078 static void connclose_getfile(aim_session_t *sess, aim_conn_t *conn)
1080 { 1079 {
1080 #if 0
1081 aim_msgcookie_t *cook; 1081 aim_msgcookie_t *cook;
1082 struct aim_filetransfer_priv *priv = (struct aim_filetransfer_priv *)conn->priv; 1082 struct aim_filetransfer_priv *priv = (struct aim_filetransfer_priv *)conn->priv;
1083 1083
1084 cook = aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTGET); 1084 cook = aim_uncachecookie(sess, priv->cookie, AIM_COOKIETYPE_OFTGET);
1085 aim_cookie_free(sess, cook); 1085 aim_cookie_free(sess, cook);
1086 1086 #endif
1087 return; 1087 return;
1088 } 1088 }
1089 1089
1090 static void connkill_getfile(aim_session_t *sess, aim_conn_t *conn) 1090 static void connkill_getfile(aim_session_t *sess, aim_conn_t *conn)
1091 { 1091 {
1447 #else 1447 #else
1448 return -1; 1448 return -1;
1449 #endif 1449 #endif
1450 } 1450 }
1451 1451
1452 /* We are receiving a file, and the buddy sent us this header describing
1453 * it. We send back a similar header to confirm, then we're ready to
1454 * start reading the raw data.
1455 */
1452 static int handlehdr_sendfile_sending(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) 1456 static int handlehdr_sendfile_sending(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr)
1453 { 1457 {
1454 struct aim_filetransfer_priv *ft; 1458 struct aim_filetransfer_priv *ft;
1455 struct aim_fileheader_t *fh; 1459 struct aim_fileheader_t *fh;
1456 aim_frame_t *newoft; 1460 aim_frame_t *newoft;
1459 fh = aim_oft_getfh(hdr); 1463 fh = aim_oft_getfh(hdr);
1460 1464
1461 /* We receive a null cookie for the first file; we must fill 1465 /* We receive a null cookie for the first file; we must fill
1462 * it in to authenticate ourselves. -- wtm 1466 * it in to authenticate ourselves. -- wtm
1463 */ 1467 */
1464 ft = conn->priv; 1468 ft = conn->internal;
1465 memcpy(&(fh->bcookie), ft->cookie, 8); 1469 memcpy(&(fh->bcookie), ft->cookie, 8);
1466 1470
1467 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t)); 1471 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t));
1468 free(fh); 1472 free(fh);
1469 1473
1470 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0202, 0))) { 1474 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, AIM_OFT_PROTO_ACCEPT, 0))) {
1471 faimdprintf(sess, 2, "faim: send_final_transfer: tx_new OFT failed\n"); 1475 faimdprintf(sess, 2, "faim: send_final_transfer: tx_new OFT failed\n");
1472 return -1; 1476 return -1;
1473 } 1477 }
1474 1478
1475 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 1479 memcpy(newoft->hdr.oft.magic, "OFT2", 4);
1486 return -1; 1490 return -1;
1487 } 1491 }
1488 1492
1489 aim_tx_enqueue(sess, newoft); 1493 aim_tx_enqueue(sess, newoft);
1490 1494
1491 faimdprintf(sess, 2, "faim: OFT: OFT 0x0202 enqueued.\n"); 1495 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_SENDFILEFILEREQ)) == NULL)
1492
1493 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ)) == NULL)
1494 return 1; 1496 return 1;
1495 1497
1496 { 1498 {
1497 char *cur; 1499 char *cur;
1498 /* Convert the directory separator: it is sent 1500 /* Convert the directory separator: it is sent
1500 */ 1502 */
1501 while ((cur = strchr(ft->fh.name, 0x01))) { 1503 while ((cur = strchr(ft->fh.name, 0x01))) {
1502 *cur = G_DIR_SEPARATOR; 1504 *cur = G_DIR_SEPARATOR;
1503 } 1505 }
1504 } 1506 }
1505 return userfunc(sess, NULL, conn, ft->fh.name, ft->fh.size); 1507 return userfunc(sess, NULL, conn, &(ft->fh));
1506 } 1508 }
1507 1509
1508 1510
1509 /* 1511 /*
1510 * These were originally described by Josh Myer: 1512 * These were originally described by Josh Myer:
1550 free(fh); 1552 free(fh);
1551 1553
1552 return 0; 1554 return 0;
1553 } 1555 }
1554 1556
1557 /* We are sending a file, and the buddy sent us this header indicating
1558 * that he or she is ready for the raw data.
1559 */
1555 static int handlehdr_sendfile_recv(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) { 1560 static int handlehdr_sendfile_recv(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) {
1556 struct aim_fileheader_t *fh; 1561 struct aim_fileheader_t *fh;
1557 aim_msgcookie_t *cook; 1562 aim_msgcookie_t *cook;
1558 int ret = 1; 1563 int ret = 1;
1559 struct aim_filetransfer_priv *ft; 1564 struct aim_filetransfer_priv *ft;
1564 free(fh); 1569 free(fh);
1565 return -1; 1570 return -1;
1566 } 1571 }
1567 ft = (struct aim_filetransfer_priv *)cook->data; 1572 ft = (struct aim_filetransfer_priv *)cook->data;
1568 1573
1569 faimdprintf(sess, 2, "faim: get_rend: looks like we're ready to send data.(oft 0x0202)\n"); 1574 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_SENDFILEFILESEND)) )
1570 1575 ret = userfunc(sess, NULL, conn, &(ft->fh));
1571 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND)) )
1572 ret = userfunc(sess, NULL, conn, ft->fh.nrecvd);
1573 1576
1574 free(fh); 1577 free(fh);
1575 1578
1576 return ret; 1579 return ret;
1577 } 1580 }
1605 #else 1608 #else
1606 return -1; 1609 return -1;
1607 #endif 1610 #endif
1608 } 1611 }
1609 1612
1613 /* We just sent the raw data of a file, and the buddy sent us back this
1614 * header indicating that the transfer is complete.
1615 */
1610 static int handlehdr_sendfile_finish(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) 1616 static int handlehdr_sendfile_finish(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr)
1611 { 1617 {
1612 struct aim_fileheader_t *fh; 1618 struct aim_fileheader_t *fh;
1613 aim_msgcookie_t *cook; 1619 aim_msgcookie_t *cook;
1614 aim_rxcallback_t userfunc; 1620 aim_rxcallback_t userfunc;
1618 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTSEND))) { 1624 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTSEND))) {
1619 free(fh); 1625 free(fh);
1620 return -1; 1626 return -1;
1621 } 1627 }
1622 1628
1623 faimdprintf(sess, 2, "faim: get_rend: looks like we're done with a transfer (oft 0x0204)\n"); 1629 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_SENDFILECOMPLETE)) )
1624
1625 debug_printf("sendfile: receiver sent checksum %x\n", fh->recvcsum);
1626
1627 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE)) )
1628 userfunc(sess, NULL, conn, fh->bcookie); 1630 userfunc(sess, NULL, conn, fh->bcookie);
1629 1631
1630 free(fh); 1632 free(fh);
1631 return 0; 1633 return 0;
1632 } 1634 }
1663 fu8_t hdrbuf1[6]; 1665 fu8_t hdrbuf1[6];
1664 fu8_t *hdr = NULL; 1666 fu8_t *hdr = NULL;
1665 int hdrlen, hdrtype; 1667 int hdrlen, hdrtype;
1666 int ret = -1; 1668 int ret = -1;
1667 1669
1668 if (!sess || !conn) 1670
1669 return -1; 1671 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) {
1672 /* This should never happen. -- wtm */
1673 return getcommand_getfile(sess, conn);
1674 }
1670 1675
1671 memset(hdrbuf1, 0, sizeof(hdrbuf1)); 1676 memset(hdrbuf1, 0, sizeof(hdrbuf1));
1672 1677
1673 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) {
1674 /* This should never happen yet. -- wtm */
1675 return getcommand_getfile(sess, conn);
1676 }
1677
1678 /* XXX fix all the error cases here */
1679 if (aim_recv(conn->fd, hdrbuf1, 6) < 6) { 1678 if (aim_recv(conn->fd, hdrbuf1, 6) < 6) {
1680 faimdprintf(sess, 2, "faim: rend: read error (fd: %i)\n", conn->fd); 1679 faimdprintf(sess, 2, "faim: rend: read error (fd: %i)\n", conn->fd);
1681
1682 aim_conn_close(conn); 1680 aim_conn_close(conn);
1683
1684 return -1; 1681 return -1;
1685 } 1682 }
1686 1683
1687 hdrlen = aimutil_get16(hdrbuf1+4); 1684 hdrlen = aimutil_get16(hdrbuf1+4);
1688 hdrlen -= 6; 1685 hdrlen -= 6;
1689 1686
1690 hdr = malloc(hdrlen); 1687 hdr = malloc(hdrlen);
1688 if (!hdr) {
1689 aim_conn_close(conn);
1690 return -1;
1691 }
1691 1692
1692 if (aim_recv(conn->fd, hdr, hdrlen) < hdrlen) { 1693 if (aim_recv(conn->fd, hdr, hdrlen) < hdrlen) {
1693 faimdprintf(sess, 2, "faim: rend: read2 error on %d (%d)\n", conn->fd, hdrlen); 1694 faimdprintf(sess, 2, "faim: rend: read2 error on %d (%d)\n", conn->fd, hdrlen);
1694 free(hdr); 1695 free(hdr);
1695 aim_conn_close(conn); 1696 aim_conn_close(conn);
1698 1699
1699 hdrtype = aimutil_get16(hdr); 1700 hdrtype = aimutil_get16(hdr);
1700 1701
1701 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_SENDFILE) { 1702 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_SENDFILE) {
1702 switch(hdrtype) { 1703 switch(hdrtype) {
1703 case 0x0101: 1704 case AIM_OFT_PROTO_OFFER:
1704 ret = handlehdr_sendfile_sending(sess, conn, hdr); 1705 ret = handlehdr_sendfile_sending(sess, conn,
1706 hdr);
1705 break; 1707 break;
1706 case 0x0205: 1708 case AIM_OFT_PROTO_RESUME:
1707 /* This seems equivalent to 0x0202,
1708 * but has the nrecvd and nrecvcsum
1709 * fields filled in. We send back a
1710 * 0x0106, and get then a 0x0207 which
1711 * we treat just like a 0x0202. -- wtm */
1712 ret = handlehdr_sendfile_resume(sess, 1709 ret = handlehdr_sendfile_resume(sess,
1713 conn, hdr); 1710 conn, hdr);
1714 break; 1711 break;
1715 case 0x0207: /* see above */; 1712 case AIM_OFT_PROTO_RESUMEACCEPT: /* like _ACCEPT */;
1716 case 0x0202: 1713 case AIM_OFT_PROTO_ACCEPT:
1717 ret = handlehdr_sendfile_recv(sess, conn, hdr); 1714 ret = handlehdr_sendfile_recv(sess, conn, hdr);
1718 break; 1715 break;
1719 case 0x0204: 1716 case AIM_OFT_PROTO_ACK:
1720 ret = handlehdr_sendfile_finish(sess, conn, hdr); 1717 ret = handlehdr_sendfile_finish(sess, conn, hdr);
1721 break; 1718 break;
1722 default: 1719 default:
1723 debug_printf("unknown header type %x received", hdrtype); 1720 faimdprintf(sess, 2, "faim: OFT frame: uknown type %04x\n", hdrtype);
1724 ret = -1; 1721 ret = -1;
1725 break; 1722 break;
1726 } 1723 }
1727 free(hdr); 1724 free(hdr);
1728 if (ret == -1) 1725 if (ret == -1)
1730 return ret; 1727 return ret;
1731 } 1728 }
1732 1729
1733 if (hdrtype == 0x0001) 1730 if (hdrtype == 0x0001)
1734 ret = handlehdr_directim(sess, conn, hdr); 1731 ret = handlehdr_directim(sess, conn, hdr);
1732
1733 /* This _really_ shouldn't happen. :) -- wtm */
1734
1735 else if (hdrtype == 0x1108) /* getfile listing.txt incoming tx->rx */ 1735 else if (hdrtype == 0x1108) /* getfile listing.txt incoming tx->rx */
1736 ret = handlehdr_getfile_listing(sess, conn, hdr); 1736 ret = handlehdr_getfile_listing(sess, conn, hdr);
1737 else if (hdrtype == 0x1209) /* get file listing ack rx->tx */ 1737 else if (hdrtype == 0x1209) /* get file listing ack rx->tx */
1738 ret = handlehdr_getfile_listing2(sess, conn, hdr); 1738 ret = handlehdr_getfile_listing2(sess, conn, hdr);
1739 else if (hdrtype == 0x120b) /* get file listing rx confirm */ 1739 else if (hdrtype == 0x120b) /* get file listing rx confirm */
1873 return check << 16; 1873 return check << 16;
1874 } 1874 }
1875 1875
1876 faim_export fu32_t aim_update_checksum(aim_session_t *sess, aim_conn_t *conn, 1876 faim_export fu32_t aim_update_checksum(aim_session_t *sess, aim_conn_t *conn,
1877 const unsigned char *buffer, int len) { 1877 const unsigned char *buffer, int len) {
1878 struct aim_filetransfer_priv *ft = conn->priv; 1878 struct aim_filetransfer_priv *ft = conn->internal;
1879 1879
1880 ft->fh.nrecvd += len; 1880 ft->fh.nrecvd += len;
1881 ft->fh.recvcsum = aim_oft_checksum(buffer, len, ft->fh.recvcsum); 1881 ft->fh.recvcsum = aim_oft_checksum(buffer, len, ft->fh.recvcsum);
1882 1882
1883 return 0; 1883 return 0;
2078 return NULL; 2078 return NULL;
2079 } 2079 }
2080 2080
2081 newconn->fd = listenfd; 2081 newconn->fd = listenfd;
2082 newconn->subtype = AIM_CONN_SUBTYPE_OFT_GETFILE; 2082 newconn->subtype = AIM_CONN_SUBTYPE_OFT_GETFILE;
2083 newconn->priv = priv; 2083 newconn->internal = priv;
2084 faimdprintf(sess, 2,"faim: listening (fd = %d, unconnected)\n", newconn->fd); 2084 faimdprintf(sess, 2,"faim: listening (fd = %d, unconnected)\n", newconn->fd);
2085 2085
2086 return newconn; 2086 return newconn;
2087 #endif 2087 #endif
2088 } 2088 }
2139 #endif 2139 #endif
2140 2140
2141 /* Identify a file that we are about to send by transmitting the 2141 /* Identify a file that we are about to send by transmitting the
2142 * appropriate header. 2142 * appropriate header.
2143 */ 2143 */
2144 faim_export int aim_oft_sendfile_request(aim_session_t *sess, aim_conn_t *conn, const char *name, int filesdone, int numfiles, int size, int totsize) 2144 faim_export int aim_oft_sendfile_request(aim_session_t *sess, aim_conn_t *conn, const char *filename, int filesdone, int numfiles, int size, int totsize)
2145 { 2145 {
2146 aim_frame_t *newoft; 2146 aim_frame_t *newoft;
2147 aim_msgcookie_t *cook; 2147 aim_msgcookie_t *cook;
2148 struct aim_filetransfer_priv *ft = (struct aim_filetransfer_priv *)conn->priv; 2148 struct aim_filetransfer_priv *ft = (struct aim_filetransfer_priv *)conn->internal;
2149 struct aim_fileheader_t *fh; 2149 struct aim_fileheader_t *fh;
2150 2150
2151 if (!sess || !conn || !name) 2151 if (!sess || !conn || !filename)
2152 return -1; 2152 return -1;
2153 2153
2154 if (!(fh = (struct aim_fileheader_t*)calloc(1, sizeof(struct aim_fileheader_t)))) 2154 if (!(fh = (struct aim_fileheader_t*)calloc(1, sizeof(struct aim_fileheader_t))))
2155 return -1; 2155 return -1;
2156 2156
2161 * the WinAIM clients, we seem to be able to get away with just 2161 * the WinAIM clients, we seem to be able to get away with just
2162 * setting the checksum to zero. 2162 * setting the checksum to zero.
2163 * -- wtm 2163 * -- wtm
2164 */ 2164 */
2165 { 2165 {
2166 int fd = open(name, O_RDONLY); 2166 int fd = open(filename, O_RDONLY);
2167 if (fd >= 0) { 2167 if (fd >= 0) {
2168 int bytes; 2168 int bytes;
2169 char buf[1024]; 2169 char buf[1024];
2170 fh->checksum = 0xffff0000; 2170 fh->checksum = 0xffff0000;
2171 while ((bytes = read(fd, buf, 1024)) > 0) { 2171 while ((bytes = read(fd, buf, 1024)) > 0) {
2204 2204
2205 /* we need to figure out these encodings for filenames */ 2205 /* we need to figure out these encodings for filenames */
2206 fh->nencode = 0x0000; 2206 fh->nencode = 0x0000;
2207 fh->nlanguage = 0x0000; 2207 fh->nlanguage = 0x0000;
2208 2208
2209 { 2209 /* Don't "show full pathname to buddy", just because it is
2210 /* Don't "show full pathname to buddy", just because it is 2210 * non-portable. -- wtm
2211 * non-portable. -- wtm 2211 */
2212 */ 2212 strncpy(fh->name, oft_basename(filename), sizeof(fh->name));
2213 char *basename = g_path_get_basename(name);
2214 strncpy(fh->name, basename, sizeof(fh->name));
2215 g_free(basename);
2216 }
2217 2213
2218 /* XXX we should normally send a null cookie here, and make 2214 /* XXX we should normally send a null cookie here, and make
2219 * the receiver fill it in for authentication -- wtm 2215 * the receiver fill it in for authentication -- wtm
2220 */ 2216 */
2221 memcpy(fh->bcookie, ft->cookie, 8); 2217 memcpy(fh->bcookie, ft->cookie, 8);
2227 /* Update both headers to be safe. */ 2223 /* Update both headers to be safe. */
2228 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t)); 2224 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t));
2229 memcpy(&(((struct aim_filetransfer_priv *)cook->data)->fh), fh, 2225 memcpy(&(((struct aim_filetransfer_priv *)cook->data)->fh), fh,
2230 sizeof(struct aim_fileheader_t)); 2226 sizeof(struct aim_fileheader_t));
2231 2227
2232 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0101, 0))) { 2228 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, AIM_OFT_PROTO_OFFER, 0))) {
2233 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n"); 2229 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n");
2234 free(fh); 2230 free(fh);
2235 return -1; 2231 return -1;
2236 } 2232 }
2237 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 2233 memcpy(newoft->hdr.oft.magic, "OFT2", 4);
2314 faim_export int aim_oft_end(aim_session_t *sess, aim_conn_t *conn) 2310 faim_export int aim_oft_end(aim_session_t *sess, aim_conn_t *conn)
2315 { 2311 {
2316 aim_frame_t *newoft; 2312 aim_frame_t *newoft;
2317 struct aim_filetransfer_priv *ft; 2313 struct aim_filetransfer_priv *ft;
2318 2314
2319 if (!sess || !conn || !conn->priv) 2315 if (!sess || !conn || !conn->internal)
2320 return -1; 2316 return -1;
2321 2317
2322 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0204, 0))) { 2318 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, AIM_OFT_PROTO_ACK, 0))) {
2323 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n"); 2319 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n");
2324 return -1; 2320 return -1;
2325 } 2321 }
2326 2322
2327 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 2323 memcpy(newoft->hdr.oft.magic, "OFT2", 4);
2330 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { 2326 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) {
2331 aim_frame_destroy(newoft); 2327 aim_frame_destroy(newoft);
2332 return -1; 2328 return -1;
2333 } 2329 }
2334 2330
2335 ft = (struct aim_filetransfer_priv *)conn->priv; 2331 ft = (struct aim_filetransfer_priv *)conn->internal;
2336 ft->state = 4; /* no longer wanting data */ 2332 ft->state = 4; /* no longer wanting data */
2337 ft->fh.flags = 0x21; 2333 ft->fh.flags = 0x21;
2338 2334
2339 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)))) { 2335 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)))) {
2340 aim_frame_destroy(newoft); 2336 aim_frame_destroy(newoft);
2344 aim_tx_enqueue(sess, newoft); 2340 aim_tx_enqueue(sess, newoft);
2345 2341
2346 return 0; 2342 return 0;
2347 } 2343 }
2348 2344
2345 /* Portability. Yuck. */
2346 static const char *oft_basename(const char *name) {
2347 const char *r = strrchr(name, G_DIR_SEPARATOR);
2348 r = r ? r + 1 : name;
2349 return r;
2350 }
2351