clnt_kudp.c

来自「操作系统SunOS 4.1.3版本的源码」· C语言 代码 · 共 740 行 · 第 1/2 页

C
740
字号
	if (m->m_next == 0) {		/* XXX */		m->m_len = XDR_GETPOS(&(p->cku_outxdr));	}	if (p->cku_err.re_errno =	    ku_sendto_mbuf(so, m, &p->cku_addr)) {		p->cku_err.re_status = RPC_CANTSEND;		goto done;	}	/*	 * Start the roundtrip timer and calculate retransmit time.	 */	t1 = millitime();	tout = t1 + rto;	reply_msg.acpted_rply.ar_verf = _null_auth;	reply_msg.acpted_rply.ar_results.where = resultsp;	reply_msg.acpted_rply.ar_results.proc = xdr_results;recv_again:	while (rtries < RECVTRIES) {		s = splnet();		while (so->so_rcv.sb_cc == 0) {			if (get_udp() != 0)				continue;			if ((t2 = millitime()) > tout) {				(void) splx(s);				p->cku_err.re_status = RPC_TIMEDOUT;				p->cku_err.re_errno = ETIMEDOUT;				rcstat.rctimeouts++;				rcstat.rcretrans++;				rtries++;				if (t2 > maxtout)	/* time to return */					goto done;				/*				 * Update average and mean deviation and keep				 * doubling the retransmission timeout until we				 * get a good return.				 */				rtupdate(t2 - t1);				rto = rto << 1;		/* double rto */				/*				 * After 2 retransmissions, bump the				 * retransmission timeout to at least 1 second.				 * This is the el-cheapo method of flood				 * avoidance. The Real method would be to keep				 * sa, sd, and rto for each of several classes				 * of rpc since mount requests take an order of				 * magnitude or longer than read requests but,				 * hey, this is just the boot program and we're				 * lucky to get adaptive retransmits at all.				 */				if (rtries > 1)					rto = (rto < ONESECOND)? ONESECOND: rto;				if (rto > MAXRTO)					rto = MAXRTO;				buffree(p);				if (verbosemode)					printf("X");				goto call_again;			}		}		/*		 * Update sa, sd, and rto.		 */		t2 = millitime();		rto = rtupdate(t2 - t1);		if (so->so_error) {			so->so_error = 0;			(void) splx(s);			continue;		}		p->cku_inmbuf = ku_recvfrom(so, &from);		if (sin) {			*sin = from;		}#ifdef	RPCDEBUG		rpc_debug(6, "clntkudp_callit_addr: cku_inmbuf 0x%x\n",			p->cku_inmbuf);#endif	/* RPCDEBUG */		(void) splx(s);		if (p->cku_inmbuf == NULL) {			continue;		}		p->cku_inbuf = mtod(p->cku_inmbuf, char *);		if (p->cku_inmbuf->m_len < sizeof (u_long)) {			m_freem(p->cku_inmbuf);			continue;		}		/*		 * If reply transaction id matches id sent		 * we have a good packet.		 */		if (*((u_long *)(p->cku_inbuf))		    != *((u_long *)(p->cku_outbuf))) {#ifdef	RPCDEBUG		rpc_debug(6, "clntkudp_callit_addr: bad xid 0x%x not 0x%x\n",		    *((u_long *)(p->cku_inbuf)), *((u_long *)(p->cku_outbuf)));#endif	/* RPCDEBUG */			rcstat.rcbadxids++;			m_freem(p->cku_inmbuf);			continue;		}		break;	}	if (rtries > RECVTRIES) {#ifdef	RPCDEBUG	rpc_debug(1, "clntkudp_callit retries exhausted\n");#endif	/* RPCDEBUG */		if (verbosemode)			printf("retries exhausted, giving up\n");		p->cku_err.re_status = RPC_CANTRECV;		goto done;	}	/*	 * Process reply	 */	xdrs = &(p->cku_inxdr);	xdrmbuf_init(xdrs, p->cku_inmbuf, XDR_DECODE);	/*	 * Decode and validate the response.	 */	if (xdr_replymsg(xdrs, &reply_msg)) {		_seterr_reply(&reply_msg, &(p->cku_err));		if (p->cku_err.re_status == RPC_SUCCESS) {			/*			 * Reply is good, check auth.			 */			if (! AUTH_VALIDATE(h->cl_auth,			    &reply_msg.acpted_rply.ar_verf)) {				if (verbosemode) {					clntstat_print(RPC_AUTHERROR);					printf("\n");				}			    rpc_debug(3, "clntkudp_callit_addr: bad auth\n");				p->cku_err.re_status = RPC_AUTHERROR;				p->cku_err.re_why = AUTH_INVALIDRESP;			}		}	} else {		if (verbosemode) {			clntstat_print(RPC_CANTDECODERES);			printf("\n");		}		rpc_debug(10, "clntkudp_callit_addr: RPC_CANTDECODERES\n");		p->cku_err.re_status = RPC_CANTDECODERES;	}	m_freem(p->cku_inmbuf);#ifdef RPCDEBUG	rpc_debug(6, "clntkudp_callit_addr done\n");#endifdone:	if (verbosemode && (p->cku_err.re_status != RPC_SUCCESS)) {		printf("call ");		clntstat_print(p->cku_err.re_status);		printf("\n");	}	/*	 * Weed out remote rpc error replies.	 */	if (ignorebad &&		((p->cku_err.re_status == RPC_VERSMISMATCH) ||		    (p->cku_err.re_status == RPC_AUTHERROR) ||		    (p->cku_err.re_status == RPC_PROGUNAVAIL) ||		    (p->cku_err.re_status == RPC_PROGVERSMISMATCH) ||		    (p->cku_err.re_status == RPC_PROCUNAVAIL) ||		    (p->cku_err.re_status == RPC_CANTDECODEARGS) ||		    (p->cku_err.re_status == RPC_SYSTEMERROR))) {		if (verbosemode)			printf("-- ignored\n");		goto recv_again;	}	u.u_cred = tmpcred;	p->cku_flags &= ~CKU_BUSY;	if (p->cku_flags & CKU_WANTED) {		p->cku_flags &= ~CKU_WANTED;#ifdef	RPCDEBUG		rpc_debug(5, "clntkudp_callit_addr: wakeup\n");#endif	/* RPCDEBUG */		wakeup((caddr_t)h);	}	if (p->cku_err.re_status != RPC_SUCCESS) {		rcstat.rcbadcalls++;	}	buffree(p);	return (p->cku_err.re_status);}/* * V. Jacobson Mean+Varience retransmission timer alrorithm. * Update scaled average and mean deviation * and return new retransmit timer value. */staticrtupdate(m)int	m;{	m -= (sa >> 3);	sa += m;	if (m < 0)		m = -m;	m -= (sd >> 2);	sd += m;	return (((sa >> 2) + sd) >> 1);}enum clnt_statclntkudp_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;{#ifdef RPCDEBUG	rpc_debug(6,		"clntkudp_callit(h 0x%x, procnum 0x%x, xdr_args 0x%x, argsp 0x%x, xdr_results 0x%x, resultsp 0x%x, wait 0x%x)\n",		h, procnum, xdr_args, argsp, xdr_results, resultsp, wait);#endif	return (clntkudp_callit_addr(h, procnum, xdr_args, argsp, xdr_results,		resultsp, wait, (struct sockaddr_in *)0, 0));}/* * Wake up client waiting for a reply. */ckuwakeup(p)	register struct cku_private *p;{#ifdef RPCDEBUG	rpc_debug(6, "ckuwakeup\n");#endif	p->cku_flags |= CKU_TIMEDOUT;}/* * Return error info on this handle. */voidclntkudp_error(h, err)	CLIENT *h;	struct rpc_err *err;{	register struct cku_private *p = htop(h);	*err = p->cku_err;}static bool_tclntkudp_freeres(cl, xdr_res, res_ptr)	CLIENT *cl;	xdrproc_t xdr_res;	caddr_t res_ptr;{	register struct cku_private *p = (struct cku_private *)cl->cl_private;	register XDR *xdrs = &(p->cku_outxdr);	xdrs->x_op = XDR_FREE;	return ((*xdr_res)(xdrs, res_ptr));}voidclntkudp_abort(){}/* * Destroy rpc handle. * Frees the space used for output buffer, private data, and handle * structure, and closes the socket for this handle. */voidclntkudp_destroy(h)	CLIENT *h;{#ifdef RPCDEBUG	rpc_debug(6, "cku_destroy %x\n", h);#endif}/* * try to bind to a reserved port */bindresvport(so)	struct socket *so;{	struct sockaddr_in *sin;	struct mbuf *m;	u_short i;	int error;	int saveuid;#define	MAX_PRIV	(IPPORT_RESERVED-1)#define	MIN_PRIV	(IPPORT_RESERVED/2)	m = m_get(M_WAIT, MT_SONAME);	if (m == NULL) {		printf("bindresvport: couldn't alloc mbuf");		return (ENOBUFS);	}	sin = mtod(m, struct sockaddr_in *);	sin->sin_family = AF_INET;	sin->sin_addr.s_addr = INADDR_ANY;	m->m_len = sizeof (struct sockaddr_in);	saveuid = u.u_uid;	u.u_uid = 0;	error = EADDRINUSE;	for (i = MAX_PRIV; error == EADDRINUSE && i >= MIN_PRIV; i--) {		sin->sin_port = htons(i);		error = sobind(so, m);	}	u.u_uid = saveuid;	(void) m_freem(m);	return (error);}clnt_delay(i)	int	i;{	for (; i > 0; i--);}rpcstats(){	if (rcstat.rccalls > 0)		printf("rpc:  calls %d badcalls %d retrans %d badxids %d timeouts %d waits %d newcreds %d\n",			rcstat.rccalls,			rcstat.rcbadcalls,			rcstat.rcretrans,			rcstat.rcbadxids,			rcstat.rctimeouts,			rcstat.rcwaits,			rcstat.rcnewcreds);}

⌨️ 快捷键说明

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