socket-0.8.1.0: platform/win32/cbits/hs_socket.c
#include <hs_socket.h>
int hs_socket_init() {
static int has_already_been_initialised = 0;
if (!has_already_been_initialised) {
WSADATA wsaData;
int ini = WSAStartup(MAKEWORD(2,2), &wsaData);
if (ini != NO_ERROR) {
WSACleanup();
return -1;
} else {
has_already_been_initialised = 1;
}
}
return 0;
};
int hs_socket(int domain, int type, int protocol, int *err) {
if (!hs_socket_init()) {
u_long iMode = 1;
int fd = socket(domain, type, protocol);
if (fd >= 0) {
if (!ioctlsocket(fd, FIONBIO, &iMode)) {
return fd;
} else {
closesocket(fd);
}
}
}
*err = WSAGetLastError();
return -1;
};
int hs_bind(int sockfd, const struct sockaddr *name, int namelen, int *err) {
int i = bind(sockfd, name, namelen);
if (i) {
*err = WSAGetLastError();
}
return i;
};
int hs_connect(int sockfd, const struct sockaddr *name, int namelen, int *err) {
int i = connect(sockfd, name, namelen);
if (i) {
*err = WSAGetLastError();
}
return i;
};
/**
* Determine a sockets connection status.
*
* Return values:
* 0: connection established
* 1: connection pending
* 2: connection failed
* 3: select or getsockopt failed
*
* The operation will block for the least possible time interval (1 micro second)
* and is not used as it is supposed to be used as we don't want to block.
* Haskell's RTS is used to wait and poll this operation from time to time.
*/
int hs_connect_status (int sockfd, int *err) {
int errlen = sizeof(int);
struct timeval timeout = {0,1};
fd_set writefds;
fd_set exceptfds;
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
FD_SET(sockfd, &writefds);
FD_SET(sockfd, &exceptfds);
switch (select(sockfd, NULL, &writefds, &exceptfds, &timeout)) {
case 0:
return 1; // Connection pending.
case 1:
if (FD_ISSET(sockfd, &writefds)) {
return 0; // Connection established.
}
if (FD_ISSET(sockfd, &exceptfds) && !getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (char*) err, &errlen)) {
return 2; // Connection failed.
}
default:
*err = WSAGetLastError();
return -1; // select or getsockopt failed.
}
}
int hs_listen (int sockfd, int backlog, int *err) {
int i = listen(sockfd, backlog);
if (i) {
*err = WSAGetLastError();
}
return i;
};
int hs_accept(int fd, struct sockaddr *addr, int *addrlen, int *err) {
u_long iMode = 1;
int ft = accept(fd, addr, addrlen);
if (ft >= 0) {
if (!ioctlsocket(ft, FIONBIO, &iMode)) {
return ft;
} else {
closesocket(ft);
}
}
*err = WSAGetLastError();
return ft;
}
int hs_close(int sockfd, int *err) {
int i = closesocket(sockfd);
if (i) {
*err = WSAGetLastError();
}
return i;
};
int hs_send (int sockfd, const void *buf, size_t len, int flags, int *err) {
int i = send(sockfd, buf, len, flags);
if (i < 0) {
*err = WSAGetLastError();
}
return i;
};
int hs_recv (int sockfd, void *buf, size_t len, int flags, int *err) {
int i = recv(sockfd, buf, len, flags);
if (i < 0) {
*err = WSAGetLastError();
}
return i;
};
int hs_sendto (int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, int addrlen, int *err) {
int i = sendto(sockfd, buf, len, flags, dest_addr, addrlen);
if (i < 0) {
*err = WSAGetLastError();
}
return i;
};
int hs_recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, int *addrlen, int *err) {
int i = recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
if (i < 0) {
*err = WSAGetLastError();
}
return i;
};
int hs_getsockopt(int sockfd, int level, int option_name, void *option_value, int *option_len, int *err) {
int i = getsockopt(sockfd, level, option_name, option_value, option_len);
if (i) {
*err = WSAGetLastError();
}
return i;
};
int hs_setsockopt(int sockfd, int level, int option_name, const void *option_value, int option_len, int *err) {
int i = setsockopt(sockfd, level, option_name, option_value, option_len);
if (i) {
*err = WSAGetLastError();
}
return i;
};
int hs_getaddrinfo(const char *node, const char *service,
const struct addrinfo *hints,
struct addrinfo **res) {
if (hs_socket_init() != 0) {
return -1;
}
return getaddrinfo(node, service, hints, res);
};
int hs_getnameinfo(const struct sockaddr *sa, int salen,
char *host, int hostlen,
char *serv, int servlen, int flags) {
if (hs_socket_init() != 0) {
return -1;
}
return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
};
void hs_freeaddrinfo(struct addrinfo *res) {
freeaddrinfo(res);
return;
};
int hs_getsockname(int fd, struct sockaddr *addr, socklen_t *addrlen, int *err) {
int i = getsockname(fd, addr, addrlen);
if (i < 0) {
*err = WSAGetLastError();
}
return i;
}