aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmessage/lliosocket.h
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llmessage/lliosocket.h')
-rw-r--r--linden/indra/llmessage/lliosocket.h374
1 files changed, 374 insertions, 0 deletions
diff --git a/linden/indra/llmessage/lliosocket.h b/linden/indra/llmessage/lliosocket.h
new file mode 100644
index 0000000..f994404
--- /dev/null
+++ b/linden/indra/llmessage/lliosocket.h
@@ -0,0 +1,374 @@
1/**
2 * @file lliosocket.h
3 * @author Phoenix
4 * @date 2005-07-31
5 * @brief Declaration of files used for handling sockets and associated pipes
6 *
7 * Copyright (c) 2005-2007, Linden Research, Inc.
8 *
9 * The source code in this file ("Source Code") is provided by Linden Lab
10 * to you under the terms of the GNU General Public License, version 2.0
11 * ("GPL"), unless you have obtained a separate licensing agreement
12 * ("Other License"), formally executed by you and Linden Lab. Terms of
13 * the GPL can be found in doc/GPL-license.txt in this distribution, or
14 * online at http://secondlife.com/developers/opensource/gplv2
15 *
16 * There are special exceptions to the terms and conditions of the GPL as
17 * it is applied to this Source Code. View the full text of the exception
18 * in the file doc/FLOSS-exception.txt in this software distribution, or
19 * online at http://secondlife.com/developers/opensource/flossexception
20 *
21 * By copying, modifying or distributing this software, you acknowledge
22 * that you have read and understood your obligations described above,
23 * and agree to abide by those obligations.
24 *
25 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
26 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
27 * COMPLETENESS OR PERFORMANCE.
28 */
29
30#ifndef LL_LLIOSOCKET_H
31#define LL_LLIOSOCKET_H
32
33/**
34 * The socket interface provided here is a simple wraper around apr
35 * sockets, with a pipe source and sink to read and write off of the
36 * socket. Every socket only performs non-blocking operations except
37 * the server socket which only performs blocking operations when an
38 * OS poll indicates it will not block.
39 */
40
41#include "lliopipe.h"
42#include "apr-1/apr_pools.h"
43#include "apr-1/apr_network_io.h"
44#include "llchainio.h"
45
46class LLHost;
47
48/**
49 * @class LLSocket
50 * @brief Implementation of a wrapper around a socket.
51 *
52 * An instance of this class represents a single socket over it's
53 * entire life - from uninitialized, to connected, to a listening
54 * socket depending on it's purpose. This class simplifies our access
55 * into the socket interface by only providing stream/tcp and
56 * datagram/udp sockets - the only types we are interested in, since
57 * those are the only properly supported by all of our platforms.
58 */
59class LLSocket
60{
61public:
62 /**
63 * @brief Reference counted shared pointers to sockets.
64 */
65 typedef boost::shared_ptr<LLSocket> ptr_t;
66
67 /**
68 * @brief Type of socket to create.
69 */
70 enum EType
71 {
72 STREAM_TCP,
73 DATAGRAM_UDP,
74 };
75
76 /**
77 * @brief Anonymous enumeration to help identify ports
78 */
79 enum
80 {
81 PORT_INVALID = (U16)-1,
82 PORT_EPHEMERAL = 0,
83 };
84
85 /**
86 * @brief Create a socket.
87 *
88 * This is the call you would use if you intend to create a listen
89 * socket. If you intend the socket to be known to external
90 * clients without prior port notification, do not use
91 * PORT_EPHEMERAL.
92 * @param pool The apr pool to use. A child pool will be created
93 * and associated with the socket.
94 * @param type The type of socket to create
95 * @param port The port for the socket
96 * @return A valid socket shared pointer if the call worked.
97 */
98 static ptr_t create(
99 apr_pool_t* pool,
100 EType type,
101 U16 port = PORT_EPHEMERAL);
102
103 /**
104 * @brief Create a LLSocket when you already have an apr socket.
105 *
106 * This method assumes an ephemeral port. This is typically used
107 * by calls which spawn a socket such as a call to
108 * <code>accept()</code> as in the server socket. This call should
109 * not fail if you have a valid apr socket.
110 * Because of the nature of how accept() works, you are expected
111 * to create a new pool for the socket, use that pool for the
112 * accept, and pass it in here where it will be bound with the
113 * socket and destroyed at the same time.
114 * @param socket The apr socket to use
115 * @param pool The pool used to create the socket. *NOTE: The pool
116 * passed in will be DESTROYED.
117 * @return A valid socket shared pointer if the call worked.
118 */
119 static ptr_t create(apr_socket_t* socket, apr_pool_t* pool);
120
121 /**
122 * @brief Perform a blocking connect to a host. Do not use in production.
123 *
124 * @param host The host to connect this socket to.
125 * @return Returns true if the connect was successful.
126 */
127 bool blockingConnect(const LLHost& host);
128
129 /**
130 * @brief Get the type of socket
131 */
132 //EType getType() const { return mType; }
133
134 /**
135 * @brief Get the port.
136 *
137 * This will return PORT_EPHEMERAL if bind was never called.
138 * @return Returns the port associated with this socket.
139 */
140 U16 getPort() const { return mPort; }
141
142 /**
143 * @brief Get the apr socket implementation.
144 *
145 * @return Returns the raw apr socket.
146 */
147 apr_socket_t* getSocket() const { return mSocket; }
148
149protected:
150 /**
151 * @brief Protected constructor since should only make sockets
152 * with one of the two <code>create()</code> calls.
153 */
154 LLSocket(apr_socket_t* socket, apr_pool_t* pool);
155
156 /**
157 * @brief Set default socket options.
158 */
159 void setOptions();
160
161public:
162 /**
163 * @brief Do not call this directly.
164 */
165 ~LLSocket();
166
167protected:
168 // The apr socket.
169 apr_socket_t* mSocket;
170
171 // our memory pool
172 apr_pool_t* mPool;
173
174 // The port if we know it.
175 U16 mPort;
176
177 //EType mType;
178};
179
180/**
181 * @class LLIOSocketReader
182 * @brief An LLIOPipe implementation which reads from a socket.
183 * @see LLIOPipe
184 *
185 * An instance of a socket reader wraps around an LLSocket and
186 * performs non-blocking reads and passes it to the next pipe in the
187 * chain.
188 */
189class LLIOSocketReader : public LLIOPipe
190{
191public:
192 LLIOSocketReader(LLSocket::ptr_t socket);
193 ~LLIOSocketReader();
194
195protected:
196 /* @name LLIOPipe virtual implementations
197 */
198 //@{
199 /**
200 * @brief Process the data coming in the socket.
201 *
202 * Since the socket and next pipe must exist for process to make
203 * any sense, this method will return STATUS_PRECONDITION_NOT_MET
204 * unless if they are not known.
205 * If a STATUS_STOP returned by the next link in the chain, this
206 * reader will turn of the socket polling.
207 * @param buffer Pointer to a buffer which needs processing. Probably NULL.
208 * @param bytes Number of bytes to in buffer to process. Probably 0.
209 * @param eos True if this function is the last. Almost always false.
210 * @param read Number of bytes actually processed.
211 * @param pump The pump which is calling process. May be NULL.
212 * @param context A data structure to pass structured data
213 * @return STATUS_OK unless the preconditions are not met.
214 */
215 virtual EStatus process_impl(
216 const LLChannelDescriptors& channels,
217 buffer_ptr_t& buffer,
218 bool& eos,
219 LLSD& context,
220 LLPumpIO* pump);
221 //@}
222
223protected:
224 LLSocket::ptr_t mSource;
225 std::vector<U8> mBuffer;
226 bool mInitialized;
227};
228
229/**
230 * @class LLIOSocketWriter
231 * @brief An LLIOPipe implementation which writes to a socket
232 * @see LLIOPipe
233 *
234 * An instance of a socket writer wraps around an LLSocket and
235 * performs non-blocking writes of the data passed in.
236 */
237class LLIOSocketWriter : public LLIOPipe
238{
239public:
240 LLIOSocketWriter(LLSocket::ptr_t socket);
241 ~LLIOSocketWriter();
242
243protected:
244 /* @name LLIOPipe virtual implementations
245 */
246 //@{
247 /**
248 * @brief Write the data in buffer to the socket.
249 *
250 * Since the socket pipe must exist for process to make any sense,
251 * this method will return STATUS_PRECONDITION_NOT_MET if it is
252 * not known.
253 * @param buffer Pointer to a buffer which needs processing.
254 * @param bytes Number of bytes to in buffer to process.
255 * @param eos True if this function is the last.
256 * @param read Number of bytes actually processed.
257 * @param pump The pump which is calling process. May be NULL.
258 * @param context A data structure to pass structured data
259 * @return A return code for the write.
260 */
261 virtual EStatus process_impl(
262 const LLChannelDescriptors& channels,
263 buffer_ptr_t& buffer,
264 bool& eos,
265 LLSD& context,
266 LLPumpIO* pump);
267 //@}
268
269protected:
270 LLSocket::ptr_t mDestination;
271 U8* mLastWritten;
272 bool mInitialized;
273};
274
275/**
276 * @class LLIOServerSocket
277 * @brief An IOPipe implementation which listens and spawns connected
278 * sockets.
279 * @see LLIOPipe, LLChainIOFactory
280 *
281 * Each server socket instance coordinates with a pump to ensure it
282 * only processes waiting connections. It uses the provided socket,
283 * and assumes it is correctly initialized. When the connection is
284 * established, the server will call the chain factory to build a
285 * chain, and attach a socket reader and the front and a socket writer
286 * at the end. It is up to the chain factory to create something which
287 * correctly handles the established connection using the reader as a
288 * source, and the writer as the final sink.
289 * The newly added chain timeout is in DEFAULT_CHAIN_EXPIRY_SECS unless
290 * adjusted with a call to setResponseTimeout().
291 */
292class LLIOServerSocket : public LLIOPipe
293{
294public:
295 typedef LLSocket::ptr_t socket_t;
296 typedef boost::shared_ptr<LLChainIOFactory> factory_t;
297 LLIOServerSocket(apr_pool_t* pool, socket_t listener, factory_t reactor);
298 virtual ~LLIOServerSocket();
299
300 /**
301 * @brief Set the timeout for the generated chains.
302 *
303 * This value is passed directly to the LLPumpIO::addChain()
304 * method. The default on construction is set to
305 * DEFAULT_CHAIN_EXPIRY_SECS which is a reasonable value for most
306 * applications based on this library. Avoid passing in
307 * NEVER_CHAIN_EXPIRY_SECS unless you have another method of
308 * harvesting chains.
309 * @param timeout_secs The seconds before timeout for the response chain.
310 */
311 void setResponseTimeout(F32 timeout_secs);
312
313 /* @name LLIOPipe virtual implementations
314 */
315 //@{
316protected:
317 /**
318 * @brief Process the data in buffer
319 */
320 virtual EStatus process_impl(
321 const LLChannelDescriptors& channels,
322 buffer_ptr_t& buffer,
323 bool& eos,
324 LLSD& context,
325 LLPumpIO* pump);
326 //@}
327
328protected:
329 apr_pool_t* mPool;
330 socket_t mListenSocket;
331 factory_t mReactor;
332 bool mInitialized;
333 F32 mResponseTimeout;
334};
335
336#if 0
337/**
338 * @class LLIODataSocket
339 * @brief BRIEF_DESC
340 *
341 * THOROUGH_DESCRIPTION
342 */
343class LLIODataSocket : public LLIOSocket
344{
345public:
346 /**
347 * @brief Construct a datagram socket.
348 *
349 * If you pass in LLIOSocket::PORT_EPHEMERAL as the suggested
350 * port, The socket will not be in a 'listen' mode, but can still
351 * read data sent back to it's port. When suggested_port is not
352 * ephemeral or invalid and bind fails, the port discovery
353 * algorithm will search through a limited set of ports to
354 * try to find an open port. If that process fails, getPort() will
355 * return LLIOSocket::PORT_INVALID
356 * @param suggested_port The port you would like to bind. Use
357 * LLIOSocket::PORT_EPHEMERAL for an unspecified port.
358 * @param start_discovery_port The start range for
359 * @param pool The pool to use for allocation.
360 */
361 LLIODataSocket(
362 U16 suggested_port,
363 U16 start_discovery_port,
364 apr_pool_t* pool);
365 virtual ~LLIODataSocket();
366
367protected:
368
369private:
370 apr_socket_t* mSocket;
371};
372#endif
373
374#endif // LL_LLIOSOCKET_H