2 * Copyright (C) 2008 Martin Willi
3 * Copyright (C) 2007 Andreas Steffen
4 * Hochschule fuer Technik Rapperswil
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 #include <curl/curl.h>
20 #include <utils/debug.h>
22 #include "curl_fetcher.h"
24 #define DEFAULT_TIMEOUT 10
26 typedef struct private_curl_fetcher_t private_curl_fetcher_t
;
29 * private data of a curl_fetcher_t object.
31 struct private_curl_fetcher_t
{
35 curl_fetcher_t
public;
43 * Optional HTTP headers
45 struct curl_slist
*headers
;
50 fetcher_callback_t cb
;
54 * Data to pass to curl callback
57 fetcher_callback_t cb
;
62 * Curl callback function, invokes fetcher_callback_t function
64 static size_t curl_cb(void *ptr
, size_t size
, size_t nmemb
, cb_data_t
*data
)
66 size_t realsize
= size
* nmemb
;
68 if (data
->cb(data
->user
, chunk_create(ptr
, realsize
)))
75 METHOD(fetcher_t
, fetch
, status_t
,
76 private_curl_fetcher_t
*this, char *uri
, void *userdata
)
78 char error
[CURL_ERROR_SIZE
];
85 if (this->cb
== fetcher_default_callback
)
87 *(chunk_t
*)userdata
= chunk_empty
;
90 if (curl_easy_setopt(this->curl
, CURLOPT_URL
, uri
) != CURLE_OK
)
91 { /* URL type not supported by curl */
94 curl_easy_setopt(this->curl
, CURLOPT_ERRORBUFFER
, error
);
95 curl_easy_setopt(this->curl
, CURLOPT_FAILONERROR
, TRUE
);
96 curl_easy_setopt(this->curl
, CURLOPT_NOSIGNAL
, TRUE
);
97 curl_easy_setopt(this->curl
, CURLOPT_CONNECTTIMEOUT
, DEFAULT_TIMEOUT
);
98 curl_easy_setopt(this->curl
, CURLOPT_WRITEFUNCTION
, (void*)curl_cb
);
99 curl_easy_setopt(this->curl
, CURLOPT_WRITEDATA
, &data
);
102 curl_easy_setopt(this->curl
, CURLOPT_HTTPHEADER
, this->headers
);
105 DBG2(DBG_LIB
, " sending http request to '%s'...", uri
);
106 switch (curl_easy_perform(this->curl
))
108 case CURLE_UNSUPPORTED_PROTOCOL
:
109 status
= NOT_SUPPORTED
;
115 DBG1(DBG_LIB
, "libcurl http request failed: %s", error
);
122 METHOD(fetcher_t
, set_option
, bool,
123 private_curl_fetcher_t
*this, fetcher_option_t option
, ...)
125 bool supported
= TRUE
;
128 va_start(args
, option
);
131 case FETCH_REQUEST_DATA
:
133 chunk_t data
= va_arg(args
, chunk_t
);
135 curl_easy_setopt(this->curl
, CURLOPT_POSTFIELDS
, (char*)data
.ptr
);
136 curl_easy_setopt(this->curl
, CURLOPT_POSTFIELDSIZE
, data
.len
);
139 case FETCH_REQUEST_TYPE
:
141 char header
[BUF_LEN
];
142 char *request_type
= va_arg(args
, char*);
144 snprintf(header
, BUF_LEN
, "Content-Type: %s", request_type
);
145 this->headers
= curl_slist_append(this->headers
, header
);
148 case FETCH_REQUEST_HEADER
:
150 char *header
= va_arg(args
, char*);
152 this->headers
= curl_slist_append(this->headers
, header
);
155 case FETCH_HTTP_VERSION_1_0
:
157 curl_easy_setopt(this->curl
, CURLOPT_HTTP_VERSION
,
158 CURL_HTTP_VERSION_1_0
);
163 curl_easy_setopt(this->curl
, CURLOPT_CONNECTTIMEOUT
,
164 va_arg(args
, u_int
));
169 this->cb
= va_arg(args
, fetcher_callback_t
);
180 METHOD(fetcher_t
, destroy
, void,
181 private_curl_fetcher_t
*this)
183 curl_slist_free_all(this->headers
);
184 curl_easy_cleanup(this->curl
);
189 * Described in header.
191 curl_fetcher_t
*curl_fetcher_create()
193 private_curl_fetcher_t
*this;
199 .set_option
= _set_option
,
203 .curl
= curl_easy_init(),
204 .cb
= fetcher_default_callback
,
212 return &this->public;