f5cd342b9d3ac54f48b4f0bdfbd6b913c6db8b91
[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
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 h 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, const char *uri)
78 {
79 return chunk_empty;
80 }
81
82 /**
83 * Implements fetcher_t.post
84 */
85 static chunk_t post(private_fetcher_t *this, const char *request_type, chunk_t request)
86 {
87 chunk_t response = chunk_empty;
88
89 #ifdef LIBCURL
90 if (this->curl)
91 {
92 CURLcode res;
93 struct curl_slist *headers = NULL;
94 chunk_t curl_response = chunk_empty;
95 char curl_error_buffer[CURL_ERROR_SIZE];
96 char content_type[BUF_LEN];
97
98 /* set content type header */
99 snprintf(content_type, BUF_LEN, "Content-Type: %s", request_type);
100 headers = curl_slist_append(headers, content_type);
101
102 /* set options */
103 curl_easy_setopt(this->curl, CURLOPT_HTTPHEADER, headers);
104 curl_easy_setopt(this->curl, CURLOPT_URL, this->uri);
105 curl_easy_setopt(this->curl, CURLOPT_WRITEFUNCTION, curl_write_buffer);
106 curl_easy_setopt(this->curl, CURLOPT_WRITEDATA, (void *)&curl_response);
107 curl_easy_setopt(this->curl, CURLOPT_POSTFIELDS, request.ptr);
108 curl_easy_setopt(this->curl, CURLOPT_POSTFIELDSIZE, request.len);
109 curl_easy_setopt(this->curl, CURLOPT_ERRORBUFFER, &curl_error_buffer);
110 curl_easy_setopt(this->curl, CURLOPT_FAILONERROR, TRUE);
111 curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, FETCHER_TIMEOUT);
112
113 DBG2("sending http post request to '%s'", this->uri);
114 res = curl_easy_perform(this->curl);
115
116 if (res == CURLE_OK)
117 {
118 DBG2("received valid http response");
119 response = chunk_clone(curl_response);
120 }
121 else
122 {
123 DBG1("http post request to '%s' using libcurl failed: %s",
124 this->uri, curl_error_buffer);
125 }
126 curl_free(curl_response.ptr);
127 }
128 #else
129 DBG1("warning: libcurl fetching not compiled in");
130 #endif /* LIBCURL */
131 return response;
132 }
133
134 /**
135 * Implements fetcher_t.destroy
136 */
137 static void destroy(private_fetcher_t *this)
138 {
139 curl_easy_cleanup(this->curl);
140 free(this);
141 }
142
143 /*
144 * Described in header.
145 */
146 fetcher_t *fetcher_create(const char *uri)
147 {
148 private_fetcher_t *this = malloc_thing(private_fetcher_t);
149
150 /* initialize */
151 this->uri = uri;
152 #ifdef LIBCURL
153 this->curl = curl_easy_init();
154 if (this->curl == NULL)
155 {
156 DBG1("curl_easy_init_failed()");
157 }
158 #endif /* LIBCURL */
159
160 /* public functions */
161 this->public.get = (chunk_t (*) (fetcher_t*,const char*))get;
162 this->public.post = (chunk_t (*) (fetcher_t*,const char*,chunk_t))post;
163 this->public.destroy = (void (*) (fetcher_t*))destroy;
164
165 return &this->public;
166 }
167
168 /**
169 * Described in header.
170 */
171 void fetcher_initialize(void)
172 {
173 #ifdef LIBCURL
174 CURLcode res;
175
176 /* initialize libcurl */
177 DBG1("initializing libcurl");
178 res = curl_global_init(CURL_GLOBAL_NOTHING);
179 if (res != CURLE_OK)
180 {
181 DBG1("libcurl could not be initialized: %s", curl_easy_strerror(res));
182 }
183 #endif /* LIBCURL */
184 }
185
186 /**
187 * Described in header.
188 */
189 void fetcher_finalize(void)
190 {
191 #ifdef LIBCURL
192 /* finalize libcurl */
193 DBG1("finalizing libcurl");
194 curl_global_cleanup();
195 #endif /* LIBCURL */
196 }
197