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