#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pcdefs.h"
#include "shared.h"
#include "data.h"
#include "tcp.h"
#include "funcdef.h"

void transq(struct tcpport *);
extern u_char _far *bios;

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

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

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

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

		CLI;
		time = *(u_long _far *)&bios[0x46c];
		STI;
		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,
				    (p->outpkt.t.hlen >> 2) & 0x3c -
				    sizeof (struct tcph));
			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 < (unsigned)(time - p->lasttime)) {
				if (p->rto < MAXRTO) 
					p->rto = p->rto << 1;
				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
transq(p)
struct tcpport *p;
{
	int bites;

/*
*   find out how many bytes the other side will allow us to send (window)
*/
#ifdef notdef
	bites = p->outsize;
	if (p->outfree < bites)
		bites = p->outfree;
#else
	bites = min(min(p->outsize, p->outfree), p->outwin);
#endif
	if (bites == 0 && p->outfree)
		bites = 1;

	if (bites) {
		_fmemcpy(p->outpkt.x.data, p->dataout, bites);
	}
	p->wait_tx = 0;
	(void) tcpsend(p, bites);		/* send it */
}
