PageRenderTime 50ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llmessage/llproxy.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 352 lines | 136 code | 58 blank | 158 comment | 0 complexity | ce1952a22a3a4ea13413871fa2867265 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llproxy.h
  3. * @brief UDP and HTTP proxy communications
  4. *
  5. * $LicenseInfo:firstyear=2011&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2011, 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 LL_PROXY_H
  27. #define LL_PROXY_H
  28. #include "llcurl.h"
  29. #include "llhost.h"
  30. #include "lliosocket.h"
  31. #include "llmemory.h"
  32. #include "llsingleton.h"
  33. #include "llthread.h"
  34. #include <string>
  35. // SOCKS error codes returned from the StartProxy method
  36. #define SOCKS_OK 0
  37. #define SOCKS_CONNECT_ERROR (-1)
  38. #define SOCKS_NOT_PERMITTED (-2)
  39. #define SOCKS_NOT_ACCEPTABLE (-3)
  40. #define SOCKS_AUTH_FAIL (-4)
  41. #define SOCKS_UDP_FWD_NOT_GRANTED (-5)
  42. #define SOCKS_HOST_CONNECT_FAILED (-6)
  43. #define SOCKS_INVALID_HOST (-7)
  44. #ifndef MAXHOSTNAMELEN
  45. #define MAXHOSTNAMELEN (255 + 1) /* socks5: 255, +1 for len. */
  46. #endif
  47. #define SOCKSMAXUSERNAMELEN 255
  48. #define SOCKSMAXPASSWORDLEN 255
  49. #define SOCKSMINUSERNAMELEN 1
  50. #define SOCKSMINPASSWORDLEN 1
  51. #define SOCKS_VERSION 0x05 // we are using SOCKS 5
  52. #define SOCKS_HEADER_SIZE 10
  53. // SOCKS 5 address/hostname types
  54. #define ADDRESS_IPV4 0x01
  55. #define ADDRESS_HOSTNAME 0x03
  56. #define ADDRESS_IPV6 0x04
  57. // Lets just use our own ipv4 struct rather than dragging in system
  58. // specific headers
  59. union ipv4_address_t {
  60. U8 octets[4];
  61. U32 addr32;
  62. };
  63. // SOCKS 5 control channel commands
  64. #define COMMAND_TCP_STREAM 0x01
  65. #define COMMAND_TCP_BIND 0x02
  66. #define COMMAND_UDP_ASSOCIATE 0x03
  67. // SOCKS 5 command replies
  68. #define REPLY_REQUEST_GRANTED 0x00
  69. #define REPLY_GENERAL_FAIL 0x01
  70. #define REPLY_RULESET_FAIL 0x02
  71. #define REPLY_NETWORK_UNREACHABLE 0x03
  72. #define REPLY_HOST_UNREACHABLE 0x04
  73. #define REPLY_CONNECTION_REFUSED 0x05
  74. #define REPLY_TTL_EXPIRED 0x06
  75. #define REPLY_PROTOCOL_ERROR 0x07
  76. #define REPLY_TYPE_NOT_SUPPORTED 0x08
  77. #define FIELD_RESERVED 0x00
  78. // The standard SOCKS 5 request packet
  79. // Push current alignment to stack and set alignment to 1 byte boundary
  80. // This enabled us to use structs directly to set up and receive network packets
  81. // into the correct fields, without fear of boundary alignment causing issues
  82. #pragma pack(push,1)
  83. // SOCKS 5 command packet
  84. struct socks_command_request_t {
  85. U8 version;
  86. U8 command;
  87. U8 reserved;
  88. U8 atype;
  89. U32 address;
  90. U16 port;
  91. };
  92. // Standard SOCKS 5 reply packet
  93. struct socks_command_response_t {
  94. U8 version;
  95. U8 reply;
  96. U8 reserved;
  97. U8 atype;
  98. U8 add_bytes[4];
  99. U16 port;
  100. };
  101. #define AUTH_NOT_ACCEPTABLE 0xFF // reply if preferred methods are not available
  102. #define AUTH_SUCCESS 0x00 // reply if authentication successful
  103. // SOCKS 5 authentication request, stating which methods the client supports
  104. struct socks_auth_request_t {
  105. U8 version;
  106. U8 num_methods;
  107. U8 methods; // We are only using a single method currently
  108. };
  109. // SOCKS 5 authentication response packet, stating server preferred method
  110. struct socks_auth_response_t {
  111. U8 version;
  112. U8 method;
  113. };
  114. // SOCKS 5 password reply packet
  115. struct authmethod_password_reply_t {
  116. U8 version;
  117. U8 status;
  118. };
  119. // SOCKS 5 UDP packet header
  120. struct proxywrap_t {
  121. U16 rsv;
  122. U8 frag;
  123. U8 atype;
  124. U32 addr;
  125. U16 port;
  126. };
  127. #pragma pack(pop) /* restore original alignment from stack */
  128. // Currently selected HTTP proxy type
  129. enum LLHttpProxyType
  130. {
  131. LLPROXY_SOCKS = 0,
  132. LLPROXY_HTTP = 1
  133. };
  134. // Auth types
  135. enum LLSocks5AuthType
  136. {
  137. METHOD_NOAUTH = 0x00, // Client supports no auth
  138. METHOD_GSSAPI = 0x01, // Client supports GSSAPI (Not currently supported)
  139. METHOD_PASSWORD = 0x02 // Client supports username/password
  140. };
  141. /**
  142. * @brief Manage SOCKS 5 UDP proxy and HTTP proxy.
  143. *
  144. * This class is responsible for managing two interconnected tasks,
  145. * connecting to a SOCKS 5 proxy for use by LLPacketRing to send UDP
  146. * packets and managing proxy settings for HTTP requests.
  147. *
  148. * <h1>Threading:</h1>
  149. * Because HTTP requests can be generated in threads outside the
  150. * main thread, it is necessary for some of the information stored
  151. * by this class to be available to other threads. The members that
  152. * need to be read across threads are in a labeled section below.
  153. * To protect those members, a mutex, mProxyMutex should be locked
  154. * before reading or writing those members. Methods that can lock
  155. * mProxyMutex are in a labeled section below. Those methods should
  156. * not be called while the mutex is already locked.
  157. *
  158. * There is also a LLAtomic type flag (mHTTPProxyEnabled) that is used
  159. * to track whether the HTTP proxy is currently enabled. This allows
  160. * for faster unlocked checks to see if the proxy is enabled. This
  161. * allows us to cut down on the performance hit when the proxy is
  162. * disabled compared to before this class was introduced.
  163. *
  164. * <h1>UDP Proxying:</h1>
  165. * UDP datagrams are proxied via a SOCKS 5 proxy with the UDP associate
  166. * command. To initiate the proxy, a TCP socket connection is opened
  167. * to the SOCKS 5 host, and after a handshake exchange, the server
  168. * returns a port and address to send the UDP traffic that is to be
  169. * proxied to. The LLProxy class tracks this address and port after the
  170. * exchange and provides it to LLPacketRing when required to. All UDP
  171. * proxy management occurs in the main thread.
  172. *
  173. * <h1>HTTP Proxying:</h1>
  174. * This class allows all viewer HTTP packets to be sent through a proxy.
  175. * The user can select whether to send HTTP packets through a standard
  176. * "web" HTTP proxy, through a SOCKS 5 proxy, or to not proxy HTTP
  177. * communication. This class does not manage the integrated web browser
  178. * proxy, which is handled in llviewermedia.cpp.
  179. *
  180. * The implementation of HTTP proxying is handled by libcurl. LLProxy
  181. * is responsible for managing the HTTP proxy options and provides a
  182. * thread-safe method to apply those options to a curl request
  183. * (LLProxy::applyProxySettings()). This method is overloaded
  184. * to accommodate the various abstraction libcurl layers that exist
  185. * throughout the viewer (LLCurlEasyRequest, LLCurl::Easy, and CURL).
  186. *
  187. * If you are working with LLCurl or LLCurlEasyRequest objects,
  188. * the configured proxy settings will be applied in the constructors
  189. * of those request handles. If you are working with CURL objects
  190. * directly, you will need to pass the handle of the request to
  191. * applyProxySettings() before issuing the request.
  192. *
  193. * To ensure thread safety, all LLProxy members that relate to the HTTP
  194. * proxy require the LLProxyMutex to be locked before accessing.
  195. */
  196. class LLProxy: public LLSingleton<LLProxy>
  197. {
  198. LOG_CLASS(LLProxy);
  199. public:
  200. /*###########################################################################################
  201. METHODS THAT DO NOT LOCK mProxyMutex!
  202. ###########################################################################################*/
  203. // Constructor, cannot have parameters due to LLSingleton parent class. Call from main thread only.
  204. LLProxy();
  205. // Static check for enabled status for UDP packets. Call from main thread only.
  206. static bool isSOCKSProxyEnabled() { return sUDPProxyEnabled; }
  207. // Get the UDP proxy address and port. Call from main thread only.
  208. LLHost getUDPProxy() const { return mUDPProxy; }
  209. /*###########################################################################################
  210. END OF NON-LOCKING METHODS
  211. ###########################################################################################*/
  212. /*###########################################################################################
  213. METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED!
  214. ###########################################################################################*/
  215. // Destructor, closes open connections. Do not call directly, use cleanupClass().
  216. ~LLProxy();
  217. // Delete LLProxy singleton. Allows the apr_socket used in the SOCKS 5 control channel to be
  218. // destroyed before the call to apr_terminate. Call from main thread only.
  219. static void cleanupClass();
  220. // Apply the current proxy settings to a curl request. Doesn't do anything if mHTTPProxyEnabled is false.
  221. // Safe to call from any thread.
  222. void applyProxySettings(CURL* handle);
  223. void applyProxySettings(LLCurl::Easy* handle);
  224. void applyProxySettings(LLCurlEasyRequest* handle);
  225. // Start a connection to the SOCKS 5 proxy. Call from main thread only.
  226. S32 startSOCKSProxy(LLHost host);
  227. // Disconnect and clean up any connection to the SOCKS 5 proxy. Call from main thread only.
  228. void stopSOCKSProxy();
  229. // Use Password auth when connecting to the SOCKS proxy. Call from main thread only.
  230. bool setAuthPassword(const std::string &username, const std::string &password);
  231. // Disable authentication when connecting to the SOCKS proxy. Call from main thread only.
  232. void setAuthNone();
  233. // Proxy HTTP packets via httpHost, which can be a SOCKS 5 or a HTTP proxy.
  234. // as specified in type. Call from main thread only.
  235. bool enableHTTPProxy(LLHost httpHost, LLHttpProxyType type);
  236. bool enableHTTPProxy();
  237. // Stop proxying HTTP packets. Call from main thread only.
  238. void disableHTTPProxy();
  239. /*###########################################################################################
  240. END OF LOCKING METHODS
  241. ###########################################################################################*/
  242. private:
  243. /*###########################################################################################
  244. METHODS THAT LOCK mProxyMutex! DO NOT CALL WHILE mProxyMutex IS LOCKED!
  245. ###########################################################################################*/
  246. // Perform a SOCKS 5 authentication and UDP association with the proxy server.
  247. S32 proxyHandshake(LLHost proxy);
  248. // Get the currently selected auth method.
  249. LLSocks5AuthType getSelectedAuthMethod() const;
  250. // Get the currently selected HTTP proxy type
  251. LLHttpProxyType getHTTPProxyType() const;
  252. std::string getSocksPwd() const;
  253. std::string getSocksUser() const;
  254. /*###########################################################################################
  255. END OF LOCKING METHODS
  256. ###########################################################################################*/
  257. private:
  258. // Is the HTTP proxy enabled? Safe to read in any thread, but do not write directly.
  259. // Instead use enableHTTPProxy() and disableHTTPProxy() instead.
  260. mutable LLAtomic32<bool> mHTTPProxyEnabled;
  261. // Mutex to protect shared members in non-main thread calls to applyProxySettings().
  262. mutable LLMutex mProxyMutex;
  263. /*###########################################################################################
  264. MEMBERS READ AND WRITTEN ONLY IN THE MAIN THREAD. DO NOT SHARE!
  265. ###########################################################################################*/
  266. // Is the UDP proxy enabled?
  267. static bool sUDPProxyEnabled;
  268. // UDP proxy address and port
  269. LLHost mUDPProxy;
  270. // TCP proxy control channel address and port
  271. LLHost mTCPProxy;
  272. // socket handle to proxy TCP control channel
  273. LLSocket::ptr_t mProxyControlChannel;
  274. /*###########################################################################################
  275. END OF UNSHARED MEMBERS
  276. ###########################################################################################*/
  277. /*###########################################################################################
  278. MEMBERS WRITTEN IN MAIN THREAD AND READ IN ANY THREAD. ONLY READ OR WRITE AFTER LOCKING mProxyMutex!
  279. ###########################################################################################*/
  280. // HTTP proxy address and port
  281. LLHost mHTTPProxy;
  282. // Currently selected HTTP proxy type. Can be web or socks.
  283. LLHttpProxyType mProxyType;
  284. // SOCKS 5 selected authentication method.
  285. LLSocks5AuthType mAuthMethodSelected;
  286. // SOCKS 5 username
  287. std::string mSocksUsername;
  288. // SOCKS 5 password
  289. std::string mSocksPassword;
  290. /*###########################################################################################
  291. END OF SHARED MEMBERS
  292. ###########################################################################################*/
  293. };
  294. #endif