gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r23069 - gnunet/src/gns


From: gnunet
Subject: [GNUnet-SVN] r23069 - gnunet/src/gns
Date: Fri, 3 Aug 2012 16:54:17 +0200

Author: schanzen
Date: 2012-08-03 16:54:17 +0200 (Fri, 03 Aug 2012)
New Revision: 23069

Modified:
   gnunet/src/gns/gnunet-gns-proxy.c
Log:
-add httppost, put, fixes

Modified: gnunet/src/gns/gnunet-gns-proxy.c
===================================================================
--- gnunet/src/gns/gnunet-gns-proxy.c   2012-08-03 14:37:37 UTC (rev 23068)
+++ gnunet/src/gns/gnunet-gns-proxy.c   2012-08-03 14:54:17 UTC (rev 23069)
@@ -197,6 +197,9 @@
   /* Handle to cURL */
   CURL *curl;
 
+  /* is curl running? */
+  int curl_running;
+
   /* Optional header replacements for curl (LEHO) */
   struct curl_slist *headers;
 
@@ -292,13 +295,19 @@
   struct MHD_PostProcessor *post_handler;
 
   /* post data */
-  struct ProxyPostData *post_data_head;
-  struct ProxyPostData *post_data_tail;
+  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;
   
 };
 
@@ -353,13 +362,21 @@
 /**
  * Post data structure
  */
-struct ProxyPostData
+struct ProxyUploadData
 {
   /* DLL */
-  struct ProxyPostData *next;
+  struct ProxyUploadData *next;
 
   /* DLL */
-  struct ProxyPostData *prev;
+  struct ProxyUploadData *prev;
+
+  char *key;
+
+  char *filename;
+
+  char *content_type;
+
+  size_t content_length;
   
   /* value */
   char *value;
@@ -516,29 +533,84 @@
                   size_t size)
 {
   struct ProxyCurlTask* ctask = cls;
-  struct ProxyPostData* pdata;
+  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);
 
+  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->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_SEND);
+    curl_easy_pause (ctask->curl, CURLPAUSE_CONT);
 
   if (0 == off)
   {
     /* a key */
-    pdata = GNUNET_malloc (sizeof (struct ProxyPostData));
+    pdata = GNUNET_malloc (sizeof (struct ProxyUploadData));
     enc = escape_to_urlenc (key);
     pdata->value = GNUNET_malloc (strlen (enc) + 3);
-    if (NULL != ctask->post_data_head)
+    if (NULL != ctask->upload_data_head)
     {
       pdata->value[0] = '&';
       memcpy (pdata->value+1, enc, strlen (enc));
@@ -554,13 +626,13 @@
                 "Escaped POST key: '%s'\n",
                 pdata->value);
 
-    GNUNET_CONTAINER_DLL_insert_tail (ctask->post_data_head,
-                                      ctask->post_data_tail,
+    GNUNET_CONTAINER_DLL_insert_tail (ctask->upload_data_head,
+                                      ctask->upload_data_tail,
                                       pdata);
   }
 
   /* a value */
-  pdata = GNUNET_malloc (sizeof (struct ProxyPostData));
+  pdata = GNUNET_malloc (sizeof (struct ProxyUploadData));
   enc = escape_to_urlenc (data);
   pdata->value = GNUNET_malloc (strlen (enc) + 1);
   memcpy (pdata->value, enc, strlen (enc));
@@ -572,8 +644,8 @@
               "Escaped POST value: '%s'\n",
               pdata->value);
 
-  GNUNET_CONTAINER_DLL_insert_tail (ctask->post_data_head,
-                                    ctask->post_data_tail,
+  GNUNET_CONTAINER_DLL_insert_tail (ctask->upload_data_head,
+                                    ctask->upload_data_tail,
                                     pdata);
   return MHD_YES;
 }
@@ -626,14 +698,16 @@
   else
     hdr_val = value;
 
