Added a new FETCH_CALLBACK option to fetch data without allocation
authorMartin Willi <martin@revosec.ch>
Fri, 1 Apr 2011 08:30:42 +0000 (10:30 +0200)
committerMartin Willi <martin@revosec.ch>
Mon, 4 Apr 2011 06:48:27 +0000 (08:48 +0200)
src/libstrongswan/Makefile.am
src/libstrongswan/fetcher/fetcher.c [new file with mode: 0644]
src/libstrongswan/fetcher/fetcher.h
src/libstrongswan/fetcher/fetcher_manager.c
src/libstrongswan/fetcher/fetcher_manager.h
src/libstrongswan/plugins/curl/curl_fetcher.c
src/libstrongswan/plugins/soup/soup_fetcher.c

index 6a29d8e..b6c70da 100644 (file)
@@ -46,7 +46,7 @@ credentials/sets/callback_cred.c credentials/sets/callback_cred.h \
 credentials/auth_cfg.c credentials/auth_cfg.h credentials/credential_set.h \
 credentials/cert_validator.h \
 database/database.h database/database_factory.h database/database_factory.c \
-fetcher/fetcher.h fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
+fetcher/fetcher.h fetcher/fetcher.c fetcher/fetcher_manager.h fetcher/fetcher_manager.c \
 eap/eap.h eap/eap.c \
 plugins/plugin_loader.c plugins/plugin_loader.h plugins/plugin.h \
 processing/jobs/job.h \
diff --git a/src/libstrongswan/fetcher/fetcher.c b/src/libstrongswan/fetcher/fetcher.c
new file mode 100644 (file)
index 0000000..ca5a721
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2011 Martin Willi
+ * Copyright (C) 2011 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "fetcher.h"
+
+/**
+ * See header.
+ */
+bool fetcher_default_callback(void *userdata, chunk_t chunk)
+{
+       chunk_t *accu = userdata;
+
+       accu->ptr = realloc(accu->ptr, accu->len + chunk.len);
+       if (accu->ptr)
+       {
+               memcpy(&accu->ptr[accu->len], chunk.ptr, chunk.len);
+               accu->len += chunk.len;
+               return TRUE;
+       }
+       return FALSE;
+}
index f312206..5b734da 100644 (file)
@@ -1,6 +1,7 @@
 /*
- * Copyright (C) 2008 Martin Willi
+ * Copyright (C) 2008-2011 Martin Willi
  * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011 revosec AG
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -25,6 +26,23 @@ typedef struct fetcher_t fetcher_t;
 typedef enum fetcher_option_t fetcher_option_t;
 
 #include <stdarg.h>
+#include <chunk.h>
+
+/**
+ * Constructor function which creates fetcher instances.
+ *
+ * @return                     fetcher instance
+ */
+typedef fetcher_t* (*fetcher_constructor_t)();
+
+/**
+ * Callback function used with FETCH_CALLBACK.
+ *
+ * @param userdata     userdata passed to fetcher_t.fetch()
+ * @param chunk                chunk with next chunk of data
+ * @return                     TRUE to continue with transfer, FALSE to abort
+ */
+typedef bool (*fetcher_callback_t)(void *userdata, chunk_t chunk);
 
 #include <library.h>
 
