X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fgns%2Fgnunet-gns-proxy.c;h=cdc18e3f6b156ca8bfab88ffcf423f4ce292c10a;hb=bcbd694ad35e182e5a1486b545ea0706082ee94a;hp=69c02774b5014c76b91ff5b05a9c3544b8a69dc6;hpb=d6f54d88f5aeddb925cf69337c83dca176e9ecee;p=oweals%2Fgnunet.git diff --git a/src/gns/gnunet-gns-proxy.c b/src/gns/gnunet-gns-proxy.c index 69c02774b..cdc18e3f6 100644 --- a/src/gns/gnunet-gns-proxy.c +++ b/src/gns/gnunet-gns-proxy.c @@ -34,8 +34,12 @@ #include #include +#define HAVE_MHD_NO_LISTEN_SOCKET MHD_VERSION >= 0x00091401 + #define GNUNET_GNS_PROXY_PORT 7777 #define MHD_MAX_CONNECTIONS 300 +#define MAX_HTTP_URI_LENGTH 2048 +#define POSTBUFFERSIZE 4096 /* MHD/cURL defines */ #define BUF_WAIT_FOR_CURL 0 @@ -187,9 +191,15 @@ struct ProxyCurlTask /* DLL for tasks */ struct ProxyCurlTask *next; + /* Already accepted */ + int accepted; + /* Handle to cURL */ CURL *curl; + /* is curl running? */ + int curl_running; + /* Optional header replacements for curl (LEHO) */ struct curl_slist *headers; @@ -200,7 +210,7 @@ struct ProxyCurlTask long curl_response_code; /* The URL to fetch */ - char url[2048]; + char url[MAX_HTTP_URI_LENGTH]; /* The cURL write buffer / MHD read buffer */ char buffer[CURL_MAX_WRITE_SIZE + CURL_BUF_PADDING]; @@ -250,6 +260,9 @@ struct ProxyCurlTask /* The hostname (Host header field) */ char host[256]; + /* The port */ + uint16_t port; + /* The LEgacy HOstname (can be empty) */ char leho[256]; @@ -273,6 +286,28 @@ struct ProxyCurlTask /* connection */ struct MHD_Connection *connection; + + /*put*/ + size_t put_read_offset; + size_t put_read_size; + + /*post*/ + struct MHD_PostProcessor *post_handler; + + /* post data */ + struct ProxyUploadData *upload_data_head; + struct ProxyUploadData *upload_data_tail; + + int post_done; + + /* the type of POST encoding */ + char* post_type; + + struct curl_httppost *httppost; + + struct curl_httppost *httppost_last; + + int is_httppost; }; @@ -324,6 +359,36 @@ struct ProxySetCookieHeader char *cookie; }; +/** + * Post data structure + */ +struct ProxyUploadData +{ + /* DLL */ + struct ProxyUploadData *next; + + /* DLL */ + struct ProxyUploadData *prev; + + char *key; + + char *filename; + + char *content_type; + + size_t content_length; + + /* value */ + char *value; + + /* to copy */ + size_t bytes_left; + + /* size */ + size_t total_bytes; +}; + + /* The port the proxy is running on (default 7777) */ static unsigned long port = GNUNET_GNS_PROXY_PORT; @@ -367,13 +432,13 @@ static struct MhdHttpList *mhd_httpd_tail; static regex_t re_dotplus; /* The users local GNS zone hash */ -static struct GNUNET_CRYPTO_ShortHashCode local_gns_zone; +static struct GNUNET_CRYPTO_ShortHashCode *local_gns_zone; /* The users local private zone */ -static struct GNUNET_CRYPTO_ShortHashCode local_private_zone; +static struct GNUNET_CRYPTO_ShortHashCode *local_private_zone; /* The users local shorten zone */ -static struct GNUNET_CRYPTO_ShortHashCode local_shorten_zone; +static struct GNUNET_CRYPTO_ShortHashCode *local_shorten_zone; /* The CA for SSL certificate generation */ static struct ProxyCA proxy_ca; @@ -410,19 +475,183 @@ is_tld(const char* name, const char* tld) return GNUNET_YES; } +/** + * convert integer to string representation + * + * @param i integer + * @return the character + */ +char i_to_hexchar (char i) +{ + static char hexmap[] = "0123456789abcdef"; + GNUNET_assert (sizeof (hexmap) > (i & 15)); + return hexmap[i & 15]; +} + +/** + * Escape given 0-terminated string + * + * @param to_esc string to escapse + * @return allocated new escaped string (MUST free!) + */ +static char* +escape_to_urlenc (const char *to_esc) +{ + char *pos = (char*)to_esc; + char *res = GNUNET_malloc (strlen (to_esc) * 3 + 1); + char *rpos = res; + + while ('\0' != *pos) + { + if (isalnum (*pos) || + ('-' == *pos) || ('_' == *pos) || + ('.' == *pos) || ('~' == *pos)) + *rpos++ = *pos; + else if (' ' == *pos) + *rpos++ = '+'; + else + { + *rpos++ = '%'; + *rpos++ = i_to_hexchar (*pos >> 4); + *rpos++ = i_to_hexchar (*pos >> 15); + } + pos++; + } + *rpos = '\0'; + return res; +} + static int -get_uri_val_iter (void *cls, +con_post_data_iter (void *cls, enum MHD_ValueKind kind, const char *key, - const char *value) + const char *filename, + const char *content_type, + const char *transfer_encoding, + const char *data, + uint64_t off, + size_t size) { - char* buf = cls; + struct ProxyCurlTask* ctask = cls; + struct ProxyUploadData* pdata; + char* enc; + char* new_value; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Got POST data: '%s : %s' at offset %llu size %lld\n", + key, data, off, size); - sprintf (buf+strlen (buf), "?%s=%s", key, value); + GNUNET_assert (NULL != ctask->post_type); + if (0 == strcasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, + ctask->post_type)) + { + ctask->is_httppost = GNUNET_YES; + /* new part */ + if (0 == off) + { + pdata = GNUNET_malloc (sizeof (struct ProxyUploadData)); + pdata->key = strdup (key); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Copied %lld\n"); + + if (NULL != filename) + { + pdata->filename = strdup (filename); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Filename %s\n", filename); + } + + if (NULL != content_type) + { + pdata->content_type = strdup (content_type); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Content-Type %s\n", content_type); + } + + pdata->value = GNUNET_malloc (size); + pdata->total_bytes = size; + memcpy (pdata->value, data, size); + GNUNET_CONTAINER_DLL_insert_tail (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Copied %lld bytes of POST Data\n", size); + return MHD_YES; + } + + pdata = ctask->upload_data_tail; + new_value = GNUNET_malloc (size + pdata->total_bytes); + memcpy (new_value, pdata->value, pdata->total_bytes); + memcpy (new_value+off, data, size); + GNUNET_free (pdata->value); + pdata->value = new_value; + pdata->total_bytes += size; + + return MHD_YES; + + } + + if (0 != strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, + ctask->post_type)) + { + return MHD_NO; + } + + ctask->is_httppost = GNUNET_NO; + + if (NULL != ctask->curl) + curl_easy_pause (ctask->curl, CURLPAUSE_CONT); + + if (0 == off) + { + /* a key */ + pdata = GNUNET_malloc (sizeof (struct ProxyUploadData)); + enc = escape_to_urlenc (key); + pdata->value = GNUNET_malloc (strlen (enc) + 3); + if (NULL != ctask->upload_data_head) + { + pdata->value[0] = '&'; + memcpy (pdata->value+1, enc, strlen (enc)); + } + else + memcpy (pdata->value, enc, strlen (enc)); + pdata->value[strlen (pdata->value)] = '='; + pdata->bytes_left = strlen (pdata->value); + pdata->total_bytes = pdata->bytes_left; + GNUNET_free (enc); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Escaped POST key: '%s'\n", + pdata->value); + + GNUNET_CONTAINER_DLL_insert_tail (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); + } + + /* a value */ + pdata = GNUNET_malloc (sizeof (struct ProxyUploadData)); + enc = escape_to_urlenc (data); + pdata->value = GNUNET_malloc (strlen (enc) + 1); + memcpy (pdata->value, enc, strlen (enc)); + pdata->bytes_left = strlen (pdata->value); + pdata->total_bytes = pdata->bytes_left; + GNUNET_free (enc); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Escaped POST value: '%s'\n", + pdata->value); + + GNUNET_CONTAINER_DLL_insert_tail (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); return MHD_YES; } + /** * Read HTTP request header field 'Host' * @@ -440,12 +669,28 @@ con_val_iter (void *cls, { struct ProxyCurlTask *ctask = cls; char* buf = ctask->host; + char* port; char* cstr; const char* hdr_val; + unsigned int uport; if (0 == strcmp ("Host", key)) { - strcpy (buf, value); + port = strstr (value, ":"); + if (NULL != port) + { + strncpy (buf, value, port-value); + port++; + if ((1 != sscanf (port, "%u", &uport)) || + (uport > UINT16_MAX) || + (0 == uport)) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Unable to parse port!\n"); + else + ctask->port = (uint16_t) uport; + } + else + strcpy (buf, value); return MHD_YES; } @@ -454,6 +699,22 @@ con_val_iter (void *cls, else hdr_val = value; + if (0 == strcasecmp (MHD_HTTP_HEADER_CONTENT_TYPE, + key)) + { + if (0 == strncasecmp (value, + MHD_HTTP_POST_ENCODING_FORM_URLENCODED, + strlen (MHD_HTTP_POST_ENCODING_FORM_URLENCODED))) + ctask->post_type = MHD_HTTP_POST_ENCODING_FORM_URLENCODED; + else if (0 == strncasecmp (value, + MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, + strlen (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))) + ctask->post_type = MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA; + else + ctask->post_type = NULL; + + } + cstr = GNUNET_malloc (strlen (key) + strlen (hdr_val) + 3); GNUNET_snprintf (cstr, strlen (key) + strlen (hdr_val) + 3, "%s: %s", key, hdr_val); @@ -502,6 +763,9 @@ curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls) char hdr_mime[html_mime_len+1]; char hdr_generic[bytes+1]; char new_cookie_hdr[bytes+strlen (ctask->leho)+1]; + char new_location[MAX_HTTP_URI_LENGTH+500]; + char real_host[264]; + char leho_host[264]; char* ndup; char* tok; char* cookie_domain; @@ -509,6 +773,7 @@ curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls) char* hdr_val; int delta_cdomain; size_t offset = 0; + char cors_hdr[strlen (ctask->leho) + strlen ("https://")]; if (NULL == ctask->response) { @@ -520,8 +785,30 @@ curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls) &mhd_content_cb, ctask, NULL); + + /* if we have a leho add a CORS header */ + if (0 != strcmp ("", ctask->leho)) + { + /* We could also allow ssl and http here */ + if (ctask->mhd->is_ssl) + sprintf (cors_hdr, "https://%s", ctask->leho); + else + sprintf (cors_hdr, "http://%s", ctask->leho); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: Adding CORS header field %s\n", + cors_hdr); + + if (GNUNET_NO == MHD_add_response_header (ctask->response, + "Access-Control-Allow-Origin", + cors_hdr)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "MHD: Error adding CORS header field %s\n", + cors_hdr); + } + } ctask->ready_to_queue = GNUNET_YES; - } if (html_mime_len <= bytes) @@ -610,24 +897,11 @@ curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls) offset++; } - //memcpy (new_cookie_hdr+offset, tok, strlen (tok)); - GNUNET_free (ndup); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got Set-Cookie HTTP header %s\n", new_cookie_hdr); - //pch = GNUNET_malloc (sizeof (struct ProxySetCookieHeader)); - //len = strlen (hdr_cookie) - cookie_hdr_len - 1; - //pch->cookie = GNUNET_malloc (len + 1); - //memset (pch->cookie, 0, len + 1); - //memcpy (pch->cookie, hdr_cookie+cookie_hdr_len+1, len); - //GNUNET_CONTAINER_DLL_insert (ctask->set_cookies_head, - // ctask->set_cookies_tail, - // pch); - //pch = ctask->set_cookies_head; - //while (pch != NULL) - //{ if (GNUNET_NO == MHD_add_response_header (ctask->response, MHD_HTTP_HEADER_SET_COOKIE, new_cookie_hdr)) @@ -637,40 +911,61 @@ curl_check_hdr (void *buffer, size_t size, size_t nmemb, void *cls) hdr_generic+cookie_hdr_len+1); } return bytes; - //GNUNET_free (pch->cookie); - //GNUNET_CONTAINER_DLL_remove (ctask->set_cookies_head, - // ctask->set_cookies_tail, - // pch); - //GNUNET_free (pch); - //pch = ctask->set_cookies_head; - //} } ndup = GNUNET_strdup (hdr_generic); hdr_type = strtok (ndup, ":"); - if (hdr_type != NULL) + if (NULL == hdr_type) + { + GNUNET_free (ndup); + return bytes; + } + + hdr_val = strtok (NULL, ""); + + if (NULL == hdr_val) + { + GNUNET_free (ndup); + return bytes; + } + + hdr_val++; + + if (0 == strcasecmp (MHD_HTTP_HEADER_LOCATION, hdr_type)) { - hdr_val = strtok (NULL, ""); - if (hdr_val != NULL) + if (ctask->mhd->is_ssl) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Trying to set %s: %s\n", - hdr_type, - hdr_val+1); - if (GNUNET_NO == MHD_add_response_header (ctask->response, - hdr_type, - hdr_val+1)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "MHD: Error adding %s header field %s\n", - hdr_type, - hdr_val+1); - } + sprintf (leho_host, "https://%s", ctask->leho); + sprintf (real_host, "https://%s", ctask->host); + } + else + { + sprintf (leho_host, "http://%s", ctask->leho); + sprintf (real_host, "http://%s", ctask->host); + } + + if (0 == memcmp (leho_host, hdr_val, strlen (leho_host))) + { + sprintf (new_location, "%s%s", real_host, hdr_val+strlen (leho_host)); + hdr_val = new_location; } } - GNUNET_free (ndup); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Trying to set %s: %s\n", + hdr_type, + hdr_val); + if (GNUNET_NO == MHD_add_response_header (ctask->response, + hdr_type, + hdr_val)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "MHD: Error adding %s header field %s\n", + hdr_type, + hdr_val); + } + GNUNET_free (ndup); return bytes; } @@ -731,8 +1026,9 @@ mhd_content_free (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct ProxyCurlTask *ctask = cls; - GNUNET_assert (NULL == ctask->pp_match_head); + struct ProxyUploadData *pdata; + GNUNET_assert (NULL == ctask->pp_match_head); if (NULL != ctask->headers) curl_slist_free_all (ctask->headers); @@ -742,7 +1038,20 @@ mhd_content_free (void *cls, if (NULL != ctask->response) MHD_destroy_response (ctask->response); + if (NULL != ctask->post_handler) + MHD_destroy_post_processor (ctask->post_handler); + for (pdata = ctask->upload_data_head; NULL != pdata; pdata = ctask->upload_data_head) + { + GNUNET_CONTAINER_DLL_remove (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); + GNUNET_free_non_null (pdata->filename); + GNUNET_free_non_null (pdata->content_type); + GNUNET_free_non_null (pdata->key); + GNUNET_free_non_null (pdata->value); + GNUNET_free (pdata); + } GNUNET_free (ctask); } @@ -763,7 +1072,7 @@ mhd_content_cb (void *cls, size_t max) { struct ProxyCurlTask *ctask = cls; - struct ProxyREMatch *re_match = ctask->pp_match_head; + struct ProxyREMatch *re_match; ssize_t copied = 0; long long int bytes_to_copy = ctask->buffer_write_ptr - ctask->buffer_read_ptr; @@ -774,10 +1083,10 @@ mhd_content_cb (void *cls, if ((GNUNET_YES == ctask->download_is_finished) && (GNUNET_NO == ctask->download_error) && - (0 == bytes_to_copy) && - (BUF_WAIT_FOR_CURL == ctask->buf_status)) + (0 == bytes_to_copy)) /* && + (BUF_WAIT_FOR_CURL == ctask->buf_status))*/ { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "MHD: sending response for %s\n", ctask->url); ctask->download_in_progress = GNUNET_NO; run_mhd_now (ctask->mhd); @@ -788,10 +1097,10 @@ mhd_content_cb (void *cls, if ((GNUNET_YES == ctask->download_error) && (GNUNET_YES == ctask->download_is_finished) && - (0 == bytes_to_copy) && - (BUF_WAIT_FOR_CURL == ctask->buf_status)) + (0 == bytes_to_copy)) /* && + (BUF_WAIT_FOR_CURL == ctask->buf_status))*/ { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "MHD: sending error response\n"); ctask->download_in_progress = GNUNET_NO; run_mhd_now (ctask->mhd); @@ -804,7 +1113,7 @@ mhd_content_cb (void *cls, return 0; copied = 0; - for (; NULL != re_match; re_match = ctask->pp_match_head) + for (re_match = ctask->pp_match_head; NULL != re_match; re_match = ctask->pp_match_head) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MHD: Processing PP %s\n", @@ -856,7 +1165,7 @@ mhd_content_cb (void *cls, return copied; } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MHD: Adding PP result %s to buffer\n", re_match->result); memcpy (buf+copied, re_match->result, strlen (re_match->result)); @@ -870,7 +1179,7 @@ mhd_content_cb (void *cls, bytes_to_copy = ctask->buffer_write_ptr - ctask->buffer_read_ptr; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MHD: copied: %d left: %d, space left in buf: %d\n", copied, bytes_to_copy, max-copied); @@ -879,7 +1188,7 @@ mhd_content_cb (void *cls, if (GNUNET_NO == ctask->download_is_finished) { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MHD: Purging buffer\n"); memmove (ctask->buffer, ctask->buffer_read_ptr, bytes_to_copy); ctask->buffer_read_ptr = ctask->buffer; @@ -898,9 +1207,6 @@ mhd_content_cb (void *cls, copied += bytes_to_copy; ctask->buf_status = BUF_WAIT_FOR_CURL; - //if ((NULL != ctask->curl) && - // (GNUNET_NO == ctask->download_is_finished) && - // ((ctask->buffer_write_ptr - ctask->buffer_read_ptr) <= 0)) if (NULL != ctask->curl) curl_easy_pause (ctask->curl, CURLPAUSE_CONT); @@ -910,6 +1216,7 @@ mhd_content_cb (void *cls, return copied; } + /** * Shorten result callback * @@ -924,7 +1231,7 @@ process_shorten (void* cls, const char* short_name) if (NULL == short_name) { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PP: Unable to shorten %s\n", re_match->hostname); GNUNET_CONTAINER_DLL_remove (re_match->ctask->pp_match_head, @@ -939,11 +1246,11 @@ process_shorten (void* cls, const char* short_name) else strcpy (result, short_name); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PP: Shorten %s -> %s\n", re_match->hostname, result); - //this is evil.. what about https + if (re_match->ctask->mhd->is_ssl) sprintf (re_match->result, "href=\"https://%s", result); else @@ -955,8 +1262,10 @@ process_shorten (void* cls, const char* short_name) /** - * Tabula Rasa postprocess buffer + * Postprocess data in buffer. From read ptr to write ptr * + * @param cls the curlproxytask + * @param tc task context */ static void postprocess_buffer (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) @@ -971,20 +1280,20 @@ postprocess_buffer (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) if (GNUNET_YES != ctask->parse_content) { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PP: Not parsing content\n"); ctask->buf_status = BUF_WAIT_FOR_MHD; run_mhd_now (ctask->mhd); return; } - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PP: We need to parse the HTML\n"); /* 0 means match found */ while (0 == regexec (&re_dotplus, re_ptr, RE_N_MATCHES, m, 0)) { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PP: regex match\n"); GNUNET_assert (m[1].rm_so != -1); @@ -994,14 +1303,12 @@ postprocess_buffer (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) re_match = GNUNET_malloc (sizeof (struct ProxyREMatch)); re_match->start = re_ptr + m[0].rm_so; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "XXXXX: %d\n", re_match->start); re_match->end = re_ptr + m[3].rm_eo; re_match->done = GNUNET_NO; re_match->ctask = ctask; strcpy (re_match->hostname, re_hostname); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Got hostname %s\n", re_hostname); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "PP: Got hostname %s\n", re_hostname); re_ptr += m[3].rm_eo; if (GNUNET_YES == is_tld (re_match->hostname, GNUNET_GNS_TLD_PLUS)) @@ -1013,9 +1320,9 @@ postprocess_buffer (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) re_match->shorten_task = GNUNET_GNS_shorten_zone (gns_handle, re_match->hostname, - &local_private_zone, - &local_shorten_zone, - &local_gns_zone, + local_private_zone, + local_shorten_zone, + local_gns_zone, &process_shorten, re_match); //FIXME cancel appropriately @@ -1025,14 +1332,19 @@ postprocess_buffer (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } ctask->buf_status = BUF_WAIT_FOR_MHD; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PP: No more matches\n"); run_mhd_now (ctask->mhd); } /** - * Tabula Rasa cURL download + * Handle data from cURL * + * @param ptr pointer to the data + * @param size number of blocks of data + * @param nmemb blocksize + * @param ctx the curlproxytask + * @return number of bytes handled */ static size_t curl_download_cb (void *ptr, size_t size, size_t nmemb, void* ctx) @@ -1043,15 +1355,18 @@ curl_download_cb (void *ptr, size_t size, size_t nmemb, void* ctx) size_t buf_space = sizeof (ctask->buffer) - (ctask->buffer_write_ptr-ctask->buffer); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CURL: Got %d. %d free in buffer\n", total, buf_space); + if (BUF_WAIT_FOR_CURL != ctask->buf_status) + return CURL_WRITEFUNC_PAUSE; + if (total > (buf_space - CURL_BUF_PADDING)) { if (ctask->buf_status == BUF_WAIT_FOR_CURL) { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CURL: Buffer full starting postprocessing\n"); ctask->buf_status = BUF_WAIT_FOR_PP; ctask->pp_task = GNUNET_SCHEDULER_add_now (&postprocess_buffer, @@ -1072,10 +1387,115 @@ curl_download_cb (void *ptr, size_t size, size_t nmemb, void* ctx) ctask->buffer_write_ptr += total; ctask->buffer_write_ptr[0] = '\0'; - //run_mhd_now (ctask->mhd); return total; } + +/** + * cURL callback for put data + */ +static size_t +put_read_callback (void *buf, size_t size, size_t nmemb, void *cls) +{ + struct ProxyCurlTask *ctask = cls; + struct ProxyUploadData *pdata = ctask->upload_data_head; + size_t len = size * nmemb; + size_t to_copy; + char* pos; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: put read callback\n"); + + if (NULL == pdata) + return CURL_READFUNC_PAUSE; + + //fin + if (NULL == pdata->value) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: Terminating PUT\n"); + + GNUNET_CONTAINER_DLL_remove (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); + GNUNET_free (pdata); + return 0; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: read callback value %s\n", pdata->value); + + to_copy = pdata->bytes_left; + if (to_copy > len) + to_copy = len; + + pos = pdata->value + (pdata->total_bytes - pdata->bytes_left); + memcpy (buf, pos, to_copy); + pdata->bytes_left -= to_copy; + if (pdata->bytes_left <= 0) + { + GNUNET_free (pdata->value); + GNUNET_CONTAINER_DLL_remove (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); + GNUNET_free (pdata); + } + return to_copy; +} + + +/** + * cURL callback for post data + */ +static size_t +post_read_callback (void *buf, size_t size, size_t nmemb, void *cls) +{ + struct ProxyCurlTask *ctask = cls; + struct ProxyUploadData *pdata = ctask->upload_data_head; + size_t len = size * nmemb; + size_t to_copy; + char* pos; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: read callback\n"); + + if (NULL == pdata) + return CURL_READFUNC_PAUSE; + + //fin + if (NULL == pdata->value) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: Terminating POST data\n"); + + GNUNET_CONTAINER_DLL_remove (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); + GNUNET_free (pdata); + return 0; + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CURL: read callback value %s\n", pdata->value); + + to_copy = pdata->bytes_left; + if (to_copy > len) + to_copy = len; + + pos = pdata->value + (pdata->total_bytes - pdata->bytes_left); + memcpy (buf, pos, to_copy); + pdata->bytes_left -= to_copy; + if (pdata->bytes_left <= 0) + { + GNUNET_free (pdata->value); + GNUNET_CONTAINER_DLL_remove (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); + GNUNET_free (pdata); + } + return to_copy; +} + /** * Task that is run when we are ready to receive more data * from curl @@ -1134,14 +1554,23 @@ curl_download_prepare () if (curl_download_task != GNUNET_SCHEDULER_NO_TASK) GNUNET_SCHEDULER_cancel (curl_download_task); - curl_download_task = - GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, - rtime, - grs, gws, - &curl_task_download, curl_multi); + if (-1 != max) + { + curl_download_task = + GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT, + rtime, + grs, gws, + &curl_task_download, curl_multi); + } + else if (NULL != ctasks_head) + { + /* as specified in curl docs */ + curl_download_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, + &curl_task_download, + curl_multi); + } GNUNET_NETWORK_fdset_destroy (gws); GNUNET_NETWORK_fdset_destroy (grs); - } @@ -1170,10 +1599,10 @@ curl_task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Shutdown requested while trying to download\n"); - //TODO cleanup - return; + //TODO cleanup + return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ready to dl\n"); @@ -1188,8 +1617,7 @@ curl_task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Running curl tasks: %d\n", running); - ctask = ctasks_head; - for (; ctask != NULL; ctask = ctask->next) + for (ctask = ctasks_head; NULL != ctask; ctask = ctask->next) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CTask: %s\n", ctask->url); @@ -1204,7 +1632,7 @@ curl_task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) do { - ctask = ctasks_head; + msg = curl_multi_info_read (curl_multi, &msgnum); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Messages left: %d\n", msgnum); @@ -1220,7 +1648,7 @@ curl_task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Download curl failed"); - for (; ctask != NULL; ctask = ctask->next) + for (ctask = ctasks_head; NULL != ctask; ctask = ctask->next) { if (NULL == ctask->curl) continue; @@ -1254,19 +1682,16 @@ curl_task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CURL: download completed.\n"); - for (; ctask != NULL; ctask = ctask->next) + for (ctask = ctasks_head; NULL != ctask; ctask = ctask->next) { if (NULL == ctask->curl) continue; - if (memcmp (msg->easy_handle, ctask->curl, sizeof (CURL)) != 0) - continue; - - if (ctask->buf_status != BUF_WAIT_FOR_CURL) + if (0 != memcmp (msg->easy_handle, ctask->curl, sizeof (CURL))) continue; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "CURL: task %s found.\n", ctask->url); + "CURL: completed task %s found.\n", ctask->url); if (CURLE_OK == curl_easy_getinfo (ctask->curl, CURLINFO_RESPONSE_CODE, &resp_code)) @@ -1282,11 +1707,9 @@ curl_task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) ctask); } - //ctask->ready_to_queue = MHD_YES; + ctask->ready_to_queue = MHD_YES; ctask->download_is_finished = GNUNET_YES; - //GNUNET_SCHEDULER_add_now (&run_mhd, ctask->mhd); - /* We MUST not modify the multi handle else we loose messages */ GNUNET_CONTAINER_DLL_remove (ctasks_head, ctasks_tail, ctask); @@ -1305,7 +1728,7 @@ curl_task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } } while (msgnum > 0); - for (ctask=clean_head; ctask != NULL; ctask = ctask->next) + for (ctask=clean_head; NULL != ctask; ctask = ctask->next) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CURL: Removing task %s.\n", ctask->url); @@ -1315,7 +1738,7 @@ curl_task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } num_ctasks=0; - for (ctask=ctasks_head; ctask != NULL; ctask = ctask->next) + for (ctask=ctasks_head; NULL != ctask; ctask = ctask->next) { num_ctasks++; } @@ -1328,7 +1751,6 @@ curl_task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_assert ( num_ctasks == running ); - run_httpds (); } while (mret == CURLM_CALL_MULTI_PERFORM); if (mret != CURLM_OK) @@ -1340,6 +1762,7 @@ curl_task_download (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) curl_download_prepare(); } + /** * Process LEHO lookup * @@ -1381,7 +1804,7 @@ process_leho_lookup (void *cls, if (0 != strcmp (ctask->leho, "")) { - sprintf (hosthdr, "%s%s", "Host: ", ctask->leho); + sprintf (hosthdr, "%s%s:%d", "Host: ", ctask->leho, ctask->port); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New HTTP header value: %s\n", hosthdr); ctask->headers = curl_slist_append (ctask->headers, hosthdr); @@ -1409,7 +1832,7 @@ process_leho_lookup (void *cls, "Curl resolve: %s\n", resolvename); ctask->resolver = curl_slist_append ( ctask->resolver, resolvename); curl_easy_setopt (ctask->curl, CURLOPT_RESOLVE, ctask->resolver); - sprintf (curlurl, "https://%s%s", ctask->leho, ctask->url); + sprintf (curlurl, "https://%s:%d%s", ctask->leho, ctask->port, ctask->url); curl_easy_setopt (ctask->curl, CURLOPT_URL, curlurl); } else @@ -1466,7 +1889,7 @@ process_get_authority (void *cls, GNUNET_GNS_lookup_zone (gns_handle, ctask->host, - &local_gns_zone, + local_gns_zone, GNUNET_GNS_RECORD_LEHO, GNUNET_YES, //Only cached for performance shorten_zonekey, @@ -1474,6 +1897,16 @@ process_get_authority (void *cls, ctask); } +static void* +mhd_log_callback (void* cls, const char* url) +{ + struct ProxyCurlTask *ctask; + + ctask = GNUNET_malloc (sizeof (struct ProxyCurlTask)); + strcpy (ctask->url, url); + ctask->accepted = GNUNET_NO; + return ctask; +} /** * Main MHD callback for handling requests. @@ -1512,35 +1945,36 @@ create_response (void *cls, const char* page = "gnoxy"\ "cURL fail"; - char curlurl[512]; // buffer overflow! + char curlurl[MAX_HTTP_URI_LENGTH]; // buffer overflow! int ret = MHD_YES; + int i; - struct ProxyCurlTask *ctask; + struct ProxyCurlTask *ctask = *con_cls; + struct ProxyUploadData *fin_post; + struct curl_forms forms[5]; + struct ProxyUploadData *upload_data_iter; //FIXME handle - if (0 != strcasecmp (meth, MHD_HTTP_METHOD_GET)) + if ((0 != strcasecmp (meth, MHD_HTTP_METHOD_GET)) && + (0 != strcasecmp (meth, MHD_HTTP_METHOD_PUT)) && + (0 != strcasecmp (meth, MHD_HTTP_METHOD_POST)) && + (0 != strcasecmp (meth, MHD_HTTP_METHOD_HEAD))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "MHD: %s NOT IMPLEMENTED!\n", meth); return MHD_NO; } - if (0 != *upload_data_size) - return MHD_NO; - if (NULL == *con_cls) + if (GNUNET_NO == ctask->accepted) { - ctask = GNUNET_malloc (sizeof (struct ProxyCurlTask)); - ctask->mhd = hd; - *con_cls = ctask; - - // FIXME: probably not best here, also never free'ed... - if (NULL == curl_multi) - curl_multi = curl_multi_init (); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Got %s request for %s\n", meth, url); + ctask->mhd = hd; ctask->curl = curl_easy_init(); - - if ((NULL == ctask->curl) || (NULL == curl_multi)) // ugh, curl_multi init failure check MUCH earlier + ctask->curl_running = GNUNET_NO; + if (NULL == ctask->curl) { ctask->response = MHD_create_response_from_buffer (strlen (page), (void*)page, @@ -1552,46 +1986,83 @@ create_response (void *cls, GNUNET_free (ctask); return ret; } - - ctask->download_in_progress = GNUNET_YES; - ctask->buf_status = BUF_WAIT_FOR_CURL; - ctask->connection = con; - ctask->curl_response_code = MHD_HTTP_OK; - ctask->buffer_read_ptr = ctask->buffer; - ctask->buffer_write_ptr = ctask->buffer; - ctask->pp_task = GNUNET_SCHEDULER_NO_TASK; + + if (ctask->mhd->is_ssl) + ctask->port = HTTPS_PORT; + else + ctask->port = HTTP_PORT; MHD_get_connection_values (con, MHD_HEADER_KIND, &con_val_iter, ctask); - + curl_easy_setopt (ctask->curl, CURLOPT_HEADERFUNCTION, &curl_check_hdr); curl_easy_setopt (ctask->curl, CURLOPT_HEADERDATA, ctask); curl_easy_setopt (ctask->curl, CURLOPT_WRITEFUNCTION, &curl_download_cb); curl_easy_setopt (ctask->curl, CURLOPT_WRITEDATA, ctask); curl_easy_setopt (ctask->curl, CURLOPT_FOLLOWLOCATION, 0); curl_easy_setopt (ctask->curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); - //curl_easy_setopt (ctask->curl, CURLOPT_MAXREDIRS, 4); - /* no need to abort if the above failed */ + if (GNUNET_NO == ctask->mhd->is_ssl) { - sprintf (curlurl, "http://%s%s", ctask->host, url); - MHD_get_connection_values (con, - MHD_GET_ARGUMENT_KIND, - &get_uri_val_iter, curlurl); + sprintf (curlurl, "http://%s:%d%s", ctask->host, ctask->port, ctask->url); curl_easy_setopt (ctask->curl, CURLOPT_URL, curlurl); } - strcpy (ctask->url, url); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "MHD: Adding new curl task for %s%s\n", ctask->host, url); - MHD_get_connection_values (con, - MHD_GET_ARGUMENT_KIND, - &get_uri_val_iter, ctask->url); - - //curl_easy_setopt (ctask->curl, CURLOPT_URL, curlurl); + + curl_easy_setopt (ctask->curl, CURLOPT_FAILONERROR, 1); curl_easy_setopt (ctask->curl, CURLOPT_CONNECTTIMEOUT, 600L); curl_easy_setopt (ctask->curl, CURLOPT_TIMEOUT, 600L); + + /* Add GNS header */ + ctask->headers = curl_slist_append (ctask->headers, + "GNS: YES"); + ctask->accepted = GNUNET_YES; + ctask->download_in_progress = GNUNET_YES; + ctask->buf_status = BUF_WAIT_FOR_CURL; + ctask->connection = con; + ctask->curl_response_code = MHD_HTTP_OK; + ctask->buffer_read_ptr = ctask->buffer; + ctask->buffer_write_ptr = ctask->buffer; + ctask->pp_task = GNUNET_SCHEDULER_NO_TASK; + + + if (0 == strcasecmp (meth, MHD_HTTP_METHOD_PUT)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Setting up PUT\n"); + + curl_easy_setopt (ctask->curl, CURLOPT_UPLOAD, 1); + curl_easy_setopt (ctask->curl, CURLOPT_READDATA, ctask); + curl_easy_setopt (ctask->curl, CURLOPT_READFUNCTION, &put_read_callback); + ctask->headers = curl_slist_append (ctask->headers, + "Transfer-Encoding: chunked"); + } + + if (0 == strcasecmp (meth, MHD_HTTP_METHOD_POST)) + { + //FIXME handle multipart + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Setting up POST processor\n"); + ctask->post_handler = MHD_create_post_processor (con, + POSTBUFFERSIZE, + &con_post_data_iter, + ctask); + ctask->headers = curl_slist_append (ctask->headers, + "Transfer-Encoding: chunked"); + return MHD_YES; + } + + if (0 == strcasecmp (meth, MHD_HTTP_METHOD_HEAD)) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Setting NOBODY\n"); + curl_easy_setopt (ctask->curl, CURLOPT_NOBODY, 1); + } + + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: Adding new curl task for %s\n", ctask->host); GNUNET_GNS_get_authority (gns_handle, ctask->host, @@ -1599,10 +2070,109 @@ create_response (void *cls, ctask); ctask->ready_to_queue = GNUNET_NO; ctask->fin = GNUNET_NO; + ctask->curl_running = GNUNET_YES; return MHD_YES; } ctask = (struct ProxyCurlTask *) *con_cls; + if (0 == strcasecmp (meth, MHD_HTTP_METHOD_POST)) + { + if (0 != *upload_data_size) + { + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Invoking POST processor\n"); + MHD_post_process (ctask->post_handler, + upload_data, *upload_data_size); + *upload_data_size = 0; + if ((GNUNET_NO == ctask->is_httppost) && + (GNUNET_NO == ctask->curl_running)) + { + curl_easy_setopt (ctask->curl, CURLOPT_POST, 1); + curl_easy_setopt (ctask->curl, CURLOPT_READFUNCTION, + &post_read_callback); + curl_easy_setopt (ctask->curl, CURLOPT_READDATA, ctask); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: Adding new curl task for %s\n", ctask->host); + + GNUNET_GNS_get_authority (gns_handle, + ctask->host, + &process_get_authority, + ctask); + ctask->ready_to_queue = GNUNET_NO; + ctask->fin = GNUNET_NO; + ctask->curl_running = GNUNET_YES; + } + return MHD_YES; + } + else if (GNUNET_NO == ctask->post_done) + { + if (GNUNET_YES == ctask->is_httppost) + { + for (upload_data_iter = ctask->upload_data_head; + NULL != upload_data_iter; + upload_data_iter = upload_data_iter->next) + { + i = 0; + if (NULL != upload_data_iter->filename) + { + forms[i].option = CURLFORM_FILENAME; + forms[i].value = upload_data_iter->filename; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Adding filename %s\n", + forms[i].value); + i++; + } + if (NULL != upload_data_iter->content_type) + { + forms[i].option = CURLFORM_CONTENTTYPE; + forms[i].value = upload_data_iter->content_type; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Adding content type %s\n", + forms[i].value); + i++; + } + forms[i].option = CURLFORM_PTRCONTENTS; + forms[i].value = upload_data_iter->value; + forms[i+1].option = CURLFORM_END; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Adding formdata for %s (len=%lld)\n", + upload_data_iter->key, + upload_data_iter->total_bytes); + + curl_formadd(&ctask->httppost, &ctask->httppost_last, + CURLFORM_COPYNAME, upload_data_iter->key, + CURLFORM_CONTENTSLENGTH, upload_data_iter->total_bytes, + CURLFORM_ARRAY, forms, + CURLFORM_END); + } + curl_easy_setopt (ctask->curl, CURLOPT_HTTPPOST, + ctask->httppost); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "MHD: Adding new curl task for %s\n", ctask->host); + + GNUNET_GNS_get_authority (gns_handle, + ctask->host, + &process_get_authority, + ctask); + ctask->ready_to_queue = GNUNET_YES; + ctask->fin = GNUNET_NO; + ctask->curl_running = GNUNET_YES; + ctask->post_done = GNUNET_YES; + return MHD_YES; + } + + fin_post = GNUNET_malloc (sizeof (struct ProxyUploadData)); + GNUNET_CONTAINER_DLL_insert_tail (ctask->upload_data_head, + ctask->upload_data_tail, + fin_post); + ctask->post_done = GNUNET_YES; + return MHD_YES; + } + } if (GNUNET_YES != ctask->ready_to_queue) return MHD_YES; /* wait longer */ @@ -1627,7 +2197,7 @@ run_httpds () { struct MhdHttpList *hd; - for (hd=mhd_httpd_head; hd != NULL; hd = hd->next) + for (hd=mhd_httpd_head; NULL != hd; hd = hd->next) run_httpd (hd); } @@ -1666,7 +2236,7 @@ run_httpd (struct MhdHttpList *hd) haveto = MHD_get_timeout (hd->daemon, &timeout); - if (haveto == MHD_YES) + if (MHD_YES == haveto) tv.rel_value = (uint64_t) timeout; else tv = GNUNET_TIME_UNIT_FOREVER_REL; @@ -1674,7 +2244,7 @@ run_httpd (struct MhdHttpList *hd) GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1); GNUNET_NETWORK_fdset_copy_native (wes, &es, max + 1); - if (hd->httpd_task != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != hd->httpd_task) GNUNET_SCHEDULER_cancel (hd->httpd_task); hd->httpd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH, @@ -1751,12 +2321,11 @@ do_write_remote (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) else { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "write remote"); - //Really!?!?!? - if (s5r->rtask != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != s5r->rtask) GNUNET_SCHEDULER_cancel (s5r->rtask); - if (s5r->wtask != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != s5r->wtask) GNUNET_SCHEDULER_cancel (s5r->wtask); - if (s5r->fwdrtask != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != s5r->fwdrtask) GNUNET_SCHEDULER_cancel (s5r->fwdrtask); GNUNET_NETWORK_socket_close (s5r->remote_sock); GNUNET_NETWORK_socket_close (s5r->sock); @@ -1779,11 +2348,11 @@ do_write_remote (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) static void cleanup_s5r (struct Socks5Request *s5r) { - if (s5r->rtask != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != s5r->rtask) GNUNET_SCHEDULER_cancel (s5r->rtask); - if (s5r->fwdwtask != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != s5r->fwdwtask) GNUNET_SCHEDULER_cancel (s5r->fwdwtask); - if (s5r->fwdrtask != GNUNET_SCHEDULER_NO_TASK) + if (GNUNET_SCHEDULER_NO_TASK != s5r->fwdrtask) GNUNET_SCHEDULER_cancel (s5r->fwdrtask); if (NULL != s5r->remote_sock) @@ -2154,18 +2723,28 @@ add_handle_to_ssl_mhd (struct GNUNET_NETWORK_Handle *h, const char* domain) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No previous SSL instance found... starting new one for %s\n", domain); - - hd->daemon = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_SSL, 4444, - &accept_cb, NULL, - &create_response, hd, + hd->daemon = MHD_start_daemon (MHD_USE_DEBUG + | MHD_USE_SSL +#if HAVE_MHD_NO_LISTEN_SOCKET + | MHD_USE_NO_LISTEN_SOCKET, + 0, +#else + , 4444, //Dummy +#endif + &accept_cb, NULL, + &create_response, hd, +#if !HAVE_MHD_NO_LISTEN_SOCKET MHD_OPTION_LISTEN_SOCKET, GNUNET_NETWORK_get_fd (mhd_unix_socket), - MHD_OPTION_CONNECTION_LIMIT, MHD_MAX_CONNECTIONS, - MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16, - MHD_OPTION_NOTIFY_COMPLETED, - NULL, NULL, - MHD_OPTION_HTTPS_MEM_KEY, pgc->key, - MHD_OPTION_HTTPS_MEM_CERT, pgc->cert, - MHD_OPTION_END); +#endif + MHD_OPTION_CONNECTION_LIMIT, + MHD_MAX_CONNECTIONS, + MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16, + MHD_OPTION_NOTIFY_COMPLETED, NULL, NULL, + MHD_OPTION_HTTPS_MEM_KEY, pgc->key, + MHD_OPTION_HTTPS_MEM_CERT, pgc->cert, + MHD_OPTION_URI_LOG_CALLBACK, &mhd_log_callback, + NULL, + MHD_OPTION_END); GNUNET_assert (hd->daemon != NULL); hd->httpd_task = GNUNET_SCHEDULER_NO_TASK; @@ -2465,8 +3044,6 @@ do_read (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) } - //GNUNET_CONTAINER_DLL_remove (s5conns.head, s5conns.tail, s5r); - } @@ -2510,7 +3087,6 @@ do_accept (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) s5r->rtask = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, s5r->sock, &do_read, s5r); - //GNUNET_CONTAINER_DLL_insert (s5conns.head, s5conns.tail, s5r); } @@ -2531,11 +3107,19 @@ do_shutdown (void *cls, struct NetworkHandleList *tmp_nh; struct ProxyCurlTask *ctask; struct ProxyCurlTask *ctask_tmp; + struct ProxyUploadData *pdata; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shutting down...\n"); gnutls_global_deinit (); + + if (NULL != local_gns_zone) + GNUNET_free (local_gns_zone); + if (NULL != local_private_zone) + GNUNET_free (local_private_zone); + if (NULL != local_shorten_zone) + GNUNET_free (local_shorten_zone); if (GNUNET_SCHEDULER_NO_TASK != curl_download_task) { @@ -2602,9 +3186,24 @@ do_shutdown (void *cls, if (NULL != ctask->response) MHD_destroy_response (ctask->response); + pdata = ctask->upload_data_head; + + //FIXME free pdata here + for (; pdata != NULL; pdata = ctask->upload_data_head) + { + GNUNET_CONTAINER_DLL_remove (ctask->upload_data_head, + ctask->upload_data_tail, + pdata); + GNUNET_free_non_null (pdata->filename); + GNUNET_free_non_null (pdata->content_type); + GNUNET_free_non_null (pdata->key); + GNUNET_free_non_null (pdata->value); + GNUNET_free (pdata); + } GNUNET_free (ctask); } + curl_multi_cleanup (curl_multi); GNUNET_GNS_disconnect (gns_handle); } @@ -2667,69 +3266,74 @@ load_local_zone_key (const struct GNUNET_CONFIGURATION_Handle *cfg) key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); + local_gns_zone = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_ShortHashCode)); GNUNET_CRYPTO_short_hash(&pkey, sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &local_gns_zone); - zone = &local_gns_zone; + local_gns_zone); + zone = local_gns_zone; GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Using zone: %s!\n", &zonename); GNUNET_CRYPTO_rsa_key_free(key); GNUNET_free(keyfile); - + keyfile = NULL; + if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", "PRIVATE_ZONEKEY", &keyfile)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to load private zone key config value!\n"); - return GNUNET_NO; } - if (GNUNET_NO == GNUNET_DISK_file_test (keyfile)) + if ((NULL != keyfile) && (GNUNET_NO == GNUNET_DISK_file_test (keyfile))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to load private zone key %s!\n", keyfile); GNUNET_free(keyfile); - return GNUNET_NO; } - - key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); - GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); - GNUNET_CRYPTO_short_hash(&pkey, - sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &local_private_zone); - GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Using private zone: %s!\n", &zonename); - GNUNET_CRYPTO_rsa_key_free(key); - GNUNET_free(keyfile); + else + { + key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); + GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); + local_private_zone = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_ShortHashCode)); + GNUNET_CRYPTO_short_hash(&pkey, + sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + local_private_zone); + GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Using private zone: %s!\n", &zonename); + GNUNET_CRYPTO_rsa_key_free(key); + GNUNET_free(keyfile); + } + keyfile = NULL; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns", "SHORTEN_ZONEKEY", &keyfile)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to load shorten zone key config value!\n"); - return GNUNET_NO; } - if (GNUNET_NO == GNUNET_DISK_file_test (keyfile)) + if ((NULL != keyfile) && (GNUNET_NO == GNUNET_DISK_file_test (keyfile))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unable to load shorten zone key %s!\n", keyfile); GNUNET_free(keyfile); - return GNUNET_NO; } - - key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); - GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); - GNUNET_CRYPTO_short_hash(&pkey, - sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &local_shorten_zone); - GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Using shorten zone: %s!\n", &zonename); - GNUNET_CRYPTO_rsa_key_free(key); - GNUNET_free(keyfile); + else + { + key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile); + GNUNET_CRYPTO_rsa_key_get_public (key, &pkey); + local_shorten_zone = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_ShortHashCode)); + GNUNET_CRYPTO_short_hash(&pkey, + sizeof(struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + local_shorten_zone); + GNUNET_CRYPTO_short_hash_to_enc (zone, &zonename); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Using shorten zone: %s!\n", &zonename); + GNUNET_CRYPTO_rsa_key_free(key); + GNUNET_free(keyfile); + } return GNUNET_YES; } @@ -2748,19 +3352,26 @@ run (void *cls, char *const *args, const char *cfgfile, { struct sockaddr_in sa; struct MhdHttpList *hd; - struct sockaddr_un mhd_unix_sock_addr; - size_t len; - char* proxy_sockfile; char* cafile_cfg = NULL; char* cafile; +#if !HAVE_MHD_NO_LISTEN_SOCKET + size_t len; + char* proxy_sockfile; + struct sockaddr_un mhd_unix_sock_addr; +#endif - curl_multi = NULL; + curl_multi = curl_multi_init (); + if (NULL == curl_multi) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to create cURL multo handle!\n"); + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Loading CA\n"); - cafile = cafile_opt; - if (NULL == cafile) { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns-proxy", @@ -2775,9 +3386,10 @@ run (void *cls, char *const *args, const char *cfgfile, } cafile = cafile_cfg; } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Using %s as CA\n", cafile); gnutls_global_init (); - gnutls_x509_crt_init (&proxy_ca.cert); gnutls_x509_privkey_init (&proxy_ca.key); @@ -2863,7 +3475,7 @@ run (void *cls, char *const *args, const char *cfgfile, mhd_httpd_head = NULL; mhd_httpd_tail = NULL; total_mhd_connections = 0; - +#ifndef HAVE_MHD_NO_LISTEN_SOCKET if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns-proxy", "PROXY_UNIXPATH", &proxy_sockfile)) @@ -2872,7 +3484,7 @@ run (void *cls, char *const *args, const char *cfgfile, "Specify PROXY_UNIXPATH in gns-proxy config section!\n"); return; } - + mhd_unix_socket = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0); @@ -2914,18 +3526,28 @@ run (void *cls, char *const *args, const char *cfgfile, "Unable to listen on unix domain socket!\n"); return; } +#endif hd = GNUNET_malloc (sizeof (struct MhdHttpList)); hd->is_ssl = GNUNET_NO; strcpy (hd->domain, ""); - httpd = MHD_start_daemon (MHD_USE_DEBUG, 4444, //Dummy port + httpd = MHD_start_daemon (MHD_USE_DEBUG +#if HAVE_MHD_NO_LISTEN_SOCKET + | MHD_USE_NO_LISTEN_SOCKET, + 0, +#else + , 4444, //Dummy port +#endif &accept_cb, NULL, &create_response, hd, +#if !HAVE_MHD_NO_LISTEN_SOCKET MHD_OPTION_LISTEN_SOCKET, GNUNET_NETWORK_get_fd (mhd_unix_socket), +#endif MHD_OPTION_CONNECTION_LIMIT, MHD_MAX_CONNECTIONS, MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 16, MHD_OPTION_NOTIFY_COMPLETED, NULL, NULL, + MHD_OPTION_URI_LOG_CALLBACK, &mhd_log_callback, NULL, MHD_OPTION_END); GNUNET_assert (httpd != NULL);