Return to soup_fetcher.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / soup |
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: }