summaryrefslogtreecommitdiff
path: root/src/libs/network/socket
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/network/socket')
-rw-r--r--src/libs/network/socket/Makeinfo11
-rw-r--r--src/libs/network/socket/socket.c61
-rw-r--r--src/libs/network/socket/socket.h99
-rw-r--r--src/libs/network/socket/socket_bsd.c283
-rw-r--r--src/libs/network/socket/socket_bsd.h33
-rw-r--r--src/libs/network/socket/socket_win.c314
-rw-r--r--src/libs/network/socket/socket_win.h34
7 files changed, 835 insertions, 0 deletions
diff --git a/src/libs/network/socket/Makeinfo b/src/libs/network/socket/Makeinfo
new file mode 100644
index 0000000..19e1637
--- /dev/null
+++ b/src/libs/network/socket/Makeinfo
@@ -0,0 +1,11 @@
+uqm_CFILES="socket.c"
+uqm_HFILES="socket.h"
+
+if [ -n "$uqm_USE_WINSOCK" ]; then
+ uqm_CFILES="$uqm_CFILES socket_win.c"
+ uqm_HFILES="$uqm_HFILES socket_win.h"
+else
+ uqm_CFILES="$uqm_CFILES socket_bsd.c"
+ uqm_HFILES="$uqm_CFILES socket_bsd.h"
+fi
+
diff --git a/src/libs/network/socket/socket.c b/src/libs/network/socket/socket.c
new file mode 100644
index 0000000..be7d601
--- /dev/null
+++ b/src/libs/network/socket/socket.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2006 Serge van den Boom <svdb@stack.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "port.h"
+
+#define SOCKET_INTERNAL
+#include "socket.h"
+
+#ifdef USE_WINSOCK
+# include <winsock2.h>
+#else
+# include <sys/socket.h>
+# include <netinet/in.h>
+#endif
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
+const int protocolFamilyTranslation[] = {
+ /* .[PF_unspec] = */ PF_UNSPEC,
+ /* .[PF_inet] = */ PF_INET,
+ /* .[PF_inet6] = */ PF_INET6,
+};
+
+const int protocolTranslation[] = {
+ /* .[IPProto_tcp] = */ IPPROTO_TCP,
+ /* .[IPProto_udp] = */ IPPROTO_UDP,
+};
+
+const int socketTypeTranslation[] = {
+ /* .[Sock_stream] = */ SOCK_STREAM,
+ /* .[Sock_dgram] = */ SOCK_DGRAM,
+};
+
+
+Socket *
+Socket_open(ProtocolFamily domain, SocketType type, Protocol protocol) {
+ return Socket_openNative(protocolFamilyTranslation[domain],
+ socketTypeTranslation[type], protocolTranslation[protocol]);
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
diff --git a/src/libs/network/socket/socket.h b/src/libs/network/socket/socket.h
new file mode 100644
index 0000000..5c75467
--- /dev/null
+++ b/src/libs/network/socket/socket.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2006 Serge van den Boom <svdb@stack.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef LIBS_NETWORK_SOCKET_SOCKET_H_
+#define LIBS_NETWORK_SOCKET_SOCKET_H_
+
+typedef struct Socket Socket;
+#define Socket_noSocket ((Socket *) NULL)
+
+#include "port.h"
+
+#ifdef USE_WINSOCK
+# include "socket_win.h"
+#else
+# include "socket_bsd.h"
+#endif
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
+// Defining our own types for protocol families and protocols instead of
+// using the system defines, so that the layer using this API does not have
+// to have anything to do with the system layer.
+
+typedef enum {
+ PF_unspec,
+ PF_inet,
+ PF_inet6,
+} ProtocolFamily;
+typedef ProtocolFamily AddressFamily;
+
+typedef enum {
+ IPProto_tcp,
+ IPProto_udp,
+} Protocol;
+
+typedef enum {
+ Sock_stream,
+ Sock_dgram,
+} SocketType;
+
+#ifdef SOCKET_INTERNAL
+extern const int protocolFamilyTranslation[];
+#define addressFamilyTranslation protocolFamilyTranslation;
+extern const int protocolTranslation[];
+extern const int socketTypeTranslation[];
+#endif
+
+
+////////////////////////////////////////////////////////////////////////////
+
+
+Socket *Socket_open(ProtocolFamily domain, SocketType type,
+ Protocol protocol);
+#ifdef SOCKET_INTERNAL
+Socket *Socket_openNative(int domain, int type, int protocol);
+#endif
+int Socket_close(Socket *sock);
+
+int Socket_connect(Socket *sock, const struct sockaddr *addr,
+ socklen_t addrLen);
+int Socket_bind(Socket *sock, const struct sockaddr *addr,
+ socklen_t addrLen);
+int Socket_listen(Socket *sock, int backlog);
+Socket *Socket_accept(Socket *sock, struct sockaddr *addr, socklen_t *addrLen);
+ssize_t Socket_send(Socket *sock, const void *buf, size_t len, int flags);
+ssize_t Socket_sendto(Socket *sock, const void *buf, size_t len, int flags,
+ const struct sockaddr *addr, socklen_t addrLen);
+ssize_t Socket_recv(Socket *sock, void *buf, size_t len, int flags);
+ssize_t Socket_recvfrom(Socket *sock, void *buf, size_t len, int flags,
+ struct sockaddr *from, socklen_t *fromLen);
+
+int Socket_setNonBlocking(Socket *sock);
+int Socket_setReuseAddr(Socket *sock);
+int Socket_setNodelay(Socket *sock);
+int Socket_setTOS(Socket *sock, int tos);
+int Socket_setInteractive(Socket *sock);
+int Socket_setInlineOOB(Socket *sock);
+int Socket_setKeepAlive(Socket *sock);
+int Socket_getError(Socket *sock, int *err);
+
+#endif /* LIBS_NETWORK_SOCKET_SOCKET_H_ */
+
diff --git a/src/libs/network/socket/socket_bsd.c b/src/libs/network/socket/socket_bsd.c
new file mode 100644
index 0000000..2bf25b8
--- /dev/null
+++ b/src/libs/network/socket/socket_bsd.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright 2006 Serge van den Boom <svdb@stack.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// Socket functions for BSD sockets.
+
+#define SOCKET_INTERNAL
+#include "socket.h"
+
+#include "libs/log.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
+# include <netinet/in_systm.h>
+# include <netinet/in.h>
+#endif
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+
+static Socket *
+Socket_alloc(void) {
+ return malloc(sizeof (Socket));
+}
+
+static void
+Socket_free(Socket *sock) {
+ free(sock);
+}
+
+Socket *
+Socket_openNative(int domain, int type, int protocol) {
+ Socket *result;
+ int fd;
+
+ fd = socket(domain, type, protocol);
+ if (fd == -1) {
+ // errno is set
+ return Socket_noSocket;
+ }
+
+ result = Socket_alloc();
+ result->fd = fd;
+ return result;
+}
+
+int
+Socket_close(Socket *sock) {
+ int closeResult;
+
+ do {
+ closeResult = close(sock->fd);
+ if (closeResult == 0) {
+ Socket_free(sock);
+ return 0;
+ }
+ } while (errno == EINTR);
+
+ return -1;
+}
+
+int
+Socket_connect(Socket *sock, const struct sockaddr *addr,
+ socklen_t addrLen) {
+ int connectResult;
+
+ do {
+ connectResult = connect(sock->fd, addr, addrLen);
+ } while (connectResult == -1 && errno == EINTR);
+
+ return connectResult;
+}
+
+int
+Socket_bind(Socket *sock, const struct sockaddr *addr, socklen_t addrLen) {
+ return bind(sock->fd, addr, addrLen);
+}
+
+int
+Socket_listen(Socket *sock, int backlog) {
+ return listen(sock->fd, backlog);
+}
+
+Socket *
+Socket_accept(Socket *sock, struct sockaddr *addr, socklen_t *addrLen) {
+ int acceptResult;
+ socklen_t tempAddrLen;
+
+ do {
+ tempAddrLen = *addrLen;
+ acceptResult = accept(sock->fd, addr, &tempAddrLen);
+ if (acceptResult != -1) {
+ Socket *result = Socket_alloc();
+ result->fd = acceptResult;
+ *addrLen = tempAddrLen;
+ return result;
+ }
+
+ } while (errno == EINTR);
+
+ // errno is set
+ return Socket_noSocket;
+}
+
+ssize_t
+Socket_send(Socket *sock, const void *buf, size_t len, int flags) {
+ return send(sock->fd, buf, len, flags);
+}
+
+ssize_t
+Socket_sendto(Socket *sock, const void *buf, size_t len, int flags,
+ const struct sockaddr *addr, socklen_t addrLen) {
+ return sendto(sock->fd, buf, len, flags, addr, addrLen);
+}
+
+ssize_t
+Socket_recv(Socket *sock, void *buf, size_t len, int flags) {
+ return recv(sock->fd, buf, len, flags);
+}
+
+ssize_t
+Socket_recvfrom(Socket *sock, void *buf, size_t len, int flags,
+ struct sockaddr *from, socklen_t *fromLen) {
+ return recvfrom(sock->fd, buf, len, flags, from, fromLen);
+}
+
+int
+Socket_setNonBlocking(Socket *sock) {
+ int flags;
+
+ flags = fcntl(sock->fd, F_GETFL);
+ if (flags == -1) {
+ int savedErrno = errno;
+ log_add(log_Error, "Getting file descriptor flags of socket failed: "
+ "%s.", strerror(errno));
+ errno = savedErrno;
+ return -1;
+ }
+
+ if (fcntl(sock->fd, F_SETFL, flags | O_NONBLOCK) == -1) {
+ int savedErrno = errno;
+ log_add(log_Error, "Setting non-blocking mode on socket failed: "
+ "%s.", strerror(errno));
+ errno = savedErrno;
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+Socket_setReuseAddr(Socket *sock) {
+ int flag = 1;
+
+ if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof flag)
+ == -1) {
+ int savedErrno = errno;
+ log_add(log_Error, "Setting socket reuse failed: %s.",
+ strerror(errno));
+ errno = savedErrno;
+ return -1;
+ }
+ return 0;
+}
+
+// Send data as soon as it is available. Do not collect data to send at
+// once.
+int
+Socket_setNodelay(Socket *sock) {
+ int flag = 1;
+
+ if (setsockopt(sock->fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof flag)
+ == -1) {
+#ifdef DEBUG
+ int savedErrno = errno;
+ log_add(log_Warning, "Disabling Nagle algorithm failed: %s.",
+ strerror(errno));
+ errno = savedErrno;
+#endif
+ return -1;
+ }
+ return 0;
+}
+
+// 'tos' should be IPTOS_LOWDELAY, IPTOS_THROUGHPUT, IPTOS_THROUGHPUT,
+// IPTOS_RELIABILITY, or IPTOS_MINCOST.
+int
+Socket_setTOS(Socket *sock, int tos) {
+ if (setsockopt(sock->fd, IPPROTO_IP, IP_TOS, &tos, sizeof tos) == -1) {
+#ifdef DEBUG
+ int savedErrno = errno;
+ log_add(log_Warning, "Setting socket type-of-service failed: %s.",
+ strerror(errno));
+ errno = savedErrno;
+#endif
+ return -1;
+ }
+ return 0;
+}
+
+// This function setups the socket for optimal configuration for an
+// interactive connection.
+int
+Socket_setInteractive(Socket *sock) {
+ if (Socket_setNodelay(sock) == -1) {
+ // errno is set
+ return -1;
+ }
+
+ if (Socket_setTOS(sock, IPTOS_LOWDELAY) == -1) {
+ // errno is set
+ return -1;
+ }
+ return 0;
+}
+
+int
+Socket_setInlineOOB(Socket *sock) {
+ int flag = 1;
+
+ if (setsockopt(sock->fd, SOL_SOCKET, SO_OOBINLINE, &flag, sizeof flag)
+ == -1) {
+ int savedErrno = errno;
+ log_add(log_Error, "Setting inline OOB on socket failed: %s",
+ strerror(errno));
+ errno = savedErrno;
+ return -1;
+ }
+ return 0;
+}
+
+int
+Socket_setKeepAlive(Socket *sock) {
+ int flag = 1;
+
+ if (setsockopt(sock->fd, IPPROTO_TCP, SO_KEEPALIVE, &flag, sizeof flag)
+ == -1) {
+ int savedErrno = errno;
+ log_add(log_Error, "Setting keep-alive on socket failed: %s",
+ strerror(errno));
+ errno = savedErrno;
+ return -1;
+ }
+ return 0;
+}
+
+int
+Socket_getError(Socket *sock, int *err) {
+ socklen_t errLen = sizeof(*err);
+
+ if (getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, err, &errLen) == -1) {
+ // errno is set
+ return -1;
+ }
+
+ assert(errLen == sizeof(*err));
+ // err is set
+ return 0;
+}
+
+
diff --git a/src/libs/network/socket/socket_bsd.h b/src/libs/network/socket/socket_bsd.h
new file mode 100644
index 0000000..8019c01
--- /dev/null
+++ b/src/libs/network/socket/socket_bsd.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2006 Serge van den Boom <svdb@stack.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef LIBS_NETWORK_SOCKET_SOCKET_BSD_H_
+#define LIBS_NETWORK_SOCKET_SOCKET_BSD_H_
+
+#include "types.h"
+#include <sys/socket.h>
+
+#ifdef SOCKET_INTERNAL
+struct Socket {
+ int fd;
+};
+#endif /* SOCKET_INTERNAL */
+
+
+#endif /* LIBS_NETWORK_SOCKET_SOCKET_BSD_H_ */
+
diff --git a/src/libs/network/socket/socket_win.c b/src/libs/network/socket/socket_win.c
new file mode 100644
index 0000000..e1ed002
--- /dev/null
+++ b/src/libs/network/socket/socket_win.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2006 Serge van den Boom <svdb@stack.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// Socket functions for Winsock sockets.
+
+#define PORT_WANT_ERRNO
+#include "port.h"
+#include "../netport.h"
+
+#define SOCKET_INTERNAL
+#include "socket.h"
+
+#include "libs/log.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <winsock2.h>
+
+
+Socket *
+Socket_alloc(void) {
+ return malloc(sizeof (Socket));
+}
+
+void
+Socket_free(Socket *sock) {
+ free(sock);
+}
+
+Socket *
+Socket_openNative(int domain, int type, int protocol) {
+ Socket *result;
+ SOCKET sock;
+
+ sock = socket(domain, type, protocol);
+ if (sock == INVALID_SOCKET) {
+ errno = getWinsockErrno();
+ return Socket_noSocket;
+ }
+
+ result = Socket_alloc();
+ result->sock = sock;
+ return result;
+}
+
+int
+Socket_close(Socket *sock) {
+ int closeResult;
+
+ do {
+ closeResult = closesocket(sock->sock);
+ if (closeResult != SOCKET_ERROR) {
+ Socket_free(sock);
+ return 0;
+ }
+
+ errno = getWinsockErrno();
+ } while (errno == EINTR);
+
+ return -1;
+}
+
+int
+Socket_connect(Socket *sock, const struct sockaddr *addr,
+ socklen_t addrLen) {
+ int connectResult;
+
+ do {
+ connectResult = connect(sock->sock, addr, addrLen);
+ if (connectResult == 0)
+ return 0;
+
+ errno = getWinsockErrno();
+ } while (errno == EINTR);
+
+ if (errno == EWOULDBLOCK) {
+ // Windows returns (WSA)EWOULDBLOCK when a connection is being
+ // initiated on a non-blocking socket, while other platforms
+ // use EINPROGRESS in such cases.
+ errno = EINPROGRESS;
+ }
+
+ return -1;
+}
+
+int
+Socket_bind(Socket *sock, const struct sockaddr *addr, socklen_t addrLen) {
+ int bindResult;
+
+ bindResult = bind(sock->sock, addr, addrLen);
+ if (bindResult == SOCKET_ERROR) {
+ errno = getWinsockErrno();
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+Socket_listen(Socket *sock, int backlog) {
+ int listenResult;
+
+ listenResult = listen(sock->sock, backlog);
+ if (listenResult == SOCKET_ERROR) {
+ errno = getWinsockErrno();
+ return -1;
+ }
+
+ return 0;
+}
+
+Socket *
+Socket_accept(Socket *sock, struct sockaddr *addr, socklen_t *addrLen) {
+ SOCKET acceptResult;
+ socklen_t tempAddrLen;
+
+ do {
+ tempAddrLen = *addrLen;
+ acceptResult = accept(sock->sock, addr, &tempAddrLen);
+ if (acceptResult != INVALID_SOCKET) {
+ Socket *result = Socket_alloc();
+ result->sock = acceptResult;
+ *addrLen = tempAddrLen;
+ return result;
+ }
+
+ errno = getWinsockErrno();
+ } while (errno == EINTR);
+
+ // errno is set
+ return Socket_noSocket;
+}
+
+ssize_t
+Socket_send(Socket *sock, const void *buf, size_t len, int flags) {
+ int sendResult;
+
+ sendResult = send(sock->sock, buf, len, flags);
+ if (sendResult == SOCKET_ERROR) {
+ errno = getWinsockErrno();
+ return -1;
+ }
+
+ return sendResult;
+}
+
+ssize_t
+Socket_sendto(Socket *sock, const void *buf, size_t len, int flags,
+ const struct sockaddr *addr, socklen_t addrLen) {
+ int sendResult;
+
+ sendResult = sendto(sock->sock, buf, len, flags, addr, addrLen);
+ if (sendResult == SOCKET_ERROR) {
+ errno = getWinsockErrno();
+ return -1;
+ }
+
+ return sendResult;
+}
+
+ssize_t
+Socket_recv(Socket *sock, void *buf, size_t len, int flags) {
+ int recvResult;
+
+ recvResult = recv(sock->sock, buf, len, flags);
+ if (recvResult == SOCKET_ERROR) {
+ errno = getWinsockErrno();
+ return -1;
+ }
+
+ return recvResult;
+}
+
+ssize_t
+Socket_recvfrom(Socket *sock, void *buf, size_t len, int flags,
+ struct sockaddr *from, socklen_t *fromLen) {
+ int recvResult;
+
+ recvResult = recvfrom(sock->sock, buf, len, flags, from, fromLen);
+ if (recvResult == SOCKET_ERROR) {
+ errno = getWinsockErrno();
+ return -1;
+ }
+
+ return recvResult;
+}
+
+int
+Socket_setNonBlocking(Socket *sock) {
+ unsigned long flag = 1;
+
+ if (ioctlsocket(sock->sock, FIONBIO, &flag) == SOCKET_ERROR) {
+ int savedErrno = getWinsockErrno();
+ log_add(log_Error, "Setting non-block mode on socket failed: %s.",
+ strerror(errno));
+ errno = savedErrno;
+ return -1;
+ }
+ return 0;
+}
+
+int
+Socket_setReuseAddr(Socket *sock) {
+ BOOL flag = 1;
+
+ if (setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR,
+ (const char *) &flag, sizeof flag) == SOCKET_ERROR) {
+ int savedErrno = getWinsockErrno();
+ log_add(log_Error, "Setting socket reuse failed: %s.",
+ strerror(errno));
+ errno = savedErrno;
+ return -1;
+ }
+ return 0;
+}
+
+// Send data as soon as it is available. Do not collect data to send at
+// once.
+int
+Socket_setNodelay(Socket *sock) {
+ BOOL flag = 1;
+
+ if (setsockopt(sock->sock, IPPROTO_TCP, TCP_NODELAY,
+ (const char *) &flag, sizeof flag) == SOCKET_ERROR) {
+#ifdef DEBUG
+ int savedErrno = getWinsockErrno();
+ log_add(log_Warning, "Disabling Nagle algorithm failed: %s.",
+ strerror(errno));
+ errno = savedErrno;
+#endif
+ return -1;
+ }
+ return 0;
+}
+
+// This function setups the socket for optimal configuration for an
+// interactive connection.
+int
+Socket_setInteractive(Socket *sock) {
+ if (Socket_setNodelay(sock) == -1) {
+ // errno is set
+ return -1;
+ }
+
+#if 0
+ if (Socket_setTOS(sock, IPTOS_LOWDELAY) == -1) {
+ // errno is set
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+int
+Socket_setInlineOOB(Socket *sock) {
+ BOOL flag = 1;
+
+ if (setsockopt(sock->sock, SOL_SOCKET, SO_OOBINLINE, (const char *) &flag,
+ sizeof flag) == SOCKET_ERROR) {
+ int savedErrno = getWinsockErrno();
+ log_add(log_Error, "Setting inline OOB on socket failed: %s",
+ strerror(errno));
+ errno = savedErrno;
+ return -1;
+ }
+ return 0;
+}
+
+int
+Socket_setKeepAlive(Socket *sock) {
+ BOOL flag = 1;
+
+ if (setsockopt(sock->sock, IPPROTO_TCP, SO_KEEPALIVE,
+ (const char *) &flag, sizeof flag) == SOCKET_ERROR) {
+ int savedErrno = getWinsockErrno();
+ log_add(log_Error, "Setting keep-alive on socket failed: %s",
+ strerror(errno));
+ errno = savedErrno;
+ return -1;
+ }
+ return 0;
+}
+
+int
+Socket_getError(Socket *sock, int *err) {
+ int errLen = sizeof(*err);
+
+ if (getsockopt(sock->sock, SOL_SOCKET, SO_ERROR, (char *) err, &errLen)
+ == SOCKET_ERROR) {
+ errno = getWinsockErrno();
+ return -1;
+ }
+
+ assert(errLen == sizeof(*err));
+ // err is set
+ return 0;
+}
+
+
diff --git a/src/libs/network/socket/socket_win.h b/src/libs/network/socket/socket_win.h
new file mode 100644
index 0000000..ed1674c
--- /dev/null
+++ b/src/libs/network/socket/socket_win.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2006 Serge van den Boom <svdb@stack.nl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef LIBS_NETWORK_SOCKET_SOCKET_WIN_H_
+#define LIBS_NETWORK_SOCKET_SOCKET_WIN_H_
+
+#ifdef SOCKET_INTERNAL
+#include <winsock2.h>
+struct Socket {
+ SOCKET sock;
+};
+#endif /* SOCKET_INTERNAL */
+
+typedef int socklen_t;
+struct sockaddr;
+
+#endif /* LIBS_NETWORK_SOCKET_SOCKET_WIN_H_ */
+
+