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>
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
;
49 * writes data into a dynamically resizeable chunk_t
51 static size_t append(void *ptr
, size_t size
, size_t nmemb
, chunk_t
*data
)
53 size_t realsize
= size
* nmemb
;
55 data
->ptr
= (u_char
*)realloc(data
->ptr
, data
->len
+ realsize
);
58 memcpy(&data
->ptr
[data
->len
], ptr
, realsize
);
59 data
->len
+= realsize
;
64 METHOD(fetcher_t
, fetch
, status_t
,
65 private_curl_fetcher_t
*this, char *uri
, chunk_t
*result
)
67 char error
[CURL_ERROR_SIZE
];
70 *result
= chunk_empty
;
72 if (curl_easy_setopt(this->curl
, CURLOPT_URL
, uri
) != CURLE_OK
)
73 { /* URL type not supported by curl */
76 curl_easy_setopt(this->curl
, CURLOPT_ERRORBUFFER
, error
);
77 curl_easy_setopt(this->curl
, CURLOPT_FAILONERROR
, TRUE
);
78 curl_easy_setopt(this->curl
, CURLOPT_NOSIGNAL
, TRUE
);
79 curl_easy_setopt(this->curl
, CURLOPT_CONNECTTIMEOUT
, DEFAULT_TIMEOUT
);
80 curl_easy_setopt(this->curl
, CURLOPT_WRITEFUNCTION
, (void*)append
);
81 curl_easy_setopt(this->curl
, CURLOPT_WRITEDATA
, (void*)result
);
84 curl_easy_setopt(this->curl
, CURLOPT_HTTPHEADER
, this->headers
);
87 DBG2(" sending http request to '%s'...", uri
);
88 switch (curl_easy_perform(this->curl
))
90 case CURLE_UNSUPPORTED_PROTOCOL
:
91 status
= NOT_SUPPORTED
;
97 DBG1("libcurl http request failed: %s", error
);
104 METHOD(fetcher_t
, set_option
, bool,
105 private_curl_fetcher_t
*this, fetcher_option_t option
, ...)
109 va_start(args
, option
);
112 case FETCH_REQUEST_DATA
:
114 chunk_t data
= va_arg(args
, chunk_t
);
116 curl_easy_setopt(this->curl
, CURLOPT_POSTFIELDS
, (char*)data
.ptr
);
117 curl_easy_setopt(this->curl
, CURLOPT_POSTFIELDSIZE
, data
.len
);
120 case FETCH_REQUEST_TYPE
:
122 char header
[BUF_LEN
];
123 char *request_type
= va_arg(args
, char*);
125 snprintf(header
, BUF_LEN
, "Content-Type: %s", request_type
);
126 this->headers
= curl_slist_append(this->headers
, header
);
129 case FETCH_REQUEST_HEADER
:
131 char *header
= va_arg(args
, char*);
133 this->headers
= curl_slist_append(this->headers
, header
);
136 case FETCH_HTTP_VERSION_1_0
:
138 curl_easy_setopt(this->curl
, CURLOPT_HTTP_VERSION
,
139 CURL_HTTP_VERSION_1_0
);
144 curl_easy_setopt(this->curl
, CURLOPT_CONNECTTIMEOUT
,
145 va_arg(args
, u_int
));
153 METHOD(fetcher_t
, destroy
, void,
154 private_curl_fetcher_t
*this)
156 curl_slist_free_all(this->headers
);
157 curl_easy_cleanup(this->curl
);
162 * Described in header.
164 curl_fetcher_t
*curl_fetcher_create()
166 private_curl_fetcher_t
*this;
169 .public.interface
= {
171 .set_option
= _set_option
,
174 .curl
= curl_easy_init(),
182 return &this->public;