updated Doxyfile
[strongswan.git] / src / libstrongswan / plugins / curl / curl_fetcher.c
1 /*
2 * Copyright (C) 2008 Martin Willi
3 * Copyright (C) 2007 Andreas Steffen
4 * Hochschule fuer Technik Rapperswil
5 *
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>.
10 *
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
14 * for more details.
15 *
16 * $Id$
17 */
18
19 #include <curl/curl.h>
20
21 #include <library.h>
22 #include <debug.h>
23
24 #include "curl_fetcher.h"
25
26 #define DEFAULT_TIMEOUT 10
27
28 typedef struct private_curl_fetcher_t private_curl_fetcher_t;
29
30 /**
31 * private data of a curl_fetcher_t object.
32 */
33 struct private_curl_fetcher_t {
34 /**
35 * Public data
36 */
37 curl_fetcher_t public;
38
39 /**
40 * CURL handle
41 */
42 CURL* curl;
43
44 /**
45 * request type, as set with FETCH_REQUEST_TYPE
46 */
47 char *request_type;
48 };
49
50 /**
51 * writes data into a dynamically resizeable chunk_t
52 */
53 static size_t append(void *ptr, size_t size, size_t nmemb, chunk_t *data)
54 {
55 size_t realsize = size * nmemb;
56
57 data->ptr = (u_char*)realloc(data->ptr, data->len + realsize);
58 if (data->ptr)
59 {
60 memcpy(&data->ptr[data->len], ptr, realsize);
61 data->len += realsize;
62 }
63 return realsize;
64 }
65
66 /**
67 * Implements fetcher_t.fetch.
68 */
69 static status_t fetch(private_curl_fetcher_t *this, char *uri, chunk_t *result)
70 {
71 struct curl_slist *headers = NULL;
72 char error[CURL_ERROR_SIZE];
73 char buf[256];;
74 status_t status;
75
76 *result = chunk_empty;
77
78 if (curl_easy_setopt(this->curl, CURLOPT_URL, uri) != CURLE_OK)
79 { /* URL type not supported by curl */
80 return NOT_SUPPORTED;
81 }
82 curl_easy_setopt(this->curl, CURLOPT_ERRORBUFFER, error);
83 curl_easy_setopt(this->curl, CURLOPT_FAILONERROR, TRUE);
84 curl_easy_setopt(this->curl, CURLOPT_NOSIGNAL, TRUE);
85 curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, DEFAULT_TIMEOUT);
86 curl_easy_setopt(this->curl, CURLOPT_WRITEFUNCTION, (void*)append);
87 curl_easy_setopt(this->curl, CURLOPT_WRITEDATA, (void*)result);
88 if (this->request_type)
89 {
90 snprintf(buf, sizeof(buf), "Content-Type: %s", this->request_type);
91 headers = curl_slist_append(headers, buf);
92 curl_easy_setopt(this->curl, CURLOPT_HTTPHEADER, headers);
93 }
94
95 DBG2("sending http request to '%s'...", uri);
96 switch (curl_easy_perform(this->curl))
97 {
98 case CURLE_UNSUPPORTED_PROTOCOL:
99 status = NOT_SUPPORTED;
100 break;
101 case CURLE_OK:
102 status = SUCCESS;
103 break;
104 default:
105 DBG1("libcurl http request failed: %s", error);
106 status = FAILED;
107 break;
108 }
109 curl_slist_free_all(headers);
110 return status;
111 }
112
113 /**
114 * Implementation of fetcher_t.set_option.
115 */
116 static bool set_option(private_curl_fetcher_t *this, fetcher_option_t option, ...)
117 {
118 va_list args;
119
120 va_start(args, option);
121 switch (option)
122 {
123 case FETCH_REQUEST_DATA:
124 {
125 chunk_t data = va_arg(args, chunk_t);
126 curl_easy_setopt(this->curl, CURLOPT_POSTFIELDS, (char*)data.ptr);
127 curl_easy_setopt(this->curl, CURLOPT_POSTFIELDSIZE, data.len);
128 return TRUE;
129 }
130 case FETCH_REQUEST_TYPE:
131 {
132 this->request_type = va_arg(args, char*);
133 return TRUE;
134 }
135 case FETCH_TIMEOUT:
136 {
137 curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT,
138 va_arg(args, u_int));
139 return TRUE;
140 }
141 default:
142 return FALSE;
143 }
144 }
145
146 /**
147 * Implements fetcher_t.destroy
148 */
149 static void destroy(private_curl_fetcher_t *this)
150 {
151 curl_easy_cleanup(this->curl);
152 free(this);
153 }
154
155 /*
156 * Described in header.
157 */
158 curl_fetcher_t *curl_fetcher_create()
159 {
160 private_curl_fetcher_t *this = malloc_thing(private_curl_fetcher_t);
161
162 this->curl = curl_easy_init();
163 if (this->curl == NULL)
164 {
165 free(this);
166 return NULL;
167 }
168 this->request_type = NULL;
169
170 this->public.interface.fetch = (status_t(*)(fetcher_t*,char*,chunk_t*))fetch;
171 this->public.interface.set_option = (bool(*)(fetcher_t*, fetcher_option_t option, ...))set_option;
172 this->public.interface.destroy = (void (*)(fetcher_t*))destroy;
173
174 return &this->public;
175 }
176