diff -r a569148841ff -r efbd59642577 libidav/session.c --- 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 #include -#include -#include +#include +#include +#include +#include #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 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); - } }