PageRenderTime 1ms CodeModel.GetById 6ms app.highlight 29ms RepoModel.GetById 2ms app.codeStats 0ms

/indra/llmessage/llurlrequest.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 382 lines | 124 code | 52 blank | 206 comment | 0 complexity | c2126a99c6df045d95843faa8c3e4a11 MD5 | raw file
  1/** 
  2 * @file llurlrequest.h
  3 * @author Phoenix
  4 * @date 2005-04-21
  5 * @brief Declaration of url based requests on pipes.
  6 *
  7 * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  8 * Second Life Viewer Source Code
  9 * Copyright (C) 2010, Linden Research, Inc.
 10 * 
 11 * This library is free software; you can redistribute it and/or
 12 * modify it under the terms of the GNU Lesser General Public
 13 * License as published by the Free Software Foundation;
 14 * version 2.1 of the License only.
 15 * 
 16 * This library is distributed in the hope that it will be useful,
 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 19 * Lesser General Public License for more details.
 20 * 
 21 * You should have received a copy of the GNU Lesser General Public
 22 * License along with this library; if not, write to the Free Software
 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 24 * 
 25 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 26 * $/LicenseInfo$
 27 */
 28
 29#ifndef LL_LLURLREQUEST_H
 30#define LL_LLURLREQUEST_H
 31
 32/** 
 33 * This file holds the declaration of useful classes for dealing with
 34 * url based client requests. 
 35 */
 36
 37#include <string>
 38#include "lliopipe.h"
 39#include "llchainio.h"
 40#include "llerror.h"
 41#include <openssl/x509_vfy.h>
 42#include "llcurl.h"
 43
 44
 45extern const std::string CONTEXT_REQUEST;
 46extern const std::string CONTEXT_DEST_URI_SD_LABEL;
 47extern const std::string CONTEXT_RESPONSE;
 48extern const std::string CONTEXT_TRANSFERED_BYTES;
 49
 50class LLURLRequestDetail;
 51
 52class LLURLRequestComplete;
 53
 54/** 
 55 * @class LLURLRequest
 56 * @brief Class to handle url based requests.
 57 * @see LLIOPipe
 58 *
 59 * Currently, this class is implemented on top of curl. From the
 60 * vantage of a programmer using this class, you do not care so much,
 61 * but it's useful to know since in order to accomplish 'non-blocking'
 62 * behavior, we have to use a more expensive curl interface which can
 63 * still block if the server enters a half-accepted state. It would be
 64 * worth the time and effort to eventually port this to a raw client
 65 * socket.
 66 */
 67class LLURLRequest : public LLIOPipe
 68{
 69	LOG_CLASS(LLURLRequest);
 70public:
 71
 72	typedef int (* SSLCertVerifyCallback)(X509_STORE_CTX *ctx, void *param);
 73	/** 
 74	 * @brief This enumeration is for specifying the type of request.
 75	 */
 76	enum ERequestAction
 77	{
 78		INVALID,
 79		HTTP_HEAD,
 80		HTTP_GET,
 81		HTTP_PUT,
 82		HTTP_POST,
 83		HTTP_DELETE,
 84		HTTP_MOVE, // Caller will need to set 'Destination' header
 85		REQUEST_ACTION_COUNT
 86	};
 87
 88	/**
 89	 * @brief Turn the requst action into an http verb.
 90	 */
 91	static std::string actionAsVerb(ERequestAction action);
 92
 93	/** 
 94	 * @brief Constructor.
 95	 *
 96	 * @param action One of the ERequestAction enumerations.
 97	 */
 98	LLURLRequest(ERequestAction action);
 99
100	/** 
101	 * @brief Constructor.
102	 *
103	 * @param action One of the ERequestAction enumerations.
104	 * @param url The url of the request. It should already be encoded.
105	 */
106	LLURLRequest(ERequestAction action, const std::string& url);
107
108	/** 
109	 * @brief Destructor.
110	 */
111	virtual ~LLURLRequest();
112
113	/* @name Instance methods
114	 */
115	//@{
116	/** 
117	 * @brief Set the url for the request
118	 *
119	 * This method assumes the url is encoded appropriately for the
120	 * request. 
121	 * The url must be set somehow before the first call to process(),
122	 * or the url will not be set correctly.
123	 * 
124	 */
125	void setURL(const std::string& url);
126	std::string getURL() const;
127	/** 
128	 * @brief Add a header to the http post.
129	 *
130	 * The header must be correctly formatted for HTTP requests. This
131	 * provides a raw interface if you know what kind of request you
132	 * will be making during construction of this instance. All
133	 * required headers will be automatically constructed, so this is
134	 * usually useful for encoding parameters.
135	 */
136	void addHeader(const char* header);
137
138	/**
139	 * @brief Check remote server certificate signed by a known root CA.
140	 *
141	 * Set whether request will check that remote server
142	 * certificates are signed by a known root CA when using HTTPS.
143	 */
144	void setSSLVerifyCallback(SSLCertVerifyCallback callback, void * param);
145
146	
147	/**
148	 * @brief Return at most size bytes of body.
149	 *
150	 * If the body had more bytes than this limit, they will not be
151	 * returned and the connection closed.  In this case, STATUS_STOP
152	 * will be passed to responseStatus();
153	 */
154	void setBodyLimit(U32 size);
155
156	/** 
157	 * @brief Set a completion callback for this URLRequest.
158	 *
159	 * The callback is added to this URLRequet's pump when either the
160	 * entire buffer is known or an error like timeout or connection
161	 * refused has happened. In the case of a complete transfer, this
162	 * object builds a response chain such that the callback and the
163	 * next process consumer get to read the output.
164	 *
165	 * This setup is a little fragile since the url request consumer
166	 * might not just read the data - it may do a channel change,
167	 * which invalidates the input to the callback, but it works well
168	 * in practice.
169	 */
170	void setCallback(LLURLRequestComplete* callback);
171	//@}
172
173	/* @name LLIOPipe virtual implementations
174	 */
175
176    /**
177     * @ brief Turn off (or on) the CURLOPT_PROXY header.
178     */
179    void useProxy(bool use_proxy);
180
181    /**
182     * @ brief Set the CURLOPT_PROXY header to the given value.
183     */
184	void useProxy(const std::string& proxy);
185
186	/**
187	 * @brief Turn on cookie handling for this request with CURLOPT_COOKIEFILE.
188	 */
189	void allowCookies();
190
191	/*virtual*/ bool isValid() ;
192
193public:
194	/** 
195	 * @brief Give this pipe a chance to handle a generated error
196	 */
197	virtual EStatus handleError(EStatus status, LLPumpIO* pump);
198
199	
200protected:
201	/** 
202	 * @brief Process the data in buffer
203	 */
204	virtual EStatus process_impl(
205		const LLChannelDescriptors& channels,
206		buffer_ptr_t& buffer,
207		bool& eos,
208		LLSD& context,
209		LLPumpIO* pump);
210	//@}
211
212protected:
213	enum EState
214	{
215		STATE_INITIALIZED,
216		STATE_WAITING_FOR_RESPONSE,
217		STATE_PROCESSING_RESPONSE,
218		STATE_HAVE_RESPONSE,
219	};
220	EState mState;
221	ERequestAction mAction;
222	LLURLRequestDetail* mDetail;
223	LLIOPipe::ptr_t mCompletionCallback;
224	 S32 mRequestTransferedBytes;
225	 S32 mResponseTransferedBytes;
226
227	static CURLcode _sslCtxCallback(CURL * curl, void *sslctx, void *param);
228	
229private:
230	/** 
231	 * @brief Initialize the object. Called during construction.
232	 */
233	void initialize();
234
235	/** 
236	 * @brief Handle action specific url request configuration.
237	 *
238	 * @return Returns true if this is configured.
239	 */
240	bool configure();
241
242	/** 
243	 * @brief Download callback method.
244	 */
245 	static size_t downCallback(
246		char* data,
247		size_t size,
248		size_t nmemb,
249		void* user);
250
251	/** 
252	 * @brief Upload callback method.
253	 */
254 	static size_t upCallback(
255		char* data,
256		size_t size,
257		size_t nmemb,
258		void* user);
259
260	/** 
261	 * @brief Declaration of unimplemented method to prevent copy
262	 * construction.
263	 */
264	LLURLRequest(const LLURLRequest&);
265};
266
267
268/** 
269 * @class LLContextURLExtractor
270 * @brief This class unpacks the url out of a agent usher service so
271 * it can be packed into a LLURLRequest object.
272 * @see LLIOPipe
273 *
274 * This class assumes that the context is a map that contains an entry
275 * named CONTEXT_DEST_URI_SD_LABEL.
276 */
277class LLContextURLExtractor : public LLIOPipe
278{
279public:
280	LLContextURLExtractor(LLURLRequest* req) : mRequest(req) {}
281	~LLContextURLExtractor() {}
282
283protected:
284	/* @name LLIOPipe virtual implementations
285	 */
286	//@{
287	/** 
288	 * @brief Process the data in buffer
289	 */
290	virtual EStatus process_impl(
291		const LLChannelDescriptors& channels,
292		buffer_ptr_t& buffer,
293		bool& eos,
294		LLSD& context,
295		LLPumpIO* pump);
296	//@}
297
298protected:
299	LLURLRequest* mRequest;
300};
301
302
303/** 
304 * @class LLURLRequestComplete
305 * @brief Class which can optionally be used with an LLURLRequest to
306 * get notification when the url request is complete.
307 */
308class LLURLRequestComplete : public LLIOPipe
309{
310public:
311	
312	// Called once for each header received, except status lines
313	virtual void header(const std::string& header, const std::string& value);
314
315	// May be called more than once, particularly for redirects and proxy madness.
316	// Ex. a 200 for a connection to https through a proxy, followed by the "real" status
317	//     a 3xx for a redirect followed by a "real" status, or more redirects.
318	virtual void httpStatus(U32 status, const std::string& reason) { }
319
320	virtual void complete(
321		const LLChannelDescriptors& channels,
322		const buffer_ptr_t& buffer);
323
324	/** 
325	 * @brief This method is called when we got a valid response.
326	 *
327	 * It is up to class implementers to do something useful here.
328	 */
329	virtual void response(
330		const LLChannelDescriptors& channels,
331		const buffer_ptr_t& buffer);
332
333	/** 
334	 * @brief This method is called if there was no response.
335	 *
336	 * It is up to class implementers to do something useful here.
337	 */
338	virtual void noResponse();
339
340	/** 
341	 * @brief This method will be called by the LLURLRequest object.
342	 *
343	 * If this is set to STATUS_OK or STATUS_STOP, then the transfer
344	 * is asssumed to have worked. This will lead to calling response()
345	 * on the next call to process(). Otherwise, this object will call
346	 * noResponse() on the next call to process.
347	 * @param status The status of the URLRequest.
348	 */
349	void responseStatus(EStatus status);
350
351	// constructor & destructor.
352	LLURLRequestComplete();
353	virtual ~LLURLRequestComplete();
354
355protected:
356	/* @name LLIOPipe virtual implementations
357	 */
358	//@{
359	/** 
360	 * @brief Process the data in buffer
361	 */
362	virtual EStatus process_impl(
363		const LLChannelDescriptors& channels,
364		buffer_ptr_t& buffer,
365		bool& eos,
366		LLSD& context,
367		LLPumpIO* pump);
368	//@}
369
370	// value to note if we actually got the response. This value
371	// depends on correct useage from the LLURLRequest instance.
372	EStatus mRequestStatus;
373};
374
375
376
377/**
378 * External constants
379 */
380extern const std::string CONTEXT_DEST_URI_SD_LABEL;
381
382#endif // LL_LLURLREQUEST_H