1 2 // Copyright Michael D. Parker 2018. 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 bindbc.sdl.bind.sdlstdinc; 14 import bindbc.sdl.bind.sdlversion : SDL_version; 15 16 enum SDLNetSupport { 17 noLibrary, 18 badLibrary, 19 sdlNet200 = 200, 20 sdlNet201 = 201, 21 } 22 23 enum ubyte SDL_NET_MAJOR_VERSION = 2; 24 enum ubyte SDL_NET_MINOR_VERSION = 0; 25 26 version(SDL_Net_201) { 27 enum sdlNetSupport = SDLNetSupport.sdlNet201; 28 enum SDL_NET_PATCHLEVEL = 1; 29 } 30 else { 31 enum sdlNetSupport = SDLNetSupport.sdlNet200; 32 enum SDL_NET_PATCHLEVEL = 0; 33 } 34 35 alias SDLNet_Version = SDL_version; 36 37 @nogc nothrow void SDL_NET_VERSION(SDL_version* X) { 38 X.major = SDL_NET_MAJOR_VERSION; 39 X.minor = SDL_NET_MINOR_VERSION; 40 X.patch = SDL_NET_PATCHLEVEL; 41 } 42 43 struct IPaddress { 44 Uint32 host; 45 Uint16 port; 46 } 47 48 enum { 49 INADDR_ANY = 0x00000000, 50 INADDR_NONE = 0xFFFFFFFF, 51 INADDR_LOOPBACK = 0x7f000001, 52 INADDR_BROADCAST = 0xFFFFFFFF, 53 } 54 55 alias TCPsocket = void*; 56 57 enum SDLNET_MAX_UDPCHANNELS = 32; 58 enum SDLNET_MAX_UDPADRESSES = 4; 59 60 alias UDPsocket = void*; 61 62 struct UDPpacket { 63 int channel; 64 Uint8* data; 65 int len; 66 int maxlen; 67 int status; 68 IPaddress address; 69 } 70 71 struct _SDLNet_SocketSet; 72 alias _SDLNet_SocketSet* SDLNet_SocketSet; 73 74 struct _SDLNet_GenericSocket { 75 int ready; 76 } 77 alias SDLNet_GenericSocket = _SDLNet_GenericSocket*; 78 79 @nogc nothrow { 80 int SDLNet_TCP_AddSocket(SDLNet_SocketSet set,void* sock) { 81 return SDLNet_AddSocket(set,cast(SDLNet_GenericSocket)sock); 82 } 83 alias SDLNet_UDP_AddSocket = SDLNet_TCP_AddSocket; 84 85 int SDLNet_TCP_DelSocket(SDLNet_SocketSet set,void* sock) { 86 return SDLNet_DelSocket(set,cast(SDLNet_GenericSocket)sock); 87 } 88 alias SDLNet_UDP_DelSocket = SDLNet_TCP_DelSocket; 89 90 bool SDLNet_SocketReady(void* sock) { 91 return sock && (cast(SDLNet_GenericSocket)sock).ready != 0; 92 } 93 } 94 95 static if(staticBinding) { 96 extern(C) @nogc nothrow { 97 const(SDLNet_Version)* SDLNet_Linked_Version(); 98 int SDLNet_Init(); 99 void SDLNet_Quit(); 100 int SDLNet_ResolveHost(IPaddress*,const(char)*,Uint16); 101 const(char)* SDLNet_ResolveIP(const(IPaddress)*); 102 int SDLNet_GetLocalAddresses(IPaddress*,int); 103 TCPsocket SDLNet_TCP_Open(IPaddress*); 104 TCPsocket SDLNet_TCP_Accept(TCPsocket); 105 IPaddress* SDLNet_TCP_GetPeerAddress(TCPsocket); 106 int SDLNet_TCP_Send(TCPsocket,const(void)*,int); 107 int SDLNet_TCP_Recv(TCPsocket,void*,int); 108 void SDLNet_TCP_Close(TCPsocket); 109 UDPpacket* SDLNet_AllocPacket(int); 110 int SDLNet_ResizePacket(UDPpacket*,int); 111 void SDLNet_FreePacket(UDPpacket*); 112 UDPpacket** SDLNet_AllocPacketV(int,int); 113 void SDLNet_FreePacketV(UDPpacket**); 114 UDPsocket SDLNet_UDP_Open(Uint16); 115 void SDLNet_UDP_SetPacketLoss(UDPsocket,int); 116 int SDLNet_UDP_Bind(UDPsocket,int,const(IPaddress)*); 117 void SDLNet_UDP_Unbind(UDPsocket,int); 118 IPaddress* SDLNet_UDP_GetPeerAddress(UDPsocket,int); 119 int SDLNet_UDP_SendV(UDPsocket,UDPpacket**,int); 120 int SDLNet_UDP_Send(UDPsocket,int,UDPpacket*); 121 int SDLNet_UDP_RecvV(UDPsocket,UDPpacket**); 122 int SDLNet_UDP_Recv(UDPsocket,UDPpacket*); 123 void SDLNet_UDP_Close(UDPsocket); 124 SDLNet_SocketSet SDLNet_AllocSocketSet(int); 125 int SDLNet_AddSocket(SDLNet_SocketSet,SDLNet_GenericSocket); 126 int SDLNet_DelSocket(SDLNet_SocketSet,SDLNet_GenericSocket); 127 int SDLNet_CheckSockets(SDLNet_SocketSet,Uint32); 128 void SDLNet_FreeSocketSet(SDLNet_SocketSet); 129 void SDLNet_SetError(const(char)* fmt,...); 130 const(char)* SDLNet_GetError(); 131 } 132 } 133 else { 134 import bindbc.loader; 135 136 extern(C) @nogc nothrow { 137 alias pSDLNet_Linked_Version = const(SDLNet_Version)* function(); 138 alias pSDLNet_Init = int function(); 139 alias pSDLNet_Quit = void function(); 140 alias pSDLNet_ResolveHost = int function(IPaddress*,const(char)*,Uint16); 141 alias pSDLNet_ResolveIP = const(char)* function(const(IPaddress)*); 142 alias pSDLNet_GetLocalAddresses = int function(IPaddress*,int); 143 alias pSDLNet_TCP_Open = TCPsocket function(IPaddress*); 144 alias pSDLNet_TCP_Accept = TCPsocket function(TCPsocket); 145 alias pSDLNet_TCP_GetPeerAddress = IPaddress* function(TCPsocket); 146 alias pSDLNet_TCP_Send = int function(TCPsocket,const(void)*,int); 147 alias pSDLNet_TCP_Recv = int function(TCPsocket,void*,int); 148 alias pSDLNet_TCP_Close = void function(TCPsocket); 149 alias pSDLNet_AllocPacket = UDPpacket* function(int); 150 alias pSDLNet_ResizePacket = int function(UDPpacket*,int); 151 alias pSDLNet_FreePacket = void function(UDPpacket*); 152 alias pSDLNet_AllocPacketV = UDPpacket** function(int,int); 153 alias pSDLNet_FreePacketV = void function(UDPpacket**); 154 alias pSDLNet_UDP_Open = UDPsocket function(Uint16); 155 alias pSDLNet_UDP_SetPacketLoss = void function(UDPsocket,int); 156 alias pSDLNet_UDP_Bind = int function(UDPsocket,int,const(IPaddress)*); 157 alias pSDLNet_UDP_Unbind = void function(UDPsocket,int); 158 alias pSDLNet_UDP_GetPeerAddress = IPaddress* function(UDPsocket,int); 159 alias pSDLNet_UDP_SendV = int function(UDPsocket,UDPpacket**,int); 160 alias pSDLNet_UDP_Send = int function(UDPsocket,int,UDPpacket*); 161 alias pSDLNet_UDP_RecvV = int function(UDPsocket,UDPpacket**); 162 alias pSDLNet_UDP_Recv = int function(UDPsocket,UDPpacket*); 163 alias pSDLNet_UDP_Close = void function(UDPsocket); 164 alias pSDLNet_AllocSocketSet = SDLNet_SocketSet function(int); 165 alias pSDLNet_AddSocket = int function(SDLNet_SocketSet,SDLNet_GenericSocket); 166 alias pSDLNet_DelSocket = int function(SDLNet_SocketSet,SDLNet_GenericSocket); 167 alias pSDLNet_CheckSockets = int function(SDLNet_SocketSet,Uint32); 168 alias pSDLNet_FreeSocketSet = void function(SDLNet_SocketSet); 169 alias pSDLNet_SetError = void function(const(char)* fmt,...); 170 alias pSDLNet_GetError = const(char)* function(); 171 } 172 173 __gshared { 174 pSDLNet_Linked_Version SDLNet_Linked_Version; 175 pSDLNet_Init SDLNet_Init; 176 pSDLNet_Quit SDLNet_Quit; 177 pSDLNet_ResolveHost SDLNet_ResolveHost; 178 pSDLNet_ResolveIP SDLNet_ResolveIP; 179 pSDLNet_GetLocalAddresses SDLNet_GetLocalAddresses; 180 pSDLNet_TCP_Open SDLNet_TCP_Open; 181 pSDLNet_TCP_Accept SDLNet_TCP_Accept; 182 pSDLNet_TCP_GetPeerAddress SDLNet_TCP_GetPeerAddress; 183 pSDLNet_TCP_Send SDLNet_TCP_Send; 184 pSDLNet_TCP_Recv SDLNet_TCP_Recv; 185 pSDLNet_TCP_Close SDLNet_TCP_Close; 186 pSDLNet_AllocPacket SDLNet_AllocPacket; 187 pSDLNet_ResizePacket SDLNet_ResizePacket; 188 pSDLNet_FreePacket SDLNet_FreePacket; 189 pSDLNet_AllocPacketV SDLNet_AllocPacketV; 190 pSDLNet_FreePacketV SDLNet_FreePacketV; 191 pSDLNet_UDP_Open SDLNet_UDP_Open; 192 pSDLNet_UDP_SetPacketLoss SDLNet_UDP_SetPacketLoss; 193 pSDLNet_UDP_Bind SDLNet_UDP_Bind; 194 pSDLNet_UDP_Unbind SDLNet_UDP_Unbind; 195 pSDLNet_UDP_GetPeerAddress SDLNet_UDP_GetPeerAddress; 196 pSDLNet_UDP_SendV SDLNet_UDP_SendV; 197 pSDLNet_UDP_Send SDLNet_UDP_Send; 198 pSDLNet_UDP_RecvV SDLNet_UDP_RecvV; 199 pSDLNet_UDP_Recv SDLNet_UDP_Recv; 200 pSDLNet_UDP_Close SDLNet_UDP_Close; 201 pSDLNet_AllocSocketSet SDLNet_AllocSocketSet; 202 pSDLNet_AddSocket SDLNet_AddSocket; 203 pSDLNet_DelSocket SDLNet_DelSocket; 204 pSDLNet_CheckSockets SDLNet_CheckSockets; 205 pSDLNet_FreeSocketSet SDLNet_FreeSocketSet; 206 pSDLNet_SetError SDLNet_SetError; 207 pSDLNet_GetError SDLNet_GetError; 208 } 209 210 private { 211 SharedLib lib; 212 SDLNetSupport loadedVersion; 213 } 214 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 }