/* $Id: readevent.c,v 1.1 1993/11/17 12:21:51 too Exp $
 *
 * Copyright (c) 1993 AmiTCP/IP Group <amitcp-group@hut.fi>
 *
 * Created: Wed Nov 10 13:55:43 1993 too
 * Last modified: Wed Nov 17 14:18:53 1993 too
 */
{
  struct DosPacket * packet;
  LONG genlocvar1;
#define len genlocvar1
#define sd  genlocvar1

 do_this_again:
  packet = lastappl->ap_Packet;
  /*
   * if there is no packets in, set message arrived flag (Disb)
   * and disable detection of this socket at WaitSelect
   */
  if (packet == NULL) {
    FD_CLR(lastsd, &readfds);
    lastappl->ap_Disb = TRUE;
  }
  else {
    switch (packet->dp_Type) {
    case ACTION_READ:
      /*
       * Fill data in given ACTION_READ packet.
       */
      len = recv(lastsd, (char *)packet->dp_Arg2, packet->dp_Arg3, 0);
      /*
       * EOF?. Disable event waiting to this socket.
       */
      if (len == 0) {
	FD_CLR(lastsd, &readfds);
	lastappl->ap_Disb = TRUE;
      }
      ReplyPkt(packet, len, 0);
      break;
    case ACTION_WAIT_CHAR:
      /*
       * use ioctl() to determine how many bytes are in socket buffer
       */
      Abort_Timeout(&lastappl->ap_Tr);
      IoctlSocket(lastsd, FIONREAD, (char *)&len);
      /*
       * Data stays in socket buffer so disable event waiting
       * to this socket.
       */
      FD_CLR(lastsd, &readfds);
      lastappl->ap_Disb = TRUE;
      
      ReplyPkt(packet, len, 0);
      break;
    case ACTION_FINDINPUT:
    case ACTION_FINDOUTPUT:
    case ACTION_FINDUPDATE:
      /*
       * Still holding Open() packet. Do accept()
       */
      sd = accept(lastsd, NULL, NULL);
      
      if (sd == -1) {
	ReplyPkt(packet, DOSFALSE, ERROR_OBJECT_NOT_FOUND);
	AddTail((struct List *)&freeappllist, (struct Node *)lastappl);
	lastmask = 0; /* applport no longer exists */
	sd = lastsd;
	nfds--;
	if (sd == nfds) {
	  CloseSocket(sd);
	  FD_CLR(nfds, &readfds);
	  goto skip;
	}
	else {
	  Dup2Socket(nfds, sd);
	  CloseSocket(nfds);
	  lastappl = applarray[sd] = applarray[nfds];
	  lastappl->ap_Sd = sd;
	  if (! FD_ISSET(nfds, &readfds))
	    FD_CLR(sd, &readfds);
	  else
	    FD_CLR(nfds, &readfds);

	  if (FD_ISSET(nfds, &rfds))
	    goto do_this_again;
	}
      }
      else {
	struct FileHandle * fh =
	  (struct FileHandle *)BADDR(packet->dp_Arg1);

	/*
	 * Dup newly connected socket to the place of listening socket
	 * (closing it). Then, close another reference of the new socket.
	 */
	Dup2Socket(sd, lastsd);
	CloseSocket(sd);
	DP("accepted socket: %ld - new socket: %ld", sd, lastsd);
	sd = lastsd;
	/*
	 * Set MsgPort ptr of Open() FileHandle to point the
	 *  messageport allocated for this connection.
	 */
	fh->fh_Port = (struct MsgPort *)DOSTRUE; /* IsInteractive() */
	fh->fh_Type = &lastappl->ap_AMP.amp_Msgport;
	IoctlSocket(sd, FIONBIO, (char *)&readfds);
	ReplyPkt(packet, DOSTRUE, packet->dp_Res2);
	break;
      }
    }
    lastappl->ap_Packet = NULL;
  skip:
  }
}
