1 /*
2     TiMidity++ -- MIDI to WAVE converter and player
3     Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4     Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 
20 */
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif /* HAVE_CONFIG_H */
25 #include <stdio.h>
26 #include <stdlib.h>
27 #if !defined(WINSOCK)
28 #include <unistd.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <netdb.h>
33 #include <arpa/inet.h>  /* for inet_ntoa */
34 #ifndef NO_STRING_H
35 #include <string.h>
36 #else
37 #include <strings.h>
38 #endif
39 #endif
40 
41 #include "timidity.h"
42 #include "common.h"
43 #include "net.h"
44 
45 #ifndef INADDR_NONE
46 #define INADDR_NONE 0xffffffff
47 #endif /* INADDR_NONE */
48 
49 #if !defined(WINSOCK)
50 #ifndef INVALID_SOCKET
51 #define INVALID_SOCKET -1
52 #endif /* INVALID_SOCKET */
53 #ifndef SOCKET_ERROR
54 #define SOCKET_ERROR -1
55 #endif /* SOCKET_ERROR */
56 #endif
57 
58 #ifdef WIN32
59 #if _WIN32_WINNT < 0x0501
60 typedef int (WSAAPI * GETADDRINFO) (const char FAR *, const char FAR *,
61                                           const struct addrinfo FAR *,
62                                           struct addrinfo FAR * FAR *);
63 
64 typedef void (WSAAPI * FREEADDRINFO) ( struct addrinfo FAR * );
65 extern GETADDRINFO ws2_getaddrinfo;
66 extern FREEADDRINFO ws2_freeaddrinfo;
67 #define getaddrinfo ws2_getaddrinfo
68 #define freeaddrinfo ws2_freeaddrinfo
69 #else
70 #include <wspiapi.h>
71 #endif
72 #endif
73 
open_socket(char * host,unsigned short port)74 SOCKET open_socket(char *host, unsigned short port)
75 {
76     SOCKET fd = -1;
77     struct addrinfo hints, *result, *rp;
78     char service[NI_MAXSERV];
79     int s;
80 
81 #if defined(WINSOCK)
82     static int first = 1;
83     if(first) {
84 	WSADATA dmy;
85 	WSAStartup(MAKEWORD(1,1), &dmy);
86 	first = 0;
87     }
88 #endif
89 
90     memset(&hints, 0, sizeof(struct addrinfo));
91     hints.ai_family = AF_UNSPEC;
92     hints.ai_socktype = SOCK_STREAM;
93 #ifdef AI_ADDRCONFIG
94     /* By default, only look up addresses using address types for
95      * which a local interface is configured (i.e. no IPv6 if no IPv6
96      * interfaces. */
97     hints.ai_flags = AI_ADDRCONFIG;
98 #endif
99 
100     snprintf(service, sizeof(service), "%d", port);
101 
102     s = getaddrinfo(host, service, &hints, &result);
103 #ifdef AI_ADDRCONFIG
104     if (s == EAI_BADFLAGS) {
105         /* Retry with no flags if AI_ADDRCONFIG was rejected. */
106         hints.ai_flags = 0;
107         s = getaddrinfo(host, service, &hints, &result);
108     }
109 #endif
110 
111     if (s)
112         return (SOCKET)-1;
113 
114     for (rp = result; rp != NULL; rp = rp->ai_next)
115     {
116         if (rp->ai_family != AF_INET && rp->ai_family != AF_INET6)
117             continue;
118 
119         fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
120 
121         if (fd != -1 && connect(fd, rp->ai_addr, rp->ai_addrlen) != -1)
122             break;
123 
124         if (fd != -1) {
125             close(fd);
126             fd = -1;
127         }
128     }
129 
130     freeaddrinfo(result);
131     return (SOCKET) fd;
132 }
133 
134 #if !defined(__W32__) || defined(__CYGWIN32__)
socket_write(SOCKET fd,char * buff,long bufsiz)135 long socket_write(SOCKET fd, char *buff, long bufsiz)
136 {
137     return write(fd, buff, bufsiz);
138 }
139 
socket_shutdown(SOCKET fd,int how)140 int socket_shutdown(SOCKET fd, int how)
141 {
142     return shutdown(fd, how);
143 }
144 
socket_fdopen(SOCKET fd,char * mode)145 FILE *socket_fdopen(SOCKET fd, char *mode)
146 {
147     return fdopen(fd, mode);
148 }
149 
socket_fgets(char * buff,int n,FILE * fp)150 char *socket_fgets(char *buff, int n, FILE *fp)
151 {
152     return fgets(buff, n, fp);
153 }
154 
socket_fgetc(FILE * fp)155 int socket_fgetc(FILE *fp)
156 {
157     return getc(fp);
158 }
159 
socket_fread(void * buff,long bufsiz,FILE * fp)160 long socket_fread(void *buff, long bufsiz, FILE *fp)
161 {
162     return (long)fread(buff, 1, bufsiz, fp);
163 }
164 
socket_fwrite(void * buff,long bufsiz,FILE * fp)165 long socket_fwrite(void *buff, long bufsiz, FILE *fp)
166 {
167     return (long)fwrite(buff, 1, bufsiz, fp);
168 }
169 
socket_fclose(FILE * fp)170 int socket_fclose(FILE *fp)
171 {
172     return fclose(fp);
173 }
174 
socket_fflush(FILE * fp)175 int socket_fflush(FILE *fp)
176 {
177     return fflush(fp);
178 }
179 #else /* __W32__ */
180 
181 #include "url.h"
182 
183 /* Fake FILE * */
184 
185 typedef struct _w32_fp_socket_t
186 {
187     SOCKET fd; /* Now, It has only fd */
188 } w32_fp_socket;
189 #define W32_FP2SOCKET(fp) (((w32_fp_socket *)(fp))->fd)
190 
socket_safe_recv(SOCKET fd,char * buff,long bufsiz)191 static long socket_safe_recv(SOCKET fd, char *buff, long bufsiz)
192 {
193     fd_set fds;
194     int maxfd, n;
195 
196     FD_ZERO(&fds);
197     FD_SET(fd, &fds);
198     maxfd = fd + 1;
199 
200     n = select(maxfd, &fds, NULL, NULL, NULL);
201     if(n <= 0)
202 	return n;
203     return recv(fd, buff, bufsiz, 0);
204 }
205 
socket_write(SOCKET fd,char * buff,long bufsiz)206 long socket_write(SOCKET fd, char *buff, long bufsiz)
207 {
208     return send(fd, buff, bufsiz, 0);
209 }
210 
socket_shutdown(SOCKET fd,int how)211 int socket_shutdown(SOCKET fd, int how)
212 {
213     return shutdown(fd, how);
214 }
215 
216 #pragma argsused
socket_fdopen(SOCKET fd,char * mode)217 FILE *socket_fdopen(SOCKET fd, char *mode)
218 {
219     FILE *fp;
220 
221     /* w32_fp_socket fake FILE.
222      * `mode' argument is ignored.
223      */
224     if((fp = (FILE *)safe_malloc(sizeof(w32_fp_socket))) == NULL)
225 	return NULL;
226     memset(fp, 0, sizeof(w32_fp_socket));
227     W32_FP2SOCKET(fp) = fd;
228     return fp;
229 }
230 
socket_getc(SOCKET fd)231 static int socket_getc(SOCKET fd)
232 {
233     int n;
234     unsigned char c;
235 
236     n = socket_safe_recv(fd, (char *)&c, 1);
237     if(n <= 0)
238 	return EOF;
239     return (int)c;
240 }
241 
socket_fgets(char * buff,int n,FILE * fp)242 char *socket_fgets(char *buff, int n, FILE *fp)
243 {
244     SOCKET fd = W32_FP2SOCKET(fp);
245     int len;
246 
247     n--; /* for '\0' */
248     if(n == 0)
249 	*buff = '\0';
250     if(n <= 0)
251 	return buff;
252 
253     len = 0;
254     while(len < n)
255     {
256 	int c;
257 	c = socket_getc(fd);
258 	if(c == -1)
259 	    break;
260 	buff[len++] = c;
261 	if(c == url_newline_code)
262 	    break;
263     }
264     if(len == 0)
265 	return NULL;
266     buff[len] = '\0';
267     return buff;
268 }
269 
socket_fgetc(FILE * fp)270 int socket_fgetc(FILE *fp)
271 {
272     SOCKET fd = W32_FP2SOCKET(fp);
273     return socket_getc(fd);
274 }
275 
socket_fread(void * buff,long bufsiz,FILE * fp)276 long socket_fread(void *buff, long bufsiz, FILE *fp)
277 {
278     SOCKET fd = W32_FP2SOCKET(fp);
279     return socket_safe_recv(fd, buff, bufsiz);
280 }
281 
socket_fwrite(void * buff,long bufsiz,FILE * fp)282 long socket_fwrite(void *buff, long bufsiz, FILE *fp)
283 {
284     SOCKET fd = W32_FP2SOCKET(fp);
285     return socket_write(fd, buff, bufsiz);
286 }
287 
socket_fclose(FILE * fp)288 int socket_fclose(FILE *fp)
289 {
290     SOCKET fd = W32_FP2SOCKET(fp);
291     int ret;
292     ret = closesocket(fd);
293     free(fp);
294     return ret;
295 }
296 
socket_fflush(FILE * fp)297 int socket_fflush(FILE *fp)
298 {
299     return 0;
300 }
301 
302 #endif
303