Mercurial > pidgin
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 |