@@ -27,19 +27,24 @@ #import "OFCharacterSet.h" #import "OFLocale.h" #import "OFString.h" #import "OFException.h" /* For some E* -> WSAE* defines */ +#import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFLockFailedException.h" #import "OFUnlockFailedException.h" #import "socket.h" #import "socket_helpers.h" #ifdef OF_HAVE_THREADS -# include "mutex.h" +# ifndef OF_AMIGAOS +# import "mutex.h" +# else +# import "tlskey.h" +# endif #endif #include "once.h" #ifdef OF_AMIGAOS # include @@ -48,90 +53,172 @@ #ifdef OF_NINTENDO_3DS # include <3ds/types.h> # include <3ds/services/soc.h> #endif -#ifdef OF_HAVE_THREADS +#if defined(OF_HAVE_THREADS) && !defined(OF_AMIGAOS) static of_mutex_t mutex; #endif -#ifdef OF_AMIGAOS -/* TODO: Support multiple threads */ +#ifndef OF_AMIGAOS +static bool initSuccessful = false; +#else +# ifdef OF_HAVE_THREADS +of_tlskey_t of_socket_base_key; +# ifdef OF_AMIGAOS4 +of_tlskey_t of_socket_interface_key; +# endif +# else struct Library *SocketBase; -# ifdef OF_AMIGAOS4 +# ifdef OF_AMIGAOS4 struct SocketIFace *ISocket = NULL; +# endif +# endif +#endif + +#if defined(OF_HAVE_THREADS) && defined(OF_AMIGAOS) +OF_CONSTRUCTOR() +{ + if (!of_tlskey_new(&of_socket_base_key)) + @throw [OFInitializationFailedException exception]; + +# ifdef OF_AMIGAOS4 + if (!of_tlskey_new(&of_socket_interface_key)) + @throw [OFInitializationFailedException exception]; # endif +} #endif -static bool initSuccessful = false; +#if !defined(OF_AMIGAOS) || !defined(OF_HAVE_THREADS) static void init(void) { -#if defined(OF_WINDOWS) +# if defined(OF_WINDOWS) WSADATA wsa; if (WSAStartup(MAKEWORD(2, 0), &wsa)) return; -#elif defined(OF_AMIGAOS) +# elif defined(OF_AMIGAOS) if ((SocketBase = OpenLibrary("bsdsocket.library", 4)) == NULL) return; -# ifdef OF_AMIGAOS4 +# ifdef OF_AMIGAOS4 if ((ISocket = (struct SocketIFace *) GetInterface(SocketBase, "main", 1, NULL)) == NULL) { CloseLibrary(SocketBase); return; } -# endif -#elif defined(OF_WII) +# endif +# elif defined(OF_WII) if (net_init() < 0) return; -#elif defined(OF_NINTENDO_3DS) +# elif defined(OF_NINTENDO_3DS) void *ctx; if ((ctx = memalign(0x1000, 0x100000)) == NULL) return; if (socInit(ctx, 0x100000) != 0) return; atexit((void (*)(void))socExit); -#endif +# endif -#ifdef OF_HAVE_THREADS +# if defined(OF_HAVE_THREADS) && !defined(OF_AMIGAOS) if (!of_mutex_new(&mutex)) return; -# ifdef OF_WII +# ifdef OF_WII if (!of_spinlock_new(&spinlock)) return; +# endif # endif -#endif initSuccessful = true; } -#ifdef OF_AMIGAOS +# ifdef OF_AMIGAOS OF_DESTRUCTOR() { -# ifdef OF_AMIGAOS4 +# ifdef OF_AMIGAOS4 if (ISocket != NULL) DropInterface((struct Interface *)ISocket); -# endif +# endif if (SocketBase != NULL) CloseLibrary(SocketBase); } +# endif #endif bool -of_socket_init() +of_socket_init(void) { +#if !defined(OF_AMIGAOS) || !defined(OF_HAVE_THREADS) static of_once_t onceControl = OF_ONCE_INIT; of_once(&onceControl, init); return initSuccessful; +#else + struct Library *socketBase; +# ifdef OF_AMIGAOS4 + struct SocketIFace *socketInterface; +# endif + +# ifdef OF_AMIGAOS4 + if ((socketInterface = of_tlskey_get(of_socket_interface_key)) != NULL) +# else + if ((socketBase = of_tlskey_get(of_socket_base_key)) != NULL) +# endif + return true; + + if ((socketBase = OpenLibrary("bsdsocket.library", 4)) == NULL) + return false; + +# ifdef OF_AMIGAOS4 + if ((socketInterface = (struct SocketIFace *) + GetInterface(socketBase, "main", 1, NULL)) == NULL) { + CloseLibrary(socketBase); + return false; + } +# endif + + if (!of_tlskey_set(of_socket_base_key, socketBase)) { + CloseLibrary(socketBase); +# ifdef OF_AMIGAOS4 + DropInterface((struct Interface *)socketInterface); +# endif + return false; + } + +# ifdef OF_AMIGAOS4 + if (!of_tlskey_set(of_socket_interface_key, socketInterface)) { + CloseLibrary(socketBase); + DropInterface((struct Interface *)socketInterface); + return false; + } +# endif + + return true; +#endif +} + +#if defined(OF_HAVE_THREADS) && defined(OF_AMIGAOS) +void +of_socket_deinit(void) +{ + struct Library *socketBase = of_tlskey_get(of_socket_base_key); +# ifdef OF_AMIGAOS4 + struct SocketIFace *socketInterface = + of_tlskey_get(of_socket_interface_key); + + if (socketInterface != NULL) + DropInterface((struct Interface *)socketInterface); +# endif + if (socketBase != NULL) + CloseLibrary(socketBase); } +#endif int of_socket_errno() { #if defined(OF_WINDOWS) @@ -237,19 +324,19 @@ of_getsockname(of_socket_t sock, struct sockaddr *restrict addr, socklen_t *restrict addrLen) { int ret; -# ifdef OF_HAVE_THREADS +# if defined(OF_HAVE_THREADS) && !defined(OF_AMIGAOS) if (!of_mutex_lock(&mutex)) @throw [OFLockFailedException exception]; # endif ret = getsockname(sock, addr, addrLen); -# ifdef OF_HAVE_THREADS +# if defined(OF_HAVE_THREADS) && !defined(OF_AMIGAOS) if (!of_mutex_unlock(&mutex)) @throw [OFUnlockFailedException exception]; # endif return ret;