SRI-NOSC/ncpk/nrdwr.c

Compare this file to the similar file:
Show the results in this format:

#
#include "param.h"
#include "net_net.h"
#include "inode.h"
#include "buf.h"
#include "user.h"
#include "net_hosthost.h"
#include "file.h"
#include "reg.h"

#ifdef SCCSID
/* SCCS PROGRAM IDENTIFICATION STRING */
char id_nrdwr[] "~|^`nrdwr.c\tV3.9E2\t09Mar78\n";
#endif

/* if CLOSE0 is defined you get zero bytes read on end of netfile.
If CLOSE0 is not defined, you get -1 returned on end of netfile.
Write on end of netfile still returns error.
*/
#define CLOSE0 X
/*name:
	netread

function:
	to handle user reads on a file previously opened with netopen

algorithm:
	if there is a socket
		while there is no data and the connection is open
		sleep
	
		if the connection is open
			transfer the min of the num in the queue and the num
			the user asked for into his space
			send a reallocation for the amount of data read
			into user space
			tell user that that much has been transfered
			make the amount in the queue correct

parameters:
	aip	-	a pointer to a socket( i_addr part of an inode )
			that is type read.

returns:
	nothing

globals:
	none

calls:
	min
	sleep
	bytesout
	sendalloc
	spl_imp

called by:
	rdwr of ken/sys2.c

history:
	7Jan75	S.F.Holmgreg initial coding
	15Mar77	S.M.Abraham to set and clear n_rcvwt flag bit
	14Jun77	J.S.Kravitz to return if u.u_count == 0
	14Jun77	J.S.Kravitz to not reallocate on closed
		connection
_ifdef SFHBYTE
	added multiple of 8 bytesizes 01/27/78 S. F. Holmgren
_endif

*/

netread( aip )		/* handles user reads -- called from rdwr of */
struct inode *aip;	   /*net/sys/sys2.c  */
{

register amt;
register struct rdskt *sktp;
register tries;
extern int lbolt;


	sktp = aip;	/* for speed */
	/* is this a valid socket pointer */
	if( sktp == 0 )
	{
		err:
		u.u_error = EBADF;
		return;
	}
	if ( ! u.u_count)
		return;

	tries = 0;
	sktp->r_rdproc = u.u_procp;
	retry:
	spl_imp();	/* so i get to sleep before anyone can wake me */
	while (	( (amt=min(sktp->r_qtotal,u.u_count)) == 0)
	&&	(sktp->r_flags&n_open)
	) {
		sktp -> r_flags =| n_rcvwt ; /* mark skt as waiting for data */
		sleep( sktp,NETPRI );
		sktp -> r_flags =& ~n_rcvwt; /*skt not waiting for data */
	}
	spl0();

	/* wait for data still trickling in even though conn closed */
	if( amt == 0 && tries == 0 )
	{
		/* so we dont do this again */
		tries++;
		/* sleep for 4 seconds */
		sleep( &lbolt,NETPRI );
		/* there still no data? */
		if( sktp->r_qtotal == 0 )
#ifndef CLOSE0
			goto err;		/* yep then say done */
#endif not CLOSE0
#ifdef CLOSE0
			return;		/* yep then say done */
#endif CLOSE0
		else
			goto retry;		/* ahh some data then get it */
	}
	if( amt > 0 )
	{
#ifdef SFHBYTE
		amt =* sktp->r_bsize/8;	/* go to 8 bit bytes */
#endif
		amt =- bytesout( &sktp->r_msgq,u.u_base,amt,0 );	/* give user data */
#ifdef SFHBYTE
		amt = (amt*8)/sktp->r_bsize;	/* go to byte size bytes */
#endif
		u.u_count =- amt;
		if (sktp->r_flags & n_open)
			sendalloc( sktp,amt );
		sktp->r_qtotal =- amt;		/* decrement queued total */
	}
#ifndef CLOSE0
	else
		goto err;

#endif not CLOSE0
}

/*name:
	netwrite

function:
	to handle user writes on a file opened with netopen

algorithm:
	is there a socket and has the user specified a non zero count
		while there is no allocation and the connection is open
			sleep
		if the connection is open
			send as many bytes as the allocation will permit
			wait for the rfnm to return( this is probably not the 
			place to wait for a rfnm )
			if there was an error then resend the data
			update the address and count of data still to be
			sent

			decrement the amount of allocation available from
			the foreign host.

parameters:
	aip	-	a pointer to a socket of type write

returns:
	nothing	( well really the fact that data was sent to the net )

globals:
	none

calls:
	annyalloc
	spl_imp
	min
	sleep
	sndnetbytes
	netsleep
	dpsub

called by:
	rdwr of ken/sys2.c

history:
	initial coding 1/7/75 by S. F. Holmgren
	added bse, cnt, and flg params for server telnet.
	8/26/76 by S. F. Holmgren
	modiefied 3/15/77 by SMA to set and reset n_sendwt,
	n_allwt, and n_prevmerr
	12Jun77 server telnet test code deleted from ncp. Specifically,
		.. bse,cnt,flg are now obtained from the U again, instead
		of as parameter. J.S.Kravitz
	12Jun77 Comment on spl_imp changed J.S.Kravitz
_ifdef SFHBYTE
	modified to add multiple of 8 bit bytesize 01/27/78 S. F. Holmgren
_endif

*/

