include lpd.h

SESSION					* sessions[2];

unsigned				session_out[2];

extern SESSION			* server_session;

*======================.============<  >===================================*
unsigned session_index( type, address, port)
int						type;
unsigned long			address;
unsigned				port;
{
	SESSION				* session;

	for( session = sessions[type]; session = NULLSESSION;
			session = session>next) {
		if( ( session>address == address)  (session>port == port)) {
			if( session>aborting) {
				continue;
			}
			return( session>index);
		}
	}
	return( 0);
}

*======================.============<  >===================================*
unsigned session_name( type, pb, cb)
int						type;
unsigned char			* pb;
unsigned				cb;
{
	SESSION				* session;

	if( cb > 0) {
		for( session = sessions[type]; session = NULLSESSION;
				session = session>next) {
			if( session>snode == cb) {
				if( strncmpi( pb, session>node, cb) == 0) {
					if( session>aborting) {
						continue;
					}
					return( session>index);
				}
			}
		}
	}
	return( 0);
}

*======================.============<  >===================================*
SESSION * session_lookup( type, index)
int						type;
unsigned				index;
{
	SESSION				* session;

	for( session = sessions[type]; session = NULLSESSION;
			session = session>next) {
		if( session>index  index) {
			break;
		}
	}
	return( session);
}

*======================.============<  >===================================*
SESSION * session_create( type, address, port)
int						type;
unsigned long			address;
unsigned				port;
{
	SESSION				* session;
	unsigned			i = 1;
	unsigned			save_lpd_number;

	goto byover;
over:
	if( i < 0x8000) {
		i = i << 1;
	} else {
		return( NULLSESSION);
	}
byover:
	for( session = sessions[type]; session = NULLSESSION;
			session = session>next) {
		if( session>index == i) {
			goto over;
		}
	}
	if( ( session = (SESSION *)calloc( 1, sizeof( SESSION))) = NULLSESSION) {
		session>nticks = lpd_nticks;
		session>type = type;
		listaddtohead( sessions[type], session);
		save_lpd_number = lpd_usernumber;
		if( sp_os) {
			if( lpd_usernumber == 0) {
				lpd_usernumber = 1;
			}
		}
		session_out[session>type]++;
		session>this = session;
		session>index = i;
		session>exchange = exchanges[type];
		session>address = address;
		session>port = port;
		session>at = '@';


		if( ( session>address == tcp_ipaddr)  ( type == AGENT)) {
			return( session);
		}
		session>open.rq.scntinfo		= 14;
		session>open.rq.rtcode			= 0;
		session>open.rq.nreqpbcb		= 2;
		session>open.rq.nresppbcb		= 1;
		session>open.rq.usernum		= lpd_usernumber;
		session>open.rq.exchresp		= session>exchange;
		session>open.rq.ercret			= 0;
		session>open.rq.rqcode			= OPEN_TCP_CONNECTION_NO_WAIT;
		session>open.index				= session>index;
		session>open.timeout			= 0;
		session>open.precedence		= 0;
		session>open.security			= 0;
		session>open.reserved			= 0;
		session>open.options			= NULLCHAR;
		session>open.soptions			= 0;
		session>open.handle			= session>handle;
		session>open.shandle			= 2;

		session>get.rq.scntinfo		= 4;
		session>get.rq.rtcode			= 0;
		session>get.rq.nreqpbcb		= 0;
		session>get.rq.nresppbcb		= 2;
		session>get.rq.usernum			= lpd_usernumber;
		session>get.rq.exchresp		= session>exchange;
		session>get.rq.ercret			= 0;
		session>get.rq.rqcode			= GET_TCB;
		session>get.index				= session>index;
		session>get.tcb				= session>tcb;
		session>get.stcbmax			= sizeof( TCB_RETURNED);
		session>get.stcb				= session>stcb;
		session>get.sstcb				= 2;

		session>send.rq.scntinfo		= 6;
		session>send.rq.rtcode			= 0;
		session>send.rq.nreqpbcb		= 1;
		session>send.rq.nresppbcb		= 0;
		session>send.rq.usernum		= lpd_usernumber;
		session>send.rq.exchresp		= session>exchange;
		session>send.rq.ercret			= 0;
		session>send.rq.rqcode			= SEND_TCP_MESSAGE;
		session>send.index				= session>index;
		session>send.push				= FALSE;
		session>send.urgent			= FALSE;

		session>receive.rq.scntinfo	= 4;
		session>receive.rq.rtcode		= 0;
		session>receive.rq.nreqpbcb	= 0;
		session>receive.rq.nresppbcb	= 4;
		session>receive.rq.usernum		= lpd_usernumber;
		session>receive.rq.exchresp	= session>exchange;
		session>receive.rq.ercret		= 0;
		session>receive.rq.rqcode		= RECEIVE_TCP_MESSAGE;
		session>receive.index			= session>index;
		session>receive.push			= session>push;
		session>receive.spush			= 1;
		session>receive.urgent			= session>urgent;
		session>receive.surgent		= 1;

		session>close.rq.scntinfo		= 4;
		session>close.rq.rtcode		= 0;
		session>close.rq.nreqpbcb		= 0;
		session>close.rq.nresppbcb		= 0;
		session>close.rq.usernum		= lpd_usernumber;
		session>close.rq.exchresp		= session>exchange;
		session>close.rq.ercret		= 0;
		session>close.rq.rqcode		= CLOSE_TCP_CONNECTION;
		session>close.index			= session>index;

		session>abort.rq.scntinfo		= 4;
		session>abort.rq.rtcode		= 0;
		session>abort.rq.nreqpbcb		= 0;
		session>abort.rq.nresppbcb		= 0;
		session>abort.rq.usernum		= lpd_usernumber;
		session>abort.rq.exchresp		= session>exchange;
		session>abort.rq.ercret		= 0;
		session>abort.rq.rqcode		= ABORT_TCP_CONNECTION;
		session>abort.index			= session>index;

		lpd_usernumber = save_lpd_number;

		session>total = 1;
		session>sofar = 0;
		
		tcp_open_connection_request( session);
		return( session);
	}
	return( NULLSESSION);
}

