#include #include #include #include #include #include #include #include #include #include #include #include #include #include "serversocket.h" #include "exceptions.h" Bu::ServerSocket::ServerSocket( int nPort, int nPoolSize ) : nPort( nPort ) { /* Create the socket and set it up to accept connections. */ struct sockaddr_in name; /* Give the socket a name. */ name.sin_family = AF_INET; name.sin_port = htons( nPort ); // I think this specifies who we will accept connections from, // a good thing to make configurable later on name.sin_addr.s_addr = htonl( INADDR_ANY ); startServer( name, nPoolSize ); } Bu::ServerSocket::ServerSocket(const FString &sAddr,int nPort, int nPoolSize) : nPort( nPort ) { /* Create the socket and set it up to accept connections. */ struct sockaddr_in name; /* Give the socket a name. */ name.sin_family = AF_INET; name.sin_port = htons( nPort ); inet_aton( sAddr.getStr(), &name.sin_addr ); startServer( name, nPoolSize ); } Bu::ServerSocket::~ServerSocket() { } void Bu::ServerSocket::startServer( struct sockaddr_in &name, int nPoolSize ) { /* Create the socket. */ nServer = socket( PF_INET, SOCK_STREAM, 0 ); if( nServer < 0 ) { throw Bu::SocketException("Couldn't create a listen socket."); } int opt = 1; setsockopt( nServer, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof( opt ) ); if( bind( nServer, (struct sockaddr *) &name, sizeof(name) ) < 0 ) { throw Bu::SocketException("Couldn't bind to the listen socket."); } if( listen( nServer, nPoolSize ) < 0 ) { throw Bu::SocketException( "Couldn't begin listening to the server socket." ); } FD_ZERO( &fdActive ); /* Initialize the set of active sockets. */ FD_SET( nServer, &fdActive ); } int Bu::ServerSocket::accept( int nTimeoutSec, int nTimeoutUSec ) { fd_set fdRead = fdActive; struct timeval xT; xT.tv_sec = nTimeoutSec; xT.tv_usec = nTimeoutUSec; if( TEMP_FAILURE_RETRY(select( nServer+1, &fdRead, NULL, NULL, &xT )) < 0 ) { throw SocketException( "Error scanning for new connections: %s", strerror( errno ) ); } if( FD_ISSET( nServer, &fdRead ) ) { struct sockaddr_in clientname; size_t size; int nClient; size = sizeof( clientname ); #ifdef __CYGWIN__ nClient = ::accept( nServer, (struct sockaddr *)&clientname, (int *)&size ); #else nClient = ::accept( nServer, (struct sockaddr *)&clientname, &size ); #endif if( nClient < 0 ) { throw SocketException( "Error accepting a new connection: %s", strerror( errno ) ); } char tmpa[20]; inet_ntop( AF_INET, (void *)&clientname.sin_addr, tmpa, 20 ); //"New connection from host %s, port %hd.", // tmpa, ntohs (clientname.sin_port) ); { int flags; flags = fcntl( nClient, F_GETFL, 0 ); flags |= O_NONBLOCK; if( fcntl( nClient, F_SETFL, flags ) < 0) { throw SocketException( "Error setting option on client socket: %s", strerror( errno ) ); } } return nClient; } return -1; }