#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;
	int len;
	void lapbstate();

	axp = (struct ax25_cb *)n;
	if (axp->n2 != 0 && axp->retries++ >= axp->n2){
	    /* Retry count exceeded, drop the link.
	     * Note that this is a change from the original AX.25
	     * spec; attempting to restart the link caused more
	     * problems than it solved.
	     */
	    lapbstate(axp,DISCONNECTED,LAPBFAIL);
	    del_ax25(axp);
	    return;
	}
	switch(axp->state){
	case SETUP:
	    sendctl(axp,COMMAND,SABM|PF);
	    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;

	    /* I believe that retransmitting the oldest unacked
	     * I-frame tends to give better performance than polling,
	     * as long as the frame isn't too "large", because
	     * chances are that the I frame got lost anyway.
	     * This is an option in LAPB, but not in the official AX.25.
	     * When oldest unacked I-frame smaller than PTHRESH, use info poll */
	    if(axp->txq != NULLBUF &&
		(((len = len_mbuf(axp->txq)) < axp->pthresh && !axp->remotebusy && axp->retries < 3) ||
		 axp->proto == V1)){
		/* Retransmit oldest unacked I-frame */
		bp = copy_p(axp->txq,len);
		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;
	case FRAMEREJECT:
	    frmr(axp,0,0);		/* Retransmit last FRMR */
	    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;
	struct mbuf *bp;

	axp = (struct ax25_cb *)n;

	/* Now look if any valid frames are still in the sammler.  This means */
	/* they were received earlier, and not repeated during T2 */
	while ((bp = axp->sammlq[axp->vr]) != NULLBUF){
		axp->sammlq[axp->vr] = NULLBUF;
		axp->vr = (axp->vr+1) & MMASK;
		procdata(axp,bp);		/* accept the frame */
	}

	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;
	if(axp->proto == V1)
	    return;			/* Not supported in the old protocol */
	axp->waitack = YES;
	control = len_mbuf(axp->rxq) > axp->window? RNR|PF : RR|PF;
	sendctl(axp,COMMAND,control);
}

