Sterling Hughes brings the share interface
authorDaniel Stenberg <daniel@haxx.se>
Tue, 13 Aug 2002 14:20:47 +0000 (14:20 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 13 Aug 2002 14:20:47 +0000 (14:20 +0000)
include/curl/curl.h
lib/Makefile.am
lib/share.c [new file with mode: 0644]
lib/share.h [new file with mode: 0644]
lib/url.c
lib/urldata.h

index 6c4722f606e413201d39701c5c39fceec897490a..7c7a47f9c382f886ab032e890a01782f3fae6c9b 100644 (file)
@@ -192,10 +192,11 @@ typedef enum {
   CURLE_SSL_PEER_CERTIFICATE,    /* 51 - peer's certificate wasn't ok */
   CURLE_GOT_NOTHING,             /* 52 - when this is a specific error */
   CURLE_SSL_ENGINE_NOTFOUND,     /* 53 - SSL crypto engine not found */
-  CURLE_SSL_ENGINE_SETFAILED,    /* 54 - can not set SSL crypto engine as default */
+  CURLE_SSL_ENGINE_SETFAILED,    /* 54 - can not set SSL crypto engine as
+                                    default */
   CURLE_SEND_ERROR,              /* 55 - failed sending network data */
   CURLE_RECV_ERROR,              /* 56 - failure in receiving network data */
-
+  CURLE_SHARE_IN_USE,            /* 57 - share is in use */
   CURL_LAST /* never use! */
 } CURLcode;
 
@@ -562,9 +563,13 @@ typedef enum {
   /* Instruct libcurl to use a smaller receive buffer */
   CINIT(BUFFERSIZE, LONG, 98),
 
-  /* Instruct libcurl to do not use any signal/alarm handlers, even with timeouts. */
+  /* Instruct libcurl to never use any signal/alarm handlers, even with
+     timeouts. */
   CINIT(NOSIGNAL, LONG, 99),
   
+  /* Provide a CURLShare for mutexing non-ts data */
+  CINIT(SHARE, OBJECTPOINT, 100),
+
   CURLOPT_LASTENTRY /* the last unusued */
 } CURLoption;
 
@@ -839,6 +844,41 @@ typedef enum {
 #define CURL_GLOBAL_NOTHING 0
 #define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL
 
+
+/*****************************************************************************
+ * Setup defines, protos etc for the sharing stuff.
+ */
+
+/* Different types of locks that a share can aquire */
+typedef enum {
+  CURL_LOCK_TYPE_NONE = 0,
+  CURL_LOCK_TYPE_COOKIE = 1<<0,
+  CURL_LOCK_TYPE_DNS = 1<<1,
+  CURL_LOCK_TYPE_SSL_SESSION = 2<<1,
+  CURL_LOCK_TYPE_CONNECT = 2<<2,
+  CURL_LOCK_TYPE_LAST
+} curl_lock_type;
+
+typedef void (*curl_lock_function)(CURL *, curl_lock_type, void *);
+typedef void (*curl_unlock_function)(CURL *, curl_lock_type, void *);
+
+typedef struct {
+  unsigned int specifier;
+  unsigned int locked;
+  unsigned int dirty;
+  
+  curl_lock_function lockfunc;
+  curl_unlock_function unlockfunc;
+  void *clientdata;
+} curl_share;
+
+curl_share *curl_share_init (void);
+CURLcode curl_share_setopt (curl_share *, curl_lock_type, int);
+CURLcode curl_share_set_lock_function (curl_share *, curl_lock_function);
+CURLcode curl_share_set_unlock_function (curl_share *, curl_unlock_function);
+CURLcode curl_share_set_lock_data (curl_share *, void *);
+CURLcode curl_share_destroy (curl_share *);
+
 #ifdef  __cplusplus
 }
 #endif
index 3efcdf2c2de09b01508e5f27bdd4f0272a84194b..2f03a859279557277dcc73f3785afa213d81634c 100644 (file)
@@ -60,7 +60,7 @@ escape.h       getpass.c      netrc.c        telnet.h       \
 getinfo.c getinfo.h transfer.c strequal.c strequal.h easy.c \
 security.h security.c krb4.c krb4.h memdebug.c memdebug.h inet_ntoa_r.h \
 http_chunks.c http_chunks.h strtok.c strtok.h connect.c connect.h \
-llist.c llist.h hash.c hash.h multi.c
+llist.c llist.h hash.c hash.h multi.c share.c share.h
 
 
 noinst_HEADERS = setup.h transfer.h
diff --git a/lib/share.c b/lib/share.c
new file mode 100644 (file)
index 0000000..1050e50
--- /dev/null
@@ -0,0 +1,169 @@
+/*****************************************************************************
+ *                                  _   _ ____  _     
+ *  Project                     ___| | | |  _ \| |    
+ *                             / __| | | | |_) | |    
+ *                            | (__| |_| |  _ <| |___ 
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * In order to be useful for every potential user, curl and libcurl are
+ * dual-licensed under the MPL and the MIT/X-derivate licenses.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the MPL or the MIT/X-derivate
+ * licenses. You may pick one of these licenses.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * $Id$
+ *****************************************************************************/
+
+#include "setup.h"
+#include <stdlib.h>
+#include <curl/curl.h>
+#include "share.h"
+#include "urldata.h"
+
+/* The last #include file should be: */
+#ifdef MALLOCDEBUG
+#include "memdebug.h"
+#endif
+
+#define CURL_SHARE_SET_LOCKED(__share, __type) ((__share)->locked += (__type))
+#define CURL_SHARE_SET_UNLOCKED(__share, __type) ((__share)->locked -= (__type))
+
+#define CURL_SHARE_SET_USED(__share, __type) ((__share)->specifier += (__type))
+#define CURL_SHARE_SET_UNUSED(__share, __type) ((__share)->specifier -= (__type))
+#define CURL_SHARE_IS_USED(__share, __type) ((__share)->specifier & (__type))
+#define CURL_SHARE_IS_LOCKED(__share, __type) ((__share)->locked & (__type))
+
+#define CURL_SHARE_IS_DIRTY(__share) ((__share)->dirty)
+
+#define CURL_SHARE_GET(__handle) (((struct SessionHandle *) (__handle))->share)
+
+curl_share *
+curl_share_init (void)
+{
+  curl_share *share = (curl_share *) malloc (sizeof (curl_share));
+  if (share) {
+    memset (share, 0, sizeof (curl_share));
+  }
+
+  return share;
+}
+
+CURLcode 
+curl_share_setopt (curl_share *share, curl_lock_type option, int enable)
+{
+  if (CURL_SHARE_IS_DIRTY(share)) {
+    return CURLE_SHARE_IN_USE;
+  }
+
+  if (enable) {
+    CURL_SHARE_SET_USED (share, option);
+  }
+  else {
+    CURL_SHARE_SET_UNUSED (share, option);
+  }
+
+  return CURLE_OK;
+}
+
+CURLcode
+curl_share_set_lock_function (curl_share *share, curl_lock_function lock)
+{
+  if (CURL_SHARE_IS_DIRTY(share)) {
+    return CURLE_SHARE_IN_USE;
+  }
+
+  share->lockfunc = lock;
+  return CURLE_OK;
+}
+
+CURLcode
+curl_share_set_unlock_function (curl_share *share, curl_unlock_function unlock)
+{
+  if (CURL_SHARE_IS_DIRTY(share)) {
+    return CURLE_SHARE_IN_USE;
+  }
+
+  share->unlockfunc = unlock;
+  return CURLE_OK;
+}
+
+CURLcode
+curl_share_set_lock_data (curl_share *share, void *data) 
+{
+  if (CURL_SHARE_IS_DIRTY(share)) {
+    return CURLE_SHARE_IN_USE;
+  }
+
+  share->clientdata = data;
+  return CURLE_OK;
+}
+
+Curl_share_error 
+Curl_share_acquire_lock (CURL *handle, curl_lock_type type)
+{
+  curl_share *share = CURL_SHARE_GET (handle);
+  if (share == NULL) {
+    return SHARE_ERROR_INVALID;
+  }
+
+  if (! (share->specifier & type)) {
+    return SHARE_ERROR_NOT_REGISTERED;
+  }
+
+  if (CURL_SHARE_IS_LOCKED (share, type)) {
+    return SHARE_ERROR_OK;
+  }
+
+  share->lockfunc (handle, type, share->clientdata);
+  CURL_SHARE_SET_LOCKED (share, type);
+
+  return SHARE_ERROR_OK;
+}
+
+Curl_share_error 
+Curl_share_release_lock (CURL *handle, curl_lock_type type)
+{
+  curl_share *share = CURL_SHARE_GET(handle);
+  if (share == NULL) {
+    return SHARE_ERROR_INVALID;
+  }
+
+  if (! (share->specifier & type)) {
+    return SHARE_ERROR_NOT_REGISTERED;
+  }
+
+  if (!CURL_SHARE_IS_LOCKED (share, type)) {
+    return SHARE_ERROR_OK;
+  }
+
+  share->unlockfunc (handle, type, share->clientdata);
+  CURL_SHARE_SET_UNLOCKED (share, type);
+
+  return SHARE_ERROR_OK;
+}
+
+CURLcode curl_share_destroy (curl_share *share)
+{
+  if (CURL_SHARE_IS_DIRTY(share)) {
+    return CURLE_SHARE_IN_USE;
+  }
+
+  free (share);
+  
+  return CURLE_OK;
+}
+
+/*
+ * local variables:
+ * eval: (load-file "../curl-mode.el")
+ * end:
+ * vim600: fdm=marker
+ * vim: et sw=2 ts=2 sts=2 tw=78
+ */
diff --git a/lib/share.h b/lib/share.h
new file mode 100644 (file)
index 0000000..5550c64
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __CURL_SHARE_H
+#define __CURL_SHARE_H
+
+/*****************************************************************************
+ *                                  _   _ ____  _     
+ *  Project                     ___| | | |  _ \| |    
+ *                             / __| | | | |_) | |    
+ *                            | (__| |_| |  _ <| |___ 
+ *                             \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2002, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * In order to be useful for every potential user, curl and libcurl are
+ * dual-licensed under the MPL and the MIT/X-derivate licenses.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the MPL or the MIT/X-derivate
+ * licenses. You may pick one of these licenses.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ * $Id$
+ *****************************************************************************/
+
+#include "setup.h"
+#include <curl/curl.h>
+
+typedef enum {
+  SHARE_ERROR_OK = 0,
+  SHARE_ERROR_INVALID, 
+  SHARE_ERROR_NOT_REGISTERED,
+  SHARE_ERROR_LAST
+} Curl_share_error;
+
+Curl_share_error Curl_share_aquire_lock (CURL *, curl_lock_type);
+Curl_share_error Curl_share_release_lock (CURL *, curl_lock_type);
+
+#endif /* __CURL_SHARE_H */
+
+/*
+ * local variables:
+ * eval: (load-file "../curl-mode.el")
+ * end:
+ * vim600: fdm=marker
+ * vim: et sw=2 ts=2 sts=2 tw=78
+ */
index ead5eb494f12f81d66cbd1fade96c93ff5236011..08180efa9d80c3681dac8eacd5d355db31897722 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -178,6 +178,10 @@ CURLcode Curl_close(struct SessionHandle *data)
   Curl_SSL_Close_All(data);
 #endif
 
+  /* No longer a dirty share, if it exists */
+  if (data->share)
+    data->share->dirty--;
+
   if(data->state.auth_host)
     free(data->state.auth_host);
 
@@ -1032,6 +1036,18 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)
     data->set.no_signal = va_arg(param, long) ? TRUE : FALSE;
     break;
 
+  case CURLOPT_SHARE:
+    {
+      curl_share *set;
+      set = va_arg(param, curl_share *);
+      if(data->share)
+        data->share->dirty--;
+
+      data->share = set;
+      data->share->dirty++;
+    }
+    break;
+
   default:
     /* unknown tag and its companion, just ignore: */
     return CURLE_FAILED_INIT; /* correct this */
index 44a4a72007a6adfc944d3ac485c10c638986f91d..dece629fdaa798fcfe1cd1997746e863ad974c21 100644 (file)
@@ -694,7 +694,8 @@ struct UserDefined {
  * 'struct urlstate' instead.  */
 
 struct SessionHandle {
-  curl_hash          *hostcache;
+  curl_hash *hostcache;
+  curl_share *share;           /* Share, handles global variable mutexing */
   struct UserDefined set;      /* values set by the libcurl user */
   struct DynamicStatic change; /* possibly modified userdefined data */