frontlib/nonblocksockets.c
changeset 7158 a0573014ff4f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/frontlib/nonblocksockets.c	Thu May 31 18:32:01 2012 +0200
@@ -0,0 +1,76 @@
+#include "nonblocksockets.h"
+#include "logging.h"
+#include <stdlib.h>
+
+static uint32_t get_peer_ip(TCPsocket sock) {
+	IPaddress *addr = SDLNet_TCP_GetPeerAddress(sock);
+	return SDLNet_Read32(&addr->host);
+}
+
+static bool connection_is_local(TCPsocket sock) {
+	return get_peer_ip(sock) == (uint32_t)((127UL<<24)+1); // 127.0.0.1
+}
+
+void flib_nbsocket_close(NonBlockSocket *nbsockptr) {
+	NonBlockSocket nbsock = *nbsockptr;
+	if(nbsock!=NULL) {
+		SDLNet_DelSocket(nbsock->sockset, (SDLNet_GenericSocket)nbsock->sock);
+		SDLNet_TCP_Close(nbsock->sock);
+		SDLNet_FreeSocketSet(nbsock->sockset);
+	}
+	free(nbsock);
+	*nbsockptr = NULL;
+}
+
+NonBlockSocket flib_nbsocket_accept(TCPsocket listensocket, bool localOnly) {
+	NonBlockSocket result = NULL;
+	if(!listensocket) {
+		flib_log_e("Attempt to accept a connection on a NULL socket.");
+		return NULL;
+	}
+	while(result==NULL) {
+		TCPsocket sock = SDLNet_TCP_Accept(listensocket);
+		if(!sock) {
+			// No incoming connections
+			return NULL;
+		}
+		if(localOnly && !connection_is_local(sock)) {
+			flib_log_i("Rejected nonlocal connection attempt from %s", flib_format_ip(get_peer_ip(sock)));
+			SDLNet_TCP_Close(sock);
+		} else {
+			result = malloc(sizeof(_NonBlockSocket));
+			if(result==NULL) {
+				flib_log_e("Out of memory!");
+				SDLNet_TCP_Close(sock);
+				return NULL;
+			}
+			result->sock = sock;
+			result->sockset = SDLNet_AllocSocketSet(1);
+			if(result->sockset==NULL) {
+				flib_log_e("Out of memory!");
+				SDLNet_TCP_Close(sock);
+				free(result);
+				return NULL;
+			}
+			SDLNet_AddSocket(result->sockset, (SDLNet_GenericSocket)result->sock);
+		}
+	}
+	return result;
+}
+
+int flib_nbsocket_recv(NonBlockSocket sock, void *data, int maxlen) {
+	if(!sock) {
+		flib_log_e("Attempt to receive on a NULL socket.");
+		return -1;
+	}
+	int readySockets = SDLNet_CheckSockets(sock->sockset, 0);
+	if(readySockets>0) {
+		int size = SDLNet_TCP_Recv(sock->sock, data, maxlen);
+		return size>0 ? size : -1;
+	} else if(readySockets==0) {
+		return 0;
+	} else {
+		flib_log_e("Error in select system call: %s", SDLNet_GetError());
+		return -1;
+	}
+}