llurlrequest.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:11k
源码类别:

游戏引擎

开发平台:

C++ Builder

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