Support FETCH_CALLBACK in curl fetcher
authorMartin Willi <martin@revosec.ch>
Fri, 1 Apr 2011 09:01:42 +0000 (11:01 +0200)
committerMartin Willi <martin@revosec.ch>
Mon, 4 Apr 2011 06:48:27 +0000 (08:48 +0200)
src/libstrongswan/plugins/curl/curl_fetcher.c

index 6c03ebe..7f8c0ae 100644 (file)
@@ -43,22 +43,33 @@ struct private_curl_fetcher_t {
         * Optional HTTP headers
         */
        struct curl_slist *headers;
+
+       /**
+        * Callback function
+        */
+       fetcher_callback_t cb;
 };
 
 /**
- * writes data into a dynamically resizeable chunk_t
+ * Data to pass to curl callback
+ */
+typedef struct {
+       fetcher_callback_t cb;
+       void *user;
+} cb_data_t;
+
+/**
+ * Curl callback function, invokes fetcher_callback_t function
  */
-static size_t append(void *ptr, size_t size, size_t nmemb, chunk_t *data)
+static size_t curl_cb(void *ptr, size_t size, size_t nmemb, cb_data_t *data)
 {
        size_t realsize = size * nmemb;
 
-       data->ptr = (u_char*)realloc(data->ptr, data->len + realsize);
-       if (data->ptr)
+       if (data->cb(data->user, chunk_create(ptr, realsize)))
        {
-               memcpy(&data->ptr[data->len], ptr, realsize);
-               data->len += realsize;
+               return realsize;
        }
-       return realsize;
+       return 0;
 }
 
 METHOD(fetcher_t, fetch, status_t,
@@ -66,9 +77,15 @@ METHOD(fetcher_t, fetch, status_t,
 {
        char error[CURL_ERROR_SIZE];
        status_t status;
-       chunk_t *result = userdata;
+       cb_data_t data = {
+               .cb = this->cb,
+               .user = userdata,
+       };
 
-       *result = chunk_empty;
+       if (this->cb == fetcher_default_callback)
+       {
+               *(chunk_t*)userdata = chunk_empty;
+       }
 
        if (curl_easy_setopt(this->curl, CURLOPT_URL, uri) != CURLE_OK)
        {       /* URL type not supported by curl */
@@ -78,8 +95,8 @@ METHOD(fetcher_t, fetch, status_t,
        curl_easy_setopt(this->curl, CURLOPT_FAILONERROR, TRUE);
        curl_easy_setopt(this->curl, CURLOPT_NOSIGNAL, TRUE);
        curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, DEFAULT_TIMEOUT);
-       curl_easy_setopt(this->curl, CURLOPT_WRITEFUNCTION, (void*)append);
-       curl_easy_setopt(this->curl, CURLOPT_WRITEDATA, (void*)result);
+       curl_easy_setopt(this->curl, CURLOPT_WRITEFUNCTION, (void*)curl_cb);
+       curl_easy_setopt(this->curl, CURLOPT_WRITEDATA, &data);
        if (this->headers)
        {
                curl_easy_setopt(this->curl, CURLOPT_HTTPHEADER, this->headers);
@@ -147,6 +164,11 @@ METHOD(fetcher_t, set_option, bool,
                                                         va_arg(args, u_int));
                        break;
                }
+               case FETCH_CALLBACK:
+               {
+                       this->cb = va_arg(args, fetcher_callback_t);
+                       break;
+               }
                default:
                        supported = FALSE;
                        break;
@@ -179,6 +201,7 @@ curl_fetcher_t *curl_fetcher_create()
                        },
                },
                .curl = curl_easy_init(),
+               .cb = fetcher_default_callback,
        );
 
        if (!this->curl)