make DavContext mt-safe

Thu, 01 Feb 2024 10:41:39 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Thu, 01 Feb 2024 10:41:39 +0100
changeset 805
bff983370565
parent 804
1e24f187c362
child 806
673a803d2203

make DavContext mt-safe

libidav/config.c file | annotate | diff | comparison | revisions
libidav/session.c file | annotate | diff | comparison | revisions
libidav/webdav.c file | annotate | diff | comparison | revisions
libidav/webdav.h file | annotate | diff | comparison | revisions
make/vs/libidav/libidav.vcxproj file | annotate | diff | comparison | revisions
make/vs/libidav/libidav.vcxproj.filters file | annotate | diff | comparison | revisions
--- a/libidav/config.c	Mon Jan 29 11:20:34 2024 +0100
+++ b/libidav/config.c	Thu Feb 01 10:41:39 2024 +0100
@@ -579,6 +579,9 @@
         stype = "https";
     } else if(type == DAV_HTTP_PROXY) {
         stype = "http";
+    } else {
+        fprintf(stderr, "unknown proxy type\n");
+        return 1;
     }
     
     if(!proxy) {
--- a/libidav/session.c	Mon Jan 29 11:20:34 2024 +0100
+++ b/libidav/session.c	Thu Feb 01 10:41:39 2024 +0100
@@ -94,7 +94,7 @@
     curl_easy_setopt(sn->handle, CURLOPT_URL, base_url);
     
     // add to context
-    cxListAdd(context->sessions, sn);
+    dav_context_add_session(context, sn);
     sn->context = context;
     
     return sn;
@@ -302,12 +302,8 @@
 
 void dav_session_destroy(DavSession *sn) { 
     // remove session from context
-    CxList *sessions = sn->context->sessions;
-    ssize_t i = cxListFind(sessions, sn);
-    if(i >= 0) {
-        cxListRemove(sessions, i);
-    } else {
-        printf("Error: session not found in ctx->sessions\n");
+    if (dav_context_remove_session(sn->context, sn)) {
+        fprintf(stderr, "Error: session not found in ctx->sessions\n");
         dav_session_destructor(sn);
     }
 }
--- a/libidav/webdav.c	Mon Jan 29 11:20:34 2024 +0100
+++ b/libidav/webdav.c	Thu Feb 01 10:41:39 2024 +0100
@@ -146,15 +146,68 @@
     free(ctx);
 }
 
+#ifndef _WIN32
+
+void dav_context_set_mtsafe(DavContext *ctx, DavBool enable) {
+    if (enable) {
+        pthread_mutex_init(&ctx->mutex, NULL);
+    } else {
+        pthread_mutex_destroy(&ctx->mutex);
+    }
+    ctx->mtsafe = enable;
+}
+
+void dav_context_lock(DavContext *ctx) {
+    if (ctx->mtsafe) {
+        pthread_mutex_lock(&ctx->mutex);
+    }
+}
+
+void dav_context_unlock(DavContext *ctx) {
+    if (ctx->mtsafe) {
+        pthread_mutex_unlock(&ctx->mutex);
+    }
+}
+
+#else
+
+void dav_context_set_mtsafe(DavContext *ctx, DavBool enable) {
+    if (enable) {
+        ctx->mutex = CreateMutex(NULL, FALSE, NULL);
+    } else {
+        CloseHandle(ctx->mutex);
+    }
+    ctx->mtsafe = enable;
+}
+
+void dav_context_lock(DavContext *ctx) {
+    if (ctx->mtsafe) {
+        WaitForSingleObject(ctx->mutex, INFINITE);
+    }
+}
+
+void dav_context_unlock(DavContext *ctx) {
+    if (ctx->mtsafe) {
+        ReleaseMutex(ctx->mutex);
+    }
+}
+
+#endif
+
 void dav_context_add_key(DavContext *context, DavKey *key) {
+    dav_context_lock(context);
     cxMapPut(context->keys, cx_hash_key_str(key->name), key);
+    dav_context_unlock(context);
 }
 
 DavKey* dav_context_get_key(DavContext *context, const char *name) {
+    DavKey *key = NULL;
+    dav_context_lock(context);
     if(name) {
-        return cxMapGet(context->keys, cx_hash_key_str(name));
+        key = cxMapGet(context->keys, cx_hash_key_str(name));
     }
-    return NULL;
+    dav_context_unlock(context);
+    return key;
 }
 
 int dav_add_namespace(DavContext *context, const char *prefix, const char *name) {
@@ -164,8 +217,19 @@
     }
     
     char *p = strdup(prefix);
+    if (!p) {
+        free(namespace);
+        return 1;
+    }
     char *n = strdup(name);
-    
+    if (!n) {
+        free(namespace);
+        free(p);
+        return 1;
+    }
+
+    dav_context_lock(context);
+
     int err = 0;
     if(p && n) {
         namespace->prefix = p;
@@ -178,19 +242,29 @@
         if(p) free(p);
         if(n) free(n);
     }
+
+    dav_context_unlock(context);
     
     return err;
 }
 
 DavNamespace* dav_get_namespace(DavContext *context, const char *prefix) {
-    return cxMapGet(context->namespaces, cx_hash_key_str(prefix));
+    dav_context_lock(context);
+    DavNamespace *ns = cxMapGet(context->namespaces, cx_hash_key_str(prefix));
+    dav_context_unlock(context);
+    return ns;
 }
 
 DavNamespace* dav_get_namespace_s(DavContext *context, cxstring prefix) {
-    return cxMapGet(context->namespaces, cx_hash_key(prefix.ptr, prefix.length));
+    dav_context_lock(context);
+    DavNamespace *ns = cxMapGet(context->namespaces, cx_hash_key(prefix.ptr, prefix.length));
+    dav_context_unlock(context);
+    return ns;
 }
 
 int dav_enable_namespace_encryption(DavContext *context, const char *ns, DavBool encrypt) {
+    dav_context_lock(context);
+
     CxHashKey hkey = cx_hash_key_str(ns);
     DavNSInfo *info = cxMapGet(context->namespaceinfo, hkey);
     if(!info) {
@@ -200,15 +274,21 @@
     } else {
         info->encrypt = encrypt;
     }
+
+    dav_context_unlock(context);
     return 0;
 }
 
 int dav_namespace_is_encrypted(DavContext *context, const char *ns) {
+    int ret = 0;
+    dav_context_lock(context);
+    
     DavNSInfo *info = cxMapGet(context->namespaceinfo, cx_hash_key_str(ns));
     if(info) {
-        return info->encrypt;
+        ret = info->encrypt;
     }
-    return 0;
+    dav_context_unlock(context);
+    return ret;
 }
 
 void dav_get_property_namespace_str(
@@ -262,6 +342,28 @@
     }
 }
 
