Annotation of embedaddon/strongswan/src/libstrongswan/plugins/soup/soup_fetcher.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2010 Martin Willi
                      3:  * Copyright (C) 2010 revosec AG
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "soup_fetcher.h"
                     17: 
                     18: #include <libsoup/soup.h>
                     19: 
                     20: #include <library.h>
                     21: #include <utils/debug.h>
                     22: 
                     23: #define DEFAULT_TIMEOUT 10
                     24: 
                     25: typedef struct private_soup_fetcher_t private_soup_fetcher_t;
                     26: 
                     27: /**
                     28:  * private data of a soup_fetcher_t object.
                     29:  */
                     30: struct private_soup_fetcher_t {
                     31: 
                     32:        /**
                     33:         * Public data
                     34:         */
                     35:        soup_fetcher_t public;
                     36: 
                     37:        /**
                     38:         * HTTP request method
                     39:         */
                     40:        const char *method;
                     41: 
                     42:        /**
                     43:         * Request content type
                     44:         */
                     45:        char *type;
                     46: 
                     47:        /**
                     48:         * Request data
                     49:         */
                     50:        chunk_t data;
                     51: 
                     52:        /**
                     53:         * Request timeout
                     54:         */
                     55:        u_int timeout;
                     56: 
                     57:        /**
                     58:         * HTTP request version
                     59:         */
                     60:        SoupHTTPVersion version;
                     61: 
                     62:        /**
                     63:         * Fetcher callback function
                     64:         */
                     65:        fetcher_callback_t cb;
                     66: 
                     67:        /**
                     68:         * Response status
                     69:         */
                     70:        u_int *result;
                     71: };
                     72: 
                     73: /**
                     74:  * Data to pass to soup callback
                     75:  */
                     76: typedef struct {
                     77:        fetcher_callback_t cb;
                     78:        void *user;
                     79:        SoupSession *session;
                     80: } cb_data_t;
                     81: 
                     82: /**
                     83:  * Soup callback invoking our callback
                     84:  */
                     85: static void soup_cb(SoupMessage *message, SoupBuffer *chunk, cb_data_t *data)
                     86: {
                     87:        if (!data->cb(data->user, chunk_create((u_char*)chunk->data, chunk->length)))
                     88:        {
                     89:                soup_session_cancel_message(data->session, message,
                     90:                                                                        SOUP_STATUS_CANCELLED);
                     91:        }
                     92: }
                     93: 
                     94: METHOD(fetcher_t, fetch, status_t,
                     95:        private_soup_fetcher_t *this, char *uri, void *userdata)
                     96: {
                     97:        SoupMessage *message;
                     98:        status_t status = FAILED;
                     99:        cb_data_t data = {
                    100:                .cb = this->cb,
                    101:                .user = userdata,
                    102:        };
                    103: 
                    104:        message = soup_message_new(this->method, uri);
                    105:        if (!message)
                    106:        {
                    107:                return NOT_SUPPORTED;
                    108:        }
                    109:        if (this->cb == fetcher_default_callback)
                    110:        {
                    111:                *(chunk_t*)userdata = chunk_empty;
                    112:        }
                    113:        if (this->type)
                    114:        {
                    115:                soup_message_set_request(message, this->type, SOUP_MEMORY_STATIC,
                    116:                                                                 this->data.ptr, this->data.len);
                    117:        }
                    118:        soup_message_set_http_version(message, this->version);
                    119:        soup_message_body_set_accumulate(message->response_body, FALSE);
                    120:        g_signal_connect(message, "got-chunk", G_CALLBACK(soup_cb), &data);
                    121:        data.session = soup_session_new();
                    122:        g_object_set(G_OBJECT(data.session),
                    123:                                 SOUP_SESSION_TIMEOUT, (guint)this->timeout, NULL);
                    124: 
                    125:        DBG2(DBG_LIB, "sending http request to '%s'...", uri);
                    126:        soup_session_send_message(data.session, message);
                    127:        if (this->result)
                    128:        {
                    129:                *this->result = message->status_code;
                    130:        }
                    131:        if (SOUP_STATUS_IS_SUCCESSFUL(message->status_code))
                    132:        {
                    133:                status = SUCCESS;
                    134:        }
                    135:        else if (!this->result)
                    136:        {       /* only log an error if the code is not returned */
                    137:                DBG1(DBG_LIB, "HTTP request failed: %s", message->reason_phrase);
                    138:        }
                    139:        g_object_unref(G_OBJECT(message));
                    140:        g_object_unref(G_OBJECT(data.session));
                    141:        return status;
                    142: }
                    143: 
                    144: METHOD(fetcher_t, set_option, bool,
                    145:        private_soup_fetcher_t *this, fetcher_option_t option, ...)
                    146: {
                    147:        bool supported = TRUE;
                    148:        va_list args;
                    149: 
                    150:        va_start(args, option);
                    151:        switch (option)
                    152:        {
                    153:                case FETCH_REQUEST_DATA:
                    154:                        this->method = SOUP_METHOD_POST;
                    155:                        this->data = va_arg(args, chunk_t);
                    156:                        break;
                    157:                case FETCH_REQUEST_TYPE:
                    158:                        this->type = va_arg(args, char*);
                    159:                        break;
                    160:                case FETCH_HTTP_VERSION_1_0:
                    161:                        this->version = SOUP_HTTP_1_0;
                    162:                        break;
                    163:                case FETCH_TIMEOUT:
                    164:                        this->timeout = va_arg(args, u_int);
                    165:                        break;
                    166:                case FETCH_CALLBACK:
                    167:                        this->cb = va_arg(args, fetcher_callback_t);
                    168:                        break;
                    169:                case FETCH_RESPONSE_CODE:
                    170:                        this->result = va_arg(args, u_int*);
                    171:                        break;
                    172:                default:
                    173:                        supported = FALSE;
                    174:                        break;
                    175:        }
                    176:        va_end(args);
                    177:        return supported;
                    178: }
                    179: 
                    180: METHOD(fetcher_t, destroy, void,
                    181:        private_soup_fetcher_t *this)
                    182: {
                    183:        free(this);
                    184: }
                    185: 
                    186: /*
                    187:  * Described in header.
                    188:  */
                    189: soup_fetcher_t *soup_fetcher_create()
                    190: {
                    191:        private_soup_fetcher_t *this;
                    192: 
                    193:        INIT(this,
                    194:                .public = {
                    195:                        .interface = {
                    196:                                .fetch = _fetch,
                    197:                                .set_option = _set_option,
                    198:                                .destroy = _destroy,
                    199:                        },
                    200:                },
                    201:                .method = SOUP_METHOD_GET,
                    202:                .version = SOUP_HTTP_1_1,
                    203:                .timeout = DEFAULT_TIMEOUT,
                    204:                .cb = fetcher_default_callback,
                    205:        );
                    206: 
                    207:        return &this->public;
                    208: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>