diff options
Diffstat (limited to 'test-curl/test/src/test.c')
-rw-r--r-- | test-curl/test/src/test.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/test-curl/test/src/test.c b/test-curl/test/src/test.c new file mode 100644 index 0000000..52b1473 --- /dev/null +++ b/test-curl/test/src/test.c @@ -0,0 +1,197 @@ +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <stdbool.h> + +#include <curl/curl.h> +#include <event2/event.h> +#include <event2/bufferevent.h> +#include <event2/buffer.h> + +#define URIS_S 2 +const char *uris[] = { + "https://api.turris.cz/updater-defs/3.5/omnia/dev-karel/base.lua", + "https://api.turris.cz/updater-defs/3.5/omnia/dev-karel/base.lua.sig" +}; + +CURLM *curl_multi; +struct event_base *e_base; +struct event *e_timer; + +struct dwn_data { + const char *err; +}; + +static void check() { + CURLMsg *msg; + int msgs_left; + struct dwn_data *data; + char *url; + + while ((msg = curl_multi_info_read(curl_multi, &msgs_left))) { + if (msg->msg != CURLMSG_DONE) + continue; // No other message types are defined in libcurl. We check just because of compatibility with possible future versions. + curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &data); + curl_easy_getinfo(msg->easy_handle, CURLINFO_EFFECTIVE_URL, &url); + if (msg->data.result == CURLE_OK) { + printf("Download succesfull (%s)\n", url); + } else { + printf("Download failed (%s): %s\n", url, data->err); + exit(2); + } + } +} + +static size_t clb_write(char *ptr, size_t size, size_t nmemb, void *userd) { + // Drop all data + return size * nmemb; +} + +static void clb_timer(int fd __attribute__((unused)), short kind __attribute__((unused)), void *userp) { + printf("Timer callback\n"); + int running = 0; + curl_multi_socket_action(curl_multi, CURL_SOCKET_TIMEOUT, 0, &running); + check(); +} + +static int clb_timer_set(CURLM *curl_multi __attribute__((unused)), long timeout_ms, void *userp) { + printf("Timer set %ld\n", timeout_ms); + struct timeval timeout; + timeout.tv_sec = timeout_ms / 1000; + timeout.tv_usec = (timeout_ms % 1000) * 1000; + evtimer_add(e_timer, &timeout); + return 0; +} + +struct dt_s { + size_t id; + struct event *e; +}; + +static void clb_socket(int fd, short kind, void *userp) { + printf("Socket callback\n"); + int action = ((kind & EV_READ) ? CURL_CSELECT_IN : 0) | ((kind & EV_WRITE) ? CURL_CSELECT_OUT : 0); + int running = 0; + curl_multi_socket_action(curl_multi, fd, action, &running); + check(); + if (running <= 0 && evtimer_pending(e_timer, NULL)) + evtimer_del(e_timer); +} + +size_t id_next = 0; + +static int clb_socket_set(CURL *curl_easy, curl_socket_t s, int what, void *userp, void *socketp) { + struct dt_s *sdata = socketp; + if (what == CURL_POLL_REMOVE) { + printf("Socket remove %ld\n", sdata->id); + event_free(sdata->e); + free(sdata); + } else { + if (!sdata) { // New socket. No data associated. + printf("Socket new %ld\n", id_next); + sdata = malloc(sizeof *sdata); + sdata->e = NULL; + sdata->id = id_next++; + curl_multi_assign(curl_multi, s, sdata); + } else + printf("Socket change %ld\n", sdata->id); + short kind = ((what & CURL_POLL_IN) ? EV_READ : 0) | ((what & CURL_POLL_OUT) ? EV_WRITE : 0) | EV_PERSIST; + if (sdata->e) { + event_del(sdata->e); + event_assign(sdata->e, e_base, s, kind, clb_socket, sdata); + } else + sdata->e = event_new(e_base, s, kind, clb_socket, sdata); + event_add(sdata->e, NULL); + } + return 0; +} + +static CURL *new_curl(const char *uri, bool simple) { + CURL *curl = curl_easy_init(); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); + curl_easy_setopt(curl, CURLOPT_URL, uri); + curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ""); + curl_easy_setopt(curl, CURLOPT_CAINFO, "./ca.pem"); + curl_easy_setopt(curl, CURLOPT_CRLFILE, "./crl.pem"); + curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 120); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 30); + curl_easy_setopt(curl, CURLOPT_CAPATH, NULL); + curl_easy_setopt(curl, CURLOPT_SSL_CIPHER_LIST, NULL); + + if (!simple) { + struct dwn_data *data = malloc(sizeof *data); + curl_multi_add_handle(curl_multi, curl); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, clb_write); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, data->err); + curl_easy_setopt(curl, CURLOPT_PRIVATE, data); + } + + return curl; +} + + +int main(int argc, char *argv[]) { + bool simple = (argc > 1 && !strcmp(argv[1], "-s")); + bool multi = (argc > 1 && !strcmp(argv[1], "-m")); + curl_global_init(CURL_GLOBAL_SSL); + if (!simple) { + struct event_config *config = event_config_new(); + event_config_require_features(config, EV_FEATURE_FDS); + event_config_set_flag(config, EVENT_BASE_FLAG_NOLOCK); + e_base = event_base_new_with_config(config); + event_config_free(config); + e_timer = evtimer_new(e_base, clb_timer, NULL); + + curl_multi = curl_multi_init(); + curl_multi_setopt(curl_multi, CURLMOPT_MAX_TOTAL_CONNECTIONS, 1); + curl_multi_setopt(curl_multi, CURLMOPT_SOCKETFUNCTION, clb_socket_set); + curl_multi_setopt(curl_multi, CURLMOPT_TIMERFUNCTION, clb_timer_set); + } + + size_t i; + CURL *curls[URIS_S]; + for (i = 0; i < URIS_S; i++) { + curls[i] = new_curl(uris[i], simple); + } + if (simple) { + for (i = 0; i < URIS_S; i++) { + CURLcode res = curl_easy_perform(curls[i]); + if (res == CURLE_OK) + printf("Download succesfull (%s)\n", uris[i]); + else + printf("Download failed (%s): %s\n", uris[i], curl_easy_strerror(res)); + } + } else if (multi) { + int sr = 0; + CURLMcode cd; + do { + cd = curl_multi_perform(curl_multi, &sr); + } while(sr > 0 || cd == CURLM_CALL_MULTI_PERFORM); + if (cd != CURLM_OK) { + printf("Download failed: %s\n", curl_multi_strerror(cd)); + exit(3); + } else + printf("Download succesfull\n"); + } else + event_base_dispatch(e_base); + + for (i = 0; i < URIS_S; i++) { + if (!simple) + curl_multi_remove_handle(curl_multi, curls[i]); + curl_easy_cleanup(curls[i]); + } + + if (!simple) { + curl_multi_cleanup(curl_multi); + + event_free(e_timer); + event_base_free(e_base); + } + curl_global_cleanup(); + + return 0; +} |