]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
amigaos: fix threaded resolver on AmigaOS 4.x
authorFutaura <oliver@futaura.co.uk>
Sun, 7 Aug 2022 13:42:19 +0000 (14:42 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 10 Aug 2022 12:14:27 +0000 (14:14 +0200)
Replace ip4 resolution function on AmigaOS 4.x, as it requires runtime
feature detection and extra code to make it thread safe.

Closes #9265

lib/amigaos.c
lib/amigaos.h
lib/curl_setup.h
lib/easy.c
lib/hostip4.c

index d26cd1da18a414094a68ab604e57bd555a8978d8..dcc5316f0ffc26d488f37e304fe2bac2a488abf0 100644 (file)
 #include "curl_setup.h"
 
 #ifdef __AMIGA__
-#  include "amigaos.h"
-#  if defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL)
+
+#include "hostip.h"
+#include "amigaos.h"
+
+#ifdef HAVE_PROTO_BSDSOCKET_H
+#  if defined(__amigaos4__)
+#    include <bsdsocket/socketbasetags.h>
+#  elif !defined(USE_AMISSL)
 #    include <amitcp/socketbasetags.h>
 #  endif
 #  ifdef __libnix__
 #include "curl_memory.h"
 #include "memdebug.h"
 
-#ifdef __AMIGA__
+#ifdef HAVE_PROTO_BSDSOCKET_H
 
 #ifdef __amigaos4__
+/*
+ * AmigaOS 4.x specific code
+ */
+
+/*
+ * hostip4.c - Curl_ipv4_resolve_r() replacement code
+ *
+ * Logic that needs to be considered are the following build cases:
+ * - newlib networking
+ * - clib2 networking
+ * - direct bsdsocket.library networking (usually AmiSSL builds)
+ * Each with the threaded resolver enabled or not.
+ *
+ * With the threaded resolver enabled, try to use gethostbyname_r() where
+ * available, otherwise (re)open bsdsocket.library and fallback to
+ * gethostbyname().
+ */
+
+#include <proto/bsdsocket.h>
+
+static struct SocketIFace *__CurlISocket = NULL;
+static uint32 SocketFeatures = 0;
+
+#define HAVE_BSDSOCKET_GETHOSTBYNAME_R 0x01
+#define HAVE_BSDSOCKET_GETADDRINFO     0x02
+
+CURLcode Curl_amiga_init(void)
+{
+  struct SocketIFace *ISocket;
+  struct Library *base = OpenLibrary("bsdsocket.library", 4);
+
+  if(base) {
+    ISocket = (struct SocketIFace *)GetInterface(base, "main", 1, NULL);
+    if(ISocket) {
+      ULONG enabled = 0;
+
+      SocketBaseTags(SBTM_SETVAL(SBTC_CAN_SHARE_LIBRARY_BASES), TRUE,
+                     SBTM_GETREF(SBTC_HAVE_GETHOSTADDR_R_API), (ULONG)&enabled,
+                     TAG_DONE);
+
+      if(enabled) {
+        SocketFeatures |= HAVE_BSDSOCKET_GETHOSTBYNAME_R;
+      }
+
+      __CurlISocket = ISocket;
+
+      atexit(Curl_amiga_cleanup);
+
+      return CURLE_OK;
+    }
+    CloseLibrary(base);
+  }
+
+  return CURLE_FAILED_INIT;
+}
+
+void Curl_amiga_cleanup(void)
+{
+  if(__CurlISocket) {
+    struct Library *base = __CurlISocket->Data.LibBase;
+    DropInterface((struct Interface *)__CurlISocket);
+    CloseLibrary(base);
+    __CurlISocket = NULL;
+  }
+}
+
+#ifdef CURLRES_AMIGA
+/*
+ * Because we need to handle the different cases in hostip4.c at run-time,
+ * not at compile-time, based on what was detected in Curl_amiga_init(),
+ * we replace it completely with our own as to not complicate the baseline
+ * code. Assumes malloc/calloc/free are thread safe because Curl_he2ai()
+ * allocates memory also.
+ */
+
+struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
+                                          int port)
+{
+  struct Curl_addrinfo *ai = NULL;
+  struct hostent *h;
+  struct SocketIFace *ISocket = __CurlISocket;
+
+  if(SocketFeatures & HAVE_BSDSOCKET_GETHOSTBYNAME_R) {
+    LONG h_errnop = 0;
+    struct hostent *buf;
+
+    buf = calloc(1, CURL_HOSTENT_SIZE);
+    if(buf) {
+      h = gethostbyname_r((STRPTR)hostname, buf,
+                          (char *)buf + sizeof(struct hostent),
+                          CURL_HOSTENT_SIZE - sizeof(struct hostent),
+                          &h_errnop);
+      if(h) {
+        ai = Curl_he2ai(h, port);
+      }
+      free(buf);
+    }
+  }
+  else {
+    #ifdef CURLRES_THREADED
+    /* gethostbyname() is not thread safe, so we need to reopen bsdsocket
+     * on the thread's context
+     */
+    struct Library *base = OpenLibrary("bsdsocket.library", 4);
+    if(base) {
+      ISocket = (struct SocketIFace *)GetInterface(base, "main", 1, NULL);
+      if(ISocket) {
+        h = gethostbyname((STRPTR)hostname);
+        if(h) {
+          ai = Curl_he2ai(h, port);
+        }
+        DropInterface((struct Interface *)ISocket);
+      }
+      CloseLibrary(base);
+    }
+    #else
+    /* not using threaded resolver - safe to use this as-is */
+    h = gethostbyname(hostname);
+    if(h) {
+      ai = Curl_he2ai(h, port);
+    }
+    #endif
+  }
+
+  return ai;
+}
+#endif /* CURLRES_AMIGA */
 
 #ifdef USE_AMISSL
 int Curl_amiga_select(int nfds, fd_set *readfds, fd_set *writefds,
@@ -54,7 +187,11 @@ int Curl_amiga_select(int nfds, fd_set *readfds, fd_set *writefds,
 }
 #endif /* USE_AMISSL */
 
-#elif defined(HAVE_PROTO_BSDSOCKET_H) && !defined(USE_AMISSL)
+#elif !defined(USE_AMISSL) /* __amigaos4__ */
+/*
+ * Amiga OS3 specific code
+ */
+
 struct Library *SocketBase = NULL;
 extern int errno, h_errno;
 
@@ -64,7 +201,7 @@ void __request(const char *msg);
 # define __request(msg)       Printf(msg "\n\a")
 #endif
 
-void Curl_amiga_cleanup()
+void Curl_amiga_cleanup(void)
 {
   if(SocketBase) {
     CloseLibrary(SocketBase);
@@ -72,35 +209,36 @@ void Curl_amiga_cleanup()
   }
 }
 
-bool Curl_amiga_init()
+CURLcode Curl_amiga_init(void)
 {
   if(!SocketBase)
     SocketBase = OpenLibrary("bsdsocket.library", 4);
 
   if(!SocketBase) {
     __request("No TCP/IP Stack running!");
-    return FALSE;
+    return CURLE_FAILED_INIT;
   }
 
   if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG) &errno,
                     SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG) "curl",
                     TAG_DONE)) {
     __request("SocketBaseTags ERROR");
-    return FALSE;
+    return CURLE_FAILED_INIT;
   }
 
 #ifndef __libnix__
   atexit(Curl_amiga_cleanup);
 #endif
 
