⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clnt_kudp.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic	char	*sccsid = "@(#)clnt_kudp.c	4.3	(ULTRIX)	2/28/91";#endif lint/************************************************************************ *									* *			Copyright (c) 1986 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* *	Portions of this software have been licensed to  *	Digital Equipment Company, Maynard, MA. *	Copyright (c) 1986 Sun Microsystems, Inc.  ALL RIGHTS RESERVED. *//* * clnt_kudp.c * Implements a kernel UDP/IP based, client side RPC. *//* * *   Modification history: * * 29 Jan 91 -- chet *	Make kernel RPC calls interruptible. * * 10 Dec 89 -- chet *	Add arphasmbuf() call in clntkudp_callit() after timeouts *	to free an mbuf on the arpresolve trash heap (avoids long sleeps). * *  30 May 88 -- U. Sinkewicz *	Added SO_LOCK to replace smp_lock(&so->lk_socket, LK_RETRY) *	as part of an smp bug fix.  Fix guarantees that socket doesn't  *	change while unlocked during sleeps or for the lock heirarchy. * *  1 Sep 88 -- chet *	Remove transaction ID - it's now in the client handle *	passed down from the application * * 06-Jun-88	condylis *	Added SMP locking for clntkudpxid and mbuf data contained in *	outbuf member of cku_private structure.  New routine to  *	initialize rpc smp locks (rpcinit).  Added interaction with *	socket locks.  Added SMP locking of RPC client statistics. * * 12-11-87	Robin L. and Larry C. and Ricky P. *	Added new kmalloc memory allocation to system. * * 02-Mar-87 -- logcher *	Merged in diskless changes, added checks for null pointers *	in clntkudp_create */#include "../h/param.h"#include "../h/systm.h"#include "../h/user.h"#include "../h/kernel.h"#include "../h/proc.h"#include "../h/socket.h"#include "../h/socketvar.h"#include "../h/mbuf.h"#include "../net/if.h"#include "../net/route.h"#include "../netinet/in.h"#include "../netinet/in_pcb.h"#include "../rpc/types.h"#include "../rpc/xdr.h"#include "../rpc/auth.h"#include "../rpc/clnt.h"#include "../rpc/rpc_msg.h"#include "../h/smp_lock.h"struct mbuf	*ku_recvfrom();int		ckuwakeup();enum clnt_stat	clntkudp_callit();void		clntkudp_abort();void		clntkudp_error();bool_t		clntkudp_freeres();bool_t		clntkudp_control();void		clntkudp_destroy();void		xdrmbuf_init();/* * Operations vector for UDP/IP based RPC *//* static */ struct clnt_ops udp_ops = {	clntkudp_callit,	/* do rpc call */	clntkudp_abort,		/* abort call */	clntkudp_error,		/* return error status */	clntkudp_freeres,	/* free results */	clntkudp_destroy,	/* destroy rpc handle */	clntkudp_control	/* the ioctl() of rpc */};/* * Private data per rpc handle.  This structure is allocated by * clntkudp_create, and freed by cku_destroy. */struct cku_private {	u_int			 cku_flags;	/* see below */	CLIENT			 cku_client;	/* client handle */	int			 cku_retrys;	/* request retrys */	struct socket		*cku_sock;	/* open udp socket */	struct sockaddr_in	 cku_addr;	/* remote address */	struct rpc_err		 cku_err;	/* error status */	XDR			 cku_outxdr;	/* xdr routine for output */	XDR			 cku_inxdr;	/* xdr routine for input */	u_int			 cku_outpos;	/* position of in output mbuf */	char			*cku_outbuf;	/* output buffer */	char			*cku_inbuf;	/* input buffer */	struct mbuf		*cku_inmbuf;	/* input mbuf */	struct ucred		*cku_cred;	/* credentials *//* SMP lock for protecting mbuf	data of cku_private	 * This lock is used with CKU_BUFBUSY and CKU_BUFWANTED flags */	struct	lock_t	cku_lk_outbuf;};/* SMP lock for xids contained in client handles	*/struct	lock_t	lk_rpcxid;struct {	int	rccalls;	int	rcbadcalls;	int	rcretrans;	int	rcbadxids;	int	rctimeouts;	int	rcwaits;	int	rcnewcreds;	int	rcbadverfs;} rcstat;#define	ptoh(p)		(&((p)->cku_client))#define	htop(h)		((struct cku_private *)((h)->cl_private))/* cku_flags */#define	CKU_TIMEDOUT	0x001#define	CKU_BUSY	0x002#define	CKU_WANTED	0x004#define	CKU_BUFBUSY	0x008#define	CKU_BUFWANTED	0x010#define CKU_ONCE_ONLY	0x020/* Times to retry */#define	RECVTRIES	2#define	SNDTRIES	4/* Need the externs for rpcinit routine 	*/extern	struct lock_t	lk_rpccallout;extern	struct lock_t	lk_rpcdupreq;extern	struct lock_t	lk_rpcrqcred;extern	struct lock_t	lk_nfsstat;clntkudp_once(cl, flag)	CLIENT  *cl;{	struct cku_private *p = (struct cku_private *)cl->cl_private;	if (flag != 0) {		p->cku_flags |= CKU_ONCE_ONLY;	} else {		p->cku_flags &= ~CKU_ONCE_ONLY;	}}staticnoop(){}staticbuffree(p)	struct cku_private *p;{	int	s;	s = splimp();	smp_lock(&p->cku_lk_outbuf, LK_RETRY);	p->cku_flags &= ~CKU_BUFBUSY;	if (p->cku_flags & CKU_BUFWANTED) {		p->cku_flags &= ~CKU_BUFWANTED;		wakeup((caddr_t)&p->cku_outbuf);	}	smp_unlock(&p->cku_lk_outbuf);	splx(s);}/* * Create an rpc handle for a udp rpc connection. * Allocates space for the handle structure and the private data, and * opens a socket.  Note sockets and handles are one to one. */CLIENT *clntkudp_create(addr, pgm, vers, retrys, cred)	struct sockaddr_in *addr;	u_long pgm;	u_long vers;	int retrys;	struct ucred *cred;{	register CLIENT *h;	register struct cku_private *p;	int error = 0;	struct rpc_msg call_msg;	struct mbuf *m, *mclgetx();	extern int nfs_portmon;#ifdef RPCDEBUG	rpc_debug(4, "clntkudp_create(%X, %d, %d, %d\n",	    addr->sin_addr.s_addr, pgm, vers, retrys);#endif	kmem_alloc(p, struct cku_private *, (u_int)sizeof *p, KM_RPC);	if(p == NULL)		panic("clntkudp_create: kmem_alloc returns 0");	h = ptoh(p);	/* handle */	h->cl_ops = &udp_ops;	h->cl_private = (caddr_t) p;	h->cl_auth = authkern_create();	/* call message, just used to pre-serialize below */	call_msg.rm_xid = 0;	call_msg.rm_direction = CALL;	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;	call_msg.rm_call.cb_prog = pgm;	call_msg.rm_call.cb_vers = vers;	/* private */	clntkudp_init(h, addr, retrys, cred);	kmem_alloc(p->cku_outbuf, char *, (u_int)UDPMSGSIZE, KM_RPC);	if(p->cku_outbuf == NULL)		panic("clntkudp_create: kmem_alloc returns 0 for p->cku_outbuf");	/* Initialize SMP lock for mbuf data buffer		*/	lockinit(&p->cku_lk_outbuf, &lock_cku_d);	m = mclgetx(noop, 0, p->cku_outbuf, UDPMSGSIZE, M_DONTWAIT);	if (m == NULL)		goto bad;	xdrmbuf_init(&p->cku_outxdr, m, XDR_ENCODE);	/* pre-serialize call message header */	if (! xdr_callhdr(&(p->cku_outxdr), &call_msg)) {		printf("clntkudp_create - Fatal header serialization error.");		(void) m_freem(m);		goto bad;	}	p->cku_outpos = XDR_GETPOS(&(p->cku_outxdr));	(void) m_free(m);	/*	 * Open udp socket.	 *	 * We must clear u.u_error after calling socreate() because	 * socreate calls suser() which may set u.u_error as a side	 * effect.  This is really a bug in socreate() which should	 * be fixed someday, but for now we just patch things up here.	 */	error = socreate(AF_INET, &p->cku_sock, SOCK_DGRAM, IPPROTO_UDP);	u.u_error = 0;		/* XXX */	if (error) {		printf("clntkudp_create: socket creation problem, %d", error);		goto bad;	}	if (error = bindresvport(p->cku_sock)) {		printf("clntkudp_create: socket bind problem, %d", error);		goto bad;	}	return (h);bad:	kmem_free((caddr_t)p->cku_outbuf, KM_RPC);	kmem_free((caddr_t)(caddr_t)p, KM_RPC);#ifdef RPCDEBUG	rpc_debug(4, "create failed\n");#endif	return ((CLIENT *)NULL);}clntkudp_init(h, addr, retrys, cred)	CLIENT *h;	struct sockaddr_in *addr;	int retrys;	struct ucred *cred;{	struct cku_private *p = htop(h);	p->cku_retrys = retrys;	p->cku_addr = *addr;	p->cku_cred = cred;	p->cku_flags &= (CKU_BUFBUSY | CKU_BUFWANTED);}/* * Time out back off function. tim is in hz */#define MAXTIMO	(60 * hz)#define backoff(tim)	((((tim) << 1) > MAXTIMO) ? MAXTIMO : ((tim) << 1))/* * Call remote procedure. * Most of the work of rpc is done here.  We serialize what is left * of the header (some was pre-serialized in the handle), serialize * the arguments, and send it off.  We wait for a reply or a time out. * Timeout causes an immediate return, other packet problems may cause * a retry on the receive.  When a good packet is received we deserialize * it, and check verification.  A bad reply code will cause one retry * with full (longhand) credentials. */enum clnt_stat clntkudp_callit(h, procnum, xdr_args, argsp, xdr_results, resultsp, wait)	register CLIENT	*h;	u_long		procnum;	xdrproc_t	xdr_args;	caddr_t		argsp;	xdrproc_t	xdr_results;	caddr_t		resultsp;	struct timeval	wait;{	register struct cku_private *p = htop(h);	register XDR	   	   *xdrs;	register struct socket	   *so = p->cku_sock;	int			   rtries;	int			   stries = p->cku_retrys;	struct sockaddr_in	   from;	int			   s;	struct ucred		   *tmpcred;	struct mbuf		   *m = NULL;	int timohz;	u_long xid;	u_int rempos = 0;	int refreshes = 2;	/* number of times to refresh credential */ 	int interrupted;        /* return from sleep() */ 	int smask;              /* saved signal mask */ 	struct proc *pp = u.u_procp;#ifdef RPCDEBUG	rpc_debug(4, "cku_callit\n");#endif	smp_lock(&lk_nfsstat, LK_RETRY);	rcstat.rccalls++;	smp_unlock(&lk_nfsstat);	while (p->cku_flags & CKU_BUSY) {		smp_lock(&lk_nfsstat, LK_RETRY);		rcstat.rcwaits++;		smp_unlock(&lk_nfsstat);		p->cku_flags |= CKU_WANTED;		(void) sleep((caddr_t)h, PZERO-2);	}	p->cku_flags |= CKU_BUSY;	if ((p->cku_flags & CKU_ONCE_ONLY) != 0)		stries = 1;	/*	 * Set credentials into the u structure	 */	tmpcred = u.u_cred;	u.u_cred = p->cku_cred;	/*	 * This is dumb but easy: keep the time out in units of hz	 * so it is easy to call timeout and modify the value.	 */	timohz = wait.tv_sec * hz + (wait.tv_usec * hz) / 1000000;call_again:	/*	 * Wait til buffer gets freed then make a type 2 mbuf point at it	 * The buffree routine clears CKU_BUFBUSY and does a wakeup when	 * the mbuf gets freed.	 */	/*	 * SMP lock this sleep wakeup mechanism which is described	 * above.	 */	s = splimp();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -