/*
 *  Copyright (C) 2011-2012 Christian Beier <dontmind@freeshell.org>
 *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
 *
 *  This is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This software is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this software; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
 *  USA.
 */

/*
 * listen.c - listen for incoming connections
 */

#ifdef __STRICT_ANSI__
#define _BSD_SOURCE
#endif
#include <unistd.h>
#include <sys/types.h>
#ifdef __MINGW32__
#define close closesocket
#include <winsock2.h>
#undef max
#else
#include <sys/wait.h>
#include <sys/utsname.h>
#endif
#include <sys/time.h>
#include <rfb/rfbclient.h>

/*
 * listenForIncomingConnections() - listen for incoming connections from
 * servers, and fork a new process to deal with each connection.
 */

void
listenForIncomingConnections(rfbClient* client)
{
#ifdef __MINGW32__
  /* FIXME */
  rfbClientErr("listenForIncomingConnections on MinGW32 NOT IMPLEMENTED\n");
  return;
#else
  int listenSocket, listen6Socket = -1;
  fd_set fds;

  client->listenSpecified = TRUE;

  listenSocket = ListenAtTcpPortAndAddress(client->listenPort, client->listenAddress);

  if ((listenSocket < 0))
    return;

  rfbClientLog("%s -listen: Listening on port %d\n",
	  client->programName,client->listenPort);
  rfbClientLog("%s -listen: Command line errors are not reported until "
	  "a connection comes in.\n", client->programName);

#ifdef LIBVNCSERVER_IPv6 /* only try that if we're IPv6-capable, otherwise we may try to bind to the same port which would make all that listening fail */ 
  /* only do IPv6 listen of listen6Port is set */
  if (client->listen6Port > 0)
    {
      listen6Socket = ListenAtTcpPortAndAddress(client->listen6Port, client->listen6Address);

      if (listen6Socket < 0)
	return;

      rfbClientLog("%s -listen: Listening on IPV6 port %d\n",
		   client->programName,client->listenPort);
      rfbClientLog("%s -listen: Command line errors are not reported until "
		   "a connection comes in.\n", client->programName);
    }
#endif

  while (TRUE) {
    int r;
    /* reap any zombies */
    int status, pid;
    while ((pid= wait3(&status, WNOHANG, (struct rusage *)0))>0);

    /* TODO: callback for discard any events (like X11 events) */

    FD_ZERO(&fds); 

    if(listenSocket >= 0)
      FD_SET(listenSocket, &fds);  
    if(listen6Socket >= 0)
      FD_SET(listen6Socket, &fds);

    r = select(max(listenSocket, listen6Socket)+1, &fds, NULL, NULL, NULL);

    if (r > 0) {
      if (FD_ISSET(listenSocket, &fds))
	client->sock = AcceptTcpConnection(client->listenSock); 
      else if (FD_ISSET(listen6Socket, &fds))
	client->sock = AcceptTcpConnection(client->listen6Sock);

      if (client->sock < 0)
	return;
      if (!SetNonBlocking(client->sock))
	return;

      /* Now fork off a new process to deal with it... */

      switch (fork()) {

      case -1: 
	rfbClientErr("fork\n"); 
	return;

      case 0:
	/* child - return to caller */
	close(listenSocket);
	close(listen6Socket);
	return;

      default:
	/* parent - go round and listen again */
	close(client->sock); 
	break;
      }
    }
  }
#endif
}



/*
 * listenForIncomingConnectionsNoFork() - listen for incoming connections
 * from servers, but DON'T fork, instead just wait timeout microseconds.
 * If timeout is negative, block indefinitly.
 * Returns 1 on success (there was an incoming connection on the listen socket
 * and we accepted it successfully), -1 on error, 0 on timeout.
 */

int
listenForIncomingConnectionsNoFork(rfbClient* client, int timeout)
{
  fd_set fds;
  struct timeval to;
  int r;

  to.tv_sec= timeout / 1000000;
  to.tv_usec= timeout % 1000000;

  client->listenSpecified = TRUE;

  if (client->listenSock < 0)
    {
      client->listenSock = ListenAtTcpPortAndAddress(client->listenPort, client->listenAddress);

      if (client->listenSock < 0)
	return -1;

      rfbClientLog("%s -listennofork: Listening on port %d\n",
		   client->programName,client->listenPort);
      rfbClientLog("%s -listennofork: Command line errors are not reported until "
		   "a connection comes in.\n", client->programName);
    }

#ifdef LIBVNCSERVER_IPv6 /* only try that if we're IPv6-capable, otherwise we may try to bind to the same port which would make all that listening fail */ 
  /* only do IPv6 listen of listen6Port is set */
  if (client->listen6Port > 0 && client->listen6Sock < 0)
    {
      client->listen6Sock = ListenAtTcpPortAndAddress(client->listen6Port, client->listen6Address);

      if (client->listen6Sock < 0)
	return -1;

      rfbClientLog("%s -listennofork: Listening on IPV6 port %d\n",
		   client->programName,client->listenPort);
      rfbClientLog("%s -listennofork: Command line errors are not reported until "
		   "a connection comes in.\n", client->programName);
    }
#endif

  FD_ZERO(&fds);

  if(client->listenSock >= 0)
    FD_SET(client->listenSock, &fds);
  if(client->listen6Sock >= 0)
    FD_SET(client->listen6Sock, &fds);

  if (timeout < 0)
    r = select(max(client->listenSock, client->listen6Sock) +1, &fds, NULL, NULL, NULL);
  else
    r = select(max(client->listenSock, client->listen6Sock) +1, &fds, NULL, NULL, &to);

  if (r > 0)
    {
      if (FD_ISSET(client->listenSock, &fds))
	client->sock = AcceptTcpConnection(client->listenSock); 
      else if (FD_ISSET(client->listen6Sock, &fds))
	client->sock = AcceptTcpConnection(client->listen6Sock);

      if (client->sock < 0)
	return -1;
      if (!SetNonBlocking(client->sock))
	return -1;

      if(client->listenSock >= 0) {
	close(client->listenSock);
	client->listenSock = -1;
      }
      if(client->listen6Sock >= 0) {
	close(client->listen6Sock);
	client->listen6Sock = -1;
      }
      return r;
    }

  /* r is now either 0 (timeout) or -1 (error) */
  return r;
}


