PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/ClassMaster2014/barahon/Transcend_0.3_UnixSource/minorGems/network/linux/SocketServerLinux.cpp

https://gitlab.com/garheade/linux_camp
C++ | 243 lines | 97 code | 72 blank | 74 comment | 22 complexity | 8a33deca09da371aa3400199bed15102 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. #include "minorGems/network/SocketServer.h"
  49. #include <string.h>
  50. #include <sys/types.h>
  51. #include <sys/time.h>
  52. #include <unistd.h>
  53. #include <sys/socket.h>
  54. #include <netinet/in.h>
  55. #include <stdlib.h>
  56. // BSD does not define socklen_t
  57. #ifdef BSD
  58. typedef int socklen_t;
  59. #else
  60. // poll not available on BSD
  61. #include <sys/poll.h>
  62. #endif
  63. /**
  64. * BSD Compilation note:
  65. *
  66. * Use g++ option -DBSD to define the BSD preprocessor variable.
  67. */
  68. SocketServer::SocketServer( int inPort, int inMaxQueuedConnections ) {
  69. int error = 0;
  70. if( !Socket::isFrameworkInitialized() ) {
  71. // try to init the framework
  72. int error = Socket::initSocketFramework();
  73. if( error == -1 ) {
  74. printf( "initializing network socket framework failed\n" );
  75. exit( 1 );
  76. }
  77. }
  78. // create the socket
  79. int sockID = socket( AF_INET, SOCK_STREAM, 0 );
  80. if( sockID == -1 ) {
  81. printf( "Failed to construct a socket\n" );
  82. exit( 1 );
  83. }
  84. // store socket id in native object pointer
  85. int *idStorage = new int[1];
  86. idStorage[0] = sockID;
  87. mNativeObjectPointer = (void *)idStorage;
  88. // this setsockopt code partially copied from gnut
  89. // set socket option to enable reusing addresses so that the socket is
  90. // unbound immediately when the server is shut down
  91. // (otherwise, rebinding to the same port will fail for a while
  92. // after the server is shut down)
  93. int reuseAddressValue = 1;
  94. error = setsockopt( sockID,
  95. SOL_SOCKET, // socket-level option
  96. SO_REUSEADDR, // reuse address option
  97. &reuseAddressValue, // value to set for this option
  98. sizeof( reuseAddressValue) ); // size of the value
  99. if( error == -1 ) {
  100. printf( "Failed to set socket options\n" );
  101. exit( 1 );
  102. }
  103. // bind socket to the port
  104. struct sockaddr_in address;
  105. address.sin_family = AF_INET;
  106. address.sin_port = htons( inPort );
  107. address.sin_addr.s_addr = INADDR_ANY;
  108. error = bind( sockID, (struct sockaddr *) &address, sizeof( address ) );
  109. if( error == -1 ) {
  110. printf( "Bad socket bind, port %d\n", inPort );
  111. exit( 1 );
  112. }
  113. // start listening for connections
  114. error = listen( sockID, inMaxQueuedConnections );
  115. if( error == -1 ) {
  116. printf( "Bad socket listen\n" );
  117. exit(1);
  118. }
  119. }
  120. SocketServer::~SocketServer() {
  121. int *socketIDptr = (int *)( mNativeObjectPointer );
  122. int socketID = socketIDptr[0];
  123. close( socketID );
  124. delete [] socketIDptr;
  125. }
  126. Socket *SocketServer::acceptConnection( long inTimeoutInMilliseconds,
  127. char *outTimedOut ) {
  128. // printf( "Waiting for a connection.\n" );
  129. // extract socket id from native object pointer
  130. int *socketIDptr = (int *)( mNativeObjectPointer );
  131. int socketID = socketIDptr[0];
  132. if( outTimedOut != NULL ) {
  133. *outTimedOut = false;
  134. }
  135. if( inTimeoutInMilliseconds != -1 ) {
  136. // if we have a timeout specified, select before accepting
  137. // this found in the Linux man page for select,
  138. // but idea (which originally used poll) was found
  139. // in the Unix Socket FAQ
  140. fd_set rfds;
  141. struct timeval tv;
  142. int retval;
  143. // insert our socket descriptor into this set
  144. FD_ZERO( &rfds );
  145. FD_SET( socketID, &rfds );
  146. // convert our timeout into the structure's format
  147. tv.tv_sec = inTimeoutInMilliseconds / 1000;
  148. tv.tv_usec = ( inTimeoutInMilliseconds % 1000 ) * 1000 ;
  149. retval = select( socketID + 1, &rfds, NULL, NULL, &tv );
  150. if( retval == 0 ) {
  151. // timeout
  152. if( outTimedOut != NULL ) {
  153. *outTimedOut = true;
  154. }
  155. return NULL;
  156. }
  157. }
  158. int acceptedID = accept( socketID, NULL, NULL );
  159. if( acceptedID == -1 ) {
  160. printf( "Failed to accept a network connection.\n" );
  161. return NULL;
  162. }
  163. else {
  164. Socket *acceptedSocket = new Socket();
  165. int *idStorage = new int[1];
  166. idStorage[0] = acceptedID;
  167. acceptedSocket->mNativeObjectPointer = (void *)idStorage;
  168. //printf( "Connection received.\n" );
  169. return acceptedSocket;
  170. }
  171. }