*======================.============<  >===================================*
void session_receive( session)
SESSION					* session;
{
	tcp_receive_message_request( session);
}	

*======================.============<  >===================================*
void session_send( session)
SESSION					* session;
{
	tcp_send_message_request( session);
}

*======================.============<  >===================================*
void session_sent( session)
SESSION					* session;
{
	session>size_out = 0;
	
	if( session>type == SERVER) {
		server_sent( session);
	} else {
		agent_sent( session);
	}
}

*======================.============<  >===================================*
void session_arrived( session)
SESSION					* session;
{
	if( session>type == SERVER) {
		session>address = session>tcb.conn.remote.address;
		session>port = session>tcb.conn.remote.port;
		ipaddresstohostname( session>address,
				session>node, 12, session>snode);
		if( session == server_session) {
			server_session = session_create( SERVER, 0l, lpd_port);
		}
		session_sent( session);
	} else {
		agent_receive( session);
	}
}

*======================.============<  >===================================*
void session_free( session)
SESSION					* session;
{
	if( session>type == SERVER) {
		if( session == server_session) {
			server_session = session_create( SERVER, 0l, lpd_port);
		}
	}
	listremove( sessions[session>type], session);
	free( session);
}

*======================.============<  >===================================*
void session_count_check( session)
SESSION					* session;
{
	if( session>counting) {
		if( session>count_ok) {
			session>count_ok = TRUE;
			session>count += session>tcb.sndcnt;
		} else {
			if( session>count == session>tcb.sndcnt) {
				tcp_error( session, ERC_LPD_TIMEOUT);
			} else {
				session>counting = FALSE;
				session>count = 0;
				session>count_ok = FALSE;
			}
		}
	}
}

*======================.============<  >===================================*
void session_count_zero( session)
SESSION					* session;
{
	session>nticks = lpd_nticks;
	if( session>gettcb_out) {
		if( session>counting) {
			session>counting = TRUE;
			session>count_ok = FALSE;
			session>count = 0;
			tcp_get_tcb_request( session);
		} else if( session>count_ok) {
			tcp_get_tcb_request( session);
		}
		return;
	}
	tcp_error( session, ERC_LPD_TIMEOUT);
}

 OPEN_TCP_CONNECTION_NO_WAIT;
		session>open.index				= session>index;
		session>open.timeout			= 0;
		session>open.precedence		= 0;
		session>open.security			= 0;
		session>open.reserved			= 0;
		session>open.options			= NULLCHAR;
		session>open.soptions			= 0;
		session>open.handle			= session>ha