aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChloe Kudryavtsev <code@toast.bunkerlabs.net>2023-03-20 18:12:53 -0400
committerChloe Kudryavtsev <code@toast.bunkerlabs.net>2023-03-20 18:12:53 -0400
commit33923ba6779dbb6f42e5849cad2236b8cd8445d3 (patch)
treeb99965bf196d662b7cf1eb1ab53f2fc8f2a6399f
parentadd curl global init/cleanup (diff)
add slist argument handling, extra cleanup
when a curl_easy_setopt expects an slist, we convert an indexed datatype that is expected to be filled with strings into an slist, registering it for cleanup in a way that should avoid memory leaks
-rw-r--r--jurl.c20
-rw-r--r--jurl.h13
-rw-r--r--jurl_setopt.c21
3 files changed, 51 insertions, 3 deletions
diff --git a/jurl.c b/jurl.c
index f5d4204..365740a 100644
--- a/jurl.c
+++ b/jurl.c
@@ -7,6 +7,18 @@ int jurl_gc(void *p, size_t s) {
(void) s;
jurl_handle *jurl = (jurl_handle*)p;
if (jurl->handle) curl_easy_cleanup(jurl->handle);
+ while (jurl->cleanup) {
+ struct jurl_cleanup *cur = jurl->cleanup;
+ switch (cur->type) {
+ case JURL_CLEANUP_TYPE_SLIST:
+ curl_slist_free_all(cur->slist);
+ break;
+ default:
+ janet_panic("unknown type of cleanup data in jurl_gc");
+ }
+ jurl->cleanup = cur->next;
+ free(cur);
+ }
return 0;
}
@@ -27,6 +39,14 @@ JANET_CFUN(jurl_new) {
return janet_wrap_abstract(jurl);
}
+struct jurl_cleanup *register_cleanup(jurl_handle *jurl, enum jurl_cleanup_type type) {
+ struct jurl_cleanup *out = malloc(sizeof(struct jurl_cleanup));
+ out->next = jurl->cleanup;
+ jurl->cleanup = out;
+ out->type = type;
+ return out;
+}
+
JANET_CFUN(jurl_reset) {
janet_fixarity(argc, 1);
jurl_handle *jurl = (jurl_handle*)janet_getabstract(argv, 0, &jurl_type);
diff --git a/jurl.h b/jurl.h
index 382b178..4182025 100644
--- a/jurl.h
+++ b/jurl.h
@@ -3,12 +3,25 @@
#include <janet.h>
// jurl globals
+enum jurl_cleanup_type {
+ JURL_CLEANUP_TYPE_SLIST,
+};
+struct jurl_cleanup {
+ struct jurl_cleanup *next;
+ enum jurl_cleanup_type type;
+ union {
+ struct curl_slist *slist; // when JURL_CLEANUP_TYPE_SLIST
+ };
+};
+
struct jurl_handle {
CURL* handle;
+ struct jurl_cleanup* cleanup;
};
typedef struct jurl_handle jurl_handle;
// jurl.c
+struct jurl_cleanup *register_cleanup(jurl_handle *jurl, enum jurl_cleanup_type type);
JANET_CFUN(jurl_new);
JANET_CFUN(jurl_reset);
JANET_CFUN(jurl_dup);
diff --git a/jurl_setopt.c b/jurl_setopt.c
index a3cf8e6..f0b0cd7 100644
--- a/jurl_setopt.c
+++ b/jurl_setopt.c
@@ -312,10 +312,25 @@ JANET_CFUN(jurl_setopt) {
// TODO: how to clean up leak?
janet_panic("jurl_setopt: FILE* not implemented");
break;
- case JURL_PARAMTYPE_SLIST:
- // TODO: make sure all slits are plain strings
- janet_panic("jurl_setopt: slist not implemented");
+ case JURL_PARAMTYPE_SLIST: {
+ // we register the cleanup ahead of time, because...
+ struct jurl_cleanup *clean = register_cleanup(jurl, JURL_CLEANUP_TYPE_SLIST);
+
+ JanetView args = janet_getindexed(argv, 2);
+ for (int32_t i = 0; i < args.len; i++) {
+ const char *s = janet_getcstring(args.items, i);
+ // we use the cleanup pointer directly, this way...
+ struct curl_slist *newlist = curl_slist_append(clean->slist, s);
+ if (!newlist) {
+ // if we ever panic in the *middle* of handling,
+ // the slist will get cleaned up during garbage collection anyway
+ janet_panic("failed to append to slist in jurl_setopt");
+ }
+ clean->slist = newlist;
+ }
+ curl_easy_setopt(jurl->handle, opt->opt, clean->slist);
break;
+ }
case JURL_PARAMTYPE_BITMASK:
// TODO: bitmask table
janet_panic("jurl_setopt: bitmasks not implemented");