/* ....[@@@..[@@@..............[@.................. MUD++ is a written from ....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and ....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++. ....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing ....[@......[@..[@@@@@..[@@@@@.................. development project. All ................................................ contributions are welcome. ....Copyright(C).1995.Melvin.Smith.............. Enjoy. ------------------------------------------------------------------------------ Melvin Smith (aka Fusion) msmith@falcon.mercer.peachnet.edu MUD++ development mailing list mudpp-list@spice.com ------------------------------------------------------------------------------ server.cc */ #include "server.h" void sig_handler( int ) { // Generate core raise( SIGSEGV ); } Server::~Server() { master->close(); } Socket * Server::getSock() { return master; } // This is for booting "into" a previous servers process // space and inheriting the open master descriptor. Skip // all the master struct creation and just assign the // descriptor to sock and clean up a few other things. // This really needs some serious error handling. Also need // to save the sock struct info in the reboot.tab file // and recreate it from that. // --Fusion int Server::boot( int oldport, int olddesc ) { signal( SIGPIPE, SIG_IGN ); signal( SIGBUS, sig_handler ); master = new Socket( "", oldport, olddesc ); printf( "SERVER: Rebooted succesfully - ready for connections.\n" ); printf( "SERVER: Port [%d]\n", master->getPort() ); topdesc = olddesc; return 0; } int Server::boot( int tport ) { signal( SIGPIPE, SIG_IGN ); signal( SIGBUS, sig_handler ); master = new Socket( tport ); if( master->error() ) { perror( "SERVER: Socket::boot()" ); exit(0); } master->reuseAddr(); master->noDelay(); if( master->listen() ) { perror( "SERVER: Socket::listen()" ); exit(0); } masterdesc = topdesc = master->getDesc(); masterport = master->getPort(); printf( "SERVER: Booted succesfully - ready for connections.\n" ); printf( "SERVER: Port [%d]\n", masterport ); return 0; } int Server::poll() { memcpy( &R_SET, &MASTER_SET, bitwidth ); memcpy( &W_SET, &MASTER_SET, bitwidth ); memcpy( &E_SET, &MASTER_SET, bitwidth ); FD_SET( masterdesc, &R_SET ); // if( select( topdesc+1, &R_SET, &W_SET, &E_SET, &null_time) == -1 ) if( select( topdesc+1, &R_SET, &W_SET, &E_SET, 0 ) == -1 ) { printf("SERVER: select() error in Poll() - exiting.\n"); exit( errno ); } return FD_ISSET( masterdesc, &R_SET ); } // I high resolution sleep function // Best to inline this to remove the overhead of the function call void Server::sleep( long millisecs ) { static struct timeval sleep_time; sleep_time.tv_sec = 0; sleep_time.tv_usec = millisecs; if( select( 0, NULL, NULL, NULL, &sleep_time ) == -1 ) { printf("SERVER: Error select() in Sleep()\n"); exit( errno ); } } // Do we want the numerical ip or try to get the name from the // nameserver? If you have a slow nameserver dont use this. void Server::useNameServer() { nameserver = 1; } int Server::newConnection() { FD_ZERO( &R_SET ); FD_SET( masterdesc, &R_SET ); if( select( masterdesc + 1, &R_SET, 0, 0, &null_time ) == -1 ) { printf("SERVER: select() error in NewConnection() - exiting.\n"); exit( errno ); } return FD_ISSET( masterdesc, &R_SET ); } Socket * Server::accept() { int desc; Socket *newSock = master->accept(); if( !newSock ) { if( errno == EAGAIN || errno == EWOULDBLOCK ) return 0; perror( "Server::accept()" ); exit(0); return 0; } newSock->noDelay(); newSock->getPeerName(); newSock->resolveIP(); desc = newSock->getDesc(); if( desc > topdesc ) topdesc = desc; FD_SET( desc, &MASTER_SET ); descripts++; return newSock; } void Server::addSock( Socket * sock ) { if( FD_ISSET( sock->getDesc(), &MASTER_SET ) ) { printf( "SERVER: Error. Attempt to add existing descriptor.\n" ); exit(0); } FD_SET( sock->getDesc(), &MASTER_SET ); if( sock->getDesc() > topdesc ) topdesc = sock->getDesc(); descripts++; } void Server::remove( Socket * sock ) { // I exit on the following two errors because if this happens // you need to find out why. int desc = sock->getDesc(); if( desc < 0 || desc >= maxdesc ) { printf("SERVER: Close() - desc [%d] out of bounds.\n", desc); exit( 0 ); } if( ! FD_ISSET( desc, &MASTER_SET ) ) { printf("SERVER: Invalid descriptor\n"); exit( 0 ); } FD_CLR( desc, &MASTER_SET ); if( !--descripts ) { topdesc = masterdesc; return; } if( desc == topdesc ) { for( desc = topdesc-1; !FD_ISSET( desc, &MASTER_SET ); desc-- ) ; topdesc = desc; } } int Server::canRead( Socket * sock ) { return FD_ISSET( sock->getDesc(), &R_SET ); } int Server::canWrite( Socket * sock ) { return FD_ISSET( sock->getDesc(), &W_SET ); } int Server::error( Socket * sock ) { int desc = sock->getDesc(); if( FD_ISSET( desc, &E_SET ) ) { FD_CLR( desc, &R_SET ); FD_CLR( desc, &W_SET ); return FD_ISSET( desc, &E_SET ); } return 0; }