SRI-NOSC/ncpd/skt_util.c

#

/*	skt_util.c	*/

/*	globals declared in this file:
		n_s_left

	functions declared in this file:
		sm_dux
		sm_splx
		free_skt
		att_skt
		get_skt
		kill_skt
		init_skts
		clean_skt
*/


#include	"files.h"
#include	"hstlnk.h"
#include	"socket.h"
#include	"globvar.h"
#include	"kwrite.h"

/* SCCS PROGRAM IDENTIFICATION STRING */
char whatid_skt_util[] "~|^`skt_util.c\tV3.9E0\tJan78\n";

int	n_s_left	nsockets;	/* counter for allocating sockets */

/*name:
	sm_dux

function:
	given local and foreign base sockets, and a socket operation
	code ( init or listen), performs the operation on the pair of
	connections so defined, associating local with foreign+1
	and local+1 with foreign.

algorithm:
	compute local socket +1 via skt_off.
	compute foreign +1 via skt_off.
	do the operation to create a receive data socket using local and
	foreign+1 via sm_splx.
	do the operation to create a send data socket using local+1
	and foreign via sm_splx.

parameters:
	lbs_addr	address of local base socket.
	fbs_addr	address of foreign base socket.
	op		socket operation code (must be si_init or si_glsn
			{in which case fbs_addr must be a legal address
			but the content is irrelevant} or si_slsn).

returns:
	nothing.

globals:
	ksx_rcv
	ksx_xmit

calls:
	skt_off
	sm_splx

called by:
	fi_sktnm
	kr_odrct
	fi_rfnm

history:
	initial coding 1/6/75 by G. R. Grossman

*/

sm_dux(lbs_addr,fbs_addr,op)
char	*lbs_addr,*fbs_addr;
int	op;
{
	char	lskt_1[2],	/* holds local socket +1 */
		fskt_1[4];	/* holds foreign socket + 1 */

	skt_off(&lbs_addr[2],&lskt_1[2],1,2);	/* compute local socket +1
						   and store in lskt_1 */

		/* perform operation creating send data socket */
	sm_splx(&lskt_1[0],fbs_addr,ksx_xmit,op);

	skt_off(&fbs_addr[4],&fskt_1[4],1,4);	/* compute foreign socket +1
						   and store in fskt_1 */
		/* perform operation creating receive data socket */
	sm_splx(lbs_addr,&fskt_1[0],ksx_rcv,op);
}

/*name:
	sm_splx

function:
	creates a data socket given local and foreign sockets, socket type,
	and operation.

algorithm:
	set fields of skt_req:
		file pointer from global fp.
		socket type from parameter sinx.
		operation from parameter op.
		byte size 8.
		host from global host.
		if receive:
			link number via asn_lnkn.
		otherwise (send):
			link number to "null" (0377)	(1/10/75 GRG).
		local socket by copying thru parameter ls_addr.
		foreign socket by copying thru parameter fs_addr.
	create/match socket via get_skt.
parameters:
	ls_addr		pointer to local socket number.
	fs_addr		pointer to foreign socket number.
	sinx		socket type.
	op		socket operation code (see remarks under parameters
			for sm_dux).

returns:
	nothing.

globals:
	fp
	host
	skt_req=

calls:
	asn_lnkn
	get_skt

called by:
	sm_dux
	kr_odrct

history:
	initial coding 1/6/75 by G. R. Grossman
	null link # for send socket 1/10/75 by G. R. Grossman
_ifdef SFHBYTE
	added variable bytesize 01/27/78 by S. F. Holmgren
_endif

*/

sm_splx(ls_addr,fs_addr,sinx,op)
char	*ls_addr,*fs_addr;
int	sinx,op;
{
	register char	*sbp,		/* source pointer for copying
					   socket numbers */
			*dbp;		/* dest pointer for same */
	register int	n;		/* counter for same */

	skt_req.s_filep = fp;		/* set file pointer */
	skt_req.s_sinx = sinx;		/* socket type */
	skt_req.s_state = op;		/* socket operation */
#ifndef SFHBYTE
	skt_req.s_bysz = 8;		/* byte size */
#endif
#ifdef SFHBYTE
	skt_req.s_bysz = (fp->f_bysz == 0) ? 8 : fp->f_bysz;	/* byte size */
#endif
	skt_req.s_hstlnk.hl_host = host;/* host number */
	if ( (ls_addr[1] & 1) == 0 )	/* receive socket? */
		skt_req.s_hstlnk.hl_link = asn_lnkn();
			/* assign link number */
	else				/* send socket */
		skt_req.s_hstlnk.hl_link = 0377;	/* "null link #" */
	dbp = &skt_req.s_lskt[0];	/* set dest for socket number copy */
	sbp = ls_addr;			/* ditto for source */
	*dbp++ = *sbp++;		/* 1st byte of local socket */
	*dbp++ = *sbp++;		/* 2nd  "   "    "      "   */
	sbp = fs_addr;			/* set source for foreign socket */
	for (n = 4 ; n ; --n )		/* copy loop */
		*dbp++ = *sbp++;
	get_skt();			/* go do it to the socket */
}

/*name:
	free_skt

function:
	detaches a socket from its file and de-allocates it.

algorithm:
	if the socket is attached to a file:
		detach via fi_sgone.
	increment socket allocation counter.
	set socket state to null ( this makes it available).

parameters:
	skt_p	pointer to socket struct to be detached and deallocated.

returns:
	nothing.

globals:
	n_s_left=

calls:
	fi_sgone

called by:
	cls_q
	cls_clsw
	clo_lsn
	clo_c2cw

history:
	initial coding 1/6/75 by G. R. Grossman
	modified by greep to clear timeout

*/

