libidav/session.c

changeset 747
efbd59642577
parent 742
7e67689241fd
child 777
15006651a5d1
--- a/libidav/session.c	Sun Apr 16 14:12:24 2023 +0200
+++ b/libidav/session.c	Fri Apr 21 21:25:32 2023 +0200
@@ -30,8 +30,10 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <ucx/buffer.h>
-#include <ucx/utils.h>
+#include <cx/buffer.h>
+#include <cx/utils.h>
+#include <cx/basic_mempool.h>
+#include <cx/hash_map.h>
 
 #include "utils.h"
 #include "session.h"
@@ -42,14 +44,14 @@
     if(!base_url) {
         return NULL;
     }
-    sstr_t url = sstr(base_url);
+    cxstring url = cx_str(base_url);
     if(url.length == 0) {
         return NULL;
     }
     DavSession *sn = malloc(sizeof(DavSession));
     memset(sn, 0, sizeof(DavSession));
-    sn->mp = ucx_mempool_new(DAV_SESSION_MEMPOOL_SIZE);
-    sn->pathcache = ucx_map_new_a(sn->mp->allocator, DAV_PATH_CACHE_SIZE);
+    sn->mp = cxBasicMempoolCreate(DAV_SESSION_MEMPOOL_SIZE);
+    sn->pathcache = cxHashMapCreate(sn->mp->allocator, CX_STORE_POINTERS, DAV_PATH_CACHE_SIZE);
     sn->key = NULL;
     sn->errorstr = NULL;
     sn->error = DAV_OK;
@@ -60,14 +62,11 @@
     sn->handle = curl_easy_init();
     curl_easy_setopt(sn->handle, CURLOPT_FOLLOWLOCATION, 1L);
     
-    // create lock manager
-    DavLockManager *locks = ucx_mempool_malloc(sn->mp, sizeof(DavLockManager));
-    locks->resource_locks = ucx_map_new_a(sn->mp->allocator, 16);
-    locks->collection_locks = NULL;
-    sn->locks = locks;
+    // lock manager is created on-demand
+    sn->locks = NULL;
 
     // set proxy
