PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/ClassMaster2014/barahon/Cultivation_9_UnixSource/minorGems/network/Socket.h

https://gitlab.com/garheade/linux_camp
C Header | 329 lines | 60 code | 80 blank | 189 comment | 3 complexity | 839f5add26f7bf3a3a9f944a2d889aa4 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /*
  2. * Modification History
  3. *
  4. * 2001-January-9 Jason Rohrer
  5. * Created.
  6. *
  7. * 2001-January-28 Jason Rohrer
  8. * Added a static framework init function.
  9. *
  10. * 2001-November-13 Jason Rohrer
  11. * Changed timeout parameter to signed, since -1 is a possible argument.
  12. *
  13. * 2002-March-29 Jason Rohrer
  14. * Added Fortify inclusion.
  15. *
  16. * 2002-August-2 Jason Rohrer
  17. * Added functon for getting remote host address.
  18. *
  19. * 2003-February-3 Jason Rohrer
  20. * Added a function for getting the local host address from a socket.
  21. *
  22. * 2003-August-12 Jason Rohrer
  23. * Added more verbose comment about receive timeout parameter.
  24. * Added a function for flushing socket sends.
  25. *
  26. * 2003-November-20 Jason Rohrer
  27. * Made flush function robust against bogus receive return values.
  28. *
  29. * 2004-December13 Jason Rohrer
  30. * Added a breakConnection function.
  31. *
  32. * 2005-July-5 Jason Rohrer
  33. * Added port number when getting address of remote host.
  34. *
  35. * 2006-May-28 Jason Rohrer
  36. * Changed timeout behavior slightly to support emulation of non-blocking mode.
  37. * Added support for non-blocking sends.
  38. *
  39. * 2008-September-30 Jason Rohrer
  40. * Added support for non-blocking connect.
  41. *
  42. * 2010-January-26 Jason Rohrer
  43. * Added support for disabling Nagle algorithm.
  44. */
  45. #include "minorGems/common.h"
  46. #ifndef SOCKET_CLASS_INCLUDED
  47. #define SOCKET_CLASS_INCLUDED
  48. #include "minorGems/network/HostAddress.h"
  49. #include "minorGems/system/Time.h"
  50. #ifdef FORTIFY
  51. #include "minorGems/util/development/fortify/fortify.h"
  52. #endif
  53. /**
  54. * Network socket. Does not contain an interface for listening to connections
  55. * (see SocketServer for these interfaces) or for establishing connections
  56. * (see SocketClient for these interfaces).
  57. *
  58. * Note: Implementation for the functions defined here is provided
  59. * separately for each platform (in the mac/ linux/ and win32/
  60. * subdirectories).
  61. *
  62. * @author Jason Rohrer
  63. */
  64. class Socket {
  65. public:
  66. /**
  67. * Constructor for a socket.
  68. *
  69. * Should not be called directly. Use SocketClient or SocketServer
  70. * to obtain an outbound or inbound socket connection.
  71. */
  72. Socket();
  73. // destroying a Socket closes the connection
  74. ~Socket();
  75. /**
  76. * Initializes the socket framework. Must be called
  77. * once by program before sockets are used. Note
  78. * that SocketClient and SocketServer both should call
  79. * init automatically when they are first used.
  80. *
  81. * @return 0 on success, or -1 on failure.
  82. */
  83. static int initSocketFramework();
  84. /**
  85. * Gets whether the socket framework has been initialized.
  86. *
  87. * @return true if the framework has been initialized.
  88. */
  89. static char isFrameworkInitialized();
  90. /**
  91. * For outbound sockets that were opened in non-blocking mode:
  92. *
  93. * Get whether socket is connected yet.
  94. *
  95. * @return 1 on success, 0 on still waiting, -1 on error.
  96. */
  97. int isConnected();
  98. /**
  99. * Sends bytes through this socket.
  100. *
  101. * @param inBuffer the buffer of bytes to send.
  102. * @param inNumBytes the number of bytes to send.
  103. * @param inAllowedToBlock set to false to prevent blocking.
  104. * Defaults to true.
  105. * @param inAllowDelay set to false to disable Nagle algorithm,
  106. * where a buffer should be sent NOW without waiting for
  107. * more data accumulation.
  108. * Defaults to true.
  109. *
  110. * @return the number of bytes sent successfully,
  111. * or -1 for a socket error.
  112. * Returns -2 if not allowed to block and the operation
  113. * would block.
  114. */
  115. int send( unsigned char *inBuffer, int inNumBytes,
  116. char inAllowedToBlock = true,
  117. char inAllowDelay = true );
  118. /**
  119. * Receives bytes from this socket.
  120. *
  121. * @param inBuffer the buffer where received bytes will be put.
  122. * Must be pre-allocated memory space.
  123. * @param inNumBytes the number of bytes to read from the socket.
  124. * @param inTimeout the timeout for this receive operation in
  125. * milliseconds. Set to -1 for an infinite timeout.
  126. * -2 is returned from this call in the event of a timeout.
  127. * If timeout is set, only available data is returned (up
  128. * to, but not more than inNumBytes). The socket does not
  129. * wait for all inNumBytes to become available before returning.
  130. * Thus, a timeout return value (-2) means no data was available
  131. * before the timeout. If some data is available, we never
  132. * time out. If no timeout is set (-1 for infinite), the socket
  133. * waits for all inNumBytes to arrive before returning.
  134. * Thus, setting a timeout of 0 effectively puts the socket
  135. * into non-blocking mode.
  136. *
  137. * @return the number of bytes read successfully,
  138. * or -1, -2 for a socket error or timeout, respectively.
  139. */
  140. int receive( unsigned char *inBuffer, int inNumBytes,
  141. long inTimeout );
  142. /**
  143. * Flushes sent data through the socket.
  144. *
  145. * Intended to be called before deleting the socket to ensure
  146. * that data goes through. The mechanism used by this function
  147. * does not guarantee that data goes through, but it works
  148. * better than simply closing the socket on many platforms.
  149. *
  150. * The method used by this call works best if the remote
  151. * host closes the connection. For example, if we send the
  152. * remote host a "connection closing" indicator, then
  153. * call writeFlushBeforeClose, and the remote host closes
  154. * the connection upon receiving the indicator, all of our
  155. * sent data will be received by the remote host after
  156. * writeFlushBeforeClose returns (assuming that the maximum
  157. * time is long enough for the remote host to actually close
  158. * the connection).
  159. *
  160. * Good maximum times should be in the several-second range,
  161. * though the Apache system uses 30 seconds. For slow connections,
  162. * this might be necessary.
  163. *
  164. * This call will cause any received data to be discarded.
  165. *
  166. * This call DOES NOT close the socket. The socket must be deleted
  167. * as usual after this call returns.
  168. *
  169. * @param inMaxTimeInMilliseconds the maximum time to wait
  170. * in milliseconds. This call may block slightly longer than
  171. * this if the remote host is still sending data.
  172. */
  173. void sendFlushBeforeClose( int inMaxTimeInMilliseconds );
  174. /**
  175. * Forces this socket's connection to break, causing any blocked
  176. * send or receive operations to fail.
  177. *
  178. * Note that this operation is inherently not thread-safe, so
  179. * some external mechanism must be used to ensure that the socket
  180. * is not destroyed by another thread before breakConnection is called.
  181. * The SocketManager class is one such external mechanism.
  182. */
  183. void breakConnection();
  184. /**
  185. * Gets the host connected to the other end of this socket.
  186. *
  187. * @return the address of the remote host, or NULL if obtaining
  188. * the address fails. The port of the returned address
  189. * will always be set to the port that the host is connecting from.
  190. * Must be destroyed by caller if non-NULL.
  191. */
  192. HostAddress *getRemoteHostAddress();
  193. /**
  194. * Gets the local address attached to this socket.
  195. *
  196. * Getting the local address from a socket is more
  197. * accurate than non-connected methods (for example, the methods
  198. * used in HostAddress.h implementations.
  199. *
  200. * @return the address of the local host, or NULL if obtaining
  201. * the address fails. The port of the returned address
  202. * will always be set to 0.
  203. * Must be destroyed by caller if non-NULL.
  204. */
  205. HostAddress *getLocalHostAddress();
  206. /**
  207. * Used by platform-specific implementations.
  208. */
  209. void *mNativeObjectPointer;
  210. // called by socket client to set connected status
  211. void setConnected( char inConnected ) {
  212. mConnected = inConnected;
  213. }
  214. private:
  215. static char sInitialized;
  216. char mConnected;
  217. char mIsConnectionBroken;
  218. // toggle Nagle algorithm (inValue=1 turns it off)
  219. void setNoDelay( int inValue );
  220. };
  221. inline Socket::Socket()
  222. : mConnected( true ), mIsConnectionBroken( false ) {
  223. }
  224. inline char Socket::isFrameworkInitialized() {
  225. return sInitialized;
  226. }
  227. inline void Socket::sendFlushBeforeClose( int inMaxTimeInMilliseconds ) {
  228. unsigned char *tempBuffer = new unsigned char[1];
  229. int numRead = -2;
  230. int timeout = 1000;
  231. if( timeout > inMaxTimeInMilliseconds ) {
  232. timeout = inMaxTimeInMilliseconds;
  233. }
  234. long totalTimeout = 0;
  235. unsigned long startSec;
  236. unsigned long startMsec;
  237. Time::getCurrentTime( &startSec, &startMsec );
  238. // keep reading data from socket until we get an error
  239. // or wait too long (pass our max timeout)
  240. while( numRead != -1 && totalTimeout < inMaxTimeInMilliseconds ) {
  241. numRead =
  242. this->receive( tempBuffer, 1, timeout );
  243. // track total time whether the receive timed out or not
  244. totalTimeout =
  245. (long)( Time::getMillisecondsSince( startSec, startMsec ) );
  246. }
  247. delete [] tempBuffer;
  248. }
  249. #endif