+int dav_context_add_session(DavContext *context, DavSession *sn) {
+    dav_context_lock(context);
+    int ret = cxListAdd(context->sessions, sn);
+    dav_context_unlock(context);
+    return ret;
+}
+
+int dav_context_remove_session(DavContext *context, DavSession *sn) {
+    int ret = 0;
+    dav_context_lock(context);
+    CxList *sessions = context->sessions;
+    ssize_t i = cxListFind(sessions, sn);
+    if(i >= 0) {
+        cxListRemove(sessions, i);
+    } else {
+        ret = 1;
+    }
+    dav_context_unlock(context);
+    return ret;
+}
+
+
 // TODO: add sstr_t version of dav_get_property_ns
 
 void dav_set_effective_href(DavSession *sn, DavResource *resource) {
--- a/libidav/webdav.h	Mon Jan 29 11:20:34 2024 +0100
+++ b/libidav/webdav.h	Thu Feb 01 10:41:39 2024 +0100
@@ -39,6 +39,12 @@
 #include <curl/curl.h>
 #include <libxml/tree.h>
 
+#ifndef _WIN32
+#include <pthread.h>
+#else
+#include <Windows.h>
+#endif
+
 #ifdef	__cplusplus
 extern "C" {
 #endif
@@ -67,6 +73,12 @@
 typedef struct DavInputStream  DavInputStream;
 typedef struct DavOutputStream DavOutputStream;
 
+#ifndef _WIN32
+#define DAV_MUTEX pthread_mutex_t 
+#else
+#define DAV_MUTEX HANDLE
+#endif
+
 typedef size_t(*dav_read_func)(void*, size_t, size_t, void*);
 typedef size_t(*dav_write_func)(const void*, size_t, size_t, void*);
 typedef int(*dav_seek_func)(const void *, long, int);
@@ -180,12 +192,14 @@
 };
 
 struct DavContext {
-    CxMap    *namespaces;
-    CxMap    *namespaceinfo;
-    CxMap    *keys;
-    CxList   *sessions;
-    DavProxy *http_proxy;
-    DavProxy *https_proxy;
+    CxMap     *namespaces;
+    CxMap     *namespaceinfo;
+    CxMap     *keys;
+    CxList    *sessions;
+    DavProxy  *http_proxy;
+    DavProxy  *https_proxy;
+    DAV_MUTEX mutex;
+    DavBool   mtsafe;
 };
 
 struct DavProxy {
@@ -251,6 +265,10 @@
 
 DavContext* dav_context_new(void);
 void dav_context_destroy(DavContext *ctx);
+void dav_context_set_mtsafe(DavContext *ctx, DavBool enable);
+
+void dav_context_lock(DavContext *ctx);
+void dav_context_unlock(DavContext *ctx);
 
 void dav_context_add_key(DavContext *context, DavKey *key);
 DavKey* dav_context_get_key(DavContext *context, const char *name);
@@ -262,6 +280,9 @@
 int dav_enable_namespace_encryption(DavContext *context, const char *ns, DavBool encrypt);
 int dav_namespace_is_encrypted(DavContext *context, const char *ns);
 
+int dav_context_add_session(DavContext *context, DavSession *sn);
+int dav_context_remove_session(DavContext *context, DavSession *sn);
+
 DavSession* dav_session_new(DavContext *context, char *base_url);
 DavSession* dav_session_new_auth(
         DavContext *context,
--- a/make/vs/libidav/libidav.vcxproj	Mon Jan 29 11:20:34 2024 +0100
+++ b/make/vs/libidav/libidav.vcxproj	Thu Feb 01 10:41:39 2024 +0100
@@ -109,7 +109,7 @@
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
     <ClCompile>
       <WarningLevel>Level3</WarningLevel>
-      <SDLCheck>true</SDLCheck>
+      <SDLCheck>false</SDLCheck>
       <PreprocessorDefinitions>_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ConformanceMode>true</ConformanceMode>
       <LanguageStandard_C>stdc11</LanguageStandard_C>
@@ -144,6 +144,7 @@
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClCompile Include="..\..\..\libidav\config.c" />
     <ClCompile Include="..\..\..\libidav\crypto.c" />
     <ClCompile Include="..\..\..\libidav\davqlexec.c" />
     <ClCompile Include="..\..\..\libidav\davqlparser.c" />
@@ -156,6 +157,7 @@
     <ClCompile Include="..\..\..\libidav\xml.c" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="..\..\..\libidav\config.h" />
     <ClInclude Include="..\..\..\libidav\crypto.h" />
     <ClInclude Include="..\..\..\libidav\davqlexec.h" />
     <ClInclude Include="..\..\..\libidav\davqlparser.h" />
--- a/make/vs/libidav/libidav.vcxproj.filters	Mon Jan 29 11:20:34 2024 +0100
+++ b/make/vs/libidav/libidav.vcxproj.filters	Thu Feb 01 10:41:39 2024 +0100
@@ -45,6 +45,9 @@
     <ClCompile Include="..\..\..\libidav\xml.c">
       <Filter>Quelldateien</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\..\libidav\config.c">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\..\libidav\crypto.h">
@@ -77,5 +80,8 @@
     <ClInclude Include="..\..\..\libidav\xml.h">
       <Filter>Headerdateien</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\..\libidav\config.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
\ No newline at end of file

mercurial