aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmessage/llurlrequest.h
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llmessage/llurlrequest.h')
-rw-r--r--linden/indra/llmessage/llurlrequest.h414
1 files changed, 414 insertions, 0 deletions
diff --git a/linden/indra/llmessage/llurlrequest.h b/linden/indra/llmessage/llurlrequest.h
new file mode 100644
index 0000000..788b0e4
--- /dev/null
+++ b/linden/indra/llmessage/llurlrequest.h
@@ -0,0 +1,414 @@
1/**
2 * @file llurlrequest.h
3 * @author Phoenix
4 * @date 2005-04-21
5 * @brief Declaration of url based requests on pipes.
6 *
7 * Copyright (c) 2005-2007, Linden Research, Inc.
8 *
9 * The source code in this file ("Source Code") is provided by Linden Lab
10 * to you under the terms of the GNU General Public License, version 2.0
11 * ("GPL"), unless you have obtained a separate licensing agreement
12 * ("Other License"), formally executed by you and Linden Lab. Terms of
13 * the GPL can be found in doc/GPL-license.txt in this distribution, or
14 * online at http://secondlife.com/developers/opensource/gplv2
15 *
16 * There are special exceptions to the terms and conditions of the GPL as
17 * it is applied to this Source Code. View the full text of the exception
18 * in the file doc/FLOSS-exception.txt in this software distribution, or
19 * online at http://secondlife.com/developers/opensource/flossexception
20 *
21 * By copying, modifying or distributing this software, you acknowledge
22 * that you have read and understood your obligations described above,
23 * and agree to abide by those obligations.
24 *
25 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
26 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
27 * COMPLETENESS OR PERFORMANCE.
28 */
29
30#ifndef LL_LLURLREQUEST_H
31#define LL_LLURLREQUEST_H
32
33/**
34 * This file holds the declaration of useful classes for dealing with
35 * url based client requests.
36 */
37
38#include <string>
39#include "lliopipe.h"
40#include "llchainio.h"
41
42class LLURLRequestDetail;
43
44class LLURLRequestComplete;
45
46/**
47 * @class LLURLRequest
48 * @brief Class to handle url based requests.
49 * @see LLIOPipe
50 *
51 * Currently, this class is implemented on top of curl. From the
52 * vantage of a programmer using this class, you do not care so much,
53 * but it's useful to know since in order to accomplish 'non-blocking'
54 * behavior, we have to use a more expensive curl interface which can
55 * still block if the server enters a half-accepted state. It would be
56 * worth the time and effort to eventually port this to a raw client
57 * socket.
58 */
59class LLURLRequest : public LLIOPipe
60{
61public:
62 /**
63 * @brief This enumeration is for specifying the type of request.
64 */
65 enum ERequestAction
66 {
67 INVALID,
68 HTTP_GET,
69 HTTP_PUT,
70 HTTP_POST,
71 HTTP_DELETE,
72 REQUEST_ACTION_COUNT
73 };
74
75 /**
76 * @brief Constructor.
77 *
78 * @param action One of the ERequestAction enumerations.
79 */
80 LLURLRequest(ERequestAction action);
81
82 /**
83 * @brief Constructor.
84 *
85 * @param action One of the ERequestAction enumerations.
86 * @param url The url of the request. It should already be encoded.
87 */
88 LLURLRequest(ERequestAction action, const std::string& url);
89
90 /**
91 * @brief Destructor.
92 */
93 virtual ~LLURLRequest();
94
95 /* @name Instance methods
96 */
97 //@{
98 /**
99 * @brief Set the url for the request
100 *
101 * This method assumes the url is encoded appropriately for the
102 * request.
103 * The url must be set somehow before the first call to process(),
104 * or the url will not be set correctly.
105 *
106 */
107 void setURL(const std::string& url);
108
109 /**
110 * @brief Add a header to the http post.
111 *
112 * The header must be correctly formatted for HTTP requests. This
113 * provides a raw interface if you know what kind of request you
114 * will be making during construction of this instance. All
115 * required headers will be automatically constructed, so this is
116 * usually useful for encoding parameters.
117 */
118 void addHeader(const char* header);
119
120 /**
121 * @brief Check remote server certificate signed by a known root CA.
122 *
123 * Set whether request will check that remote server
124 * certificates are signed by a known root CA when using HTTPS.
125 * Use the supplied root certificate bundle if supplied, else use
126 * the standard bundle as found by libcurl and openssl.
127 */
128 void checkRootCertificate(bool check, const char* caBundle = NULL);
129
130 /**
131 * @brief Request a particular response encoding if available.
132 *
133 * This call is a shortcut for requesting a particular encoding
134 * from the server, eg, 'gzip'.
135 */
136 void requestEncoding(const char* encoding);
137
138 /**
139 * @brief Return at most size bytes of body.
140 *
141 * If the body had more bytes than this limit, they will not be
142 * returned and the connection closed. In this case, STATUS_STOP
143 * will be passed to responseStatus();
144 */
145 void setBodyLimit(U32 size);
146
147 /**
148 * @brief Set a completion callback for this URLRequest.
149 *
150 * The callback is added to this URLRequet's pump when either the
151 * entire buffer is known or an error like timeout or connection
152 * refused has happened. In the case of a complete transfer, this
153 * object builds a response chain such that the callback and the
154 * next process consumer get to read the output.
155 *
156 * This setup is a little fragile since the url request consumer
157 * might not just read the data - it may do a channel change,
158 * which invalidates the input to the callback, but it works well
159 * in practice.
160 */
161 void setCallback(LLURLRequestComplete* callback);
162 //@}
163
164 /**
165 * @ brief Set certificate authority file used to verify HTTPS certs.
166 */
167 static void setCertificateAuthorityFile(const std::string& file_name);
168
169 /**
170 * @ brief Set certificate authority path used to verify HTTPS certs.
171 */
172 static void setCertificateAuthorityPath(const std::string& path);
173
174 /* @name LLIOPipe virtual implementations
175 */
176public:
177 /**
178 * @brief Give this pipe a chance to handle a generated error
179 */
180 virtual EStatus handleError(EStatus status, LLPumpIO* pump);
181
182protected:
183 /**
184 * @brief Process the data in buffer
185 */
186 virtual EStatus process_impl(
187 const LLChannelDescriptors& channels,
188 buffer_ptr_t& buffer,
189 bool& eos,
190 LLSD& context,
191 LLPumpIO* pump);
192 //@}
193
194protected:
195 enum EState
196 {
197 STATE_INITIALIZED,
198 STATE_WAITING_FOR_RESPONSE,
199 STATE_PROCESSING_RESPONSE,
200 STATE_HAVE_RESPONSE,
201 };
202 EState mState;
203 ERequestAction mAction;
204 LLURLRequestDetail* mDetail;
205 LLIOPipe::ptr_t mCompletionCallback;
206
207private:
208 /**
209 * @brief Initialize the object. Called during construction.
210 */
211 void initialize();
212
213 /**
214 * @brief Handle action specific url request configuration.
215 *
216 * @return Returns true if this is configured.
217 */
218 bool configure();
219
220 /**
221 * @brief Download callback method.
222 */
223 static size_t downCallback(
224 void* data,
225 size_t size,
226 size_t nmemb,
227 void* user);
228
229 /**
230 * @brief Upload callback method.
231 */
232 static size_t upCallback(
233 void* data,
234 size_t size,
235 size_t nmemb,
236 void* user);
237
238 /**
239 * @brief Declaration of unimplemented method to prevent copy
240 * construction.
241 */
242 LLURLRequest(const LLURLRequest&);
243};
244
245
246/**
247 * @class LLContextURLExtractor
248 * @brief This class unpacks the url out of a agent usher service so
249 * it can be packed into a LLURLRequest object.
250 * @see LLIOPipe
251 *
252 * This class assumes that the context is a map that contains an entry
253 * named CONTEXT_DEST_URI_SD_LABEL.
254 */
255class LLContextURLExtractor : public LLIOPipe
256{
257public:
258 LLContextURLExtractor(LLURLRequest* req) : mRequest(req) {}
259 ~LLContextURLExtractor() {}
260
261protected:
262 /* @name LLIOPipe virtual implementations
263 */
264 //@{
265 /**
266 * @brief Process the data in buffer
267 */
268 virtual EStatus process_impl(
269 const LLChannelDescriptors& channels,
270 buffer_ptr_t& buffer,
271 bool& eos,
272 LLSD& context,
273 LLPumpIO* pump);
274 //@}
275
276protected:
277 LLURLRequest* mRequest;
278};
279
280
281/**
282 * @class LLURLRequestComplete
283 * @brief Class which can optionally be used with an LLURLRequest to
284 * get notification when the url request is complete.
285 */
286class LLURLRequestComplete : public LLIOPipe
287{
288public:
289
290 virtual void header(const std::string& header, const std::string& value);
291 ///< Called once for each header received, prior to httpStatus
292
293 virtual void httpStatus(U32 status, const std::string& reason);
294 ///< Always called on request completion, prior to complete
295
296 virtual void complete(
297 const LLChannelDescriptors& channels,
298 const buffer_ptr_t& buffer);
299
300 /**
301 * @brief This method is called when we got a valid response.
302 *
303 * It is up to class implementers to do something useful here.
304 */
305 virtual void response(
306 const LLChannelDescriptors& channels,
307 const buffer_ptr_t& buffer);
308
309 /**
310 * @brief This method is called if there was no response.
311 *
312 * It is up to class implementers to do something useful here.
313 */
314 virtual void noResponse();
315
316 /**
317 * @brief This method will be called by the LLURLRequest object.
318 *
319 * If this is set to STATUS_OK or STATUS_STOP, then the transfer
320 * is asssumed to have worked. This will lead to calling response()
321 * on the next call to process(). Otherwise, this object will call
322 * noResponse() on the next call to process.
323 * @param status The status of the URLRequest.
324 */
325 void responseStatus(EStatus status);
326
327 // constructor & destructor.
328 LLURLRequestComplete();
329 virtual ~LLURLRequestComplete();
330
331protected:
332 /* @name LLIOPipe virtual implementations
333 */
334 //@{
335 /**
336 * @brief Process the data in buffer
337 */
338 virtual EStatus process_impl(
339 const LLChannelDescriptors& channels,
340 buffer_ptr_t& buffer,
341 bool& eos,
342 LLSD& context,
343 LLPumpIO* pump);
344 //@}
345
346 // value to note if we actually got the response. This value
347 // depends on correct useage from the LLURLRequest instance.
348 EStatus mRequestStatus;
349};
350
351
352/**
353 * @class LLURLRequestClientFactory
354 * @brief Template class to build url request based client chains
355 *
356 * This class eases construction of a basic sd rpc client. Here is an
357 * example of it's use:
358 * <code>
359 * class LLUsefulService : public LLService { ... }<br>
360 * LLService::registerCreator(<br>
361 * "useful",<br>
362 * LLService::creator_t(new LLURLRequestClientFactory<LLUsefulService>))<br>
363 * </code>
364 *
365 * This class should work, but I never got around to using/testing it.
366 *
367 */
368#if 0
369template<class Client>
370class LLURLRequestClientFactory : public LLChainIOFactory
371{
372public:
373 LLURLRequestClientFactory(LLURLRequest::ERequestAction action) {}
374 LLURLRequestClientFactory(
375 LLURLRequest::ERequestAction action,
376 const std::string& fixed_url) :
377 mAction(action),
378 mURL(fixed_url)
379 {
380 }
381 virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
382 {
383 lldebugs << "LLURLRequestClientFactory::build" << llendl;
384 LLIOPipe::ptr_t service(new Client);
385 chain.push_back(service);
386 LLURLRequest* http(new LLURLRequest(mAction));
387 LLIOPipe::ptr_t http_pipe(http);
388 // *FIX: how do we know the content type?
389 //http->addHeader("Content-Type: text/llsd");
390 if(mURL.empty())
391 {
392 chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
393 }
394 else
395 {
396 http->setURL(mURL);
397 }
398 chain.push_back(http_pipe);
399 chain.push_back(service);
400 return true;
401 }
402
403protected:
404 LLURLRequest::ERequestAction mAction;
405 std::string mURL;
406};
407#endif
408
409/**
410 * External constants
411 */
412extern const std::string CONTEXT_DEST_URI_SD_LABEL;
413
414#endif // LL_LLURLREQUEST_H