project_files/frontlib/nonblocksockets.c
author Medo <smaxein@googlemail.com>
Thu, 31 May 2012 18:54:40 +0200
changeset 7160 c42949cfdd92
parent 7158 frontlib/nonblocksockets.c@a0573014ff4f
permissions -rw-r--r--
Moved frontlib into project_files

#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;
	}
}