project_files/frontlib/socket.c
changeset 7175 038e3415100a
parent 7171 906e72caea7b
child 7177 bf6cf4dd847a
equal deleted inserted replaced
7173:7c2eb284f9f1 7175:038e3415100a
    21 
    21 
    22 static bool connection_is_local(TCPsocket sock) {
    22 static bool connection_is_local(TCPsocket sock) {
    23 	return get_peer_ip(sock) == (uint32_t)((127UL<<24)+1); // 127.0.0.1
    23 	return get_peer_ip(sock) == (uint32_t)((127UL<<24)+1); // 127.0.0.1
    24 }
    24 }
    25 
    25 
       
    26 static flib_tcpsocket flib_socket_create(TCPsocket sdlsock) {
       
    27 	flib_tcpsocket result = malloc(sizeof(_flib_tcpsocket));
       
    28 	if(!result) {
       
    29 		flib_log_e("Can't allocate socket: Out of memory!");
       
    30 		return NULL;
       
    31 	}
       
    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;
       
    44 }
       
    45 
    26 flib_acceptor flib_acceptor_create(uint16_t port) {
    46 flib_acceptor flib_acceptor_create(uint16_t port) {
    27 	flib_acceptor result = malloc(sizeof(_flib_acceptor));
    47 	flib_acceptor result = malloc(sizeof(_flib_acceptor));
    28 	if(!result) {
    48 	if(!result) {
    29 		flib_log_e("Out of memory!");
    49 		flib_log_e("Can't allocate acceptor: Out of memory!");
    30 		return NULL;
    50 		return NULL;
    31 	}
    51 	}
    32 
    52 
    33 	IPaddress addr;
    53 	IPaddress addr;
    34 	addr.host = INADDR_ANY;
    54 	addr.host = INADDR_ANY;
    45 			return NULL;
    65 			return NULL;
    46 		}
    66 		}
    47 	} else {
    67 	} else {
    48 		/* SDL_net does not seem to have a way to listen on a random unused port
    68 		/* SDL_net does not seem to have a way to listen on a random unused port
    49 		   and find out which port that is, so let's try to find one ourselves. */
    69 		   and find out which port that is, so let's try to find one ourselves. */
    50 		// TODO: Is socket binding fail-fast on all platforms?
       
    51 		srand(time(NULL));
    70 		srand(time(NULL));
    52 		rand();
    71 		rand();
    53 		for(int i=0; i<1000; i++) {
    72 		for(int i=0; i<1000; i++) {
    54 			// IANA suggests using ports in the range 49152-65535 for things like this
    73 			// IANA suggests using ports in the range 49152-65535 for things like this
    55 			result->port = 49152+(rand()%(65535-49152));
    74 			result->port = 49152+(rand()%(65535-49152));
    56 			SDLNet_Write16(result->port, &addr.port);
    75 			SDLNet_Write16(result->port, &addr.port);
    57 			result->sock = SDLNet_TCP_Open(&addr);
    76 			result->sock = SDLNet_TCP_Open(&addr);
    58 			if(result->sock) {
    77 			if(result->sock) {
    59 				return result;
    78 				return result;
    60 			} else {
    79 			} else {
    61 				flib_log_i("Unable to listen on port %u: %s", result->port, SDLNet_GetError());
    80 				flib_log_w("Unable to listen on port %u: %s", result->port, SDLNet_GetError());
    62 			}
    81 			}
    63 		}
    82 		}
    64 		flib_log_e("Unable to listen on a random unused port.");
    83 		flib_log_e("Unable to listen on a random unused port.");
    65 		free(result);
    84 		free(result);
    66 		return NULL;
    85 		return NULL;
    67 	}
    86 	}
    68 }
    87 }
    69 
    88 
    70 uint16_t flib_acceptor_listenport(flib_acceptor acceptor) {
    89 uint16_t flib_acceptor_listenport(flib_acceptor acceptor) {
       
    90 	if(!acceptor) {
       
    91 		flib_log_e("Call to flib_acceptor_listenport with acceptor==null");
       
    92 		return 0;
       
    93 	}
    71 	return acceptor->port;
    94 	return acceptor->port;
    72 }
    95 }
    73 
    96 
    74 void flib_acceptor_close(flib_acceptor *acceptorptr) {
    97 void flib_acceptor_close(flib_acceptor *acceptorptr) {
    75 	if(acceptorptr == NULL || *acceptorptr == NULL) {
    98 	if(!acceptorptr) {
    76 		return;
    99 		flib_log_e("Call to flib_acceptor_close with acceptorptr==null");
       
   100 	} else if(*acceptorptr) {
       
   101 		SDLNet_TCP_Close((*acceptorptr)->sock);
       
   102 		free(*acceptorptr);
       
   103 		*acceptorptr = NULL;
    77 	}
   104 	}
    78 	SDLNet_TCP_Close((*acceptorptr)->sock);
       
    79 	free(*acceptorptr);
       
    80 	*acceptorptr = NULL;
       
    81 }
   105 }
    82 
   106 
    83 flib_tcpsocket flib_socket_accept(flib_acceptor acceptor, bool localOnly) {
   107 flib_tcpsocket flib_socket_accept(flib_acceptor acceptor, bool localOnly) {
    84 	flib_tcpsocket result = NULL;
       
    85 	if(!acceptor) {
   108 	if(!acceptor) {
       
   109 		flib_log_e("Call to flib_socket_accept with acceptor==null");
    86 		return NULL;
   110 		return NULL;
    87 	}
   111 	}
    88 	while(result==NULL) {
   112 	flib_tcpsocket result = NULL;
    89 		TCPsocket sock = SDLNet_TCP_Accept(acceptor->sock);
   113 	TCPsocket sock = NULL;
    90 		if(!sock) {
   114 	while(!result && (sock = SDLNet_TCP_Accept(acceptor->sock))) {
    91 			// No incoming connections
       
    92 			return NULL;
       
    93 		}
       
    94 		if(localOnly && !connection_is_local(sock)) {
   115 		if(localOnly && !connection_is_local(sock)) {
    95 			flib_log_i("Rejected nonlocal connection attempt from %s", flib_format_ip(get_peer_ip(sock)));
   116 			flib_log_i("Rejected nonlocal connection attempt from %s", flib_format_ip(get_peer_ip(sock)));
    96 			SDLNet_TCP_Close(sock);
   117 			SDLNet_TCP_Close(sock);
    97 		} else {
   118 		} else {
    98 			result = malloc(sizeof(_flib_tcpsocket));
   119 			result = flib_socket_create(sock);
    99 			if(result==NULL) {
   120 			if(!result) {
   100 				flib_log_e("Out of memory!");
       
   101 				SDLNet_TCP_Close(sock);
   121 				SDLNet_TCP_Close(sock);
   102 				return NULL;
       
   103 			}
   122 			}
   104 			result->sock = sock;
       
   105 			result->sockset = SDLNet_AllocSocketSet(1);
       
   106 			if(result->sockset==NULL) {
       
   107 				flib_log_e("Out of memory!");
       
   108 				SDLNet_TCP_Close(sock);
       
   109 				free(result);
       
   110 				return NULL;
       
   111 			}
       
   112 			SDLNet_AddSocket(result->sockset, (SDLNet_GenericSocket)result->sock);
       
   113 		}
   123 		}
   114 	}
   124 	}
   115 	return result;
   125 	return result;
   116 }
   126 }
   117 
   127 
   118 void flib_socket_close(flib_tcpsocket *sockptr) {
   128 void flib_socket_close(flib_tcpsocket *sockptr) {
   119 	if(sockptr==NULL || *sockptr == NULL) {
   129 	if(!sockptr) {
   120 		return;
   130 		flib_log_e("Call to flib_socket_close with sockptr==null");
       
   131 	} else if(*sockptr) {
       
   132 		flib_tcpsocket sock = *sockptr;
       
   133 		SDLNet_DelSocket(sock->sockset, (SDLNet_GenericSocket)sock->sock);
       
   134 		SDLNet_TCP_Close(sock->sock);
       
   135 		SDLNet_FreeSocketSet(sock->sockset);
       
   136 		free(sock);
       
   137 		*sockptr = NULL;
   121 	}
   138 	}
   122 	flib_tcpsocket sock = *sockptr;
       
   123 	SDLNet_DelSocket(sock->sockset, (SDLNet_GenericSocket)sock->sock);
       
   124 	SDLNet_TCP_Close(sock->sock);
       
   125 	SDLNet_FreeSocketSet(sock->sockset);
       
   126 	free(sock);
       
   127 	*sockptr = NULL;
       
   128 }
   139 }
   129 
   140 
   130 int flib_socket_nbrecv(flib_tcpsocket sock, void *data, int maxlen) {
   141 int flib_socket_nbrecv(flib_tcpsocket sock, void *data, int maxlen) {
   131 	if(!sock) {
   142 	if(!sock || (maxlen>0 && !data)) {
   132 		flib_log_e("Attempt to receive on a NULL socket.");
   143 		flib_log_e("Call to flib_socket_nbrecv with sock==null or data==null");
   133 		return -1;
   144 		return -1;
   134 	}
   145 	}
   135 	int readySockets = SDLNet_CheckSockets(sock->sockset, 0);
   146 	int readySockets = SDLNet_CheckSockets(sock->sockset, 0);
   136 	if(readySockets>0) {
   147 	if(readySockets>0) {
   137 		int size = SDLNet_TCP_Recv(sock->sock, data, maxlen);
   148 		int size = SDLNet_TCP_Recv(sock->sock, data, maxlen);
   143 		return -1;
   154 		return -1;
   144 	}
   155 	}
   145 }
   156 }
   146 
   157 
   147 int flib_socket_send(flib_tcpsocket sock, void *data, int len) {
   158 int flib_socket_send(flib_tcpsocket sock, void *data, int len) {
       
   159 	if(!sock || (len>0 && !data)) {
       
   160 		flib_log_e("Call to flib_socket_send with sock==null or data==null");
       
   161 		return -1;
       
   162 	}
   148 	return SDLNet_TCP_Send(sock->sock, data, len);
   163 	return SDLNet_TCP_Send(sock->sock, data, len);
   149 }
   164 }