home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 13 / AACD13.ISO / AACD / Online / StrICQ / Src / STRICQFXfer.c < prev    next >
C/C++ Source or Header  |  2000-02-16  |  33KB  |  1,220 lines

  1. /*
  2.  
  3. STRICQ - An Amiga, MUI Based, ICQ Clone.
  4. Copyright (C) 1998-2000 Douglas F. McLaughlin
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20. Douglas F. McLaughlin - stricq@owlnet.net
  21.  
  22. */
  23.  
  24. #include <sys/types.h>
  25.  
  26. #include <math.h>
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <time.h>
  31.  
  32. #include <exec/types.h>
  33.  
  34. #include <devices/timer.h>
  35.  
  36. #include <libraries/asl.h>
  37. #include <libraries/asyncio.h>
  38. #include <libraries/icq.h>
  39.  
  40. #include <bsdsocket/socketbasetags.h>
  41.  
  42. #include <sys/errno.h>
  43. #include <sys/time.h>
  44.  
  45. #include <proto/asyncio.h>
  46. #include <proto/dos.h>
  47.  
  48. #include "STRICQMUI.h"
  49. #include "cmd_codes.h"
  50.  
  51. #include <proto/socket.h>
  52.  
  53.  
  54. LONG __asm SetFileSendStats(REG(a2) APTR obj);
  55. void __asm SkipFile(REG(a2) APTR obj);
  56.  
  57. void  EndFile(struct Contact *);
  58. ULONG GetSize(struct FileList *files);
  59. void  QueueNextFile(struct Sockets *, struct Contact *);
  60. void  ResetTimer(struct TimeData *);
  61. BOOL  StartFileXFer(struct Contact *, BOOL);
  62.  
  63. extern void Add2Log(UBYTE, ULONG, UWORD, BOOL, UWORD, char *, ULONG);
  64. extern void AddUser2CList(struct Contact *);
  65. extern void DelSockets(UWORD);
  66. extern struct Contact *GetContact(ULONG);
  67. extern struct Sockets *GetSocketFmContact(struct Contact *, UBYTE);
  68. extern void HandleError(UBYTE, char *, ...);
  69. extern void PrepNewContact(struct Contact *);
  70. extern void SendAMessage(APTR, ULONG, char *, UWORD, UBYTE, int);
  71. extern BOOL SendTCPMessage(ULONG, char *, UWORD, UWORD, UWORD, ULONG, char *, ULONG, UWORD, ULONG);
  72. extern struct Sockets *GetSocketFmSocket(UWORD);
  73. extern void revmemcpy(char *, char *, int);
  74.  
  75. extern char err_buf[];
  76.  
  77. extern ULONG AsyncBuf, TCPCodes[], TCP_Seq;
  78.  
  79. extern struct MUI_CustomClass *mcc_Time;
  80. extern struct ObjApp *app;
  81.  
  82.  
  83. void ParseFilePkt(char *buf, int len, UWORD sock)
  84.  
  85. {
  86.  
  87. char cbuf[128];
  88.  
  89. int off = 0;
  90.  
  91. ULONG uin;
  92.  
  93. UWORD pktlen = 0;
  94.  
  95. struct Contact *user, User;
  96. struct Sockets *socks;
  97.  
  98. if (socks = GetSocketFmSocket(sock)) user = GetContact(socks->UIN);
  99.  
  100. revmemcpy((char *)&pktlen,buf+off,2); off += 2;
  101.  
  102. switch(buf[off++]) {
  103.   case (char)0xff: {
  104.     PrintHex(DBG_TCP_PKTS,"Recv file packet 0xFF",buf,len);
  105.     off += 8;
  106.     revmemcpy((char *)&uin,buf+off,4); off += 4;
  107.     if (!(user = GetContact(uin))) {
  108.       PrepNewContact(&User);
  109.       User.UIN = uin;
  110.       sprintf(cbuf,"%ld",uin);
  111.       User.Nick = cbuf;
  112.       User.Status = STAT_NEWUIN;
  113.       User.CanTCP = 4;
  114.       AddUser2CList(&User);
  115.       user = GetContact(uin);
  116.     }
  117.     socks->UIN = user->UIN;
  118.     socks->HadInit = TRUE;
  119.     socks->Timehack = time(NULL);
  120.     DoMethod(app->LV_SockList,MUIM_NList_Redraw,MUIV_NList_Redraw_All);
  121.     break;
  122.   }
  123.   case (char)0x00: {
  124.     char *nick, *mynick, *dldir;
  125.     UBYTE hs = 0x01;
  126.     ULONG tot_files = 0, tot_size = 0, speed = 0;
  127.     UWORD nick_len = 0, plen = 0, revlen = 0;
  128.     PrintHex(DBG_TCP_PKTS,"Recv packet 0x00",buf,len);
  129.     off += 4;
  130.     revmemcpy((char *)&tot_files,buf+off,4); off += 4;
  131.     revmemcpy((char *)&tot_size,buf+off,4); off += 4;
  132.     revmemcpy((char *)&speed,buf+off,4); off += 4;
  133.     off += 2;
  134.     nick = buf+off;
  135.     if (!StartFileXFer(user,TRUE)) {
  136.       DelSockets(sock);
  137.       return;
  138.     }
  139.     if (tot_files == 1) set(user->FWin->BT_Skip,MUIA_Disabled,TRUE);
  140.     user->FWin->TotAllFiles = user->FWin->CurrFiles = 0;
  141.     user->FWin->TotalFiles = tot_files;
  142.     user->FWin->TotFilesSize = tot_size;
  143.     sprintf(cbuf,"0/%ld",tot_files);
  144.     set(user->FWin->TX_FileCount,MUIA_Text_Contents,cbuf);
  145.     sprintf(cbuf,"0 Bytes of %ld",tot_size);
  146.     set(user->FWin->TX_BatchStat,MUIA_Text_Contents,cbuf);
  147.     set(user->FWin->GA_BatchXfer,MUIA_Gauge_Current,0);
  148.     set(user->FWin->GA_BatchXfer,MUIA_Gauge_Max,(tot_size>65535?tot_size/1024:tot_size));
  149.     sprintf(user->FWin->Title,"FileDirect Session With %s",nick);
  150.     set(user->FWin->WI_FileWin,MUIA_Window_Title,user->FWin->Title);
  151.     get(app->STR_DownloadDir,MUIA_String_Contents,&dldir);
  152.     set(user->FWin->TX_StoreDir,MUIA_Text_Contents,dldir);
  153.     get(app->STR_Nick,MUIA_String_Contents,&mynick);
  154.     nick_len = strlen(mynick)+1;
  155.     get(user->FWin->NU_Speed,MUIA_Numeric_Value,&speed);
  156.     revmemcpy(cbuf+plen,(char *)&hs,1); plen++;
  157.     revmemcpy(cbuf+plen,(char *)&speed,4); plen += 4;
  158.     revmemcpy(cbuf+plen,(char *)&nick_len,2); plen += 2;
  159.     strcpy(cbuf+plen,mynick); plen += nick_len;
  160.     PrintHex(DBG_TCP_PKTS,"Send packet 0x01",cbuf,plen);
  161.     revmemcpy((char *)&revlen,(char *)&plen,2);
  162.     send(sock,(char *)&revlen,2,0);
  163.     send(sock,cbuf,plen,0);
  164.     break;
  165.   }
  166.   case (char)0x01: {
  167.     char *nick;
  168.     PrintHex(DBG_TCP_PKTS,"Recv packet 0x01",buf,len);
  169.     off += 6;
  170.     nick = buf+off;
  171.     sprintf(user->FWin->Title,"FileDirect Session With %s",nick);
  172.     set(user->FWin->WI_FileWin,MUIA_Window_Title,user->FWin->Title);
  173.     QueueNextFile(socks,user);
  174.     break;
  175.   }
  176.   case (char)0x02: {
  177.     char *filename, *X1, *dldir, fullname[MAXNAMLEN];
  178.     LONG access = MODE_WRITE, ret;
  179.     UBYTE hs = 0x03;
  180.     ULONG filesize = 0, X2 = 0, X3 = 0, speed = 0, size;
  181.     UWORD text_len = 0, plen = 0, revlen = 0;
  182.     struct FileList File;
  183.     PrintHex(DBG_TCP_PKTS,"Recv packet 0x02",buf,len);
  184.     off++;
  185.     revmemcpy((char *)&text_len,buf+off,2); off += 2;
  186.     filename = buf+off; off += text_len;
  187.     revmemcpy((char *)&text_len,buf+off,2); off += 2;
  188.     X1 = buf+off; off += text_len;
  189.     revmemcpy((char *)&filesize,buf+off,4); off += 4;
  190.     revmemcpy((char *)&X2,buf+off,4); off += 4;
  191.     revmemcpy((char *)&speed,buf+off,4);
  192.     user->FWin->ThisFile = 0;
  193.     user->FWin->ThisFileSize = filesize;
  194.     set(user->FWin->TX_Filename,MUIA_Text_Contents,filename);
  195.     sprintf(cbuf,"%ld/%ld",++user->FWin->CurrFiles,user->FWin->TotalFiles);
  196.     set(user->FWin->TX_FileCount,MUIA_Text_Contents,cbuf);
  197.     set(user->FWin->GA_FileXfer,MUIA_Gauge_Current,0);
  198.     set(user->FWin->GA_FileXfer,MUIA_Gauge_Max,(filesize>65535?filesize/1024:filesize));
  199.     sprintf(cbuf,"0 Bytes of %ld",filesize);
  200.     set(user->FWin->TX_FileStat,MUIA_Text_Contents,cbuf);
  201.     get(app->STR_DownloadDir,MUIA_String_Contents,&dldir);
  202.     if (LASTCHAR(dldir) == ':' || LASTCHAR(dldir) == '/') sprintf(fullname,"%s%s",dldir,filename);
  203.     else sprintf(fullname,"%s/%s",dldir,filename);
  204.     if (user->FWin->File) CloseAsync(user->FWin->File);
  205.     strcpy(File.Filename,fullname);
  206.     if (size = GetSize(&File)) {
  207.       if ((ret = MUI_Request(app->App,user->FWin->WI_FileWin,0,NULL,"Resume|Overwrite|Cancel","%s Already Exists!\n\n Here:  %ld\nThere:  %ld",filename,size,filesize)) == 0) {
  208.         set(user->FWin->TX_Status,MUIA_Text_Contents,"User Abort.");
  209.         DelSockets(sock);
  210.         return;
  211.       }
  212.       if (ret == 1) {
  213.         access = MODE_APPEND;
  214.         user->FWin->ThisFile = size;
  215.         user->FWin->TotAllFiles += size;
  216.       }
  217.       else size = 0;
  218.     }
  219.     if (!(user->FWin->File = OpenAsync(fullname,access,AsyncBuf))) {
  220.       set(user->FWin->TX_Status,MUIA_Text_Contents,"Unable to Open File");
  221.       DelSockets(sock);
  222.       return;
  223.     }
  224.     strcpy(user->FWin->Status,"Receiving");
  225.     set(user->FWin->TX_Status,MUIA_Text_Contents,user->FWin->Status);
  226.     if (user->FWin->StartTime == 0) user->FWin->StartTime = time(NULL);
  227.     get(user->FWin->NU_Speed,MUIA_Numeric_Value,&speed);
  228.     revmemcpy(cbuf+plen,(char *)&hs,1); plen++;
  229.     revmemcpy(cbuf+plen,(char *)&size,4); plen += 4;
  230.     revmemcpy(cbuf+plen,(char *)&X3,4); plen += 4;
  231.     revmemcpy(cbuf+plen,(char *)&speed,4); plen += 4;
  232.     PrintHex(DBG_TCP_PKTS,"Send packet 0x03",cbuf,plen);
  233.     revmemcpy((char *)&revlen,(char *)&plen,2);
  234.     send(sock,(char *)&revlen,2,0);
  235.     send(sock,cbuf,plen,0);
  236.     break;
  237.   }
  238.   case (char)0x03: {
  239.     ULONG resume, X1;
  240.     struct FileList *files;
  241.     PrintHex(DBG_TCP_PKTS,"Recv packet 0x03",buf,len);
  242.     revmemcpy((char *)&resume,buf+off,4); off += 4;
  243.     revmemcpy((char *)&X1,buf+off,4); off += 4;
  244.     DoMethod(app->LV_FileList,MUIM_NList_GetEntry,0,&files);
  245.     if (user->FWin->File) CloseAsync(user->FWin->File);
  246.     if (!(user->FWin->File = OpenAsync(files->Filename,MODE_READ,AsyncBuf))) {
  247.       set(user->FWin->TX_Status,MUIA_Text_Contents,"Unable to Open File");
  248.       SkipFile(user->FWin->BT_Skip);
  249.       break;
  250.     }
  251.     if (resume) {
  252.       SeekAsync(user->FWin->File,resume,MODE_START);
  253.       user->FWin->ThisFile = resume;
  254.       user->FWin->TotAllFiles += resume;
  255.     }
  256.     strcpy(user->FWin->Status,"Sending");
  257.     set(user->FWin->TX_Status,MUIA_Text_Contents,user->FWin->Status);
  258.     if (user->FWin->StartTime == 0) user->FWin->StartTime = time(NULL);
  259.     socks->FileMode = user;
  260.     break;
  261.   }
  262.   case (char)0x04: {
  263.     ULONG entries;
  264.     PrintHex(DBG_TCP_PKTS,"Recv packet 0x04",buf,len);
  265.     set(user->FWin->TX_Status,MUIA_Text_Contents,"Skipping");
  266.     user->FWin->TotAllFiles += ((user->FWin->ThisFileSize)-(user->FWin->ThisFile));
  267.     if (user->FWin->File) {
  268.       CloseAsync(user->FWin->File);
  269.       user->FWin->File = NULL;
  270.       socks->FileMode = NULL;
  271.     }
  272.     if (user->FWin->CC_Timer) {
  273.       DoMethod(app->LV_FileList,MUIM_NList_Remove,0);
  274.       SetFileSendStats(NULL);
  275.       get(app->LV_FileList,MUIA_NList_Entries,&entries);
  276.       if (entries > 0) QueueNextFile(socks,user);
  277.     }
  278.     break;
  279.   }
  280.   case (char)0x05: {
  281.     ULONG speed = 0, secs = 0, micros;
  282.     PrintHex(DBG_TCP_PKTS,"Recv packet 0x05",buf,len);
  283.     revmemcpy((char *)&speed,buf+off,4);
  284.     DoMethod(user->FWin->NU_Speed,MUIM_NoNotifySet,MUIA_Numeric_Value,speed);
  285.     micros = (100-speed)*50000;
  286.     while(micros > 1000000) {
  287.       micros -= 1000000;
  288.       secs++;
  289.     }
  290.     if (speed == 100) micros = 25000;
  291.     set(user->FWin->CC_Timer,TIME_SetSecs,secs);
  292.     set(user->FWin->CC_Timer,TIME_SetMicro,micros);
  293.     if (speed == 0) set(user->FWin->TX_Status,MUIA_Text_Contents,"Paused");
  294.     else set(user->FWin->TX_Status,MUIA_Text_Contents,user->FWin->Status);
  295.     break;
  296.   }
  297.   case (char)0x06: {
  298.     int hours, mins, secs, cps;
  299.     ULONG interim, remain;
  300.     PrintHex(DBG_TCP_PKTS,"Recv packet 0x06",buf,16);
  301.     user->FWin->PktCnt++;
  302.     user->FWin->ThisFile += (pktlen-1);
  303.     user->FWin->TotAllFiles += (pktlen-1);
  304.     set(user->FWin->GA_FileXfer,MUIA_Gauge_Current,(user->FWin->ThisFileSize>65535?user->FWin->ThisFile/1024:user->FWin->ThisFile));
  305.     set(user->FWin->GA_BatchXfer,MUIA_Gauge_Current,(user->FWin->TotFilesSize>65535?user->FWin->TotAllFiles/1024:user->FWin->TotAllFiles));
  306.     sprintf(cbuf,"%ld Bytes of %ld",user->FWin->ThisFile,user->FWin->ThisFileSize);
  307.     set(user->FWin->TX_FileStat,MUIA_Text_Contents,cbuf);
  308.     sprintf(user->FWin->FilePcnt,"%2.0f%%",100.0*user->FWin->ThisFile/user->FWin->ThisFileSize);
  309.     set(user->FWin->GA_FileXfer,MUIA_Gauge_InfoText,user->FWin->FilePcnt);
  310.     sprintf(cbuf,"%ld Bytes of %ld",user->FWin->TotAllFiles,user->FWin->TotFilesSize);
  311.     set(user->FWin->TX_BatchStat,MUIA_Text_Contents,cbuf);
  312.     sprintf(user->FWin->BatchPcnt,"%2.0f%%",100.0*user->FWin->TotAllFiles/user->FWin->TotFilesSize);
  313.     set(user->FWin->GA_BatchXfer,MUIA_Gauge_InfoText,user->FWin->BatchPcnt);
  314.     interim = time(NULL)-(user->FWin->StartTime);
  315.     hours = interim/60/60;
  316.     mins = (interim-(hours*60*60))/60;
  317.     secs = interim-(hours*60*60)-(mins*60);
  318.     sprintf(cbuf,"%02d:%02d:%02d",hours,mins,secs);
  319.     set(user->FWin->TX_Elapsed,MUIA_Text_Contents,cbuf);
  320.     cps = (interim>0?user->FWin->TotAllFiles/interim:0);
  321.     cps = ((user->FWin->CPS)+=cps)/user->FWin->PktCnt;
  322.     if (cps != 0) {
  323.       sprintf(cbuf,"%d",cps);
  324.       set(user->FWin->TX_CPS,MUIA_Text_Contents,cbuf);
  325.       remain = (user->FWin->TotFilesSize/cps)-interim;
  326.       hours = remain/60/60;
  327.       mins = (remain-(hours*60*60))/60;
  328.       secs = remain-(hours*60*60)-(mins*60);
  329.       sprintf(cbuf,"%02d:%02d:%02d",hours,mins,secs);
  330.       set(user->FWin->TX_Remain,MUIA_Text_Contents,cbuf);
  331.     }
  332.     if (user->FWin->File) {
  333.       WriteAsync(user->FWin->File,buf+off,pktlen-1);
  334.       if (pktlen < 0x0801) {
  335.         CloseAsync(user->FWin->File);
  336.         user->FWin->File = NULL;
  337.         strcpy(user->FWin->Status,"Finished");
  338.         set(user->FWin->TX_Status,MUIA_Text_Contents,user->FWin->Status);
  339.       }
  340.     }
  341.     break;
  342.   }
  343.   default:
  344.     PrintHex(DBG_TCP_ERRS,"Unknown FileDirect packet",buf,len);
  345.     CloseAsync(user->FWin->File);
  346.     user->FWin->File = NULL;
  347.     strcpy(user->FWin->Status,"Error Abort");
  348.     set(user->FWin->TX_Status,MUIA_Text_Contents,user->FWin->Status);
  349. }
  350.  
  351. socks->Timehack = time(NULL);
  352.  
  353. return;
  354.  
  355. }
  356.  
  357.  
  358. BOOL StartFileXFer(struct Contact *user, BOOL open)
  359.  
  360. {
  361.  
  362. struct FileWin *FWin;
  363.  
  364. if (user->FWin) {
  365.   user->FWin->Skip = FALSE;
  366.   user->FWin->PktCnt = 0;
  367.   user->FWin->StartTime = 0;
  368.   user->FWin->Speed = user->FWin->ThisFile = user->FWin->ThisFileSize = user->FWin->CurrFiles = user->FWin->TotalFiles = user->FWin->TotAllFiles = user->FWin->TotFilesSize = user->FWin->CPS = 0;
  369.   set(user->FWin->NU_Speed,MUIA_Disabled,FALSE);
  370.   set(user->FWin->BT_Skip,MUIA_Disabled,FALSE);
  371.   set(user->FWin->BT_Abort,MUIA_Disabled,FALSE);
  372.   if (open) set(user->FWin->WI_FileWin,MUIA_Window_Open,TRUE);
  373.   return(TRUE);
  374. }
  375.  
  376. if (!(FWin = AllocVec(sizeof(struct FileWin),MEMF_CLEAR))) {
  377.   HandleError(DBG_OTH_FATL,"Failed to AllocVec %d bytes!",sizeof(struct FileWin));
  378.   return(FALSE);
  379. }
  380.  
  381. FWin->DoNotDelete = FALSE;
  382.  
  383. strcpy(FWin->Status,"Listening");
  384.  
  385. strcpy(FWin->Title,"Initiating FileDirect");
  386.  
  387. FWin->WI_FileWin = WindowObject,
  388.   MUIA_Window_Title, FWin->Title,
  389.   MUIA_Window_ID, user->UIN | 0x30000000,
  390.   MUIA_Window_Activate, FALSE,
  391.   MUIA_UserData, user,
  392.   WindowContents, VGroup,
  393.     Child, VGroup,
  394.       MUIA_Group_Columns, 4,
  395.       Child, Label("FileName"),
  396.       Child, FWin->TX_Filename = TextObject,
  397.         MUIA_Background, MUII_TextBack,
  398.         MUIA_Frame, MUIV_Frame_Text,
  399.         MUIA_Text_Contents, NULL,
  400.       End,
  401.       Child, Label("Files"),
  402.       Child, FWin->TX_FileCount = TextObject,
  403.         MUIA_Background, MUII_TextBack,
  404.         MUIA_Frame, MUIV_Frame_Text,
  405.         MUIA_Text_Contents, NULL,
  406.       End,
  407.       Child, Label("Directory"),
  408.       Child, FWin->TX_StoreDir = TextObject,
  409.         MUIA_Background, MUII_TextBack,
  410.         MUIA_Frame, MUIV_Frame_Text,
  411.         MUIA_Text_Contents, NULL,
  412.       End,
  413.       Child, Label("Status"),
  414.       Child, FWin->TX_Status = TextObject,
  415.         MUIA_Background, MUII_TextBack,
  416.         MUIA_Frame, MUIV_Frame_Text,
  417.         MUIA_Text_Contents, FWin->Status,
  418.       End,
  419.       Child, Label("File"),
  420.       Child, FWin->GA_FileXfer = GaugeObject,
  421.         MUIA_Background, MUII_TextBack,
  422.         MUIA_Frame, MUIV_Frame_Gauge,
  423.         MUIA_Gauge_Horiz, TRUE,
  424.       End,
  425.       Child, Label("Size"),
  426.       Child, FWin->TX_FileStat = TextObject,
  427.         MUIA_Background, MUII_TextBack,
  428.         MUIA_Frame, MUIV_Frame_Text,
  429.         MUIA_Text_Contents, NULL,
  430.       End,
  431.       Child, Label("Batch"),
  432.       Child, FWin->GA_BatchXfer = GaugeObject,
  433.         MUIA_Background, MUII_TextBack,
  434.         MUIA_Frame, MUIV_Frame_Gauge,
  435.         MUIA_Gauge_Horiz, TRUE,
  436.       End,
  437.       Child, Label("Size"),
  438.       Child, FWin->TX_BatchStat = TextObject,
  439.         MUIA_Background, MUII_TextBack,
  440.         MUIA_Frame, MUIV_Frame_Text,
  441.         MUIA_Text_Contents, NULL,
  442.       End,
  443.       Child, Label("Elapsed"),
  444.       Child, HGroup,
  445.         Child, FWin->TX_Elapsed = TextObject,
  446.           MUIA_Background, MUII_TextBack,
  447.           MUIA_Frame, MUIV_Frame_Text,
  448.           MUIA_Text_PreParse, "\033c",
  449.           MUIA_Text_Contents, "00:00:00",
  450.         End,
  451.         Child, Label("Remaining"),
  452.         Child, FWin->TX_Remain = TextObject,
  453.           MUIA_Background, MUII_TextBack,
  454.           MUIA_Frame, MUIV_Frame_Text,
  455.           MUIA_Text_PreParse, "\033c",
  456.           MUIA_Text_Contents, "N/A",
  457.         End,
  458.       End,
  459.       Child, Label("CPS"),
  460.       Child, FWin->TX_CPS = TextObject,
  461.         MUIA_Background, MUII_TextBack,
  462.         MUIA_Frame, MUIV_Frame_Text,
  463.         MUIA_Text_Contents, "N/A",
  464.       End,
  465.       Child, Label("Speed"),
  466.       Child, FWin->NU_Speed = SliderObject,
  467.         MUIA_CycleChain, 1,
  468.         MUIA_UserData, user,
  469.         MUIA_Numeric_Default, 100,
  470.         MUIA_Numeric_Max, 100,
  471.         MUIA_Numeric_Value, 100,
  472.       End,
  473.       Child, HSpace(0),
  474.       Child, HGroup,
  475.         Child, FWin->BT_Skip = SimpleButton("Skip File"),
  476.         Child, FWin->BT_Abort = SimpleButton("Abort"),
  477.       End,
  478.     End,
  479.   End,
  480. End;
  481.  
  482. if (!FWin->WI_FileWin) {
  483.   HandleError(DBG_OTH_FATL,"Could not create a file window.");
  484.   FreeVec(FWin);
  485.   FWin = NULL;
  486.   return(FALSE);
  487. }
  488.  
  489. user->FWin = FWin;
  490.  
  491. DoMethod(app->App,OM_ADDMEMBER,FWin->WI_FileWin);
  492.  
  493. set(FWin->BT_Skip,MUIA_CycleChain,1);
  494. set(FWin->BT_Skip,MUIA_UserData,user);
  495. set(FWin->BT_Abort,MUIA_CycleChain,1);
  496. set(FWin->BT_Abort,MUIA_UserData,user);
  497.  
  498. set(FWin->WI_FileWin,MUIA_Window_ActiveObject,FWin->BT_Abort);
  499.  
  500. DoMethod(FWin->WI_FileWin, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, FWin->WI_FileWin, 2,
  501.          MUIM_CallHook, &KillXferWinHook);
  502.  
  503. DoMethod(FWin->NU_Speed, MUIM_Notify, MUIA_Numeric_Value, MUIV_EveryTime, FWin->NU_Speed, 2,
  504.          MUIM_CallHook, &SetXferSpeedHook);
  505.  
  506. DoMethod(FWin->BT_Skip, MUIM_Notify, MUIA_Pressed, FALSE, FWin->BT_Skip, 2,
  507.          MUIM_CallHook, &SkipFileHook);
  508.  
  509. DoMethod(FWin->BT_Abort, MUIM_Notify, MUIA_Pressed, FALSE, FWin->BT_Abort, 2,
  510.          MUIM_CallHook, &AbortXferHook);
  511.  
  512. if (open) set(FWin->WI_FileWin,MUIA_Window_Open,TRUE);
  513.  
  514. return(TRUE);
  515.  
  516. }
  517.  
  518.  
  519. void __asm SetXferSpeed(REG(a2) APTR obj)
  520.  
  521. {
  522.  
  523. char buf[10];
  524.  
  525. ULONG speed = 0, secs = 0, micros;
  526.  
  527. UWORD len = 0, revlen;
  528.  
  529. struct Contact *user;
  530. struct Sockets *socks;
  531. struct TCP_FileSpeed Speed;
  532.  
  533. get(obj,MUIA_UserData,&user);
  534.  
  535. if (!(socks = GetSocketFmContact(user,SOCK_FILE))) return;
  536.  
  537. get(user->FWin->NU_Speed,MUIA_Numeric_Value,&speed);
  538.  
  539. Speed.Speed = speed;
  540.  
  541. len = TCP_CreateFilePacket(TCP_FILE_SPEED,&Speed,buf,&revlen);
  542.  
  543. send(socks->Socket,(char *)&revlen,2,0);
  544. send(socks->Socket,buf,len,0);
  545.  
  546. micros = (100-speed)*50000;
  547.  
  548. while(micros > 1000000) {
  549.   micros -= 1000000;
  550.   secs++;
  551. }
  552.  
  553. if (speed == 100) micros = 25000;
  554.  
  555. set(user->FWin->CC_Timer,TIME_SetSecs,secs);
  556. set(user->FWin->CC_Timer,TIME_SetMicro,micros);
  557.  
  558. if (speed == 0) set(user->FWin->TX_Status,MUIA_Text_Contents,"Paused");
  559. else set(user->FWin->TX_Status,MUIA_Text_Contents,user->FWin->Status);
  560.  
  561. return;
  562.  
  563. }
  564.  
  565.  
  566. void __asm SkipFile(REG(a2) APTR obj)
  567.  
  568. {
  569.  
  570. char buf[10];
  571.  
  572. ULONG entries;
  573.  
  574. UWORD len = 0, revlen;
  575.  
  576. struct Contact *user;
  577. struct Sockets *socks;
  578.  
  579. get(obj,MUIA_UserData,&user);
  580.  
  581. if (!(socks = GetSocketFmContact(user,SOCK_FILE))) return;
  582.  
  583. buf[0] = (char)0x04; len++;
  584.  
  585. revmemcpy(buf+1,(char *)&user->FWin->CurrFiles,4); len += 4;
  586.  
  587. PrintHex(DBG_TCP_PKTS,"Send packet 0x04",buf,5);
  588.  
  589. revmemcpy((char *)&revlen,(char *)&len,2);
  590.  
  591. send(socks->Socket,(char *)&revlen,2,0);
  592. send(socks->Socket,buf,len,0);
  593.  
  594. set(user->FWin->TX_Status,MUIA_Text_Contents,"Skipping");
  595. user->FWin->TotAllFiles += ((user->FWin->ThisFileSize)-(user->FWin->ThisFile));
  596.  
  597. if (user->FWin->File) {
  598.   CloseAsync(user->FWin->File);
  599.   user->FWin->File = NULL;
  600.   socks->FileMode = NULL;
  601. }
  602.  
  603. DoMethod(app->LV_FileList,MUIM_NList_Remove,0);
  604.  
  605. SetFileSendStats(NULL);
  606.  
  607. get(app->LV_FileList,MUIA_NList_Entries,&entries);
  608.  
  609. if (entries > 0) QueueNextFile(socks,user);
  610.  
  611. return;
  612.  
  613. }
  614.  
  615.  
  616. void __asm AbortXfer(REG(a2) APTR obj)
  617.  
  618. {
  619.  
  620. struct Contact *user;
  621. struct Sockets *socks;
  622.  
  623. get(obj,MUIA_UserData,&user);
  624.  
  625. if (!(socks = GetSocketFmContact(user,SOCK_FILE))) return;
  626.  
  627. DelSockets(socks->Socket);
  628.  
  629. if (user->FWin->File) {
  630.   CloseAsync(user->FWin->File);
  631.   user->FWin->File = NULL;
  632.   socks->FileMode = NULL;
  633. }
  634.  
  635. set(user->FWin->TX_Status,MUIA_Text_Contents,"Aborted");
  636.  
  637. set(user->FWin->NU_Speed,MUIA_Disabled,TRUE);
  638. set(user->FWin->BT_Skip,MUIA_Disabled,TRUE);
  639. set(user->FWin->BT_Abort,MUIA_Disabled,TRUE);
  640.  
  641. EndFile(user);
  642.  
  643. return;
  644.  
  645. }
  646.  
  647.  
  648. void EndFile(struct Contact *user)
  649.  
  650. {
  651.  
  652. if (user->FWin) {
  653.   if (user->FWin->File) {
  654.     CloseAsync(user->FWin->File);
  655.     user->FWin->File = NULL;
  656.   }
  657.   if (user->FWin->CC_Timer) DoMethod(user->FWin->CC_Timer,TIME_RemApp,app->App);
  658.   user->FWin->CC_Timer = NULL;
  659.   if (user->FWin->TotAllFiles < user->FWin->TotFilesSize) set(user->FWin->TX_Status,MUIA_Text_Contents,"Aborted");
  660.   set(user->FWin->NU_Speed,MUIA_Disabled,TRUE);
  661.   set(user->FWin->BT_Skip,MUIA_Disabled,TRUE);
  662.   set(user->FWin->BT_Abort,MUIA_Disabled,TRUE);
  663. }
  664.  
  665. return;
  666.  
  667. }
  668.  
  669.  
  670. void __asm KillXferWin(REG(a2) APTR obj)
  671.  
  672. {
  673.  
  674. struct Contact *user;
  675.  
  676. get(obj,MUIA_UserData,&user);
  677.  
  678. if (!user->FWin) return;
  679.  
  680. AbortXfer(obj);
  681.  
  682. set(user->FWin->WI_FileWin,MUIA_Window_Open,FALSE);
  683.  
  684. //DoMethod(app->App,OM_REMMEMBER,user->FWin->WI_FileWin);
  685.  
  686. //MUI_DisposeObject(user->FWin->WI_FileWin);
  687.  
  688. //FreeVec(user->FWin);
  689.  
  690. //user->FWin = NULL;
  691.  
  692. return;
  693.  
  694. }
  695.  
  696.  
  697. APTR __asm AddFile(REG(a2) APTR pool, REG(a1) struct FileList *files)
  698.  
  699. {
  700.  
  701. struct FileList *newfiles = NULL;
  702.  
  703. if (!(newfiles = AllocPooled(pool,sizeof(struct FileList)))) return(NULL);
  704.  
  705. strcpy(newfiles->Filename,files->Filename);
  706.  
  707. newfiles->Filesize = files->Filesize;
  708.  
  709. return(newfiles);
  710.  
  711. }
  712.  
  713.  
  714. void __asm RemFile(REG(a2) APTR pool, REG(a1) struct FileList *newfiles)
  715.  
  716. {
  717.  
  718. FreePooled(pool,newfiles,sizeof(struct FileList));
  719.  
  720. return;
  721.  
  722. }
  723.  
  724.  
  725. LONG __asm CmpFile(REG(a1) struct FileList *f1, REG(a2) struct FileList *f2)
  726.  
  727. {
  728.  
  729. return(stricmp(f1->Filename,f2->Filename));
  730.  
  731. }
  732.  
  733.  
  734. void __asm DisplayFile(REG(a2) char **array, REG(a1) struct FileList *files)
  735.  
  736. {
  737.  
  738. static char buf[32];
  739.  
  740. if (files) {
  741.   sprintf(buf,"%ld",files->Filesize);
  742.   *array++ = files->Filename;
  743.   *array   = buf;
  744. }
  745. else {
  746.   *array++ = "Filename";
  747.   *array   = "Filesize";
  748. }
  749.  
  750. return;
  751.  
  752. }
  753.  
  754.  
  755. void __asm OpenFileDirectWin(REG(a2) APTR obj)
  756.  
  757. {
  758.  
  759. ULONG uin;
  760.  
  761. get(obj,MUIA_UserData,&uin);
  762.  
  763. set(app->BT_SendFile,MUIA_UserData,uin);
  764.  
  765. DoMethod(app->LV_FileList,MUIM_NList_Clear);
  766.  
  767. set(app->TX_TotalFiles,MUIA_Text_Contents,"No Files");
  768. set(app->TX_TotalSize,MUIA_Text_Contents,"Zero Bytes");
  769.  
  770. set(app->GP_FDescGroup,MUIA_Disabled,FALSE);
  771. set(app->BT_AddFile,MUIA_Disabled,FALSE);
  772. set(app->BT_RemFile,MUIA_Disabled,FALSE);
  773.  
  774. set(app->WI_FileSendOut,MUIA_Window_Open,TRUE);
  775.  
  776. return;
  777.  
  778. }
  779.  
  780.  
  781. void __asm AddFiles2Send(REG(a2) APTR obj)
  782.  
  783. {
  784.  
  785. char title[] = "Choose Files To Send:";
  786.  
  787. char *dldir;
  788.  
  789. int i;
  790.  
  791. struct FileList       Files;
  792. struct FileRequester *myasl;
  793. struct WBArg         *files;
  794. struct Window        *mywin = NULL;
  795.  
  796. struct TagItem MyASLTags[] = {
  797.   {ASLFR_TitleText,    NULL},
  798.   {ASLFR_Window,       NULL},
  799.   {ASLFR_InitialDrawer,NULL},
  800.   {ASLFR_DoMultiSelect,TRUE},
  801.  
  802.   {TAG_DONE,NULL},
  803. };
  804.  
  805. get(app->WI_Main,MUIA_Window_Window,&mywin);
  806. get(app->STR_DownloadDir,MUIA_String_Contents,&dldir);
  807.  
  808. MyASLTags[0].ti_Data = (ULONG)title;
  809. MyASLTags[1].ti_Data = (ULONG)mywin;
  810. MyASLTags[2].ti_Data = (ULONG)dldir;
  811.  
  812. if (!(myasl = MUI_AllocAslRequest(ASL_FileRequest,MyASLTags))) return;
  813.  
  814. if (!MUI_AslRequest(myasl,NULL)) return;
  815.  
  816. if (myasl->rf_NumArgs) {
  817.   files = myasl->rf_ArgList;
  818.   for(i = 0; i < myasl->rf_NumArgs; i++) {
  819.     if (LASTCHAR(myasl->fr_Drawer) != ':' && LASTCHAR(myasl->fr_Drawer) != '/') sprintf(Files.Filename,"%s/%s",myasl->fr_Drawer,files[i].wa_Name);
  820.     else sprintf(Files.Filename,"%s%s",myasl->fr_Drawer,files[i].wa_Name);
  821.     GetSize(&Files);
  822.     DoMethod(app->LV_FileList,MUIM_NList_InsertSingle,&Files,MUIV_NList_Insert_Sorted);
  823.   }
  824. }
  825. else {
  826.   if (LASTCHAR(myasl->fr_Drawer) != ':' && LASTCHAR(myasl->fr_Drawer) != '/') sprintf(Files.Filename,"%s/%s",myasl->fr_Drawer,myasl->fr_File);
  827.   else sprintf(Files.Filename,"%s%s",myasl->fr_Drawer,myasl->fr_File);
  828.   GetSize(&Files);
  829.   DoMethod(app->LV_FileList,MUIM_NList_InsertSingle,&Files,MUIV_NList_Insert_Sorted);
  830. }
  831.  
  832. MUI_FreeAslRequest(myasl);
  833.  
  834. SetFileSendStats(NULL);
  835.  
  836. return;
  837.  
  838. }
  839.  
  840.  
  841. ULONG GetSize(struct FileList *files)
  842.  
  843. {
  844.  
  845. __aligned struct FileInfoBlock *myFIB;
  846.  
  847. BPTR mylock;
  848.  
  849. if (!(myFIB = (struct FileInfoBlock *)AllocVec(sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR))) {
  850.   HandleError(DBG_OTH_FATL,"Could not allocate FileInfoBlock for filesize check.\n");
  851.   return(0);
  852. }
  853.  
  854. if ((mylock = Lock(files->Filename,SHARED_LOCK)) == NULL) {
  855.   FreeVec(myFIB);
  856.   return(0);
  857. }
  858.  
  859. if (Examine(mylock,myFIB) == NULL) {
  860.   HandleError(DBG_OTH_FATL,"Couldn't Examine '%s'.\n",files->Filename);
  861.   FreeVec(myFIB);
  862.   UnLock(mylock);
  863.   return(0);
  864. }
  865.  
  866. files->Filesize = myFIB->fib_Size;
  867.  
  868. UnLock(mylock);
  869. FreeVec(myFIB);
  870.  
  871. return(files->Filesize);
  872.  
  873. }
  874.  
  875.  
  876. LONG __asm SetFileSendStats(REG(a2) APTR obj)
  877.  
  878. {
  879.  
  880. char buf[32];
  881.  
  882. int i;
  883.  
  884. LONG entries, totalbytes = 0, totalfiles = 0;
  885.  
  886. struct FileList *files;
  887.  
  888. get(app->LV_FileList,MUIA_NList_Entries,&entries);
  889.  
  890. if (entries < 1) {
  891.   set(app->TX_TotalFiles,MUIA_Text_Contents,"No Files");
  892.   set(app->TX_TotalSize,MUIA_Text_Contents,"Zero Bytes");
  893.   return(0);
  894. }
  895.  
  896. for(i = 0; i < entries; i++) {
  897.   DoMethod(app->LV_FileList,MUIM_NList_GetEntry,i,&files);
  898.   if (files) {
  899.     totalbytes += files->Filesize;
  900.     totalfiles++;
  901.   }
  902. }
  903.  
  904. sprintf(buf,"%ld Files",totalfiles);
  905. set(app->TX_TotalFiles,MUIA_Text_Contents,buf);
  906.  
  907. sprintf(buf,"%ld Bytes",totalbytes);
  908. set(app->TX_TotalSize,MUIA_Text_Contents,buf);
  909.  
  910. return(totalbytes);
  911.  
  912. }
  913.  
  914.  
  915. void __asm SendFileSend(REG(a2) APTR obj)
  916.  
  917. {
  918.  
  919. char *msg, filename[MAXNAMLEN];
  920.  
  921. ULONG id = 0, index = 0, status, totalbytes, entries;
  922.  
  923. struct Contact *user;
  924. struct FileList *files;
  925.  
  926. get(obj,MUIA_UserData,&id);
  927.  
  928. if (!(user = GetContact(id))) return;
  929.  
  930. if (!user->UWin) return;
  931.  
  932. get(app->CY_MyStatus,MUIA_Cycle_Active,&index);
  933.  
  934. status = TCPCodes[index];
  935.  
  936. get(app->TI_FileReason,MUIA_Textinput_Contents,&msg);
  937.  
  938. get(app->LV_FileList,MUIA_NList_Entries,&entries);
  939.  
  940. if (entries < 1) return;
  941.  
  942. set(app->GP_FDescGroup,MUIA_Disabled,TRUE);
  943. set(app->BT_AddFile,MUIA_Disabled,TRUE);
  944. set(app->BT_RemFile,MUIA_Disabled,TRUE);
  945.  
  946. if (entries == 1) {
  947.   DoMethod(app->LV_FileList,MUIM_NList_GetEntry,0,&files);
  948.   strcpy(filename,FilePart(files->Filename));
  949.   totalbytes = files->Filesize;
  950. }
  951. else {
  952.   sprintf(filename,"%ld Files",entries);
  953.   totalbytes = SetFileSendStats(NULL);
  954. }
  955.  
  956. if (!SendTCPMessage(id,msg,TCP_MESSAGE,TCP_MSG_FILE,TCP_MSG_REAL,TCP_Seq,filename,totalbytes,status,0)) {
  957.   sprintf(err_buf,"Could not send FileDirect Request to %s.",user->Nick);
  958.   HandleError(DBG_TCP_ERRS,"Could not send FileDirect Request to %s.",user->Nick);
  959.   return;
  960. }
  961.  
  962. SendAMessage(NULL,id,msg,TCP_MSG_MSG,MSG_LOCAL,MSG_VIA_BEST);
  963.  
  964. set(app->WI_FileSendOut,MUIA_Window_Open,FALSE);
  965. set(app->TI_FileReason,MUIA_Textinput_Contents,NULL);
  966.  
  967. Add2Log(LOG_CLIENT,TCP_Seq--,TCP_MESSAGE,FALSE,0,NULL,0);
  968.  
  969. return;
  970.  
  971. }
  972.  
  973.  
  974. void SendFileInit(UWORD sock, struct Contact *user)
  975.  
  976. {
  977.  
  978. char buf[128], *nick;
  979.  
  980. UWORD len = 0, revlen;
  981.  
  982. struct TCP_FileBegin Begin;
  983.  
  984. if (!StartFileXFer(user,TRUE)) {
  985.   DelSockets(sock);
  986.   return;
  987. }
  988.  
  989. if (!user->FWin->CC_Timer) {
  990.   if (!(user->FWin->CC_Timer = NewObject(mcc_Time->mcc_Class,NULL,TIME_SetSecs,0,TIME_SetMicro,25000,TIME_SetTrg,TIME_Trigger2,TAG_DONE))) {
  991.     HandleError(DBG_OTH_FATL,"Could not create the FileDirect timer object.");
  992.     DelSockets(sock);
  993.     return;
  994.   }
  995. }
  996.  
  997. DoMethod(user->FWin->CC_Timer,TIME_AddApp,app->App);
  998.  
  999. set(user->FWin->CC_Timer,TIME_SetSock,sock);
  1000.  
  1001. get(app->LV_FileList,MUIA_NList_Entries,&Begin.TotalFiles);
  1002. get(user->FWin->NU_Speed,MUIA_Numeric_Value,&Begin.Speed);
  1003. get(app->STR_Nick,MUIA_String_Contents,&nick);
  1004.  
  1005. Begin.TotalSize = SetFileSendStats(NULL);
  1006.  
  1007. strcpy(Begin.Nick,nick);
  1008.  
  1009. if (Begin.TotalFiles == 1) set(user->FWin->BT_Skip,MUIA_Disabled,TRUE);
  1010.  
  1011. user->FWin->TotAllFiles = user->FWin->CurrFiles = 0;
  1012. user->FWin->TotalFiles = Begin.TotalFiles;
  1013. user->FWin->TotFilesSize = Begin.TotalSize;
  1014.  
  1015. sprintf(buf,"0/%ld",Begin.TotalFiles);
  1016.  
  1017. set(user->FWin->TX_FileCount,MUIA_Text_Contents,buf);
  1018.  
  1019. sprintf(buf,"0 Bytes of %ld",Begin.TotalSize);
  1020.  
  1021. set(user->FWin->TX_BatchStat,MUIA_Text_Contents,buf);
  1022. set(user->FWin->GA_BatchXfer,MUIA_Gauge_Current,0);
  1023. set(user->FWin->GA_BatchXfer,MUIA_Gauge_Max,(Begin.TotalSize>65535?Begin.TotalSize/1024:Begin.TotalSize));
  1024.  
  1025. Begin.X1 = 0x00000000;
  1026.  
  1027. len = TCP_CreateFilePacket(TCP_FILE_BEGIN,&Begin,buf,&revlen);
  1028.  
  1029. send(sock,(char *)&revlen,2,0);
  1030. send(sock,buf,len,0);
  1031.  
  1032. return;
  1033.  
  1034. }
  1035.  
  1036.  
  1037. ULONG SendAFile(struct IClass *cl, Object *obj, Msg msg)
  1038.  
  1039. {
  1040.  
  1041. char sbuf[FILE_PKT_SIZE+3], cbuf[128];
  1042.  
  1043. int hours, mins, secs, cps;
  1044.  
  1045. ULONG entries, interim, remain, speed, err;
  1046.  
  1047. UWORD len, revlen;
  1048.  
  1049. struct Contact *user;
  1050. struct Sockets *socks;
  1051. struct TimeData *data = INST_DATA(cl,obj);
  1052.  
  1053. if (CheckIO((struct IORequest *)data->req_hbeat)) WaitIO((struct IORequest *)data->req_hbeat);
  1054. else return(FALSE);
  1055.  
  1056. //printf("In SendAFile.\n");
  1057.  
  1058. if (socks = GetSocketFmSocket(data->Socket)) socks->Timehack = time(NULL);
  1059.  
  1060. if (!socks->FileMode) {
  1061.   ResetTimer(data);
  1062.   return(FALSE);
  1063. }
  1064.  
  1065. user = socks->FileMode;
  1066.  
  1067. if (!user->FWin->File) {
  1068.   ResetTimer(data);
  1069.   return(FALSE);
  1070. }
  1071.  
  1072. get(user->FWin->NU_Speed,MUIA_Numeric_Value,&speed);
  1073.  
  1074. if (speed == 0) {
  1075.   ResetTimer(data);
  1076.   return(FALSE);
  1077. }
  1078.  
  1079. if (user->FWin->FileData.DataLen == 0) user->FWin->FileData.DataLen = ReadAsync(user->FWin->File,user->FWin->FileData.Data,FILE_PKT_SIZE);
  1080.  
  1081. if (user->FWin->FileData.DataLen > 0) {
  1082.   len = TCP_CreateFilePacket(TCP_FILE_DATA,&user->FWin->FileData,sbuf,&revlen);
  1083.   if (send(socks->Socket,sbuf,len+2,0) == -1) {
  1084.     if ((err = Errno()) != EWOULDBLOCK) {
  1085.       SocketBaseTags(SBTM_GETREF(SBTC_ERRNOSTRPTR),&err,TAG_DONE);
  1086.       sprintf(err_buf,"Error on file send socket %d: %s\n",socks->Socket,(char *)err);
  1087.       HandleError(DBG_TCP_ERRS,"Error on file send socket %d: %s\n",socks->Socket,(char *)err);
  1088.       DelSockets(socks->Socket);
  1089.       return(FALSE);
  1090.     }
  1091.     ResetTimer(data);
  1092.     return(TRUE);
  1093.   }
  1094.   user->FWin->FileData.DataLen = 0;
  1095.   user->FWin->PktCnt++;
  1096.   user->FWin->ThisFile += (len-1);
  1097.   user->FWin->TotAllFiles += (len-1);
  1098.   set(user->FWin->GA_FileXfer,MUIA_Gauge_Current,(user->FWin->ThisFileSize>65535?user->FWin->ThisFile/1024:user->FWin->ThisFile));
  1099.   set(user->FWin->GA_BatchXfer,MUIA_Gauge_Current,(user->FWin->TotFilesSize>65535?user->FWin->TotAllFiles/1024:user->FWin->TotAllFiles));
  1100.   sprintf(cbuf,"%ld Bytes of %ld",user->FWin->ThisFile,user->FWin->ThisFileSize);
  1101.   set(user->FWin->TX_FileStat,MUIA_Text_Contents,cbuf);
  1102.   sprintf(user->FWin->FilePcnt,"%2.0f%%",100.0*user->FWin->ThisFile/user->FWin->ThisFileSize);
  1103.   set(user->FWin->GA_FileXfer,MUIA_Gauge_InfoText,user->FWin->FilePcnt);
  1104.   sprintf(cbuf,"%ld Bytes of %ld",user->FWin->TotAllFiles,user->FWin->TotFilesSize);
  1105.   set(user->FWin->TX_BatchStat,MUIA_Text_Contents,cbuf);
  1106.   sprintf(user->FWin->BatchPcnt,"%2.0f%%",100.0*user->FWin->TotAllFiles/user->FWin->TotFilesSize);
  1107.   set(user->FWin->GA_BatchXfer,MUIA_Gauge_InfoText,user->FWin->BatchPcnt);
  1108.   interim = time(NULL)-(user->FWin->StartTime);
  1109.   hours = interim/60/60;
  1110.   mins = (interim-(hours*60*60))/60;
  1111.   secs = interim-(hours*60*60)-(mins*60);
  1112.   sprintf(cbuf,"%02d:%02d:%02d",hours,mins,secs);
  1113.   set(user->FWin->TX_Elapsed,MUIA_Text_Contents,cbuf);
  1114.   cps = (interim>0?user->FWin->TotAllFiles/interim:0);
  1115. //cps = ((user->FWin->CPS)+=cps)/user->FWin->PktCnt;
  1116.   if (cps != 0) {
  1117.     sprintf(cbuf,"%d",cps);
  1118.     set(user->FWin->TX_CPS,MUIA_Text_Contents,cbuf);
  1119.     remain = (user->FWin->TotFilesSize/cps)-interim;
  1120.     hours = remain/60/60;
  1121.     mins = (remain-(hours*60*60))/60;
  1122.     secs = remain-(hours*60*60)-(mins*60);
  1123.     sprintf(cbuf,"%02d:%02d:%02d",hours,mins,secs);
  1124.     set(user->FWin->TX_Remain,MUIA_Text_Contents,cbuf);
  1125.   }
  1126. }
  1127.  
  1128. if (len < FILE_PKT_SIZE+1) {
  1129.   CloseAsync(user->FWin->File);
  1130.   user->FWin->File = NULL;
  1131.   set(user->FWin->TX_Status,MUIA_Text_Contents,"Finished");
  1132.   socks->FileMode = NULL;
  1133.   DoMethod(app->LV_FileList,MUIM_NList_Remove,0);
  1134.   SetFileSendStats(NULL);
  1135.   get(app->LV_FileList,MUIA_NList_Entries,&entries);
  1136.   if (entries > 0) QueueNextFile(socks,user);
  1137.   else EndFile(user);
  1138. }
  1139.  
  1140. ResetTimer(data);
  1141.  
  1142. return(TRUE);
  1143.  
  1144. }
  1145.  
  1146.  
  1147. void ResetTimer(struct TimeData *data)
  1148.  
  1149. {
  1150.  
  1151. data->req_hbeat->tr_node.io_Command = TR_ADDREQUEST;
  1152. data->req_hbeat->tr_time.tv_secs = data->Seconds;
  1153. data->req_hbeat->tr_time.tv_micro = data->Micros;
  1154. SendIO((struct IORequest *)data->req_hbeat);
  1155.  
  1156. return;
  1157.  
  1158. }
  1159.  
  1160.  
  1161. void QueueNextFile(struct Sockets *socks, struct Contact *user)
  1162.  
  1163. {
  1164.  
  1165. char *path, c, sbuf[128];
  1166.  
  1167. ULONG speed;
  1168.  
  1169. UWORD len, revlen;
  1170.  
  1171. struct FileList *files;
  1172. struct TCP_FileReady Ready;
  1173.  
  1174. DoMethod(app->LV_FileList,MUIM_NList_GetEntry,0,&files);
  1175.  
  1176. user->FWin->ThisFile = 0;
  1177. user->FWin->ThisFileSize = files->Filesize;
  1178.  
  1179. set(user->FWin->TX_Filename,MUIA_Text_Contents,FilePart(files->Filename));
  1180.  
  1181. sprintf(sbuf,"%ld/%ld",++user->FWin->CurrFiles,user->FWin->TotalFiles);
  1182.  
  1183. set(user->FWin->TX_FileCount,MUIA_Text_Contents,sbuf);
  1184.  
  1185. set(user->FWin->GA_FileXfer,MUIA_Gauge_Current,0);
  1186.  
  1187. set(user->FWin->GA_FileXfer,MUIA_Gauge_Max,(files->Filesize>65535?files->Filesize/1024:files->Filesize));
  1188.  
  1189. sprintf(sbuf,"0 Bytes of %ld",files->Filesize);
  1190.  
  1191. set(user->FWin->TX_FileStat,MUIA_Text_Contents,sbuf);
  1192.  
  1193. path = PathPart(files->Filename);
  1194.  
  1195. c = *path;
  1196.  
  1197. *path = '\0';
  1198.  
  1199. set(user->FWin->TX_StoreDir,MUIA_Text_Contents,files->Filename);
  1200.  
  1201. *path = c;
  1202.  
  1203. get(user->FWin->NU_Speed,MUIA_Numeric_Value,&speed);
  1204.  
  1205. Ready.X1 = 0x00;
  1206. Ready.Filename = FilePart(files->Filename);
  1207. Ready.Text = LINE;
  1208. Ready.Filesize = files->Filesize;
  1209. Ready.X2 = 0x00000000;
  1210. Ready.Speed = speed;
  1211.  
  1212. len = TCP_CreateFilePacket(TCP_FILE_READY,&Ready,sbuf,&revlen);
  1213.  
  1214. send(socks->Socket,(char *)&revlen,2,0);
  1215. send(socks->Socket,sbuf,len,0);
  1216.  
  1217. return;
  1218.  
  1219. }
  1220.