-  if (0 == strcmp (MHD_HTTP_HEADER_CONTENT_TYPE,
+  if (0 == strcasecmp (MHD_HTTP_HEADER_CONTENT_TYPE,
                    key))
   {
-    if (0 == strcmp (value,
-                     MHD_HTTP_POST_ENCODING_FORM_URLENCODED))
+    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 == strcmp (value,
-                          MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA))
+    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;
@@ -1099,7 +1173,7 @@
   ctask->buf_status = BUF_WAIT_FOR_CURL;
   
   if (NULL != ctask->curl)
-    curl_easy_pause (ctask->curl, CURLPAUSE_RECV);
+    curl_easy_pause (ctask->curl, CURLPAUSE_CONT);
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "MHD: copied %d bytes\n", copied);
@@ -1280,14 +1354,68 @@
   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
-read_callback (void *buf, size_t size, size_t nmemb, void *cls)
+post_read_callback (void *buf, size_t size, size_t nmemb, void *cls)
 {
   struct ProxyCurlTask *ctask = cls;
-  struct ProxyPostData *pdata = ctask->post_data_head;
+  struct ProxyUploadData *pdata = ctask->upload_data_head;
   size_t len = size * nmemb;
   size_t to_copy;
   char* pos;
@@ -1304,8 +1432,8 @@
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "CURL: Terminating POST data\n");
 
-    GNUNET_CONTAINER_DLL_remove (ctask->post_data_head,
-                                 ctask->post_data_tail,
+    GNUNET_CONTAINER_DLL_remove (ctask->upload_data_head,
+                                 ctask->upload_data_tail,
                                  pdata);
     GNUNET_free (pdata);
     return 0;
@@ -1324,8 +1452,8 @@
   if (pdata->bytes_left <= 0)
   {
     GNUNET_free (pdata->value);
-    GNUNET_CONTAINER_DLL_remove (ctask->post_data_head,
-                                 ctask->post_data_tail,
+    GNUNET_CONTAINER_DLL_remove (ctask->upload_data_head,
+                                 ctask->upload_data_tail,
                                  pdata);
     GNUNET_free (pdata);
   }
@@ -1783,9 +1911,12 @@
   
   char curlurl[MAX_HTTP_URI_LENGTH]; // buffer overflow!
   int ret = MHD_YES;
+  int i;
 
   struct ProxyCurlTask *ctask = *con_cls;
-  struct ProxyPostData *fin_post;
+  struct ProxyUploadData *fin_post;
+  struct curl_forms forms[5];
+  struct ProxyUploadData *upload_data_iter;
   
   //FIXME handle
   if ((0 != strcasecmp (meth, MHD_HTTP_METHOD_GET)) &&
@@ -1806,6 +1937,7 @@
                 "Got %s request for %s\n", meth, url);
     ctask->mhd = hd;
     ctask->curl = curl_easy_init();
+    ctask->curl_running = GNUNET_NO;
     if (NULL == ctask->curl)
     {
       ctask->response = MHD_create_response_from_buffer (strlen (page),
@@ -1819,9 +1951,36 @@
       return ret;
     }
     
+    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);
+
+    if (GNUNET_NO == ctask->mhd->is_ssl)
+    {
+      sprintf (curlurl, "http://%s:%d%s";, ctask->host, ctask->port, 
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->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;
@@ -1830,52 +1989,32 @@
     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);
-
     if (0 == strcasecmp (meth, MHD_HTTP_METHOD_PUT))
     {
-      //FIXME: this prolly works like POST?
-      if (0 == *upload_data_size)
-      {
-        curl_easy_cleanup (ctask->curl);
-        GNUNET_free (ctask);
-        return MHD_NO;
-      }
-      ctask->put_read_offset = 0;
-      ctask->put_read_size = *upload_data_size;
+      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, upload_data);
-      //curl_easy_setopt (ctask->curl, CURLOPT_READFUNCTION, &curl_read_cb);
-      
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                  "Got PUT data: %s\n", upload_data);
-      curl_easy_cleanup (ctask->curl);
-      GNUNET_free (ctask);
-      return MHD_NO;
+      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_INFO,
+      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);
-      curl_easy_setopt (ctask->curl, CURLOPT_POST, 1);
-      curl_easy_setopt (ctask->curl, CURLOPT_READFUNCTION,
-                        &read_callback);
-      curl_easy_setopt (ctask->curl, CURLOPT_READDATA, ctask);
       ctask->headers = curl_slist_append (ctask->headers,
-                                          "Transfer-Encoding: chunked");
+                                         "Transfer-Encoding: chunked");
+      return MHD_YES;
     }
 
     if (0 == strcasecmp (meth, MHD_HTTP_METHOD_HEAD))
@@ -1885,38 +2024,17 @@
       curl_easy_setopt (ctask->curl, CURLOPT_NOBODY, 1);
     }
 
-    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);
-
-    if (GNUNET_NO == ctask->mhd->is_ssl)
-    {
-      sprintf (curlurl, "http://%s:%d%s";, ctask->host, ctask->port, 
ctask->url);
-      //MHD_get_connection_values (con,
-      //                           MHD_GET_ARGUMENT_KIND,
-      //                           &get_uri_val_iter, curlurl);
-      curl_easy_setopt (ctask->curl, CURLOPT_URL, curlurl);
-    }
     
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "MHD: Adding new curl task for %s\n", ctask->host);
-    //MHD_get_connection_values (con,
-    //                           MHD_GET_ARGUMENT_KIND,
-    //                           &get_uri_val_iter, ctask->url);
 
-    curl_easy_setopt (ctask->curl, CURLOPT_FAILONERROR, 1);
-    curl_easy_setopt (ctask->curl, CURLOPT_CONNECTTIMEOUT, 600L);
-    curl_easy_setopt (ctask->curl, CURLOPT_TIMEOUT, 600L);
-
     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;
   }
 
@@ -1925,18 +2043,95 @@
   {
     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)
     {
-      fin_post = GNUNET_malloc (sizeof (struct ProxyPostData));
-      GNUNET_CONTAINER_DLL_insert_tail (ctask->post_data_head,
-                                        ctask->post_data_tail,
+      if (GNUNET_YES == ctask->is_httppost)
+      {
+        i = 0;
+        for (upload_data_iter = ctask->upload_data_head;
+             NULL != upload_data_iter;
+             upload_data_iter = upload_data_iter->next)
+        {
+          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;
@@ -2954,7 +3149,9 @@
     if (NULL != ctask->response)
       MHD_destroy_response (ctask->response);
 
+    //FIXME free pdata here
 
+
     GNUNET_free (ctask);
   }
   curl_multi_cleanup (curl_multi);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]