#include "pcdefs.h"
#include "mbuf.h"
#include "protocol.h"
#include "data.h"
#include "tcp.h"
#include "funcdef.h"

void _near _fastcall transq(struct tcpport _far *);

/************************************************************************/
/*  tcptick
*      sleep, while demuxing packets, so we don't miss anything
*
*/
/* void _near _fastcall */
void _near _fastcall
tcptick()
{
	int	i;
	u_long	time;
	struct tcpport _far *p;

/*
*  Check each port to see if retransmission is necessary.
*/
	for (i = 0; i < NPORTS; i++) {
		p = (struct tcpport _far *)portlist[i];
		if (!p)
			continue;

		if (p->state == SCLOSED || p->state == SLISTEN)
			continue;

		if (p->type != SOCK_STREAM)
			continue;

		_disable();
		time = N_CLICKS();
		_enable();
		if (p->lasttime > time)		/* midnight wrap */
			p->lasttime = 1L;

		if (p->state == STWAIT) {
			if (p->lasttime + WAITTIME < time)
				p->state = SCLOSED;
			continue;
		}
		if (p->state >= SSYNRS && p->state <= SSYNS) {
			/* SSYNRS, SSYNR, and SSYNS */
			if (p->lasttime + 18L < time)
				(void) tcpsend(p, 4);
			continue;
		}
		if (p->wait_tx) {
			p->wait_tx--;
			if (!p->wait_tx) {
				transq(p);
				continue;
			}
		}
		if (p->outfree || p->state > SEST) {
/*
*  if a retransmission timeout occurs, exponential back-off.
*  This number returns toward the correct value by the RTT measurement
*  code in ackcheck.
*
*  fix: 5/12/88, if timer was at MAXRTO, transq didn't get hit - TK
*/
			if (p->rto < (u_int)(time - p->lasttime)) {
				if (p->rto < MAXRTO) 
					p->rto = p->rto << 1;
dfputs("back off\r\n");
				transq(p);
			}
		}
	}
}

/************************************************************************/
/*  transq
*
*   Needed for TCP, not as general as cpqueue, 
*   but is required for efficient transmit of the whole window.
*
*   Transmit the entire queue (window) to the other host without expecting
*   any sort of acknowledgement.
*
*/
void _near _fastcall
transq(p)
struct tcpport _far *p;
{
	u_int bites;

/*
*   find out how many bytes the other side will allow us to send (window)
*/
	bites = p->outsize;
	if (p->outfree < bites)
		bites = p->outfree;
	if (p->outwin < bites) {
		bites = p->outwin;
		if (bites == 0 && p->outfree)
			bites = 1;
	}

	if (bites) {
		(void) memcpy((u_char _far *)p->outpkt.x.data,
		    (u_char _far *)p->dataout, bites);
	}
	(void) tcpsend(p, bites);		/* send it */
}
