1 /*
2 napster code base by Drago (drago@0x00.org)
3 released: 11-30-99
4 */
5 
6 #include <stdlib.h>
7 #include <string.h>
8 #include <netinet/in.h>
9 #include <sys/socket.h>
10 #include <netdb.h>
11 #include <stdarg.h>
12 #include <time.h>
13 #include <sys/time.h>
14 #include <assert.h>
15 
16 #include "napi.h"
17 
18 
n_GetServer(void)19 _N_SERVER *n_GetServer(void) {
20 	char serverline[1024], *server;
21 	int fd, r, port;
22 	struct sockaddr_in socka;
23 	static _N_SERVER theserver;
24 
25 	fd=socket(AF_INET, SOCK_STREAM, 0);
26 	socka.sin_addr.s_addr=inet_addr(n_nslookup(N_DISTRO_SERVER));
27 	socka.sin_family=AF_INET;
28 	socka.sin_port=htons(N_DISTRO_SERVER_PORT);
29 
30 	if (connect(fd, (struct sockaddr *)&socka, sizeof(struct sockaddr))!=0) {
31 		n_Error("connect()");
32 		close(fd);
33 		return NULL;
34 	}
35 
36 	r=read(fd, serverline, sizeof(serverline));
37 	if (r==-1) {
38 		n_Error("read()");
39 		close(fd);
40 		return NULL;
41 	}
42 	server=strstr(serverline, ":");
43 	if (!server) {
44 		n_Error("No port token?");
45 		close(fd);
46 		return NULL;
47 	}
48 
49 	*server='\0';
50 	server++;
51 	port=atoi(server);
52 	server=serverline;
53 
54 	strncpy(theserver.address, server, sizeof(theserver.address));
55 	theserver.port=port;
56 
57 	n_Debug("Server: %s Port: %d", theserver.address, theserver.port);
58 	close(fd);
59 	return &theserver;
60 }
61 
n_nslookup(char * addr)62 char *n_nslookup(char *addr) {
63 	struct hostent *h;
64 	if ((h=gethostbyname(addr)) == NULL) {
65 		return addr;
66 	}
67 	return (char *)inet_ntoa(*((struct in_addr *)h->h_addr));
68 }
69 
n_Connect(_N_SERVER * s,_N_AUTH * a)70 int n_Connect(_N_SERVER *s, _N_AUTH *a) {
71 	int r, port;
72 	struct sockaddr_in socka;
73 
74 	n_serverfd=socket(AF_INET, SOCK_STREAM, 0);
75 	socka.sin_addr.s_addr=inet_addr(n_nslookup(s->address));
76 	socka.sin_family=AF_INET;
77 	socka.sin_port=htons(s->port);
78 
79 	if (connect(n_serverfd, (struct sockaddr *)&socka, sizeof(struct sockaddr))!=0) {
80 		n_Error("connect()");
81 		close(n_serverfd);
82 		return 0;
83 	}
84 
85 	n_Debug("Connected");
86 
87 	n_SendCommand(CMDS_LOGIN, "%s %s %d \"v2.0 BETA 3\" %d", a->username, a->password, n_dataport, n_connectionspeed);
88 	{
89 		_N_COMMAND *cmd;
90 		cmd=n_GetCommand();
91 		if (cmd->cmd[2]==CMDR_ERROR) {
92 			n_Error("%s", cmd->data);
93 			return 0;
94 		} else {
95 			n_HandleCommand(cmd);
96 		}
97 	}
98 	return 1;
99 }
100 
n_HandleCommand(_N_COMMAND * cmd)101 void n_HandleCommand(_N_COMMAND *cmd) {
102 	switch (cmd->cmd[2]) {
103 		case CMDR_MOTD:
104 			if (n_HookMotd) {
105 				n_HookMotd(cmd->data);
106 			} else {
107 				n_Debug("No motd hook installed");
108 			}
109 		break;
110 		case CMDR_STATS:
111 /*
112 			D:napi.c:n_GetCommand():171:Data: 2104 197246 798
113 			2104==Libraries
114 			197246==songs
115 			798==gigs
116 */
117 			if (n_HookStats) {
118 				_N_STATS s;
119 				if (sscanf(cmd->data, "%d %d %d",
120 					&s.libraries, &s.songs, &s.gigs)!=3) {
121 					n_Error("Too few args");
122 				}
123 				else n_HookStats(&s);
124 			} else {
125 				n_Debug("No stats hook installed");
126 			}
127 		break;
128 	}
129 }
130 
n_SendCommand(_N_CMD ncmd,char * fmt,...)131 void n_SendCommand(_N_CMD ncmd, char *fmt, ...) {
132 	char buff[2048];
133 	_N_COMMAND command;
134 	va_list ap;
135 
136 	va_start(ap, fmt);
137 
138 	command.cmd[0]=vsnprintf(buff, sizeof(buff), fmt, ap);
139 	va_end(ap);
140 
141 	command.cmd[1]='\0';
142 	command.cmd[2]=ncmd;
143 	command.cmd[3]='\0';
144 
145 	n_Debug("Flags: %d %d %d %d", command.cmd[0], command.cmd[1], command.cmd[2], command.cmd[3]);
146 	n_Debug("Data: %s", buff);
147 
148 	n_Send(command.cmd, sizeof(command.cmd));
149 	n_Send(buff, command.cmd[0]);
150 }
151 
n_Send(char * data,int s)152 int n_Send(char *data, int s) {
153 	return write(n_serverfd, data, s);
154 }
155 
n_Loop(void)156 int n_Loop(void) {
157 	int sret;
158 	struct timeval tv;
159 	fd_set rfd;
160 	FD_ZERO(&rfd);
161 	FD_SET(n_serverfd, &rfd);
162 	tv.tv_sec=0;
163 	tv.tv_usec=0;
164 
165 	sret = select(n_serverfd+1, &rfd, NULL, NULL, &tv);
166 	if (sret>0) {
167 		if (FD_ISSET(n_serverfd, &rfd)) {
168 			n_DoCommand();
169 			return 1;
170 		}
171 	}
172 }
173 
n_GetCommand(void)174 _N_COMMAND *n_GetCommand(void) {
175 	static char rbuff[1024];
176 	static _N_COMMAND command;
177 	read(n_serverfd, command.cmd, sizeof(command.cmd));
178 	if (command.cmd[1]==0) {
179 		int r;
180 		assert(sizeof(rbuff) > command.cmd[0]);
181 		r=n_ReadCount(rbuff, command.cmd[0]);
182 	} else {
183 		int r=0;
184 		int cc=command.cmd[3]+1;
185 		while(cc>0) {
186 			assert(sizeof(rbuff) > r);
187 			if (read(n_serverfd, &rbuff[r], sizeof(char))==1) r++;
188 			if (rbuff[r-1]=='.') cc--;
189 		}
190 		rbuff[r]=0;
191 	}
192 	command.data=rbuff;
193         n_Debug("Flags: %d %d %d %d", command.cmd[0], command.cmd[1], command.cmd[2], command.cmd[3]);
194         n_Debug("Data: %s", command.data);
195 	return &command;
196 }
197 
n_DoCommand(void)198 void n_DoCommand(void) {
199 	_N_COMMAND *cmd;
200 	cmd=n_GetCommand();
201 	n_HandleCommand(cmd);
202 }
203 
n_ReadCount(char * buff,int c)204 int n_ReadCount(char *buff, int c) {
205 	int rc=0;
206 	while (c>rc) {
207 		if (read(n_serverfd, &buff[rc], sizeof(char))==1) rc++;
208 	}
209 	buff[rc]=0;
210 }
211 
n_SetMotdHook(void (* f)(char *))212 void n_SetMotdHook(void (*f)(char *)) {
213 	n_HookMotd=f;
214 	n_Debug("Installed motd hook");
215 }
216 
n_SetStatsHook(void (* f)(_N_STATS *))217 void n_SetStatsHook(void (*f)(_N_STATS *)) {
218 	n_HookStats=f;
219 	n_Debug("Installed stats hook");
220 }
221 
222