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