PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/ClassMaster2014/barahon/Cultivation_9_UnixSource/minorGems/network/linux/SocketServerLinux.cpp

https://gitlab.com/garheade/linux_camp
C++ | 254 lines | 104 code | 73 blank | 77 comment | 22 complexity | e7c5feeeb1f0f3ce7d086d210aa8d9f3 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-15 Jason Rohrer
  8. * Commented out redundant status messages that should be handled at a
  9. * higher level.
  10. *
  11. * 2001-January-28 Jason Rohrer
  12. * Changed to comply with new initSocketFramework Socket interface.
  13. *
  14. * 2001-January-29 Jason Rohrer
  15. * Fixed an endian bug with the port number.
  16. *
  17. * 2001-May-12 Jason Rohrer
  18. * Added a port number to the "bad socket bind" error message.
  19. *
  20. * 2001-November-13 Jason Rohrer
  21. * Added a missing include.
  22. *
  23. * 2001-December-12 Jason Rohrer
  24. * Changed some type usage and the include order to make BSD compatible.
  25. * Added a BSD definition test to make socklen_t type compatible
  26. * on both BSD and Linux.
  27. *
  28. * 2002-March-27 Jason Rohrer
  29. * Added a timeout to accept.
  30. *
  31. * 2002-March-29 Jason Rohrer
  32. * Fixed a bug in return value when accept fails.
  33. *
  34. * 2002-April-11 Jason Rohrer
  35. * Changed to use select instead of poll to make it more portable.
  36. * Fixed a bug in the timeout implementation.
  37. *
  38. * 2002-April-12 Jason Rohrer
  39. * Changed to use poll on Linux and select on BSD,
  40. * since select does not seem to work on LinuxX86.
  41. * Fixed X86 accept/select bug by getting rid of union
  42. * and some unused parameters (it seems that stack space was a problem).
  43. *
  44. * 2004-February-23 Jason Rohrer
  45. * Added socket option to clear up lingering bound ports after shutdown.
  46. * Changed to close server socket instead of using shutdown.
  47. *
  48. * 2010-January-26 Jason Rohrer
  49. * Fixed socklen_t on later versions of MacOSX.
  50. */
  51. #include "minorGems/network/SocketServer.h"
  52. #include <string.h>
  53. #include <sys/types.h>
  54. #include <sys/time.h>
  55. #include <unistd.h>
  56. #include <sys/socket.h>
  57. #include <netinet/in.h>
  58. #include <stdlib.h>
  59. // BSD does not define socklen_t
  60. #ifdef BSD
  61. #ifndef IPHONE
  62. #ifndef __OpenBSD__
  63. #ifndef _SOCKLEN_T // later versions of MacOS define it and mark it
  64. typedef int socklen_t;
  65. #endif
  66. #endif
  67. #endif
  68. #endif
  69. #ifndef BSD
  70. // poll not available on BSD
  71. #include <sys/poll.h>
  72. #endif
  73. /**
  74. * BSD Compilation note:
  75. *
  76. * Use g++ option -DBSD to define the BSD preprocessor variable.
  77. */
  78. SocketServer::SocketServer( int inPort, int inMaxQueuedConnections ) {
  79. int error = 0;
  80. if( !Socket::isFrameworkInitialized() ) {
  81. // try to init the framework
  82. int error = Socket::initSocketFramework();
  83. if( error == -1 ) {
  84. printf( "initializing network socket framework failed\n" );
  85. exit( 1 );
  86. }
  87. }
  88. // create the socket
  89. int sockID = socket( AF_INET, SOCK_STREAM, 0 );
  90. if( sockID == -1 ) {
  91. printf( "Failed to construct a socket\n" );
  92. exit( 1 );
  93. }
  94. // store socket id in native object pointer
  95. int *idStorage = new int[1];
  96. idStorage[0] = sockID;
  97. mNativeObjectPointer = (void *)idStorage;
  98. // this setsockopt code partially copied from gnut
  99. // set socket option to enable reusing addresses so that the socket is
  100. // unbound immediately when the server is shut down
  101. // (otherwise, rebinding to the same port will fail for a while
  102. // after the server is shut down)
  103. int reuseAddressValue = 1;
  104. error = setsockopt( sockID,
  105. SOL_SOCKET, // socket-level option
  106. SO_REUSEADDR, // reuse address option
  107. &reuseAddressValue, // value to set for this option
  108. sizeof( reuseAddressValue) ); // size of the value
  109. if( error == -1 ) {
  110. printf( "Failed to set socket options\n" );
  111. exit( 1 );
  112. }
  113. // bind socket to the port
  114. struct sockaddr_in address;
  115. address.sin_family = AF_INET;
  116. address.sin_port = htons( inPort );
  117. address.sin_addr.s_addr = INADDR_ANY;
  118. error = bind( sockID, (struct sockaddr *) &address, sizeof( address ) );
  119. if( error == -1 ) {
  120. printf( "Bad socket bind, port %d\n", inPort );
  121. exit( 1 );
  122. }
  123. // start listening for connections
  124. error = listen( sockID, inMaxQueuedConnections );
  125. if( error == -1 ) {
  126. printf( "Bad socket listen\n" );
  127. exit(1);
  128. }
  129. }
  130. SocketServer::~SocketServer() {
  131. int *socketIDptr = (int *)( mNativeObjectPointer );
  132. int socketID = socketIDptr[0];
  133. close( socketID );
  134. delete [] socketIDptr;
  135. }
  136. Socket *SocketServer::acceptConnection( long inTimeoutInMilliseconds,
  137. char *outTimedOut ) {
  138. // printf( "Waiting for a connection.\n" );
  139. // extract socket id from native object pointer
  140. int *socketIDptr = (int *)( mNativeObjectPointer );
  141. int socketID = socketIDptr[0];
  142. if( outTimedOut != NULL ) {
  143. *outTimedOut = false;
  144. }
  145. if( inTimeoutInMilliseconds != -1 ) {
  146. // if we have a timeout specified, select before accepting
  147. // this found in the Linux man page for select,
  148. // but idea (which originally used poll) was found
  149. // in the Unix Socket FAQ
  150. fd_set rfds;
  151. struct timeval tv;
  152. int retval;
  153. // insert our socket descriptor into this set
  154. FD_ZERO( &rfds );
  155. FD_SET( socketID, &rfds );
  156. // convert our timeout into the structure's format
  157. tv.tv_sec = inTimeoutInMilliseconds / 1000;
  158. tv.tv_usec = ( inTimeoutInMilliseconds % 1000 ) * 1000 ;
  159. retval = select( socketID + 1, &rfds, NULL, NULL, &tv );
  160. if( retval == 0 ) {
  161. // timeout
  162. if( outTimedOut != NULL ) {
  163. *outTimedOut = true;
  164. }
  165. return NULL;
  166. }
  167. }
  168. int acceptedID = accept( socketID, NULL, NULL );
  169. if( acceptedID == -1 ) {
  170. printf( "Failed to accept a network connection.\n" );
  171. return NULL;
  172. }
  173. else {
  174. Socket *acceptedSocket = new Socket();
  175. int *idStorage = new int[1];
  176. idStorage[0] = acceptedID;
  177. acceptedSocket->mNativeObjectPointer = (void *)idStorage;
  178. //printf( "Connection received.\n" );
  179. return acceptedSocket;
  180. }
  181. }