]> sjero.net Git - wget/blob - src/connect.c
[svn] Remove host canonicalization code.
[wget] / src / connect.c
1 /* Establishing and handling network connections.
2    Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
3
4 This file is part of GNU Wget.
5
6 GNU Wget 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 GNU Wget 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 Wget; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <sys/types.h>
24 #ifdef HAVE_UNISTD_H
25 # include <unistd.h>
26 #endif
27
28 #ifdef WINDOWS
29 # include <winsock.h>
30 #else
31 # include <sys/socket.h>
32 # include <netdb.h>
33 # include <netinet/in.h>
34 #ifndef __BEOS__
35 # include <arpa/inet.h>
36 #endif
37 #endif /* WINDOWS */
38
39 #include <errno.h>
40 #ifdef HAVE_STRING_H
41 # include <string.h>
42 #else
43 # include <strings.h>
44 #endif /* HAVE_STRING_H */
45 #ifdef HAVE_SYS_SELECT_H
46 # include <sys/select.h>
47 #endif /* HAVE_SYS_SELECT_H */
48
49 #include "wget.h"
50 #include "connect.h"
51 #include "host.h"
52
53 #ifndef errno
54 extern int errno;
55 #endif
56
57 /* Variables shared by bindport and acceptport: */
58 static int msock = -1;
59 static struct sockaddr *addr;
60
61
62 /* Create an internet connection to HOSTNAME on PORT.  The created
63    socket will be stored to *SOCK.  */
64 uerr_t
65 make_connection (int *sock, char *hostname, unsigned short port)
66 {
67   struct sockaddr_in sock_name;
68
69   if (!lookup_host (hostname, (unsigned char *)&sock_name.sin_addr))
70     return HOSTERR;
71
72   /* Set port and protocol */
73   sock_name.sin_family = AF_INET;
74   sock_name.sin_port = htons (port);
75
76   /* Make an internet socket, stream type.  */
77   if ((*sock = socket (AF_INET, SOCK_STREAM, 0)) == -1)
78     return CONSOCKERR;
79
80   if (opt.bind_address != NULL)
81     {
82       /* Bind the client side to the requested address. */
83       if (bind (*sock, (struct sockaddr *) opt.bind_address,
84                 sizeof (*opt.bind_address)))
85         return CONSOCKERR;
86     }
87
88   /* Connect the socket to the remote host.  */
89   if (connect (*sock, (struct sockaddr *) &sock_name, sizeof (sock_name)))
90     {
91       if (errno == ECONNREFUSED)
92         return CONREFUSED;
93       else
94         return CONERROR;
95     }
96   DEBUGP (("Created fd %d.\n", *sock));
97   return NOCONERROR;
98 }
99
100 int
101 test_socket_open (int sock)
102 {
103 #ifdef HAVE_SELECT
104   fd_set check_set;
105   struct timeval to;
106
107   /* Check if we still have a valid (non-EOF) connection.  From Andrew
108    * Maholski's code in the Unix Socket FAQ.  */
109
110   FD_ZERO (&check_set);
111   FD_SET (sock, &check_set);
112
113   /* Wait one microsecond */
114   to.tv_sec = 0;
115   to.tv_usec = 1;
116
117   /* If we get a timeout, then that means still connected */
118   if (select (sock + 1, &check_set, NULL, NULL, &to) == 0)
119     {
120       /* Connection is valid (not EOF), so continue */
121       return 1;
122     }
123   else
124     return 0;
125 #else
126   /* Without select, it's hard to know for sure. */
127   return 1;
128 #endif
129 }
130
131 /* Bind the local port PORT.  This does all the necessary work, which
132    is creating a socket, setting SO_REUSEADDR option on it, then
133    calling bind() and listen().  If *PORT is 0, a random port is
134    chosen by the system, and its value is stored to *PORT.  The
135    internal variable MPORT is set to the value of the ensuing master
136    socket.  Call acceptport() to block for and accept a connection.  */
137 uerr_t
138 bindport (unsigned short *port)
139 {
140   int optval = 1;
141   static struct sockaddr_in srv;
142
143   msock = -1;
144   addr = (struct sockaddr *) &srv;
145   if ((msock = socket (AF_INET, SOCK_STREAM, 0)) < 0)
146     return CONSOCKERR;
147   if (setsockopt (msock, SOL_SOCKET, SO_REUSEADDR,
148                   (char *)&optval, sizeof (optval)) < 0)
149     return CONSOCKERR;
150
151   if (opt.bind_address == NULL)
152     {
153       srv.sin_family = AF_INET;
154       srv.sin_addr.s_addr = htonl (INADDR_ANY);
155     }
156   else
157     srv = *opt.bind_address;
158
159   srv.sin_port = htons (*port);
160   if (bind (msock, addr, sizeof (struct sockaddr_in)) < 0)
161     {
162       CLOSE (msock);
163       msock = -1;
164       return BINDERR;
165     }
166   DEBUGP (("Master socket fd %d bound.\n", msock));
167   if (!*port)
168     {
169       /* #### addrlen should be a 32-bit type, which int is not
170          guaranteed to be.  Oh, and don't try to make it a size_t,
171          because that can be 64-bit.  */
172       int addrlen = sizeof (struct sockaddr_in);
173       if (getsockname (msock, addr, &addrlen) < 0)
174         {
175           CLOSE (msock);
176           msock = -1;
177           return CONPORTERR;
178         }
179       *port = ntohs (srv.sin_port);
180     }
181   if (listen (msock, 1) < 0)
182     {
183       CLOSE (msock);
184       msock = -1;
185       return LISTENERR;
186     }
187   return BINDOK;
188 }
189
190 #ifdef HAVE_SELECT
191 /* Wait for file descriptor FD to be readable, MAXTIME being the
192    timeout in seconds.  If WRITEP is non-zero, checks for FD being
193    writable instead.
194
195    Returns 1 if FD is accessible, 0 for timeout and -1 for error in
196    select().  */
197 int
198 select_fd (int fd, int maxtime, int writep)
199 {
200   fd_set fds, exceptfds;
201   struct timeval timeout;
202
203   FD_ZERO (&fds);
204   FD_SET (fd, &fds);
205   FD_ZERO (&exceptfds);
206   FD_SET (fd, &exceptfds);
207   timeout.tv_sec = maxtime;
208   timeout.tv_usec = 0;
209   /* HPUX reportedly warns here.  What is the correct incantation?  */
210   return select (fd + 1, writep ? NULL : &fds, writep ? &fds : NULL,
211                  &exceptfds, &timeout);
212 }
213 #endif /* HAVE_SELECT */
214
215 /* Call accept() on MSOCK and store the result to *SOCK.  This assumes
216    that bindport() has been used to initialize MSOCK to a correct
217    value.  It blocks the caller until a connection is established.  If
218    no connection is established for OPT.TIMEOUT seconds, the function
219    exits with an error status.  */
220 uerr_t
221 acceptport (int *sock)
222 {
223   int addrlen = sizeof (struct sockaddr_in);
224
225 #ifdef HAVE_SELECT
226   if (select_fd (msock, opt.timeout, 0) <= 0)
227     return ACCEPTERR;
228 #endif
229   if ((*sock = accept (msock, addr, &addrlen)) < 0)
230     return ACCEPTERR;
231   DEBUGP (("Created socket fd %d.\n", *sock));
232   return ACCEPTOK;
233 }
234
235 /* Close SOCK, as well as the most recently remembered MSOCK, created
236    via bindport().  If SOCK is -1, close MSOCK only.  */
237 void
238 closeport (int sock)
239 {
240   /*shutdown (sock, 2);*/
241   if (sock != -1)
242     CLOSE (sock);
243   if (msock != -1)
244     CLOSE (msock);
245   msock = -1;
246 }
247
248 /* Return the local IP address associated with the connection on FD.
249    It is returned in a static buffer.  */
250 unsigned char *
251 conaddr (int fd)
252 {
253   static unsigned char res[4];
254   struct sockaddr_in mysrv;
255   struct sockaddr *myaddr;
256   int addrlen = sizeof (mysrv); /* see bindport() for discussion of
257                                    using `int' here. */
258
259   myaddr = (struct sockaddr *) (&mysrv);
260   if (getsockname (fd, myaddr, (int *)&addrlen) < 0)
261     return NULL;
262   memcpy (res, &mysrv.sin_addr, 4);
263   return res;
264 }
265
266 /* Read at most LEN bytes from FD, storing them to BUF.  This is
267    virtually the same as read(), but takes care of EINTR braindamage
268    and uses select() to timeout the stale connections (a connection is
269    stale if more than OPT.TIMEOUT time is spent in select() or
270    read()).  */
271 int
272 iread (int fd, char *buf, int len)
273 {
274   int res;
275
276   do
277     {
278 #ifdef HAVE_SELECT
279       if (opt.timeout)
280         {
281           do
282             {
283               res = select_fd (fd, opt.timeout, 0);
284             }
285           while (res == -1 && errno == EINTR);
286           if (res <= 0)
287             {
288               /* Set errno to ETIMEDOUT on timeout.  */
289               if (res == 0)
290                 /* #### Potentially evil!  */
291                 errno = ETIMEDOUT;
292               return -1;
293             }
294         }
295 #endif
296       res = READ (fd, buf, len);
297     }
298   while (res == -1 && errno == EINTR);
299
300   return res;
301 }
302
303 /* Write LEN bytes from BUF to FD.  This is similar to iread(), but
304    doesn't bother with select().  Unlike iread(), it makes sure that
305    all of BUF is actually written to FD, so callers needn't bother
306    with checking that the return value equals to LEN.  Instead, you
307    should simply check for -1.  */
308 int
309 iwrite (int fd, char *buf, int len)
310 {
311   int res = 0;
312
313   /* `write' may write less than LEN bytes, thus the outward loop
314      keeps trying it until all was written, or an error occurred.  The
315      inner loop is reserved for the usual EINTR f*kage, and the
316      innermost loop deals with the same during select().  */
317   while (len > 0)
318     {
319       do
320         {
321 #ifdef HAVE_SELECT
322           if (opt.timeout)
323             {
324               do
325                 {
326                   res = select_fd (fd, opt.timeout, 1);
327                 }
328               while (res == -1 && errno == EINTR);
329               if (res <= 0)
330                 {
331                   /* Set errno to ETIMEDOUT on timeout.  */
332                   if (res == 0)
333                     /* #### Potentially evil!  */
334                     errno = ETIMEDOUT;
335                   return -1;
336                 }
337             }
338 #endif
339           res = WRITE (fd, buf, len);
340         }
341       while (res == -1 && errno == EINTR);
342       if (res <= 0)
343         break;
344       buf += res;
345       len -= res;
346     }
347   return res;
348 }