PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llmessage/lliosocket.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 380 lines | 111 code | 35 blank | 234 comment | 0 complexity | 56b56b8e9187540d3f8031034e116d64 MD5 | raw file
Possible License(s): LGPL-2.1
  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. * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  8. * Second Life Viewer Source Code
  9. * Copyright (C) 2010, Linden Research, Inc.
  10. *
  11. * This library is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU Lesser General Public
  13. * License as published by the Free Software Foundation;
  14. * version 2.1 of the License only.
  15. *
  16. * This library is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  19. * Lesser General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU Lesser General Public
  22. * License along with this library; if not, write to the Free Software
  23. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  24. *
  25. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  26. * $/LicenseInfo$
  27. */
  28. #ifndef LL_LLIOSOCKET_H
  29. #define LL_LLIOSOCKET_H
  30. /**
  31. * The socket interface provided here is a simple wraper around apr
  32. * sockets, with a pipe source and sink to read and write off of the
  33. * socket. Every socket only performs non-blocking operations except
  34. * the server socket which only performs blocking operations when an
  35. * OS poll indicates it will not block.
  36. */
  37. #include "lliopipe.h"
  38. #include "apr_pools.h"
  39. #include "apr_network_io.h"
  40. #include "llchainio.h"
  41. class LLHost;
  42. /**
  43. * @class LLSocket
  44. * @brief Implementation of a wrapper around a socket.
  45. *
  46. * An instance of this class represents a single socket over it's
  47. * entire life - from uninitialized, to connected, to a listening
  48. * socket depending on it's purpose. This class simplifies our access
  49. * into the socket interface by only providing stream/tcp and
  50. * datagram/udp sockets - the only types we are interested in, since
  51. * those are the only properly supported by all of our platforms.
  52. */
  53. class LLSocket
  54. {
  55. public:
  56. /**
  57. * @brief Reference counted shared pointers to sockets.
  58. */
  59. typedef boost::shared_ptr<LLSocket> ptr_t;
  60. /**
  61. * @brief Type of socket to create.
  62. */
  63. enum EType
  64. {
  65. STREAM_TCP,
  66. DATAGRAM_UDP,
  67. };
  68. /**
  69. * @brief Anonymous enumeration to help identify ports
  70. */
  71. enum
  72. {
  73. PORT_INVALID = (U16)-1,
  74. PORT_EPHEMERAL = 0,
  75. };
  76. /**
  77. * @brief Create a socket.
  78. *
  79. * This is the call you would use if you intend to create a listen
  80. * socket. If you intend the socket to be known to external
  81. * clients without prior port notification, do not use
  82. * PORT_EPHEMERAL.
  83. * @param pool The apr pool to use. A child pool will be created
  84. * and associated with the socket.
  85. * @param type The type of socket to create
  86. * @param port The port for the socket
  87. * @return A valid socket shared pointer if the call worked.
  88. */
  89. static ptr_t create(
  90. apr_pool_t* pool,
  91. EType type,
  92. U16 port = PORT_EPHEMERAL);
  93. /**
  94. * @brief Create a LLSocket when you already have an apr socket.
  95. *
  96. * This method assumes an ephemeral port. This is typically used
  97. * by calls which spawn a socket such as a call to
  98. * <code>accept()</code> as in the server socket. This call should
  99. * not fail if you have a valid apr socket.
  100. * Because of the nature of how accept() works, you are expected
  101. * to create a new pool for the socket, use that pool for the
  102. * accept, and pass it in here where it will be bound with the
  103. * socket and destroyed at the same time.
  104. * @param socket The apr socket to use
  105. * @param pool The pool used to create the socket. *NOTE: The pool
  106. * passed in will be DESTROYED.
  107. * @return A valid socket shared pointer if the call worked.
  108. */
  109. static ptr_t create(apr_socket_t* socket, apr_pool_t* pool);
  110. /**
  111. * @brief Perform a blocking connect to a host. Do not use in production.
  112. *
  113. * @param host The host to connect this socket to.
  114. * @return Returns true if the connect was successful.
  115. */
  116. bool blockingConnect(const LLHost& host);
  117. /**
  118. * @brief Get the type of socket
  119. */
  120. //EType getType() const { return mType; }
  121. /**
  122. * @brief Get the port.
  123. *
  124. * This will return PORT_EPHEMERAL if bind was never called.
  125. * @return Returns the port associated with this socket.
  126. */
  127. U16 getPort() const { return mPort; }
  128. /**
  129. * @brief Get the apr socket implementation.
  130. *
  131. * @return Returns the raw apr socket.
  132. */
  133. apr_socket_t* getSocket() const { return mSocket; }
  134. /**
  135. * @brief Set default socket options, with SO_NONBLOCK = 0 and a timeout in us.
  136. * @param timeout Number of microseconds to wait on this socket. Any
  137. * negative number means block-forever. TIMEOUT OF 0 IS NON-PORTABLE.
  138. */
  139. void setBlocking(S32 timeout);
  140. /**
  141. * @brief Set default socket options, with SO_NONBLOCK = 1 and timeout = 0.
  142. */
  143. void setNonBlocking();
  144. protected:
  145. /**
  146. * @brief Protected constructor since should only make sockets
  147. * with one of the two <code>create()</code> calls.
  148. */
  149. LLSocket(apr_socket_t* socket, apr_pool_t* pool);
  150. public:
  151. /**
  152. * @brief Do not call this directly.
  153. */
  154. ~LLSocket();
  155. protected:
  156. // The apr socket.
  157. apr_socket_t* mSocket;
  158. // our memory pool
  159. apr_pool_t* mPool;
  160. // The port if we know it.
  161. U16 mPort;
  162. //EType mType;
  163. };
  164. /**
  165. * @class LLIOSocketReader
  166. * @brief An LLIOPipe implementation which reads from a socket.
  167. * @see LLIOPipe
  168. *
  169. * An instance of a socket reader wraps around an LLSocket and
  170. * performs non-blocking reads and passes it to the next pipe in the
  171. * chain.
  172. */
  173. class LLIOSocketReader : public LLIOPipe
  174. {
  175. public:
  176. LLIOSocketReader(LLSocket::ptr_t socket);
  177. ~LLIOSocketReader();
  178. protected:
  179. /* @name LLIOPipe virtual implementations
  180. */
  181. //@{
  182. /**
  183. * @brief Process the data coming in the socket.
  184. *
  185. * Since the socket and next pipe must exist for process to make
  186. * any sense, this method will return STATUS_PRECONDITION_NOT_MET
  187. * unless if they are not known.
  188. * If a STATUS_STOP returned by the next link in the chain, this
  189. * reader will turn of the socket polling.
  190. * @param buffer Pointer to a buffer which needs processing. Probably NULL.
  191. * @param bytes Number of bytes to in buffer to process. Probably 0.
  192. * @param eos True if this function is the last. Almost always false.
  193. * @param read Number of bytes actually processed.
  194. * @param pump The pump which is calling process. May be NULL.
  195. * @param context A data structure to pass structured data
  196. * @return STATUS_OK unless the preconditions are not met.
  197. */
  198. virtual EStatus process_impl(
  199. const LLChannelDescriptors& channels,
  200. buffer_ptr_t& buffer,
  201. bool& eos,
  202. LLSD& context,
  203. LLPumpIO* pump);
  204. //@}
  205. protected:
  206. LLSocket::ptr_t mSource;
  207. std::vector<U8> mBuffer;
  208. bool mInitialized;
  209. };
  210. /**
  211. * @class LLIOSocketWriter
  212. * @brief An LLIOPipe implementation which writes to a socket
  213. * @see LLIOPipe
  214. *
  215. * An instance of a socket writer wraps around an LLSocket and
  216. * performs non-blocking writes of the data passed in.
  217. */
  218. class LLIOSocketWriter : public LLIOPipe
  219. {
  220. public:
  221. LLIOSocketWriter(LLSocket::ptr_t socket);
  222. ~LLIOSocketWriter();
  223. protected:
  224. /* @name LLIOPipe virtual implementations
  225. */
  226. //@{
  227. /**
  228. * @brief Write the data in buffer to the socket.
  229. *
  230. * Since the socket pipe must exist for process to make any sense,
  231. * this method will return STATUS_PRECONDITION_NOT_MET if it is
  232. * not known.
  233. * @param buffer Pointer to a buffer which needs processing.
  234. * @param bytes Number of bytes to in buffer to process.
  235. * @param eos True if this function is the last.
  236. * @param read Number of bytes actually processed.
  237. * @param pump The pump which is calling process. May be NULL.
  238. * @param context A data structure to pass structured data
  239. * @return A return code for the write.
  240. */
  241. virtual EStatus process_impl(
  242. const LLChannelDescriptors& channels,
  243. buffer_ptr_t& buffer,
  244. bool& eos,
  245. LLSD& context,
  246. LLPumpIO* pump);
  247. //@}
  248. protected:
  249. LLSocket::ptr_t mDestination;
  250. U8* mLastWritten;
  251. bool mInitialized;
  252. };
  253. /**
  254. * @class LLIOServerSocket
  255. * @brief An IOPipe implementation which listens and spawns connected
  256. * sockets.
  257. * @see LLIOPipe, LLChainIOFactory
  258. *
  259. * Each server socket instance coordinates with a pump to ensure it
  260. * only processes waiting connections. It uses the provided socket,
  261. * and assumes it is correctly initialized. When the connection is
  262. * established, the server will call the chain factory to build a
  263. * chain, and attach a socket reader and the front and a socket writer
  264. * at the end. It is up to the chain factory to create something which
  265. * correctly handles the established connection using the reader as a
  266. * source, and the writer as the final sink.
  267. * The newly added chain timeout is in DEFAULT_CHAIN_EXPIRY_SECS unless
  268. * adjusted with a call to setResponseTimeout().
  269. */
  270. class LLIOServerSocket : public LLIOPipe
  271. {
  272. public:
  273. typedef LLSocket::ptr_t socket_t;
  274. typedef boost::shared_ptr<LLChainIOFactory> factory_t;
  275. LLIOServerSocket(apr_pool_t* pool, socket_t listener, factory_t reactor);
  276. virtual ~LLIOServerSocket();
  277. /**
  278. * @brief Set the timeout for the generated chains.
  279. *
  280. * This value is passed directly to the LLPumpIO::addChain()
  281. * method. The default on construction is set to
  282. * DEFAULT_CHAIN_EXPIRY_SECS which is a reasonable value for most
  283. * applications based on this library. Avoid passing in
  284. * NEVER_CHAIN_EXPIRY_SECS unless you have another method of
  285. * harvesting chains.
  286. * @param timeout_secs The seconds before timeout for the response chain.
  287. */
  288. void setResponseTimeout(F32 timeout_secs);
  289. /* @name LLIOPipe virtual implementations
  290. */
  291. //@{
  292. protected:
  293. /**
  294. * @brief Process the data in buffer
  295. */
  296. virtual EStatus process_impl(
  297. const LLChannelDescriptors& channels,
  298. buffer_ptr_t& buffer,
  299. bool& eos,
  300. LLSD& context,
  301. LLPumpIO* pump);
  302. //@}
  303. protected:
  304. apr_pool_t* mPool;
  305. socket_t mListenSocket;
  306. factory_t mReactor;
  307. bool mInitialized;
  308. F32 mResponseTimeout;
  309. };
  310. #if 0
  311. /**
  312. * @class LLIODataSocket
  313. * @brief BRIEF_DESC
  314. *
  315. * THOROUGH_DESCRIPTION
  316. */
  317. class LLIODataSocket : public LLIOSocket
  318. {
  319. public:
  320. /**
  321. * @brief Construct a datagram socket.
  322. *
  323. * If you pass in LLIOSocket::PORT_EPHEMERAL as the suggested
  324. * port, The socket will not be in a 'listen' mode, but can still
  325. * read data sent back to it's port. When suggested_port is not
  326. * ephemeral or invalid and bind fails, the port discovery
  327. * algorithm will search through a limited set of ports to
  328. * try to find an open port. If that process fails, getPort() will
  329. * return LLIOSocket::PORT_INVALID
  330. * @param suggested_port The port you would like to bind. Use
  331. * LLIOSocket::PORT_EPHEMERAL for an unspecified port.
  332. * @param start_discovery_port The start range for
  333. * @param pool The pool to use for allocation.
  334. */
  335. LLIODataSocket(
  336. U16 suggested_port,
  337. U16 start_discovery_port,
  338. apr_pool_t* pool);
  339. virtual ~LLIODataSocket();
  340. protected:
  341. private:
  342. apr_socket_t* mSocket;
  343. };
  344. #endif
  345. #endif // LL_LLIOSOCKET_H