1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <string.h>
5
6 #include "mynet.h"
7 #include "debug.h"
8
9 /* Cette fonction se reconnecte au server servername,
10 * port serverport, toute les time secondes, avec un
11 * maximum de _nb_tentatives.
12 *
13 * Si _nb_tentatives est NULL, ou �gal a -1, alors il n'y
14 * a aucune limite.
15 *
16 * Retourne la chausette cr��e
17 */
reconnect(int time,int _nb_tentatives,int _get_headers,icyHeaders * out_icy)18 int reconnect(int time, int _nb_tentatives, int _get_headers, icyHeaders *out_icy)
19 {
20 int tentatives = 0;
21 int server_socket;
22 serverSettings_t *settings;
23 icyHeaders *icy;
24
25 if (!time) time = 2;
26
27 if (serversPool == NULL)
28 {
29 _ERROR("Error: not any server defined.\n");
30 exit(1);
31 }
32
33 /* Get an entry in the pool */
34 settings = getSettings(serversPool, &poolPosition);
35 if (settings == NULL)
36 {
37 _ERROR("No valid settings in urlPool.\n");
38 exit(1);
39 }
40
41 RECO:
42 sleep(time);
43
44 while ( (server_socket = server_connect(settings->serverAddr, settings->port)) < 0)
45 {
46 /* Get an entry in the pool */
47 settings = getSettings(serversPool, &poolPosition);
48 if (settings == NULL)
49 {
50 _ERROR("No valid settings in urlPool.\n");
51 exit(1);
52 }
53
54 tentatives++;
55 if ((tentatives > _nb_tentatives) && (_nb_tentatives != -1))
56 {
57 MESSAGE("Too many tentatives. Exiting program.\n");
58 exit(-2);
59 }
60 MESSAGE("Reconnecting to http://%s:%d%s [try %d] in %d sec.\n", settings->serverAddr, settings->port, settings->mountpoint, tentatives, time);
61 sleep(time);
62 }
63
64 VERBOSE("Time spent to reconnect: %d seconds, %d tentatives.\n", (tentatives * time), tentatives);
65
66 if (sendHeaders(server_socket, settings->mountpoint, 1) <= 0)
67 {
68 _ERROR("Error sending headers: 0 byte sent.\n");
69 goto RECO;
70 }
71
72 if (_get_headers)
73 {
74 if ( (icy = readicyheaders(getHeaders(server_socket))) == NULL)
75 goto RECO;
76 else
77 out_icy = icy;
78 }
79
80 cPigeStats->reconnections++;
81
82 return server_socket;
83 }
84
server_connect(char * servername,int serverport)85 int server_connect (char *servername, int serverport)
86 {
87 struct sockaddr_in serverSockAddr;
88 struct hostent *serverHostEnt;
89 in_addr_t hostAddr;
90
91 #if WIN32
92 int res;
93 VERBOSE("Using win32 sockets\n");
94 WSADATA WSAData;
95 if((res = WSAStartup(MAKEWORD(2,0), &WSAData)) != 0)
96 printf("Impossible d'initialiser l'API Winsock 2.0\n");
97 #endif
98
99 VERBOSE("Entring Server_connect\n");
100
101 /* on initialise la socket */
102 memset(&serverSockAddr, 0, sizeof(serverSockAddr));
103 VERBOSE("Servername: %s\n", servername);
104 VERBOSE("Port: %d\n", serverport);
105 hostAddr = inet_addr(servername);
106
107 /* If it is an ip address */
108 if ( hostAddr != INADDR_NONE )
109 memcpy(&serverSockAddr.sin_addr, &hostAddr, sizeof(hostAddr));
110 else {
111 serverHostEnt = gethostbyname(servername);
112 if (serverHostEnt == NULL)
113 {
114 _ERROR("Error with gethostbyname. exiting.\n");
115 return -1;
116 }
117 memcpy(&serverSockAddr.sin_addr, serverHostEnt->h_addr, serverHostEnt->h_length);
118 }
119 serverSockAddr.sin_port = htons(serverport);
120 serverSockAddr.sin_family = AF_INET; /* FIXEME: IPv6 Support ? */
121
122 /* creation de la socket */
123 if ( (server_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
124 {
125 _ERROR("Error creating shoutcast socket. Exiting.\n");
126 return -2;
127 }
128
129 VERBOSE("Socket Creation Sucessful.\n");
130 VERBOSE("Connection in progress...\n");
131
132 /* requete de connexion */
133 if(connect( server_socket, (struct sockaddr *)&serverSockAddr, sizeof(serverSockAddr)) < 0 )
134 {
135 _ERROR("Remote host connection failed.\n");
136 return -3;
137 } else {
138 VERBOSE("Connected.\n");
139 }
140
141 FD_ZERO(&rfds);
142 FD_SET(server_socket, &rfds);
143
144 return server_socket;
145 }
146
server_close(int serversocket)147 int server_close (int serversocket)
148 {
149 VERBOSE("Closing server connection.\n");
150 shutdown(server_socket, 2);
151 close(server_socket);
152 server_socket = 0;
153 VERBOSE("Server connection closed.\n");
154 return -1;
155 }
156
sendHeaders(int serversocket,char * mountpoint,int metadata)157 int sendHeaders(int serversocket, char *mountpoint, int metadata)
158 {
159 int ret = 0;
160 char headers[256 + sizeof(USER_AGENT) + 16 + 11 + 4];
161
162 if (mountpoint == NULL)
163 snprintf(headers, 255, "GET / HTTP/1.0\r\n");
164 else
165 snprintf(headers, 255, "GET %s HTTP/1.0\r\n", mountpoint);
166
167 if (metadata != 0)
168 strncat(headers, "Icy-MetaData:1\r\n", 16);
169 else
170 strncat(headers, "Icy-MetaData:0\r\n", 16);
171
172 strncat(headers, "User-Agent:", 11);
173 strncat(headers, USER_AGENT, sizeof(USER_AGENT));
174 strncat(headers, "\r\n\r\n", 4);
175
176 ret = send(serversocket, headers, strlen(headers), 0);
177 return ret;
178 }
179
getHeaders(int serversocket)180 char *getHeaders(int serversocket)
181 {
182 int count = 0;
183 int j, i = 0;
184 int retval, errorCode = 0;
185 char *ptr;
186 char headers[4096]; /* Must check for overflow */
187 char buffer[512];
188 char c;
189
190 memset(headers, 0, 4096);
191 memset(buffer, 0, 512);
192
193 /* For select() it's a global struct. */
194 timeout.tv_sec = SOCKET_TIMEOUT;
195 timeout.tv_usec = 0;
196
197 retval = select(server_socket+1, &rfds, NULL, NULL, &timeout);
198 if (retval <= 0)
199 {
200 _ERROR("Erreur de connexion in getHeaders().\n");
201 goto error;
202 }
203
204 i = 0;
205
206 while ( (recv(serversocket, &c, 1, 0) > 0) && (i < 512) )
207 {
208 if (c == '\r')
209 continue;
210
211 if (c == '\n')
212 break;
213
214 buffer[i++] = c;
215 }
216
217 errorCode = getHTTPCode(buffer);
218 switch(errorCode)
219 {
220 case 200:
221 case 301:
222 case 302:
223 break;
224 default:
225 _ERROR("Unknown error code received: %d\n", errorCode);
226 goto error;
227 break;
228 }
229
230 headers[0] = 0;
231
232 for(j = 0, i = 0; ((j < 4096) && (count != 4)); j++)
233 {
234 /* For select() it's a global struct. */
235 timeout.tv_sec = SOCKET_TIMEOUT;
236 timeout.tv_usec = 0;
237 retval = select(server_socket+1, &rfds, NULL, NULL, &timeout);
238 if (retval <= 0)
239 {
240 _ERROR("Connection error in select (getHeaders).\n");
241 goto error;
242
243 } else if (recv(server_socket, &c, 1, 0) != 1) {
244 _ERROR("Error reading data in getHeaders()\n");
245 goto error;
246 }
247
248 if ((c == '\n') || (c == '\r'))
249 {
250 headers[i++] = c;
251 count++;
252 } else {
253 headers[i++] = c;
254 count = 0;
255 }
256 }
257 headers[i] = 0;
258
259 if (!strlen(headers))
260 return NULL;
261
262 ptr = strdup(headers);
263 printf("\n\n%s\n\n", ptr);
264
265 return ptr;
266
267 error:
268 server_close(server_socket);
269
270 return NULL;
271 }
272
getHTTPCode(char * buffer)273 int getHTTPCode(char *buffer)
274 {
275 char c;
276 char array[256]; /* Must check for overflow */
277 int i;
278 int j = 0;
279 int flag = 0;
280 int returnCode = 0;
281
282 if ((buffer == NULL) || (strlen(buffer) > 256)) return 0;
283
284 for (i = 0; i < strlen(buffer) && j < 256; i++)
285 {
286 c = buffer[i];
287
288 if (c == ' ')
289 {
290 if (flag)
291 {
292 array[j+1] = 0;
293 flag = 0;
294 } else
295 flag = 1;
296 }
297
298 if (flag)
299 array[j++] = c;
300
301 } /* for */
302
303 array[j] = 0;
304 returnCode = atoi((char *) &array);
305
306 return returnCode;
307 }
308
309
310