ReactOS  0.4.14-dev-49-gfb4591c
SConnect.c
Go to the documentation of this file.
1 #include "syshdrs.h"
2 
3 #ifndef NO_SIGNALS
4 extern volatile Sjmp_buf gNetTimeoutJmp;
5 extern volatile Sjmp_buf gPipeJmp;
6 #endif
7 
8 int
9 SConnect(int sfd, const struct sockaddr_in *const addr, int tlen)
10 {
11 #ifndef NO_SIGNALS
12  int result;
13  vsio_sigproc_t sigalrm;
14 
15  if (SSetjmp(gNetTimeoutJmp) != 0) {
16  alarm(0);
17  (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
18  errno = ETIMEDOUT;
19  return (kTimeoutErr);
20  }
21 
22  sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler);
23  alarm((unsigned int) tlen);
24 
25  errno = 0;
26  do {
27  result = connect(sfd, (struct sockaddr *) addr,
28  (int) sizeof(struct sockaddr_in));
29  } while ((result < 0) && (errno == EINTR));
30 
31  alarm(0);
32  (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
33  return (result);
34 #else /* NO_SIGNALS */
35  unsigned long opt;
36  fd_set ss, xx;
37  struct timeval tv;
38  int result;
39  int cErrno;
40 #if defined(WIN32) || defined(_WINDOWS)
41  int wsaErrno;
42  int soerr, soerrsize;
43 #else
44  int optval;
45  int optlen;
46 #endif
47 
48  errno = 0;
49  if (tlen <= 0) {
50  do {
51  result = connect(sfd, (struct sockaddr *) addr,
52  (int) sizeof(struct sockaddr_in));
53  SETERRNO
54  } while ((result < 0) && (errno == EINTR));
55  return (result);
56  }
57 
58 #ifdef FIONBIO
59  opt = 1;
60  if (ioctlsocket(sfd, FIONBIO, &opt) != 0) {
61  SETERRNO
62  return (-1);
63  }
64 #else
65  if (fcntl(sfd, F_GETFL, &opt) < 0) {
66  SETERRNO
67  return (-1);
68  } else if (fcntl(sfd, F_SETFL, opt | O_NONBLOCK) < 0) {
69  SETERRNO
70  return (-1);
71  }
72 #endif
73 
74  errno = 0;
75  result = connect(sfd, (struct sockaddr *) addr,
76  (int) sizeof(struct sockaddr_in));
77  if (result == 0)
78  return 0; /* Already?!? */
79 
80  if ((result < 0)
81 #if defined(WIN32) || defined(_WINDOWS)
82  && ((wsaErrno = WSAGetLastError()) != WSAEWOULDBLOCK)
83  && (wsaErrno != WSAEINPROGRESS)
84 #else
85  && (errno != EWOULDBLOCK) && (errno != EINPROGRESS)
86 #endif
87  ) {
88  SETERRNO
89  shutdown(sfd, 2);
90  return (-1);
91  }
92  cErrno = errno;
93 
94  forever {
95 #if defined(WIN32) || defined(_WINDOWS)
96  WSASetLastError(0);
97 #endif
98  FD_ZERO(&ss);
99  FD_SET(sfd, &ss);
100  xx = ss;
101  tv.tv_sec = tlen;
102  tv.tv_usec = 0;
104  if (result == 1) {
105  /* ready */
106  break;
107  } else if (result == 0) {
108  /* timeout */
109  errno = ETIMEDOUT;
111  /* Don't bother turning off FIONBIO */
112  return (kTimeoutErr);
113  } else if (errno != EINTR) {
114  /* Don't bother turning off FIONBIO */
115  SETERRNO
116  return (-1);
117  }
118  }
119 
120  /* Supposedly once the select() returns with a writable
121  * descriptor, it is connected and we don't need to
122  * recall connect(). When select() returns an exception,
123  * the connection failed -- we can get the connect error
124  * doing a write on the socket which will err out.
125  */
126 
127  if (FD_ISSET(sfd, &xx)) {
128 #if defined(WIN32) || defined(_WINDOWS)
129  errno = 0;
130  soerr = 0;
131  soerrsize = sizeof(soerr);
132  result = getsockopt(sfd, SOL_SOCKET, SO_ERROR, (char *) &soerr, &soerrsize);
133  if ((result >= 0) && (soerr != 0)) {
134  errno = soerr;
135  } else {
136  errno = 0;
137  (void) send(sfd, "\0", 1, 0);
138  SETERRNO
139  }
140 #else
141  errno = 0;
142  (void) send(sfd, "\0", 1, 0);
143 #endif
144  result = errno;
145  shutdown(sfd, 2);
146  errno = result;
147  return (-1);
148  }
149 
150 #if defined(WIN32) || defined(_WINDOWS)
151 #else
152  if (cErrno == EINPROGRESS) {
153  /*
154  * [from Linux connect(2) page]
155  *
156  * EINPROGRESS
157  *
158  * The socket is non-blocking and the connection can­
159  * not be completed immediately. It is possible to
160  * select(2) or poll(2) for completion by selecting
161  * the socket for writing. After select indicates
162  * writability, use getsockopt(2) to read the
163  * SO_ERROR option at level SOL_SOCKET to determine
164  * whether connect completed successfully (SO_ERROR
165  * is zero) or unsuccessfully (SO_ERROR is one of the
166  * usual error codes listed above, explaining the
167  * reason for the failure).
168  */
169  optval = 0;
170  optlen = sizeof(optval);
171  if (getsockopt(sfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == 0) {
172  errno = optval;
173  if (errno != 0)
174  return (-1);
175  }
176  }
177 #endif
178 
179 #ifdef FIONBIO
180  opt = 0;
181  if (ioctlsocket(sfd, FIONBIO, &opt) != 0) {
182  SETERRNO
183  shutdown(sfd, 2);
184  return (-1);
185  }
186 #else
187  if (fcntl(sfd, F_SETFL, opt) < 0) {
188  SETERRNO
189  shutdown(sfd, 2);
190  return (-1);
191  }
192 #endif
193 
194  return (0);
195 #endif /* NO_SIGNALS */
196 } /* SConnect */
Definition: winsock.h:66
#define SELECT_TYPE_ARG234
Definition: wincfg.h:4
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
volatile sio_sigproc_t vsio_sigproc_t
Definition: sio.h:124
#define O_NONBLOCK
Definition: port.h:158
#define EINTR
Definition: acclib.h:80
unsigned long tv_sec
Definition: linux.h:1738
#define WSAEWOULDBLOCK
Definition: winerror.h:1948
#define EINPROGRESS
Definition: errno.h:126
#define WIN32
Definition: windef.h:30
int errno
#define SOL_SOCKET
Definition: winsock.h:398
#define FD_ZERO(set)
Definition: winsock.h:96
#define FD_SET(fd, set)
Definition: winsock.h:89
INT WSAAPI connect(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: sockctrl.c:23
#define WSAEINPROGRESS
Definition: winerror.h:1949
int SConnect(int sfd, const struct sockaddr_in *const addr, int tlen)
Definition: SConnect.c:9
#define Sjmp_buf
Definition: sio.h:41
#define SETERRNO
Definition: sio.h:119
#define FD_ISSET(fd, set)
Definition: winsock.h:100
INT WSAAPI select(IN INT s, IN OUT LPFD_SET readfds, IN OUT LPFD_SET writefds, IN OUT LPFD_SET exceptfds, IN CONST struct timeval *timeout)
Definition: select.c:41
#define EWOULDBLOCK
Definition: errno.h:42
smooth NULL
Definition: ftsmooth.c:416
unsigned long tv_usec
Definition: linux.h:1739
#define kTimeoutErr
Definition: sio.h:58
#define SO_ERROR
Definition: winsock.h:194
#define ioctlsocket
Definition: main.c:40
VOID WSAAPI WSASetLastError(IN INT iError)
Definition: dllmain.c:123
INT WSAAPI WSAGetLastError(VOID)
Definition: dllmain.c:112
INT WSAAPI shutdown(IN SOCKET s, IN INT how)
Definition: sockctrl.c:506
INT WSAAPI send(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags)
Definition: send.c:23
int xx
Definition: npserver.c:29
#define SSetjmp(a)
Definition: sio.h:39
GLenum const GLvoid * addr
Definition: glext.h:9621
#define SELECT_TYPE_ARG5
Definition: wincfg.h:7
#define forever
Definition: ncftp.h:73
#define FIONBIO
Definition: winsock.h:149
INT WSAAPI getsockopt(IN SOCKET s, IN INT level, IN INT optname, OUT CHAR FAR *optval, IN OUT INT FAR *optlen)
Definition: sockctrl.c:271
#define SETWSATIMEOUTERR
Definition: sio.h:120
void(*)(int) SSignal(int signum, void(*handler)(int))
Definition: sio.h:237
#define ETIMEDOUT
Definition: errno.h:121
#define ss
Definition: i386-dis.c:432
GLuint64EXT * result
Definition: glext.h:11304
void(* sio_sigproc_t)(int)
Definition: sio.h:123
void SIOHandler(int)