home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Enigma Amiga Life 109
/
EnigmaAmiga109CD.iso
/
software
/
on-line
/
amster
/
src
/
download.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-01-21
|
9KB
|
406 lines
/*
** Download
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <proto/exec.h>
#include <proto/socket.h>
#include <proto/dos.h>
#include <libraries/dos.h>
#include <netdb.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/tcp.h>
#include <bsdsocket/socketbasetags.h>
#include <error.h>
#include "mui.h"
#include <MUI/NListview_mcc.h>
#include <MUI/NFloattext_mcc.h>
#include "gui.h"
#include "info.h"
#include "download.h"
#include "napster.h"
#include "prefs.h"
#include "amster_Cat.h"
dldata dl_list=NULL;
ULONG dl_new(struct IClass *cl, Object *obj, struct opSet *msg);
void _dl_pollq(dldata song);
void _dl_abort(dldata song, char *msg);
void _dl_filename(char *buf, char *title);
extern struct Hook handleHook;
ULONG __stdargs DoSuperNew(struct IClass *cl,Object *obj,ULONG tag1,...)
{
return(DoSuperMethod(cl,obj,OM_NEW,&tag1,NULL));
}
MUIF dl_dispatch(REG(a0) struct IClass *cl,REG(a2) Object *obj,REG(a1) Msg msg)
{
switch(msg->MethodID) {
case OM_NEW: return(dl_new(cl,obj,(APTR)msg));
case DL_ABORT:
{
struct dl_data *data = INST_DATA(cl,obj);
_dl_abort(data->song,(char *)MSG_DL_ABORT);
return(NULL);
}
case DL_CLOSE:
{
struct dl_data *data = INST_DATA(cl,obj);
_dl_abort(data->song,(char *)MSG_DL_ABORT);
data->song->abort=1;
DoMethod(gui->app,MUIM_Application_PushMethod,gui->app,3,MUIM_CallHook,&handleHook,99);
return(NULL);
}
case DL_GAUGE:
{
struct dl_data *data = INST_DATA(cl,obj);
u_long i = (u_long)((muimsg)msg)->arg1;
set(data->lvl,MUIA_Gauge_Divide,i/10000);
return(NULL);
}
case DL_UPDATE:
{
static char buf[50];
struct dl_data *data = INST_DATA(cl,obj);
int i = (int)((muimsg)msg)->arg1;
set(data->lvl,MUIA_Gauge_Current,i);
sprintf(buf,"%ld",i);
set(data->sz,MUIA_Text_Contents,buf);
return(NULL);
}
case DL_STAT:
{
struct dl_data *data = INST_DATA(cl,obj);
char *tmp = (char*)((muimsg)msg)->arg1;
set(data->stat,MUIA_Text_Contents,tmp);
return(NULL);
}
}
return(DoSuperMethodA(cl,obj,msg));
}
ULONG dl_new(struct IClass *cl, Object *obj, struct opSet *msg)
{
struct dl_data *data;
dldata song = (dldata)GetTagData(DL_SONG,0,msg->ops_AttrList);
Object *but,*stat,*lvl,*sz;
if (obj = (Object *)DoSuperNew(cl,obj,
WindowContents, VGroup,
Child, NListviewObject,
MUIA_NListview_NList, NFloattextObject,
ReadListFrame,
MUIA_NFloattext_Text,song->info,
End,
End,
Child, stat = TextObject,
TextFrame,
MUIA_Background, MUII_TextBack,
MUIA_Text_PreParse, "\33c",
MUIA_Text_Contents, MSG_DL_HOSTLOOKUP,
End,
Child, lvl = GaugeObject,
GaugeFrame,
MUIA_Gauge_Horiz, TRUE,
MUIA_Gauge_Max, 10000,
MUIA_Gauge_Divide, 400,
MUIA_Gauge_InfoText, "",
End,
Child, ScaleObject, End,
Child, HGroup,
Child, sz = TextObject,
MUIA_Text_PreParse, "\33c",
End,
Child, but = SimpleButton(MSG_DL_ABORT_GAD),
End,
End,
TAG_MORE, msg->ops_AttrList))
{
data = INST_DATA(cl,obj);
data->song = song;
data->stat = stat;
data->but = but;
data->lvl = lvl;
data->sz = sz;
set(obj,MUIA_Window_ID,MAKE_ID('D','O','W','N'));
set(obj,MUIA_Window_Title,MSG_DL_TITLE);
DoMethod(but,MUIM_Notify,MUIA_Pressed,FALSE,obj,1,DL_ABORT);
DoMethod(obj,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,obj,1,DL_CLOSE);
return((ULONG)obj);
}
return(0);
}
void dl_addq(songdata sd)
{
dldata song;
Object *win;
song = malloc(sizeof(_dldata));
if(!song) return;
memset(song,0,sizeof(_dldata));
song->sock = -1;
strcpy(song->title,sd->title);
strcpy(song->user,sd->user);
song->size = sd->size;
sprintf(song->info,MSG_DL_INFORMATION,
sd->title,sd->user,nap_getlinktype(sd->link),sd->size,sd->bitrate,sd->freq);
win = NewObject(gui->dl_mcc->mcc_Class,NULL,DL_SONG,(u_long)song,TAG_DONE);
if(win==0) {
free(song);
return;
}
song->window=win;
DoMethod(gui->app,OM_ADDMEMBER,win);
set(win,MUIA_Window_Open,TRUE);
if(dl_list) song->next=dl_list;
dl_list=song;
}
void dl_startq(char *title, char *user, u_long ip, int port)
{
struct sockaddr_in sin;
long tmp=1;
dldata song;
long s;
song = dl_find(title,user);
if(!song) return;
if(song->state!=0) return;
DoMethod(song->window,DL_STAT,MSG_DL_CONNECTING);
s = socket(AF_INET,SOCK_STREAM,0);
if(s<0) {
DoMethod(song->window,DL_STAT,MSG_ERR_SOCKETERROR);
return;
}
sin.sin_addr.s_addr= ip;
gui_debugf("+++host ip %d.%d.%d.%d\n",(ip&0xFF000000)>>24,(ip&0xFF0000)>>16,(ip&0xFF00)>>8,ip&0xFF);
sin.sin_port=port;
sin.sin_family=AF_INET;
sin.sin_len=sizeof(sin);
IoctlSocket(s,FIOASYNC,(char *)&tmp);
IoctlSocket(s,FIONBIO,(char *)&tmp);
song->state=1;
song->sock=s;
song->ip = ip;
tmp = connect(s,(struct sockaddr *)&sin,sin.sin_len);
if(tmp != -1) return;
if (Errno()==EINPROGRESS) return;
_dl_abort(song,(char *)MSG_ERR_CONNECTERROR);
}
dldata dl_find(char *title, char *user)
{
dldata song;
song = dl_list;
while(song) {
if(strcmp(song->user,user)==0 && strcmp(song->title,title)==0) return(song);
song = song->next;
}
return(NULL);
}
void dl_pollall(void)
{
dldata song;
song = dl_list;
while(song) {
if(song->state!=0) _dl_pollq(song);
song = song->next;
}
}
int dl_flush(void)
{
dldata song=dl_list,old=dl_list,next;
while(song) {
next = song->next;
if(song->abort==1) {
set(song->window,MUIA_Window_Open,FALSE);
DoMethod(gui->app,OM_REMMEMBER,song->window);
MUI_DisposeObject(song->window);
if(song==dl_list) {
dl_list = next;
} else {
old->next = next;
}
free(song);
} else {
old = song;
}
song = next;
}
if(dl_list==NULL) return(1);
return(0);
}
void _dl_pollq(dldata song)
{
static unsigned char buf[4096];
struct fd_set fds;
struct timeval tv;
long s = song->sock;
FD_ZERO(&fds);
FD_SET(song->sock,&fds);
tv.tv_sec=0;
tv.tv_usec=15;
if(song->state==1) {
if (WaitSelect(s+1,NULL,&fds,NULL,&tv,0)==1) {
long tmp=0;
song->state=2;
IoctlSocket(s,FIONBIO,(char *)&tmp);
return;
}
} else if(song->state==2) {
if(WaitSelect(s+1,&fds,NULL,NULL,&tv,0)==1) {
int r;
r = recv(s,buf,1,0);
if(r!=1 || (r==1 && buf[0]!='1')) {
_dl_abort(song,(char *)MSG_DL_LOSTCONNECTION);
return;
}
DoMethod(song->window,DL_STAT,MSG_DL_REQFILE);
song->state=3;
sprintf(buf,"GET");
send(s,buf,3,0);
sprintf(buf,"%s \"%s\" 0",pref_user,song->title);
send(s,buf,strlen(buf),0);
return;
}
} else if(song->state==3) {
if(WaitSelect(s+1,&fds,NULL,NULL,&tv,0)==1) {
int i;
for(i=0;i<strlen(buf);i++) {
if(1!=recv(s,&buf[i],1,0)) {
_dl_abort(song,(char *)MSG_DL_LOSTCONNECTION);
return;
}
if(buf[i]==255) break;
}
buf[i]=0;
gui_debugf("+++ header says %s\n",buf);
DoMethod(song->window,DL_STAT,MSG_DL_DOWNLOADING);
song->state=4;
DoMethod(song->window,DL_GAUGE,song->size);
_dl_filename(buf,song->title);
gui_debugf("+++ file: %s\n",buf);
song->f = Open(buf,MODE_READWRITE);
if(!song->f) {
_dl_abort(song,(char *)MSG_DL_OPENERROR);
return;
}
buf[0]=255;
FWrite(song->f,buf,1,1);
song->cur=1;
return;
}
} else if(song->state==4) {
while(WaitSelect(s+1,&fds,NULL,NULL,&tv,0)==1) {
int len;
len=recv(s,buf,4090,0);
if(len<1) {
if(len==0 && ((song->cur) >= (song->size))) {
_dl_abort(song,(char *)MSG_DL_DOWNLOADFINISHED);
return;
}
if (len==0) {
_dl_abort(song,(char *)MSG_DL_LOSTCONNECTION);
return;
}
_dl_abort(song,(char *)MSG_ERR_NETWORKERROR);
return;
}
FWrite(song->f,buf,1,len);
song->cur = song->cur + len;
DoMethod(song->window,DL_UPDATE,song->cur);
FD_ZERO(&fds);
FD_SET(song->sock,&fds);
tv.tv_sec=0;
tv.tv_usec=15;
}
}
}
void _dl_abort(dldata song, char *msg)
{
/* static char name[1024];
static char comment[1024];
struct hostent *he_ip,*he_host;
*/
if(song->sock!= -1) CloseSocket(song->sock);
song->sock = -1;
if(song->f != 0) {
Close(song->f);
/* he_ip = gethostbyname(Inet_NtoA(song->ip));
he_host = gethostbyaddr(he_ip->h_addr_list[0],he_ip->h_length,AF_INET);
if(he_host) sprintf(comment,"from %s (@%s)",song->user,he_host->h_name);
else sprintf(comment,"from %s (@%s)",song->user,Inet_NtoA(song->ip));
if(song->state<5) sprintf(comment,"%s; size:%ld",comment,song->size);
_dl_filename(name,song->title);
SetComment(name,comment);
*/ }
song->f = 0;
song->state=0;
DoMethod(song->window,DL_STAT,msg);
}
void _dl_filename(char *buf, char *title)
{
char tmp;
int i;
for(i=strlen(title);i>0;i--) {
tmp = title[i-1];
if(tmp==':' || tmp=='/' || tmp=='\\') break;
}
if(!pref_dlpath)
sprintf(buf,"PROGDIR:%s",title+i);
else if (pref_dlpath[strlen(pref_dlpath)-1]==':')
sprintf(buf,"%s%s",pref_dlpath,title+i);
else if (pref_dlpath[strlen(pref_dlpath)-1]=='/')
sprintf(buf,"%s%s",pref_dlpath,title+i);
else
sprintf(buf,"%s/%s",pref_dlpath,title+i);
}