mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-19 10:53:58 +00:00
- prototypes now in include file
- fix timeout code - better "random" initial transaction id for long running daemons - unlimited number of file descriptors to select(). - 64 bit type safe wire protocol Obtained from: a diff of FreeBSD vs. OpenBSD/NetBSD rpc code. - typo (spelling police :-) - dont die on select() that returns time remaining (on my systems)
This commit is contained in:
parent
7bdb2acfaa
commit
5df070f36d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=21075
@ -30,7 +30,7 @@
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
/*static char *sccsid = "from: @(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";*/
|
||||
/*static char *sccsid = "from: @(#)clnt_udp.c 2.2 88/08/01 4.0 RPCSRC";*/
|
||||
static char *rcsid = "$Id: clnt_udp.c,v 1.6 1995/12/07 12:50:54 bde Exp $";
|
||||
static char *rcsid = "$Id: clnt_udp.c,v 1.7 1996/06/10 00:49:16 jraynard Exp $";
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -50,10 +50,6 @@ static char *rcsid = "$Id: clnt_udp.c,v 1.6 1995/12/07 12:50:54 bde Exp $";
|
||||
#include <errno.h>
|
||||
#include <rpc/pmap_clnt.h>
|
||||
|
||||
int bindresvport(int sd, struct sockaddr_in *);
|
||||
int _rpc_dtablesize(void);
|
||||
bool_t xdr_opaque_auth(XDR *, struct opaque_auth *);
|
||||
|
||||
/*
|
||||
* UDP bases client side rpc operations
|
||||
*/
|
||||
@ -122,6 +118,10 @@ clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
|
||||
register struct cu_data *cu = NULL;
|
||||
struct timeval now;
|
||||
struct rpc_msg call_msg;
|
||||
static u_int32_t disrupt;
|
||||
|
||||
if (disrupt == 0)
|
||||
disrupt = (u_int32_t)(long)raddr;
|
||||
|
||||
cl = (CLIENT *)mem_alloc(sizeof(CLIENT));
|
||||
if (cl == NULL) {
|
||||
@ -159,7 +159,7 @@ clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
|
||||
cu->cu_total.tv_usec = -1;
|
||||
cu->cu_sendsz = sendsz;
|
||||
cu->cu_recvsz = recvsz;
|
||||
call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
|
||||
call_msg.rm_xid = (++disrupt) ^ getpid() ^ now.tv_sec ^ now.tv_usec;
|
||||
call_msg.rm_direction = CALL;
|
||||
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
|
||||
call_msg.rm_call.cb_prog = program;
|
||||
@ -179,7 +179,7 @@ clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
|
||||
rpc_createerr.cf_error.re_errno = errno;
|
||||
goto fooy;
|
||||
}
|
||||
/* attempt to bind to prov port */
|
||||
/* attempt to bind to priv port */
|
||||
(void)bindresvport(*sockp, (struct sockaddr_in *)0);
|
||||
/* the sockets rpc controls are non-blocking */
|
||||
(void)ioctl(*sockp, FIONBIO, (char *) &dontblock);
|
||||
@ -226,29 +226,33 @@ clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
|
||||
register int outlen;
|
||||
register int inlen;
|
||||
int fromlen;
|
||||
#ifdef FD_SETSIZE
|
||||
fd_set readfds;
|
||||
fd_set mask;
|
||||
#else
|
||||
int readfds;
|
||||
register int mask;
|
||||
#endif /* def FD_SETSIZE */
|
||||
fd_set *fds, readfds;
|
||||
struct sockaddr_in from;
|
||||
struct rpc_msg reply_msg;
|
||||
XDR reply_xdrs;
|
||||
struct timeval time_waited;
|
||||
struct timeval time_waited, start, after, tmp1, tmp2, tv;
|
||||
bool_t ok;
|
||||
int nrefreshes = 2; /* number of times to refresh cred */
|
||||
struct timeval timeout;
|
||||
|
||||
if (cu->cu_total.tv_usec == -1) {
|
||||
if (cu->cu_total.tv_usec == -1)
|
||||
timeout = utimeout; /* use supplied timeout */
|
||||
} else {
|
||||
else
|
||||
timeout = cu->cu_total; /* use default timeout */
|
||||
|
||||
if (cu->cu_sock + 1 > FD_SETSIZE) {
|
||||
int bytes = howmany(cu->cu_sock + 1, NFDBITS) * sizeof(fd_mask);
|
||||
fds = (fd_set *)malloc(bytes);
|
||||
if (fds == NULL)
|
||||
return (cu->cu_error.re_status = RPC_CANTSEND);
|
||||
memset(fds, 0, bytes);
|
||||
} else {
|
||||
fds = &readfds;
|
||||
FD_ZERO(fds);
|
||||
}
|
||||
|
||||
time_waited.tv_sec = 0;
|
||||
time_waited.tv_usec = 0;
|
||||
timerclear(&time_waited);
|
||||
|
||||
call_again:
|
||||
xdrs = &(cu->cu_outxdrs);
|
||||
xdrs->x_op = XDR_ENCODE;
|
||||
@ -259,22 +263,28 @@ clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
|
||||
(*(u_short *)(cu->cu_outbuf))++;
|
||||
if ((! XDR_PUTLONG(xdrs, (long *)&proc)) ||
|
||||
(! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
|
||||
(! (*xargs)(xdrs, argsp)))
|
||||
(! (*xargs)(xdrs, argsp))) {
|
||||
if (fds != &readfds)
|
||||
free(fds);
|
||||
return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
|
||||
}
|
||||
outlen = (int)XDR_GETPOS(xdrs);
|
||||
|
||||
send_again:
|
||||
if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0,
|
||||
(struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen)
|
||||
!= outlen) {
|
||||
(struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen) != outlen) {
|
||||
cu->cu_error.re_errno = errno;
|
||||
if (fds != &readfds)
|
||||
free(fds);
|
||||
return (cu->cu_error.re_status = RPC_CANTSEND);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hack to provide rpc-based message passing
|
||||
*/
|
||||
if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
|
||||
if (!timerisset(&timeout)) {
|
||||
if (fds != &readfds)
|
||||
free(fds);
|
||||
return (cu->cu_error.re_status = RPC_TIMEDOUT);
|
||||
}
|
||||
/*
|
||||
@ -285,40 +295,41 @@ clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
|
||||
reply_msg.acpted_rply.ar_verf = _null_auth;
|
||||
reply_msg.acpted_rply.ar_results.where = resultsp;
|
||||
reply_msg.acpted_rply.ar_results.proc = xresults;
|
||||
#ifdef FD_SETSIZE
|
||||
FD_ZERO(&mask);
|
||||
FD_SET(cu->cu_sock, &mask);
|
||||
#else
|
||||
mask = 1 << cu->cu_sock;
|
||||
#endif /* def FD_SETSIZE */
|
||||
|
||||
gettimeofday(&start, NULL);
|
||||
for (;;) {
|
||||
readfds = mask;
|
||||
switch (select(_rpc_dtablesize(), &readfds, (fd_set *)NULL,
|
||||
(fd_set *)NULL, &(cu->cu_wait))) {
|
||||
/* XXX we know the other bits are still clear */
|
||||
FD_SET(cu->cu_sock, fds);
|
||||
tv = cu->cu_wait;
|
||||
switch (select(cu->cu_sock+1, fds, NULL, NULL, &tv)) {
|
||||
|
||||
case 0:
|
||||
time_waited.tv_sec += cu->cu_wait.tv_sec;
|
||||
time_waited.tv_usec += cu->cu_wait.tv_usec;
|
||||
while (time_waited.tv_usec >= 1000000) {
|
||||
time_waited.tv_sec++;
|
||||
time_waited.tv_usec -= 1000000;
|
||||
}
|
||||
if ((time_waited.tv_sec < timeout.tv_sec) ||
|
||||
((time_waited.tv_sec == timeout.tv_sec) &&
|
||||
(time_waited.tv_usec < timeout.tv_usec)))
|
||||
timeradd(&time_waited, &cu->cu_wait, &tmp1);
|
||||
time_waited = tmp1;
|
||||
if (timercmp(&time_waited, &timeout, <))
|
||||
goto send_again;
|
||||
if (fds != &readfds)
|
||||
free(fds);
|
||||
return (cu->cu_error.re_status = RPC_TIMEDOUT);
|
||||
|
||||
/*
|
||||
* buggy in other cases because time_waited is not being
|
||||
* updated.
|
||||
*/
|
||||
case -1:
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
if (errno == EINTR) {
|
||||
gettimeofday(&after, NULL);
|
||||
timersub(&after, &start, &tmp1);
|
||||
timeradd(&time_waited, &tmp1, &tmp2);
|
||||
time_waited = tmp2;
|
||||
if (timercmp(&time_waited, &timeout, <))
|
||||
continue;
|
||||
if (fds != &readfds)
|
||||
free(fds);
|
||||
return (cu->cu_error.re_status = RPC_TIMEDOUT);
|
||||
}
|
||||
cu->cu_error.re_errno = errno;
|
||||
if (fds != &readfds)
|
||||
free(fds);
|
||||
return (cu->cu_error.re_status = RPC_CANTRECV);
|
||||
}
|
||||
|
||||
do {
|
||||
fromlen = sizeof(struct sockaddr);
|
||||
inlen = recvfrom(cu->cu_sock, cu->cu_inbuf,
|
||||
@ -329,12 +340,14 @@ clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
|
||||
if (errno == EWOULDBLOCK)
|
||||
continue;
|
||||
cu->cu_error.re_errno = errno;
|
||||
if (fds != &readfds)
|
||||
free(fds);
|
||||
return (cu->cu_error.re_status = RPC_CANTRECV);
|
||||
}
|
||||
if (inlen < sizeof(u_long))
|
||||
if (inlen < sizeof(u_int32_t))
|
||||
continue;
|
||||
/* see if reply transaction id matches sent id */
|
||||
if (*((u_long *)(cu->cu_inbuf)) != *((u_long *)(cu->cu_outbuf)))
|
||||
if (*((u_int32_t *)(cu->cu_inbuf)) != *((u_int32_t *)(cu->cu_outbuf)))
|
||||
continue;
|
||||
/* we now assume we have the proper reply */
|
||||
break;
|
||||
@ -371,6 +384,8 @@ clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
|
||||
else {
|
||||
cu->cu_error.re_status = RPC_CANTDECODERES;
|
||||
}
|
||||
if (fds != &readfds)
|
||||
free(fds);
|
||||
return (cu->cu_error.re_status);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user