-    DavProxy *proxy = sstrprefix(url, S("https")) ? context->https_proxy
+    DavProxy *proxy = cx_strprefix(url, CX_STR("https")) ? context->https_proxy
                                                   : context->http_proxy;
     
     if (proxy->url) {
@@ -95,7 +94,7 @@
     curl_easy_setopt(sn->handle, CURLOPT_URL, base_url);
     
     // add to context
-    context->sessions = ucx_list_append(context->sessions, sn);
+    cxListAdd(context->sessions, sn);
     sn->context = context;
     
     return sn;
@@ -128,16 +127,17 @@
 }
 
 void dav_session_set_baseurl(DavSession *sn, char *base_url) {
+    const CxAllocator *a = sn->mp->allocator;
     if(sn->base_url) {
-        ucx_mempool_free(sn->mp, sn->base_url);
+        cxFree(a, sn->base_url);
     }
     
-    sstr_t url = sstr(base_url);
+    cxstring url = cx_str(base_url);
     if(url.ptr[url.length - 1] == '/') {
-        sstr_t url = sstrdup_a(sn->mp->allocator, sstr(base_url));
-        sn->base_url = url.ptr;
+        cxmutstr url_m = cx_strdup_a(a, cx_str(base_url));
+        sn->base_url = url_m.ptr;
     } else {
-        char *url_str = ucx_mempool_malloc(sn->mp, url.length + 2);
+        char *url_str = cxMalloc(a, url.length + 2);
         memcpy(url_str, base_url, url.length);
         url_str[url.length]     = '/';
         url_str[url.length + 1] = '\0';
@@ -170,17 +170,17 @@
     return dav_session_curl_perform_buf(sn, NULL, NULL, status);
 }
 
-CURLcode dav_session_curl_perform_buf(DavSession *sn, UcxBuffer *request, UcxBuffer *response, long *status) {
+CURLcode dav_session_curl_perform_buf(DavSession *sn, CxBuffer *request, CxBuffer *response, long *status) {
     CURLcode ret = curl_easy_perform(sn->handle);
     long http_status;
     curl_easy_getinfo(sn->handle, CURLINFO_RESPONSE_CODE, &http_status);
     if(ret == CURLE_OK && http_status == 401 && sn->auth_prompt) {
         if(!sn->auth_prompt(sn, sn->authprompt_userdata)) {
             if(request) {
-                ucx_buffer_seek(request, 0, SEEK_SET);
+                cxBufferSeek(request, 0, SEEK_SET);
             }
             if(response) {
-                ucx_buffer_seek(response, 0, SEEK_SET);
+                cxBufferSeek(response, 0, SEEK_SET);
             }
             ret = curl_easy_perform(sn->handle);
             curl_easy_getinfo(sn->handle, CURLINFO_RESPONSE_CODE, &http_status);
@@ -274,43 +274,40 @@
 
 void dav_session_destroy(DavSession *sn) { 
     // remove session from context
-    UcxList *sessions = sn->context->sessions;
-    ssize_t i = ucx_list_find(sessions, sn, ucx_cmp_ptr, NULL);
-    if(i >= 0)  {
-        UcxList *elm = ucx_list_get(sessions, i);
-        if(elm) {
-            sn->context->sessions = ucx_list_remove(sessions, elm);
-        }
+    CxList *sessions = sn->context->sessions;
+    ssize_t i = cxListFind(sessions, sn);
+    if(i >= 0) {
+        cxListRemove(sessions, i);
     }
     
-    ucx_mempool_destroy(sn->mp);
+    cxMempoolDestroy(sn->mp);
     curl_easy_cleanup(sn->handle);
     free(sn);
 }
 
 
 void* dav_session_malloc(DavSession *sn, size_t size) {
-    return ucx_mempool_malloc(sn->mp, size);
+    return cxMalloc(sn->mp->allocator, size);
 }
 
 void* dav_session_calloc(DavSession *sn, size_t nelm, size_t size) {
-    return ucx_mempool_calloc(sn->mp, nelm, size);
+    return cxCalloc(sn->mp->allocator, nelm, size);
 }
 
 void* dav_session_realloc(DavSession *sn, void *ptr, size_t size) {
-    return ucx_mempool_realloc(sn->mp, ptr, size);
+    return cxRealloc(sn->mp->allocator, ptr, size);
 }
 
 void  dav_session_free(DavSession *sn, void *ptr) {
-    ucx_mempool_free(sn->mp, ptr);
+    cxFree(sn->mp->allocator, ptr);
 }
 
 char* dav_session_strdup(DavSession *sn, const char *str) {
-    return sstrdup_a(sn->mp->allocator, sstr((char*)str)).ptr;
+    return cx_strdup_a(sn->mp->allocator, cx_str((char*)str)).ptr;
 }
 
 
-char* dav_session_create_plain_href(DavSession *sn, char *path) {
+char* dav_session_create_plain_href(DavSession *sn, const char *path) {
     if(!DAV_ENCRYPT_NAME(sn) && !DAV_DECRYPT_NAME(sn)) {
         // non encrypted file names
         char *url = util_path_to_url(sn, path);
@@ -322,11 +319,14 @@
     }
 }
 
-char* dav_session_get_href(DavSession *sn, char *path) {
+char* dav_session_get_href(DavSession *sn, const char *path) {
     if(DAV_DECRYPT_NAME(sn) || DAV_ENCRYPT_NAME(sn)) {
-        sstr_t p = sstr(path);
-        UcxBuffer *href = ucx_buffer_new(NULL, 256, UCX_BUFFER_AUTOEXTEND);
-        UcxBuffer *pbuf = ucx_buffer_new(NULL, 256, UCX_BUFFER_AUTOEXTEND);
+        cxstring p = cx_str(path);
+        CxBuffer href;
+        CxBuffer pbuf;
+        cxBufferInit(&href, NULL, 256, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND);
+        cxBufferInit(&pbuf, NULL, 256, cxDefaultAllocator, CX_BUFFER_FREE_CONTENTS|CX_BUFFER_AUTO_EXTEND);
+        
         int start = 0;
         int begin = 0;
         
@@ -334,11 +334,11 @@
         char *cp = strdup(path);
         //printf("cp: %s\n", cp);
         while(strlen(cp) > 1) {
-            char *cached = ucx_map_cstr_get(sn->pathcache, cp);
+            char *cached = cxMapGet(sn->pathcache, cx_hash_key_str(cp));
             if(cached) {
                 start = strlen(cp);
                 begin = start;
-                ucx_buffer_puts(href, cached);
+                cxBufferPutString(&href, cached);
                 break;
             } else {
                 // check, if the parent path is cached
@@ -348,101 +348,96 @@
             }
         }
         free(cp);
-        if(href->pos == 0) {
+        if(href.pos == 0) {
             // if there are no cached elements we have to add the base url path
             // to the href buffer
-            ucx_buffer_puts(href, util_url_path(sn->base_url));
+            cxBufferPutString(&href, util_url_path(sn->base_url));
         }
         
         // create resource for name lookup
-        sstr_t rp = sstrdup(sstrn(path, start));
+        cxmutstr rp = cx_strdup(cx_strn(path, start));
         DavResource *root = dav_resource_new(sn, rp.ptr);
         free(rp.ptr);
-        resource_set_href(root, sstrn(href->space, href->pos));
+        resource_set_href(root, cx_strn(href.space, href.pos));
         
         // create request buffer for propfind requests
-        UcxBuffer *rqbuf = create_basic_propfind_request();
+        CxBuffer *rqbuf = create_basic_propfind_request();
         
-        sstr_t remaining = sstrsubs(p, start);
-        ssize_t nelm = 0;
-        sstr_t *elms = sstrsplit(remaining, S("/"), &nelm);
+        cxstring remaining = cx_strsubs(p, start);
+        CxStrtokCtx elms = cx_strtok(remaining, CX_STR("/"), INT_MAX);
         DavResource *res = root;
-        ucx_buffer_puts(pbuf, res->path);
+        cxBufferPutString(&pbuf, res->path);
         // iterate over all remaining path elements
-        for(int i=0;i<nelm;i++) {
-            sstr_t elm = elms[i];
+        cxstring elm;
+        while(cx_strtok_next(&elms, &elm)) {
             if(elm.length > 0) {
                 //printf("elm: %.*s\n", elm.length, elm.ptr);
                 DavResource *child = dav_find_child(sn, res, rqbuf, elm.ptr);
                 
                 // if necessary add a path separator
-                if(pbuf->space[pbuf->pos-1] != '/') {
-                    if(href->space[href->pos-1] != '/') {
-                        ucx_buffer_putc(href, '/');
+                if(pbuf.space[pbuf.pos-1] != '/') {
+                    if(href.space[href.pos-1] != '/') {
+                        cxBufferPut(&href, '/');
                     }
-                    ucx_buffer_putc(pbuf, '/');
+                    cxBufferPut(&pbuf, '/');
                 }
                 // add last path/href to the cache
-                sstr_t pp = sstrn(pbuf->space, pbuf->size);
-                sstr_t hh = sstrn(href->space, href->size);
+                cxstring pp = cx_strn(pbuf.space, pbuf.size);
+                cxstring hh = cx_strn(href.space, href.size);
                 dav_session_cache_path(sn, pp, hh);
                 
-                ucx_buffer_write(elm.ptr, 1, elm.length, pbuf);
+                cxBufferWrite(elm.ptr, 1, elm.length, &pbuf);
                 if(child) {
                     // href is already URL encoded, so don't encode again
-                    ucx_buffer_puts(href, util_resource_name(child->href));
+                    cxBufferPutString(&href, util_resource_name(child->href));
                     res = child;
                 } else if(DAV_ENCRYPT_NAME(sn)) {
                     char *random_name = util_random_str();
-                    ucx_buffer_puts(href, random_name);
+                    cxBufferPutString(&href, random_name);
                     free(random_name);
                 } else {
                     // path is not URL encoded, so we have to do this here
-                    scstr_t resname = scstr(util_resource_name(path));
+                    cxstring resname = cx_str(util_resource_name((const char*)path));
                     // the name of collections ends with
                     // a trailing slash, which MUST NOT be encoded
                     if(resname.ptr[resname.length-1] == '/') {
                         char *esc = curl_easy_escape(sn->handle,
                                 resname.ptr, resname.length-1);
-                        ucx_buffer_write(esc, 1, strlen(esc), href);
-                        ucx_buffer_putc(href, '/');
+                        cxBufferWrite(esc, 1, strlen(esc), &href);
+                        cxBufferPut(&href, '/');
                         curl_free(esc);
                     } else  {
                         char *esc = curl_easy_escape(sn->handle,
                                 resname.ptr, resname.length);
-                        ucx_buffer_write(esc, 1, strlen(esc), href);
+                        cxBufferWrite(esc, 1, strlen(esc), &href);
                         curl_free(esc);
                     }
                 }
             }
-            
-            // cleanup
-            free(elm.ptr);
         }
-        free(elms);
         
         // if necessary add a path separator
         if(p.ptr[p.length-1] == '/') {
-            if(href->space[href->pos-1] != '/') {
-                ucx_buffer_putc(href, '/');
+            if(href.space[href.pos-1] != '/') {
+                cxBufferPut(&href, '/');
             }
-            ucx_buffer_putc(pbuf, '/');
+            cxBufferPut(&pbuf, '/');
         }
         // add the final path to the cache
-        sstr_t pp = sstrn(pbuf->space, pbuf->size);
-        sstr_t hh = sstrn(href->space, href->size);
+        cxstring pp = cx_strn(pbuf.space, pbuf.size);
+        cxstring hh = cx_strn(href.space, href.size);
         dav_session_cache_path(sn, pp, hh);
         
-        sstr_t href_str = sstrdup_a(
+        cxmutstr href_str = cx_strdup_a(
                 sn->mp->allocator,
-                sstrn(href->space,
-                href->size));
+                cx_strn(href.space, href.size));
         
         // cleanup
         dav_resource_free_all(root);
-        ucx_buffer_free(rqbuf);
-        ucx_buffer_free(pbuf);
-        ucx_buffer_free(href);
+        cxBufferFree(rqbuf);
+        
+        cxBufferDestroy(&pbuf);
+        cxBufferDestroy(&href);
         
         return href_str.ptr;
     } else {
@@ -450,7 +445,7 @@
     }
 }
 
-DavResource* dav_find_child(DavSession *sn, DavResource *res, UcxBuffer *rqbuf, char *name) {
+DavResource* dav_find_child(DavSession *sn, DavResource *res, CxBuffer *rqbuf, const char *name) {
     if(res && !dav_propfind(sn, res, rqbuf)) {
         DavResource *child = res->children;
         while(child) {
@@ -463,16 +458,17 @@
     return NULL;
 }
 
-void dav_session_cache_path(DavSession *sn, sstr_t path, sstr_t href) {
-    char *elm = ucx_map_sstr_get(sn->pathcache, path);
+void dav_session_cache_path(DavSession *sn, cxstring path, cxstring href) {
+    CxHashKey path_key = cx_hash_key(path.ptr, path.length);
+    char *elm = cxMapGet(sn->pathcache, path_key);
     if(!elm) {
-        href = sstrdup_a(sn->mp->allocator, href);
-        ucx_map_sstr_put(sn->pathcache, path, href.ptr);
+        cxmutstr href_s = cx_strdup_a(sn->mp->allocator, href);
+        cxMapPut(sn->pathcache, path_key, href_s.ptr);
     }
 }
 
 
-DavLock* dav_create_lock(DavSession *sn, char *token, char *timeout) {
+DavLock* dav_create_lock(DavSession *sn, const char *token, char *timeout) {
     DavLock *lock = dav_session_malloc(sn, sizeof(DavLock));
     lock->path = NULL;
     lock->token = dav_session_strdup(sn, token);
@@ -490,77 +486,79 @@
     dav_session_free(sn, lock);
 }
 
-int dav_add_resource_lock(DavSession *sn, char *path, DavLock *lock) {
-    DavLockManager *locks = sn->locks;
-    if(ucx_map_cstr_get(locks->resource_locks, path)) {
-        return -1;
-    }
-    
-    ucx_map_cstr_put(locks->resource_locks, path, lock);
+
+static int dav_lock_cmp(void const *left, void const *right) {
+    const DavLock *l = left;
+    const DavLock *r = right;
+    return strcmp(l->path, r->path);
+}
+
+static int create_lock_manager(DavSession *sn) {
+    // create lock manager
+    DavLockManager *locks = cxMalloc(sn->mp->allocator, sizeof(DavLockManager));
+    locks->resource_locks = cxHashMapCreate(sn->mp->allocator, CX_STORE_POINTERS, 16);
+    locks->collection_locks = cxLinkedListCreate(sn->mp->allocator, dav_lock_cmp, CX_STORE_POINTERS);
+    sn->locks = locks;
     return 0;
 }
 
-static void insert_lock(DavSession *sn, UcxList *elm, UcxList *newelm) {
-    UcxList *next = elm->next;
-    if(next) {
-        next->prev = newelm;
-        newelm->next = next;
+static DavLockManager* get_lock_manager(DavSession *sn) {
+    DavLockManager *locks = sn->locks;
+    if(!locks) {
+        if(create_lock_manager(sn)) {
+            return NULL;
+        }
+        locks = sn->locks;
     }
-    newelm->prev = elm;
-    elm->next = newelm;
+    return locks;
 }
 
-int dav_add_collection_lock(DavSession *sn, char *path, DavLock *lock) {
-    DavLockManager *locks = sn->locks;
-    if(!locks->collection_locks) {
-        locks->collection_locks = ucx_list_append_a(
-                sn->mp->allocator,
-                NULL,
-                lock);
-        lock->path = dav_session_strdup(sn, path);
-        return 0;
+int dav_add_resource_lock(DavSession *sn, const char *path, DavLock *lock) {
+    DavLockManager *locks = get_lock_manager(sn);
+    if(!locks) {
+        return -1;
     }
     
-    UcxList *elm = locks->collection_locks;
-    for(;;) {
-        DavLock *l = elm->data;
-        int cmp = strcmp(path, l->path);
-        if(cmp > 0) {
-            UcxList *newelm = ucx_list_append_a(sn->mp->allocator, NULL, lock);
-            lock->path = dav_session_strdup(sn, path);
-            insert_lock(sn, elm, newelm);
-        } else if(cmp == 0) {
-            return -1;
-        }
-        
-        if(elm->next) {
-            elm = elm->next;
-        } else {
-            UcxList *newelm = ucx_list_append_a(sn->mp->allocator, NULL, lock);
-            lock->path = dav_session_strdup(sn, path);
-            ucx_list_concat(elm, newelm);
-            break;
-        }
+    CxHashKey path_key = cx_hash_key_str(path);
+    if(cxMapGet(locks->resource_locks, path_key)) {
+        return -1;
     }
     
+    cxMapPut(locks->resource_locks, path_key, lock);
+    return 0;
+}
+
+int dav_add_collection_lock(DavSession *sn, const char *path, DavLock *lock) {
+    DavLockManager *locks = get_lock_manager(sn);
+    if(!locks) {
+        return -1;
+    }
+    
+    cxListAdd(locks->collection_locks, lock);
+    cxListSort(locks->collection_locks);
+    
     return 0;
 }
 
-DavLock* dav_get_lock(DavSession *sn, char *path) {
-    DavLockManager *locks = sn->locks;
+DavLock* dav_get_lock(DavSession *sn, const char *path) {
+    DavLockManager *locks = get_lock_manager(sn);
+    if(!locks) {
+        return NULL;
+    }
     
-    DavLock *lock = ucx_map_cstr_get(locks->resource_locks, path);
+    cxstring p = cx_str(path);
+    
+    DavLock *lock = cxMapGet(locks->resource_locks, cx_hash_key(p.ptr, p.length));
     if(lock) {
         return lock;
     }
     
-    sstr_t p = sstr(path);
-    UCX_FOREACH(elm, locks->collection_locks) {
-        DavLock *cl = elm->data;
+    CxIterator i = cxListIterator(locks->collection_locks);
+    cx_foreach(DavLock*, cl, i) {
         int cmd = strcmp(path, cl->path);
         if(cmd == 0) {
             return cl;
-        } else if(sstrprefix(p, sstr(cl->path)))  {
+        } else if(cx_strprefix(p, cx_str(cl->path)))  {
             return cl;
         } else if(cmd > 0) {
             break;
@@ -570,26 +568,25 @@
     return NULL;
 }
 
-void dav_remove_lock(DavSession *sn, char *path, DavLock *lock) {
-    DavLockManager *locks = sn->locks;
+void dav_remove_lock(DavSession *sn, const char *path, DavLock *lock) {
+    DavLockManager *locks = get_lock_manager(sn);
+    if(!locks) {
+        return;
+    }
     
-    if(ucx_map_cstr_remove(locks->resource_locks, path)) {
+    if(cxMapRemoveAndGet(locks->resource_locks, cx_hash_key_str(path))) {
         return;
     }
     
-    UcxList *rm = NULL;
-    UCX_FOREACH(elm, locks->collection_locks) {
-        DavLock *cl = elm->data;
+    CxMutIterator i = cxListMutIterator(locks->collection_locks);
+    int rm = 0;
+    cx_foreach(DavLock* , cl, i) {
+        if(rm) {
+            break;
+        }
         if(cl == lock) {
-            rm = elm;
-            break;
+            cxIteratorFlagRemoval(i);
+            rm = 1;
         }
     }
-    
-    if(rm) {
-        locks->collection_locks = ucx_list_remove_a(
-                sn->mp->allocator,
-                locks->collection_locks,
-                rm);
-    }
 }

mercurial