XN_C_API XnStatus xnOSAcceptSocket(XN_SOCKET_HANDLE ListenSocket, XN_SOCKET_HANDLE* AcceptSocketPtr, XnUInt32 nMillisecondsTimeout) { // Local function variables XnInt32 nRetVal = 0; struct timeval selectTimeOut; struct timeval* pTimeout = xnOSMillisecsToTimeVal(nMillisecondsTimeout, &selectTimeOut); fd_set fdReadHandles; XN_SOCKET_HANDLE AcceptSocket = NULL; // Validate the input/output pointers (to make sure none of them is NULL) XN_VALIDATE_INPUT_PTR(ListenSocket); XN_VALIDATE_OUTPUT_PTR(AcceptSocketPtr); // Make sure the actual socket handle isn't NULL XN_RET_IF_NULL(ListenSocket->Socket, XN_STATUS_OS_INVALID_SOCKET); // Wait for connection request XN_PRAGMA_START_DISABLED_WARNING_SECTION(XN_CONDITION_IS_CONST_WARNING_ID); FD_ZERO(&fdReadHandles); FD_SET(ListenSocket->Socket, &fdReadHandles); XN_PRAGMA_STOP_DISABLED_WARNING_SECTION; nRetVal = select(1 /* ignored */, &fdReadHandles, NULL, NULL, pTimeout); if (nRetVal == 0) { return (XN_STATUS_OS_NETWORK_TIMEOUT); } else if (nRetVal == SOCKET_ERROR) { XN_LOG_ERROR_RETURN(XN_STATUS_OS_NETWORK_SOCKET_ACCEPT_FAILED, XN_MASK_OS, "select() returned WinSock error: %d", WSAGetLastError()); } // Allocate a new socket XN_VALIDATE_ALIGNED_CALLOC(*AcceptSocketPtr, xnOSSocket, 1, XN_DEFAULT_MEM_ALIGN); AcceptSocket = *AcceptSocketPtr; // Accept the socket and make sure it succeeded AcceptSocket->nSocketAddressLen = sizeof(AcceptSocket->SocketAddress); AcceptSocket->Socket = accept(ListenSocket->Socket, (sockaddr*)&AcceptSocket->SocketAddress, &AcceptSocket->nSocketAddressLen); if (AcceptSocket->Socket == INVALID_SOCKET) { xnOSCloseSocket(AcceptSocket); xnOSFreeAligned(*AcceptSocketPtr); return(XN_STATUS_OS_NETWORK_SOCKET_ACCEPT_FAILED); } // All is good... return (XN_STATUS_OK); }
XN_C_API XnStatus xnOSReceiveNetworkBuffer(XN_SOCKET_HANDLE Socket, XnChar* cpBuffer, XnUInt32* pnBufferSize, XnUInt32 nMillisecondsTimeout) { // Local function variables XnInt32 nRetVal = 0; struct timeval selectTimeOut; struct timeval* pTimeout = xnOSMillisecsToTimeVal(nMillisecondsTimeout, &selectTimeOut); fd_set fdReadHandles; // Validate the input/output pointers (to make sure none of them is NULL) XN_VALIDATE_INPUT_PTR(Socket); XN_VALIDATE_OUTPUT_PTR(cpBuffer); XN_VALIDATE_OUTPUT_PTR(pnBufferSize); // Make sure the actual socket handle isn't NULL XN_RET_IF_NULL(Socket->Socket, XN_STATUS_OS_INVALID_SOCKET); XN_PRAGMA_START_DISABLED_WARNING_SECTION(XN_CONDITION_IS_CONST_WARNING_ID); FD_ZERO(&fdReadHandles); FD_SET(Socket->Socket, &fdReadHandles); XN_PRAGMA_STOP_DISABLED_WARNING_SECTION; nRetVal = select(1 /* ignored */, &fdReadHandles, NULL, NULL, pTimeout); if (nRetVal == 0) { return (XN_STATUS_OS_NETWORK_TIMEOUT); } else if (nRetVal != 1) { XN_LOG_ERROR_RETURN(XN_STATUS_OS_NETWORK_RECEIVE_FAILED, XN_MASK_OS, "select() failed with winsock error %d", WSAGetLastError()); } // Receive the data from our socket to the buffer and make sure it succeeded *pnBufferSize = recv(Socket->Socket, cpBuffer, *pnBufferSize, 0); if (*pnBufferSize == 0) { xnLogVerbose(XN_MASK_OS, "Socket has been gracefully closed"); return (XN_STATUS_OS_NETWORK_CONNECTION_CLOSED); } else if (*pnBufferSize == SOCKET_ERROR) { XN_LOG_ERROR_RETURN(XN_STATUS_OS_NETWORK_RECEIVE_FAILED, XN_MASK_OS, "recv() failed with winsock error %d", WSAGetLastError()); } // All is good... return (XN_STATUS_OK); }
XN_C_API XnStatus xnOSConnectSocket(XN_SOCKET_HANDLE Socket, XnUInt32 nMillisecsTimeout) { // Local function variables XnInt32 nRetVal = 0; sockaddr SocketAddress; fd_set fdWriteHandles; fd_set fdExceptHandles; struct timeval selectTimeOut; struct timeval* pTimeout = xnOSMillisecsToTimeVal(nMillisecsTimeout, &selectTimeOut); // Validate the input/output pointers (to make sure none of them is NULL) XN_VALIDATE_INPUT_PTR(Socket); // Make sure the actual socket handle isn't NULL XN_RET_IF_NULL(Socket->Socket, XN_STATUS_OS_INVALID_SOCKET); // Connect to the socket and make sure it succeeded xnOSMemCopy(&SocketAddress, &Socket->SocketAddress, sizeof(SocketAddress)); // if timeout is XN_SOCKET_DEFAULT_TIMEOUT, leave the socket as a blocking one if (nMillisecsTimeout != XN_SOCKET_DEFAULT_TIMEOUT) { // Make the socket non-blocking temporarily u_long nNonBlockingSocket = 1; if (ioctlsocket(Socket->Socket, FIONBIO, &nNonBlockingSocket) != 0) { XN_LOG_ERROR_RETURN(XN_STATUS_OS_NETWORK_SOCKET_CONNECT_FAILED, XN_MASK_OS, "ioctlsocket() failed with error %d", WSAGetLastError()); } } nRetVal = connect(Socket->Socket, &SocketAddress, sizeof(SocketAddress)); if ((nRetVal == SOCKET_ERROR) && (WSAGetLastError() != WSAEWOULDBLOCK)) { xnLogError(XN_MASK_OS, "connect() failed with winsock error %d", WSAGetLastError()); return(XN_STATUS_OS_NETWORK_SOCKET_CONNECT_FAILED); } if (nMillisecsTimeout != XN_SOCKET_DEFAULT_TIMEOUT) { XN_PRAGMA_START_DISABLED_WARNING_SECTION(XN_CONDITION_IS_CONST_WARNING_ID); FD_ZERO(&fdWriteHandles); FD_SET(Socket->Socket, &fdWriteHandles); FD_ZERO(&fdExceptHandles); FD_SET(Socket->Socket, &fdExceptHandles); XN_PRAGMA_STOP_DISABLED_WARNING_SECTION; nRetVal = select(1 /* ignored */, NULL, &fdWriteHandles, &fdExceptHandles, pTimeout); // in any case, make the socket blocking again before we check select()'s success u_long nBlockingSocket = 0; ioctlsocket(Socket->Socket, FIONBIO, &nBlockingSocket); if (nRetVal == 0) { return (XN_STATUS_OS_NETWORK_TIMEOUT); } else if (nRetVal == SOCKET_ERROR) { XN_LOG_ERROR_RETURN(XN_STATUS_OS_NETWORK_SOCKET_CONNECT_FAILED, XN_MASK_OS, "select() returned WinSock error: %d", WSAGetLastError()); } else { // select returned due to socket state change. Check if an error occurred or everything is OK. if (FD_ISSET(Socket->Socket, &fdExceptHandles)) { XnUInt32 nLastError = 0; XnInt32 nLastErrorSize = sizeof(nLastError); getsockopt(Socket->Socket, SOL_SOCKET, SO_ERROR, (char*)&nLastError, &nLastErrorSize); XN_LOG_ERROR_RETURN(XN_STATUS_OS_NETWORK_SOCKET_CONNECT_FAILED, XN_MASK_OS, "Connect failed with error: %u", nLastError); } // else, it means it's in the writable state, which means connect succeeded. XN_ASSERT(FD_ISSET(Socket->Socket, &fdWriteHandles)); } } // All is good... return (XN_STATUS_OK); }
XN_C_API XnStatus xnOSConnectSocket(XN_SOCKET_HANDLE Socket, XnUInt32 nMillisecsTimeout) { // Local function variables XnInt32 nRetVal = 0; sockaddr SocketAddress; fd_set fdWriteHandles; fd_set fdExceptHandles; struct timeval selectTimeOut; struct timeval* pTimeout = xnOSMillisecsToTimeVal(nMillisecsTimeout, &selectTimeOut); // Validate the input/output pointers (to make sure none of them is NULL) XN_VALIDATE_INPUT_PTR(Socket); // Make sure the actual socket handle isn't NULL XN_RET_IF_INVALID(Socket->Socket, XN_STATUS_OS_INVALID_SOCKET); // Connect to the socket and make sure it succeeded if (sizeof(SocketAddress) != sizeof(Socket->SocketAddress)) { return(XN_STATUS_OS_NETWORK_SOCKET_CONNECT_FAILED); } xnOSMemCopy(&SocketAddress, &Socket->SocketAddress, sizeof(SocketAddress)); // Make the socket non-blocking temporarily int nFlags = fcntl(Socket->Socket, F_GETFL, 0); int nNonBlockFlags = nFlags | O_NONBLOCK; if (-1 == fcntl(Socket->Socket, F_SETFL, nNonBlockFlags)) { XN_LOG_ERROR_RETURN(XN_STATUS_OS_NETWORK_SOCKET_CONNECT_FAILED, XN_MASK_OS, "fcntl() failed with error %d", errno); } //This is a non-blocking connect() call - it doesn't do anything until we call select() nRetVal = connect(Socket->Socket, &SocketAddress, sizeof(SocketAddress)); if (nRetVal == -1 && errno != EINPROGRESS) { xnLogError(XN_MASK_OS, "connect() failed with error %d", errno); return(XN_STATUS_OS_NETWORK_SOCKET_CONNECT_FAILED); } FD_ZERO(&fdWriteHandles); FD_SET(Socket->Socket, &fdWriteHandles); FD_ZERO(&fdExceptHandles); FD_SET(Socket->Socket, &fdExceptHandles); nRetVal = select(Socket->Socket + 1, NULL, &fdWriteHandles, &fdExceptHandles, pTimeout); //Make the socket blocking again before we check select()'s success fcntl(Socket->Socket, F_SETFL, nFlags); if (nRetVal == 0) { return (XN_STATUS_OS_NETWORK_TIMEOUT); } else if (nRetVal == -1) { XN_LOG_ERROR_RETURN(XN_STATUS_OS_NETWORK_SOCKET_ACCEPT_FAILED, XN_MASK_OS, "select() returned error: %d", errno); } else { // select returned due to socket state change. Check if an error occurred or everything is OK. if (FD_ISSET(Socket->Socket, &fdExceptHandles)) { XnUInt32 nLastError = 0; XnUInt32 nLastErrorSize = sizeof(nLastError); getsockopt(Socket->Socket, SOL_SOCKET, SO_ERROR, &nLastError, &nLastErrorSize); XN_LOG_ERROR_RETURN(XN_STATUS_OS_NETWORK_SOCKET_CONNECT_FAILED, XN_MASK_OS, "Connect failed with error: %u", nLastError); } // else, it means it's in the writable state, which means connect succeeded. XN_ASSERT(FD_ISSET(Socket->Socket, &fdWriteHandles)); } // All is good... return (XN_STATUS_OK); }