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

  1. /*
  2. ** Napster Protocol
  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 <netdb.h>
  14. #include <sys/time.h>
  15. #include <sys/socket.h>
  16. #include <sys/ioctl.h>
  17. #include <netinet/tcp.h>
  18. #include <bsdsocket/socketbasetags.h>
  19.  
  20. #include "napster.h"
  21. #include "gui.h"
  22. #include "search.h"
  23. #include "download.h"
  24. #include "prefs.h"
  25. #include "info.h"
  26. #include "msg.h"
  27. #include "amster_Cat.h"
  28.  
  29. struct Library *SocketBase=NULL;
  30. unsigned long nap_sigmask;
  31. long nap_sock= -1;
  32.  
  33. char *nap_linktype[] = {
  34.     (char*)_MSG_LINE_UNKNOWN,
  35.     (char*)_MSG_LINE_14400,
  36.     (char*)_MSG_LINE_28800,
  37.     (char*)_MSG_LINE_33600,
  38.     (char*)_MSG_LINE_57600,
  39.     (char*)_MSG_LINE_64000,
  40.     (char*)_MSG_LINE_128000,
  41.     (char*)_MSG_LINE_CABLE,
  42.     (char*)_MSG_LINE_DSL,
  43.     (char*)_MSG_LINE_T1,
  44.     (char*)_MSG_LINE_T3,
  45.     NULL
  46. };
  47.  
  48. int _nap_lala(void);
  49. void _nap_bibi(void);
  50. long _nap_connect(char *server);
  51. void _nap_send(unsigned int type, char *buf);
  52. int _nap_read(unsigned int *type, char **buf);
  53.  
  54. void _nap_parsesearch(char *buf);
  55. void _nap_parsebrowseuser(char *buf);
  56. char *_nap_findserver(void);
  57.  
  58.  
  59. int nap_login(void)
  60. {
  61.     char *srv;
  62.     char buf[256], tmp[100];
  63.     char *rep;
  64.     unsigned int type;
  65.  
  66.     if(pref_server) srv=pref_server;
  67.     else
  68.     {
  69.         set(gui->stat,MUIA_Text_Contents,MSG_STATUS2_FINDINGOPTIMAL);
  70.         srv=_nap_findserver();
  71.     }
  72.     if(!srv || strcmp(srv,"127.0.0.1:1111") == 0) {
  73.         /* Sometimes the server returns "127.0.0.1:1111" - quite odd. */
  74.         set(gui->stat,MUIA_Text_Contents,MSG_STATUS2_OPTIMALFAILED);
  75.         return(0);
  76.     }
  77.  
  78.     sprintf(tmp,MSG_STATUS2_CONNECTINGTO,srv);
  79.     set(gui->stat,MUIA_Text_Contents,tmp);
  80.  
  81.     nap_sock = _nap_connect(srv);
  82.     if(nap_sock<0) {
  83.         sprintf(tmp,MSG_STATUS2_CONNECTFAILED,srv);
  84.         set(gui->stat,MUIA_Text_Contents,tmp);
  85.         return(0);
  86.     }
  87.  
  88.     gui_debug((char *)MSG_INFO_CONNECTED);
  89.  
  90.     if(pref_regflag) {
  91.         sprintf(buf,"%s",pref_user);
  92.         _nap_send(NAP_CREATEUSER,buf);
  93.     }
  94.  
  95.     sprintf(buf,"%s %s %d \"%s\" %d",pref_user,pref_pass,0,pref_napvers,pref_link);
  96.     _nap_send(NAP_LOGIN,buf);
  97.     if(!_nap_read(&type,&rep)) {
  98.         gui_debug((char *)MSG_ERR_RECVERROR);
  99.         nap_logout();
  100.         return(0);
  101.     }
  102.     if(type==NAP_ERROR) {
  103.         gui_debug((char *)MSG_INFO_LOGINFAILED);
  104.         nap_logout();
  105.         return(0);
  106.     }
  107.  
  108.     gui_debug((char *)MSG_INFO_LOGGEDIN);
  109.     gui_state(1);
  110.     return(1);
  111. }
  112.  
  113.  
  114. void nap_updateaccount(void)
  115. {
  116.     _nap_send(NAP_EMAILCHANGE,pref_email);
  117. }
  118.  
  119.  
  120. void nap_logout(void)
  121. {
  122.     if(nap_sock>=0) CloseSocket(nap_sock);
  123.     nap_sock = -1;
  124.     _nap_bibi();
  125.     gui_state(0);
  126. }
  127.  
  128.  
  129. int nap_listen(void)
  130. {
  131.     char *buf;
  132.     unsigned int type;
  133.     struct fd_set fds;
  134.     struct timeval tv;
  135.  
  136.     dl_pollall();
  137.  
  138.     if(nap_sock== -1) return(1);
  139.  
  140.     while(1) {
  141.         FD_ZERO(&fds);
  142.         FD_SET(nap_sock,&fds);
  143.         tv.tv_sec=0;
  144.         tv.tv_usec=15;
  145.         if(WaitSelect(nap_sock+1,&fds,NULL,NULL,&tv,0)<1) return(0);
  146.  
  147.         if(!_nap_read(&type,&buf)) {
  148.             gui_debug((char *)MSG_ERR_NETWORKERROR);
  149.             nap_logout();
  150.             return(1);
  151.         }
  152.  
  153.         switch(type) {
  154.             case NAP_SEARCHRESULT:
  155.                 _nap_parsesearch(buf);
  156.                 break;
  157.             case NAP_SEARCHCOMPLETE:
  158.                 gui_found(NULL);
  159.                 break;
  160.             case NAP_BROWSERESULT:
  161.                 _nap_parsebrowseuser(buf);
  162.                 break;
  163.             case NAP_BROWSECOMPLETE:
  164.                 gui_found(NULL);
  165.                 break;
  166.             case NAP_FILECOUNT:
  167.                 {
  168.                 char *tmp,*tmp2;
  169.                 strtok(buf," ");
  170.                 tmp=strtok(NULL," ");
  171.                 tmp2=strtok(NULL,"");
  172.                 gui_srvstat(atoi(buf),atoi(tmp),atoi(tmp2));
  173.                 break;
  174.                 }
  175.             case NAP_PRIVATEMSG:
  176.                 {
  177.                 char *nick,*msg;
  178.                 nick = strtok(buf," ");
  179.                 msg = strtok(NULL,"");
  180.                 msg_got(nick,msg);
  181.                 break;
  182.                 }
  183.             case NAP_FILEINFO:
  184.                 {
  185.                 char title[256],user[20];
  186.                 unsigned long ip;
  187.                 int port;
  188.                 sscanf(buf, "%s %u %d \"%[^\"]\"",user,&ip,&port,title);
  189.                 dl_startq(title,user,NAP_SWAPIP(ip),port);
  190.                 }
  191.                 break;
  192.             case NAP_LOGINRESP:
  193.                 gui_debugf((char *)MSG_INFO_EMAIL,buf);
  194.                 break;
  195.             case NAP_SYSMSG:
  196.                 gui_debug(buf);
  197.                 break;
  198.             default:
  199.                 gui_debugf("<<%d:%s>>",type,buf);
  200.                 break;
  201.         }
  202.         free(buf);
  203.     }
  204. }
  205.  
  206.  
  207. void nap_browseuser(char *nick)
  208. {
  209.     _nap_send(NAP_BROWSEUSER,nick);
  210. }
  211.  
  212.  
  213. void nap_search(char *keys, int max, int speed, int speedval, int bit, int bitval, int freq, int freqval)
  214. {
  215.     static char *opts[] = {
  216.         "AT LEAST",
  217.         "EQUAL TO",
  218.         "AT BEST"
  219.     };
  220.     char buf[1024];
  221.     char *tmp;
  222.  
  223.     tmp = buf + sprintf(buf,"FILENAME CONTAINS \"%s\" MAX_RESULTS %d",keys,max);
  224.  
  225.     if(speed) tmp=tmp+sprintf(tmp," LINESPEED \"%s\" %d",opts[speed-1],speedval);
  226.     if(bit) tmp=tmp+sprintf(tmp," BITRATE \"%s\" %d",opts[bit-1],bitval);
  227.     if(freq) sprintf(tmp," FREQ \"%s\" %d",opts[freq-1],freqval);
  228.  
  229.     _nap_send(NAP_SEARCH,buf);
  230. }
  231.  
  232.  
  233. void nap_request(songdata sd)
  234. {
  235.     char buf[1024];
  236.  
  237.     sprintf(buf,"\"%s\" \"%s\"",sd->user,sd->title);
  238.     _nap_send(NAP_FILEINFOREQ,buf);
  239.     dl_addq(sd);
  240. }
  241.  
  242.  
  243. void nap_msg(char *nick, char *msg)
  244. {
  245.     char buf[1024];
  246.  
  247.     sprintf(buf,"%s %s",nick,msg);
  248.     _nap_send(NAP_PRIVATEMSG,buf);
  249. }
  250.  
  251.  
  252. char *nap_getlinktype(int link)
  253. {
  254.     return(nap_linktype[link]);
  255. }
  256.  
  257.  
  258. /* private functions */
  259.  
  260. void _nap_parsesearch(char *buf)
  261. {
  262.     songdata sd;
  263.     int tmp;
  264.  
  265.     sd = malloc(sizeof(_songdata));
  266.     if(!sd) return;
  267.     memset(sd,0,sizeof(_songdata));
  268.     sscanf(buf,"\"%[^\"]\" %s %lu %d %d %d %s %d %d",sd->title,sd->chksum,&sd->size,&sd->bitrate,&sd->freq,&sd->time,sd->user,&tmp,&sd->link);
  269.     gui_found(sd);
  270. }
  271.  
  272.  
  273. void _nap_parsebrowseuser(char *buf)
  274. {
  275.     songdata sd;
  276.  
  277.     sd = malloc(sizeof(_songdata));
  278.     if(!sd) return;
  279.     memset(sd,0,sizeof(_songdata));
  280.     sscanf(buf,"%s \"%[^\"]\" %s %lu %d %d %d %d",sd->user,sd->title,sd->chksum,&sd->size,&sd->bitrate,&sd->freq,&sd->time);
  281.     gui_found(sd);
  282. }
  283.  
  284.  
  285. char *_nap_findserver(void)
  286. {
  287.     long s;
  288.     static char buf[256];
  289.     char *col;
  290.     int len;
  291.  
  292.     s = _nap_connect(pref_mainserver);
  293.     if(s<0) return(NULL);
  294.  
  295.     len = recv(s,buf,255,0);
  296.     CloseSocket(s);
  297.     if(len<=0) {
  298.         gui_debug((char *)MSG_ERR_RECVERROR);
  299.         _nap_bibi();
  300.         return(NULL);
  301.     }
  302.  
  303.     buf[len]=0;
  304.     col = strchr(buf,'\n');
  305.     if(col) *col=0;
  306.  
  307.     if (strncmp(buf,"wait",4)==0 || strncmp(buf,"busy",4)==0) {
  308.         gui_debug((char *)MSG_INFO_SERVERBUSY);
  309.         _nap_bibi();
  310.         return(NULL);
  311.     }
  312.  
  313.     gui_debugf((char *)MSG_INFO_OPTIMAL,buf);
  314.     return(buf);
  315. }
  316.  
  317.  
  318.  
  319.  
  320. /* low level private functions */
  321.  
  322. int _nap_lala(void)
  323. {
  324.     if(SocketBase) return(1);
  325.     SocketBase = OpenLibrary("bsdsocket.library",0);
  326.     if(!SocketBase) {
  327.         gui_debug((char *)MSG_NO_TCPIP);
  328.         return(0);
  329.     }
  330.     SocketBaseTags(SBTM_SETVAL(SBTC_SIGIOMASK),(char *)nap_sigmask,TAG_DONE);
  331.     return(1);
  332. }
  333.  
  334.  
  335. void _nap_bibi(void)
  336. {
  337.     if(dl_list!=NULL) return;
  338.     if(SocketBase) CloseLibrary(SocketBase);
  339.     SocketBase = NULL;
  340. }
  341.  
  342.  
  343. long _nap_connect(char *server)
  344. {
  345.     long s;
  346.     struct hostent *host;
  347.     struct sockaddr_in sin;
  348.     char *col,*addr;
  349.     int port;
  350.     long temp=1;
  351.  
  352.     if(!_nap_lala()) return(-1);
  353.  
  354.     addr = strdup(server);
  355.     col = strtok(addr,":");
  356.     if(!col) {
  357.         gui_debug((char *)MSG_INFO_PORTNEEDED);
  358.         _nap_bibi();
  359.         return(-1);
  360.     }
  361.     col = strtok(NULL,"");
  362.     port = atoi(col);
  363.  
  364.     host = gethostbyname(addr);
  365.     if(!host) {
  366.         gui_debug((char *)MSG_ERR_LOOKUPFAILED);
  367.         _nap_bibi();
  368.         return(-1);
  369.     }
  370.     memcpy(&sin.sin_addr,host->h_addr,host->h_length);
  371.     sin.sin_family = host->h_addrtype;
  372.     sin.sin_port = port;
  373.     sin.sin_len = sizeof(sin);
  374.  
  375.     s = socket(AF_INET,SOCK_STREAM,0);
  376.     if(s<0) {
  377.         gui_debug((char *)MSG_ERR_SOCKETERROR);
  378.         _nap_bibi();
  379.         return(-1);
  380.     }
  381.  
  382.     if(connect(s,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))<0) {
  383.         gui_debug((char *)MSG_ERR_CONNECTERROR);
  384.         _nap_bibi();
  385.         CloseSocket(s);
  386.         return(-1);
  387.     }
  388.  
  389.     IoctlSocket(s,FIOASYNC,(char *)&temp);
  390.     return(s);
  391. }
  392.  
  393.  
  394. int _nap_read(unsigned int *type, char **buf)
  395. {
  396.     static u_char hdr[4];
  397.     char *tmp;
  398.     unsigned int len,rlen=0,i;
  399.     len = recv(nap_sock,hdr,4,0);
  400.     if(len!=4) return(0);
  401.     len = hdr[0] + (hdr[1]<<8);
  402.     *type = hdr[2] + (hdr[3]<<8);
  403.  
  404.     tmp = malloc(len+2);
  405.     if(!tmp) return(0);
  406.     while(rlen<len) {
  407.         i = recv(nap_sock,tmp+rlen,len-rlen,0);
  408.         if(i<0) {
  409.             free(tmp);
  410.             return(0);
  411.         }
  412.         rlen += i;
  413.     }
  414.     tmp[rlen]=0;
  415.     *buf = tmp;
  416.     return(1);
  417. }
  418.  
  419.  
  420. void _nap_send(unsigned int type, char *buf)
  421. {
  422.     static u_char hdr[4];
  423.     int len;
  424.  
  425.     len = strlen(buf);
  426.     hdr[0] = len&0xFF;
  427.     hdr[1] = (len&0xFF00)>>8;
  428.     hdr[2] = type&0xFF;
  429.     hdr[3] = (type&0xFF00)>>8;
  430.     send(nap_sock,hdr,4,0);
  431.     send(nap_sock,buf,len,0);
  432. }
  433.