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 + -
显示快捷键?