/***************************************************************
 * 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)
    {
      //      socket_->close();
      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,NULL,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;

  int clilen = sizeof(cli_addr);
  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_;
}




