#include <winsock2.h>
#include <ws2tcpip.h>
#include "err.h"
+ #include "preference.h"
#endif
/*
int socketCommType) // IN: SOCK_STREAM or SOCK_DGRAM?
{
if (bind(dst, addr, addrlen) == SOCKET_ERROR) {
- Log("%s: Could not bind socket.\n", __FUNCTION__);
+ Log("%s: Could not bind socket %d, error %d.\n",
+ __FUNCTION__, dst, WSAGetLastError());
return FALSE;
}
if (!blocking) {
unsigned long a = 1;
if (ioctlsocket(*src, FIONBIO, &a) == SOCKET_ERROR) {
- Log("%s: Could not make socket non-blocking.\n", __FUNCTION__);
+ Log("%s: Could not make socket %d non-blocking, error %d.\n",
+ __FUNCTION__, *src, WSAGetLastError());
return FALSE;
}
}
if (socketCommType == SOCK_STREAM && listen(dst, 1) == SOCKET_ERROR) {
- Log("%s: Could not listen on a socket.\n", __FUNCTION__);
+ Log("%s: Could not listen on a socket %d, error %d.\n",
+ __FUNCTION__, dst, WSAGetLastError());
return FALSE;
}
if (getsockname(dst, addr, &addrlen) == SOCKET_ERROR) {
- Log("%s: getsockname() failed.\n", __FUNCTION__);
+ Log("%s: getsockname() failed for socket %d, error %d.\n",
+ __FUNCTION__, dst, WSAGetLastError());
return FALSE;
}
PollSocketPairConnect(Bool blocking, // IN: blocking socket?
struct sockaddr *addr, // IN: the address connected to
int addrlen, // IN: length of struct sockaddr
- SOCKET *s) // IN: connecting socket
+ SOCKET *s, // IN: connecting socket
+ SocketSpecialOpts opts) // IN: socket special options
{
- if (connect(*s, addr, addrlen) == SOCKET_ERROR) {
+ if (blocking && (opts & POLL_OPTIONS_SOCKET_PAIR_NONBLOCK_CONN)) {
+ /* Change blocking socket to non-blocking socket for timeout */
+ unsigned long unblock = 1;
+ if (ioctlsocket(*s, FIONBIO, &unblock) == SOCKET_ERROR) {
+ Log("%s: Set socket %d to non-blocking mode failed, error %d.\n",
+ __FUNCTION__, *s, WSAGetLastError());
+ return FALSE;
+ }
+
+ if (connect(*s, addr, addrlen) == SOCKET_ERROR) {
+ WSAPOLLFD pollFds[1];
+ /* wait timeout seconds */
+ unsigned int timeout = Preference_GetLong(3,
+ "pref.wsa.socket.pair.connect.timeout.seconds") * 1000;
+ int ret = WSAGetLastError();
+ if (ret != WSAEWOULDBLOCK) {
+ /* connection failed */
+ Log("%s: Non-blocking socket %d could not connect to a local "
+ "socket, error %d.\n", __FUNCTION__, *s, WSAGetLastError());
+ return FALSE;
+ }
+
+ pollFds[0].fd = *s;
+ pollFds[0].events = POLLWRNORM;
+ pollFds[0].revents = 0;
+
+ ret = WSAPoll(pollFds, 1, timeout);
+ if (ret <= 0) {
+ /* WSAPoll failed or connection timed out */
+ if (ret == 0) {
+ WSASetLastError(WSAETIMEDOUT);
+ }
+ Log("%s: Non-blocking socket %d connects to a local socket "
+ "failed, error %d.\n", __FUNCTION__, *s, WSAGetLastError());
+ return FALSE;
+ }
+
+ if ((pollFds[0].revents &
+ (POLLWRNORM|POLLERR|POLLHUP)) != POLLWRNORM) {
+ /* connection failed */
+ int error = 0;
+ int errLen = sizeof error;
+ getsockopt(*s, SOL_SOCKET, SO_ERROR, (char *)&error, &errLen);
+ WSASetLastError(error);
+ Log("%s: Non-blocking socket %d connect to a local socket failed, "
+ "error %d.\n", __FUNCTION__, *s, WSAGetLastError());
+ return FALSE;
+ }
+ }
+ /* connection successful */
+ Log("%s: Non-blocking socket %d connected successfully with "
+ "socket type %d.\n", __FUNCTION__, *s, addr->sa_family);
+ unblock = 0;
+ if (ioctlsocket(*s, FIONBIO, &unblock) == SOCKET_ERROR) {
+ Log("%s: Non-blocking socket %d restored to blocking mode failed, "
+ "error %d.\n", __FUNCTION__, *s, WSAGetLastError());
+ return FALSE;
+ }
+ } else if (connect(*s, addr, addrlen) == SOCKET_ERROR) {
if (blocking || WSAGetLastError() != WSAEWOULDBLOCK) {
- Log("%s: Could not connect to a local socket.\n", __FUNCTION__);
+ Log("%s: socket %d could not connect to a local socket, "
+ "error %d.\n", __FUNCTION__, *s, WSAGetLastError());
return FALSE;
}
- } else if (!blocking) {
- Log("%s: non-blocking socket connected immediately!\n", __FUNCTION__);
- return FALSE;
+ } else {
+ Log("%s: non-blocking socket %d connected immediately!\n",
+ __FUNCTION__, *s);
}
return TRUE;
struct sockaddr *addr, // IN: the address connected to
int addrlen, // IN: length of struct sockaddr
Bool blocking, // IN: blocking socket?
- SOCKET *s) // OUT: connecting socket
+ SOCKET *s, // OUT: connecting socket
+ SocketSpecialOpts opts) // IN: socket special options
{
SOCKET temp = INVALID_SOCKET;
}
if (!PollSocketPairPrepare(blocking, s, temp, addr, addrlen, socketCommType)) {
- Log("%s: Could not prepare the socket pair for the following connecting,\
- socket type: %d\n", __FUNCTION__, sa_family);
+ Log("%s: Could not prepare the socket pair for the following "
+ "connecting, socket type: %d, sockets: %d, %d.\n",
+ __FUNCTION__, sa_family, *s, temp);
goto outCloseTemp;
}
- if (!PollSocketPairConnect(blocking, addr, addrlen, s)) {
- Log("%s: Could not make socket pair connected, socket type: %d",
- __FUNCTION__, sa_family);
+ if (!PollSocketPairConnect(blocking, addr, addrlen, s, opts)) {
+ Log("%s: Could not make socket pair connected, socket type: %d, "
+ "sockets: %d, %d.\n", __FUNCTION__, sa_family, *s, temp);
goto outCloseTemp;
}
static SOCKET
PollIPv4SocketPairStartConnecting(int socketCommType, // IN: SOCK_STREAM or SOCK_DGRAM?
Bool blocking, // IN: blocking socket?
- SOCKET *s) // OUT: connecting socket
+ SOCKET *s, // OUT: connecting socket
+ SocketSpecialOpts opts) // IN: socket special options
{
struct sockaddr_in iaddr;
int addrlen;
iaddr.sin_port = 0;
return PollSocketPairConnecting(iaddr.sin_family, socketCommType,
- (struct sockaddr*) &iaddr, addrlen, blocking, s);
+ (struct sockaddr*) &iaddr, addrlen,
+ blocking, s, opts);
}
static SOCKET
PollIPv6SocketPairStartConnecting(int socketCommType, // IN: SOCK_STREAM or SOCK_DGRAM?
Bool blocking, // IN: blocking socket?
- SOCKET *s) // OUT: connecting socket
+ SOCKET *s, // OUT: connecting socket
+ SocketSpecialOpts opts) // IN: socket special options
{
struct sockaddr_in6 iaddr6;
int addrlen;
iaddr6.sin6_port = 0;
return PollSocketPairConnecting(iaddr6.sin6_family, socketCommType,
- (struct sockaddr*) &iaddr6, addrlen, blocking, s);
+ (struct sockaddr*) &iaddr6, addrlen,
+ blocking, s, opts);
}
vaddr.svm_cid = VMCISock_GetLocalCID();
return PollSocketPairConnecting(vaddr.svm_family, socketCommType,
- (struct sockaddr*) &vaddr, addrlen, blocking, s);
+ (struct sockaddr*) &vaddr, addrlen,
+ blocking, s, 0);
}
PollSocketPairStartConnecting(Bool vmci, // IN: vmci socket?
Bool stream, // IN: stream socket?
Bool blocking, // IN: blocking socket?
- SOCKET *s) // OUT: connecting socket
+ SOCKET *s, // OUT: connecting socket
+ SocketSpecialOpts opts) // IN: socket special options
{
SOCKET temp = INVALID_SOCKET;
int socketCommType = stream ? SOCK_STREAM : SOCK_DGRAM;
if (vmci) {
temp = PollVMCISocketPairStartConnecting(socketCommType, blocking, s);
} else {
- temp = PollIPv6SocketPairStartConnecting(socketCommType, blocking, s);
+ temp = PollIPv6SocketPairStartConnecting(socketCommType, blocking,
+ s, opts);
if (temp == INVALID_SOCKET) {
- temp = PollIPv4SocketPairStartConnecting(socketCommType, blocking, s);
+ temp = PollIPv4SocketPairStartConnecting(socketCommType, blocking,
+ s, opts);
}
}
-
return temp;
}
int
Poll_SocketPair(Bool vmci, // IN: create vmci pair?
Bool stream, // IN: stream socket?
- int fds[2]) // OUT: 2 sockets connected to each other
+ int fds[2], // OUT: 2 sockets connected to each other
+ SocketSpecialOpts opts) // IN: socket special options
{
SOCKET temp = INVALID_SOCKET;
fds[0] = INVALID_SOCKET;
fds[1] = INVALID_SOCKET;
- temp = PollSocketPairStartConnecting(vmci, stream, TRUE, (SOCKET *)&fds[0]);
+ temp = PollSocketPairStartConnecting(vmci, stream, TRUE,
+ (SOCKET *)&fds[0], opts);
if (temp == INVALID_SOCKET) {
goto out;
}
#ifdef _WIN32
socketPairs[i].fds[0] = INVALID_SOCKET;
socketPairs[i].fds[1] = INVALID_SOCKET;
- if (Poll_SocketPair(useVMCI, TRUE, socketPairs[i].fds) < 0) {
+ if (Poll_SocketPair(useVMCI, TRUE, socketPairs[i].fds, 0) < 0) {
Warning("%s: failure -- error creating socketpair, iteration %d\n",
__FUNCTION__, i);
break;
closesocket(fds[1]);
fds[0] = INVALID_SOCKET;
fds[1] = INVALID_SOCKET;
- if (Poll_SocketPair(TRUE, TRUE, fds) < 0) {
+ if (Poll_SocketPair(TRUE, TRUE, fds, 0) < 0) {
Warning("%s: failure -- error creating vmci socketpair\n",
__FUNCTION__);
state ++;
closesocket(fds[1]);
fds[0] = INVALID_SOCKET;
fds[1] = INVALID_SOCKET;
- if (Poll_SocketPair(FALSE, TRUE, fds) < 0) {
+ if (Poll_SocketPair(FALSE, TRUE, fds, 0) < 0) {
Warning("%s: failure -- error creating socketpair\n",
__FUNCTION__);
state += 3;
closesocket(fds[1]);
fds[0] = INVALID_SOCKET;
fds[1] = INVALID_SOCKET;
- if (Poll_SocketPair(FALSE, TRUE, fds) < 0)
+ if (Poll_SocketPair(FALSE, TRUE, fds, 0) < 0)
#else
close(fds[0]);
close(fds[1]);
}
fds[0] = INVALID_SOCKET;
fds[1] = INVALID_SOCKET;
- if (Poll_SocketPair(FALSE, TRUE, fds) < 0) {
+ if (Poll_SocketPair(FALSE, TRUE, fds, 0) < 0) {
#else
fds[0] = -1;
fds[1] = -1;