home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / software / on-line / amster / src / download.c < prev    next >
C/C++ Source or Header  |  2000-01-21  |  9KB  |  406 lines

  1. /*
  2. ** Download
  3. */
  4.  
  5. #include "config.h"
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10.  
  11. #include <proto/exec.h>
  12. #include <proto/socket.h>
  13. #include <proto/dos.h>
  14. #include <libraries/dos.h>
  15. #include <netdb.h>
  16. #include <sys/time.h>
  17. #include <sys/socket.h>
  18. #include <sys/ioctl.h>
  19. #include <netinet/tcp.h>
  20. #include <bsdsocket/socketbasetags.h>
  21. #include <error.h>
  22.  
  23. #include "mui.h"
  24. #include <MUI/NListview_mcc.h>
  25. #include <MUI/NFloattext_mcc.h>
  26. #include "gui.h"
  27. #include "info.h"
  28. #include "download.h"
  29. #include "napster.h"
  30. #include "prefs.h"
  31. #include "amster_Cat.h"
  32.  
  33. dldata dl_list=NULL;
  34.  
  35. ULONG dl_new(struct IClass *cl, Object *obj, struct opSet *msg);
  36. void _dl_pollq(dldata song);
  37. void _dl_abort(dldata song, char *msg);
  38. void _dl_filename(char *buf, char *title);
  39.  
  40. extern struct Hook handleHook;
  41.  
  42.  
  43. ULONG __stdargs DoSuperNew(struct IClass *cl,Object *obj,ULONG tag1,...)
  44. {
  45.     return(DoSuperMethod(cl,obj,OM_NEW,&tag1,NULL));
  46. }
  47.  
  48.  
  49. MUIF dl_dispatch(REG(a0) struct IClass *cl,REG(a2) Object *obj,REG(a1) Msg msg)
  50. {
  51.     switch(msg->MethodID) {
  52.         case OM_NEW: return(dl_new(cl,obj,(APTR)msg));
  53.         case DL_ABORT:
  54.             {
  55.             struct dl_data *data = INST_DATA(cl,obj);
  56.             _dl_abort(data->song,(char *)MSG_DL_ABORT);
  57.             return(NULL);
  58.             }
  59.         case DL_CLOSE:
  60.             {
  61.             struct dl_data *data = INST_DATA(cl,obj);
  62.             _dl_abort(data->song,(char *)MSG_DL_ABORT);
  63.             data->song->abort=1;
  64.             DoMethod(gui->app,MUIM_Application_PushMethod,gui->app,3,MUIM_CallHook,&handleHook,99);
  65.             return(NULL);
  66.             }
  67.         case DL_GAUGE:
  68.             {
  69.             struct dl_data *data = INST_DATA(cl,obj);
  70.             u_long i = (u_long)((muimsg)msg)->arg1;
  71.             set(data->lvl,MUIA_Gauge_Divide,i/10000);
  72.             return(NULL);
  73.             }
  74.         case DL_UPDATE:
  75.             {
  76.             static char buf[50];
  77.             struct dl_data *data = INST_DATA(cl,obj);
  78.             int i = (int)((muimsg)msg)->arg1;
  79.             set(data->lvl,MUIA_Gauge_Current,i);
  80.             sprintf(buf,"%ld",i);
  81.             set(data->sz,MUIA_Text_Contents,buf);
  82.             return(NULL);
  83.             }
  84.         case DL_STAT:
  85.             {
  86.             struct dl_data *data = INST_DATA(cl,obj);
  87.             char *tmp = (char*)((muimsg)msg)->arg1;
  88.             set(data->stat,MUIA_Text_Contents,tmp);
  89.             return(NULL);
  90.             }
  91.     }
  92.     return(DoSuperMethodA(cl,obj,msg));
  93. }
  94.  
  95.  
  96. ULONG dl_new(struct IClass *cl, Object *obj, struct opSet *msg)
  97. {
  98.     struct dl_data *data;
  99.     dldata song = (dldata)GetTagData(DL_SONG,0,msg->ops_AttrList);
  100.     Object *but,*stat,*lvl,*sz;
  101.  
  102.     if (obj = (Object *)DoSuperNew(cl,obj,
  103.         WindowContents, VGroup,
  104.             Child, NListviewObject,
  105.                 MUIA_NListview_NList, NFloattextObject,
  106.                     ReadListFrame,
  107.                     MUIA_NFloattext_Text,song->info,
  108.                 End,
  109.             End,
  110.             Child, stat = TextObject,
  111.                 TextFrame,
  112.                 MUIA_Background, MUII_TextBack,
  113.                 MUIA_Text_PreParse, "\33c",
  114.                 MUIA_Text_Contents, MSG_DL_HOSTLOOKUP,
  115.             End,
  116.             Child, lvl = GaugeObject,
  117.                 GaugeFrame,
  118.                 MUIA_Gauge_Horiz, TRUE,
  119.                 MUIA_Gauge_Max, 10000,
  120.                 MUIA_Gauge_Divide, 400,
  121.                 MUIA_Gauge_InfoText, "",
  122.             End,
  123.             Child, ScaleObject, End,
  124.             Child, HGroup,
  125.                 Child, sz = TextObject,
  126.                     MUIA_Text_PreParse, "\33c",
  127.                 End,
  128.                 Child, but = SimpleButton(MSG_DL_ABORT_GAD),
  129.             End,
  130.         End,
  131.         TAG_MORE, msg->ops_AttrList))
  132.     {
  133.         data = INST_DATA(cl,obj);
  134.         data->song = song;
  135.         data->stat = stat;
  136.         data->but = but;
  137.         data->lvl = lvl;
  138.         data->sz = sz;
  139.  
  140.         set(obj,MUIA_Window_ID,MAKE_ID('D','O','W','N'));
  141.         set(obj,MUIA_Window_Title,MSG_DL_TITLE);
  142.  
  143.         DoMethod(but,MUIM_Notify,MUIA_Pressed,FALSE,obj,1,DL_ABORT);
  144.         DoMethod(obj,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,obj,1,DL_CLOSE);
  145.  
  146.         return((ULONG)obj);
  147.     }
  148.     return(0);
  149. }
  150.  
  151.  
  152. void dl_addq(songdata sd)
  153. {
  154.     dldata song;
  155.     Object *win;
  156.  
  157.     song = malloc(sizeof(_dldata));
  158.     if(!song) return;
  159.     memset(song,0,sizeof(_dldata));
  160.  
  161.     song->sock = -1;
  162.     strcpy(song->title,sd->title);
  163.     strcpy(song->user,sd->user);
  164.     song->size = sd->size;
  165.     sprintf(song->info,MSG_DL_INFORMATION,
  166.                sd->title,sd->user,nap_getlinktype(sd->link),sd->size,sd->bitrate,sd->freq);
  167.  
  168.     win = NewObject(gui->dl_mcc->mcc_Class,NULL,DL_SONG,(u_long)song,TAG_DONE);
  169.     if(win==0) {
  170.         free(song);
  171.         return;
  172.     }
  173.     song->window=win;
  174.     DoMethod(gui->app,OM_ADDMEMBER,win);
  175.     set(win,MUIA_Window_Open,TRUE);
  176.  
  177.     if(dl_list) song->next=dl_list;
  178.     dl_list=song;
  179. }
  180.  
  181.  
  182. void dl_startq(char *title, char *user, u_long ip, int port)
  183. {
  184.     struct sockaddr_in sin;
  185.     long tmp=1;
  186.     dldata song;
  187.     long s;
  188.  
  189.     song = dl_find(title,user);
  190.     if(!song) return;
  191.     if(song->state!=0) return;
  192.  
  193.     DoMethod(song->window,DL_STAT,MSG_DL_CONNECTING);
  194.  
  195.     s = socket(AF_INET,SOCK_STREAM,0);
  196.     if(s<0) {
  197.         DoMethod(song->window,DL_STAT,MSG_ERR_SOCKETERROR);
  198.         return;
  199.     }
  200.     sin.sin_addr.s_addr= ip;
  201. gui_debugf("+++host ip %d.%d.%d.%d\n",(ip&0xFF000000)>>24,(ip&0xFF0000)>>16,(ip&0xFF00)>>8,ip&0xFF);
  202.     sin.sin_port=port;
  203.     sin.sin_family=AF_INET;
  204.     sin.sin_len=sizeof(sin);
  205.     IoctlSocket(s,FIOASYNC,(char *)&tmp);
  206.     IoctlSocket(s,FIONBIO,(char *)&tmp);
  207.     song->state=1;
  208.     song->sock=s;
  209.     song->ip = ip;
  210.     tmp = connect(s,(struct sockaddr *)&sin,sin.sin_len);
  211.     if(tmp != -1) return;
  212.     if (Errno()==EINPROGRESS) return;
  213.     _dl_abort(song,(char *)MSG_ERR_CONNECTERROR);
  214. }
  215.  
  216.  
  217. dldata dl_find(char *title, char *user)
  218. {
  219.     dldata song;
  220.  
  221.     song = dl_list;
  222.     while(song) {
  223.         if(strcmp(song->user,user)==0 && strcmp(song->title,title)==0) return(song);
  224.         song = song->next;
  225.     }
  226.     return(NULL);
  227. }
  228.  
  229.  
  230. void dl_pollall(void)
  231. {
  232.     dldata song;
  233.     song = dl_list;
  234.     while(song) {
  235.         if(song->state!=0) _dl_pollq(song);
  236.         song = song->next;
  237.     }
  238. }
  239.  
  240.  
  241. int dl_flush(void)
  242. {
  243.     dldata song=dl_list,old=dl_list,next;
  244.     while(song) {
  245.         next = song->next;
  246.         if(song->abort==1) {
  247.             set(song->window,MUIA_Window_Open,FALSE);
  248.             DoMethod(gui->app,OM_REMMEMBER,song->window);
  249.             MUI_DisposeObject(song->window);
  250.             if(song==dl_list) {
  251.                 dl_list = next;
  252.             } else {
  253.                 old->next = next;
  254.             }
  255.             free(song);
  256.         } else {
  257.             old = song;
  258.         }
  259.         song = next;
  260.     }
  261.     if(dl_list==NULL) return(1);
  262.     return(0);
  263. }
  264.  
  265.  
  266. void _dl_pollq(dldata song)
  267. {
  268.     static unsigned char buf[4096];
  269.     struct fd_set fds;
  270.     struct timeval tv;
  271.     long s = song->sock;
  272.  
  273.     FD_ZERO(&fds);
  274.     FD_SET(song->sock,&fds);
  275.     tv.tv_sec=0;
  276.     tv.tv_usec=15;
  277.  
  278.     if(song->state==1) {
  279.         if (WaitSelect(s+1,NULL,&fds,NULL,&tv,0)==1) {
  280.             long tmp=0;
  281.             song->state=2;
  282.             IoctlSocket(s,FIONBIO,(char *)&tmp);
  283.             return;
  284.         }
  285.  
  286.     } else if(song->state==2) {
  287.         if(WaitSelect(s+1,&fds,NULL,NULL,&tv,0)==1) {
  288.             int r;
  289.             r = recv(s,buf,1,0);
  290.             if(r!=1 || (r==1 && buf[0]!='1')) {
  291.                 _dl_abort(song,(char *)MSG_DL_LOSTCONNECTION);
  292.                 return;
  293.             }
  294.             DoMethod(song->window,DL_STAT,MSG_DL_REQFILE);
  295.             song->state=3;
  296.             sprintf(buf,"GET");
  297.             send(s,buf,3,0);
  298.             sprintf(buf,"%s \"%s\" 0",pref_user,song->title);
  299.             send(s,buf,strlen(buf),0);
  300.             return;
  301.         }
  302.     } else if(song->state==3) {
  303.         if(WaitSelect(s+1,&fds,NULL,NULL,&tv,0)==1) {
  304.             int i;
  305.             for(i=0;i<strlen(buf);i++) {
  306.                 if(1!=recv(s,&buf[i],1,0)) {
  307.                     _dl_abort(song,(char *)MSG_DL_LOSTCONNECTION);
  308.                     return;
  309.                 }
  310.                 if(buf[i]==255) break;
  311.             }
  312.             buf[i]=0;
  313. gui_debugf("+++ header says %s\n",buf);
  314.  
  315.             DoMethod(song->window,DL_STAT,MSG_DL_DOWNLOADING);
  316.             song->state=4;
  317.             DoMethod(song->window,DL_GAUGE,song->size);
  318.             _dl_filename(buf,song->title);
  319. gui_debugf("+++ file: %s\n",buf);
  320.             song->f = Open(buf,MODE_READWRITE);
  321.             if(!song->f) {
  322.                 _dl_abort(song,(char *)MSG_DL_OPENERROR);
  323.                 return;
  324.             }
  325.             buf[0]=255;
  326.             FWrite(song->f,buf,1,1);
  327.             song->cur=1;
  328.             return;
  329.         }
  330.  
  331.     } else if(song->state==4) {
  332.         while(WaitSelect(s+1,&fds,NULL,NULL,&tv,0)==1) {
  333.             int len;
  334.             len=recv(s,buf,4090,0);
  335.             if(len<1) {
  336.                 if(len==0 && ((song->cur) >= (song->size))) {
  337.                     _dl_abort(song,(char *)MSG_DL_DOWNLOADFINISHED);
  338.                     return;
  339.                 }
  340.                 if (len==0) {
  341.                     _dl_abort(song,(char *)MSG_DL_LOSTCONNECTION);
  342.                     return;
  343.                 }
  344.                 _dl_abort(song,(char *)MSG_ERR_NETWORKERROR);
  345.                 return;
  346.             }
  347.             FWrite(song->f,buf,1,len);
  348.             song->cur = song->cur + len;
  349.             DoMethod(song->window,DL_UPDATE,song->cur);
  350.             FD_ZERO(&fds);
  351.             FD_SET(song->sock,&fds);
  352.             tv.tv_sec=0;
  353.             tv.tv_usec=15;
  354.         }
  355.  
  356.     }
  357. }
  358.  
  359.  
  360. void _dl_abort(dldata song, char *msg)
  361. {
  362. /*    static char name[1024];
  363.     static char comment[1024];
  364.     struct hostent *he_ip,*he_host;
  365. */
  366.     if(song->sock!= -1) CloseSocket(song->sock);
  367.     song->sock = -1;
  368.     if(song->f != 0) {
  369.         Close(song->f);
  370.  
  371. /*        he_ip = gethostbyname(Inet_NtoA(song->ip));
  372.         he_host = gethostbyaddr(he_ip->h_addr_list[0],he_ip->h_length,AF_INET);
  373.         if(he_host) sprintf(comment,"from %s (@%s)",song->user,he_host->h_name);
  374.         else sprintf(comment,"from %s (@%s)",song->user,Inet_NtoA(song->ip));
  375.  
  376.         if(song->state<5) sprintf(comment,"%s; size:%ld",comment,song->size);
  377.  
  378.         _dl_filename(name,song->title);
  379.         SetComment(name,comment);
  380. */    }
  381.     song->f = 0;
  382.     song->state=0;
  383.     DoMethod(song->window,DL_STAT,msg);
  384. }
  385.  
  386.  
  387. void _dl_filename(char *buf, char *title)
  388. {
  389.     char tmp;
  390.     int i;
  391.  
  392.     for(i=strlen(title);i>0;i--) {
  393.         tmp = title[i-1];
  394.         if(tmp==':' || tmp=='/' || tmp=='\\') break;
  395.     }
  396.  
  397.     if(!pref_dlpath)
  398.         sprintf(buf,"PROGDIR:%s",title+i);
  399.     else if (pref_dlpath[strlen(pref_dlpath)-1]==':')
  400.         sprintf(buf,"%s%s",pref_dlpath,title+i);
  401.     else if (pref_dlpath[strlen(pref_dlpath)-1]=='/')
  402.         sprintf(buf,"%s%s",pref_dlpath,title+i);
  403.     else
  404.         sprintf(buf,"%s/%s",pref_dlpath,title+i);
  405. }
  406.