home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 13
/
AACD13.ISO
/
AACD
/
Online
/
StrICQ
/
Src
/
STRICQFXfer.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-02-16
|
33KB
|
1,220 lines
/*
STRICQ - An Amiga, MUI Based, ICQ Clone.
Copyright (C) 1998-2000 Douglas F. McLaughlin
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Douglas F. McLaughlin - stricq@owlnet.net
*/
#include <sys/types.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <exec/types.h>
#include <devices/timer.h>
#include <libraries/asl.h>
#include <libraries/asyncio.h>
#include <libraries/icq.h>
#include <bsdsocket/socketbasetags.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <proto/asyncio.h>
#include <proto/dos.h>
#include "STRICQMUI.h"
#include "cmd_codes.h"
#include <proto/socket.h>
LONG __asm SetFileSendStats(REG(a2) APTR obj);
void __asm SkipFile(REG(a2) APTR obj);
void EndFile(struct Contact *);
ULONG GetSize(struct FileList *files);
void QueueNextFile(struct Sockets *, struct Contact *);
void ResetTimer(struct TimeData *);
BOOL StartFileXFer(struct Contact *, BOOL);
extern void Add2Log(UBYTE, ULONG, UWORD, BOOL, UWORD, char *, ULONG);
extern void AddUser2CList(struct Contact *);
extern void DelSockets(UWORD);
extern struct Contact *GetContact(ULONG);
extern struct Sockets *GetSocketFmContact(struct Contact *, UBYTE);
extern void HandleError(UBYTE, char *, ...);
extern void PrepNewContact(struct Contact *);
extern void SendAMessage(APTR, ULONG, char *, UWORD, UBYTE, int);
extern BOOL SendTCPMessage(ULONG, char *, UWORD, UWORD, UWORD, ULONG, char *, ULONG, UWORD, ULONG);
extern struct Sockets *GetSocketFmSocket(UWORD);
extern void revmemcpy(char *, char *, int);
extern char err_buf[];
extern ULONG AsyncBuf, TCPCodes[], TCP_Seq;
extern struct MUI_CustomClass *mcc_Time;
extern struct ObjApp *app;
void ParseFilePkt(char *buf, int len, UWORD sock)
{
char cbuf[128];
int off = 0;
ULONG uin;
UWORD pktlen = 0;
struct Contact *user, User;
struct Sockets *socks;
if (socks = GetSocketFmSocket(sock)) user = GetContact(socks->UIN);
revmemcpy((char *)&pktlen,buf+off,2); off += 2;
switch(buf[off++]) {
case (char)0xff: {
PrintHex(DBG_TCP_PKTS,"Recv file packet 0xFF",buf,len);
off += 8;
revmemcpy((char *)&uin,buf+off,4); off += 4;
if (!(user = GetContact(uin))) {
PrepNewContact(&User);
User.UIN = uin;
sprintf(cbuf,"%ld",uin);
User.Nick = cbuf;
User.Status = STAT_NEWUIN;
User.CanTCP = 4;
AddUser2CList(&User);
user = GetContact(uin);
}
socks->UIN = user->UIN;
socks->HadInit = TRUE;
socks->Timehack = time(NULL);
DoMethod(app->LV_SockList,MUIM_NList_Redraw,MUIV_NList_Redraw_All);
break;
}
case (char)0x00: {
char *nick, *mynick, *dldir;
UBYTE hs = 0x01;
ULONG tot_files = 0, tot_size = 0, speed = 0;
UWORD nick_len = 0, plen = 0, revlen = 0;
PrintHex(DBG_TCP_PKTS,"Recv packet 0x00",buf,len);
off += 4;
revmemcpy((char *)&tot_files,buf+off,4); off += 4;
revmemcpy((char *)&tot_size,buf+off,4); off += 4;
revmemcpy((char *)&speed,buf+off,4); off += 4;
off += 2;
nick = buf+off;
if (!StartFileXFer(user,TRUE)) {
DelSockets(sock);
return;
}
if (tot_files == 1) set(user->FWin->BT_Skip,MUIA_Disabled,TRUE);
user->FWin->TotAllFiles = user->FWin->CurrFiles = 0;
user->FWin->TotalFiles = tot_files;
user->FWin->TotFilesSize = tot_size;
sprintf(cbuf,"0/%ld",tot_files);
set(user->FWin->TX_FileCount,MUIA_Text_Contents,cbuf);
sprintf(cbuf,"0 Bytes of %ld",tot_size);
set(user->FWin->TX_BatchStat,MUIA_Text_Contents,cbuf);
set(user->FWin->GA_BatchXfer,MUIA_Gauge_Current,0);
set(user->FWin->GA_BatchXfer,MUIA_Gauge_Max,(tot_size>65535?tot_size/1024:tot_size));
sprintf(user->FWin->Title,"FileDirect Session With %s",nick);
set(user->FWin->WI_FileWin,MUIA_Window_Title,user->FWin->Title);
get(app->STR_DownloadDir,MUIA_String_Contents,&dldir);
set(user->FWin->TX_StoreDir,MUIA_Text_Contents,dldir);
get(app->STR_Nick,MUIA_String_Contents,&mynick);
nick_len = strlen(mynick)+1;
get(user->FWin->NU_Speed,MUIA_Numeric_Value,&speed);
revmemcpy(cbuf+plen,(char *)&hs,1); plen++;
revmemcpy(cbuf+plen,(char *)&speed,4); plen += 4;
revmemcpy(cbuf+plen,(char *)&nick_len,2); plen += 2;
strcpy(cbuf+plen,mynick); plen += nick_len;
PrintHex(DBG_TCP_PKTS,"Send packet 0x01",cbuf,plen);
revmemcpy((char *)&revlen,(char *)&plen,2);
send(sock,(char *)&revlen,2,0);
send(sock,cbuf,plen,0);
break;
}
case (char)0x01: {
char *nick;
PrintHex(DBG_TCP_PKTS,"Recv packet 0x01",buf,len);
off += 6;
nick = buf+off;
sprintf(user->FWin->Title,"FileDirect Session With %s",nick);
set(user->FWin->WI_FileWin,MUIA_Window_Title,user->FWin->Title);
QueueNextFile(socks,user);
break;
}
case (char)0x02: {
char *filename, *X1, *dldir, fullname[MAXNAMLEN];
LONG access = MODE_WRITE, ret;
UBYTE hs = 0x03;
ULONG filesize = 0, X2 = 0, X3 = 0, speed = 0, size;
UWORD text_len = 0, plen = 0, revlen = 0;
struct FileList File;
PrintHex(DBG_TCP_PKTS,"Recv packet 0x02",buf,len);
off++;
revmemcpy((char *)&text_len,buf+off,2); off += 2;
filename = buf+off; off += text_len;
revmemcpy((char *)&text_len,buf+off,2); off += 2;
X1 = buf+off; off += text_len;
revmemcpy((char *)&filesize,buf+off,4); off += 4;
revmemcpy((char *)&X2,buf+off,4); off += 4;
revmemcpy((char *)&speed,buf+off,4);
user->FWin->ThisFile = 0;
user->FWin->ThisFileSize = filesize;
set(user->FWin->TX_Filename,MUIA_Text_Contents,filename);
sprintf(cbuf,"%ld/%ld",++user->FWin->CurrFiles,user->FWin->TotalFiles);
set(user->FWin->TX_FileCount,MUIA_Text_Contents,cbuf);
set(user->FWin->GA_FileXfer,MUIA_Gauge_Current,0);
set(user->FWin->GA_FileXfer,MUIA_Gauge_Max,(filesize>65535?filesize/1024:filesize));
sprintf(cbuf,"0 Bytes of %ld",filesize);
set(user->FWin->TX_FileStat,MUIA_Text_Contents,cbuf);
get(app->STR_DownloadDir,MUIA_String_Contents,&dldir);
if (LASTCHAR(dldir) == ':' || LASTCHAR(dldir) == '/') sprintf(fullname,"%s%s",dldir,filename);
else sprintf(fullname,"%s/%s",dldir,filename);
if (user->FWin->File) CloseAsync(user->FWin->File);
strcpy(File.Filename,fullname);
if (size = GetSize(&File)) {
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) {
set(user->FWin->TX_Status,MUIA_Text_Contents,"User Abort.");
DelSockets(sock);
return;
}
if (ret == 1) {
access = MODE_APPEND;
user->FWin->ThisFile = size;
user->FWin->TotAllFiles += size;
}
else size = 0;
}
if (!(user->FWin->File = OpenAsync(fullname,access,AsyncBuf))) {
set(user->FWin->TX_Status,MUIA_Text_Contents,"Unable to Open File");
DelSockets(sock);
return;
}
strcpy(user->FWin->Status,"Receiving");
set(user->FWin->TX_Status,MUIA_Text_Contents,user->FWin->Status);
if (user->FWin->StartTime == 0) user->FWin->StartTime = time(NULL);
get(user->FWin->NU_Speed,MUIA_Numeric_Value,&speed);
revmemcpy(cbuf+plen,(char *)&hs,1); plen++;
revmemcpy(cbuf+plen,(char *)&size,4); plen += 4;
revmemcpy(cbuf+plen,(char *)&X3,4); plen += 4;
revmemcpy(cbuf+plen,(char *)&speed,4); plen += 4;
PrintHex(DBG_TCP_PKTS,"Send packet 0x03",cbuf,plen);
revmemcpy((char *)&revlen,(char *)&plen,2);
send(sock,(char *)&revlen,2,0);
send(sock,cbuf,plen,0);
break;
}
case (char)0x03: {
ULONG resume, X1;
struct FileList *files;
PrintHex(DBG_TCP_PKTS,"Recv packet 0x03",buf,len);
revmemcpy((char *)&resume,buf+off,4); off += 4;
revmemcpy((char *)&X1,buf+off,4); off += 4;
DoMethod(app->LV_FileList,MUIM_NList_GetEntry,0,&files);
if (user->FWin->File) CloseAsync(user->FWin->File);
if (!(user->FWin->File = OpenAsync(files->Filename,MODE_READ,AsyncBuf))) {
set(user->FWin->TX_Status,MUIA_Text_Contents,"Unable to Open File");
SkipFile(user->FWin->BT_Skip);
break;
}
if (resume) {
SeekAsync(user->FWin->File,resume,MODE_START);
user->FWin->ThisFile = resume;
user->FWin->TotAllFiles += resume;
}
strcpy(user->FWin->Status,"Sending");
set(user->FWin->TX_Status,MUIA_Text_Contents,user->FWin->Status);
if (user->FWin->StartTime == 0) user->FWin->StartTime = time(NULL);
socks->FileMode = user;
break;
}
case (char)0x04: {
ULONG entries;
PrintHex(DBG_TCP_PKTS,"Recv packet 0x04",buf,len);
set(user->FWin->TX_Status,MUIA_Text_Contents,"Skipping");
user->FWin->TotAllFiles += ((user->FWin->ThisFileSize)-(user->FWin->ThisFile));
if (user->FWin->File) {
CloseAsync(user->FWin->File);
user->FWin->File = NULL;
socks->FileMode = NULL;
}
if (user->FWin->CC_Timer) {
DoMethod(app->LV_FileList,MUIM_NList_Remove,0);
SetFileSendStats(NULL);
get(app->LV_FileList,MUIA_NList_Entries,&entries);
if (entries > 0) QueueNextFile(socks,user);
}
break;
}
case (char)0x05: {
ULONG speed = 0, secs = 0, micros;
PrintHex(DBG_TCP_PKTS,"Recv packet 0x05",buf,len);
revmemcpy((char *)&speed,buf+off,4);
DoMethod(user->FWin->NU_Speed,MUIM_NoNotifySet,MUIA_Numeric_Value,speed);
micros = (100-speed)*50000;
while(micros > 1000000) {
micros -= 1000000;
secs++;
}
if (speed == 100) micros = 25000;
set(user->FWin->CC_Timer,TIME_SetSecs,secs);
set(user->FWin->CC_Timer,TIME_SetMicro,micros);
if (speed == 0) set(user->FWin->TX_Status,MUIA_Text_Contents,"Paused");
else set(user->FWin->TX_Status,MUIA_Text_Contents,user->FWin->Status);
break;
}
case (char)0x06: {
int hours, mins, secs, cps;
ULONG interim, remain;
PrintHex(DBG_TCP_PKTS,"Recv packet 0x06",buf,16);
user->FWin->PktCnt++;
user->FWin->ThisFile += (pktlen-1);
user->FWin->TotAllFiles += (pktlen-1);
set(user->FWin->GA_FileXfer,MUIA_Gauge_Current,(user->FWin->ThisFileSize>65535?user->FWin->ThisFile/1024:user->FWin->ThisFile));
set(user->FWin->GA_BatchXfer,MUIA_Gauge_Current,(user->FWin->TotFilesSize>65535?user->FWin->TotAllFiles/1024:user->FWin->TotAllFiles));
sprintf(cbuf,"%ld Bytes of %ld",user->FWin->ThisFile,user->FWin->ThisFileSize);
set(user->FWin->TX_FileStat,MUIA_Text_Contents,cbuf);
sprintf(user->FWin->FilePcnt,"%2.0f%%",100.0*user->FWin->ThisFile/user->FWin->ThisFileSize);
set(user->FWin->GA_FileXfer,MUIA_Gauge_InfoText,user->FWin->FilePcnt);
sprintf(cbuf,"%ld Bytes of %ld",user->FWin->TotAllFiles,user->FWin->TotFilesSize);
set(user->FWin->TX_BatchStat,MUIA_Text_Contents,cbuf);
sprintf(user->FWin->BatchPcnt,"%2.0f%%",100.0*user->FWin->TotAllFiles/user->FWin->TotFilesSize);
set(user->FWin->GA_BatchXfer,MUIA_Gauge_InfoText,user->FWin->BatchPcnt);
interim = time(NULL)-(user->FWin->StartTime);
hours = interim/60/60;
mins = (interim-(hours*60*60))/60;
secs = interim-(hours*60*60)-(mins*60);
sprintf(cbuf,"%02d:%02d:%02d",hours,mins,secs);
set(user->FWin->TX_Elapsed,MUIA_Text_Contents,cbuf);
cps = (interim>0?user->FWin->TotAllFiles/interim:0);
cps = ((user->FWin->CPS)+=cps)/user->FWin->PktCnt;
if (cps != 0) {
sprintf(cbuf,"%d",cps);
set(user->FWin->TX_CPS,MUIA_Text_Contents,cbuf);
remain = (user->FWin->TotFilesSize/cps)-interim;
hours = remain/60/60;
mins = (remain-(hours*60*60))/60;
secs = remain-(hours*60*60)-(mins*60);
sprintf(cbuf,"%02d:%02d:%02d",hours,mins,secs);
set(user->FWin->TX_Remain,MUIA_Text_Contents,cbuf);
}
if (user->FWin->File) {
WriteAsync(user->FWin->File,buf+off,pktlen-1);
if (pktlen < 0x0801) {
CloseAsync(user->FWin->File);
user->FWin->File = NULL;
strcpy(user->FWin->Status,"Finished");
set(user->FWin->TX_Status,MUIA_Text_Contents,user->FWin->Status);
}
}
break;
}
default:
PrintHex(DBG_TCP_ERRS,"Unknown FileDirect packet",buf,len);
CloseAsync(user->FWin->File);
user->FWin->File = NULL;
strcpy(user->FWin->Status,"Error Abort");
set(user->FWin->TX_Status,MUIA_Text_Contents,user->FWin->Status);
}
socks->Timehack = time(NULL);
return;
}
BOOL StartFileXFer(struct Contact *user, BOOL open)
{
struct FileWin *FWin;
if (user->FWin) {
user->FWin->Skip = FALSE;
user->FWin->PktCnt = 0;
user->FWin->StartTime = 0;
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;
set(user->FWin->NU_Speed,MUIA_Disabled,FALSE);
set(user->FWin->BT_Skip,MUIA_Disabled,FALSE);
set(user->FWin->BT_Abort,MUIA_Disabled,FALSE);
if (open) set(user->FWin->WI_FileWin,MUIA_Window_Open,TRUE);
return(TRUE);
}
if (!(FWin = AllocVec(sizeof(struct FileWin),MEMF_CLEAR))) {
HandleError(DBG_OTH_FATL,"Failed to AllocVec %d bytes!",sizeof(struct FileWin));
return(FALSE);
}
FWin->DoNotDelete = FALSE;
strcpy(FWin->Status,"Listening");
strcpy(FWin->Title,"Initiating FileDirect");
FWin->WI_FileWin = WindowObject,
MUIA_Window_Title, FWin->Title,
MUIA_Window_ID, user->UIN | 0x30000000,
MUIA_Window_Activate, FALSE,
MUIA_UserData, user,
WindowContents, VGroup,
Child, VGroup,
MUIA_Group_Columns, 4,
Child, Label("FileName"),
Child, FWin->TX_Filename = TextObject,
MUIA_Background, MUII_TextBack,
MUIA_Frame, MUIV_Frame_Text,
MUIA_Text_Contents, NULL,
End,
Child, Label("Files"),
Child, FWin->TX_FileCount = TextObject,
MUIA_Background, MUII_TextBack,
MUIA_Frame, MUIV_Frame_Text,
MUIA_Text_Contents, NULL,
End,
Child, Label("Directory"),
Child, FWin->TX_StoreDir = TextObject,
MUIA_Background, MUII_TextBack,
MUIA_Frame, MUIV_Frame_Text,
MUIA_Text_Contents, NULL,
End,
Child, Label("Status"),
Child, FWin->TX_Status = TextObject,
MUIA_Background, MUII_TextBack,
MUIA_Frame, MUIV_Frame_Text,
MUIA_Text_Contents, FWin->Status,
End,
Child, Label("File"),
Child, FWin->GA_FileXfer = GaugeObject,
MUIA_Background, MUII_TextBack,
MUIA_Frame, MUIV_Frame_Gauge,
MUIA_Gauge_Horiz, TRUE,
End,
Child, Label("Size"),
Child, FWin->TX_FileStat = TextObject,
MUIA_Background, MUII_TextBack,
MUIA_Frame, MUIV_Frame_Text,
MUIA_Text_Contents, NULL,
End,
Child, Label("Batch"),
Child, FWin->GA_BatchXfer = GaugeObject,
MUIA_Background, MUII_TextBack,
MUIA_Frame, MUIV_Frame_Gauge,
MUIA_Gauge_Horiz, TRUE,
End,
Child, Label("Size"),
Child, FWin->TX_BatchStat = TextObject,
MUIA_Background, MUII_TextBack,
MUIA_Frame, MUIV_Frame_Text,
MUIA_Text_Contents, NULL,
End,
Child, Label("Elapsed"),
Child, HGroup,
Child, FWin->TX_Elapsed = TextObject,
MUIA_Background, MUII_TextBack,
MUIA_Frame, MUIV_Frame_Text,
MUIA_Text_PreParse, "\033c",
MUIA_Text_Contents, "00:00:00",
End,
Child, Label("Remaining"),
Child, FWin->TX_Remain = TextObject,
MUIA_Background, MUII_TextBack,
MUIA_Frame, MUIV_Frame_Text,
MUIA_Text_PreParse, "\033c",
MUIA_Text_Contents, "N/A",
End,
End,
Child, Label("CPS"),
Child, FWin->TX_CPS = TextObject,
MUIA_Background, MUII_TextBack,
MUIA_Frame, MUIV_Frame_Text,
MUIA_Text_Contents, "N/A",
End,
Child, Label("Speed"),
Child, FWin->NU_Speed = SliderObject,
MUIA_CycleChain, 1,
MUIA_UserData, user,
MUIA_Numeric_Default, 100,
MUIA_Numeric_Max, 100,
MUIA_Numeric_Value, 100,
End,
Child, HSpace(0),
Child, HGroup,
Child, FWin->BT_Skip = SimpleButton("Skip File"),
Child, FWin->BT_Abort = SimpleButton("Abort"),
End,
End,
End,
End;
if (!FWin->WI_FileWin) {
HandleError(DBG_OTH_FATL,"Could not create a file window.");
FreeVec(FWin);
FWin = NULL;
return(FALSE);
}
user->FWin = FWin;
DoMethod(app->App,OM_ADDMEMBER,FWin->WI_FileWin);
set(FWin->BT_Skip,MUIA_CycleChain,1);
set(FWin->BT_Skip,MUIA_UserData,user);
set(FWin->BT_Abort,MUIA_CycleChain,1);
set(FWin->BT_Abort,MUIA_UserData,user);
set(FWin->WI_FileWin,MUIA_Window_ActiveObject,FWin->BT_Abort);
DoMethod(FWin->WI_FileWin, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, FWin->WI_FileWin, 2,
MUIM_CallHook, &KillXferWinHook);
DoMethod(FWin->NU_Speed, MUIM_Notify, MUIA_Numeric_Value, MUIV_EveryTime, FWin->NU_Speed, 2,
MUIM_CallHook, &SetXferSpeedHook);
DoMethod(FWin->BT_Skip, MUIM_Notify, MUIA_Pressed, FALSE, FWin->BT_Skip, 2,
MUIM_CallHook, &SkipFileHook);
DoMethod(FWin->BT_Abort, MUIM_Notify, MUIA_Pressed, FALSE, FWin->BT_Abort, 2,
MUIM_CallHook, &AbortXferHook);
if (open) set(FWin->WI_FileWin,MUIA_Window_Open,TRUE);
return(TRUE);
}
void __asm SetXferSpeed(REG(a2) APTR obj)
{
char buf[10];
ULONG speed = 0, secs = 0, micros;
UWORD len = 0, revlen;
struct Contact *user;
struct Sockets *socks;
struct TCP_FileSpeed Speed;
get(obj,MUIA_UserData,&user);
if (!(socks = GetSocketFmContact(user,SOCK_FILE))) return;
get(user->FWin->NU_Speed,MUIA_Numeric_Value,&speed);
Speed.Speed = speed;
len = TCP_CreateFilePacket(TCP_FILE_SPEED,&Speed,buf,&revlen);
send(socks->Socket,(char *)&revlen,2,0);
send(socks->Socket,buf,len,0);
micros = (100-speed)*50000;
while(micros > 1000000) {
micros -= 1000000;
secs++;
}
if (speed == 100) micros = 25000;
set(user->FWin->CC_Timer,TIME_SetSecs,secs);
set(user->FWin->CC_Timer,TIME_SetMicro,micros);
if (speed == 0) set(user->FWin->TX_Status,MUIA_Text_Contents,"Paused");
else set(user->FWin->TX_Status,MUIA_Text_Contents,user->FWin->Status);
return;
}
void __asm SkipFile(REG(a2) APTR obj)
{
char buf[10];
ULONG entries;
UWORD len = 0, revlen;
struct Contact *user;
struct Sockets *socks;
get(obj,MUIA_UserData,&user);
if (!(socks = GetSocketFmContact(user,SOCK_FILE))) return;
buf[0] = (char)0x04; len++;
revmemcpy(buf+1,(char *)&user->FWin->CurrFiles,4); len += 4;
PrintHex(DBG_TCP_PKTS,"Send packet 0x04",buf,5);
revmemcpy((char *)&revlen,(char *)&len,2);
send(socks->Socket,(char *)&revlen,2,0);
send(socks->Socket,buf,len,0);
set(user->FWin->TX_Status,MUIA_Text_Contents,"Skipping");
user->FWin->TotAllFiles += ((user->FWin->ThisFileSize)-(user->FWin->ThisFile));
if (user->FWin->File) {
CloseAsync(user->FWin->File);
user->FWin->File = NULL;
socks->FileMode = NULL;
}
DoMethod(app->LV_FileList,MUIM_NList_Remove,0);
SetFileSendStats(NULL);
get(app->LV_FileList,MUIA_NList_Entries,&entries);
if (entries > 0) QueueNextFile(socks,user);
return;
}
void __asm AbortXfer(REG(a2) APTR obj)
{
struct Contact *user;
struct Sockets *socks;
get(obj,MUIA_UserData,&user);
if (!(socks = GetSocketFmContact(user,SOCK_FILE))) return;
DelSockets(socks->Socket);
if (user->FWin->File) {
CloseAsync(user->FWin->File);
user->FWin->File = NULL;
socks->FileMode = NULL;
}
set(user->FWin->TX_Status,MUIA_Text_Contents,"Aborted");
set(user->FWin->NU_Speed,MUIA_Disabled,TRUE);
set(user->FWin->BT_Skip,MUIA_Disabled,TRUE);
set(user->FWin->BT_Abort,MUIA_Disabled,TRUE);
EndFile(user);
return;
}
void EndFile(struct Contact *user)
{
if (user->FWin) {
if (user->FWin->File) {
CloseAsync(user->FWin->File);
user->FWin->File = NULL;
}
if (user->FWin->CC_Timer) DoMethod(user->FWin->CC_Timer,TIME_RemApp,app->App);
user->FWin->CC_Timer = NULL;
if (user->FWin->TotAllFiles < user->FWin->TotFilesSize) set(user->FWin->TX_Status,MUIA_Text_Contents,"Aborted");
set(user->FWin->NU_Speed,MUIA_Disabled,TRUE);
set(user->FWin->BT_Skip,MUIA_Disabled,TRUE);
set(user->FWin->BT_Abort,MUIA_Disabled,TRUE);
}
return;
}
void __asm KillXferWin(REG(a2) APTR obj)
{
struct Contact *user;
get(obj,MUIA_UserData,&user);
if (!user->FWin) return;
AbortXfer(obj);
set(user->FWin->WI_FileWin,MUIA_Window_Open,FALSE);
//DoMethod(app->App,OM_REMMEMBER,user->FWin->WI_FileWin);
//MUI_DisposeObject(user->FWin->WI_FileWin);
//FreeVec(user->FWin);
//user->FWin = NULL;
return;
}
APTR __asm AddFile(REG(a2) APTR pool, REG(a1) struct FileList *files)
{
struct FileList *newfiles = NULL;
if (!(newfiles = AllocPooled(pool,sizeof(struct FileList)))) return(NULL);
strcpy(newfiles->Filename,files->Filename);
newfiles->Filesize = files->Filesize;
return(newfiles);
}
void __asm RemFile(REG(a2) APTR pool, REG(a1) struct FileList *newfiles)
{
FreePooled(pool,newfiles,sizeof(struct FileList));
return;
}
LONG __asm CmpFile(REG(a1) struct FileList *f1, REG(a2) struct FileList *f2)
{
return(stricmp(f1->Filename,f2->Filename));
}
void __asm DisplayFile(REG(a2) char **array, REG(a1) struct FileList *files)
{
static char buf[32];
if (files) {
sprintf(buf,"%ld",files->Filesize);
*array++ = files->Filename;
*array = buf;
}
else {
*array++ = "Filename";
*array = "Filesize";
}
return;
}
void __asm OpenFileDirectWin(REG(a2) APTR obj)
{
ULONG uin;
get(obj,MUIA_UserData,&uin);
set(app->BT_SendFile,MUIA_UserData,uin);
DoMethod(app->LV_FileList,MUIM_NList_Clear);
set(app->TX_TotalFiles,MUIA_Text_Contents,"No Files");
set(app->TX_TotalSize,MUIA_Text_Contents,"Zero Bytes");
set(app->GP_FDescGroup,MUIA_Disabled,FALSE);
set(app->BT_AddFile,MUIA_Disabled,FALSE);
set(app->BT_RemFile,MUIA_Disabled,FALSE);
set(app->WI_FileSendOut,MUIA_Window_Open,TRUE);
return;
}
void __asm AddFiles2Send(REG(a2) APTR obj)
{
char title[] = "Choose Files To Send:";
char *dldir;
int i;
struct FileList Files;
struct FileRequester *myasl;
struct WBArg *files;
struct Window *mywin = NULL;
struct TagItem MyASLTags[] = {
{ASLFR_TitleText, NULL},
{ASLFR_Window, NULL},
{ASLFR_InitialDrawer,NULL},
{ASLFR_DoMultiSelect,TRUE},
{TAG_DONE,NULL},
};
get(app->WI_Main,MUIA_Window_Window,&mywin);
get(app->STR_DownloadDir,MUIA_String_Contents,&dldir);
MyASLTags[0].ti_Data = (ULONG)title;
MyASLTags[1].ti_Data = (ULONG)mywin;
MyASLTags[2].ti_Data = (ULONG)dldir;
if (!(myasl = MUI_AllocAslRequest(ASL_FileRequest,MyASLTags))) return;
if (!MUI_AslRequest(myasl,NULL)) return;
if (myasl->rf_NumArgs) {
files = myasl->rf_ArgList;
for(i = 0; i < myasl->rf_NumArgs; i++) {
if (LASTCHAR(myasl->fr_Drawer) != ':' && LASTCHAR(myasl->fr_Drawer) != '/') sprintf(Files.Filename,"%s/%s",myasl->fr_Drawer,files[i].wa_Name);
else sprintf(Files.Filename,"%s%s",myasl->fr_Drawer,files[i].wa_Name);
GetSize(&Files);
DoMethod(app->LV_FileList,MUIM_NList_InsertSingle,&Files,MUIV_NList_Insert_Sorted);
}
}
else {
if (LASTCHAR(myasl->fr_Drawer) != ':' && LASTCHAR(myasl->fr_Drawer) != '/') sprintf(Files.Filename,"%s/%s",myasl->fr_Drawer,myasl->fr_File);
else sprintf(Files.Filename,"%s%s",myasl->fr_Drawer,myasl->fr_File);
GetSize(&Files);
DoMethod(app->LV_FileList,MUIM_NList_InsertSingle,&Files,MUIV_NList_Insert_Sorted);
}
MUI_FreeAslRequest(myasl);
SetFileSendStats(NULL);
return;
}
ULONG GetSize(struct FileList *files)
{
__aligned struct FileInfoBlock *myFIB;
BPTR mylock;
if (!(myFIB = (struct FileInfoBlock *)AllocVec(sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR))) {
HandleError(DBG_OTH_FATL,"Could not allocate FileInfoBlock for filesize check.\n");
return(0);
}
if ((mylock = Lock(files->Filename,SHARED_LOCK)) == NULL) {
FreeVec(myFIB);
return(0);
}
if (Examine(mylock,myFIB) == NULL) {
HandleError(DBG_OTH_FATL,"Couldn't Examine '%s'.\n",files->Filename);
FreeVec(myFIB);
UnLock(mylock);
return(0);
}
files->Filesize = myFIB->fib_Size;
UnLock(mylock);
FreeVec(myFIB);
return(files->Filesize);
}
LONG __asm SetFileSendStats(REG(a2) APTR obj)
{
char buf[32];
int i;
LONG entries, totalbytes = 0, totalfiles = 0;
struct FileList *files;
get(app->LV_FileList,MUIA_NList_Entries,&entries);
if (entries < 1) {
set(app->TX_TotalFiles,MUIA_Text_Contents,"No Files");
set(app->TX_TotalSize,MUIA_Text_Contents,"Zero Bytes");
return(0);
}
for(i = 0; i < entries; i++) {
DoMethod(app->LV_FileList,MUIM_NList_GetEntry,i,&files);
if (files) {
totalbytes += files->Filesize;
totalfiles++;
}
}
sprintf(buf,"%ld Files",totalfiles);
set(app->TX_TotalFiles,MUIA_Text_Contents,buf);
sprintf(buf,"%ld Bytes",totalbytes);
set(app->TX_TotalSize,MUIA_Text_Contents,buf);
return(totalbytes);
}
void __asm SendFileSend(REG(a2) APTR obj)
{
char *msg, filename[MAXNAMLEN];
ULONG id = 0, index = 0, status, totalbytes, entries;
struct Contact *user;
struct FileList *files;
get(obj,MUIA_UserData,&id);
if (!(user = GetContact(id))) return;
if (!user->UWin) return;
get(app->CY_MyStatus,MUIA_Cycle_Active,&index);
status = TCPCodes[index];
get(app->TI_FileReason,MUIA_Textinput_Contents,&msg);
get(app->LV_FileList,MUIA_NList_Entries,&entries);
if (entries < 1) return;
set(app->GP_FDescGroup,MUIA_Disabled,TRUE);
set(app->BT_AddFile,MUIA_Disabled,TRUE);
set(app->BT_RemFile,MUIA_Disabled,TRUE);
if (entries == 1) {
DoMethod(app->LV_FileList,MUIM_NList_GetEntry,0,&files);
strcpy(filename,FilePart(files->Filename));
totalbytes = files->Filesize;
}
else {
sprintf(filename,"%ld Files",entries);
totalbytes = SetFileSendStats(NULL);
}
if (!SendTCPMessage(id,msg,TCP_MESSAGE,TCP_MSG_FILE,TCP_MSG_REAL,TCP_Seq,filename,totalbytes,status,0)) {
sprintf(err_buf,"Could not send FileDirect Request to %s.",user->Nick);
HandleError(DBG_TCP_ERRS,"Could not send FileDirect Request to %s.",user->Nick);
return;
}
SendAMessage(NULL,id,msg,TCP_MSG_MSG,MSG_LOCAL,MSG_VIA_BEST);
set(app->WI_FileSendOut,MUIA_Window_Open,FALSE);
set(app->TI_FileReason,MUIA_Textinput_Contents,NULL);
Add2Log(LOG_CLIENT,TCP_Seq--,TCP_MESSAGE,FALSE,0,NULL,0);
return;
}
void SendFileInit(UWORD sock, struct Contact *user)
{
char buf[128], *nick;
UWORD len = 0, revlen;
struct TCP_FileBegin Begin;
if (!StartFileXFer(user,TRUE)) {
DelSockets(sock);
return;
}
if (!user->FWin->CC_Timer) {
if (!(user->FWin->CC_Timer = NewObject(mcc_Time->mcc_Class,NULL,TIME_SetSecs,0,TIME_SetMicro,25000,TIME_SetTrg,TIME_Trigger2,TAG_DONE))) {
HandleError(DBG_OTH_FATL,"Could not create the FileDirect timer object.");
DelSockets(sock);
return;
}
}
DoMethod(user->FWin->CC_Timer,TIME_AddApp,app->App);
set(user->FWin->CC_Timer,TIME_SetSock,sock);
get(app->LV_FileList,MUIA_NList_Entries,&Begin.TotalFiles);
get(user->FWin->NU_Speed,MUIA_Numeric_Value,&Begin.Speed);
get(app->STR_Nick,MUIA_String_Contents,&nick);
Begin.TotalSize = SetFileSendStats(NULL);
strcpy(Begin.Nick,nick);
if (Begin.TotalFiles == 1) set(user->FWin->BT_Skip,MUIA_Disabled,TRUE);
user->FWin->TotAllFiles = user->FWin->CurrFiles = 0;
user->FWin->TotalFiles = Begin.TotalFiles;
user->FWin->TotFilesSize = Begin.TotalSize;
sprintf(buf,"0/%ld",Begin.TotalFiles);
set(user->FWin->TX_FileCount,MUIA_Text_Contents,buf);
sprintf(buf,"0 Bytes of %ld",Begin.TotalSize);
set(user->FWin->TX_BatchStat,MUIA_Text_Contents,buf);
set(user->FWin->GA_BatchXfer,MUIA_Gauge_Current,0);
set(user->FWin->GA_BatchXfer,MUIA_Gauge_Max,(Begin.TotalSize>65535?Begin.TotalSize/1024:Begin.TotalSize));
Begin.X1 = 0x00000000;
len = TCP_CreateFilePacket(TCP_FILE_BEGIN,&Begin,buf,&revlen);
send(sock,(char *)&revlen,2,0);
send(sock,buf,len,0);
return;
}
ULONG SendAFile(struct IClass *cl, Object *obj, Msg msg)
{
char sbuf[FILE_PKT_SIZE+3], cbuf[128];
int hours, mins, secs, cps;
ULONG entries, interim, remain, speed, err;
UWORD len, revlen;
struct Contact *user;
struct Sockets *socks;
struct TimeData *data = INST_DATA(cl,obj);
if (CheckIO((struct IORequest *)data->req_hbeat)) WaitIO((struct IORequest *)data->req_hbeat);
else return(FALSE);
//printf("In SendAFile.\n");
if (socks = GetSocketFmSocket(data->Socket)) socks->Timehack = time(NULL);
if (!socks->FileMode) {
ResetTimer(data);
return(FALSE);
}
user = socks->FileMode;
if (!user->FWin->File) {
ResetTimer(data);
return(FALSE);
}
get(user->FWin->NU_Speed,MUIA_Numeric_Value,&speed);
if (speed == 0) {
ResetTimer(data);
return(FALSE);
}
if (user->FWin->FileData.DataLen == 0) user->FWin->FileData.DataLen = ReadAsync(user->FWin->File,user->FWin->FileData.Data,FILE_PKT_SIZE);
if (user->FWin->FileData.DataLen > 0) {
len = TCP_CreateFilePacket(TCP_FILE_DATA,&user->FWin->FileData,sbuf,&revlen);
if (send(socks->Socket,sbuf,len+2,0) == -1) {
if ((err = Errno()) != EWOULDBLOCK) {
SocketBaseTags(SBTM_GETREF(SBTC_ERRNOSTRPTR),&err,TAG_DONE);
sprintf(err_buf,"Error on file send socket %d: %s\n",socks->Socket,(char *)err);
HandleError(DBG_TCP_ERRS,"Error on file send socket %d: %s\n",socks->Socket,(char *)err);
DelSockets(socks->Socket);
return(FALSE);
}
ResetTimer(data);
return(TRUE);
}
user->FWin->FileData.DataLen = 0;
user->FWin->PktCnt++;
user->FWin->ThisFile += (len-1);
user->FWin->TotAllFiles += (len-1);
set(user->FWin->GA_FileXfer,MUIA_Gauge_Current,(user->FWin->ThisFileSize>65535?user->FWin->ThisFile/1024:user->FWin->ThisFile));
set(user->FWin->GA_BatchXfer,MUIA_Gauge_Current,(user->FWin->TotFilesSize>65535?user->FWin->TotAllFiles/1024:user->FWin->TotAllFiles));
sprintf(cbuf,"%ld Bytes of %ld",user->FWin->ThisFile,user->FWin->ThisFileSize);
set(user->FWin->TX_FileStat,MUIA_Text_Contents,cbuf);
sprintf(user->FWin->FilePcnt,"%2.0f%%",100.0*user->FWin->ThisFile/user->FWin->ThisFileSize);
set(user->FWin->GA_FileXfer,MUIA_Gauge_InfoText,user->FWin->FilePcnt);
sprintf(cbuf,"%ld Bytes of %ld",user->FWin->TotAllFiles,user->FWin->TotFilesSize);
set(user->FWin->TX_BatchStat,MUIA_Text_Contents,cbuf);
sprintf(user->FWin->BatchPcnt,"%2.0f%%",100.0*user->FWin->TotAllFiles/user->FWin->TotFilesSize);
set(user->FWin->GA_BatchXfer,MUIA_Gauge_InfoText,user->FWin->BatchPcnt);
interim = time(NULL)-(user->FWin->StartTime);
hours = interim/60/60;
mins = (interim-(hours*60*60))/60;
secs = interim-(hours*60*60)-(mins*60);
sprintf(cbuf,"%02d:%02d:%02d",hours,mins,secs);
set(user->FWin->TX_Elapsed,MUIA_Text_Contents,cbuf);
cps = (interim>0?user->FWin->TotAllFiles/interim:0);
//cps = ((user->FWin->CPS)+=cps)/user->FWin->PktCnt;
if (cps != 0) {
sprintf(cbuf,"%d",cps);
set(user->FWin->TX_CPS,MUIA_Text_Contents,cbuf);
remain = (user->FWin->TotFilesSize/cps)-interim;
hours = remain/60/60;
mins = (remain-(hours*60*60))/60;
secs = remain-(hours*60*60)-(mins*60);
sprintf(cbuf,"%02d:%02d:%02d",hours,mins,secs);
set(user->FWin->TX_Remain,MUIA_Text_Contents,cbuf);
}
}
if (len < FILE_PKT_SIZE+1) {
CloseAsync(user->FWin->File);
user->FWin->File = NULL;
set(user->FWin->TX_Status,MUIA_Text_Contents,"Finished");
socks->FileMode = NULL;
DoMethod(app->LV_FileList,MUIM_NList_Remove,0);
SetFileSendStats(NULL);
get(app->LV_FileList,MUIA_NList_Entries,&entries);
if (entries > 0) QueueNextFile(socks,user);
else EndFile(user);
}
ResetTimer(data);
return(TRUE);
}
void ResetTimer(struct TimeData *data)
{
data->req_hbeat->tr_node.io_Command = TR_ADDREQUEST;
data->req_hbeat->tr_time.tv_secs = data->Seconds;
data->req_hbeat->tr_time.tv_micro = data->Micros;
SendIO((struct IORequest *)data->req_hbeat);
return;
}
void QueueNextFile(struct Sockets *socks, struct Contact *user)
{
char *path, c, sbuf[128];
ULONG speed;
UWORD len, revlen;
struct FileList *files;
struct TCP_FileReady Ready;
DoMethod(app->LV_FileList,MUIM_NList_GetEntry,0,&files);
user->FWin->ThisFile = 0;
user->FWin->ThisFileSize = files->Filesize;
set(user->FWin->TX_Filename,MUIA_Text_Contents,FilePart(files->Filename));
sprintf(sbuf,"%ld/%ld",++user->FWin->CurrFiles,user->FWin->TotalFiles);
set(user->FWin->TX_FileCount,MUIA_Text_Contents,sbuf);
set(user->FWin->GA_FileXfer,MUIA_Gauge_Current,0);
set(user->FWin->GA_FileXfer,MUIA_Gauge_Max,(files->Filesize>65535?files->Filesize/1024:files->Filesize));
sprintf(sbuf,"0 Bytes of %ld",files->Filesize);
set(user->FWin->TX_FileStat,MUIA_Text_Contents,sbuf);
path = PathPart(files->Filename);
c = *path;
*path = '\0';
set(user->FWin->TX_StoreDir,MUIA_Text_Contents,files->Filename);
*path = c;
get(user->FWin->NU_Speed,MUIA_Numeric_Value,&speed);
Ready.X1 = 0x00;
Ready.Filename = FilePart(files->Filename);
Ready.Text = LINE;
Ready.Filesize = files->Filesize;
Ready.X2 = 0x00000000;
Ready.Speed = speed;
len = TCP_CreateFilePacket(TCP_FILE_READY,&Ready,sbuf,&revlen);
send(socks->Socket,(char *)&revlen,2,0);
send(socks->Socket,sbuf,len,0);
return;
}