implemented http get method
[strongswan.git] / src / libstrongswan / utils / fetcher.c
1 /**
2 * @file fetcher.c
3 *
4 * @brief Implementation of fetcher_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2007 Andreas Steffen
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <fetcher://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #ifdef LIBCURL
24 #include <curl/curl.h>
25 #endif /* LIBCURL */
26
27 #include <library.h>
28 #include <debug.h>
29
30 #include "fetcher.h"
31
32 typedef struct private_fetcher_t private_fetcher_t;
33
34 /**
35 * @brief Private Data of a fetcher_t object.
36 */
37 struct private_fetcher_t {
38 /**
39 * Public data
40 */
41 fetcher_t public;
42
43 /**
44 * URI of the information source
45 */
46 const char *uri;
47
48 #ifdef LIBCURL
49 /**
50 * we use libcurl from http://curl.haxx.se/ as a fetcher
51 */
52 CURL* curl;
53 #endif /* LIBCURL */
54
55 };
56
57 /**
58 * writes data into a dynamically resizeable chunk_t
59 * needed for libcurl responses
60 */
61 size_t curl_write_buffer(void *ptr, size_t size, size_t nmemb, void *data)
62 {
63 size_t realsize = size * nmemb;
64 chunk_t *mem = (chunk_t*)data;
65
66 mem->ptr = (u_char *)realloc(mem->ptr, mem->len + realsize);
67 if (mem->ptr) {
68 memcpy(&(mem->ptr[mem->len]), ptr, realsize);
69 mem->len += realsize;
70 }
71 return realsize;
72 }
73
74 /**
75 * Implements fetcher_t.get
76 */
77 static chunk_t get(private_fetcher_t *this)
78 {
79 chunk_t response = chunk_empty;
80
81 #ifdef LIBCURL
82 if (this->curl)
83 {
84 CURLcode res;
85 chunk_t curl_response = chunk_empty;
86 char curl_error_buffer[CURL_ERROR_SIZE];
87
88 curl_easy_setopt(this->curl, CURLOPT_URL, this->uri);
89 curl_easy_setopt(this->curl, CURLOPT_WRITEFUNCTION, curl_write_buffer);
90 curl_easy_setopt(this->curl, CURLOPT_WRITEDATA, (void *)&curl_response);
91 curl_easy_setopt(this->curl, CURLOPT_ERRORBUFFER, &curl_error_buffer);
92 curl_easy_setopt(this->curl, CURLOPT_FAILONERROR, TRUE);
93 curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, FETCHER_TIMEOUT);
94 curl_easy_setopt(this->curl, CURLOPT_NOSIGNAL, TRUE);
95
96 DBG1("sending http get request to '%s'...", this->uri);
97 res = curl_easy_perform(this->curl);
98
99 if (res == CURLE_OK)
100 {
101 DBG1("received valid http response");
102 response = chunk_clone(curl_response);
103 }
104 else
105 {
106 DBG1("http get request to '%s' using libcurl failed: %s",
107 this->uri, curl_error_buffer);
108 }
109 curl_free(curl_response.ptr);
110 }
111 #else
112 DBG1("warning: libcurl fetching not compiled in");
113 #endif /* LIBCURL */
114 return response;
115 }
116
117 /**
118 * Implements fetcher_t.post
119 */
120 static chunk_t post(private_fetcher_t *this, const char *request_type, chunk_t request)
121 {
122 chunk_t response = chunk_empty;
123
124 #ifdef LIBCURL
125 if (this->curl)
126 {
127 CURLcode res;
128 struct curl_slist *headers = NULL;
129 chunk_t curl_response = chunk_empty;
130 char curl_error_buffer[CURL_ERROR_SIZE];
131 char content_type[BUF_LEN];
132
133 /* set content type header */
134 snprintf(content_type, BUF_LEN, "Content-Type: %s", request_type);
135 headers = curl_slist_append(headers, content_type);
136
137 /* set options */
138 curl_easy_setopt(this->curl, CURLOPT_HTTPHEADER, headers);
139 curl_easy_setopt(this->curl, CURLOPT_URL, this->uri);
140 curl_easy_setopt(this->curl, CURLOPT_WRITEFUNCTION, curl_write_buffer);
141 curl_easy_setopt(this->curl, CURLOPT_WRITEDATA, (void *)&curl_response);
142 curl_easy_setopt(this->curl, CURLOPT_POSTFIELDS, request.ptr);
143 curl_easy_setopt(this->curl, CURLOPT_POSTFIELDSIZE, request.len);
144 curl_easy_setopt(this->curl, CURLOPT_ERRORBUFFER, &curl_error_buffer);
145 curl_easy_setopt(this->curl, CURLOPT_FAILONERROR, TRUE);
146 curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, FETCHER_TIMEOUT);
147 curl_easy_setopt(this->curl, CURLOPT_NOSIGNAL, TRUE);
148
149 DBG1("sending http post request to '%s'...", this->uri);
150 res = curl_easy_perform(this->curl);
151
152 if (res == CURLE_OK)
153 {
154 DBG1("received valid http response");
155 response = chunk_clone(curl_response);
156 }
157 else
158 {
159 DBG1("http post request to '%s' using libcurl failed: %s",
160 this->uri, curl_error_buffer);
161 }
162 curl_slist_free_all(headers);
163 curl_free(curl_response.ptr);
164 }
165 #else
166 DBG1("warning: libcurl fetching not compiled in");
167 #endif /* LIBCURL */
168 return response;
169 }
170
171 /**
172 * Implements fetcher_t.destroy
173 */
174 static void destroy(private_fetcher_t *this)
175 {
176 #ifdef LIBCURL
177 curl_easy_cleanup(this->curl);
178 #endif /* LIBCURL */
179 free(this);
180 }
181
182 /*
183 * Described in header.
184 */
185 fetcher_t *fetcher_create(const char *uri)
186 {
187 private_fetcher_t *this = malloc_thing(private_fetcher_t);
188
189 /* initialize */
190 this->uri = uri;
191 #ifdef LIBCURL
192 this->curl = curl_easy_init();
193 if (this->curl == NULL)
194 {
195 DBG1("curl_easy_init_failed()");
196 }
197 #endif /* LIBCURL */
198
199 /* public functions */
200 this->public.get = (chunk_t (*) (fetcher_t*))get;
201 this->public.post = (chunk_t (*) (fetcher_t*,const char*,chunk_t))post;
202 this->public.destroy = (void (*) (fetcher_t*))destroy;
203
204 return &this->public;
205 }
206
207 /**
208 * Described in header.
209 */
210 void fetcher_initialize(void)
211 {
212 #ifdef LIBCURL
213 CURLcode res;
214
215 /* initialize libcurl */
216 DBG1("initializing libcurl");
217 res = curl_global_init(CURL_GLOBAL_NOTHING);
218 if (res != CURLE_OK)
219 {
220 DBG1("libcurl could not be initialized: %s", curl_easy_strerror(res));
221 }
222 #endif /* LIBCURL */
223 }
224
225 /**
226 * Described in header.
227 */
228 void fetcher_finalize(void)
229 {
230 #ifdef LIBCURL
231 /* finalize libcurl */
232 DBG1("finalizing libcurl");
233 curl_global_cleanup();
234 #endif /* LIBCURL */
235 }
236