netwrite( aip )
struct wrtskt *aip;
{

register struct wrtskt *sktp;
register n;


sktp = aip;		/* for speed */
if ( sktp == 0 ) return;
while( u.u_count > 0 )
{
	sktp->w_wrtproc = u.u_procp;
	/*
	 * in order to assure that the allocation doesn't arrive before
	 * we get to sleep, we shut imp interface interrupts off here
	 * for a moment
	 */
	spl_imp();
	while(	(n=min( anyalloc(sktp),u.u_count) ) == 0
	&&	(sktp->w_flags & n_open))
	{
		sktp -> w_flags =| n_allwt ; /* mark skt as waiting for ALL */
		sleep( sktp,NETPRI );
		sktp -> w_flags =& ~n_allwt ; /* skt no longer waiting */
	}
	spl0();

	if (sktp->w_flags & n_open)	/* connection still open */
	{
		retry:
			/* send as much as allocation will permit */
			sndnetbytes ( u.u_base
				,n
				,sktp
				,(sktp->w_hostlink & ~0200)
				,0
				);

			/* wait for rfnm to return */
			if( netsleep( sktp,n_rfnmwt ) & n_xmterr )
				/* if got trans err send again */
			{
				sktp -> w_flags =| n_prevmerr ; /* note error */
				goto retry;
			}
			else /* no error, so send operation complete */
				sktp -> w_flags =& ~(n_prevmerr | n_sendwt) ;

#ifndef SFHBYTE
			u.u_base =+ n;
#endif
#ifdef SFHBYTE
			u.u_base =+ n*(sktp->w_bsize/8);
#endif
			u.u_count =- n;

			/* update allocation from foreign host */
			sktp->w_msgs =- 1;
#ifndef SFHBYTE
			dpsub( sktp->w_falloc, (n<<3) );
#endif
#ifdef SFHBYTE
			dpsub( sktp->w_falloc, (n*sktp->w_bsize) );
#endif
	}
	else
	{
		u.u_error = EBADF;
		return;
	}
}
}
/*name:
	anyalloc

function:
	returns = 	0 if there is no allocation from the foreign host
	        =	1000 if >= 1000 bytes are allocated( max net msg size )
	        =	number of bytes allocated if none of the above

algorithm:
	if number of messages allocated is zero return zero
	if the high word of the two word allocate is non zero
	or
	the low word of the allocation is greater or equal to 8000
	then return 1000 
	otherwise
		return the number of bytes allocated

parameters:
	pointer to a write socket( i_addr part of an inode )

returns:
	see function

globals:
	none

calls:
	nothing

called by:
	netwrite

history:
	initial coding 1/7/75 by S. F. Holmgren
_ifdef SFHBYTE
	added multiple of 8 bit bytesizes 01/27/78 S. F. Holmgren
_endif

*/

anyalloc( wsp )
struct wrtskt *wsp;
{
				/*  called from netwrite  */

	register struct wrtskt *sktp;
	sktp = wsp;
	if (sktp->w_msgs == 0)	/* any msg allocation ? */
		return( 0 );	/* no return zero allocation */
	if ( sktp->w_falloc[0] != 0  ||  sktp->w_falloc[1] >= 8000)
#ifndef SFHBYTE
		return( 1000 );	/* there are at least 1000 bytes so return that  */
	return( (sktp->w_falloc[1]>>3) & 017777); /* return num of bytes alloced */
#endif
#ifdef SFHBYTE
		return( 8000/sktp->w_bsize );
	return( sktp->w_falloc[1]/sktp->w_bsize );	/* return num bytes alloced */
#endif

}



/*name:
	netsleep

function:
	will sleep on the socket( asp ) until one of n_xmterr or n_eof
	or flg get set

algorithm:
	while none of the above mentioned bits are set
	sleep
	determine which bit has been set and return it

parameters:
	asp	-	pointer to a socket
	flg	-	a bit or set of bits to wait for

returns:
	the bit set by the other potions of the system

globals:
	none

calls:
	sleep
	spl_imp

called by:
	netwrite

history:
	initial coding 1/7/75 by S. F. Holmgren
	update of procp value added (from abraham's copy 9may77)

*/

netsleep( asp,flg )
struct wrtskt *asp;
{

	register struct wrtskt *sktp;
	register result;

	sktp = asp;
	sktp -> w_wrtproc = u.u_procp;
	
	spl_imp();	/* see comments on spl_imp's in netread and netwrite */

	while (( sktp->w_flags&(n_xmterr | n_eof | flg)) == 0)
		sleep( sktp,NETPRI );
	spl0();

