static const char* version_id =
  "$Id: ServerSocket.cc,v 1.11 1999/10/22 20:06:50 v2kea318 Exp $";

// $Log: ServerSocket.cc,v $
// Revision 1.11  1999/10/22  20:06:50  v2kea318
// Undo revision 1.4.  There is no need for any value other than INADDR_ANY.
//
// Revision 1.10  1999/09/21  19:55:30  v2kea318
// Added the thread-safe flag to the accept method.
//
// Revision 1.9  1999/08/18  16:01:56  v2kea318
// Fixed the casting operators to use C++ style casts.
//
// Revision 1.8  1999/08/12  19:24:37  v2kea318
// Do not embed C++ style comments (//) inside C style comments (/* */).
//
// Revision 1.7  1999/07/30  20:44:12  v2kea318
// Converted the code to G++ compliance.
//
// Revision 1.6  1999/07/09  18:26:38  v2kea318
// *** empty log message ***
//
// Revision 1.5  1999/04/28  19:02:52  v2kea318
// Changed the constructor.  Added a static function to determine the
// name of the machine we're on.
//
// Revision 1.4  1999/04/27  14:58:39  v2kea318
// Update the use of the hp data field of the base class.
//
// Revision 1.3  1999/04/26  14:28:52  v2kea318
// Build the hostent data as a copy.
//
// Revision 1.2  1999/04/23  20:12:18  v2kea318
// Working version!
//
// Revision 1.1  1999/04/23  18:54:46  v2kea318
// Initial revision
//
//***************************************************************************

#include "ServerSocket.h"
#include <cerrno>

extern char *sys_errlist[ ];

//***************************************************************************

static char* gethname() 
{
  static const size_t maxhostname = 256;
  static char localhost[maxhostname + 1];
  gethostname(localhost, maxhostname);
  return localhost;
}

ServerSocket::ServerSocket(int p) : SocketBase(gethname(), p)
{
  // build the SA structure.
  sa.sin_addr.s_addr = INADDR_ANY;

  // build the socket.
  build();

  // set socket options.
  int on = 1;
  setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);

  // bind the socket.
  if (bind(sock, reinterpret_cast<const struct sockaddr *>(&sa), 
	   sizeof sa) < 0)
      throw SocketException("Socket already in use");

  // specify the queue size.
  listen(sock, SOMAXCONN);
}

//***************************************************************************

Pointer<Socket> ServerSocket::accept(bool tsafe) 
{
  // allocate memory for a socket.
  Pointer<Socket> client(new Socket, tsafe);

  // accept the connection.
  size_t i = sizeof client->sa;
  if ((client->sock = 
       ::accept(this->sock,
		reinterpret_cast<struct sockaddr *>(&(client->sa)),
		&i)) < 0)
      throw SocketException(sys_errlist[errno]);

  /* Build the client hostent structure.  We need to store a copy 
     of the data. */
  struct hostent* thp = 
      gethostbyaddr(reinterpret_cast<char *>(&(client->sa.sin_addr.s_addr)),
		    sizeof sa.sin_addr.s_addr,
		    AF_INET);
  client->hp.copy(thp);
  
  // return the client socket.
  return client;
}
