From 878db58d03e98521c0da55628b7be1c7cca76463 Mon Sep 17 00:00:00 2001 From: Ashish Gupta Date: Tue, 2 May 2017 12:01:38 +0200 Subject: Add http kolibrios fetcher --- content/fetchers/httplib_kolibri.c | 346 +++++++++++++++++++++++++++++++++++++ content/fetchers/httplib_kolibri.h | 4 + 2 files changed, 350 insertions(+) create mode 100644 content/fetchers/httplib_kolibri.c create mode 100644 content/fetchers/httplib_kolibri.h (limited to 'content') diff --git a/content/fetchers/httplib_kolibri.c b/content/fetchers/httplib_kolibri.c new file mode 100644 index 000000000..0f9bcb7c4 --- /dev/null +++ b/content/fetchers/httplib_kolibri.c @@ -0,0 +1,346 @@ +#include +#include + +#include "utils/url.h" +#include "utils/nsurl.h" +#include "utils/utils.h" +#include "utils/corestrings.h" +#include "utils/nsurl.h" +#include "utils/log.h" + +#include "content/fetch.h" +#include "content/fetchers.h" +#include "content/fetchers/httplib_kolibri.h" +#include "frontends/kolibrios/kolibri_http.h" + +#define STOP __asm__ __volatile__("int3") + +extern struct fetch; + +struct httpfetcher { + struct http_msg *handle; + struct fetch *owner; + bool headercbdone; + + struct httpfetcher *next; +}; + +struct httpfetcher *head = NULL; + +void add_to_poll(struct httpfetcher *newfetcher) { + + LOG("-=- add: newfetcher 0x%x, newfetcher->handle 0x%x", newfetcher, newfetcher->handle); + /* STOP; */ + + struct httpfetcher *t = head; + assert(newfetcher->next == NULL); + + if(head == NULL) { + head = newfetcher; + LOG("-=- head was NULL. head is now : 0x%x", head); + assert(head->next == NULL); + } + else { + while(t->next != NULL) { + LOG("-=- Passing through httpfetcher : 0x%x", t); + t = t->next; + } + LOG("-=- Adding after httpfetcher : 0x%x", t); + t->next = newfetcher; + } + LOG("-=- done: newfetcher 0x%x, newfetcher->handle 0x%x", newfetcher, newfetcher->handle); +} + +void remove_from_poll(struct http_msg *donehttp) { + struct httpfetcher *t = head, *p = head; + LOG("-=- remove: (->handle) donehttp 0x%x", donehttp); + /* STOP; */ + + while(t) { + LOG("------- t = 0x%x, t->handle = 0x%x", t, t->handle); + /* STOP; */ + + if (t->handle == donehttp) { + LOG(" -- t->handle == donehttp"); + if(t == head) { + LOG("--- t == head"); + p = t->next; + head = p; + LOG("-=- Setting head to 0x%x", p); + break; + } + else { + LOG("--- t != head"); + LOG("-=- p is 0x%x", p); + p->next = t->next; + break; + } + } + + p = t; + t = t->next; + } +} + +bool init_fetcher(lwc_string *scheme) { + bool supported_scheme; + assert(lwc_string_isequal(scheme, corestring_lwc_http, &supported_scheme) == lwc_error_ok); + kolibri_http_init(); + + /* if(supported_scheme) { */ + /* if(kolibri_http_init() == 0) */ + /* debug_board_printf("[INFO] Loaded http.obj library successfully.\n"); */ + /* else { */ + /* debug_board_printf("[ERROR] Could not load http.obj library.\n"); */ + /* return false; */ + /* } */ + /* } */ + + return supported_scheme; +} + +bool supported_url_check(const struct nsurl *url) { + bool supported; + lwc_string *url_scheme = nsurl_get_component(url, NSURL_SCHEME); + assert(lwc_string_isequal(url_scheme, corestring_lwc_http, &supported) == lwc_error_ok); + lwc_string_unref(url_scheme); + return supported; +} + +void *setup_fetch(struct fetch *parent_fetch, struct nsurl *url, + bool only_2xx, bool downgrade_tls, const char *post_urlenc, + const struct fetch_multipart_data *post_multipart, + const char **headers) { + + struct http_msg* request = NULL; + + LOG("[SETUP] Our target URL: %s", nsurl_access(url)); + LOG("[SETUP] POST urlencoded data: %s", post_urlenc); + LOG("[SETUP] Headers : %s", *headers); + + struct fetch_multipart_data *printer = post_multipart; + + while(printer != NULL) { + LOG("Multipart POST : (%s = %s)\n", printer->name, printer->value); + printer = printer->next; + } + + if(post_multipart != NULL) + LOG("[WARNING] We dont support POST multipart yet!\n"); + + if(post_urlenc) { + LOG("http_post: %s", nsurl_access(url)); + request = http_post_asm(nsurl_access(url), NULL, 0, *headers, post_urlenc, strlen(post_urlenc)); + } + else { + /* Do a GET */ + LOG("http_get: %s", nsurl_access(url)); + request = http_get_asm(nsurl_access(url), NULL, 0, *headers); + } + + LOG("Address of request : 0x%x", request); + assert(request != NULL); + + if(request == NULL) { + LOG("[ERROR] Cannot allocate more memory for http library handle creation."); + return NULL; + } + + struct httpfetcher *newfetcher = (struct httpfetcher *) malloc(sizeof(struct httpfetcher)); + assert(newfetcher); + + newfetcher->next = NULL; + newfetcher->handle = request; + newfetcher->headercbdone = false; + newfetcher->owner = parent_fetch; + + return newfetcher; +} + +bool start_fetch(void *httpf) { + LOG("-=- start_fetch : httpf: 0x%x", httpf); + add_to_poll((struct httpfetcher *) httpf); + return true; +} + +bool abort_fetch(void *httpf) { + LOG("aborting fetch 0x%x", ((struct httpfetcher *)httpf)->owner); + http_disconnect_asm(((struct httpfetcher *)httpf)->handle); + remove_from_poll(((struct httpfetcher *) httpf)->handle); + fetch_remove_from_queues(((struct httpfetcher *)httpf)->owner); + /* fetch_free(((struct httpfetcher *)httpf)->owner); */ + return true; +} + +bool free_fetch(void *httpf) { + LOG("Freeing fetch 0x%x", ((struct httpfetcher *)httpf)->owner); + http_free_asm((((struct httpfetcher *)httpf)->handle)); + free((struct httpfetcher *)httpf); + + return true; +} + +void poll_fetch(lwc_string *scheme) { + bool supported_scheme; + assert(lwc_string_isequal(scheme, corestring_lwc_http, &supported_scheme) == lwc_error_ok); + assert(supported_scheme); + + struct httpfetcher *t = head; + + while(t != NULL) { + LOG("-- Polling for t 0x%x, http_msg 0x%x, fetch 0x%x [ hcbdone = %s ]", t, t->handle, t->owner, t->headercbdone == true ? "true" : "false"); + LOG("--- http_msg struct at : %x", t->handle); + LOG("--- Header starts at : %x", &(t->handle->http_header)); + LOG("--- Header Length: %d", t->handle->header_length); + LOG("--- Content starts at : %x", &(t->handle->content_ptr)); + LOG("--- Content Length (received / total): %d / %d", t->handle->content_received, t->handle->content_length); + + int ret = http_receive_asm(t->handle); + + if(t->handle->flags & HTTP_ERRORS) { + fetch_msg msg; + msg.type = FETCH_ERROR; + LOG("---- [ERROR] http_msg -> flags = 0x%x", t->handle->flags); + msg.data.header_or_data.buf = (const uint8_t *) "HTTPLIB ERROR"; + msg.data.header_or_data.len = strlen("HTTPLIB ERROR"); + fetch_send_callback(&msg, t->owner); + t->headercbdone = true; + } + + if(t->headercbdone == false) { + if (t->handle->flags & HTTP_GOT_HEADER) { + LOG("---- Received all HTTP Headers."); + LOG("---- response status code = %d", t->handle->status); + fetch_set_http_code(t->owner, t->handle->status); + + if(t->handle->status >= 200 && t->handle->status < 300) { + fetch_msg msg; + int plen = 0; + char *ptr = &(t->handle->http_header); + + while(plen < t->handle->header_length) { + int j = plen; + + for(;;j++) { + if(*(ptr + j) == '\r') + break; + } + + msg.type = FETCH_HEADER; + msg.data.header_or_data.buf = (const uint8_t *)(ptr + plen); + msg.data.header_or_data.len = j - plen; + + char *xx = (char *) malloc(j - plen + 1); + strncpy(xx, ptr + plen, j-plen); + xx[j-plen] = '\0'; + LOG("Headerline: %s", xx); + fetch_send_callback(&msg, t->owner); + free(xx); + + plen = j + 2; + } + + t->headercbdone = true; + } + else if(t->handle->status >= 300 && t->handle->status < 400) { + if(t->handle->status == 304) { + fetch_msg msg; + msg.type = FETCH_NOTMODIFIED; + fetch_send_callback(&msg, t->owner); + remove_from_poll(t->handle); + /* t = t->next; */ + t = head; + continue; + } + else { + LOG("---- finding header 'location' for fetch 0x%x", t->owner); + fetch_msg msg; + int lenloc = 0; + char *tmp = http_find_header_field_asm(t->handle, "location"); + while(!isspace(*(tmp + lenloc))) lenloc++; + + msg.type = FETCH_REDIRECT; + char *newlocation = malloc(lenloc + 1); + strncpy(newlocation, tmp, lenloc); + newlocation[lenloc]='\0'; + msg.data.redirect = newlocation; + + LOG("---- [3xx] : Redirect to %s", msg.data.redirect); + fetch_send_callback(&msg, t->owner); + t->headercbdone = true; + LOG("---- call Remove t->handle = 0x%x", t->handle); + remove_from_poll(t->handle); + /* t = t->next; */ + t = head; + continue; + } + } + else { + fetch_msg msg; + msg.type = FETCH_ERROR; + LOG(" ---- [ERROR] Unhandled HTTP Code : %d", t->handle->status); + fetch_send_callback(&msg, t->owner); + t->headercbdone = true; + remove_from_poll(t->handle); + fetch_remove_from_queues(t->owner); + /* fetch_free(t->owner); */ + /* t = t->next; */ + t = head; + continue; + } + } + else { + LOG("---- Headers not received yet."); + } + } + else if(ret == 0) { + fetch_msg msg; + msg.type = FETCH_DATA; + msg.data.header_or_data.buf = (const uint8_t *)t->handle->content_ptr; + msg.data.header_or_data.len = t->handle->content_length; + fetch_send_callback(&msg, t->owner); + + LOG("---- FETCH_FINISHED for fetch 0x%x", t->owner); + + msg.type = FETCH_FINISHED; + msg.data.header_or_data.buf = NULL; + msg.data.header_or_data.len = 0; + fetch_send_callback(&msg, t->owner); + + struct httpfetcher *tnext = t->next; + remove_from_poll(t->handle); + fetch_remove_from_queues(t->owner); + /* fetch_free(t->owner); */ + t = head; + /* t = tnext; */ + continue; + } + + LOG("Main loop: t going from 0x%x to 0x%x", t->owner, t->next != NULL ? t->next->owner : "0"); + t = t->next; + } + + LOG("=Returning from %s", __func__); +} + +void finalize_fetcher(lwc_string *scheme) { + bool supported_scheme; + assert(lwc_string_isequal(scheme, corestring_lwc_http, &supported_scheme) == lwc_error_ok); + lwc_string_unref(scheme); +} + +static struct fetcher_operation_table fetcher_ops = { + .initialise = init_fetcher, + .acceptable = supported_url_check, + .setup = setup_fetch, + .start = start_fetch, + .abort = abort_fetch, + .free = free_fetch, + .poll = poll_fetch, + .finalise = finalize_fetcher +}; + +nserror fetch_httplib_kolibri_register(void) { + lwc_string *scheme = lwc_string_ref(corestring_lwc_http); + return fetcher_add(scheme, &fetcher_ops); +} diff --git a/content/fetchers/httplib_kolibri.h b/content/fetchers/httplib_kolibri.h new file mode 100644 index 000000000..5111a10b4 --- /dev/null +++ b/content/fetchers/httplib_kolibri.h @@ -0,0 +1,4 @@ +#include +#include + +nserror fetch_httplib_kolibri_register(void); -- cgit v1.2.3