#include "global.h"
#include "mbuf.h"
#include "ax25.h"
#include "timer.h"
#include "lapb.h"

/* Called whenever timer T1 expires */
void
recover(n)
int *n;
{
	register struct ax25_cb *axp;
	char control;
	struct mbuf *bp;

	axp = (struct ax25_cb *)n;
	if(axp->n2 != 0 && axp->retries++ >= axp->n2){
		/* Retry count exceeded; reset the link, unless
		 * a connect or disconnect was pending, in which case
		 * just give up.
		 */
		switch(axp->state){
		case DISCONNECTED:
			break;		/* The user issued a double disc */
		case SETUP:
		case DISCPENDING:
			lapbstate(axp,DISCONNECTED);	/* Just give up */
			del_ax25(axp);
			break;
		case CONNECTED:
		case FRAMEREJECT:
			lapbstate(axp,SETUP);
	 		sendctl(axp,COMMAND,SABM|PF);	/* Attempt link reset */
			break;
		}
		return;
	}
	switch(axp->state){
	case SETUP:
		sendctl(axp,COMMAND,SABM|PF);
		break;
	case FRAMEREJECT:
		frmr(axp,0,0);
		break;
	case DISCPENDING:
		sendctl(axp,COMMAND,DISC|PF);
		break;
	case CONNECTED:
		/* Don't wait for a Final reply if running the old protocol */
		if(axp->proto == V2)
			axp->waitack = YES;
		if(axp->txq != NULLBUF){
			/* Retransmit oldest unacked I-frame */
			dup_p(&bp,axp->txq,0,len_mbuf(axp->txq));
			control = PF | I | ((axp->vs - axp->unack) & MMASK) << 1
			 | axp->vr << 5;
			sendframe(axp,COMMAND,control,bp);
		} else {
			/* Transmit poll */
			control = len_mbuf(axp->rxq) > axp->window ? RNR|PF : RR|PF;
			sendctl(axp,COMMAND,control);
		}
		break;
	}
}

/* T2 has expired, we can't delay an acknowledgement any further */
void
send_ack(n)
int *n;
{
	char control;
	register struct ax25_cb *axp;

	axp = (struct ax25_cb *)n;
	control = len_mbuf(axp->rxq) > axp->window ? RNR : RR;
	sendctl(axp,RESPONSE,control);
	axp->response = 0;
}

/* Send a poll (S-frame command with the poll bit set) */
void
pollthem(n)
int *n;
{
	char control;
	register struct ax25_cb *axp;

	axp = (struct ax25_cb *)n;
	axp->waitack = YES;
	control = len_mbuf(axp->rxq) > axp->window ? RNR|PF : RR|PF;
	sendctl(axp,COMMAND,control);
}
