diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/llmessage/lliosocket.h | |
parent | README.txt (diff) | |
download | meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2 meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz |
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/llmessage/lliosocket.h')
-rw-r--r-- | linden/indra/llmessage/lliosocket.h | 374 |
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 | |||
46 | class 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 | */ | ||
59 | class LLSocket | ||
60 | { | ||
61 | public: | ||
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 | |||
149 | protected: | ||
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 | |||
161 | public: | ||
162 | /** | ||
163 | * @brief Do not call this directly. | ||
164 | */ | ||
165 | ~LLSocket(); | ||
166 | |||
167 | protected: | ||
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 | */ | ||
189 | class LLIOSocketReader : public LLIOPipe | ||
190 | { | ||
191 | public: | ||
192 | LLIOSocketReader(LLSocket::ptr_t socket); | ||
193 | ~LLIOSocketReader(); | ||
194 | |||
195 | protected: | ||
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 | |||
223 | protected: | ||
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 | */ | ||
237 | class LLIOSocketWriter : public LLIOPipe | ||
238 | { | ||
239 | public: | ||
240 | LLIOSocketWriter(LLSocket::ptr_t socket); | ||
241 | ~LLIOSocketWriter(); | ||
242 | |||
243 | protected: | ||
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 | |||
269 | protected: | ||
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 | */ | ||
292 | class LLIOServerSocket : public LLIOPipe | ||
293 | { | ||
294 | public: | ||
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 | //@{ | ||
316 | protected: | ||
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 | |||
328 | protected: | ||
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 | */ | ||
343 | class LLIODataSocket : public LLIOSocket | ||
344 | { | ||
345 | public: | ||
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 | |||
367 | protected: | ||
368 | |||
369 | private: | ||
370 | apr_socket_t* mSocket; | ||
371 | }; | ||
372 | #endif | ||
373 | |||
374 | #endif // LL_LLIOSOCKET_H | ||