Postfix3.3.1
timed_connect.c
[詳解]
1 /*++
2 /* NAME
3 /* timed_connect 3
4 /* SUMMARY
5 /* connect operation with timeout
6 /* SYNOPSIS
7 /* #include <sys/socket.h>
8 /* #include <timed_connect.h>
9 /*
10 /* int timed_connect(fd, buf, buf_len, timeout)
11 /* int fd;
12 /* struct sockaddr *buf;
13 /* int buf_len;
14 /* int timeout;
15 /* DESCRIPTION
16 /* timed_connect() implement a BSD socket connect() operation that is
17 /* bounded in time.
18 /*
19 /* Arguments:
20 /* .IP fd
21 /* File descriptor in the range 0..FD_SETSIZE. This descriptor
22 /* must be set to non-blocking mode prior to calling timed_connect().
23 /* .IP buf
24 /* Socket address buffer pointer.
25 /* .IP buf_len
26 /* Size of socket address buffer.
27 /* .IP timeout
28 /* The deadline in seconds. This must be a number > 0.
29 /* DIAGNOSTICS
30 /* Panic: interface violations.
31 /* When the operation does not complete within the deadline, the
32 /* result value is -1, and errno is set to ETIMEDOUT.
33 /* All other returns are identical to those of a blocking connect(2)
34 /* operation.
35 /* WARNINGS
36 /* .ad
37 /* .fi
38 /* A common error is to call timed_connect() without enabling
39 /* non-blocking I/O on the socket. In that case, the \fItimeout\fR
40 /* parameter takes no effect.
41 /* LICENSE
42 /* .ad
43 /* .fi
44 /* The Secure Mailer license must be distributed with this software.
45 /* AUTHOR(S)
46 /* Wietse Venema
47 /* IBM T.J. Watson Research
48 /* P.O. Box 704
49 /* Yorktown Heights, NY 10598, USA
50 /*--*/
51 
52 /* System library. */
53 
54 #include <sys_defs.h>
55 #include <sys/socket.h>
56 #include <errno.h>
57 
58 /* Utility library. */
59 
60 #include "msg.h"
61 #include "iostuff.h"
62 #include "sane_connect.h"
63 #include "timed_connect.h"
64 
65 /* timed_connect - connect with deadline */
66 
67 int timed_connect(int sock, struct sockaddr *sa, int len, int timeout)
68 {
69  int error;
70  SOCKOPT_SIZE error_len;
71 
72  /*
73  * Sanity check. Just like with timed_wait(), the timeout must be a
74  * positive number.
75  */
76  if (timeout <= 0)
77  msg_panic("timed_connect: bad timeout: %d", timeout);
78 
79  /*
80  * Start the connection, and handle all possible results.
81  */
82  if (sane_connect(sock, sa, len) == 0)
83  return (0);
84  if (errno != EINPROGRESS)
85  return (-1);
86 
87  /*
88  * A connection is in progress. Wait for a limited amount of time for
89  * something to happen. If nothing happens, report an error.
90  */
91  if (write_wait(sock, timeout) < 0)
92  return (-1);
93 
94  /*
95  * Something happened. Some Solaris 2 versions have getsockopt() itself
96  * return the error, instead of returning it via the parameter list.
97  */
98  error = 0;
99  error_len = sizeof(error);
100  if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *) &error, &error_len) < 0)
101  return (-1);
102  if (error) {
103  errno = error;
104  return (-1);
105  }
106 
107  /*
108  * No problems.
109  */
110  return (0);
111 }
NORETURN msg_panic(const char *fmt,...)
Definition: msg.c:295
int sane_connect(int sock, struct sockaddr *sa, SOCKADDR_SIZE len)
Definition: sane_connect.c:44
#define SOCKOPT_SIZE
Definition: sys_defs.h:1415
int timed_connect(int sock, struct sockaddr *sa, int len, int timeout)
Definition: timed_connect.c:67
#define write_wait(fd, timeout)
Definition: iostuff.h:40