comparison src/protocols/oscar/ft.c @ 5146:ac9ca88d4b25

[gaim-migrate @ 5510] I guess I'm gonna go ahead and commit this... I don't think there's any real functionality change. AIM file transfer might work a little better, I guess. I probably fixed a bug or two. Like, filenames>64 characters won't cause infinite loopage. Changed AIM file transfer a bit with the following two goals: -Move some code from oscar.c to libfaim. Should make it easier for 3rd parties to use libfaim for file transfer. -Allow for easier code reuse with "get file" (in the works) committer: Tailor Script <tailor@pidgin.im>
author Mark Doliner <mark@kingant.net>
date Thu, 17 Apr 2003 03:28:21 +0000
parents 6c02ee2b471d
children 2d9f7d2e3558
comparison
equal deleted inserted replaced
5145:fc09679bffbe 5146:ac9ca88d4b25
21 * ICBM) on some port, and wait for them to connect to us. 21 * ICBM) on some port, and wait for them to connect to us.
22 * The ICBM we sent should contain our IP address and the port 22 * The ICBM we sent should contain our IP address and the port
23 * number that we're listening on. 23 * number that we're listening on.
24 * 2) The receiver connects to the sender on the given IP address 24 * 2) The receiver connects to the sender on the given IP address
25 * and port. After the connection is established, the receiver 25 * and port. After the connection is established, the receiver
26 * sends another ICBM signifying that we are ready and waiting. 26 * sends an ICBM signifying that we are ready and waiting.
27 * 3) The sender sends an OFT PROMPT message over the OFT 27 * 3) The sender sends an OFT PROMPT message over the OFT
28 * connection. 28 * connection.
29 * 4) The receiver of the file sends back an exact copy of this 29 * 4) The receiver of the file sends back an exact copy of this
30 * OFT packet, except the cookie is filled in with the cookie 30 * OFT packet, except the cookie is filled in with the cookie
31 * from the ICBM. I think this might be an attempt to verify 31 * from the ICBM. I think this might be an attempt to verify
33 * we sent the ICBM to. Oh, I've been calling this the ACK. 33 * we sent the ICBM to. Oh, I've been calling this the ACK.
34 * 5) The sender starts sending raw data across the connection 34 * 5) The sender starts sending raw data across the connection
35 * until the entire file has been sent. 35 * until the entire file has been sent.
36 * 6) The receiver knows the file is finished because the sender 36 * 6) The receiver knows the file is finished because the sender
37 * sent the file size in an earlier OFT packet. So then the 37 * sent the file size in an earlier OFT packet. So then the
38 * receiver sends the DONE thingy and closes the connection. 38 * receiver sends the DONE thingy (after filling in the
39 * "received" checksum and size) and closes the connection.
39 */ 40 */
40 41
41 #define FAIM_INTERNAL 42 #define FAIM_INTERNAL
42 43
43 #ifdef HAVE_CONFIG_H 44 #ifdef HAVE_CONFIG_H
519 * When the state changes, call aim_handlerendconnection with 520 * When the state changes, call aim_handlerendconnection with
520 * the connection returned by this. aim_handlerendconnection 521 * the connection returned by this. aim_handlerendconnection
521 * will accept the pending connection and stop listening. 522 * will accept the pending connection and stop listening.
522 * 523 *
523 * @param sess The session 524 * @param sess The session
524 * @param conn The BOS conn.
525 * @param priv A dummy priv value (we'll let it get filled in later)
526 * (if you pass a %NULL, we alloc one).
527 * @param sn The screen name to connect to. 525 * @param sn The screen name to connect to.
528 * @return The new connection. 526 * @return The new connection.
529 */ 527 */
530 faim_export aim_conn_t *aim_odc_initiate(aim_session_t *sess, const char *sn) 528 faim_export aim_conn_t *aim_odc_initiate(aim_session_t *sess, const char *sn)
531 { 529 {
596 struct aim_odc_intdata *intdata; 594 struct aim_odc_intdata *intdata;
597 595
598 if (!sess || !sn) 596 if (!sess || !sn)
599 return NULL; 597 return NULL;
600 598
601 if (!(intdata = malloc(sizeof(struct aim_odc_intdata)))) 599 if (!(intdata = calloc(1, sizeof(struct aim_odc_intdata))))
602 return NULL; 600 return NULL;
603 memset(intdata, 0, sizeof(struct aim_odc_intdata));
604 memcpy(intdata->cookie, cookie, 8); 601 memcpy(intdata->cookie, cookie, 8);
605 strncpy(intdata->sn, sn, sizeof(intdata->sn)); 602 strncpy(intdata->sn, sn, sizeof(intdata->sn));
606 if (addr) 603 if (addr)
607 strncpy(intdata->ip, addr, sizeof(intdata->ip)); 604 strncpy(intdata->ip, addr, sizeof(intdata->ip));
608 605
701 free(snptr); 698 free(snptr);
702 699
703 return ret; 700 return ret;
704 } 701 }
705 702
703 faim_export struct aim_oft_info *aim_oft_createinfo(aim_session_t *sess, const fu8_t *cookie, const char *sn, const char *ip, fu16_t port, fu32_t size, fu32_t modtime, char *filename)
704 {
705 struct aim_oft_info *new;
706
707 if (!sess)
708 return NULL;
709
710 if (!(new = (struct aim_oft_info *)calloc(1, sizeof(struct aim_oft_info))))
711 return NULL;
712
713 new->sess = sess;
714 if (cookie)
715 memcpy(new->cookie, cookie, 8);
716 if (ip)
717 new->clientip = strdup(ip);
718 if (sn)
719 new->sn = strdup(sn);
720 new->port = port;
721 new->fh.totfiles = 1;
722 new->fh.filesleft = 1;
723 new->fh.totparts = 1;
724 new->fh.partsleft = 1;
725 new->fh.totsize = size;
726 new->fh.size = size;
727 new->fh.modtime = modtime;
728 new->fh.checksum = 0xffff0000;
729 new->fh.rfrcsum = 0xffff0000;
730 new->fh.rfcsum = 0xffff0000;
731 new->fh.recvcsum = 0xffff0000;
732 strncpy(new->fh.idstring, "OFT_Windows ICBMFT V1.1 32", 31);
733 if (filename)
734 strncpy(new->fh.name, filename, 63);
735
736 new->next = sess->oft_info;
737 sess->oft_info = new;
738
739 return new;
740 }
741
742 /**
743 * Remove the given oft_info struct from the oft_info linked list, and
744 * then free its memory.
745 *
746 * @param sess The session.
747 * @param oft_info The aim_oft_info struct that we're destroying.
748 * @return Return 0 if no errors, otherwise return the error number.
749 */
750 faim_export int aim_oft_destroyinfo(struct aim_oft_info *oft_info)
751 {
752 aim_session_t *sess;
753
754 if (!oft_info || !(sess = oft_info->sess))
755 return -EINVAL;
756
757 if (sess->oft_info && (sess->oft_info == oft_info)) {
758 sess->oft_info = sess->oft_info->next;
759 } else {
760 struct aim_oft_info *cur;
761 for (cur=sess->oft_info; (cur->next && (cur->next!=oft_info)); cur=cur->next);
762 if (cur->next)
763 cur->next = cur->next->next;
764 }
765
766 free(oft_info->sn);
767 free(oft_info->proxyip);
768 free(oft_info->clientip);
769 free(oft_info->verifiedip);
770 free(oft_info);
771
772 return 0;
773 }
774
706 /** 775 /**
707 * Creates a listener socket so the other dude can connect to us. 776 * Creates a listener socket so the other dude can connect to us.
708 * 777 *
709 * You'll want to set up some kind of watcher on this socket. 778 * You'll want to set up some kind of watcher on this socket.
710 * When the state changes, call aim_handlerendconnection with 779 * When the state changes, call aim_handlerendconnection with
711 * the connection returned by this. aim_handlerendconnection 780 * the connection returned by this. aim_handlerendconnection
712 * will accept the pending connection and stop listening. 781 * will accept the pending connection and stop listening.
713 * 782 *
714 * @param sess The session. 783 * @param sess The session.
715 * @param cookie This better be Mrs. Fields or I'm going to be pissed. 784 * @param oft_info File transfer information associated with this
716 * @param ip Should be 4 bytes, each byte is 1 quartet of the IP address. 785 * connection.
717 * @param port Ye olde port number to listen on. 786 * @return Return 0 if no errors, otherwise return the error number.
718 * @return Return the new conn if everything went as planned. Otherwise, 787 */
719 * return NULL. 788 faim_export int aim_sendfile_listen(aim_session_t *sess, struct aim_oft_info *oft_info)
720 */ 789 {
721 faim_export aim_conn_t *aim_sendfile_listen(aim_session_t *sess, const fu8_t *cookie, const fu8_t *ip, fu16_t port)
722 {
723 aim_conn_t *newconn;
724 int listenfd; 790 int listenfd;
725 791
726 if ((listenfd = listenestablish(port)) == -1) 792 if (!oft_info)
727 return NULL; 793 return -EINVAL;
728 794
729 if (!(newconn = aim_newconn(sess, AIM_CONN_TYPE_LISTENER, NULL))) { 795 if ((listenfd = listenestablish(oft_info->port)) == -1)
796 return 1;
797
798 if (!(oft_info->conn = aim_newconn(sess, AIM_CONN_TYPE_LISTENER, NULL))) {
730 close(listenfd); 799 close(listenfd);
731 return NULL; 800 return -ENOMEM;
732 } 801 }
733 802
734 newconn->fd = listenfd; 803 oft_info->conn->fd = listenfd;
735 newconn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE; 804 oft_info->conn->subtype = AIM_CONN_SUBTYPE_OFT_SENDFILE;
736 newconn->lastactivity = time(NULL); 805 oft_info->conn->lastactivity = time(NULL);
737 806
738 return newconn; 807 return 0;
739 } 808 }
740 809
741 /** 810 /**
742 * Extract an &aim_fileheader_t from the given buffer. 811 * Extract an &aim_fileheader_t from the given buffer.
743 * 812 *
828 aimbs_putraw(bs, fh->name, 64); /* XXX - filenames longer than 64B */ 897 aimbs_putraw(bs, fh->name, 64); /* XXX - filenames longer than 64B */
829 898
830 return 0; 899 return 0;
831 } 900 }
832 901
833 faim_export struct aim_oft_info *aim_oft_createnewheader(fu8_t *cookie, char *ip, fu32_t size, fu32_t modtime, char *filename)
834 {
835 struct aim_oft_info *new;
836
837 if (!(new = (struct aim_oft_info *)calloc(1, sizeof(struct aim_oft_info))))
838 return NULL;
839
840 if (cookie && (sizeof(cookie) == 8)) {
841 memcpy(new->cookie, cookie, 8);
842 memcpy(new->fh.bcookie, cookie, 8);
843 }
844 if (ip)
845 strncpy(new->ip, ip, 30);
846 new->fh.filesleft = 0;
847 new->fh.totparts = 1;
848 new->fh.partsleft = 1;
849 new->fh.totsize = size;
850 new->fh.size = size;
851 new->fh.modtime = modtime;
852 strcpy(new->fh.idstring, "OFT_Windows ICBMFT V1.1 32");
853 if (filename)
854 strncpy(new->fh.name, filename, 64);
855
856 return new;
857 }
858
859 /** 902 /**
860 * Create an OFT packet based on the given information, and send it on its merry way. 903 * Create an OFT packet based on the given information, and send it on its merry way.
861 * 904 *
862 * @param sess The session. 905 * @param sess The session.
863 * @param conn The already-connected OFT connection. 906 * @param type The subtype of the OFT packet we're sending.
864 * @param cookie The cookie associated with this file transfer. 907 * @param oft_info The aim_oft_info struct with the connection and OFT
865 * @param filename The filename. 908 * info we're sending.
866 * @param filesdone Number of files already transferred.
867 * @param numfiles Total number of files.
868 * @param size Size in bytes of this file.
869 * @param totsize Size in bytes of all files combined.
870 * @param checksum Funky checksum of this file.
871 * @param flags Any flags you want, baby. Send 0x21 when sending the
872 * "AIM_CB_OFT_DONE" message, and "0x02" for everything else.
873 * @return Return 0 if no errors, otherwise return the error number. 909 * @return Return 0 if no errors, otherwise return the error number.
874 */ 910 */
875 faim_export int aim_oft_sendheader(aim_session_t *sess, aim_conn_t *conn, fu16_t type, const fu8_t *cookie, const char *filename, fu16_t filesdone, fu16_t numfiles, fu32_t size, fu32_t totsize, fu32_t modtime, fu32_t checksum, fu8_t flags, fu32_t bytesreceived, fu32_t recvcsum) 911 faim_export int aim_oft_sendheader(aim_session_t *sess, fu16_t type, struct aim_oft_info *oft_info)
876 { 912 {
877 aim_frame_t *newoft; 913 aim_frame_t *fr;
878 struct aim_fileheader_t *fh; 914
879 915 if (!sess || !oft_info || !oft_info->conn || (oft_info->conn->type != AIM_CONN_TYPE_RENDEZVOUS))
880 if (!sess || !conn || (conn->type != AIM_CONN_TYPE_RENDEZVOUS) || !filename)
881 return -EINVAL; 916 return -EINVAL;
882 917
883 if (!(fh = (struct aim_fileheader_t *)calloc(1, sizeof(struct aim_fileheader_t)))) 918 #if 0
884 return -ENOMEM;
885
886 /* 919 /*
887 * If you are receiving a file, the cookie should be null, if you are sending a 920 * If you are receiving a file, the cookie should be null, if you are sending a
888 * file, the cookie should be the same as the one used in the ICBM negotiation 921 * file, the cookie should be the same as the one used in the ICBM negotiation
889 * SNACs. 922 * SNACs.
890 */ 923 */
891 if (cookie)
892 memcpy(fh->bcookie, cookie, 8);
893 fh->totfiles = numfiles;
894 fh->filesleft = numfiles - filesdone;
895 fh->totparts = 0x0001; /* set to 0x0002 sending Mac resource forks */
896 fh->partsleft = 0x0001;
897 fh->totsize = totsize;
898 fh->size = size;
899 fh->modtime = modtime;
900 fh->checksum = checksum;
901 fh->nrecvd = bytesreceived;
902 fh->recvcsum = recvcsum;
903
904 strncpy(fh->idstring, "OFT_Windows ICBMFT V1.1 32", sizeof(fh->idstring));
905 fh->flags = flags;
906 fh->lnameoffset = 0x1a; 924 fh->lnameoffset = 0x1a;
907 fh->lsizeoffset = 0x10; 925 fh->lsizeoffset = 0x10;
908 memset(fh->dummy, 0, sizeof(fh->dummy));
909 memset(fh->macfileinfo, 0, sizeof(fh->macfileinfo));
910 926
911 /* apparently 0 is ASCII, 2 is UCS-2 */ 927 /* apparently 0 is ASCII, 2 is UCS-2 */
912 /* it is likely that 3 is ISO 8859-1 */ 928 /* it is likely that 3 is ISO 8859-1 */
913 /* I think "nlanguage" might be the same thing as "subenc" in im.c */ 929 /* I think "nlanguage" might be the same thing as "subenc" in im.c */
914 fh->nencode = 0x0000; 930 fh->nencode = 0x0000;
915 fh->nlanguage = 0x0000; 931 fh->nlanguage = 0x0000;
916 932 #endif
917 strncpy(fh->name, filename, sizeof(fh->name)); 933
918 aim_oft_dirconvert_tostupid(fh->name); 934 aim_oft_dirconvert_tostupid(oft_info->fh.name);
919 935
920 if (!(newoft = aim_tx_new(sess, conn, AIM_FRAMETYPE_OFT, type, 0))) { 936 if (!(fr = aim_tx_new(sess, oft_info->conn, AIM_FRAMETYPE_OFT, type, 0)))
921 free(fh);
922 return -ENOMEM; 937 return -ENOMEM;
923 } 938
924 939 if (aim_oft_buildheader(&fr->data, &oft_info->fh) == -1) {
925 if (aim_oft_buildheader(&newoft->data, fh) == -1) { 940 aim_frame_destroy(fr);
926 aim_frame_destroy(newoft);
927 free(fh);
928 return -ENOMEM; 941 return -ENOMEM;
929 } 942 }
930 943
931 memcpy(newoft->hdr.rend.magic, "OFT2", 4); 944 memcpy(fr->hdr.rend.magic, "OFT2", 4);
932 newoft->hdr.rend.hdrlen = aim_bstream_curpos(&newoft->data); 945 fr->hdr.rend.hdrlen = aim_bstream_curpos(&fr->data);
933 946
934 aim_tx_enqueue(sess, newoft); 947 aim_tx_enqueue(sess, fr);
935
936 free(fh);
937 948
938 return 0; 949 return 0;
939 } 950 }
940 951
941 /** 952 /**