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