project_files/frontlib/socket.c
changeset 7271 5608ac657362
parent 7234 613998625a3c
child 7314 6171f0bad318
equal deleted inserted replaced
7269:5b0aeef8ba2a 7271:5608ac657362
     3 #include "util/util.h"
     3 #include "util/util.h"
     4 #include <stdlib.h>
     4 #include <stdlib.h>
     5 #include <SDL_net.h>
     5 #include <SDL_net.h>
     6 #include <time.h>
     6 #include <time.h>
     7 
     7 
     8 typedef struct _flib_tcpsocket {
     8 struct _flib_tcpsocket {
     9 	TCPsocket sock;
     9 	TCPsocket sock;
    10 	SDLNet_SocketSet sockset;
    10 	SDLNet_SocketSet sockset;
    11 } _flib_tcpsocket;
    11 };
    12 
    12 
    13 typedef struct _flib_acceptor {
    13 struct _flib_acceptor {
    14 	TCPsocket sock;
    14 	TCPsocket sock;
    15 	uint16_t port;
    15 	uint16_t port;
    16 } _flib_acceptor;
    16 };
    17 
    17 
    18 static uint32_t get_peer_ip(TCPsocket sock) {
    18 static uint32_t getPeerIp(TCPsocket sock) {
    19 	IPaddress *addr = SDLNet_TCP_GetPeerAddress(sock);
    19 	IPaddress *addr = SDLNet_TCP_GetPeerAddress(sock);
    20 	return SDLNet_Read32(&addr->host);
    20 	return SDLNet_Read32(&addr->host);
    21 }
    21 }
    22 
    22 
    23 static bool connection_is_local(TCPsocket sock) {
    23 static bool connectionIsLocal(TCPsocket sock) {
    24 	return get_peer_ip(sock) == (uint32_t)((127UL<<24)+1); // 127.0.0.1
    24 	return getPeerIp(sock) == (uint32_t)((127UL<<24)+1); // 127.0.0.1
    25 }
    25 }
    26 
    26 
    27 static flib_tcpsocket *flib_socket_create(TCPsocket sdlsock) {
    27 static flib_tcpsocket *createSocket(TCPsocket sdlsock) {
    28 	flib_tcpsocket *result = flib_calloc(1, sizeof(_flib_tcpsocket));
    28 	flib_tcpsocket *result = flib_calloc(1, sizeof(flib_tcpsocket));
    29 	if(!result) {
    29 	if(result) {
    30 		return NULL;
    30 		result->sock = sdlsock;
       
    31 		result->sockset = SDLNet_AllocSocketSet(1);
       
    32 
       
    33 		if(!result->sockset) {
       
    34 			flib_log_e("Can't allocate socket: Out of memory!");
       
    35 			SDLNet_FreeSocketSet(result->sockset);
       
    36 			free(result);
       
    37 			result = NULL;
       
    38 		} else {
       
    39 			SDLNet_AddSocket(result->sockset, (SDLNet_GenericSocket)result->sock);
       
    40 		}
    31 	}
    41 	}
    32 	result->sock = sdlsock;
       
    33 	result->sockset = SDLNet_AllocSocketSet(1);
       
    34 
       
    35 	if(!result->sockset) {
       
    36 		flib_log_e("Can't allocate socket: Out of memory!");
       
    37 		SDLNet_FreeSocketSet(result->sockset);
       
    38 		free(result);
       
    39 		return NULL;
       
    40 	}
       
    41 
       
    42 	SDLNet_AddSocket(result->sockset, (SDLNet_GenericSocket)result->sock);
       
    43 	return result;
    42 	return result;
    44 }
    43 }
    45 
    44 
    46 flib_acceptor *flib_acceptor_create(uint16_t port) {
    45 TCPsocket listen(uint16_t port) {
    47 	flib_acceptor *result = flib_calloc(1, sizeof(_flib_acceptor));
       
    48 	if(!result) {
       
    49 		return NULL;
       
    50 	}
       
    51 
       
    52 	IPaddress addr;
    46 	IPaddress addr;
    53 	addr.host = INADDR_ANY;
    47 	addr.host = INADDR_ANY;
       
    48 	SDLNet_Write16(port, &addr.port);
       
    49 	TCPsocket sock = SDLNet_TCP_Open(&addr);
       
    50 	if(!sock) {
       
    51 		flib_log_w("Unable to listen on port %u: %s", (unsigned)port, SDLNet_GetError());
       
    52 	}
       
    53 	return sock;
       
    54 }
    54 
    55 
    55 	if(port > 0) {
    56 flib_acceptor *flib_acceptor_create(uint16_t port) {
    56 		result->port = port;
    57 	flib_acceptor *result = flib_calloc(1, sizeof(flib_acceptor));
    57 		SDLNet_Write16(port, &addr.port);
    58 	if(result) {
    58 		result->sock = SDLNet_TCP_Open(&addr);
    59 		if(port > 0) {
    59 		if(result->sock) {
    60 			result->port = port;
    60 			return result;
    61 			result->sock = listen(result->port);
    61 		} else {
    62 		} else {
    62 			flib_log_e("Unable to listen on port %u: %s", (unsigned)port, SDLNet_GetError());
    63 			/* SDL_net does not seem to have a way to listen on a random unused port
    63 			free(result);
    64 			   and find out which port that is, so let's try to find one ourselves. */
    64 			return NULL;
    65 			srand(time(NULL));
    65 		}
    66 			for(int i=0; !result->sock && i<1000; i++) {
    66 	} else {
    67 				// IANA suggests using ports in the range 49152-65535 for things like this
    67 		/* SDL_net does not seem to have a way to listen on a random unused port
    68 				result->port = 49152+(rand()%(65535-49152));
    68 		   and find out which port that is, so let's try to find one ourselves. */
    69 				result->sock = listen(result->port);
    69 		srand(time(NULL));
       
    70 		rand();
       
    71 		for(int i=0; i<1000; i++) {
       
    72 			// IANA suggests using ports in the range 49152-65535 for things like this
       
    73 			result->port = 49152+(rand()%(65535-49152));
       
    74 			SDLNet_Write16(result->port, &addr.port);
       
    75 			result->sock = SDLNet_TCP_Open(&addr);
       
    76 			if(result->sock) {
       
    77 				return result;
       
    78 			} else {
       
    79 				flib_log_w("Unable to listen on port %u: %s", (unsigned)result->port, SDLNet_GetError());
       
    80 			}
    70 			}
    81 		}
    71 		}
    82 		flib_log_e("Unable to listen on a random unused port.");
    72 		if(!result->sock) {
    83 		free(result);
    73 			flib_log_e("Failed to create acceptor.");
    84 		return NULL;
    74 			free(result);
       
    75 			result = NULL;
       
    76 		}
    85 	}
    77 	}
       
    78 	return result;
    86 }
    79 }
    87 
    80 
    88 uint16_t flib_acceptor_listenport(flib_acceptor *acceptor) {
    81 uint16_t flib_acceptor_listenport(flib_acceptor *acceptor) {
    89 	if(!acceptor) {
    82 	if(!acceptor) {
    90 		flib_log_e("Call to flib_acceptor_listenport with acceptor==null");
    83 		flib_log_e("Call to flib_acceptor_listenport with acceptor==null");
    99 		free(acceptor);
    92 		free(acceptor);
   100 	}
    93 	}
   101 }
    94 }
   102 
    95 
   103 flib_tcpsocket *flib_socket_accept(flib_acceptor *acceptor, bool localOnly) {
    96 flib_tcpsocket *flib_socket_accept(flib_acceptor *acceptor, bool localOnly) {
       
    97 	flib_tcpsocket *result = NULL;
   104 	if(!acceptor) {
    98 	if(!acceptor) {
   105 		flib_log_e("Call to flib_socket_accept with acceptor==null");
    99 		flib_log_e("Call to flib_socket_accept with acceptor==null");
   106 		return NULL;
   100 	} else {
   107 	}
   101 		TCPsocket sock = NULL;
   108 	flib_tcpsocket *result = NULL;
   102 		while(!result && (sock = SDLNet_TCP_Accept(acceptor->sock))) {
   109 	TCPsocket sock = NULL;
   103 			if(localOnly && !connectionIsLocal(sock)) {
   110 	while(!result && (sock = SDLNet_TCP_Accept(acceptor->sock))) {
   104 				flib_log_i("Rejected nonlocal connection attempt from %s", flib_format_ip(getPeerIp(sock)));
   111 		if(localOnly && !connection_is_local(sock)) {
   105 			} else {
   112 			flib_log_i("Rejected nonlocal connection attempt from %s", flib_format_ip(get_peer_ip(sock)));
   106 				result = createSocket(sock);
   113 			SDLNet_TCP_Close(sock);
   107 			}
   114 		} else {
       
   115 			result = flib_socket_create(sock);
       
   116 			if(!result) {
   108 			if(!result) {
   117 				SDLNet_TCP_Close(sock);
   109 				SDLNet_TCP_Close(sock);
   118 			}
   110 			}
   119 		}
   111 		}
   120 	}
   112 	}
   132 		} else {
   124 		} else {
   133 			TCPsocket sock=SDLNet_TCP_Open(&ip);
   125 			TCPsocket sock=SDLNet_TCP_Open(&ip);
   134 			if(!sock) {
   126 			if(!sock) {
   135 				flib_log_e("SDLNet_TCP_Open: %s\n", SDLNet_GetError());
   127 				flib_log_e("SDLNet_TCP_Open: %s\n", SDLNet_GetError());
   136 			} else {
   128 			} else {
   137 				result = flib_socket_create(sock);
   129 				result = createSocket(sock);
   138 				if(result) {
   130 				if(result) {
   139 					sock = NULL;
   131 					sock = NULL;
   140 				}
   132 				}
   141 			}
   133 			}
   142 			SDLNet_TCP_Close(sock);
   134 			SDLNet_TCP_Close(sock);