static DWORD VmDnsSockPosixAcceptConnection( PVM_SOCKET pListener, PVM_SOCKET* ppSocket ) { DWORD dwError = 0; PVM_SOCKET pSocket = NULL; int fd = -1; dwError = VmDnsAllocateMemory(sizeof(*pSocket), (PVOID*)&pSocket); BAIL_ON_POSIX_SOCK_ERROR(dwError); pSocket->refCount = 1; dwError = VmDnsAllocateMutex(&pSocket->pMutex); BAIL_ON_POSIX_SOCK_ERROR(dwError); pSocket->protocol = pListener->protocol; pSocket->type = VM_SOCK_TYPE_SERVER; fd = accept(pListener->fd, &pSocket->addr, &pSocket->addrLen); if (fd < 0) { dwError = LwErrnoToWin32Error(errno); BAIL_ON_POSIX_SOCK_ERROR(dwError); } pSocket->fd = fd; pSocket->pAddr = &pSocket->addr; *ppSocket = pSocket; cleanup: return dwError; error: *ppSocket = NULL; if (pSocket) { VmDnsSockPosixFreeSocket(pSocket); } if (fd >= 0) { close(fd); } goto cleanup; }
VOID VmDnsSockPosixReleaseSocket( PVM_SOCKET pSocket ) { if (pSocket) { if (InterlockedDecrement(&pSocket->refCount) == 0) { VmDnsSockPosixFreeSocket(pSocket); } } }
DWORD VmDnsSockPosixOpenClient( PCSTR pszHost, USHORT usPort, VM_SOCK_CREATE_FLAGS dwFlags, DWORD dwTimeoutMS, PVM_SOCKET* ppSocket ) { DWORD dwError = 0; struct addrinfo hints = {0}; struct addrinfo* pAddrInfo = NULL; struct addrinfo* pInfo = NULL; int fd = -1; PVM_SOCKET pSocket = NULL; CHAR szPort[32]; struct timeval sTimeout = {0}; if (!pszHost || !usPort || !ppSocket) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_POSIX_SOCK_ERROR(dwError); } sprintf(szPort, "%d", usPort); if (dwFlags & VM_SOCK_CREATE_FLAGS_IPV6) { hints.ai_family = AF_INET6; } else if (dwFlags & VM_SOCK_CREATE_FLAGS_IPV4) { hints.ai_family = AF_INET; } else { hints.ai_family = AF_UNSPEC; } if (dwFlags & VM_SOCK_CREATE_FLAGS_UDP) { hints.ai_socktype = SOCK_DGRAM; } else { hints.ai_socktype = SOCK_STREAM; } hints.ai_flags = AI_CANONNAME | AI_NUMERICSERV; /* This will use DNS */ if (getaddrinfo(pszHost, szPort, &hints, &pAddrInfo) != 0) { dwError = LwErrnoToWin32Error(errno); BAIL_ON_POSIX_SOCK_ERROR(dwError); } for (pInfo = pAddrInfo; (fd < 0) && (pInfo != NULL); pInfo = pInfo->ai_next) { fd = socket(pInfo->ai_family, pInfo->ai_socktype, pInfo->ai_protocol); if (fd < 0) { continue; } if (dwTimeoutMS) { sTimeout.tv_sec = dwTimeoutMS / 1000; sTimeout.tv_usec = (dwTimeoutMS % 1000) * 1000; if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (const char *)&sTimeout, sizeof(sTimeout)) == -1) { close(fd); fd = -1; continue; } } if (connect(fd, pInfo->ai_addr, pInfo->ai_addrlen) < 0) { close(fd); fd = -1; continue; } break; } if (fd < 0) { dwError = ERROR_CONNECTION_UNAVAIL; BAIL_ON_POSIX_SOCK_ERROR(dwError); } if (dwFlags & VM_SOCK_CREATE_FLAGS_NON_BLOCK) { dwError = VmDnsSockPosixSetDescriptorNonBlocking(fd); BAIL_ON_POSIX_SOCK_ERROR(dwError); } dwError = VmDnsAllocateMemory(sizeof(*pSocket), (PVOID*)&pSocket); BAIL_ON_POSIX_SOCK_ERROR(dwError); pSocket->refCount = 1; pSocket->type = VM_SOCK_TYPE_CLIENT; if (dwFlags & VM_SOCK_CREATE_FLAGS_UDP) { pSocket->protocol = VM_SOCK_PROTOCOL_UDP; } else { pSocket->protocol = VM_SOCK_PROTOCOL_TCP; } dwError = VmDnsAllocateMutex(&pSocket->pMutex); BAIL_ON_POSIX_SOCK_ERROR(dwError); memcpy(&pSocket->addr, pInfo->ai_addr, pInfo->ai_addrlen); pSocket->addrLen = pInfo->ai_addrlen; pSocket->fd = fd; *ppSocket = pSocket; cleanup: if (pAddrInfo) { freeaddrinfo(pAddrInfo); } return dwError; error: if (ppSocket) { *ppSocket = NULL; } if (pSocket) { VmDnsSockPosixFreeSocket(pSocket); } if (fd >= 0) { close(fd); } goto cleanup; }
DWORD VmDnsSockPosixOpenServer( USHORT usPort, int iListenQueueSize, VM_SOCK_CREATE_FLAGS dwFlags, PVM_SOCKET* ppSocket ) { DWORD dwError = 0; union { #ifdef AF_INET6 struct sockaddr_in6 servaddr_ipv6; #endif struct sockaddr_in servaddr_ipv4; } servaddr; struct { int domain; int type; int protocol; } socketParams; struct sockaddr* pSockAddr = NULL; socklen_t addrLen = 0; int fd = -1; PVM_SOCKET pSocket = NULL; if (dwFlags & VM_SOCK_CREATE_FLAGS_IPV6) { #ifdef AF_INET6 socketParams.domain = AF_INET6; #else dwError = ERROR_NOT_SUPPORTED; BAIL_ON_POSIX_SOCK_ERROR(dwError); #endif } else { socketParams.domain = AF_INET; } if (dwFlags & VM_SOCK_CREATE_FLAGS_UDP) { socketParams.type = SOCK_DGRAM; } else { socketParams.type = SOCK_STREAM; } socketParams.protocol = 0; fd = socket(socketParams.domain, socketParams.type, socketParams.protocol); if (fd < 0) { dwError = LwErrnoToWin32Error(errno); BAIL_ON_POSIX_SOCK_ERROR(dwError); } if (dwFlags & VM_SOCK_CREATE_FLAGS_REUSE_ADDR) { dwError = VmDnsSockPosixSetReuseAddress(fd); BAIL_ON_POSIX_SOCK_ERROR(dwError); } memset(&servaddr, 0, sizeof(servaddr)); if (dwFlags & VM_SOCK_CREATE_FLAGS_IPV6) { #ifdef AF_INET6 servaddr.servaddr_ipv6.sin6_family = AF_INET6; servaddr.servaddr_ipv6.sin6_addr = in6addr_any; servaddr.servaddr_ipv6.sin6_port = htons(usPort); pSockAddr = (struct sockaddr*) &servaddr.servaddr_ipv6; addrLen = sizeof(servaddr.servaddr_ipv6); #if defined(SOL_IPV6) && defined(IPV6_V6ONLY) int one = 1; setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, (void *) &one, sizeof(one)); #endif #else dwError = ERROR_NOT_SUPPORTED; BAIL_ON_POSIX_SOCK_ERROR(dwError); #endif } else { servaddr.servaddr_ipv4.sin_family = AF_INET; servaddr.servaddr_ipv4.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.servaddr_ipv4.sin_port = htons(usPort); pSockAddr = (struct sockaddr*) &servaddr.servaddr_ipv4; addrLen = sizeof(servaddr.servaddr_ipv4); } if (bind(fd, pSockAddr, addrLen) < 0) { dwError = LwErrnoToWin32Error(errno); BAIL_ON_POSIX_SOCK_ERROR(dwError); } if (dwFlags & VM_SOCK_CREATE_FLAGS_NON_BLOCK) { dwError = VmDnsSockPosixSetDescriptorNonBlocking(fd); BAIL_ON_POSIX_SOCK_ERROR(dwError); } if (!(dwFlags & VM_SOCK_CREATE_FLAGS_UDP)) { if (iListenQueueSize <= 0) { iListenQueueSize = VM_SOCK_POSIX_DEFAULT_LISTEN_QUEUE_SIZE; } if (listen(fd, iListenQueueSize) < 0) { dwError = LwErrnoToWin32Error(errno); BAIL_ON_POSIX_SOCK_ERROR(dwError); } } dwError = VmDnsAllocateMemory(sizeof(*pSocket), (PVOID*)&pSocket); BAIL_ON_POSIX_SOCK_ERROR(dwError); pSocket->refCount = 1; dwError = VmDnsAllocateMutex(&pSocket->pMutex); BAIL_ON_POSIX_SOCK_ERROR(dwError); pSocket->type = VM_SOCK_TYPE_LISTENER; if (dwFlags & VM_SOCK_CREATE_FLAGS_UDP) { pSocket->protocol = VM_SOCK_PROTOCOL_UDP; } else { pSocket->protocol = VM_SOCK_PROTOCOL_TCP; } pSocket->fd = fd; *ppSocket = pSocket; cleanup: return dwError; error: if (ppSocket) { *ppSocket = NULL; } if (pSocket) { VmDnsSockPosixFreeSocket(pSocket); } if (fd >= 0) { close(fd); } goto cleanup; }
DWORD VmDnsSockPosixCreateTimerSocket( DWORD dwInitialMS, DWORD dwIntervalMS, PVM_SOCKET* ppSocket ) { DWORD dwError = 0; int timerFd = -1; PVM_SOCKET pSocket = NULL; struct itimerspec ts = {0}; int nSec = 0; int nNanoSec = 0; if (!ppSocket) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_POSIX_SOCK_ERROR(dwError); } timerFd = timerfd_create(CLOCK_MONOTONIC, 0); if (timerFd == -1) { dwError = LwErrnoToWin32Error(errno); BAIL_ON_POSIX_SOCK_ERROR(dwError); } nSec = dwInitialMS / 1000; nNanoSec = (dwInitialMS % 1000) * 1000000; ts.it_value.tv_sec = nSec; ts.it_value.tv_nsec = nNanoSec; nSec = dwIntervalMS / 1000; nNanoSec = (dwIntervalMS % 1000) * 1000000; ts.it_interval.tv_sec = nSec; ts.it_interval.tv_nsec = nNanoSec; if (timerfd_settime(timerFd, 0, &ts, NULL) < 0) { dwError = LwErrnoToWin32Error(errno); BAIL_ON_POSIX_SOCK_ERROR(dwError); } dwError = VmDnsAllocateMemory( sizeof(VM_SOCKET), (PVOID*)&pSocket); BAIL_ON_POSIX_SOCK_ERROR(dwError); dwError = VmDnsAllocateMutex(&pSocket->pMutex); BAIL_ON_POSIX_SOCK_ERROR(dwError); pSocket->refCount = 1; pSocket->protocol = VM_SOCK_PROTOCOL_UNKNOWN; pSocket->type = VM_SOCK_TYPE_TIMER; pSocket->fd = timerFd; *ppSocket = pSocket; cleanup: return dwError; error: if (timerFd > 0) { close(timerFd); } if (pSocket) { VmDnsSockPosixFreeSocket(pSocket); pSocket = NULL; } goto cleanup; }
static DWORD VmDnsSockPosixCreateSignalSockets( PVM_SOCKET* ppReaderSocket, PVM_SOCKET* ppWriterSocket ) { DWORD dwError = 0; PVM_SOCKET pReaderSocket = NULL; PVM_SOCKET pWriterSocket = NULL; PVM_SOCKET* sockets[] = { &pReaderSocket, &pWriterSocket }; int fdPair[] = { -1, -1 }; DWORD iSock = 0; if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fdPair) < 0) { dwError = LwErrnoToWin32Error(errno); BAIL_ON_POSIX_SOCK_ERROR(dwError); } for (; iSock < sizeof(sockets)/sizeof(sockets[0]); iSock++) { PVM_SOCKET pSocket = NULL; dwError = VmDnsAllocateMemory(sizeof(VM_SOCKET), (PVOID*)sockets[iSock]); BAIL_ON_POSIX_SOCK_ERROR(dwError); pSocket = *sockets[iSock]; pSocket->refCount = 1; dwError = VmDnsAllocateMutex(&pSocket->pMutex); BAIL_ON_POSIX_SOCK_ERROR(dwError); pSocket->protocol = VM_SOCK_PROTOCOL_TCP; pSocket->type = VM_SOCK_TYPE_SIGNAL; pSocket->fd = fdPair[iSock]; fdPair[iSock] = -1; } *ppReaderSocket = pReaderSocket; *ppWriterSocket = pWriterSocket; cleanup: return dwError; error: *ppReaderSocket = NULL; *ppWriterSocket = NULL; if (pReaderSocket) { VmDnsSockPosixFreeSocket(pReaderSocket); } if (pWriterSocket) { VmDnsSockPosixFreeSocket(pWriterSocket); } for (iSock = 0; iSock < sizeof(fdPair)/sizeof(fdPair[0]); iSock++) { if (fdPair[iSock] >= 0) { close(fdPair[iSock]); } } goto cleanup; }