{ This the ReceiveSwitch Overlay }

  PROCEDURE GetFile({ Using } data:string);
    { create file from fileheader packet }
  CONST	{ used for GetFile }
    FLEN1 = 7;	   { Position of "." in	file name }
    FLEN2 = 10;	   { Max length	of file	name }
    TEMPFILE = 'TEMP.K              ';	{ Mask for temp	file }
  VAR
    p,strend: integer;
    temp : string;
   BEGIN
     WITH CurrentPacket^ DO
      BEGIN
	IF DiskFile = IOERROR	   { check if we already have a	file }
	 THEN
	  BEGIN
	    IF Verbosity
	     THEN
	     PutCS('Creating file ...   ',data,STDERR);
                   
	    { check position of	'.' -- truncate	if bad }
	    p := index(data,PERIOD);
	    IF (p > FLEN1 )
	     THEN
	      BEGIN
		data[FLEN1] := PERIOD;
		scopy(data,p+1,temp,1);
		scopy(temp,1,data,FLEN1+1);
	      END;
	     { check Max length	}
	    IF length(data) > FLEN2
	     THEN
	     data[FLEN2	+1] := ENDSTR;
	    IF (Exists(data) AND (fileWarn = oON)) 
	     THEN
	      BEGIN
		IF local
		 THEN
		 PutCS('File already exists ',data,STDERR);
		CtoS(TEMPFILE,data);
		strend := 0;
		 REPEAT
		  strend := strend +1;
		 UNTIL (data[strend] = BLANK);
		strend := itoc(n,data,strend);
		IF local
		 THEN
		 PutCS('Creating  ...       ',data,STDERR);
              END;
	    DiskFile :=	Sopen(data,-IOWRITE);
	  END;
	IF (Diskfile <=	IOERROR)
	 THEN
	 ErrorPack('Cannot create file  ');
      END;
   END;

  PROCEDURE ReceiveInit;
    { receive init packet }
    { respond with ACK and  our	parameters }
   BEGIN
     IF	NumTry > MaxTry
      THEN
       BEGIN
	 State := Abort;
	 PutErr('Cannot	receive	init ');
       END
      ELSE
       BEGIN
	 Verbose ( 'Receiving Init      ');
	 NumTry	:= NumTry+1;
	 IF RecvPacket
	  AND (CurrentPacket^.ptype = TYPES)
	  THEN
	   BEGIN
	     WITH CurrentPacket^ DO
	      BEGIN
		n := seq;
		DeCodeParm(data);
	      END;

	     { now send	mine }
	     WITH ThisPacket^ DO
	      BEGIN
		count := NUMPARAM;
		seq := n;
		Ptype := TYPEY;
		EnCodeParm(data);
	      END;

	     SendPacket;
	     NumACK := NumACK+1;
	     State := FileHeader;
	     OldTry := NumTry;
	     NumTry := 0;
	     MaxTry := DEFTRY; { use regular default now }
	     n := (n+1)	MOD 64
	   END
	  ELSE
	   BEGIN
	     IF	Debug
	      THEN
	      PutCln('Received Bad init	  ',STDERR);
	      SendNAK(n);
	   END;
       END;
   END;

  PROCEDURE DataToFile;	{ output to file }
  VAR
    len,i : integer;
    temp : string;
   BEGIN
     WITH CurrentPacket^ DO
      BEGIN
	len := length(data);
	AddTo(ChInFileRecv ,len);
	CASE EOLforFile	OF
	  LineFeed:	putstr(data,DiskFile);
	  CrLf:
	   BEGIN  { don't output  CR }
	     FOR i:=1 TO len DO
	     IF	data[i]	<> CR
	      THEN
	      putcf(data[i],DiskFile);
	   END;
	  JustCR:
	   BEGIN   { change CR to NEWLINE }
	     FOR i:=1 TO len DO
	     IF	data[i]=CR
	      THEN
	      data[i]:=NEWLINE;
	     putstr(data,DiskFile);
	   END;
	 END;
	{ case }
      END;
   END;


  PROCEDURE Dodata;  { Process Data packet }
   BEGIN
     WITH CurrentPacket^ DO
      BEGIN
	IF  seq	= ((n +	63) MOD	64)
	 THEN
	  BEGIN		       { data last one }
	    IF OldTry>MaxTry
	     { number of tries?	}
	     THEN
	      BEGIN
		State := Abort;
		PutErr('Old data - Too many ');
	      END
	     ELSE
	      BEGIN
		SendACK(seq);
		NumTry := 0;
	      END;
	  END
	 ELSE
	  BEGIN		   { data - this one }
	    IF (n<>seq)
	     THEN
	     SendNAK(n)
	     ELSE
	      BEGIN
		DataToFile;
		SendACK(n); { ACK }
		OldTry := NumTry;
		NumTry := 0;
		n := (n+1) MOD 64;
	      END;
	  END;
      END;
   END;

  PROCEDURE DoFileLast;	  { Process File Packet	}
   BEGIN	  { File header	- last one  }
     IF	OldTry > MaxTry	{ tries	? }
      THEN
       BEGIN
	 State := Abort;
	 PutErr('Old file - Too	many ');
       END
      ELSE
       BEGIN
	 OldTry	:= OldTry+1;
	 WITH CurrentPacket^ DO
	  BEGIN
	    IF seq = ((n + 63) MOD 64)
	     { packet number }
	     THEN
	      BEGIN  { send ACK	}
		SendACK(seq);
		NumTry := 0
	      END
	     ELSE
	      BEGIN
		SendNAK(n);   {	NAK }
	      END;
	  END;
       END;
   END;


  PROCEDURE DoEOF;  { Process EOF packet }
   BEGIN		 { EOF - this one }
     IF	CurrentPacket^.seq<>n	 { packet number ? }
      THEN
      SendNAK(n) { NAK }
      ELSE
       BEGIN		   { send ACK }
	 Sclose(DiskFile);  { close file }
	 SendACK(n);
	 DiskFile := IOERROR;
	 OldTry	:= NumTry;
	 NumTry	:= 0;
	 n := (n+1) MOD	64; { next packet  }
	 State := FileHeader;	{ change state }
       END;
   END;

  PROCEDURE ReceiveData;  { Receive data packets }
  VAR
    strend: integer;
    good : boolean;
   BEGIN
     IF	NumTry > MaxTry		 { check number	of tries }
      THEN
       BEGIN
	 State := Abort;
	 IF local
	  THEN
	  PutCN('Recv data -Too	many ',n,STDERR);
       END
      ELSE
       BEGIN
	 NumTry	:= NumTry+1;		    { increase number of tries }
	 good := RecvPacket;	    { get packet }
	 WITH CurrentPacket^ DO
	  BEGIN
	    IF Verbosity
	     THEN
	     PutCN('Receiving (Data)    ',CurrentPacket^.seq,STDERR);

	    IF ((ptype = TYPED)	OR (ptype=TYPEZ)
		OR (ptype=TYPEF)) AND good	     { check type }
	     THEN
	     CASE ptype	OF
	       TYPED:  DoData;
	       TYPEF:  DoFileLast;
	       TYPEZ:  DoEOF;
	      END { case }
	     ELSE
	      BEGIN
		IF Debug
		 THEN
		 PutCln('Expected data pack  ',STDERR);
		SendNAK(n);
	      END;
	  END;
       END;
   END;


  PROCEDURE DoBreak; { Process Break packet }
   BEGIN		    { Break transmission }
     IF	CurrentPacket^.seq<>n	 { packet number ? }
      THEN
      SendNAK(n) { NAK }
      ELSE
       BEGIN		{ send	ACK }
	 SendACK(n) ;
	 State := Complete  { change state }
       END
   END;

  PROCEDURE DoFile; { Process file packet }
   BEGIN		 { File	Header }
     WITH CurrentPacket^ DO
      BEGIN
	IF seq<>n	    { packet number ? }
	 THEN
	 SendNAK(n)  { NAK }
	 ELSE
	  BEGIN		      {	send ACK }
	    AddTo(ChInFileRecv,	length(data));
	    GetFile(data);   { get file	name }
	    SendACK(n);
	    OldTry := NumTry;
	    NumTry := 0;
	    n := (n+1) MOD 64; { next packet  }
	    State := FileData;	 { change state	}
	  END;
      END;
   END;

  PROCEDURE DoEOFLast; { Process EOF Packet }
   BEGIN	       { End Of	File Last One}
     IF	OldTry > MaxTry	{ tries	? }
      THEN
       BEGIN
	 State := Abort;
	 PutErr('Old EOF - Too many  ');
       END
      ELSE
       BEGIN
	 OldTry	:= OldTry+1;
	 WITH CurrentPacket^ DO
	  BEGIN
	    IF seq =((n	+ 63 ) MOD 64)
	     { packet number }
	     THEN
	      BEGIN  { send ACK	}
		SendACK(seq);
		Numtry := 0
	      END
	     ELSE
	      BEGIN
		SendNAK(n);  { NAK }
	      END
	  END;
       END;
   END;

  PROCEDURE DoInitLast;
   BEGIN		{ Init Packet -	last one }
     IF	OldTry>MaxTry	{ number of tries? }
      THEN
       BEGIN
	 State := Abort;
	 PutErr('Old init - Too	many ');
       END
      ELSE
       BEGIN
	 OldTry	:= OldTry+1;
	 IF CurrentPacket^.seq = ((n + 63) MOD	64)
	  { packet number }
	  THEN
	   BEGIN   { send ACK }
	     WITH ThisPacket^ DO
	      BEGIN
		count := NUMPARAM;
		seq := CurrentPacket^.seq;
		ptype := TYPEY;
		EnCodeParm(data);
	      END;
	     SendPacket;
	     NumACK := NumACK+1;
	     NumTry := 0;
	   END
	  ELSE
	   BEGIN
	     SendNAK(n);  { NAK	}
	   END;
       END;
   END;

  PROCEDURE ReceiveFile; { receive file	packet }
  VAR
    good: boolean;
   BEGIN
     IF	NumTry > MaxTry		 { check number	of tries }
      THEN
       BEGIN
	 State := Abort;
	 PutErr('Recv file - Too many');
       END
      ELSE
       BEGIN
	 NumTry	:= NumTry+1;		    { increase number of tries }
	 good := RecvPacket;		 { get packet }
	 WITH CurrentPacket^ DO
	  BEGIN
	    IF Verbosity
	     THEN
	     PutCN('Receiving (File)    ',seq,STDERR);

	    IF ((ptype = TYPES)	OR (ptype=TYPEZ)
		OR (ptype=TYPEF) OR (ptype=TYPEB)) { check type	}
	     AND good
	     THEN
	     CASE ptype	OF
	       TYPES:  DoInitLast;
	       TYPEZ:  DoEOFLast;
	       TYPEF:  DoFile;
	       TYPEB:  DoBreak;
	      END { case }
	     ELSE
	      BEGIN
		IF Debug
		 THEN
		 PutCln('Expected File Pack  ',STDERR);
		SendNAK(n);
	      END;
	  END;
       END;
   END;


  {$E+}

  PROCEDURE RecvSwitch;	{ this procedure is the	main receive routine }
   BEGIN
     StartRun;
      REPEAT
       CASE State OF
	 FileData:	 ReceiveData;
	 Init:		 ReceiveInit;
	 Break:		 { nothing };
	 FileHeader:	 ReceiveFile;
	 EOFile:	 { nothing };
	 Complete:	 { nothing };
	 Abort:		 { nothing };
	END;
       { case }
      UNTIL (State = Abort ) OR	( State	= Complete );
   END;