-  return TRUE;
+  return CURLE_OK;
 }
 
 #ifdef __libnix__
 ADD2EXIT(Curl_amiga_cleanup, -50);
 #endif
 
+#endif /* !USE_AMISSL */
+
 #endif /* HAVE_PROTO_BSDSOCKET_H */
 
 #endif /* __AMIGA__ */
-
index 5255194dc7454ddccd461bc578d254c0b63e83a4..9abfb59eac643dcd2797dd89398a157a7c5064d4 100644 (file)
  ***************************************************************************/
 #include "curl_setup.h"
 
-#if defined(__AMIGA__) && defined(HAVE_BSDSOCKET_H) && !defined(USE_AMISSL)
+#if defined(__AMIGA__) && defined(HAVE_PROTO_BSDSOCKET_H) && \
+  (!defined(USE_AMISSL) || defined(__amigaos4__))
 
-bool Curl_amiga_init();
-void Curl_amiga_cleanup();
+CURLcode Curl_amiga_init(void);
+void Curl_amiga_cleanup(void);
 
 #else
 
-#define Curl_amiga_init() 1
+#define Curl_amiga_init() CURLE_OK
 #define Curl_amiga_cleanup() Curl_nop_stmt
 
 #endif
index 85d586180ecce89045c4607a941e08f3388d6a17..e5356dcc92438381526a82d4d9a4e3a4e9261751 100644 (file)
 #endif
 
 #ifdef __AMIGA__
+#  ifdef __amigaos4__
+#    define __USE_INLINE__
+     /* use our own resolver which uses runtime feature detection */
+#    define CURLRES_AMIGA
+     /* getaddrinfo() currently crashes bsdsocket.library, so disable */
+#    undef HAVE_GETADDRINFO
+#    if !(defined(__NEWLIB__) || \
+          (defined(__CLIB2__) && defined(__THREAD_SAFE)))
+       /* disable threaded resolver with clib2 - requires newlib or clib-ts */
+#      undef USE_THREADS_POSIX
+#    endif
+#  endif
 #  include <exec/types.h>
 #  include <exec/execbase.h>
 #  include <proto/exec.h>
index 06a94b01b03f8c5425a7fb36b4e872eb28dfcfef..e17a461e8449f380acd386421967efc36bbb64ce 100644 (file)
@@ -177,7 +177,7 @@ static CURLcode global_init(long flags, bool memoryfuncs)
 #endif
 
 #ifdef __AMIGA__
-  if(!Curl_amiga_init()) {
+  if(Curl_amiga_init()) {
     DEBUGF(fprintf(stderr, "Error: Curl_amiga_init failed\n"));
     goto fail;
   }
index 47da6055a958fcb2430d079b6f1d3a908f7ea9a0..1dd54e879dbb6d274175438fa08766c24a14fa76 100644 (file)
@@ -112,7 +112,8 @@ struct Curl_addrinfo *Curl_getaddrinfo(struct Curl_easy *data,
 #endif /* CURLRES_SYNCH */
 #endif /* CURLRES_IPV4 */
 
-#if defined(CURLRES_IPV4) && !defined(CURLRES_ARES)
+#if defined(CURLRES_IPV4) && \
+   !defined(CURLRES_ARES) && !defined(CURLRES_AMIGA)
 
 /*
  * Curl_ipv4_resolve_r() - ipv4 threadsafe resolver function.
@@ -297,4 +298,5 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
 
   return ai;
 }
-#endif /* defined(CURLRES_IPV4) && !defined(CURLRES_ARES) */
+#endif /* defined(CURLRES_IPV4) && !defined(CURLRES_ARES) &&
+                                   !defined(CURLRES_AMIGA) */