	result = sktp->w_flags;
	sktp->w_flags =& ~(n_xmterr|n_eof|flg);
	
	return( result & (n_xmterr|n_eof|flg) );

}

/*name:
	sendalloc

function:
	to determine if a re-allocation is needed and if so send a host
	to host allocate in the amount of the difference between hiwat
	and bytes and msgs

algorithm:
	decrement the number of bytes read from bytes allocated
	if the number of bytes allocated is less than 1/2 the number
	in hiwat( a variable parameter ) or the number of messages
	allocated is zero
	send an allocation
		get the hostnumber
		wait for any rfnms out on link zero for that host
		format the allocate protocol
		send it off 

parameters:
	asp	-	a socket pointer(read socket)
	amtread	-	number of bytes transferred into user space

returns:
	0 if no allocation sent
	1 if allocation sent

globals:
	none

calls:
	bit_on
	set_bit
	sndnetbytes
	swab
	spl_imp

called by:
	netread
	tsrvread	(newsrvtel.c)

history:
	initial coding 1/7/75 by S. F. Holmgren
	modified to return allocation indication, and saves current PS
	8/27/76 by S. F. Holmgren
	modified, 3/15/77, S.M.Abraham to set and reset n_hhchanwt
	modified, 6/30/77, J.S.Kravitz to use nominal message allocation
		of NOMMSG instead of nom byte alloc for messages
		comment on wait for rfnm added
_ifdef SFHBYTE
	added multiple of 8 bit bytesize 01/27/78 S. F. Holmgren
_endif

*/

sendalloc( asp,amtread )
struct rdskt *asp;
int amtread;
{

	register struct rdskt *sktp;
	register amt;
	register int sps;
	char host;			/* for storing host num to send alloc to */

	struct
	{
		char all;
		char alink;
		int amsgs;
		int abits[2];
	} sndalloc;


	
	sktp = asp;
	sktp->r_bytes =- amtread;
	if (	(sktp->r_bytes <= (sktp->r_hiwat>>1) )
	||  	( sktp->r_msgs <= (NOMMSG/2) )	)
	/*
	 * Don't allow allocation to go below 50 % bytes or
	 * messages if user is still reading from connection
	 */
	{
		host = (sktp->r_hostlink >> 8);

		sps = PS->integ;		/* save current prio */
		/*
		 * wait for link zero to this host to be free... note
		 * that send_alloc will not resend an allocate if there
		 * is a transmission error.
		 */
		spl_imp();
			while( bit_on( host_map,host ) != 0 )
			{
				sktp -> r_flags =| n_hhchanwt;/*note the wait*/
				sleep( host_map+host,NETPRI );
				sktp -> r_flags =& ~n_hhchanwt;/*not waiting*/
			}
			/* i win quick set rfnm bit */
			set_bit( host_map,host );
		PS->integ = sps;		/* restore prev PS */

		/* we now have a rfnm back from the host send an allocate */
		sndalloc.all = hhall;
		sndalloc.alink = sktp->r_hostlink;
		sndalloc.amsgs = swab( amt = NOMMSG - sktp->r_msgs );
		sktp->r_msgs =+ amt;	/* update to amount of msgs re allocated */
		/*
		 * this allocation thing here should be recoded using
		 * long integers, since the shift could cause very large
		 * allocations to get screwed up when the bits fall off
		 * the left side of the low order word
		 */
		sndalloc.abits[0] = 0;
		sndalloc.abits[1] = 
#ifndef SFHBYTE
			swab ( (amt = sktp->r_hiwat - sktp->r_bytes) << 3 );
#endif
#ifdef SFHBYTE
			swab( (amt = sktp->r_hiwat - sktp->r_bytes) * sktp->r_bsize );
#endif
		sktp->r_bytes =+ amt;	/* update to amount of bytes reallocated */
		sndnetbytes( &sndalloc,8,sktp,0,1 );
		return( 1 );		/* say we sent an allocaiton*/
	}
	return( 0 );			/* say we didnt send an allocation*/
	
}
/*name:
	sendins

function:
	send a host to host ins command. initiated at request of user

algorithm:
	get pointer to file passed
	if null then return
	build ins
	send to the net

parameters:
file id passed down from user in r0

returns:
	nothing

globals:
	none

calls:
	getf	(sys)
	sndnetbytes

called by:
	trap thru sysent

history:
	initial coding 11/6/75 by S. F. Holmgren

*/

sendins()
{
	register int *fp;
	register int *sktp;

	struct
	{
		char ins;
		char link;
	} sndins;

	if( (fp=getf( u.u_ar0[R0] )) == NULL )
	{
		u.u_error = EBADF;
		return;
	}
	if ( ! (fp->f_flag & FNET) )
	{
		u.u_error = ENOTNET;
		return;
	}

	sktp = fp->f_netnode[ f_wrtnode ];
	sndins.ins = hhins;
	sndins.link = sktp->w_hostlink & ~0200;
	sndnetbytes( &sndins, 2, sktp, 0, 1 );
}