comparison src/protocols/oscar/ft.c @ 3630:9682c0e022c6

[gaim-migrate @ 3753] Yeah this will probably break a lot of shit knowing my luck. But hey, I really don't care what people thnk. committer: Tailor Script <tailor@pidgin.im>
author Rob Flynn <gaim@robflynn.com>
date Fri, 11 Oct 2002 03:14:01 +0000
parents 1143524a2eaf
children bfd8df165f32
comparison
equal deleted inserted replaced
3629:afc5bb164c5a 3630:9682c0e022c6
14 #ifndef _WIN32 14 #ifndef _WIN32
15 #include <netdb.h> 15 #include <netdb.h>
16 #include <sys/socket.h> 16 #include <sys/socket.h>
17 #include <netinet/in.h> 17 #include <netinet/in.h>
18 #include <sys/utsname.h> /* for aim_directim_initiate */ 18 #include <sys/utsname.h> /* for aim_directim_initiate */
19
20 #include <arpa/inet.h> /* for inet_ntoa */ 19 #include <arpa/inet.h> /* for inet_ntoa */
21 20 #else
22 #endif 21 #include "win32dep.h"
22 #endif
23
24 #include "gaim.h"
23 25
24 /* TODO: 26 /* TODO:
25 o look for memory leaks.. there's going to be shitloads, i'm sure. 27 o look for memory leaks.. there's going to be shitloads, i'm sure.
26 */ 28 */
27 29
30 char sn[MAXSNLEN+1]; 32 char sn[MAXSNLEN+1];
31 char ip[22]; 33 char ip[22];
32 }; 34 };
33 35
34 static int listenestablish(fu16_t portnum); 36 static int listenestablish(fu16_t portnum);
37 static struct aim_fileheader_t *aim_oft_getfh(unsigned char *hdr);
35 38
36 /** 39 /**
37 * aim_handlerendconnect - call this to accept OFT connections and set up the required structures 40 * aim_handlerendconnect - call this to accept OFT connections and set up the required structures
38 * @sess: the session 41 * @sess: the session
39 * @cur: the conn the incoming connection is on 42 * @cur: the conn the incoming connection is on
54 57
55 if ((acceptfd = accept(cur->fd, &cliaddr, &clilen)) == -1) 58 if ((acceptfd = accept(cur->fd, &cliaddr, &clilen)) == -1)
56 return 0; /* not an error */ 59 return 0; /* not an error */
57 60
58 if (cliaddr.sa_family != AF_INET) { /* just in case IPv6 really is happening */ 61 if (cliaddr.sa_family != AF_INET) { /* just in case IPv6 really is happening */
62 #ifndef _WIN32
59 close(acceptfd); 63 close(acceptfd);
64 #else
65 closesocket(acceptfd);
66 #endif
60 aim_conn_close(cur); 67 aim_conn_close(cur);
61 return -1; 68 return -1;
62 } 69 }
63 70
64 if (!(newconn = aim_cloneconn(sess, cur))) { 71 if (!(newconn = aim_cloneconn(sess, cur))) {
72 #ifndef _WIN32
65 close(acceptfd); 73 close(acceptfd);
74 #else
75 closesocket(acceptfd);
76 #endif
66 aim_conn_close(cur); 77 aim_conn_close(cur);
67 return -1; 78 return -1;
68 } 79 }
69 80
70 newconn->type = AIM_CONN_TYPE_RENDEZVOUS; 81 newconn->type = AIM_CONN_TYPE_RENDEZVOUS;
83 94
84 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE))) 95 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_DIRECTIMINITIATE)))
85 ret = userfunc(sess, NULL, newconn, cur); 96 ret = userfunc(sess, NULL, newconn, cur);
86 97
87 } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) { 98 } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) {
88 #if 0
89 struct aim_filetransfer_priv *priv; 99 struct aim_filetransfer_priv *priv;
90 aim_rxcallback_t userfunc; 100 aim_rxcallback_t userfunc;
91
92 101
93 newconn->priv = cur->priv; 102 newconn->priv = cur->priv;
94 cur->priv = NULL; 103 cur->priv = NULL;
95 priv = (struct aim_filetransfer_priv *)newconn->priv; 104 priv = (struct aim_filetransfer_priv *)newconn->priv;
96 105
97 snprintf(priv->ip, sizeof(priv->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port)); 106 snprintf(priv->ip, sizeof(priv->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port));
98 107
99 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE))) 108 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE)))
100 ret = userfunc(sess, NULL, newconn, cur); 109 ret = userfunc(sess, NULL, newconn, cur);
101 #endif 110 } else if (newconn->subtype == AIM_CONN_SUBTYPE_OFT_SENDFILE) {
111 struct aim_filetransfer_priv *ft;
112 aim_rxcallback_t userfunc;
113
114 /* The new conn automatically inherits the priv value
115 * of cur. */
116 cur->priv = NULL;
117 ft = (struct aim_filetransfer_priv *)newconn->priv;
118
119 snprintf(ft->ip, sizeof(ft->ip), "%s:%u", inet_ntoa(((struct sockaddr_in *)&cliaddr)->sin_addr), ntohs(((struct sockaddr_in *)&cliaddr)->sin_port));
120
121 if ((userfunc = aim_callhandler(sess, newconn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEINITIATE)))
122 ret = userfunc(sess, NULL, newconn, cur);
102 } else { 123 } else {
103 faimdprintf(sess, 1,"Got a Connection on a listener that's not Rendezvous Closing conn.\n"); 124 faimdprintf(sess, 1,"Got a Connection on a listener that's not Rendezvous Closing conn.\n");
104 aim_conn_close(newconn); 125 aim_conn_close(newconn);
105 ret = -1; 126 ret = -1;
106 } 127 }
316 cookie->data = priv; 337 cookie->data = priv;
317 aim_cachecookie(sess, cookie); 338 aim_cachecookie(sess, cookie);
318 339
319 /* XXX switch to aim_cloneconn()? */ 340 /* XXX switch to aim_cloneconn()? */
320 if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS_OUT, NULL))) { 341 if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS_OUT, NULL))) {
342 #ifndef _WIN32
321 close(listenfd); 343 close(listenfd);
344 #else
345 closesocket(listenfd);
346 #endif
322 return NULL; 347 return NULL;
323 } 348 }
324 349
325 /* this one is for the conn */ 350 /* this one is for the conn */
326 priv = (struct aim_directim_intdata *)calloc(1, sizeof(struct aim_directim_intdata)); 351 priv = (struct aim_directim_intdata *)calloc(1, sizeof(struct aim_directim_intdata));
344 * @conn: the BOS conn, 369 * @conn: the BOS conn,
345 * @destsn: the SN to connect to. 370 * @destsn: the SN to connect to.
346 * @filename: the name of the files you want to send 371 * @filename: the name of the files you want to send
347 * 372 *
348 */ 373 */
349 faim_export aim_conn_t *aim_sendfile_initiate(aim_session_t *sess, const char *destsn, const char *filename, fu16_t numfiles, fu32_t totsize) 374 faim_export aim_conn_t *aim_sendfile_initiate(aim_session_t *sess, const char *destsn, const char *filename, fu16_t numfiles, fu32_t totsize, char *cookret)
350 { 375 {
351 aim_conn_t *newconn; 376 aim_conn_t *newconn;
352 aim_msgcookie_t *cookie; 377 aim_msgcookie_t *cookie;
353 struct aim_directim_intdata *priv; 378 struct aim_filetransfer_priv *ft;
354 int listenfd; 379 int listenfd;
380
381 /* Due to other limitations, we can only initiate one
382 * sendfile transfer at a time, so it seems safe to
383 * restrict the listener to a single port. -- wtm
384 */
355 fu16_t port = 4443; 385 fu16_t port = 4443;
356 fu8_t localip[4]; 386 fu8_t localip[4];
357 fu8_t ck[8]; 387 fu8_t ck[8];
358 388
359 if (getlocalip(localip) == -1) 389 if (getlocalip(localip) == -1)
360 return NULL; 390 return NULL;
361 391
362 if ((listenfd = listenestablish(port)) == -1) 392 if ((listenfd = listenestablish(port)) == -1)
363 return NULL; 393 return NULL;
364 394
365 aim_request_sendfile(sess, destsn, filename, numfiles, totsize, localip, port, ck); 395 {
396 /* XXX */
397 char *basename = g_path_get_basename(filename);
398 aim_request_sendfile(sess, destsn, basename,
399 numfiles, totsize, localip, port, ck);
400 g_free(basename);
401 }
366 402
367 cookie = (aim_msgcookie_t *)calloc(1, sizeof(aim_msgcookie_t)); 403 cookie = (aim_msgcookie_t *)calloc(1, sizeof(aim_msgcookie_t));
368 memcpy(cookie->cookie, ck, 8); 404 memcpy(cookie->cookie, ck, 8);
369 cookie->type = AIM_COOKIETYPE_OFTIM; 405 cookie->type = AIM_COOKIETYPE_OFTSEND;
406 memcpy(cookret, ck, 8);
370 407
371 /* this one is for the cookie */ 408 /* this one is for the cookie */
372 priv = (struct aim_directim_intdata *)calloc(1, sizeof(struct aim_directim_intdata)); 409 ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv));
373 410
374 memcpy(priv->cookie, ck, 8); 411 memcpy(ft->cookie, ck, 8);
375 strncpy(priv->sn, destsn, sizeof(priv->sn)); 412 strncpy(ft->sn, destsn, sizeof(ft->sn));
376 cookie->data = priv; 413 cookie->data = ft;
377 aim_cachecookie(sess, cookie); 414 aim_cachecookie(sess, cookie);
378 415
379 /* XXX switch to aim_cloneconn()? */
380 if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS_OUT, NULL))) { 416 if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS_OUT, NULL))) {
417 #ifndef _WIN32
381 close(listenfd); 418 close(listenfd);
419 #else
420 closesocket(listenfd);
421 #endif
382 return NULL; 422 return NULL;
383 } 423 }
384 424
385 /* this one is for the conn */ 425 /* this one is for the conn */
386 priv = (struct aim_directim_intdata *)calloc(1, sizeof(struct aim_directim_intdata)); 426 ft = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv));
387 427
388 memcpy(priv->cookie, ck, 8); 428 memcpy(ft->cookie, ck, 8);
389 strncpy(priv->sn, destsn, sizeof(priv->sn)); 429 strncpy(ft->sn, destsn, sizeof(ft->sn));
390 430
391 newconn->fd = listenfd; 431 newconn->fd = listenfd;
392 newconn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE; 432 newconn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE;
393 newconn->internal = priv; 433 newconn->priv = ft;
394 newconn->lastactivity = time(NULL); 434 newconn->lastactivity = time(NULL);
395 435
396 faimdprintf(sess, 2,"faim: listening (fd = %d, unconnected)\n", newconn->fd); 436 faimdprintf(sess, 2,"faim: listening (fd = %d, unconnected)\n", newconn->fd);
397 437
398 return newconn; 438 return newconn;
404 * @sess: session to clean up in 444 * @sess: session to clean up in
405 * @age: maximum age in seconds 445 * @age: maximum age in seconds
406 * 446 *
407 * returns number closed, -1 on error. 447 * returns number closed, -1 on error.
408 */ 448 */
409 faim_export unsigned int aim_oft_listener_clean(struct aim_session_t *sess, time_t age) 449 faim_export unsigned int aim_oft_listener_clean(aim_session_t *sess,
450 time_t age)
410 { 451 {
411 struct aim_conn_t *cur; 452 aim_conn_t *cur;
412 time_t now; 453 time_t now;
413 unsigned int hit = 0; 454 unsigned int hit = 0;
414 455
415 if (!sess) 456 if (!sess)
416 return -1; 457 return -1;
417 now = time(NULL); 458 now = time(NULL);
418 faim_mutex_lock(&sess->connlistlock);
419 for(cur = sess->connlist;cur; cur = cur->next) 459 for(cur = sess->connlist;cur; cur = cur->next)
420 if (cur->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) { 460 if (cur->type == AIM_CONN_TYPE_RENDEZVOUS_OUT) {
421 faim_mutex_lock(&cur->active);
422 if (cur->lastactivity < (now - age) ) { 461 if (cur->lastactivity < (now - age) ) {
423 faim_mutex_unlock(&cur->active);
424 aim_conn_close(cur); 462 aim_conn_close(cur);
425 hit++; 463 hit++;
426 } else 464 }
427 faim_mutex_unlock(&cur->active);
428 } 465 }
429 faim_mutex_unlock(&sess->connlistlock);
430 return hit; 466 return hit;
431 } 467 }
432 #endif 468 #endif
433 469
434 faim_export const char *aim_directim_getsn(aim_conn_t *conn) 470 faim_export const char *aim_directim_getsn(aim_conn_t *conn)
531 * @sess: the session, 567 * @sess: the session,
532 * @conn: the BOS conn for the CAP reply 568 * @conn: the BOS conn for the CAP reply
533 * @sn: the screenname to send it to, 569 * @sn: the screenname to send it to,
534 * @cookie: the cookie used 570 * @cookie: the cookie used
535 * @ip: the ip to connect to 571 * @ip: the ip to connect to
572 * @port: the port to use
573 * @rendid: capability type (%AIM_CAPS_GETFILE or %AIM_CAPS_SENDFILE)
574 *
536 * @listingfiles: number of files to share 575 * @listingfiles: number of files to share
537 * @listingtotsize: total size of shared files 576 * @listingtotsize: total size of shared files
538 * @listingsize: length of the listing file(buffer) 577 * @listingsize: length of the listing file(buffer)
539 * @listingchecksum: checksum of the listing 578 * @listingchecksum: checksum of the listing
540 * @rendid: capability type (%AIM_CAPS_GETFILE or %AIM_CAPS_SENDFILE)
541 * 579 *
542 * Returns new connection or %NULL on error. 580 * Returns new connection or %NULL on error.
543 * 581 *
544 * XXX this should take a struct. 582 * XXX this should take a struct.
545 */ 583 */
546 faim_export aim_conn_t *aim_accepttransfer(aim_session_t *sess, 584 faim_export aim_conn_t *aim_accepttransfer(aim_session_t *sess,
547 aim_conn_t *conn, 585 aim_conn_t *conn,
548 const char *sn, const fu8_t *cookie, 586 const char *sn, const fu8_t *cookie,
549 const fu8_t *ip, 587 const fu8_t *ip,
550 fu16_t listingfiles, 588 fu16_t port,
551 fu16_t listingtotsize, 589 fu16_t rendid,
552 fu16_t listingsize, 590 ...)
553 fu32_t listingchecksum, 591 {
554 fu16_t rendid) 592 aim_frame_t *newpacket;
555 { 593 aim_conn_t *newconn;
556 return NULL;
557 #if 0
558 struct command_tx_struct *newpacket, *newoft;
559 struct aim_conn_t *newconn;
560 struct aim_fileheader_t *fh;
561 struct aim_filetransfer_priv *priv; 594 struct aim_filetransfer_priv *priv;
562 struct aim_msgcookie_t *cachedcook; 595 int i;
563 int curbyte, i; 596 char addr[21];
564 597
565 if (!sess || !conn || !sn || !cookie || !ip) { 598 if (!sess || !conn || !sn || !cookie || !ip) {
566 return NULL; 599 return NULL;
567 } 600 }
568 601
569 newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS, ip); 602 /* OSCAR CAP accept packet */
603
604
605 if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x0002, 10+8+2+1+strlen(sn)+4+2+8+16))) {
606 return NULL;
607 }
608
609 aim_putsnac(&newpacket->data, 0x0004, 0x0006, 0x0000, sess->snacid_next);
610
611 for (i = 0; i < 8; i++)
612 aimbs_put8(&newpacket->data, cookie[i]);
613
614 aimbs_put16(&newpacket->data, 0x0002);
615 aimbs_put8(&newpacket->data, strlen(sn));
616 aimbs_putraw(&newpacket->data, sn, strlen(sn));
617 aimbs_put16(&newpacket->data, 0x0005);
618 aimbs_put16(&newpacket->data, 0x001a);
619 aimbs_put16(&newpacket->data, AIM_RENDEZVOUS_ACCEPT);
620
621 for (i = 0; i < 8; i++) /* yes, again... */
622 aimbs_put8(&newpacket->data, cookie[i]);
623
624 aim_putcap(&newpacket->data, rendid);
625 aim_tx_enqueue(sess, newpacket);
626
627
628 g_snprintf(addr, sizeof(addr), "%s:%d", ip, port);
629 newconn = aim_newconn(sess, AIM_CONN_TYPE_RENDEZVOUS, addr);
630
631 if (newconn->status & AIM_CONN_STATUS_CONNERR) {
632 return NULL;
633 }
570 634
571 if (!newconn || (newconn->fd == -1)) { 635 if (!newconn || (newconn->fd == -1)) {
572 perror("aim_newconn"); 636 perror("aim_newconn");
573 faimdprintf(sess, 2, "could not connect to %s (fd: %i)\n", ip, newconn?newconn->fd:0); 637 faimdprintf(sess, 2, "could not connect to %s (fd: %i)\n", ip, newconn?newconn->fd:0);
574 return newconn; 638 return newconn;
575 } else { 639 }
576 priv = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv)); 640
577 641 priv = (struct aim_filetransfer_priv *)calloc(1, sizeof(struct aim_filetransfer_priv));
578 memcpy(priv->cookie, cookie, 8); 642
579 priv->state = 0; 643 memcpy(priv->cookie, cookie, 8);
580 strncpy(priv->sn, sn, MAXSNLEN); 644 priv->state = 0;
581 strncpy(priv->ip, ip, sizeof(priv->ip)); 645 strncpy(priv->sn, sn, MAXSNLEN);
582 newconn->priv = (void *)priv; 646 strncpy(priv->ip, ip, sizeof(priv->ip));
583 647 newconn->priv = (void *)priv;
584 faimdprintf(sess, 2, "faim: connected to peer (fd = %d)\n", newconn->fd); 648
585 } 649 faimdprintf(sess, 2, "faim: connected to peer (fd = %d)\n", newconn->fd);
586 650
587 if (rendid == AIM_CAPS_GETFILE) { 651 if (rendid == AIM_CAPS_GETFILE) {
652 return NULL; /* This should never happen for now. -- wtm */
653 #if 0
654 struct aim_fileheader_t *fh;
655 aim_frame_t *newoft;
656 aim_msgcookie_t *cachedcook;
657 /* XXX take the following parameters fu16_t listingfiles,
658 fu16_t listingtotsize,
659 fu16_t listingsize,
660 fu32_t listingchecksum, */
661
588 newconn->subtype = AIM_CONN_SUBTYPE_OFT_GETFILE; 662 newconn->subtype = AIM_CONN_SUBTYPE_OFT_GETFILE;
589 663
590 faimdprintf(sess, 2, "faim: getfile request accept\n"); 664 faimdprintf(sess, 2, "faim: getfile request accept\n");
591 665
592 if (!(newoft = aim_tx_new(sess, newconn, AIM_FRAMETYPE_OFT, 0x1108, 0))) { 666 if (!(newoft = aim_tx_new(sess, newconn, AIM_FRAMETYPE_OFT, 0x1108, 0))) {
593 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n"); 667 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n");
594 /* XXX: conn leak here */ 668 /* XXX: conn leak here */
595 return NULL; 669 return NULL;
596 } 670 }
597 671
598 newoft->lock = 1;
599 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 672 memcpy(newoft->hdr.oft.magic, "OFT2", 4);
600 newoft->hdr.oft.hdr2len = 0x100 - 8; 673 newoft->hdr.oft.hdr2len = 0x100 - 8;
601 674
602 if (!(fh = (struct aim_fileheader_t*)calloc(1, sizeof(struct aim_fileheader_t)))) { 675 if (!(fh = (struct aim_fileheader_t*)calloc(1, sizeof(struct aim_fileheader_t)))) {
603 /* XXX: conn leak here */ 676 /* XXX: conn leak here */
620 fh->cretime = 0x00000000; 693 fh->cretime = 0x00000000;
621 fh->rfcsum = 0x00000000; 694 fh->rfcsum = 0x00000000;
622 fh->nrecvd = 0x00000000; 695 fh->nrecvd = 0x00000000;
623 fh->recvcsum = 0x00000000; 696 fh->recvcsum = 0x00000000;
624 memset(fh->idstring, 0, sizeof(fh->idstring)); 697 memset(fh->idstring, 0, sizeof(fh->idstring));
625 memcpy(fh->idstring, "OFT_Windows ICBMFT V1.1 32", sizeof(fh->idstring)); 698 strncpy(fh->idstring, "OFT_Windows ICBMFT V1.1 32", sizeof(fh->idstring));
626 fh->flags = 0x02; 699 fh->flags = 0x02;
627 fh->lnameoffset = 0x1a; 700 fh->lnameoffset = 0x1a;
628 fh->lsizeoffset = 0x10; 701 fh->lsizeoffset = 0x10;
629 memset(fh->dummy, 0, sizeof(fh->dummy)); 702 memset(fh->dummy, 0, sizeof(fh->dummy));
630 memset(fh->macfileinfo, 0, sizeof(fh->macfileinfo)); 703 memset(fh->macfileinfo, 0, sizeof(fh->macfileinfo));
631 704
632 /* we need to figure out these encodings for filenames */ 705 /* we need to figure out these encodings for filenames */
633 fh->nencode = 0x0000; 706 fh->nencode = 0x0000;
634 fh->nlanguage = 0x0000; 707 fh->nlanguage = 0x0000;
635 memset(fh->name, 0, sizeof(fh->name)); 708 memset(fh->name, 0, sizeof(fh->name));
636 memcpy(fh->name, "listing.txt", sizeof(fh->name)); 709 strncpy(fh->name, "listing.txt", sizeof(fh->name));
637 710
638 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { 711 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) {
639 newoft->lock = 0;
640 aim_frame_destroy(newoft); 712 aim_frame_destroy(newoft);
641 /* XXX: conn leak */ 713 /* XXX: conn leak */
642 perror("calloc (1)"); 714 perror("calloc (1)");
643 return NULL; 715 return NULL;
644 } 716 }
646 memcpy(fh->bcookie, cookie, 8); 718 memcpy(fh->bcookie, cookie, 8);
647 719
648 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, fh))) 720 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, fh)))
649 faimdprintf(sess, 1, "eek, bh fail!\n"); 721 faimdprintf(sess, 1, "eek, bh fail!\n");
650 722
651 newoft->lock = 0;
652 aim_tx_enqueue(sess, newoft); 723 aim_tx_enqueue(sess, newoft);
653 724
654 if (!(cachedcook = (struct aim_msgcookie_t *)calloc(1, sizeof(struct aim_msgcookie_t)))) { 725 if (!(cachedcook = (aim_msgcookie_t *)calloc(1, sizeof(aim_msgcookie_t)))) {
655 faimdprintf(sess, 1, "faim: accepttransfer: couldn't calloc cachedcook. yeep!\n"); 726 faimdprintf(sess, 1, "faim: accepttransfer: couldn't calloc cachedcook. yeep!\n");
656 /* XXX: more cleanup, conn leak */ 727 /* XXX: more cleanup, conn leak */
657 perror("calloc (2)"); 728 perror("calloc (2)");
658 return NULL; 729 return NULL;
659 } 730 }
660 731
661 memcpy(&(priv->fh), fh, sizeof(struct aim_fileheader_t)); 732 memcpy(&(priv->fh), fh, sizeof(struct aim_fileheader_t));
662 memcpy(cachedcook->cookie, cookie, 8); 733 memcpy(cachedcook->cookie, cookie, 8);
663 734
664 cachedcook->type = AIM_COOKIETYPE_OFTGET; 735 cachedcook->type = AIM_COOKIETYPE_OFTGET;
736 /* XXX doesn't priv need to be copied so we don't
737 * double free? -- wtm
738 */
665 cachedcook->data = (void *)priv; 739 cachedcook->data = (void *)priv;
666 740
667 if (aim_cachecookie(sess, cachedcook) == -1) 741 if (aim_cachecookie(sess, cachedcook) == -1)
668 faimdprintf(sess, 1, "faim: ERROR caching message cookie\n"); 742 faimdprintf(sess, 1, "faim: ERROR caching message cookie\n");
669 743
670 free(fh); 744 free(fh);
671 745 #endif
672 /* OSCAR CAP accept packet */ 746
673 747 } else if (rendid == AIM_CAPS_SENDFILE) {
674 if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_OSCAR, 0x0002, 10+8+2+1+strlen(sn)+4+2+8+16))) { 748 newconn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE;
675 return NULL; 749 priv->fh.recvcsum = 0xffff0000;
676 }
677 } else { 750 } else {
678 return NULL; 751 return NULL;
679 } 752 }
753
754 return newconn;
755 }
756
757 /* conn is a BOS connection over which to send the cancel msg */
758 faim_export int aim_canceltransfer(aim_session_t *sess, aim_conn_t *conn,
759 const char *cookie, const char *sn, int rendid)
760 {
761 aim_frame_t *newpacket;
762 int i;
763
764 if (!(newpacket = aim_tx_new(sess, conn, AIM_FRAMETYPE_FLAP, 0x0002, 10+8+2+1+strlen(sn)+4+2+8+16))) {
765 return 1;
766 }
680 767
681 newpacket->lock = 1; 768 aim_putsnac(&newpacket->data, 0x0004, 0x0006, 0x0000, sess->snacid_next);
682 curbyte = aim_putsnac(newpacket->data, 0x0004, 0x0006, 0x0000, sess->snac_nextid);
683 769
684 for (i = 0; i < 8; i++) 770 for (i = 0; i < 8; i++)
685 curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]); 771 aimbs_put8(&newpacket->data, cookie[i]);
686 772
687 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002); 773 aimbs_put16(&newpacket->data, 0x0002);
688 curbyte += aimutil_put8(newpacket->data+curbyte, strlen(sn)); 774 aimbs_put8(&newpacket->data, strlen(sn));
689 curbyte += aimutil_putstr(newpacket->data+curbyte, sn, strlen(sn)); 775 aimbs_putraw(&newpacket->data, sn, strlen(sn));
690 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0005); 776 aimbs_put16(&newpacket->data, 0x0005);
691 curbyte += aimutil_put16(newpacket->data+curbyte, 0x001a); 777 aimbs_put16(&newpacket->data, 0x001a);
692 curbyte += aimutil_put16(newpacket->data+curbyte, 0x0002 /* accept*/); 778 aimbs_put16(&newpacket->data, AIM_RENDEZVOUS_CANCEL);
693 779
694 for (i = 0;i < 8; i++) 780 for (i = 0; i < 8; i++)
695 curbyte += aimutil_put8(newpacket->data+curbyte, cookie[i]); 781 aimbs_put8(&newpacket->data, cookie[i]);
696 782
697 curbyte += aim_putcap(newpacket->data+curbyte, 0x10, rendid); 783 aim_putcap(&newpacket->data, rendid);
698 newpacket->lock = 0;
699 aim_tx_enqueue(sess, newpacket); 784 aim_tx_enqueue(sess, newpacket);
700 785
701 return newconn; 786 return 0;
702 #endif
703 } 787 }
704 788
705 /** 789 /**
706 * aim_getlisting(FILE *file) -- get an aim_fileheader_t for a given FILE* 790 * aim_getlisting(FILE *file) -- get an aim_fileheader_t for a given FILE*
707 * @file is an opened listing file 791 * @file is an opened listing file
812 896
813 fh->nencode = 0x0000; /* we need to figure out these encodings for filenames */ 897 fh->nencode = 0x0000; /* we need to figure out these encodings for filenames */
814 fh->nlanguage = 0x0000; 898 fh->nlanguage = 0x0000;
815 899
816 /* memset(fh->name, 0, sizeof(fh->name)); */ 900 /* memset(fh->name, 0, sizeof(fh->name)); */
817 memcpy(fh->name, "listing.txt", sizeof(fh->name)); 901 strncpy(fh->name, "listing.txt", sizeof(fh->name));
818 memset(fh->name+strlen(fh->name), 0, 64-strlen(fh->name)); 902 memset(fh->name+strlen(fh->name), 0, 64-strlen(fh->name));
819 903
820 faimdprintf(sess, 2, "faim: OFT: listing fh name %s / %s\n", fh->name, (fh->name+(strlen(fh->name)))); 904 faimdprintf(sess, 2, "faim: OFT: listing fh name %s / %s\n", fh->name, (fh->name+(strlen(fh->name))));
821 return fh; 905 return fh;
822 #endif 906 #endif
856 continue; 940 continue;
857 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 941 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
858 if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0) 942 if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0)
859 break; 943 break;
860 /* success */ 944 /* success */
945 #ifndef _WIN32
861 close(listenfd); 946 close(listenfd);
947 #else
948 closesocket(listenfd);
949 #endif
862 } while ( (res = res->ai_next) ); 950 } while ( (res = res->ai_next) );
863 951
864 if (!res) 952 if (!res)
865 return -1; 953 return -1;
866 954
867 if (listen(listenfd, 1024)!=0) { 955 if (listen(listenfd, 1024)!=0) {
868 perror("listen"); 956 perror("listen");
869 return -1; 957 return -1;
870 } 958 }
959
960 fcntl(listenfd, F_SETFL, O_NONBLOCK);
871 961
872 freeaddrinfo(ressave); 962 freeaddrinfo(ressave);
873 return listenfd; 963 return listenfd;
874 #else 964 #else
875 int listenfd; 965 int listenfd;
881 return -1; 971 return -1;
882 } 972 }
883 973
884 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) != 0) { 974 if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) != 0) {
885 perror("setsockopt(listenfd)"); 975 perror("setsockopt(listenfd)");
976 #ifndef _WIN32
886 close(listenfd); 977 close(listenfd);
978 #else
979 closesocket(listenfd);
980 #endif
887 return -1; 981 return -1;
888 } 982 }
889 983
890 memset(&sockin, 0, sizeof(struct sockaddr_in)); 984 memset(&sockin, 0, sizeof(struct sockaddr_in));
891 sockin.sin_family = AF_INET; 985 sockin.sin_family = AF_INET;
892 sockin.sin_port = htons(portnum); 986 sockin.sin_port = htons(portnum);
893 987
894 if (bind(listenfd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) { 988 if (bind(listenfd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) {
895 perror("bind(listenfd)"); 989 perror("bind(listenfd)");
990 #ifndef _WIN32
896 close(listenfd); 991 close(listenfd);
992 #else
993 closesocket(listenfd);
994 #endif
897 return -1; 995 return -1;
898 } 996 }
899 if (listen(listenfd, 4) != 0) { 997 if (listen(listenfd, 4) != 0) {
900 perror("listen(listenfd)"); 998 perror("listen(listenfd)");
999 #ifndef _WIN32
901 close(listenfd); 1000 close(listenfd);
902 return -1; 1001 #else
903 } 1002 closesocket(listenfd);
1003 #endif
1004 return -1;
1005 }
1006 fcntl(listenfd, F_SETFL, O_NONBLOCK);
904 return listenfd; 1007 return listenfd;
905 #endif 1008 #endif
906 } 1009 }
907 1010
908 static int getcommand_getfile(aim_session_t *sess, aim_conn_t *conn) 1011 static int getcommand_getfile(aim_session_t *sess, aim_conn_t *conn)
914 ft = conn->priv; 1017 ft = conn->priv;
915 if (ft->state == 2) { 1018 if (ft->state == 2) {
916 /* waiting on listing data */ 1019 /* waiting on listing data */
917 int ret = 0; 1020 int ret = 0;
918 char *listing; 1021 char *listing;
919 struct command_tx_struct *newoft; 1022 aim_frame_t *newoft;
920 1023
921 if (!(listing = malloc(ft->fh.size))) 1024 if (!(listing = malloc(ft->fh.size)))
922 return -1; 1025 return -1;
923 1026
924 ft->state = 0; 1027 ft->state = 0;
925 if (aim_recv(conn->fd, listing, ft->fh.size) != ft->fh.size) 1028 if (aim_recv(conn->fd, listing, ft->fh.size) != ft->fh.size)
926 faimdprintf(sess, 2, "OFT get: file %s was short. (0x%lx)\n", ft->fh.name, ft->fh.size); 1029 faimdprintf(sess, 2, "OFT get: file %s was short. (0x%lx)\n", ft->fh.name, ft->fh.size);
927 1030
928 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x120b, 0))) { 1031 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x120b, 0))) {
929 faimdprintf(sess, 2, "faim: aim_get_command_rendezvous: getfile listing: tx_new OFT failed\n"); 1032 faimdprintf(sess, 2, "faim: aim_get_command_rendezvous: getfile listing: tx_new OFT failed\n");
930 faim_mutex_unlock(&conn->active);
931 free(listing); 1033 free(listing);
932 aim_conn_close(conn); 1034 aim_conn_close(conn);
933 return -1; 1035 return -1;
934 } 1036 }
935 1037
961 } 1063 }
962 1064
963 if (ft->state == 3) { 1065 if (ft->state == 3) {
964 /* waiting on file data */ 1066 /* waiting on file data */
965 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILERECEIVE)) ) 1067 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILERECEIVE)) )
966 return userfunc(sess, NULL, conn, ft); 1068 return userfunc(sess, NULL, conn, ft->fh.name,
1069 ft->fh.size);
967 return 0; 1070 return 0;
968 } 1071 }
969 1072
970 if (ft->state == 4) { 1073 if (ft->state == 4) {
971 if( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILESTATE4)) ) 1074 if( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILESTATE4)) )
991 return; 1094 return;
992 } 1095 }
993 1096
994 static void connkill_sendfile(aim_session_t *sess, aim_conn_t *conn) 1097 static void connkill_sendfile(aim_session_t *sess, aim_conn_t *conn)
995 { 1098 {
996 1099 /* XXX we don't free conn->priv here because it is currently
997 free(conn->internal); 1100 * freed in the caller. If that ever changes, we should
1101 * free it here. -- wtm
1102 */
1103 conn->priv = NULL;
998 1104
999 return; 1105 return;
1000 } 1106 }
1001 1107
1002 static void connclose_getfile(aim_session_t *sess, aim_conn_t *conn) 1108 static void connclose_getfile(aim_session_t *sess, aim_conn_t *conn)
1141 { 1247 {
1142 #if 0 1248 #if 0
1143 struct aim_filetransfer_priv *ft; 1249 struct aim_filetransfer_priv *ft;
1144 struct aim_fileheader_t *fh; 1250 struct aim_fileheader_t *fh;
1145 struct aim_msgcookie_t *cook; 1251 struct aim_msgcookie_t *cook;
1146 struct command_tx_struct *newoft; 1252 aim_frame_t *newoft;
1147 aim_rxcallback_t userfunc; 1253 aim_rxcallback_t userfunc;
1148 1254
1149 faimdprintf(sess, 2,"faim: rend: fileget 0x1108\n"); 1255 faimdprintf(sess, 2,"faim: rend: fileget 0x1108\n");
1150 fh = aim_oft_getfh(hdr); 1256 fh = aim_oft_getfh(hdr);
1151 1257
1257 1363
1258 static int handlehdr_getfile_request(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) 1364 static int handlehdr_getfile_request(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr)
1259 { 1365 {
1260 #if 0 1366 #if 0
1261 struct aim_filetransfer_priv *ft; 1367 struct aim_filetransfer_priv *ft;
1262 struct aim_msgcookie_t *cook; 1368 aim_msgcookie_t *cook;
1263 struct aim_fileheader_t *fh; 1369 struct aim_fileheader_t *fh;
1264 struct command_tx_struct *newoft; 1370 aim_frame_t *newoft;
1265 int i = 0; 1371 int i = 0;
1266 aim_rxcallback_t userfunc; 1372 aim_rxcallback_t userfunc;
1267 1373
1268 fh = aim_oft_getfh(hdr); 1374 fh = aim_oft_getfh(hdr);
1269 1375
1289 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0101, 0))) { 1395 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0101, 0))) {
1290 faimdprintf(sess, 2, "faim: send_final_transfer: tx_new OFT failed\n"); 1396 faimdprintf(sess, 2, "faim: send_final_transfer: tx_new OFT failed\n");
1291 return -1; 1397 return -1;
1292 } 1398 }
1293 1399
1294 newoft->lock = 1;
1295 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 1400 memcpy(newoft->hdr.oft.magic, "OFT2", 4);
1296 newoft->hdr.oft.hdr2len = 0x100 - 8; 1401 newoft->hdr.oft.hdr2len = 0x100 - 8;
1297 1402
1298 if (!(newoft->hdr.oft.hdr2 = calloc(1,newoft->hdr.oft.hdr2len))) { 1403 if (!(newoft->hdr.oft.hdr2 = calloc(1,newoft->hdr.oft.hdr2len))) {
1299 aim_frame_destroy(newoft); 1404 aim_frame_destroy(newoft);
1305 ft->fh.recvcsum = 0; 1410 ft->fh.recvcsum = 0;
1306 ft->fh.flags = 0x20; 1411 ft->fh.flags = 0x20;
1307 1412
1308 aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)); 1413 aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh));
1309 1414
1310 newoft->lock = 0;
1311 aim_tx_enqueue(sess, newoft); 1415 aim_tx_enqueue(sess, newoft);
1312 1416
1313 faimdprintf(sess, 2, "faim: OFT: OFT file header enqueued.\n"); 1417 faimdprintf(sess, 2, "faim: OFT: OFT file header enqueued.\n");
1314 1418
1315 return i; 1419 return i;
1372 #else 1476 #else
1373 return -1; 1477 return -1;
1374 #endif 1478 #endif
1375 } 1479 }
1376 1480
1481 static int handlehdr_sendfile_sending(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr)
1482 {
1483 struct aim_filetransfer_priv *ft;
1484 struct aim_fileheader_t *fh;
1485 aim_frame_t *newoft;
1486 aim_rxcallback_t userfunc;
1487
1488 fh = aim_oft_getfh(hdr);
1489
1490 /* We receive a null cookie for the first file; we must fill
1491 * it in to authenticate ourselves. -- wtm
1492 */
1493 ft = conn->priv;
1494 memcpy(&(fh->bcookie), ft->cookie, 8);
1495
1496 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t));
1497 free(fh);
1498
1499 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0202, 0))) {
1500 faimdprintf(sess, 2, "faim: send_final_transfer: tx_new OFT failed\n");
1501 return -1;
1502 }
1503
1504 memcpy(newoft->hdr.oft.magic, "OFT2", 4);
1505
1506 newoft->hdr.oft.hdr2len = 0x100 - 8;
1507
1508 if (!(newoft->hdr.oft.hdr2 = calloc(1,newoft->hdr.oft.hdr2len))) {
1509 aim_frame_destroy(newoft);
1510 return -1;
1511 }
1512
1513 if (!aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2,
1514 &(ft->fh))) {
1515 return -1;
1516 }
1517
1518 aim_tx_enqueue(sess, newoft);
1519
1520 faimdprintf(sess, 2, "faim: OFT: OFT 0x0202 enqueued.\n");
1521
1522 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILEREQ)) == NULL)
1523 return 1;
1524
1525 {
1526 char *cur;
1527 /* Convert the directory separator: it is sent
1528 * as ^A (0x01).
1529 */
1530 while ((cur = strchr(ft->fh.name, 0x01))) {
1531 *cur = G_DIR_SEPARATOR;
1532 }
1533 }
1534 return userfunc(sess, NULL, conn, ft->fh.name, ft->fh.size);
1535 }
1536
1537
1538 /*
1539 * These were originally described by Josh Myer:
1540 * http://www.geocrawler.com/archives/3/896/2000/9/0/4291064/
1541 * -- wtm
1542 */
1543 static int handlehdr_sendfile_resume(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) {
1544 aim_frame_t *newoft;
1545 aim_msgcookie_t *cook;
1546 struct aim_fileheader_t *fh;
1547 struct aim_filetransfer_priv *ft;
1548
1549 fh = aim_oft_getfh(hdr);
1550 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTSEND))) {
1551 free(fh);
1552 return -1;
1553 }
1554 ft = (struct aim_filetransfer_priv *)cook->data;
1555
1556 ft->fh.nrecvd = fh->nrecvd;
1557 ft->fh.recvcsum = fh->recvcsum;
1558 strncpy(ft->fh.name, fh->name, sizeof(ft->fh.name));
1559 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0106, 0))) {
1560 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n");
1561 free(fh);
1562 return -1;
1563 }
1564 memcpy(newoft->hdr.oft.magic, "OFT2", 4);
1565 newoft->hdr.oft.hdr2len = 0x100 - 8;
1566
1567 if (!(newoft->hdr.oft.hdr2 = (unsigned char *)calloc(1,newoft->hdr.oft.hdr2len))) {
1568 aim_frame_destroy(newoft);
1569 return -1;
1570 }
1571
1572 if (!(aim_oft_buildheader(newoft->hdr.oft.hdr2, &(ft->fh)))) {
1573 aim_frame_destroy(newoft);
1574 free(fh);
1575 return -1;
1576 }
1577
1578 aim_tx_enqueue(sess, newoft);
1579 free(fh);
1580
1581 return 0;
1582 }
1583
1584 static int handlehdr_sendfile_recv(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) {
1585 struct aim_fileheader_t *fh;
1586 aim_msgcookie_t *cook;
1587 int ret = 1;
1588 struct aim_filetransfer_priv *ft;
1589 aim_rxcallback_t userfunc;
1590
1591 fh = aim_oft_getfh(hdr);
1592 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTSEND))) {
1593 free(fh);
1594 return -1;
1595 }
1596 ft = (struct aim_filetransfer_priv *)cook->data;
1597
1598 faimdprintf(sess, 2, "faim: get_rend: looks like we're ready to send data.(oft 0x0202)\n");
1599
1600 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILEFILESEND)) )
1601 ret = userfunc(sess, NULL, conn, ft->fh.nrecvd);
1602
1603 free(fh);
1604
1605 return ret;
1606 }
1607
1377 static int handlehdr_getfile_recv(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) 1608 static int handlehdr_getfile_recv(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr)
1378 { 1609 {
1379 #if 0 1610 #if 0
1380 struct aim_fileheader_t *fh; 1611 struct aim_fileheader_t *fh;
1381 struct aim_filetransfer_priv *ft;
1382 struct aim_msgcookie_t *cook; 1612 struct aim_msgcookie_t *cook;
1383 int ret = 1; 1613 int ret = 1;
1384 aim_rxcallback_t userfunc; 1614 aim_rxcallback_t userfunc;
1615 struct aim_filetransfer_priv *ft;
1385 1616
1386 fh = aim_oft_getfh(hdr); 1617 fh = aim_oft_getfh(hdr);
1387 1618
1388 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) { 1619 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTGET))) {
1389 free(fh); 1620 free(fh);
1401 1632
1402 return ret; 1633 return ret;
1403 #else 1634 #else
1404 return -1; 1635 return -1;
1405 #endif 1636 #endif
1637 }
1638
1639 static int handlehdr_sendfile_finish(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr)
1640 {
1641 struct aim_fileheader_t *fh;
1642 aim_msgcookie_t *cook;
1643 aim_rxcallback_t userfunc;
1644
1645 fh = aim_oft_getfh(hdr);
1646
1647 if (!(cook = aim_checkcookie(sess, fh->bcookie, AIM_COOKIETYPE_OFTSEND))) {
1648 free(fh);
1649 return -1;
1650 }
1651
1652 faimdprintf(sess, 2, "faim: get_rend: looks like we're done with a transfer (oft 0x0204)\n");
1653
1654 debug_printf("wtm: they sent csum %x\n", fh->recvcsum);
1655
1656 if ( (userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_OFT, AIM_CB_OFT_GETFILECOMPLETE)) )
1657 userfunc(sess, NULL, conn, fh->bcookie);
1658
1659 free(fh);
1660 return 0;
1406 } 1661 }
1407 1662
1408 static int handlehdr_getfile_finish(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr) 1663 static int handlehdr_getfile_finish(aim_session_t *sess, aim_conn_t *conn, fu8_t *hdr)
1409 { 1664 {
1410 #if 0 1665 #if 0
1442 if (!sess || !conn) 1697 if (!sess || !conn)
1443 return -1; 1698 return -1;
1444 1699
1445 memset(hdrbuf1, 0, sizeof(hdrbuf1)); 1700 memset(hdrbuf1, 0, sizeof(hdrbuf1));
1446 1701
1447 /* I guess? I didn't understand any of that mess... */ 1702 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) {
1448 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_GETFILE) 1703 /* This should never happen yet. -- wtm */
1449 return getcommand_getfile(sess, conn); 1704 return getcommand_getfile(sess, conn);
1705 }
1450 1706
1451 /* XXX fix all the error cases here */ 1707 /* XXX fix all the error cases here */
1452 if (aim_recv(conn->fd, hdrbuf1, 6) < 6) { 1708 if (aim_recv(conn->fd, hdrbuf1, 6) < 6) {
1453
1454 faimdprintf(sess, 2, "faim: rend: read error (fd: %i)\n", conn->fd); 1709 faimdprintf(sess, 2, "faim: rend: read error (fd: %i)\n", conn->fd);
1455 1710
1456 aim_conn_close(conn); 1711 aim_conn_close(conn);
1457 1712
1458 return -1; 1713 return -1;
1469 aim_conn_close(conn); 1724 aim_conn_close(conn);
1470 return -1; 1725 return -1;
1471 } 1726 }
1472 1727
1473 hdrtype = aimutil_get16(hdr); 1728 hdrtype = aimutil_get16(hdr);
1729
1730 if (conn->subtype == AIM_CONN_SUBTYPE_OFT_SENDFILE) {
1731 switch(hdrtype) {
1732 case 0x0101:
1733 ret = handlehdr_sendfile_sending(sess, conn, hdr);
1734 break;
1735 case 0x0205:
1736 /* This seems equivalent to 0x0202,
1737 * but has the nrecvd and nrecvcsum
1738 * fields filled in. We send back a
1739 * 0x0106, and get then a 0x0207 which
1740 * we treat just like a 0x0202. -- wtm */
1741 ret = handlehdr_sendfile_resume(sess,
1742 conn, hdr);
1743 break;
1744 case 0x0207: /* see above */;
1745 case 0x0202:
1746 ret = handlehdr_sendfile_recv(sess, conn, hdr);
1747 break;
1748 case 0x0204:
1749 ret = handlehdr_sendfile_finish(sess, conn, hdr);
1750 break;
1751 default:
1752 debug_printf("unknown header type %x received", hdrtype);
1753 ret = -1;
1754 break;
1755 }
1756 free(hdr);
1757 if (ret == -1)
1758 aim_conn_close(conn);
1759 return ret;
1760 }
1761
1762 /* Shouldn't happen for now. --wtm */
1763 return -1;
1474 1764
1475 if (hdrtype == 0x0001) 1765 if (hdrtype == 0x0001)
1476 ret = handlehdr_directim(sess, conn, hdr); 1766 ret = handlehdr_directim(sess, conn, hdr);
1477 else if (hdrtype == 0x1108) /* getfile listing.txt incoming tx->rx */ 1767 else if (hdrtype == 0x1108) /* getfile listing.txt incoming tx->rx */
1478 ret = handlehdr_getfile_listing(sess, conn, hdr); 1768 ret = handlehdr_getfile_listing(sess, conn, hdr);
1499 aim_conn_close(conn); 1789 aim_conn_close(conn);
1500 1790
1501 return ret; 1791 return ret;
1502 } 1792 }
1503 1793
1504 #if 0
1505 /** 1794 /**
1506 * aim_oft_getfh - extracts an &aim_fileheader_t from buffer hdr. 1795 * aim_oft_getfh - extracts an &aim_fileheader_t from buffer hdr.
1507 * @hdr: buffer to extract header from 1796 * @hdr: buffer to extract header from
1508 * 1797 *
1509 * returns pointer to new struct on success; %NULL on error. 1798 * returns pointer to new struct on success; %NULL on error.
1570 i += 2; 1859 i += 2;
1571 memcpy(fh->name, hdr+i, 64); 1860 memcpy(fh->name, hdr+i, 64);
1572 i += 64; 1861 i += 64;
1573 return fh; 1862 return fh;
1574 } 1863 }
1575 #endif
1576 1864
1577 /** 1865 /**
1578 * aim_oft_checksum - calculate oft checksum of buffer 1866 * aim_oft_checksum - calculate oft checksum of buffer
1579 * @buffer: buffer of data to checksum 1867 * @buffer: buffer of data to checksum
1580 * @bufsize: size of buffer 1868 * @bufsize: size of buffer
1581 * @checksum: pointer to integer to place result in (pointer!) 1869 * @prevcheck: previous checksum
1582 * 1870 *
1583 * 1871 * Prevcheck should be 0xFFFF0000 for each new file; you can have this
1584 * Note that checksum is a pointer. Checksum should be filled with 1872 * checksum chunks of files in series if you just call it repeatedly in a
1585 * 0xFFFF0000 for each new file; you can have this checksum chunks of 1873 * for(; ; ) loop and don't reset the checksum between each call. And you
1586 * files in series if you just call it repeatedly in a for(; ; ) loop 1874 * thought we didn't care about you and your pathetic client's meomry
1587 * and don't reset the checksum between each call. And you thought we 1875 * footprint ;^)
1588 * didn't care about you and your pathetic client's meomry footprint 1876 *
1589 * ;^) 1877 * Thanks to Graham Booker for providing this improved checksum
1590 * 1878 * routine, which is simpler and should be more accurate than Josh
1591 * 1879 * Meyer's original code. -- wtm
1592 * Also, it's been said that this is incorrect as currently 1880 *
1593 * written. You were warned. 1881 * This algorithim works every time I have tried it. The other fails
1882 * sometimes. So, AOL who thought this up? It has got to be the weirdest
1883 * checksum I have ever seen.
1594 */ 1884 */
1595 faim_export fu32_t aim_oft_checksum(aim_session_t *sess, const char *buffer, int bufsize, fu32_t *checksum) 1885 faim_export fu32_t aim_oft_checksum(const unsigned char *buffer, int bufferlen, int prevcheck) {
1596 { 1886 fu32_t check = (prevcheck >> 16) & 0xffff, oldcheck;
1597 return 0xdeadbeef; 1887 int i;
1598 #if 0 1888 unsigned short val;
1599 fu16_t check0, check1; 1889
1600 int i; 1890 for(i=0;i<bufferlen;i++){
1601 1891 oldcheck = check;
1602 check0 = ((*checksum & 0xFF000000) >> 16); 1892 if(i&1){
1603 check1 = ((*checksum & 0x00ff0000) >> 16); 1893 val = buffer[i];
1604 for(i = 0; i < bufsize; i++) { 1894 } else {
1605 if (i % 2) { /* use check1 -- second byte */ 1895 val = buffer[i] << 8;
1606 if ( (short)buffer[i] > check1 ) { /* wrapping */ 1896 }
1607 check1 += 0x100; /* this is a cheap way to wrap */ 1897 check -= val;
1608 1898 /* The follownig appears to be necessary.... It happens every once in a while and the checksum doesn't fail. */
1609 /* if we're wrapping, decrement the other one */ 1899 if(check > oldcheck) {
1610 /* XXX: check this corner case */ 1900 check--;
1611 if (check0 == 0) 1901 }
1612 check0 = 0x00ff; 1902 }
1613 else 1903 check = ((check & 0x0000ffff) + (check >> 16));
1614 check0--; 1904 check = ((check & 0x0000ffff) + (check >> 16));
1615 } 1905 return check << 16;
1616 check1 -= buffer[i]; 1906 }
1617 } else { /* use check0 -- first byte */ 1907
1618 if ( (short)buffer[i] > check0 ) { /* wrapping */ 1908 faim_export fu32_t aim_update_checksum(aim_session_t *sess, aim_conn_t *conn,
1619 check0 += 0x100; /* this is a cheap way to wrap */ 1909 const unsigned char *buffer, int len) {
1620 1910 struct aim_filetransfer_priv *ft = conn->priv;
1621 /* if we're wrapping, decrement the other one */ 1911
1622 /* XXX: check this corner case */ 1912 ft->fh.nrecvd += len;
1623 if (check1 == 0) 1913 ft->fh.recvcsum = aim_oft_checksum(buffer, len, ft->fh.recvcsum);
1624 check1 = 0x00ff; 1914
1625 else 1915 return 0;
1626 check1--; 1916 }
1627 } 1917
1628 check0 -= buffer[i];
1629 }
1630 }
1631
1632 if (check0 > 0xff || check1 > 0xff) {
1633 /* they shouldn't be able to do this. error! */
1634 faimdprintf(sess, 2, "check0 or check1 is too high: 0x%04x, 0x%04x\n", check0, check1);
1635 return -1;
1636 }
1637
1638 /* grab just the lowest byte; this should be clean, but just in
1639 case */
1640 check0 &= 0xff;
1641 check1 &= 0xff;
1642
1643 *checksum = ((check0 * 0x1000000) + (check1 * 0x10000));
1644 return *checksum;
1645 #endif
1646 }
1647
1648 #if 0
1649 /** 1918 /**
1650 * aim_oft_buildheader - fills a buffer with network-order fh data 1919 * aim_oft_buildheader - fills a buffer with network-order fh data
1651 * @dest: buffer to fill -- pre-alloced 1920 * @dest: buffer to fill -- pre-alloced
1652 * @fh: fh to get data from 1921 * @fh: fh to get data from
1653 * 1922 *
1654 * returns length written; -1 on error. 1923 * returns length written; -1 on error.
1655 * DOES NOT DO BOUNDS CHECKING! 1924 * DOES NOT DO BOUNDS CHECKING!
1656 * 1925 *
1657 */ 1926 */
1658 static int oft_buildheader(unsigned char *dest, struct aim_fileheader_t *fh) 1927 faim_export int aim_oft_buildheader(unsigned char *dest, struct aim_fileheader_t *fh)
1659 { 1928 {
1660 int i, curbyte; 1929 int i, curbyte;
1661 if (!dest || !fh) 1930 if (!dest || !fh)
1662 return -1; 1931 return -1;
1663 curbyte = 0; 1932 curbyte = 0;
1695 1964
1696 /* XXX: Filenames longer than 64B */ 1965 /* XXX: Filenames longer than 64B */
1697 curbyte += 64; 1966 curbyte += 64;
1698 return curbyte; 1967 return curbyte;
1699 } 1968 }
1700 #endif
1701 1969
1702 /** 1970 /**
1703 * aim_getfile_intitiate - Request an OFT getfile session 1971 * aim_getfile_intitiate - Request an OFT getfile session
1704 * @sess: your session, 1972 * @sess: your session,
1705 * @conn: the BOS conn, 1973 * @conn: the BOS conn,
1859 * @size: size of the file 2127 * @size: size of the file
1860 * 2128 *
1861 * 2129 *
1862 * returns -1 on error, 0 on successful enqueuing 2130 * returns -1 on error, 0 on successful enqueuing
1863 */ 2131 */
2132 #if 0
1864 faim_export int aim_oft_getfile_request(aim_session_t *sess, aim_conn_t *conn, const char *name, int size) 2133 faim_export int aim_oft_getfile_request(aim_session_t *sess, aim_conn_t *conn, const char *name, int size)
1865 { 2134 {
1866 return -EINVAL; 2135 aim_frame_t *newoft;
1867 #if 0
1868 struct command_tx_struct *newoft;
1869 struct aim_filetransfer_priv *ft; 2136 struct aim_filetransfer_priv *ft;
1870 if (!sess || !conn || !conn->priv || !name) 2137 if (!sess || !conn || !conn->priv || !name)
1871 return -1; 2138 return -1;
1872 2139
1873 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x120c, 0))) { 2140 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x120c, 0))) {
1874 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n"); 2141 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n");
1875 return -1; 2142 return -1;
1876 } 2143 }
1877
1878 newoft->lock = 1;
1879
1880 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 2144 memcpy(newoft->hdr.oft.magic, "OFT2", 4);
1881 newoft->hdr.oft.hdr2len = 0x100 - 8; 2145 newoft->hdr.oft.hdr2len = 0x100 - 8;
1882 2146
1883 ft = (struct aim_filetransfer_priv *)conn->priv; 2147 ft = (struct aim_filetransfer_priv *)conn->priv;
1884 ft->fh.filesleft = 1; 2148 ft->fh.filesleft = 1;
1890 ft->fh.checksum = 0; 2154 ft->fh.checksum = 0;
1891 memcpy(ft->fh.name, name, strlen(name)); 2155 memcpy(ft->fh.name, name, strlen(name));
1892 memset(ft->fh.name+strlen(name), 0, 1); 2156 memset(ft->fh.name+strlen(name), 0, 1);
1893 2157
1894 if (!(newoft->hdr.oft.hdr2 = (unsigned char *)calloc(1,newoft->hdr.oft.hdr2len))) { 2158 if (!(newoft->hdr.oft.hdr2 = (unsigned char *)calloc(1,newoft->hdr.oft.hdr2len))) {
1895 newoft->lock = 0;
1896 aim_frame_destroy(newoft); 2159 aim_frame_destroy(newoft);
1897 return -1; 2160 return -1;
1898 } 2161 }
1899 2162
1900 if (!(aim_oft_buildheader(newoft->hdr.oft.hdr2, &(ft->fh)))) { 2163 if (!(aim_oft_buildheader(newoft->hdr.oft.hdr2, &(ft->fh)))) {
1901 newoft->lock = 0;
1902 aim_frame_destroy(newoft); 2164 aim_frame_destroy(newoft);
1903 return -1; 2165 return -1;
1904 } 2166 }
1905 2167
1906 newoft->lock = 0;
1907
1908 aim_tx_enqueue(sess, newoft); 2168 aim_tx_enqueue(sess, newoft);
1909 return 0; 2169 return 0;
1910 #endif 2170 }
2171 #endif
2172
2173 /* Identify a file that we are about to send by transmitting the
2174 * appropriate header.
2175 */
2176 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)
2177 {
2178 aim_frame_t *newoft;
2179 aim_msgcookie_t *cook;
2180 struct aim_filetransfer_priv *ft = (struct aim_filetransfer_priv *)conn->priv;
2181 struct aim_fileheader_t *fh;
2182
2183 if (!sess || !conn || !name)
2184 return -1;
2185
2186 /* Authenticate whomever connected to our listener by checking
2187 * that the correct cookie was proivided. */
2188 if (!(cook = aim_checkcookie(sess, ft->cookie,
2189 AIM_COOKIETYPE_OFTSEND))) {
2190 return -1;
2191 }
2192
2193 if (!(fh = (struct aim_fileheader_t*)calloc(1, sizeof(struct aim_fileheader_t))))
2194 return -1;
2195
2196 fh->encrypt = 0x0000;
2197 fh->compress = 0x0000;
2198 fh->totfiles = numfiles;
2199 fh->filesleft = numfiles - filesdone;
2200 fh->totparts = 0x0001;
2201 fh->partsleft = 0x0001;
2202 fh->totsize = totsize;
2203 fh->size = size;
2204 fh->modtime = (int)time(NULL); /* we'll go with current time for now */
2205 fh->checksum = 0xffffffff; /* XXX: checksum ! */
2206 fh->rfcsum = 0x00000000;
2207 fh->rfsize = 0x00000000;
2208 fh->cretime = 0x00000000;
2209 fh->rfcsum = 0x00000000;
2210 fh->nrecvd = 0x00000000; /* always zero initially */
2211 fh->recvcsum = 0x00000000; /* ditto */
2212
2213 strncpy(fh->idstring, "OFT_Windows ICBMFT V1.1 32", sizeof(fh->idstring));
2214 fh->flags = 0x02;
2215 fh->lnameoffset = 0x1a;
2216 fh->lsizeoffset = 0x10;
2217 memset(fh->dummy, 0, sizeof(fh->dummy));
2218 memset(fh->macfileinfo, 0, sizeof(fh->macfileinfo));
2219
2220 /* we need to figure out these encodings for filenames */
2221 fh->nencode = 0x0000;
2222 fh->nlanguage = 0x0000;
2223
2224 {
2225 /* Don't "show full pathname to buddy", just because it is
2226 * non-portable. -- wtm
2227 */
2228 char *basename = g_path_get_basename(name);
2229 strncpy(fh->name, basename, sizeof(fh->name));
2230 g_free(basename);
2231 }
2232
2233 memcpy(fh->bcookie, cook->cookie, 8);
2234 /* Update both headers to be safe. */
2235 memcpy(&(ft->fh), fh, sizeof(struct aim_fileheader_t));
2236 memcpy(&(((struct aim_filetransfer_priv *)cook->data)->fh), fh,
2237 sizeof(struct aim_fileheader_t));
2238
2239 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0101, 0))) {
2240 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n");
2241 free(fh);
2242 return -1;
2243 }
2244 memcpy(newoft->hdr.oft.magic, "OFT2", 4);
2245 newoft->hdr.oft.hdr2len = 0x100 - 8;
2246
2247 if (!(newoft->hdr.oft.hdr2 = (unsigned char *)calloc(1,newoft->hdr.oft.hdr2len))) {
2248 aim_frame_destroy(newoft);
2249 free(fh);
2250 return -1;
2251 }
2252
2253 if (!(aim_oft_buildheader(newoft->hdr.oft.hdr2, fh))) {
2254 aim_frame_destroy(newoft);
2255 free(fh);
2256 return -1;
2257 }
2258
2259 aim_tx_enqueue(sess, newoft);
2260 free(fh);
2261 return 0;
1911 } 2262 }
1912 2263
1913 /** 2264 /**
1914 * aim_oft_getfile_ack - acknowledge a getfile download as complete 2265 * aim_oft_getfile_ack - acknowledge a getfile download as complete
1915 * @sess: your session 2266 * @sess: your session
1958 return 0; 2309 return 0;
1959 #endif 2310 #endif
1960 } 2311 }
1961 2312
1962 /** 2313 /**
1963 * aim_oft_getfile_end - end a getfile. 2314 * aim_oft_end - end a getfile/sendfile.
1964 * @sess: your session 2315 * @sess: your session
1965 * @conn: the getfile connection 2316 * @conn: the getfile connection
1966 * 2317 *
1967 * call this before you close the getfile connection if you're on the 2318 * call this before you close the getfile connection if you're on the
1968 * receiving/requesting end. 2319 * receiving/requesting end.
1969 */ 2320 */
1970 faim_export int aim_oft_getfile_end(aim_session_t *sess, aim_conn_t *conn) 2321 faim_export int aim_oft_end(aim_session_t *sess, aim_conn_t *conn)
1971 { 2322 {
1972 return -EINVAL; 2323 aim_frame_t *newoft;
1973 #if 0
1974 struct command_tx_struct *newoft;
1975 struct aim_filetransfer_priv *ft; 2324 struct aim_filetransfer_priv *ft;
1976 2325
1977 if (!sess || !conn || !conn->priv) 2326 if (!sess || !conn || !conn->priv)
1978 return -1; 2327 return -1;
1979 2328
1980 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0204, 0))) { 2329 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, 0x0204, 0))) {
1981 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n"); 2330 faimdprintf(sess, 2, "faim: aim_accepttransfer: tx_new OFT failed\n");
1982 return -1; 2331 return -1;
1983 } 2332 }
1984
1985 newoft->lock = 1;
1986 2333
1987 memcpy(newoft->hdr.oft.magic, "OFT2", 4); 2334 memcpy(newoft->hdr.oft.magic, "OFT2", 4);
1988 newoft->hdr.oft.hdr2len = 0x100 - 8; 2335 newoft->hdr.oft.hdr2len = 0x100 - 8;
1989 2336
1990 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) { 2337 if (!(newoft->hdr.oft.hdr2 = (char *)calloc(1,newoft->hdr.oft.hdr2len))) {
1991 newoft->lock = 0;
1992 aim_frame_destroy(newoft); 2338 aim_frame_destroy(newoft);
1993 return -1; 2339 return -1;
1994 } 2340 }
1995 2341
1996 ft = (struct aim_filetransfer_priv *)conn->priv; 2342 ft = (struct aim_filetransfer_priv *)conn->priv;
1997 ft->state = 4; /* no longer wanting data */ 2343 ft->state = 4; /* no longer wanting data */
1998 ft->fh.nrecvd = ft->fh.size;
1999 ft->fh.recvcsum = ft->fh.checksum;
2000 ft->fh.flags = 0x21; 2344 ft->fh.flags = 0x21;
2001 2345
2002 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)))) { 2346 if (!(aim_oft_buildheader((unsigned char *)newoft->hdr.oft.hdr2, &(ft->fh)))) {
2003 newoft->lock = 0;
2004 aim_frame_destroy(newoft); 2347 aim_frame_destroy(newoft);
2005 return -1; 2348 return -1;
2006 } 2349 }
2007 2350
2008 newoft->lock = 0;
2009 aim_tx_enqueue(sess, newoft); 2351 aim_tx_enqueue(sess, newoft);
2010 2352
2011 return 0; 2353 return 0;
2012 #endif /* 0 */ 2354 }
2013 } 2355
2014