1 /+
2 +            Copyright 2022 – 2023 Aya Partridge
3 +          Copyright 2018 - 2022 Michael D. Parker
4 + Distributed under the Boost Software License, Version 1.0.
5 +     (See accompanying file LICENSE_1_0.txt or copy at
6 +           http://www.boost.org/LICENSE_1_0.txt)
7 +/
8 module sdl_net;
9 
10 import bindbc.sdl.config;
11 static if(bindSDLNet):
12 import bindbc.sdl.codegen;
13 
14 import sdl.version_: SDL_version;
15 
16 alias SDLNet_version = SDL_version;
17 
18 enum SDLNetSupport: SDLNet_version{
19 	noLibrary   = SDLNet_version(0,0,0),
20 	badLibrary  = SDLNet_version(0,0,255),
21 	v2_0_0      = SDLNet_version(2,0,0),
22 	v2_0_1      = SDLNet_version(2,0,1),
23 	v2_2        = SDLNet_version(2,2,0),
24 	
25 	deprecated("Please use `v2_0_0` instead") sdlNet200 = SDLNet_version(2,0,0),
26 	deprecated("Please use `v2_0_1` instead") sdlNet201 = SDLNet_version(2,0,1),
27 }
28 
29 enum sdlNetSupport = (){
30 	version(SDL_Net_2_2)      return SDLNetSupport.v2_2;
31 	else version(SDL_Net_201) return SDLNetSupport.v2_0_1;
32 	else                      return SDLNetSupport.v2_0_0;
33 }();
34 
35 enum SDL_NET_MAJOR_VERSION = sdlNetSupport.major;
36 enum SDL_NET_MINOR_VERSION = sdlNetSupport.minor;
37 enum SDL_NET_PATCHLEVEL    = sdlNetSupport.patch;
38 
39 pragma(inline, true) void SDL_NET_VERSION(SDLNet_version* X) @nogc nothrow pure @safe{
40 	X.major = SDL_NET_MAJOR_VERSION;
41 	X.minor = SDL_NET_MINOR_VERSION;
42 	X.patch = SDL_NET_PATCHLEVEL;
43 }
44 
45 bool SDL_NET_VERSION_ATLEAST(ubyte X, ubyte Y, ubyte Z){ return SDLNet_version(SDL_NET_MAJOR_VERSION, SDL_NET_MINOR_VERSION, SDL_NET_PATCHLEVEL) >= SDLNet_version(X, Y, Z); }
46 
47 struct IPaddress{
48 	uint host;
49 	ushort port;
50 }
51 
52 enum: uint{
53 	INADDR_ANY        = 0x0000_0000,
54 	INADDR_NONE       = 0xFFFF_FFFF,
55 	INADDR_LOOPBACK   = 0x7F00_0001,
56 	INADDR_BROADCAST  = 0xFFFF_FFFF,
57 }
58 
59 struct _TCPsocket;
60 alias TCPsocket = _TCPsocket*;
61 
62 enum SDLNET_MAX_UDPCHANNELS = 32;
63 
64 enum SDLNET_MAX_UDPADRESSES = 4;
65 
66 struct _UDPsocket;
67 alias UDPsocket = _UDPsocket*;
68 
69 struct UDPpacket{
70 	int channel;
71 	ubyte* data;
72 	int len;
73 	int maxlen;
74 	int status;
75 	IPaddress address;
76 }
77 
78 struct _SDLNet_SocketSet;
79 alias SDLNet_SocketSet = _SDLNet_SocketSet*;
80 
81 struct _SDLNet_GenericSocket{
82 	int ready;
83 }
84 alias SDLNet_GenericSocket = _SDLNet_GenericSocket*;
85 
86 pragma(inline, true) @nogc nothrow{
87 	int SDLNet_TCP_AddSocket(SDLNet_SocketSet set, TCPsocket sock){
88 		return SDLNet_AddSocket(set, cast(SDLNet_GenericSocket)sock);
89 	}
90 	
91 	int SDLNet_UDP_AddSocket(SDLNet_SocketSet set, UDPsocket sock){
92 		return SDLNet_AddSocket(set, cast(SDLNet_GenericSocket)sock);
93 	}
94 	
95 	int SDLNet_TCP_DelSocket(SDLNet_SocketSet set, TCPsocket sock){
96 		return SDLNet_DelSocket(set, cast(SDLNet_GenericSocket)sock);
97 	}
98 	
99 	int SDLNet_UDP_DelSocket(SDLNet_SocketSet set, UDPsocket sock){
100 		return SDLNet_DelSocket(set, cast(SDLNet_GenericSocket)sock);
101 	}
102 	
103 	bool SDLNet_SocketReady(TCPsocket sock){
104 		return (sock !is null) && (cast(SDLNet_GenericSocket)sock).ready;
105 	}
106 	
107 	bool SDLNet_SocketReady(UDPsocket sock){
108 		return (sock !is null) && (cast(SDLNet_GenericSocket)sock).ready;
109 	}
110 	
111 	pure{
112 		import sdl.endian: SDL_SwapBE16, SDL_SwapBE32;
113 		
114 		void SDLNet_Write16(ushort value, void* areap){
115 			*cast(ushort*)areap = SDL_SwapBE16(value);
116 		}
117 		
118 		void SDLNet_Write32(uint value, void* areap){
119 			*cast(uint*)areap = SDL_SwapBE32(value);
120 		}
121 		
122 		ushort SDLNet_Read16(const(void)* areap){
123 			return SDL_SwapBE16(*cast(const(ushort)*)areap);
124 		}
125 		
126 		uint SDLNet_Read32(const(void)* areap){
127 			return SDL_SwapBE32(*cast(const(uint)*)areap);
128 		}
129 	}
130 }
131 
132 mixin(joinFnBinds((){
133 	string[][] ret;
134 	ret ~= makeFnBinds([
135 		[q{const(SDLNet_version)*}, q{SDLNet_Linked_Version}, q{}],
136 		[q{int}, q{SDLNet_Init}, q{}],
137 		[q{void}, q{SDLNet_Quit}, q{}],
138 		[q{int}, q{SDLNet_ResolveHost}, q{IPaddress* address, const(char)* host, ushort port}],
139 		[q{const(char)*}, q{SDLNet_ResolveIP}, q{const(IPaddress)* ip}],
140 		[q{int}, q{SDLNet_GetLocalAddresses}, q{IPaddress* addresses, int maxcount}],
141 		[q{TCPsocket}, q{SDLNet_TCP_Open}, q{IPaddress* ip}],
142 		[q{TCPsocket}, q{SDLNet_TCP_Accept}, q{TCPsocket server}],
143 		[q{IPaddress*}, q{SDLNet_TCP_GetPeerAddress}, q{TCPsocket sock}],
144 		[q{int}, q{SDLNet_TCP_Send}, q{TCPsocket sock, const(void)* data, int len}],
145 		[q{int}, q{SDLNet_TCP_Recv}, q{TCPsocket sock, void* data, int len}],
146 		[q{void}, q{SDLNet_TCP_Close}, q{TCPsocket sock}],
147 		[q{UDPpacket*}, q{SDLNet_AllocPacket}, q{int size}],
148 		[q{int}, q{SDLNet_ResizePacket}, q{UDPpacket* packet, int newsize}],
149 		[q{void}, q{SDLNet_FreePacket}, q{UDPpacket* packet}],
150 		[q{UDPpacket**}, q{SDLNet_AllocPacketV}, q{int howmany, int size}],
151 		[q{void}, q{SDLNet_FreePacketV}, q{UDPpacket** packetV}],
152 		[q{UDPsocket}, q{SDLNet_UDP_Open}, q{ushort port}],
153 		[q{void}, q{SDLNet_UDP_SetPacketLoss}, q{UDPsocket sock, int percent}],
154 		[q{int}, q{SDLNet_UDP_Bind}, q{UDPsocket sock, int channel, const(IPaddress)* address}],
155 		[q{void}, q{SDLNet_UDP_Unbind}, q{UDPsocket sock, int channel}],
156 		[q{IPaddress*}, q{SDLNet_UDP_GetPeerAddress}, q{UDPsocket sock, int channel}],
157 		[q{int}, q{SDLNet_UDP_SendV}, q{UDPsocket sock, UDPpacket** packets, int npackets}],
158 		[q{int}, q{SDLNet_UDP_Send}, q{UDPsocket sock, int channel, UDPpacket* packet}],
159 		[q{int}, q{SDLNet_UDP_RecvV}, q{UDPsocket sock, UDPpacket** packets}],
160 		[q{int}, q{SDLNet_UDP_Recv}, q{UDPsocket sock, UDPpacket* packet}],
161 		[q{void}, q{SDLNet_UDP_Close}, q{UDPsocket sock}],
162 		[q{SDLNet_SocketSet}, q{SDLNet_AllocSocketSet}, q{int maxsockets}],
163 		[q{int}, q{SDLNet_AddSocket}, q{SDLNet_SocketSet set, SDLNet_GenericSocket sock}],
164 		[q{int}, q{SDLNet_DelSocket}, q{SDLNet_SocketSet set, SDLNet_GenericSocket sock}],
165 		[q{int}, q{SDLNet_CheckSockets}, q{SDLNet_SocketSet set, uint timeout}],
166 		[q{void}, q{SDLNet_FreeSocketSet}, q{SDLNet_SocketSet set}],
167 		[q{void}, q{SDLNet_SetError}, q{const(char)* fmt, ...}],
168 		[q{const(char)*}, q{SDLNet_GetError}, q{}],
169 	]);
170 	return ret;
171 }()));
172 
173 static if(!staticBinding):
174 import bindbc.loader;
175 
176 private{
177 	SharedLib lib;
178 	SDLNetSupport loadedVersion;
179 	enum libNamesCT = (){
180 		version(Windows){
181 			return [
182 				`SDL2_net.dll`,
183 			];
184 		}else version(OSX){
185 			return [
186 				`libSDL2_net.dylib`,
187 				`/opt/homebrew/lib/libSDL2_net.dylib`,
188 				`SDL2_net`,
189 				`/Library/Frameworks/SDL2_net.framework/SDL2_net`,
190 				`/System/Library/Frameworks/SDL2_net.framework/SDL2_net`,
191 			];
192 		}else version(Posix){
193 			return [
194 				`libSDL2_net.so`,
195 				`libSDL2_net-2.0.so`,
196 				`libSDL2_net-2.0.so.0`,
197 			];
198 		}else static assert(0, "BindBC-SDL_net does not have library search paths set up for this platform");
199 	}();
200 }
201 
202 @nogc nothrow:
203 deprecated("Please use `SDLNet_Linked_Version` instead")
204 	SDLNetSupport loadedSDLNetVersion(){ return loadedVersion; }
205 
206 mixin(bindbc.sdl.codegen.makeDynloadFns("Net", [__MODULE__]));