/***************************************************************
* PrServerSocket.cpp
*
* This is an implementation of server socket methods.
*
****************************************************************/

/*
* modification history
*----------------------
*
* 02/13/98: K.C. Chang: created.
*/

#include "PrServerSocket.h"
#include "PrSocket.h"

#include <stdio.h>
#include <string.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>

#include <sys/ioctl.h>

PrServerSocket::PrServerSocket( int portNum )
{
   socket_ = NULL;
   socketFD_ = -1;
   flag_ = PR_SERVERSOCKET_ERROR;
   flag_ = Init(portNum);
}


PrServerSocket::~PrServerSocket()
{
   // should be done by the user
   if (socket_ != NULL)
      delete socket_;
   close();
}


void PrServerSocket::close()
{
   if (socketFD_>=0)
   {
      ::close(socketFD_);
   }
   socketFD_ = -1;
}

int PrServerSocket::Init( int portNum )
{
   struct sockaddr_in serv_addr;

   if ((socketFD_ = socket(AF_INET,SOCK_STREAM,0))<0)
      perror("PrServerSocket: can't open stream socket");

   memset((char *)&serv_addr,'\0',sizeof(serv_addr));
   int reuse = 1;
   setsockopt(socketFD_,SOL_SOCKET,SO_REUSEADDR,(char *)&reuse,sizeof(reuse));

   serv_addr.sin_family = AF_INET;
   serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
   serv_addr.sin_port = htons((unsigned short)portNum);

   if (bind(socketFD_,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0)
      perror("PrServerSocket: can't bind local address");

   if (listen(socketFD_,1)<0)
      perror("PrServerSocket: can't listen error");

   return PR_SERVERSOCKET_OK;
}

PrSocket *PrServerSocket::accept()
{
   if (socket_ != NULL)
   {
      delete socket_;
      socket_ = NULL;
   }

   int on=0;
   // blocking socket
#ifdef PR_QNX
   if (ioctl((short)socketFD_,FIONBIO,&on)<0)
#else // PR_QNX
   if (ioctl(socketFD_,FIONBIO,&on)<0)
#endif // PR_QNX
      perror("PrServerSocket::accept():ioctl() F_SETFL, FNDELAY");

   struct sockaddr_in cli_addr;

#ifdef PR_QNX
   int clilen = sizeof(cli_addr);
#else
   unsigned int clilen = sizeof(cli_addr);
#endif
   int newsockfd = ::accept(socketFD_,(struct sockaddr *)&cli_addr,&clilen);

   // Non-blocking socket
   on=1;
#ifdef PR_QNX
   if (ioctl((short)socketFD_,FIONBIO,&on)<0)
#else // PR_QNX
   if (ioctl(socketFD_,FIONBIO,&on)<0)
#endif // PR_QNX
      perror("PrServerSocket::accept():ioctl() F_SETFL, FNDELAY");

   if (newsockfd<0) 
   {
      socket_ = NULL;
      perror("PrServerSocket: accept error");
   }
   else
      socket_ = new PrSocket(newsockfd);

   return socket_;
}




