ReactOS 0.4.16-dev-117-g38f21f9
SConnect.c
Go to the documentation of this file.
1#include "syshdrs.h"
2
3#ifndef NO_SIGNALS
4extern volatile Sjmp_buf gNetTimeoutJmp;
5extern volatile Sjmp_buf gPipeJmp;
6#endif
7
8int
9SConnect(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);
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));
54 } while ((result < 0) && (errno == EINTR));
55 return (result);
56 }
57
58#ifdef FIONBIO
59 opt = 1;
60 if (ioctlsocket(sfd, FIONBIO, &opt) != 0) {
62 return (-1);
63 }
64#else
65 if (fcntl(sfd, F_GETFL, &opt) < 0) {
67 return (-1);
68 } else if (fcntl(sfd, F_SETFL, opt | O_NONBLOCK) < 0) {
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 ) {
89 shutdown(sfd, 2);
90 return (-1);
91 }
92 cErrno = errno;
93
94 forever {
95#if defined(WIN32) || defined(_WINDOWS)
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 */
111 /* Don't bother turning off FIONBIO */
112 return (kTimeoutErr);
113 } else if (errno != EINTR) {
114 /* Don't bother turning off FIONBIO */
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);
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) {
183 shutdown(sfd, 2);
184 return (-1);
185 }
186#else
187 if (fcntl(sfd, F_SETFL, opt) < 0) {
189 shutdown(sfd, 2);
190 return (-1);
191 }
192#endif
193
194 return (0);
195#endif /* NO_SIGNALS */
196} /* SConnect */
int SConnect(int sfd, const struct sockaddr_in *const addr, int tlen)
Definition: SConnect.c:9
#define EINTR
Definition: acclib.h:80
#define NULL
Definition: types.h:112
VOID WSAAPI WSASetLastError(IN INT iError)
Definition: dllmain.c:123
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
INT WSAAPI send(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags)
Definition: send.c:23
#define EWOULDBLOCK
Definition: errno.h:42
#define ETIMEDOUT
Definition: errno.h:121
#define EINPROGRESS
Definition: errno.h:126
GLenum const GLvoid * addr
Definition: glext.h:9621
GLuint64EXT * result
Definition: glext.h:11304
#define ss
Definition: i386-dis.c:441
#define SELECT_TYPE_ARG234
Definition: wincfg.h:4
#define SELECT_TYPE_ARG5
Definition: wincfg.h:7
void SIOHandler(int)
#define SETWSATIMEOUTERR
Definition: sio.h:120
#define SSetjmp(a)
Definition: sio.h:39
volatile sio_sigproc_t vsio_sigproc_t
Definition: sio.h:124
void(*)(int) SSignal(int signum, void(*handler)(int))
Definition: sio.h:237
#define Sjmp_buf
Definition: sio.h:41
#define kTimeoutErr
Definition: sio.h:58
void(* sio_sigproc_t)(int)
Definition: sio.h:123
#define SETERRNO
Definition: sio.h:119
#define O_NONBLOCK
Definition: port.h:158
#define forever
Definition: ncftp.h:73
#define ioctlsocket
Definition: ncftp.h:481
int xx
Definition: npserver.c:29
#define errno
Definition: errno.h:18
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
INT WSAAPI shutdown(IN SOCKET s, IN INT how)
Definition: sockctrl.c:506
Definition: winsock.h:66
unsigned long tv_sec
Definition: linux.h:1738
unsigned long tv_usec
Definition: linux.h:1739
#define WIN32
Definition: windef.h:30
#define WSAEWOULDBLOCK
Definition: winerror.h:1948
#define WSAEINPROGRESS
Definition: winerror.h:1949
#define SO_ERROR
Definition: winsock.h:194
#define FD_ISSET(fd, set)
Definition: winsock.h:100
int PASCAL FAR WSAGetLastError(void)
Definition: dllmain.c:112
#define FD_ZERO(set)
Definition: winsock.h:96
#define SOL_SOCKET
Definition: winsock.h:398
#define FD_SET(fd, set)
Definition: winsock.h:89
#define FIONBIO
Definition: winsock.h:149