@@ -64,19 +82,20 @@ enum fetcher_option_t {
        FETCH_TIMEOUT,
 
        /**
+        * Callback to invoke with each chunk of data.
+        * Additional argument fetch_callback_t.
+        * If this option is not given, the fetcher_default_callback is used,
+        * which accumulates the data into an allocated chunk.
+        */
+       FETCH_CALLBACK,
+
+       /**
         * end of fetching options
         */
        FETCH_END,
 };
 
 /**
- * Constructor function which creates fetcher instances.
- *
- * @return                     fetcher instance
- */
-typedef fetcher_t* (*fetcher_constructor_t)();
-
-/**
  * Fetcher interface, an implementation fetches data from an URL.
  */
 struct fetcher_t {
@@ -87,15 +106,18 @@ struct fetcher_t {
         * The fetcher returns NOT_SUPPORTED to indicate that it is uncappable
         * to handle such URLs. Other return values indicate a failure, and
         * fetching of that URL gets cancelled.
+        * If no FETCH_CALLBACK function is set as option, userdata must be
+        * a chunk_t*. This chunk gets allocated, accumulated data using the
+        * fetcher_default_callback() function.
         *
         * @param uri           URI to fetch from
-        * @param result        chunk which receives allocated data
+        * @param userdata      userdata to pass to callback function.
         * @return
         *                                      - SUCCESS if fetch was successful
         *                                      - NOT_SUPPORTED if fetcher does not support such URLs
         *                                      - FAILED, NOT_FOUND, PARSE_ERROR on failure
         */
-       status_t (*fetch)(fetcher_t *this, char *uri, chunk_t *result);
+       status_t (*fetch)(fetcher_t *this, char *uri, void *userdata);
 
        /**
         * Set a fetcher option, as defined in fetcher_option_t.
@@ -114,4 +136,13 @@ struct fetcher_t {
        void (*destroy)(fetcher_t *this);
 };
 
+/**
+ * Default fetcher callback function, accumulates data to a chunk.
+ *
+ * @param userdata             chunk for allocated data, empty on first invocation
+ * @param chunk                        current chunk of data
+ * @return                             FALSE if chunk too large to allocate
+ */
+bool fetcher_default_callback(void *userdata, chunk_t chunk);
+
 #endif /** FETCHER_H_ @}*/
index 7e49be4..9b363c7 100644 (file)
@@ -59,7 +59,7 @@ static void entry_destroy(entry_t *entry)
 }
 
 METHOD(fetcher_manager_t, fetch, status_t,
-       private_fetcher_manager_t *this, char *url, chunk_t *response, ...)
+       private_fetcher_manager_t *this, char *url, void *userdata, ...)
 {
        enumerator_t *enumerator;
        status_t status = NOT_SUPPORTED;
@@ -86,25 +86,31 @@ METHOD(fetcher_manager_t, fetch, status_t,
                {
                        continue;
                }
-               va_start(args, response);
+               va_start(args, userdata);
                while (good)
                {
                        opt = va_arg(args, int);
                        switch (opt)
                        {
                                case FETCH_REQUEST_DATA:
-                                       good = fetcher->set_option(fetcher, opt, va_arg(args, chunk_t));
+                                       good = fetcher->set_option(fetcher, opt,
+                                                                                       va_arg(args, chunk_t));
                                        continue;
                                case FETCH_REQUEST_TYPE:
                                case FETCH_REQUEST_HEADER:
-                                       good = fetcher->set_option(fetcher, opt, va_arg(args, char*));
+                                       good = fetcher->set_option(fetcher, opt,
+                                                                                       va_arg(args, char*));
                                        continue;
                                case FETCH_HTTP_VERSION_1_0:
                                        good = fetcher->set_option(fetcher, opt);
                                        continue;
                                case FETCH_TIMEOUT:
-                                       good = fetcher->set_option(fetcher, opt, va_arg(args, u_int));
+                                       good = fetcher->set_option(fetcher, opt,
+                                                                                       va_arg(args, u_int));
                                        continue;
+                               case FETCH_CALLBACK:
+                                       good = fetcher->set_option(fetcher, opt,
+                                                                                       va_arg(args, fetcher_callback_t));
                                case FETCH_END:
                                        break;
                        }
@@ -117,7 +123,7 @@ METHOD(fetcher_manager_t, fetch, status_t,
                        continue;
                }
 
-               status = fetcher->fetch(fetcher, url, response);
+               status = fetcher->fetch(fetcher, url, userdata);
                fetcher->destroy(fetcher);
                /* try another fetcher only if this one does not support that URL */
                if (status == NOT_SUPPORTED)
index a7ac661..15250d5 100644 (file)
@@ -31,17 +31,20 @@ typedef struct fetcher_manager_t fetcher_manager_t;
 struct fetcher_manager_t {
 
        /**
-        * Fetch data from URI into chunk.
+        * Fetch data from URI.
         *
         * The variable argument list contains fetcher_option_t's, followed
         * by a option specific data argument.
+        * If no FETCH_CALLBACK function is given as option, userdata must be
+        * a chunk_t*. This chunk gets allocated, accumulated data using the
+        * fetcher_default_callback() function.
         *
         * @param uri                   URI to fetch from
-        * @param result                chunk which receives allocated data
+        * @param userdata              userdata to pass to callback function.
         * @param options               FETCH_END terminated fetcher_option_t arguments
         * @return                              status indicating result of fetch
         */
-       status_t (*fetch)(fetcher_manager_t *this, char *url, chunk_t *response, ...);
+       status_t (*fetch)(fetcher_manager_t *this, char *url, void *userdata, ...);
 
        /**
         * Register a fetcher implementation.
index 82e24e8..6c03ebe 100644 (file)
@@ -62,10 +62,11 @@ static size_t append(void *ptr, size_t size, size_t nmemb, chunk_t *data)
 }
 
 METHOD(fetcher_t, fetch, status_t,
-       private_curl_fetcher_t *this, char *uri, chunk_t *result)
+       private_curl_fetcher_t *this, char *uri, void *userdata)
 {
        char error[CURL_ERROR_SIZE];
        status_t status;
+       chunk_t *result = userdata;
 
        *result = chunk_empty;
 
index fd97631..2c99c90 100644 (file)
@@ -61,11 +61,12 @@ struct private_soup_fetcher_t {
 };
 
 METHOD(fetcher_t, fetch, status_t,
-       private_soup_fetcher_t *this, char *uri, chunk_t *result)
+       private_soup_fetcher_t *this, char *uri, void *userdata)
 {
        SoupSession *session;
        SoupMessage *message;
        status_t status = FAILED;
+       chunk_t *result = userdata;
 
        message = soup_message_new(this->method, uri);
        if (!message)