1 2 // Copyright 2018 - 2021 Michael D. Parker 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 7 module bindbc.sdl.net; 8 9 import bindbc.sdl.config; 10 static if(bindSDLNet): 11 12 import bindbc.sdl.config; 13 import bindbc.sdl.bind.sdlversion : SDL_version; 14 15 enum SDLNetSupport { 16 noLibrary, 17 badLibrary, 18 sdlNet200 = 200, 19 sdlNet201 = 201, 20 } 21 22 enum ubyte SDL_NET_MAJOR_VERSION = 2; 23 enum ubyte SDL_NET_MINOR_VERSION = 0; 24 25 version(SDL_Net_201) { 26 enum sdlNetSupport = SDLNetSupport.sdlNet201; 27 enum SDL_NET_PATCHLEVEL = 1; 28 } 29 else { 30 enum sdlNetSupport = SDLNetSupport.sdlNet200; 31 enum SDL_NET_PATCHLEVEL = 0; 32 } 33 34 alias SDLNet_Version = SDL_version; 35 36 @nogc nothrow void SDL_NET_VERSION(SDL_version* X) { 37 X.major = SDL_NET_MAJOR_VERSION; 38 X.minor = SDL_NET_MINOR_VERSION; 39 X.patch = SDL_NET_PATCHLEVEL; 40 } 41 42 struct IPaddress { 43 uint host; 44 ubyte port; 45 } 46 47 enum { 48 INADDR_ANY = 0x00000000, 49 INADDR_NONE = 0xFFFFFFFF, 50 INADDR_LOOPBACK = 0x7f000001, 51 INADDR_BROADCAST = 0xFFFFFFFF, 52 } 53 54 alias TCPsocket = void*; 55 56 enum SDLNET_MAX_UDPCHANNELS = 32; 57 enum SDLNET_MAX_UDPADRESSES = 4; 58 59 alias UDPsocket = void*; 60 61 struct UDPpacket { 62 int channel; 63 ubyte* data; 64 int len; 65 int maxlen; 66 int status; 67 IPaddress address; 68 } 69 70 struct _SDLNet_SocketSet; 71 alias _SDLNet_SocketSet* SDLNet_SocketSet; 72 73 struct _SDLNet_GenericSocket { 74 int ready; 75 } 76 alias SDLNet_GenericSocket = _SDLNet_GenericSocket*; 77 78 @nogc nothrow { 79 int SDLNet_TCP_AddSocket(SDLNet_SocketSet set,void* sock) { 80 return SDLNet_AddSocket(set,cast(SDLNet_GenericSocket)sock); 81 } 82 alias SDLNet_UDP_AddSocket = SDLNet_TCP_AddSocket; 83 84 int SDLNet_TCP_DelSocket(SDLNet_SocketSet set,void* sock) { 85 return SDLNet_DelSocket(set,cast(SDLNet_GenericSocket)sock); 86 } 87 alias SDLNet_UDP_DelSocket = SDLNet_TCP_DelSocket; 88 89 bool SDLNet_SocketReady(void* sock) { 90 return sock && (cast(SDLNet_GenericSocket)sock).ready != 0; 91 } 92 } 93 94 static if(staticBinding) { 95 extern(C) @nogc nothrow { 96 const(SDLNet_Version)* SDLNet_Linked_Version(); 97 int SDLNet_Init(); 98 void SDLNet_Quit(); 99 int SDLNet_ResolveHost(IPaddress* address, const(char)* host, ushort port); 100 const(char)* SDLNet_ResolveIP(const(IPaddress)* ip); 101 int SDLNet_GetLocalAddresses(IPaddress* addresses, int maxcount); 102 TCPsocket SDLNet_TCP_Open(IPaddress* ip); 103 TCPsocket SDLNet_TCP_Accept(TCPsocket server); 104 IPaddress* SDLNet_TCP_GetPeerAddress(TCPsocket sock); 105 int SDLNet_TCP_Send(TCPsocket sock, const(void)* data, int len); 106 int SDLNet_TCP_Recv(TCPsocket sock, void* data, int len); 107 void SDLNet_TCP_Close(TCPsocket sock); 108 UDPpacket* SDLNet_AllocPacket(int size); 109 int SDLNet_ResizePacket(UDPpacket* packet, int newsize); 110 void SDLNet_FreePacket(UDPpacket* packet); 111 UDPpacket** SDLNet_AllocPacketV(int howmany, int size); 112 void SDLNet_FreePacketV(UDPpacket** packetV); 113 UDPsocket SDLNet_UDP_Open(ushort port); 114 void SDLNet_UDP_SetPacketLoss(UDPsocket sock, int percent); 115 int SDLNet_UDP_Bind(UDPsocket sock, int channel, const(IPaddress)* address); 116 void SDLNet_UDP_Unbind(UDPsocket sock, int channel); 117 IPaddress* SDLNet_UDP_GetPeerAddress(UDPsocket sock, int channel); 118 int SDLNet_UDP_SendV(UDPsocket sock, UDPpacket** packets, int npackets); 119 int SDLNet_UDP_Send(UDPsocket sock, int channel, UDPpacket* packet); 120 int SDLNet_UDP_RecvV(UDPsocket sock, UDPpacket** packets); 121 int SDLNet_UDP_Recv(UDPsocket sock, UDPpacket* packet); 122 void SDLNet_UDP_Close(UDPsocket sock); 123 SDLNet_SocketSet SDLNet_AllocSocketSet(int maxsockets); 124 int SDLNet_AddSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock); 125 int SDLNet_DelSocket(SDLNet_SocketSet set, SDLNet_GenericSocket sock); 126 int SDLNet_CheckSockets(SDLNet_SocketSet set, uint timeout); 127 void SDLNet_FreeSocketSet(SDLNet_SocketSet set); 128 void SDLNet_SetError(const(char)* fmt, ...); 129 const(char)* SDLNet_GetError(); 130 } 131 } 132 else { 133 import bindbc.loader; 134 135 extern(C) @nogc nothrow { 136 alias pSDLNet_Linked_Version = const(SDLNet_Version)* function(); 137 alias pSDLNet_Init = int function(); 138 alias pSDLNet_Quit = void function(); 139 alias pSDLNet_ResolveHost = int function(IPaddress* address, const(char)* host, ushort port); 140 alias pSDLNet_ResolveIP = const(char)* function(const(IPaddress)* ip); 141 alias pSDLNet_GetLocalAddresses = int function(IPaddress* addresses, int maxcount); 142 alias pSDLNet_TCP_Open = TCPsocket function(IPaddress* ip); 143 alias pSDLNet_TCP_Accept = TCPsocket function(TCPsocket server); 144 alias pSDLNet_TCP_GetPeerAddress = IPaddress* function(TCPsocket sock); 145 alias pSDLNet_TCP_Send = int function(TCPsocket sock, const(void)* data, int len); 146 alias pSDLNet_TCP_Recv = int function(TCPsocket sock, void* data, int len); 147 alias pSDLNet_TCP_Close = void function(TCPsocket sock); 148 alias pSDLNet_AllocPacket = UDPpacket* function(int size); 149 alias pSDLNet_ResizePacket = int function(UDPpacket* packet, int newsize); 150 alias pSDLNet_FreePacket = void function(UDPpacket* packet); 151 alias pSDLNet_AllocPacketV = UDPpacket** function(int howmany, int size); 152 alias pSDLNet_FreePacketV = void function(UDPpacket** packetV); 153 alias pSDLNet_UDP_Open = UDPsocket function(ushort port); 154 alias pSDLNet_UDP_SetPacketLoss = void function(UDPsocket sock, int percent); 155 alias pSDLNet_UDP_Bind = int function(UDPsocket sock, int channel, const(IPaddress)* address); 156 alias pSDLNet_UDP_Unbind = void function(UDPsocket sock, int channel); 157 alias pSDLNet_UDP_GetPeerAddress = IPaddress* function(UDPsocket sock, int channel); 158 alias pSDLNet_UDP_SendV = int function(UDPsocket sock, UDPpacket** packets, int npackets); 159 alias pSDLNet_UDP_Send = int function(UDPsocket sock, int channel, UDPpacket* packet); 160 alias pSDLNet_UDP_RecvV = int function(UDPsocket sock, UDPpacket** packets); 161 alias pSDLNet_UDP_Recv = int function(UDPsocket sock, UDPpacket* packet); 162 alias pSDLNet_UDP_Close = void function(UDPsocket sock); 163 alias pSDLNet_AllocSocketSet = SDLNet_SocketSet function(int maxsockets); 164 alias pSDLNet_AddSocket = int function(SDLNet_SocketSet set, SDLNet_GenericSocket sock); 165 alias pSDLNet_DelSocket = int function(SDLNet_SocketSet set, SDLNet_GenericSocket sock); 166 alias pSDLNet_CheckSockets = int function(SDLNet_SocketSet set, uint timeout); 167 alias pSDLNet_FreeSocketSet = void function(SDLNet_SocketSet set); 168 alias pSDLNet_SetError = void function(const(char)* fmt, ...); 169 alias pSDLNet_GetError = const(char)* function(); 170 } 171 172 __gshared { 173 pSDLNet_Linked_Version SDLNet_Linked_Version; 174 pSDLNet_Init SDLNet_Init; 175 pSDLNet_Quit SDLNet_Quit; 176 pSDLNet_ResolveHost SDLNet_ResolveHost; 177 pSDLNet_ResolveIP SDLNet_ResolveIP; 178 pSDLNet_GetLocalAddresses SDLNet_GetLocalAddresses; 179 pSDLNet_TCP_Open SDLNet_TCP_Open; 180 pSDLNet_TCP_Accept SDLNet_TCP_Accept; 181 pSDLNet_TCP_GetPeerAddress SDLNet_TCP_GetPeerAddress; 182 pSDLNet_TCP_Send SDLNet_TCP_Send; 183 pSDLNet_TCP_Recv SDLNet_TCP_Recv; 184 pSDLNet_TCP_Close SDLNet_TCP_Close; 185 pSDLNet_AllocPacket SDLNet_AllocPacket; 186 pSDLNet_ResizePacket SDLNet_ResizePacket; 187 pSDLNet_FreePacket SDLNet_FreePacket; 188 pSDLNet_AllocPacketV SDLNet_AllocPacketV; 189 pSDLNet_FreePacketV SDLNet_FreePacketV; 190 pSDLNet_UDP_Open SDLNet_UDP_Open; 191 pSDLNet_UDP_SetPacketLoss SDLNet_UDP_SetPacketLoss; 192 pSDLNet_UDP_Bind SDLNet_UDP_Bind; 193 pSDLNet_UDP_Unbind SDLNet_UDP_Unbind; 194 pSDLNet_UDP_GetPeerAddress SDLNet_UDP_GetPeerAddress; 195 pSDLNet_UDP_SendV SDLNet_UDP_SendV; 196 pSDLNet_UDP_Send SDLNet_UDP_Send; 197 pSDLNet_UDP_RecvV SDLNet_UDP_RecvV; 198 pSDLNet_UDP_Recv SDLNet_UDP_Recv; 199 pSDLNet_UDP_Close SDLNet_UDP_Close; 200 pSDLNet_AllocSocketSet SDLNet_AllocSocketSet; 201 pSDLNet_AddSocket SDLNet_AddSocket; 202 pSDLNet_DelSocket SDLNet_DelSocket; 203 pSDLNet_CheckSockets SDLNet_CheckSockets; 204 pSDLNet_FreeSocketSet SDLNet_FreeSocketSet; 205 pSDLNet_SetError SDLNet_SetError; 206 pSDLNet_GetError SDLNet_GetError; 207 } 208 209 private { 210 SharedLib lib; 211 SDLNetSupport loadedVersion; 212 } 213 214 @nogc nothrow: 215 void unloadSDLNet() 216 { 217 if(lib != invalidHandle) { 218 lib.unload(); 219 } 220 } 221 222 SDLNetSupport loadedSDLNetVersion() { return loadedVersion; } 223 224 bool isSDLNetLoaded() 225 { 226 return lib != invalidHandle; 227 } 228 229 230 SDLNetSupport loadSDLNet() 231 { 232 version(Windows) { 233 const(char)[][1] libNames = ["SDL2_net.dll"]; 234 } 235 else version(OSX) { 236 const(char)[][6] libNames = [ 237 "libSDL2_net.dylib", 238 "/usr/local/lib/libSDL2_net.dylib", 239 "../Frameworks/SDL2_net.framework/SDL2_net", 240 "/Library/Frameworks/SDL2_net.framework/SDL2_net", 241 "/System/Library/Frameworks/SDL2_net.framework/SDL2_net", 242 "/opt/local/lib/libSDL2_net.dylib" 243 ]; 244 } 245 else version(Posix) { 246 const(char)[][6] libNames = [ 247 "libSDL2_net.so", 248 "/usr/local/lib/libSDL2_net.so", 249 "libSDL2-2.0_net.so", 250 "/usr/local/lib/libSDL2-2.0_net.so", 251 "libSDL2-2.0_net.so.0", 252 "/usr/local/lib/libSDL2-2.0_net.so.0" 253 ]; 254 } 255 else static assert(0, "bindbc-sdl is not yet supported on this platform."); 256 257 SDLNetSupport ret; 258 foreach(name; libNames) { 259 ret = loadSDLNet(name.ptr); 260 if(ret != SDLNetSupport.noLibrary) break; 261 } 262 return ret; 263 } 264 265 SDLNetSupport loadSDLNet(const(char)* libName) 266 { 267 lib = load(libName); 268 if(lib == invalidHandle) { 269 return SDLNetSupport.noLibrary; 270 } 271 272 auto errCount = errorCount(); 273 loadedVersion = SDLNetSupport.badLibrary; 274 275 lib.bindSymbol(cast(void**)&SDLNet_Linked_Version,"SDLNet_Linked_Version"); 276 lib.bindSymbol(cast(void**)&SDLNet_Init,"SDLNet_Init"); 277 lib.bindSymbol(cast(void**)&SDLNet_Quit,"SDLNet_Quit"); 278 lib.bindSymbol(cast(void**)&SDLNet_ResolveHost,"SDLNet_ResolveHost"); 279 lib.bindSymbol(cast(void**)&SDLNet_ResolveIP,"SDLNet_ResolveIP"); 280 lib.bindSymbol(cast(void**)&SDLNet_GetLocalAddresses,"SDLNet_GetLocalAddresses"); 281 lib.bindSymbol(cast(void**)&SDLNet_TCP_Open,"SDLNet_TCP_Open"); 282 lib.bindSymbol(cast(void**)&SDLNet_TCP_Accept,"SDLNet_TCP_Accept"); 283 lib.bindSymbol(cast(void**)&SDLNet_TCP_GetPeerAddress,"SDLNet_TCP_GetPeerAddress"); 284 lib.bindSymbol(cast(void**)&SDLNet_TCP_Send,"SDLNet_TCP_Send"); 285 lib.bindSymbol(cast(void**)&SDLNet_TCP_Recv,"SDLNet_TCP_Recv"); 286 lib.bindSymbol(cast(void**)&SDLNet_TCP_Close,"SDLNet_TCP_Close"); 287 lib.bindSymbol(cast(void**)&SDLNet_AllocPacket,"SDLNet_AllocPacket"); 288 lib.bindSymbol(cast(void**)&SDLNet_ResizePacket,"SDLNet_ResizePacket"); 289 lib.bindSymbol(cast(void**)&SDLNet_FreePacket,"SDLNet_FreePacket"); 290 lib.bindSymbol(cast(void**)&SDLNet_AllocPacketV,"SDLNet_AllocPacketV"); 291 lib.bindSymbol(cast(void**)&SDLNet_FreePacketV,"SDLNet_FreePacketV"); 292 lib.bindSymbol(cast(void**)&SDLNet_UDP_Open,"SDLNet_UDP_Open"); 293 lib.bindSymbol(cast(void**)&SDLNet_UDP_SetPacketLoss,"SDLNet_UDP_SetPacketLoss"); 294 lib.bindSymbol(cast(void**)&SDLNet_UDP_Bind,"SDLNet_UDP_Bind"); 295 lib.bindSymbol(cast(void**)&SDLNet_UDP_Unbind,"SDLNet_UDP_Unbind"); 296 lib.bindSymbol(cast(void**)&SDLNet_UDP_GetPeerAddress,"SDLNet_UDP_GetPeerAddress"); 297 lib.bindSymbol(cast(void**)&SDLNet_UDP_SendV,"SDLNet_UDP_SendV"); 298 lib.bindSymbol(cast(void**)&SDLNet_UDP_Send,"SDLNet_UDP_Send"); 299 lib.bindSymbol(cast(void**)&SDLNet_UDP_RecvV,"SDLNet_UDP_RecvV"); 300 lib.bindSymbol(cast(void**)&SDLNet_UDP_Recv,"SDLNet_UDP_Recv"); 301 lib.bindSymbol(cast(void**)&SDLNet_UDP_Close,"SDLNet_UDP_Close"); 302 lib.bindSymbol(cast(void**)&SDLNet_AllocSocketSet,"SDLNet_AllocSocketSet"); 303 lib.bindSymbol(cast(void**)&SDLNet_AddSocket,"SDLNet_AddSocket"); 304 lib.bindSymbol(cast(void**)&SDLNet_DelSocket,"SDLNet_DelSocket"); 305 lib.bindSymbol(cast(void**)&SDLNet_CheckSockets,"SDLNet_CheckSockets"); 306 lib.bindSymbol(cast(void**)&SDLNet_FreeSocketSet,"SDLNet_FreeSocketSet"); 307 lib.bindSymbol(cast(void**)&SDLNet_SetError,"SDLNet_SetError"); 308 lib.bindSymbol(cast(void**)&SDLNet_GetError,"SDLNet_GetError"); 309 310 if(errorCount() == errCount) loadedVersion = sdlNetSupport; 311 312 return loadedVersion; 313 } 314 }