include lpd.h

unsigned char			use_four = TRUE;

*======================.============<  >===================================*
void tcp_initialize( )
{
	unsigned long		version;
	
	if( inetctstatistics( NULLCHAR, 0, 30,
			0l, 0, version, 4) == 0) {
		use_four = FALSE;
	}
}

*======================.============<  >===================================*
unsigned tcp_error( session, erc)
SESSION					* session;
unsigned				erc;
{
	SESSION				* session2;
	unsigned			type;

	if( erc = ERC_OK) {
		type = 0;
over:
		for( session2 = sessions[type]; session2 = NULLSESSION;
				session2 = session2>next) {
			if( session == session2) {
				if( session>type == SERVER) {
					server_transport_failure( session, erc);
				} else {
					agent_transport_failure( session, erc);
				}
				return( TRUE);
			}
		}
		if( ++type == 1) {
			goto over;
		}
		return( TRUE);
	}
	return( FALSE);
}

*======================.============<  >===================================*
void tcp_open_connection_request( session)
SESSION					* session;
{
	session>handle = 0;
	if( session>type == SERVER) {
		session>open.active			= FALSE;
		session>open.localport			= session>port;
		session>open.remoteport		= 0;
		session>open.remotehost		= NULLCHAR;
		session>open.sremotehost		= 0;
	} else {
		session>open.active			= TRUE;
		session>open.localport			= 1023;
		session>open.remoteport		= session>port;
		session>open.remotehost		= session>at;
		session>open.sremotehost		= 5;
	}
	session>rq_out++;
	lpd_checkerc( request( session>open));
}

*======================.============<  >===================================*
void tcp_open_connection_response( rq)
RQ_OPEN_TCP_CONNECTION	* rq;
{
	SESSION				* session;

	session = *(SESSION **)( ( (char *)rq) + SESSION_OFF_OPEN);
	session>rq_out;
	if( tcp_error( session, rq>rq.ercret)) {
		return;
	}
	session>nticks			= lpd_nticks;
	session>get.handle		= session>handle;
	session>send.handle	= session>handle;
	session>receive.handle	= session>handle;
	session>close.handle	= session>handle;
	session>abort.handle	= session>handle;
	tcp_get_tcb_request( session);
}

*======================.============<  >===================================*
void tcp_get_tcb_request( session)
SESSION					* session;
{
	if( session>gettcb_out) {
		session>rq_out++;
		session>gettcb_out = TRUE;
		if( session>used) {
			if( use_four) {
				session>tcb.notice_type = 4;
			} else {
				session>get.handle |= 0x800;
			}
		}
		lpd_checkerc( request( session>get));
	}
}

*======================.============<  >===================================*
void tcp_get_tcb_response( rq)
RQ_GET_TCB				* rq;
{
	SESSION				* session;

	session = *(SESSION **)( ( (char *)rq) + SESSION_OFF_GET);
	session>rq_out;
	session>gettcb_out = FALSE;
	if( rq>rq.ercret == ERC_CLOSE_RESET) {
		if( session>reset < 3) {
			session>reset++;
			tcp_open_connection_request( session);
			return;
		}
	}
	if( tcp_error( session, rq>rq.ercret)) {
		return;
	}
	if( session>aborting) {
		return;
	}
	if( session>used) {
		if( session>tcb.state == ESTABLISHED) {
			session>nticks = lpd_nticks;
			session>used = TRUE;
			tcp_receive_message_request( session);
			session_arrived( session);
		} else {
			tcp_get_tcb_request( session);
		}
	} else {
		session_count_check( session);
	}
}

*======================.============<  >===================================*
void tcp_receive_message_request( session)
SESSION					* session;
{
	session>receive.message		= session>in_buffer[session>sofar];
	session>receive.smessagemax	= session>total  session>sofar;
	session>receive.smessage		= session>in;
	session>receive.ssmessage		= 2;
	session>read_out = TRUE;
	session>rq_out++;
	lpd_checkerc( request( session>receive));
}

*======================.============<  >===================================*
void tcp_receive_message_response( rq)
RQ_RECEIVE_TCP_MESSAGE	* rq;
{
	SESSION				* session;

	session = *(SESSION **)( ( (char *)rq) + SESSION_OFF_RECEIVE);
	session>rq_out;
	if( tcp_error( session, rq>rq.ercret)) {
		return;
	}
	if( session>aborting) {
		return;
	}
	session>read_out = FALSE;
	session>sofar += session>in;
	session>counting = FALSE;

	if( session>total == session>sofar) {
		session>sofar = 0;
		if( session>type == SERVER) {
			server_receive( session);
		} else {
			agent_receive( session);
		}
	} else {
		tcp_receive_message_request( session);
	}
}

*======================.============<  >===================================*
void tcp_send_message_request( session)
SESSION					* session;
{
	if( session>write_out) {
		return;
	}
	session>send.message	= session>out_buffer;
	session>send.smessage	= session>size_out;
	session>rq_out++;
	session>write_out = TRUE;
	if( session>counting) {
		session>count += session>send.smessage;
	}
	lpd_checkerc( request( session>send));
}

*======================.============<  >===================================*
void tcp_send_message_response( rq)
RQ_SEND_TCP_MESSAGE		* rq;
{
	SESSION				* session;

	session = *(SESSION **)( ( (char *)rq) + SESSION_OFF_SEND);
	session>rq_out;
	session>write_out = FALSE;
	if( tcp_error( session, rq>rq.ercret)) {
		return;
	}
	if( session>aborting) {
		return;
	}
	session>nticks = lpd_nticks;
	session_sent( session);
}

*======================.============<  >===================================*
void tcp_close_connection_request( session)
SESSION					* session;
{
	session>rq_out++;
	lpd_checkerc( request( session>close));
}

*======================.============<  >===================================*
void tcp_close_connection_response( rq)
RQ_CLOSE_TCP_CONNECTION	* rq;
{
	SESSION				* session;

	session = *(SESSION **)( ( (char *)rq) + SESSION_OFF_CLOSE);
	session>rq_out;
	if( rq>rq.ercret == ERC_APP_CONN_CLOSED) {
		rq>rq.ercret = ERC_OK;
	}
	if( tcp_error( session, rq>rq.ercret)) {
		return;
	}
}

*======================.============<  >===================================*
void tcp_abort_connection_request( session)
SESSION					* session;
{
	session>rq_out++;
	session>abort.handle	= session>handle;
	lpd_checkerc( request( session>abort));
}

*======================.============<  >===================================*
void tcp_abort_connection_response( rq)
RQ_CLOSE_TCP_CONNECTION	* rq;
{
	SESSION				* session;

	session = *(SESSION **)( ( (char *)rq) + SESSION_OFF_ABORT);
	session>rq_out;
	if( tcp_error( session, rq>rq.ercret)) {
		return;
	}
}

= session>port;
		session>open.remotehost		= session>at;
		session>open.sremotehost		= 5;
	}
	session>rq_out++;
	lpd_checkerc( request( session