diff -r 4feced261c68 -r de822cd3df3a project_files/frontlib/socket.c --- a/project_files/frontlib/socket.c Tue Jan 21 22:38:13 2014 +0100 +++ b/project_files/frontlib/socket.c Tue Jan 21 22:43:06 2014 +0100 @@ -1,191 +1,191 @@ -/* - * Hedgewars, a free turn based strategy game - * Copyright (C) 2012 Simeon Maxein - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "socket.h" -#include "util/logging.h" -#include "util/util.h" -#include -#include -#include - -struct _flib_tcpsocket { - TCPsocket sock; - SDLNet_SocketSet sockset; -}; - -struct _flib_acceptor { - TCPsocket sock; - uint16_t port; -}; - -static uint32_t getPeerIp(TCPsocket sock) { - IPaddress *addr = SDLNet_TCP_GetPeerAddress(sock); - return SDLNet_Read32(&addr->host); -} - -static bool connectionIsLocal(TCPsocket sock) { - return getPeerIp(sock) == (uint32_t)((127UL<<24)+1); // 127.0.0.1 -} - -static flib_tcpsocket *createSocket(TCPsocket sdlsock) { - flib_tcpsocket *result = flib_calloc(1, sizeof(flib_tcpsocket)); - if(result) { - result->sock = sdlsock; - result->sockset = SDLNet_AllocSocketSet(1); - - if(!result->sockset) { - flib_log_e("Can't allocate socket: Out of memory!"); - SDLNet_FreeSocketSet(result->sockset); - free(result); - result = NULL; - } else { - SDLNet_AddSocket(result->sockset, (SDLNet_GenericSocket)result->sock); - } - } - return result; -} - -TCPsocket listen(uint16_t port) { - IPaddress addr; - addr.host = INADDR_ANY; - SDLNet_Write16(port, &addr.port); - TCPsocket sock = SDLNet_TCP_Open(&addr); - if(!sock) { - flib_log_w("Unable to listen on port %u: %s", (unsigned)port, SDLNet_GetError()); - } - return sock; -} - -flib_acceptor *flib_acceptor_create(uint16_t port) { - flib_acceptor *result = flib_calloc(1, sizeof(flib_acceptor)); - if(result) { - if(port > 0) { - result->port = port; - result->sock = listen(result->port); - } else { - /* SDL_net does not seem to have a way to listen on a random unused port - and find out which port that is, so let's try to find one ourselves. */ - srand(time(NULL)); - for(int i=0; !result->sock && i<1000; i++) { - // IANA suggests using ports in the range 49152-65535 for things like this - result->port = 49152+(rand()%(65536-49152)); - result->sock = listen(result->port); - } - } - if(!result->sock) { - flib_log_e("Failed to create acceptor."); - free(result); - result = NULL; - } - } - return result; -} - -uint16_t flib_acceptor_listenport(flib_acceptor *acceptor) { - if(!acceptor) { - flib_log_e("Call to flib_acceptor_listenport with acceptor==null"); - return 0; - } - return acceptor->port; -} - -void flib_acceptor_close(flib_acceptor *acceptor) { - if(acceptor) { - SDLNet_TCP_Close(acceptor->sock); - free(acceptor); - } -} - -flib_tcpsocket *flib_socket_accept(flib_acceptor *acceptor, bool localOnly) { - flib_tcpsocket *result = NULL; - if(!acceptor) { - flib_log_e("Call to flib_socket_accept with acceptor==null"); - } else { - TCPsocket sock = NULL; - while(!result && (sock = SDLNet_TCP_Accept(acceptor->sock))) { - if(localOnly && !connectionIsLocal(sock)) { - flib_log_i("Rejected nonlocal connection attempt from %s", flib_format_ip(getPeerIp(sock))); - } else { - result = createSocket(sock); - } - if(!result) { - SDLNet_TCP_Close(sock); - } - } - } - return result; -} - -flib_tcpsocket *flib_socket_connect(const char *host, uint16_t port) { - flib_tcpsocket *result = NULL; - if(!host || port==0) { - flib_log_e("Invalid parameter in flib_socket_connect"); - } else { - IPaddress ip; - if(SDLNet_ResolveHost(&ip,host,port)==-1) { - flib_log_e("SDLNet_ResolveHost: %s\n", SDLNet_GetError()); - } else { - TCPsocket sock=SDLNet_TCP_Open(&ip); - if(!sock) { - flib_log_e("SDLNet_TCP_Open: %s\n", SDLNet_GetError()); - } else { - result = createSocket(sock); - if(result) { - sock = NULL; - } - } - SDLNet_TCP_Close(sock); - } - } - return result; -} - -void flib_socket_close(flib_tcpsocket *sock) { - if(sock) { - SDLNet_DelSocket(sock->sockset, (SDLNet_GenericSocket)sock->sock); - SDLNet_TCP_Close(sock->sock); - SDLNet_FreeSocketSet(sock->sockset); - free(sock); - } -} - -int flib_socket_nbrecv(flib_tcpsocket *sock, void *data, int maxlen) { - if(!sock || (maxlen>0 && !data)) { - flib_log_e("Call to flib_socket_nbrecv with sock==null or data==null"); - 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; - } -} - -int flib_socket_send(flib_tcpsocket *sock, const void *data, int len) { - if(!sock || (len>0 && !data)) { - flib_log_e("Call to flib_socket_send with sock==null or data==null"); - return -1; - } - return SDLNet_TCP_Send(sock->sock, data, len); -} +/* + * Hedgewars, a free turn based strategy game + * Copyright (C) 2012 Simeon Maxein + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "socket.h" +#include "util/logging.h" +#include "util/util.h" +#include +#include +#include + +struct _flib_tcpsocket { + TCPsocket sock; + SDLNet_SocketSet sockset; +}; + +struct _flib_acceptor { + TCPsocket sock; + uint16_t port; +}; + +static uint32_t getPeerIp(TCPsocket sock) { + IPaddress *addr = SDLNet_TCP_GetPeerAddress(sock); + return SDLNet_Read32(&addr->host); +} + +static bool connectionIsLocal(TCPsocket sock) { + return getPeerIp(sock) == (uint32_t)((127UL<<24)+1); // 127.0.0.1 +} + +static flib_tcpsocket *createSocket(TCPsocket sdlsock) { + flib_tcpsocket *result = flib_calloc(1, sizeof(flib_tcpsocket)); + if(result) { + result->sock = sdlsock; + result->sockset = SDLNet_AllocSocketSet(1); + + if(!result->sockset) { + flib_log_e("Can't allocate socket: Out of memory!"); + SDLNet_FreeSocketSet(result->sockset); + free(result); + result = NULL; + } else { + SDLNet_AddSocket(result->sockset, (SDLNet_GenericSocket)result->sock); + } + } + return result; +} + +TCPsocket listen(uint16_t port) { + IPaddress addr; + addr.host = INADDR_ANY; + SDLNet_Write16(port, &addr.port); + TCPsocket sock = SDLNet_TCP_Open(&addr); + if(!sock) { + flib_log_w("Unable to listen on port %u: %s", (unsigned)port, SDLNet_GetError()); + } + return sock; +} + +flib_acceptor *flib_acceptor_create(uint16_t port) { + flib_acceptor *result = flib_calloc(1, sizeof(flib_acceptor)); + if(result) { + if(port > 0) { + result->port = port; + result->sock = listen(result->port); + } else { + /* SDL_net does not seem to have a way to listen on a random unused port + and find out which port that is, so let's try to find one ourselves. */ + srand(time(NULL)); + for(int i=0; !result->sock && i<1000; i++) { + // IANA suggests using ports in the range 49152-65535 for things like this + result->port = 49152+(rand()%(65536-49152)); + result->sock = listen(result->port); + } + } + if(!result->sock) { + flib_log_e("Failed to create acceptor."); + free(result); + result = NULL; + } + } + return result; +} + +uint16_t flib_acceptor_listenport(flib_acceptor *acceptor) { + if(!acceptor) { + flib_log_e("Call to flib_acceptor_listenport with acceptor==null"); + return 0; + } + return acceptor->port; +} + +void flib_acceptor_close(flib_acceptor *acceptor) { + if(acceptor) { + SDLNet_TCP_Close(acceptor->sock); + free(acceptor); + } +} + +flib_tcpsocket *flib_socket_accept(flib_acceptor *acceptor, bool localOnly) { + flib_tcpsocket *result = NULL; + if(!acceptor) { + flib_log_e("Call to flib_socket_accept with acceptor==null"); + } else { + TCPsocket sock = NULL; + while(!result && (sock = SDLNet_TCP_Accept(acceptor->sock))) { + if(localOnly && !connectionIsLocal(sock)) { + flib_log_i("Rejected nonlocal connection attempt from %s", flib_format_ip(getPeerIp(sock))); + } else { + result = createSocket(sock); + } + if(!result) { + SDLNet_TCP_Close(sock); + } + } + } + return result; +} + +flib_tcpsocket *flib_socket_connect(const char *host, uint16_t port) { + flib_tcpsocket *result = NULL; + if(!host || port==0) { + flib_log_e("Invalid parameter in flib_socket_connect"); + } else { + IPaddress ip; + if(SDLNet_ResolveHost(&ip,host,port)==-1) { + flib_log_e("SDLNet_ResolveHost: %s\n", SDLNet_GetError()); + } else { + TCPsocket sock=SDLNet_TCP_Open(&ip); + if(!sock) { + flib_log_e("SDLNet_TCP_Open: %s\n", SDLNet_GetError()); + } else { + result = createSocket(sock); + if(result) { + sock = NULL; + } + } + SDLNet_TCP_Close(sock); + } + } + return result; +} + +void flib_socket_close(flib_tcpsocket *sock) { + if(sock) { + SDLNet_DelSocket(sock->sockset, (SDLNet_GenericSocket)sock->sock); + SDLNet_TCP_Close(sock->sock); + SDLNet_FreeSocketSet(sock->sockset); + free(sock); + } +} + +int flib_socket_nbrecv(flib_tcpsocket *sock, void *data, int maxlen) { + if(!sock || (maxlen>0 && !data)) { + flib_log_e("Call to flib_socket_nbrecv with sock==null or data==null"); + 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; + } +} + +int flib_socket_send(flib_tcpsocket *sock, const void *data, int len) { + if(!sock || (len>0 && !data)) { + flib_log_e("Call to flib_socket_send with sock==null or data==null"); + return -1; + } + return SDLNet_TCP_Send(sock->sock, data, len); +}