/** * @file _httpoprequest.h * @brief Internal declarations for the HttpOpRequest subclass * * $LicenseInfo:firstyear=2012&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2012-2013, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #ifndef _LLCORE_HTTP_OPREQUEST_H_ #define _LLCORE_HTTP_OPREQUEST_H_ #include "linden_common.h" // Modifies curl/curl.h interfaces #include #include #include #include #include "httpcommon.h" #include "httprequest.h" #include "_httpoperation.h" #include "_refcounted.h" #include "httpheaders.h" #include "httpoptions.h" namespace LLCore { class BufferArray; /// HttpOpRequest requests a supported HTTP method invocation with /// option and header overrides. /// /// Essentially an RPC to get an HTTP GET, POST or PUT executed /// asynchronously with options to override behaviors and HTTP /// headers. /// /// Constructor creates a raw object incapable of useful work. /// A subsequent call to one of the setupXXX() methods provides /// the information needed to make a working request which can /// then be enqueued to a request queue. /// class HttpOpRequest : public HttpOperation { public: typedef boost::shared_ptr ptr_t; HttpOpRequest(); virtual ~HttpOpRequest(); // Use release() private: HttpOpRequest(const HttpOpRequest &); // Not defined void operator=(const HttpOpRequest &); // Not defined public: enum EMethod { HOR_GET, HOR_POST, HOR_PUT, HOR_DELETE, HOR_PATCH, HOR_COPY, HOR_MOVE }; static std::string methodToString(const EMethod &); virtual void stageFromRequest(HttpService *); virtual void stageFromReady(HttpService *); virtual void stageFromActive(HttpService *); virtual void visitNotifier(HttpRequest * request); public: /// Setup Methods /// /// Basically an RPC setup for each type of HTTP method /// invocation with one per method type. These are /// generally invoked right after construction. /// /// Threading: called by application thread /// HttpStatus setupGet(HttpRequest::policy_t policy_id, HttpRequest::priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers); HttpStatus setupGetByteRange(HttpRequest::policy_t policy_id, HttpRequest::priority_t priority, const std::string & url, size_t offset, size_t len, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers); HttpStatus setupPost(HttpRequest::policy_t policy_id, HttpRequest::priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers); HttpStatus setupPut(HttpRequest::policy_t policy_id, HttpRequest::priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers); HttpStatus setupDelete(HttpRequest::policy_t policy_id, HttpRequest::priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers); HttpStatus setupPatch(HttpRequest::policy_t policy_id, HttpRequest::priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers); HttpStatus setupCopy(HttpRequest::policy_t policy_id, HttpRequest::priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers); HttpStatus setupMove(HttpRequest::policy_t policy_id, HttpRequest::priority_t priority, const std::string & url, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers); // Internal method used to setup the libcurl options for a request. // Does all the libcurl handle setup in one place. // // Threading: called by worker thread // HttpStatus prepareRequest(HttpService * service); virtual HttpStatus cancel(); protected: // Common setup for all the request methods. // // Threading: called by application thread // void setupCommon(HttpRequest::policy_t policy_id, HttpRequest::priority_t priority, const std::string & url, BufferArray * body, const HttpOptions::ptr_t & options, const HttpHeaders::ptr_t & headers); // libcurl operational callbacks // // Threading: called by worker thread // static size_t writeCallback(void * data, size_t size, size_t nmemb, void * userdata); static size_t readCallback(void * data, size_t size, size_t nmemb, void * userdata); static int seekCallback(void *data, curl_off_t offset, int origin); static size_t headerCallback(void * data, size_t size, size_t nmemb, void * userdata); static CURLcode curlSslCtxCallback(CURL *curl, void *ssl_ctx, void *userptr); static int sslCertVerifyCallback(X509_STORE_CTX *ctx, void *param); static int debugCallback(CURL *, curl_infotype info, char * buffer, size_t len, void * userdata); protected: unsigned int mProcFlags; static const unsigned int PF_SCAN_RANGE_HEADER = 0x00000001U; static const unsigned int PF_SAVE_HEADERS = 0x00000002U; static const unsigned int PF_USE_RETRY_AFTER = 0x00000004U; HttpRequest::policyCallback_t mCallbackSSLVerify; public: // Request data EMethod mReqMethod; std::string mReqURL; BufferArray * mReqBody; off_t mReqOffset; size_t mReqLength; HttpHeaders::ptr_t mReqHeaders; HttpOptions::ptr_t mReqOptions; // Transport data bool mCurlActive; CURL * mCurlHandle; HttpService * mCurlService; curl_slist * mCurlHeaders; size_t mCurlBodyPos; char * mCurlTemp; // Scratch buffer for header processing size_t mCurlTempLen; // Result data HttpStatus mStatus; BufferArray * mReplyBody; off_t mReplyOffset; size_t mReplyLength; size_t mReplyFullLength; HttpHeaders::ptr_t mReplyHeaders; std::string mReplyConType; int mReplyRetryAfter; // Policy data int mPolicyRetries; int mPolicy503Retries; HttpTime mPolicyRetryAt; int mPolicyRetryLimit; }; // end class HttpOpRequest /// HttpOpRequestCompare isn't an operation but a uniform comparison /// functor for STL containers that order by priority. Mainly /// used for the ready queue container but defined here. class HttpOpRequestCompare { public: bool operator()(const HttpOpRequest * lhs, const HttpOpRequest * rhs) { return lhs->mReqPriority > rhs->mReqPriority; } }; // end class HttpOpRequestCompare // --------------------------------------- // Free functions // --------------------------------------- // Internal function to append the contents of an HttpHeaders // instance to a curl_slist object. curl_slist * append_headers_to_slist(const HttpHeaders::ptr_t &, curl_slist * slist); } // end namespace LLCore #endif // _LLCORE_HTTP_OPREQUEST_H_