free_skt(skt_p)
struct socket	*skt_p;
{
	register struct socket	*s_p;

	s_p = skt_p;
	s_p->s_timeo = 0;               /* clear timeout value */
	if ( s_p->s_filep != 0 )	/* attached to file? */
		fi_sgone(s_p);		/* detach */
	n_s_left =+ 1;			/* increment socket allocation
					   counter */
	s_p->s_state = ss_null;		/* set struct to null state, thus
					   deallocating it */
}

/*name:
	att_skt

function:
	attaches a socket to its file.

algorithm:
	the file pointer is obtained from the socket struct.
	the file's appropriate f_skt_x byte is set according to the
	socket's s_sinx field and the socket struct's index.
	the file's attached socket counter is incremented.

parameters:
	skt_p	pointer to socket struct to be attached to its file.

returns:
	nothing.

globals:
	sockets

calls:
	nothing.

called by:
	lsint_q
	so_ulsn

history:
	initial coding 1/6/75 by G. R. Grossman

*/

att_skt(skt_p)
struct socket	*skt_p;
{
	register struct socket	*s_p;	/*points to socket struct */
	register struct file	*f_p;	/* points to associated file struct */

	s_p = skt_p;
	f_p = s_p->s_filep;		/* get pointer to file */
	f_p->f_skt_x[s_p->s_sinx] = s_p - &sockets[0];
		/* set appropriate socket index in file; we use C's
		   conversion facilities to compute index */
	f_p->f_nsatt++;			/* increment file's attached socket
					   count */
}

/*name:
	get_skt

function:
	attempts to fulfill the request in skt_req by finding a socket
	struct in sockets whose local socket matches that is skt_req
	and calling the appropriate procedure thrugh skt_oper.
	if the above fails, calls the appropriate procedure through
	so_unm.

algorithm:
	loop through all socket structs:
		if the socket state is not null and the local sockets match:
			if the procedure called through skt_oper indexed
			by the states of skt_req and the current socket
			returns a non-zero value:
				return.
	if all socket structs are exhausted without terminating:
		call "unmatch" procedure through so_unm indexed by
		state of skt_req.

parameters:
	none.

returns:
	nothing.

globals:
	sockets
	skt_oper
	skt_req
	so_unm

calls:
	those procedures pointed to by:
		skt_oper
		so_unm

called by:
	hr_rfc
	hr_cls
	kr_ouicp
	sm_splx
	kr_osicp

history:
	initial coding 1/6/75 by G. R. Grossman

*/

get_skt()
{
	register struct socket	*p;	/* will point to socket structs
					   as we examine them */

	for ( p = &sockets[0] ; p < &sockets[nsockets] ; p++ )	/* loop thru 
								   all skts */
		if ( (p->s_state != ss_null)		/* socket in use? */
		     && (p->s_lskt->word == skt_req.s_lskt->word) )
							/* and locals match? */
			if ( (*skt_oper[skt_req.s_state][p->s_state])(p) )
				/* did op procedure return non-zero? */
				return;		/* all done if so */
	(*so_unm[skt_req.s_state])(p);	/* if fell out of loop, no match,
					   call appropriate unmatched proc */
}

/*name:
	kill_skt

function:
	performs the "kill" operation on a socket. this operation is
	used when the ncp daemon spontaneously decides to close a connection
	without prior close action by the user program or the foreign host.

algorithm:
	the appropriate procedure is called by indexing skt_oper with
	the kill op code and the state of the socket.

parameters:
	skt_p	pointer to the socket struct to be killed.

returns:
	nothing.

globals:
	skt_oper
	si_kill

calls:
	"kill" procedures in skt_oper.

called by:
	fi_sktnm
	fi_sgone
	fi_all
	fi_rfnm
	ir_re_x

history:
	initial coding 1/6/75 by G. R. Grossman

*/

kill_skt(skt_p)
struct socket	*skt_p;
{
	(*skt_oper[si_kill][skt_p->s_state])(skt_p);
}

/*name:
	init_skts

function:
	initializes socket structs at program initialization.

algorithm:
	loop thru all socket structs:
		set socket state to null.

parameters:
	none.

returns:
	nothing.

globals:
	sockets
	nsockets
	ss_null

calls:
	nothing.

called by:
	main

history:
	initial coding 1/8/75 by G. R. Grossman

*/

init_skts()
{
	register struct socket	*s_p;	/* will point to sockets as we
					   initialize them */

	for ( s_p = &sockets[0] ; s_p < &sockets[nsockets] ; s_p++ )
			/* loop thru all socket structs */
		s_p->s_state = ss_null;		/* set state to null */
}

/*name:
	clean_skt

function:
	clean up the local socket number
	clean up the foreign socket number
	clcean up the host and link numbers

algorithm:
	if state is ss_clow
		zero things of awhile

parameters:
	skt_p	-	address of a socket to be cleaned

returns:
	nothing

globals:
	none

calls:
	nothing

called by:
	cls_rfcw
	cls_cacw
	so_ut1
	so_ut2

history:
	initial coding 7/7/76 by S. F. Holmgren

*/
clean_skt( skt_p )
struct socket *skt_p;
{
	register char *sp;

	if( skt_p->s_state == ss_clow )		/* close wait? */
		for( sp = skt_p; sp < &skt_p->s_state; *sp++ = 0 );
}