1 |
#include "Flatline.h" |
2 |
|
3 |
thread int UDPServer_Socket = 0; |
4 |
|
5 |
bool NetUDPServer_Listen(uint16_t port, bool (*packet_callback)(char* data, int datalen, int from)) |
6 |
{ |
7 |
UDPServer_Socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
8 |
|
9 |
if (UDPServer_Socket < 0) |
10 |
{ |
11 |
DDrStartupMessage("could not create socket"); |
12 |
return false; |
13 |
} |
14 |
|
15 |
sockaddr_in address; |
16 |
memset(&address, 0, sizeof(sockaddr_in)); |
17 |
address.sin_family = AF_INET; |
18 |
address.sin_addr.s_addr = htonl(INADDR_ANY); |
19 |
address.sin_port = htons(port); |
20 |
|
21 |
if (bind(UDPServer_Socket, (sockaddr*)&address, sizeof(sockaddr_in)) < 0) |
22 |
{ |
23 |
DDrStartupMessage("could not bind port %d", port); |
24 |
closesocket(UDPServer_Socket); |
25 |
return false; |
26 |
} |
27 |
|
28 |
char data[65537]; |
29 |
data[sizeof(data) - 1] = '\0'; |
30 |
sockaddr_in from; |
31 |
int recvlen; |
32 |
for (;;) |
33 |
{ |
34 |
int fromlen = sizeof(sockaddr_in); |
35 |
memset(&from, 0, sizeof(sockaddr_in)); |
36 |
recvlen = recvfrom(UDPServer_Socket, data, sizeof(data) - 1, 0, (sockaddr*)&from, (void*)&fromlen); |
37 |
if (!packet_callback(data, recvlen, ntohl(from.sin_addr.s_addr))) |
38 |
break; |
39 |
} |
40 |
closesocket(UDPServer_Socket); |
41 |
return true; |
42 |
} |
43 |
|
44 |
bool NetUDPServer_Send(sockaddr* address, char* data, int datalen) |
45 |
{ |
46 |
return NetUDPSocket_Send(UDPServer_Socket, address, data, datalen); |
47 |
} |
48 |
|
49 |
int NetUDPSocket_Create(uint16_t port) |
50 |
{ |
51 |
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
52 |
|
53 |
if (sock < 0) |
54 |
{ |
55 |
DDrStartupMessage("could not create socket"); |
56 |
return -1; |
57 |
} |
58 |
|
59 |
sockaddr_in address; |
60 |
memset(&address, 0, sizeof(sockaddr_in)); |
61 |
address.sin_family = AF_INET; |
62 |
address.sin_addr.s_addr = htonl(INADDR_ANY); |
63 |
address.sin_port = htons(port); |
64 |
|
65 |
if (bind(sock, (sockaddr*)&address, sizeof(sockaddr_in)) < 0) |
66 |
{ |
67 |
DDrStartupMessage("could not bind port %d", port); |
68 |
return false; |
69 |
} |
70 |
|
71 |
unsigned long nonBlocking = 1; |
72 |
if (ioctlsocket(sock, FIONBIO, &nonBlocking)) |
73 |
{ |
74 |
DDrStartupMessage("failed to set non-blocking socket"); |
75 |
return false; |
76 |
} |
77 |
|
78 |
return sock; |
79 |
} |
80 |
|
81 |
void NetUDPSocket_Close(int socket) |
82 |
{ |
83 |
closesocket(socket); |
84 |
} |
85 |
|
86 |
bool NetUDPSocket_Send(int socket, const sockaddr* address, const char* data, int datalen) |
87 |
{ |
88 |
int addr_size; |
89 |
switch (address->sa_family) |
90 |
{ |
91 |
case AF_INET: |
92 |
addr_size = sizeof(sockaddr_in); |
93 |
break; |
94 |
case AF_INET6: |
95 |
addr_size = sizeof(sockaddr_in6); |
96 |
break; |
97 |
default: |
98 |
addr_size = sizeof(sockaddr_storage); |
99 |
} |
100 |
return sendto(socket, data, datalen, 0, address, addr_size); |
101 |
} |
102 |
|
103 |
bool NetUDPSocket_Recieve(int socket, sockaddr_storage* address, char* data, uint16_t* datalen) |
104 |
{ |
105 |
int address_size = sizeof(sockaddr_storage); |
106 |
uint32_t msg_size = recvfrom(socket, data, 512, 0, (sockaddr*)address, &address_size); |
107 |
if (msg_size == 0) |
108 |
return false; |
109 |
else |
110 |
{ |
111 |
*datalen = msg_size; |
112 |
return true; |
113 |
} |
114 |
} |