/*
 * handler.c
 *
 * Author: Tomi Ollila <too@cs.hut.fi>
 *
 * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
 *		      All rights reserved.
 *
 * Created: Wed Sep  1 18:05:18 1993 too
 * Last modified: Thu Apr 14 13:19:04 1994 too
 *
 * $Id: handler.c,v 3.2 1994/04/17 11:52:13 too Exp $
 *
 */

#if 0 && (__GNUC__ < 2) && (__SASC < 6) || !defined (AMIGA)
#error this program compiles only with amiga, gcc v2.x or sas/c version 6.x
#endif

/*
 * These Globals are constant after initialization
 */
#ifdef __GNUC__
struct ExecBase * SysBase = 0;
#endif
struct DosLibrary * DOSBase = 0;

const int one = 1;

#include "handler/begin.c"
#define RFI .

#ifdef __SASC
#undef SocketBase
struct Library * SocketBase;
#endif

static ULONG dtablesizetaglist[] = {
  SBTM_SETVAL(SBTC_DTABLESIZE), FD_SETSIZE, TAG_DONE };

int start()
{
  struct CleanUp	CU /* = { 0 } */;
  struct ApplShared	AS;
  struct ApplPort *	applarray[FD_SETSIZE];
  struct MinList	writelist;	/* list of apps having pending wrts */
  struct MinList	freewritelist;	/* free pending write structures */
  struct MinList	freeappllist;
  struct MsgPort *	mymsgport;
  ULONG 		myportflag;
  ULONG 		timerflag;
  struct DosList *	mydev;
  int			nfds;
  fd_set		readfds, writefds;
  ULONG 		sigmask; /* Exec signals to be catched */
  int			writespending = 0; /* counter */
  struct ApplPort *	lastappl = NULL;
  LONG			lastmask = 0;
  int			lastsd = 0;
  int			notDone = TRUE;

#include "handler/startup.c"

  while (notDone) {
    fd_set		rfds;
    fd_set		wfds;
    fd_set *		wfdsp;
    ULONG		smask;
    int			n;
    
    rfds = readfds;
    if (writespending) {
       DP("WRITESPENDING: writefds %lx", *(LONG *)&writefds);
      wfds = writefds;
      wfdsp = &wfds;
    }
    else
      wfdsp = NULL;
    smask = sigmask;

    /*
     * All Input events are waited here.
     */
/*    n = WaitSelect2(nfds, &rfds, wfdsp, NULL, NULL, &smask); */

    DP("BWS nfds: %lx readfds: %lx", nfds, *(LONG *)&readfds);
    n = WaitSelect2(nfds, &rfds, wfdsp, &smask);
    DP("AWS n %ld, rfds %lx, wfds %lx smask %lx", n, *(LONG *)&rfds, 
	writespending? *(LONG *)wfdsp: 0, smask);

    switch (n) {
    case -1:
      notDone = FALSE;
      break;
    case 0:
      /*
       * Since there is no timeout used the only possibility is there
       * perhaps is packet arrived. since the case where something has
       * arrived to sockets there is a possibisity a packet has arrived
       * -- the packet handling is done last under 'default' case.
       */
      goto packet;
    default:
      if (writespending) {
	DP("WRITESPENDING: wfds %lx", *(LONG *)wfdsp);
#	include "handler/pendingwrites.c"

      if (*(LONG *)&rfds == 0)
	goto packet;
      }
      /*
       * First look if data has arrived to the socket where it last arrived.
       * this speeds up net burps. If not, scan whole application array
       * through
       */
      {
	int i;

/* 	DP("lastmask %ld, rfds %ld\n", lastmask, *(LONG *)&rfds); */

	if (lastmask == *(LONG*)&rfds) {
	  i = nfds;
	  goto readit;
	}
	i = 0;
      loop:
	if (FD_ISSET(i, &rfds)) {
	  lastappl = applarray[i];
	  lastsd = i;
	readit:
#	  include "handler/readevent.c"
	}
	i++;
	if (i < nfds)
	  goto loop;
	lastmask = 1 << lastsd;
      }
    packet:
      /*
       * First see if one or more of the applications have sent packet
       * to their private port (other than an open/reopen -packet).
       */
      if (smask & applportflag) {
#	include "handler/applmsg.c"
      }
      /*
       * See if some of the waitforchar requests are expired
       */
      if (smask & timerflag) {
#	include "handler/timermsg.c"
      }
      /*
       * See if someone has sent message to my message port.
       */
      if (smask & myportflag) {
#	include "handler/mymsg.c"
      }
    } /* WaitSelect() */
  }  /* while */

  /*
   * Program received break signal. drop out all connections.
   */
# include "handler/cleanup.c"

  return clean(&CU, 0);
}
