llcorehttplibcurl.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /**
  2. * @file llcorehttplibcurl.h
  3. * @brief Declarations for internal class providing libcurl transport.
  4. *
  5. * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2012, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #ifndef _LLCORE_HTTP_LIBCURL_H_
  27. #define _LLCORE_HTTP_LIBCURL_H_
  28. #include <vector>
  29. #include "curl/curl.h" // For CURL typedef
  30. #include "curl/multi.h" // For CURLM typedef
  31. #include "llcorehttpinternal.h"
  32. #include "llcorehttprequest.h"
  33. #include "llcorehttpservice.h"
  34. #include "llerror.h"
  35. #include "hbfastset.h"
  36. namespace LLCore
  37. {
  38. class HttpPolicy;
  39. class HttpOpRequest;
  40. class HttpHeaders;
  41. // Implements libcurl-based transport for an HttpService instance.
  42. //
  43. // Threading: Single-threaded. Other than for construction/destruction, all
  44. // methods are expected to be invoked in a single thread, typically a worker
  45. // thread of some sort.
  46. class HttpLibcurl
  47. {
  48. protected:
  49. LOG_CLASS(HttpLibcurl);
  50. public:
  51. HttpLibcurl(HttpService* service);
  52. virtual ~HttpLibcurl();
  53. HttpLibcurl(const HttpLibcurl&) = delete;
  54. void operator=(const HttpLibcurl&) = delete;
  55. typedef std::shared_ptr<HttpOpRequest> opReqPtr_t;
  56. // Give cycles to libcurl to run active requests. Completed operations
  57. // (successful or failed) will be retried or handed over to the reply queue
  58. // as final responses.
  59. //
  60. // @return Indication of how long this method is willing to wait for next
  61. // service call.
  62. //
  63. // Threading: called by worker thread.
  64. HttpService::ELoopSpeed processTransport();
  65. // Add request to the active list. Caller is expected to have provided us
  66. // with a reference count on the op to hold the request (no additional
  67. // reference will be added).
  68. void addOp(const opReqPtr_t& op);
  69. // One-time call to set the number of policy classes to be serviced and to
  70. // create the resources for each. Value must agree with
  71. // HttpPolicy::setPolicies() call.
  72. //
  73. // Threading: called by init thread.
  74. void start(int policy_count);
  75. // Synchronously stop libcurl operations. All active requests are cancelled
  76. // and removed from libcurl's handling. Easy handles are detached from
  77. // their multi handles and released. Multi handles are also released.
  78. // Cancelled requests are completed with cancelled status and made
  79. // available on their respective reply queues.
  80. //
  81. // Can be restarted with a start() call.
  82. //
  83. // Threading: called by worker thread.
  84. void shutdown();
  85. // Return global and per-class counts of active requests.
  86. LL_INLINE int getActiveCount() const { return mActiveOps.size(); }
  87. int getActiveCountInClass(int policy_class) const;
  88. // Attempt to cancel a request identified by handle.
  89. //
  90. // Interface shadows HttpService's method.
  91. //
  92. // @return True if handle was found and operation cancelled.
  93. //
  94. // Threading: called by worker thread.
  95. bool cancel(HttpHandle handle);
  96. // Informs transport that a particular policy class has had options changed
  97. // and so should affect any transport state change necessary to affect
  98. // those changes. Used mainly for initialization and dynamic option
  99. // setting.
  100. //
  101. // Threading: called by worker thread.
  102. void policyUpdated(int policy_class);
  103. // Allocate a curl handle for caller. May be freed using either the
  104. // freeHandle() method or calling curl_easy_cleanup() directly.
  105. //
  106. // @return Libcurl handle (CURL *) or NULL on allocation problem.
  107. // Handle will be in curl_easy_reset() condition.
  108. //
  109. // Threading: callable by worker thread.
  110. //
  111. // Deprecation: Expect this to go away after llcorehttpoprequest is
  112. // refactored bringing code into this class.
  113. LL_INLINE CURL* getHandle() { return mHandleCache.getHandle(); }
  114. static LL_INLINE U64 getDownloadedBytes() { return sDownloadedBytes; }
  115. static LL_INLINE U64 getUploadedBytes() { return sUploadedBytes; }
  116. protected:
  117. // Invoked when libcurl has indicated a request has been processed to
  118. // completion and we need to move the request to a new state.
  119. bool completeRequest(CURLM* multi_handle, CURL* handle, CURLcode status);
  120. // Invoked to cancel an active request, mainly during shutdown and destroy.
  121. void cancelRequest(const opReqPtr_t& op);
  122. // Simple request handle cache for libcurl.
  123. //
  124. // Handle creation is somewhat slow and chunky in libcurl and there's a
  125. // pretty good speedup to be had from handle re-use. So, a simple vector is
  126. // kept of 'freed' handles to be reused as needed. When that is empty, the
  127. // first freed handle is kept as a template for handle duplication. This is
  128. // still faster than creation from nothing. And when that fails, we init
  129. // fresh from curl_easy_init().
  130. //
  131. // Handles allocated with getHandle() may be freed with either freeHandle()
  132. // or curl_easy_cleanup(). Choice may be dictated by thread constraints.
  133. //
  134. // Threading: Single-threaded. May only be used by a single thread,
  135. // typically the worker thread. If freeing requests' handles
  136. // in an unknown threading context, use curl_easy_cleanup()
  137. // for safety.
  138. class HandleCache
  139. {
  140. public:
  141. HandleCache();
  142. ~HandleCache();
  143. HandleCache(const HandleCache&) = delete;
  144. void operator=(const HandleCache&) = delete;
  145. // Allocate a curl handle for caller. May be freed using either the
  146. // freeHandle() method or calling curl_easy_cleanup() directly.
  147. //
  148. // @return Libcurl handle (CURL*) or NULL on allocation problem.
  149. //
  150. // Threading: Single-thread (worker) only.
  151. CURL* getHandle();
  152. // Free a libcurl handle acquired by whatever means. Thread safety is
  153. // left to the caller.
  154. //
  155. // Threading: Single-thread (worker) only.
  156. void freeHandle(CURL* handle);
  157. protected:
  158. typedef std::vector<CURL*> handle_cache_t;
  159. protected:
  160. CURL* mHandleTemplate; // Template for duplicating new handles
  161. handle_cache_t mCache; // Cache of old handles
  162. };
  163. protected:
  164. HttpService* mService; // Simple reference, not owner
  165. HandleCache mHandleCache; // Handle allocator, owner
  166. typedef safe_hset<opReqPtr_t> active_set_t;
  167. active_set_t mActiveOps;
  168. int mPolicyCount;
  169. CURLM** mMultiHandles; // One handle per policy class
  170. int* mActiveHandles; // Active count per policy class
  171. bool* mDirtyPolicy; // Dirty policy update waiting for stall (per pc)
  172. static U64 sDownloadedBytes;
  173. static U64 sUploadedBytes;
  174. };
  175. } // End namespace LLCore
  176. #endif // _LLCORE_HTTP_LIBCURL_H_