home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Enigma Amiga Life 109
/
EnigmaAmiga109CD.iso
/
software
/
on-line
/
amster
/
src
/
napster.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-01-21
|
8KB
|
433 lines
/*
** Napster Protocol
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <proto/exec.h>
#include <proto/socket.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 "napster.h"
#include "gui.h"
#include "search.h"
#include "download.h"
#include "prefs.h"
#include "info.h"
#include "msg.h"
#include "amster_Cat.h"
struct Library *SocketBase=NULL;
unsigned long nap_sigmask;
long nap_sock= -1;
char *nap_linktype[] = {
(char*)_MSG_LINE_UNKNOWN,
(char*)_MSG_LINE_14400,
(char*)_MSG_LINE_28800,
(char*)_MSG_LINE_33600,
(char*)_MSG_LINE_57600,
(char*)_MSG_LINE_64000,
(char*)_MSG_LINE_128000,
(char*)_MSG_LINE_CABLE,
(char*)_MSG_LINE_DSL,
(char*)_MSG_LINE_T1,
(char*)_MSG_LINE_T3,
NULL
};
int _nap_lala(void);
void _nap_bibi(void);
long _nap_connect(char *server);
void _nap_send(unsigned int type, char *buf);
int _nap_read(unsigned int *type, char **buf);
void _nap_parsesearch(char *buf);
void _nap_parsebrowseuser(char *buf);
char *_nap_findserver(void);
int nap_login(void)
{
char *srv;
char buf[256], tmp[100];
char *rep;
unsigned int type;
if(pref_server) srv=pref_server;
else
{
set(gui->stat,MUIA_Text_Contents,MSG_STATUS2_FINDINGOPTIMAL);
srv=_nap_findserver();
}
if(!srv || strcmp(srv,"127.0.0.1:1111") == 0) {
/* Sometimes the server returns "127.0.0.1:1111" - quite odd. */
set(gui->stat,MUIA_Text_Contents,MSG_STATUS2_OPTIMALFAILED);
return(0);
}
sprintf(tmp,MSG_STATUS2_CONNECTINGTO,srv);
set(gui->stat,MUIA_Text_Contents,tmp);
nap_sock = _nap_connect(srv);
if(nap_sock<0) {
sprintf(tmp,MSG_STATUS2_CONNECTFAILED,srv);
set(gui->stat,MUIA_Text_Contents,tmp);
return(0);
}
gui_debug((char *)MSG_INFO_CONNECTED);
if(pref_regflag) {
sprintf(buf,"%s",pref_user);
_nap_send(NAP_CREATEUSER,buf);
}
sprintf(buf,"%s %s %d \"%s\" %d",pref_user,pref_pass,0,pref_napvers,pref_link);
_nap_send(NAP_LOGIN,buf);
if(!_nap_read(&type,&rep)) {
gui_debug((char *)MSG_ERR_RECVERROR);
nap_logout();
return(0);
}
if(type==NAP_ERROR) {
gui_debug((char *)MSG_INFO_LOGINFAILED);
nap_logout();
return(0);
}
gui_debug((char *)MSG_INFO_LOGGEDIN);
gui_state(1);
return(1);
}
void nap_updateaccount(void)
{
_nap_send(NAP_EMAILCHANGE,pref_email);
}
void nap_logout(void)
{
if(nap_sock>=0) CloseSocket(nap_sock);
nap_sock = -1;
_nap_bibi();
gui_state(0);
}
int nap_listen(void)
{
char *buf;
unsigned int type;
struct fd_set fds;
struct timeval tv;
dl_pollall();
if(nap_sock== -1) return(1);
while(1) {
FD_ZERO(&fds);
FD_SET(nap_sock,&fds);
tv.tv_sec=0;
tv.tv_usec=15;
if(WaitSelect(nap_sock+1,&fds,NULL,NULL,&tv,0)<1) return(0);
if(!_nap_read(&type,&buf)) {
gui_debug((char *)MSG_ERR_NETWORKERROR);
nap_logout();
return(1);
}
switch(type) {
case NAP_SEARCHRESULT:
_nap_parsesearch(buf);
break;
case NAP_SEARCHCOMPLETE:
gui_found(NULL);
break;
case NAP_BROWSERESULT:
_nap_parsebrowseuser(buf);
break;
case NAP_BROWSECOMPLETE:
gui_found(NULL);
break;
case NAP_FILECOUNT:
{
char *tmp,*tmp2;
strtok(buf," ");
tmp=strtok(NULL," ");
tmp2=strtok(NULL,"");
gui_srvstat(atoi(buf),atoi(tmp),atoi(tmp2));
break;
}
case NAP_PRIVATEMSG:
{
char *nick,*msg;
nick = strtok(buf," ");
msg = strtok(NULL,"");
msg_got(nick,msg);
break;
}
case NAP_FILEINFO:
{
char title[256],user[20];
unsigned long ip;
int port;
sscanf(buf, "%s %u %d \"%[^\"]\"",user,&ip,&port,title);
dl_startq(title,user,NAP_SWAPIP(ip),port);
}
break;
case NAP_LOGINRESP:
gui_debugf((char *)MSG_INFO_EMAIL,buf);
break;
case NAP_SYSMSG:
gui_debug(buf);
break;
default:
gui_debugf("<<%d:%s>>",type,buf);
break;
}
free(buf);
}
}
void nap_browseuser(char *nick)
{
_nap_send(NAP_BROWSEUSER,nick);
}
void nap_search(char *keys, int max, int speed, int speedval, int bit, int bitval, int freq, int freqval)
{
static char *opts[] = {
"AT LEAST",
"EQUAL TO",
"AT BEST"
};
char buf[1024];
char *tmp;
tmp = buf + sprintf(buf,"FILENAME CONTAINS \"%s\" MAX_RESULTS %d",keys,max);
if(speed) tmp=tmp+sprintf(tmp," LINESPEED \"%s\" %d",opts[speed-1],speedval);
if(bit) tmp=tmp+sprintf(tmp," BITRATE \"%s\" %d",opts[bit-1],bitval);
if(freq) sprintf(tmp," FREQ \"%s\" %d",opts[freq-1],freqval);
_nap_send(NAP_SEARCH,buf);
}
void nap_request(songdata sd)
{
char buf[1024];
sprintf(buf,"\"%s\" \"%s\"",sd->user,sd->title);
_nap_send(NAP_FILEINFOREQ,buf);
dl_addq(sd);
}
void nap_msg(char *nick, char *msg)
{
char buf[1024];
sprintf(buf,"%s %s",nick,msg);
_nap_send(NAP_PRIVATEMSG,buf);
}
char *nap_getlinktype(int link)
{
return(nap_linktype[link]);
}
/* private functions */
void _nap_parsesearch(char *buf)
{
songdata sd;
int tmp;
sd = malloc(sizeof(_songdata));
if(!sd) return;
memset(sd,0,sizeof(_songdata));
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);
gui_found(sd);
}
void _nap_parsebrowseuser(char *buf)
{
songdata sd;
sd = malloc(sizeof(_songdata));
if(!sd) return;
memset(sd,0,sizeof(_songdata));
sscanf(buf,"%s \"%[^\"]\" %s %lu %d %d %d %d",sd->user,sd->title,sd->chksum,&sd->size,&sd->bitrate,&sd->freq,&sd->time);
gui_found(sd);
}
char *_nap_findserver(void)
{
long s;
static char buf[256];
char *col;
int len;
s = _nap_connect(pref_mainserver);
if(s<0) return(NULL);
len = recv(s,buf,255,0);
CloseSocket(s);
if(len<=0) {
gui_debug((char *)MSG_ERR_RECVERROR);
_nap_bibi();
return(NULL);
}
buf[len]=0;
col = strchr(buf,'\n');
if(col) *col=0;
if (strncmp(buf,"wait",4)==0 || strncmp(buf,"busy",4)==0) {
gui_debug((char *)MSG_INFO_SERVERBUSY);
_nap_bibi();
return(NULL);
}
gui_debugf((char *)MSG_INFO_OPTIMAL,buf);
return(buf);
}
/* low level private functions */
int _nap_lala(void)
{
if(SocketBase) return(1);
SocketBase = OpenLibrary("bsdsocket.library",0);
if(!SocketBase) {
gui_debug((char *)MSG_NO_TCPIP);
return(0);
}
SocketBaseTags(SBTM_SETVAL(SBTC_SIGIOMASK),(char *)nap_sigmask,TAG_DONE);
return(1);
}
void _nap_bibi(void)
{
if(dl_list!=NULL) return;
if(SocketBase) CloseLibrary(SocketBase);
SocketBase = NULL;
}
long _nap_connect(char *server)
{
long s;
struct hostent *host;
struct sockaddr_in sin;
char *col,*addr;
int port;
long temp=1;
if(!_nap_lala()) return(-1);
addr = strdup(server);
col = strtok(addr,":");
if(!col) {
gui_debug((char *)MSG_INFO_PORTNEEDED);
_nap_bibi();
return(-1);
}
col = strtok(NULL,"");
port = atoi(col);
host = gethostbyname(addr);
if(!host) {
gui_debug((char *)MSG_ERR_LOOKUPFAILED);
_nap_bibi();
return(-1);
}
memcpy(&sin.sin_addr,host->h_addr,host->h_length);
sin.sin_family = host->h_addrtype;
sin.sin_port = port;
sin.sin_len = sizeof(sin);
s = socket(AF_INET,SOCK_STREAM,0);
if(s<0) {
gui_debug((char *)MSG_ERR_SOCKETERROR);
_nap_bibi();
return(-1);
}
if(connect(s,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))<0) {
gui_debug((char *)MSG_ERR_CONNECTERROR);
_nap_bibi();
CloseSocket(s);
return(-1);
}
IoctlSocket(s,FIOASYNC,(char *)&temp);
return(s);
}
int _nap_read(unsigned int *type, char **buf)
{
static u_char hdr[4];
char *tmp;
unsigned int len,rlen=0,i;
len = recv(nap_sock,hdr,4,0);
if(len!=4) return(0);
len = hdr[0] + (hdr[1]<<8);
*type = hdr[2] + (hdr[3]<<8);
tmp = malloc(len+2);
if(!tmp) return(0);
while(rlen<len) {
i = recv(nap_sock,tmp+rlen,len-rlen,0);
if(i<0) {
free(tmp);
return(0);
}
rlen += i;
}
tmp[rlen]=0;
*buf = tmp;
return(1);
}
void _nap_send(unsigned int type, char *buf)
{
static u_char hdr[4];
int len;
len = strlen(buf);
hdr[0] = len&0xFF;
hdr[1] = (len&0xFF00)>>8;
hdr[2] = type&0xFF;
hdr[3] = (type&0xFF00)>>8;
send(nap_sock,hdr,4,0);
send(nap_sock,buf,len,0);
}