
#include "k.h"

/*
 *	r e c s w
 */

recsw(istate)
char istate;

{
	state = istate;			/* send-initiate or file receive is the start state */
	numtry = 0;			/* say no tries yet */
#if debug
	fprintf(stderr,"recsw -- initial state is %c\n",state);
#endif

	while(TRUE) 
	{
#if debug
	fprintf(stderr,"recsw -- state is now %c\n",state);
#endif
	switch(state)	/* do this for as long as necessary */
	{
		case 'D':	state = rdata();	/* data receive state */
					break;

		case 'F':	state = rfile();	/* file receive state */
					break;

		case 'R':	state = rinit();	/* send initiate state */
					break;

		case 'C':	return(TRUE);		/* complete state */

		case 'A':	return(FALSE);		/* unknown state, abort */
	}
	}
}


/*
 *	 r i n i t
 */

rinit()
{
	int len, num;

	if (numtry++ > MAXTRY) return('A');		/* abort if to many tries */
	switch(rpack(&len,&num,packet))			/* get a packet */
	{
		case 'S':						        /* send-init */
		{
			n = num;					        /* synchronize packet numbers */
			rpar(packet);					/* get the init data */
			spar(packet);					/* fill up packet with init info */
			spack('Y',n,6,packet);			/* ACK with my parameters */
			oldtry = numtry;				/* save old try count */
			numtry = 0;					        /* and start a new counter */
			n = (n+1)%64;					/* bump packet number */
			return('F');					/* OK, now enter file-send state */
		}

		case FALSE:	return (state);			/* we didn't receive a packet */

		default:	return('A');			/* unknown type, abort */
	}
}


/*
 *	r f i l e
 */

rfile()
{
	int num, len;

	if (numtry++ > MAXTRY) return('A');		/* abort if too many tries */
	switch(rpack(&len,&num,packet))			/* get packet */
	{
		case 'S':						        /* send-init */
		{
			if (oldtry++ > MAXTRY)
				return('A');				/* if too many tries, abort */
			if (num == n-1)					/* check packet number */
			{
				spar(packet);				/* get the init params */
				spack('Y',num,6,packet);	/* it's right, ACK it */
				numtry = 0;				        /* reset try counter */
				return(state);
			}
			else return('A');				/* sorry, wrong number */
		}

		case 'Z':						        /* end-of-file */
		{
			if (oldtry++ > MAXTRY) return('A');
			if (num == n-1)					/* acknowledge good packet */
			{
				spack('Y',num,0,0);
				numtry = 0;
				return(state);
			}
			else return('A');				/* or abort on bad one */
		}

		case 'F':						        /* file-header */
		{
			if (num != n) return('A');
			getfil(packet);					/* open the file */
			spack('Y',n,0,0);				/* acknowledge */
			oldtry = numtry;
			numtry = 0;
			n = (n+1)%64;
			return('D');					/* switch to data state */
		}

		case 'B':						        /* break transmission */
		{
			if (num != n) return ('A');
			spack('Y',n,0,0);				/* say OK */
			return('C');					/* and go to complete state */
		}

		case FALSE: return(state);

		default: return ('A');
	}
}


/*
 *	r d a t a
 */

rdata()
{
	int num, len;

	if (numtry++ > MAXTRY) return('A');		/* abort if too many tries */
	switch(rpack(&len,&num,packet))			/* get packet */
	{
		case 'D':						        /* data */
		{
			if (num != n)					/* right packet? */
			{						        	/* no */
				if (oldtry++ > MAXTRY)
					return('A');			/* if too many tries */
				if (num == n-1)				/* check packet number */
				{
					spar(packet);			/* get the init params */
					spack('Y',num,6,packet);/* it's right, ACK it */
					numtry = 0;			        /* reset try counter */
					return(state);
				}
				else return('A');			/* sorry wrong number */
			}			/* data with right packet number */
			bufemp(packet,fd,len);			/* write out the packet */
			spack('Y',n,0,0);				/* right packet, acknowledge */
			oldtry = numtry;
			numtry = 0;
			n = (n+1)%64;
			return('D');					/* remain in data state */
		}

		case 'F':						        /* file-send */
		{
			if (oldtry++ > MAXTRY) return('A');
			if (num == n-1)					/* acknowledge good packet */
			{
				spack('Y',num,0,0);
				numtry = 0;
				return(state);
			}
			else return('A');				/* or abort on bad one */
		}

		case 'Z':						        /* end-of-file */
		{
			if (num != n) return('A');
			spack('Y',n,0,0);				/* say OK */
			close(fd);					        /* close up the file */
			n = (n+1)%64;
			return('F');					/* and go to file state */
		}

		case FALSE:	return(state);

		default:	return('A');
	}
}
