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