clnt_dg.c (99996) | clnt_dg.c (105189) |
---|---|
1/* $NetBSD: clnt_dg.c,v 1.4 2000/07/14 08:40:41 fvdl Exp $ */ 2 3/* 4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5 * unrestricted use provided that this legend is included on all tape 6 * media and as a part of the software program in whole or part. Users 7 * may copy or modify Sun RPC without charge, but are not authorized 8 * to license or distribute it to anyone else except as part of a product or --- 24 unchanged lines hidden (view full) --- 33 */ 34 35/* #ident "@(#)clnt_dg.c 1.23 94/04/22 SMI" */ 36 37#if !defined(lint) && defined(SCCSIDS) 38static char sccsid[] = "@(#)clnt_dg.c 1.19 89/03/16 Copyr 1988 Sun Micro"; 39#endif 40#include <sys/cdefs.h> | 1/* $NetBSD: clnt_dg.c,v 1.4 2000/07/14 08:40:41 fvdl Exp $ */ 2 3/* 4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5 * unrestricted use provided that this legend is included on all tape 6 * media and as a part of the software program in whole or part. Users 7 * may copy or modify Sun RPC without charge, but are not authorized 8 * to license or distribute it to anyone else except as part of a product or --- 24 unchanged lines hidden (view full) --- 33 */ 34 35/* #ident "@(#)clnt_dg.c 1.23 94/04/22 SMI" */ 36 37#if !defined(lint) && defined(SCCSIDS) 38static char sccsid[] = "@(#)clnt_dg.c 1.19 89/03/16 Copyr 1988 Sun Micro"; 39#endif 40#include <sys/cdefs.h> |
41__FBSDID("$FreeBSD: head/lib/libc/rpc/clnt_dg.c 99996 2002-07-14 23:14:02Z alfred $"); | 41__FBSDID("$FreeBSD: head/lib/libc/rpc/clnt_dg.c 105189 2002-10-15 22:28:59Z iedowse $"); |
42 43/* 44 * Implements a connectionless client side RPC. 45 */ 46 47#include "namespace.h" 48#include "reentrant.h" | 42 43/* 44 * Implements a connectionless client side RPC. 45 */ 46 47#include "namespace.h" 48#include "reentrant.h" |
49#include <sys/poll.h> | |
50#include <sys/types.h> | 49#include <sys/types.h> |
50#include <sys/event.h> |
|
51#include <sys/time.h> 52#include <sys/socket.h> 53#include <sys/ioctl.h> 54#include <arpa/inet.h> 55#include <rpc/rpc.h> 56#include <errno.h> 57#include <stdlib.h> 58#include <string.h> --- 11 unchanged lines hidden (view full) --- 70static bool_t time_not_ok(struct timeval *); 71static enum clnt_stat clnt_dg_call(CLIENT *, rpcproc_t, xdrproc_t, void *, 72 xdrproc_t, void *, struct timeval); 73static void clnt_dg_geterr(CLIENT *, struct rpc_err *); 74static bool_t clnt_dg_freeres(CLIENT *, xdrproc_t, void *); 75static void clnt_dg_abort(CLIENT *); 76static bool_t clnt_dg_control(CLIENT *, u_int, void *); 77static void clnt_dg_destroy(CLIENT *); | 51#include <sys/time.h> 52#include <sys/socket.h> 53#include <sys/ioctl.h> 54#include <arpa/inet.h> 55#include <rpc/rpc.h> 56#include <errno.h> 57#include <stdlib.h> 58#include <string.h> --- 11 unchanged lines hidden (view full) --- 70static bool_t time_not_ok(struct timeval *); 71static enum clnt_stat clnt_dg_call(CLIENT *, rpcproc_t, xdrproc_t, void *, 72 xdrproc_t, void *, struct timeval); 73static void clnt_dg_geterr(CLIENT *, struct rpc_err *); 74static bool_t clnt_dg_freeres(CLIENT *, xdrproc_t, void *); 75static void clnt_dg_abort(CLIENT *); 76static bool_t clnt_dg_control(CLIENT *, u_int, void *); 77static void clnt_dg_destroy(CLIENT *); |
78static int __rpc_timeval_to_msec(struct timeval *); | |
79 80 81 82 83/* 84 * This machinery implements per-fd locks for MT-safety. It is not 85 * sufficient to do per-CLIENT handle locks for MT-safety because a 86 * user may create more than one CLIENT handle with the same fd behind --- 8 unchanged lines hidden (view full) --- 95 */ 96static int *dg_fd_locks; 97extern mutex_t clnt_fd_lock; 98static cond_t *dg_cv; 99#define release_fd_lock(fd, mask) { \ 100 mutex_lock(&clnt_fd_lock); \ 101 dg_fd_locks[fd] = 0; \ 102 mutex_unlock(&clnt_fd_lock); \ | 78 79 80 81 82/* 83 * This machinery implements per-fd locks for MT-safety. It is not 84 * sufficient to do per-CLIENT handle locks for MT-safety because a 85 * user may create more than one CLIENT handle with the same fd behind --- 8 unchanged lines hidden (view full) --- 94 */ 95static int *dg_fd_locks; 96extern mutex_t clnt_fd_lock; 97static cond_t *dg_cv; 98#define release_fd_lock(fd, mask) { \ 99 mutex_lock(&clnt_fd_lock); \ 100 dg_fd_locks[fd] = 0; \ 101 mutex_unlock(&clnt_fd_lock); \ |
103 thr_sigsetmask(SIG_SETMASK, &(mask), (sigset_t *) NULL); \ | 102 thr_sigsetmask(SIG_SETMASK, &(mask), NULL); \ |
104 cond_signal(&dg_cv[fd]); \ 105} 106 107static const char mem_err_clnt_dg[] = "clnt_dg_create: out of memory"; 108 109/* VARIABLES PROTECTED BY clnt_fd_lock: dg_fd_locks, dg_cv */ 110 111/* --- 7 unchanged lines hidden (view full) --- 119 struct timeval cu_wait; /* retransmit interval */ 120 struct timeval cu_total; /* total time for the call */ 121 struct rpc_err cu_error; 122 XDR cu_outxdrs; 123 u_int cu_xdrpos; 124 u_int cu_sendsz; /* send size */ 125 char *cu_outbuf; 126 u_int cu_recvsz; /* recv size */ | 103 cond_signal(&dg_cv[fd]); \ 104} 105 106static const char mem_err_clnt_dg[] = "clnt_dg_create: out of memory"; 107 108/* VARIABLES PROTECTED BY clnt_fd_lock: dg_fd_locks, dg_cv */ 109 110/* --- 7 unchanged lines hidden (view full) --- 118 struct timeval cu_wait; /* retransmit interval */ 119 struct timeval cu_total; /* total time for the call */ 120 struct rpc_err cu_error; 121 XDR cu_outxdrs; 122 u_int cu_xdrpos; 123 u_int cu_sendsz; /* send size */ 124 char *cu_outbuf; 125 u_int cu_recvsz; /* recv size */ |
127 struct pollfd pfdp; | |
128 int cu_async; 129 int cu_connect; /* Use connect(). */ 130 int cu_connected; /* Have done connect(). */ | 126 int cu_async; 127 int cu_connect; /* Use connect(). */ 128 int cu_connected; /* Have done connect(). */ |
129 struct kevent cu_kin; 130 int cu_kq; |
|
131 char cu_inbuf[1]; 132}; 133 134/* 135 * Connection less client creation returns with client handle parameters. 136 * Default options are set, which the user can change using clnt_control(). 137 * fd should be open and bound. 138 * NB: The rpch->cl_auth is initialized to null authentication. --- 129 unchanged lines hidden (view full) --- 268 */ 269 cu->cu_closeit = FALSE; 270 cu->cu_fd = fd; 271 cl->cl_ops = clnt_dg_ops(); 272 cl->cl_private = (caddr_t)(void *)cu; 273 cl->cl_auth = authnone_create(); 274 cl->cl_tp = NULL; 275 cl->cl_netid = NULL; | 131 char cu_inbuf[1]; 132}; 133 134/* 135 * Connection less client creation returns with client handle parameters. 136 * Default options are set, which the user can change using clnt_control(). 137 * fd should be open and bound. 138 * NB: The rpch->cl_auth is initialized to null authentication. --- 129 unchanged lines hidden (view full) --- 268 */ 269 cu->cu_closeit = FALSE; 270 cu->cu_fd = fd; 271 cl->cl_ops = clnt_dg_ops(); 272 cl->cl_private = (caddr_t)(void *)cu; 273 cl->cl_auth = authnone_create(); 274 cl->cl_tp = NULL; 275 cl->cl_netid = NULL; |
276 cu->pfdp.fd = cu->cu_fd; 277 cu->pfdp.events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND; | 276 cu->cu_kq = -1; 277 EV_SET(&cu->cu_kin, cu->cu_fd, EVFILT_READ, EV_ADD, 0, 0, 0); |
278 return (cl); 279err1: 280 warnx(mem_err_clnt_dg); 281 rpc_createerr.cf_stat = RPC_SYSTEMERROR; 282 rpc_createerr.cf_error.re_errno = errno; 283err2: 284 if (cl) { 285 mem_free(cl, sizeof (CLIENT)); --- 10 unchanged lines hidden (view full) --- 296 xdrproc_t xargs; /* xdr routine for args */ 297 void *argsp; /* pointer to args */ 298 xdrproc_t xresults; /* xdr routine for results */ 299 void *resultsp; /* pointer to results */ 300 struct timeval utimeout; /* seconds to wait before giving up */ 301{ 302 struct cu_data *cu = (struct cu_data *)cl->cl_private; 303 XDR *xdrs; | 278 return (cl); 279err1: 280 warnx(mem_err_clnt_dg); 281 rpc_createerr.cf_stat = RPC_SYSTEMERROR; 282 rpc_createerr.cf_error.re_errno = errno; 283err2: 284 if (cl) { 285 mem_free(cl, sizeof (CLIENT)); --- 10 unchanged lines hidden (view full) --- 296 xdrproc_t xargs; /* xdr routine for args */ 297 void *argsp; /* pointer to args */ 298 xdrproc_t xresults; /* xdr routine for results */ 299 void *resultsp; /* pointer to results */ 300 struct timeval utimeout; /* seconds to wait before giving up */ 301{ 302 struct cu_data *cu = (struct cu_data *)cl->cl_private; 303 XDR *xdrs; |
304 size_t outlen; | 304 size_t outlen = 0; |
305 struct rpc_msg reply_msg; 306 XDR reply_xdrs; | 305 struct rpc_msg reply_msg; 306 XDR reply_xdrs; |
307 struct timeval time_waited; | |
308 bool_t ok; 309 int nrefreshes = 2; /* number of times to refresh cred */ 310 struct timeval timeout; 311 struct timeval retransmit_time; | 307 bool_t ok; 308 int nrefreshes = 2; /* number of times to refresh cred */ 309 struct timeval timeout; 310 struct timeval retransmit_time; |
312 struct timeval startime, curtime; 313 int firsttimeout = 1; | 311 struct timeval next_sendtime, starttime, time_waited, tv; 312 struct timespec ts; 313 struct kevent kv; |
314 struct sockaddr *sa; 315 sigset_t mask; 316 sigset_t newmask; 317 socklen_t inlen, salen; 318 ssize_t recvlen = 0; | 314 struct sockaddr *sa; 315 sigset_t mask; 316 sigset_t newmask; 317 socklen_t inlen, salen; 318 ssize_t recvlen = 0; |
319 int rpc_lock_value; | 319 int kin_len, n, rpc_lock_value; |
320 u_int32_t xid; 321 322 outlen = 0; 323 sigfillset(&newmask); 324 thr_sigsetmask(SIG_SETMASK, &newmask, &mask); 325 mutex_lock(&clnt_fd_lock); 326 while (dg_fd_locks[cu->cu_fd]) 327 cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock); --- 7 unchanged lines hidden (view full) --- 335 timeout = utimeout; /* use supplied timeout */ 336 } else { 337 timeout = cu->cu_total; /* use default timeout */ 338 } 339 340 if (cu->cu_connect && !cu->cu_connected) { 341 if (_connect(cu->cu_fd, (struct sockaddr *)&cu->cu_raddr, 342 cu->cu_rlen) < 0) { | 320 u_int32_t xid; 321 322 outlen = 0; 323 sigfillset(&newmask); 324 thr_sigsetmask(SIG_SETMASK, &newmask, &mask); 325 mutex_lock(&clnt_fd_lock); 326 while (dg_fd_locks[cu->cu_fd]) 327 cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock); --- 7 unchanged lines hidden (view full) --- 335 timeout = utimeout; /* use supplied timeout */ 336 } else { 337 timeout = cu->cu_total; /* use default timeout */ 338 } 339 340 if (cu->cu_connect && !cu->cu_connected) { 341 if (_connect(cu->cu_fd, (struct sockaddr *)&cu->cu_raddr, 342 cu->cu_rlen) < 0) { |
343 release_fd_lock(cu->cu_fd, mask); | |
344 cu->cu_error.re_errno = errno; | 343 cu->cu_error.re_errno = errno; |
345 return (cu->cu_error.re_status = RPC_CANTSEND); | 344 cu->cu_error.re_status = RPC_CANTSEND; 345 goto out; |
346 } 347 cu->cu_connected = 1; 348 } 349 if (cu->cu_connected) { 350 sa = NULL; 351 salen = 0; 352 } else { 353 sa = (struct sockaddr *)&cu->cu_raddr; 354 salen = cu->cu_rlen; 355 } 356 time_waited.tv_sec = 0; 357 time_waited.tv_usec = 0; | 346 } 347 cu->cu_connected = 1; 348 } 349 if (cu->cu_connected) { 350 sa = NULL; 351 salen = 0; 352 } else { 353 sa = (struct sockaddr *)&cu->cu_raddr; 354 salen = cu->cu_rlen; 355 } 356 time_waited.tv_sec = 0; 357 time_waited.tv_usec = 0; |
358 retransmit_time = cu->cu_wait; | 358 retransmit_time = next_sendtime = cu->cu_wait; 359 gettimeofday(&starttime, NULL); |
359 | 360 |
361 /* Clean up in case the last call ended in a longjmp(3) call. */ 362 if (cu->cu_kq >= 0) 363 _close(cu->cu_kq); 364 if ((cu->cu_kq = kqueue()) < 0) { 365 cu->cu_error.re_errno = errno; 366 cu->cu_error.re_status = RPC_CANTSEND; 367 goto out; 368 } 369 kin_len = 1; 370 |
|
360call_again: 361 xdrs = &(cu->cu_outxdrs); 362 if (cu->cu_async == TRUE && xargs == NULL) 363 goto get_reply; 364 xdrs->x_op = XDR_ENCODE; 365 XDR_SETPOS(xdrs, cu->cu_xdrpos); 366 /* 367 * the transaction is the first thing in the out buffer 368 * XXX Yes, and it's in network byte order, so we should to 369 * be careful when we increment it, shouldn't we. 370 */ 371 xid = ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf)); 372 xid++; 373 *(u_int32_t *)(void *)(cu->cu_outbuf) = htonl(xid); 374 375 if ((! XDR_PUTINT32(xdrs, &proc)) || 376 (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || 377 (! (*xargs)(xdrs, argsp))) { | 371call_again: 372 xdrs = &(cu->cu_outxdrs); 373 if (cu->cu_async == TRUE && xargs == NULL) 374 goto get_reply; 375 xdrs->x_op = XDR_ENCODE; 376 XDR_SETPOS(xdrs, cu->cu_xdrpos); 377 /* 378 * the transaction is the first thing in the out buffer 379 * XXX Yes, and it's in network byte order, so we should to 380 * be careful when we increment it, shouldn't we. 381 */ 382 xid = ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf)); 383 xid++; 384 *(u_int32_t *)(void *)(cu->cu_outbuf) = htonl(xid); 385 386 if ((! XDR_PUTINT32(xdrs, &proc)) || 387 (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || 388 (! (*xargs)(xdrs, argsp))) { |
378 release_fd_lock(cu->cu_fd, mask); 379 return (cu->cu_error.re_status = RPC_CANTENCODEARGS); | 389 cu->cu_error.re_status = RPC_CANTENCODEARGS; 390 goto out; |
380 } 381 outlen = (size_t)XDR_GETPOS(xdrs); 382 383send_again: 384 if (_sendto(cu->cu_fd, cu->cu_outbuf, outlen, 0, sa, salen) != outlen) { 385 cu->cu_error.re_errno = errno; | 391 } 392 outlen = (size_t)XDR_GETPOS(xdrs); 393 394send_again: 395 if (_sendto(cu->cu_fd, cu->cu_outbuf, outlen, 0, sa, salen) != outlen) { 396 cu->cu_error.re_errno = errno; |
386 release_fd_lock(cu->cu_fd, mask); 387 return (cu->cu_error.re_status = RPC_CANTSEND); | 397 cu->cu_error.re_status = RPC_CANTSEND; 398 goto out; |
388 } 389 390 /* 391 * Hack to provide rpc-based message passing 392 */ 393 if (timeout.tv_sec == 0 && timeout.tv_usec == 0) { | 399 } 400 401 /* 402 * Hack to provide rpc-based message passing 403 */ 404 if (timeout.tv_sec == 0 && timeout.tv_usec == 0) { |
394 release_fd_lock(cu->cu_fd, mask); 395 return (cu->cu_error.re_status = RPC_TIMEDOUT); | 405 cu->cu_error.re_status = RPC_TIMEDOUT; 406 goto out; |
396 } 397 398get_reply: 399 400 /* 401 * sub-optimal code appears here because we have 402 * some clock time to spare while the packets are in flight. 403 * (We assume that this is actually only executed once.) 404 */ 405 reply_msg.acpted_rply.ar_verf = _null_auth; 406 reply_msg.acpted_rply.ar_results.where = resultsp; 407 reply_msg.acpted_rply.ar_results.proc = xresults; 408 | 407 } 408 409get_reply: 410 411 /* 412 * sub-optimal code appears here because we have 413 * some clock time to spare while the packets are in flight. 414 * (We assume that this is actually only executed once.) 415 */ 416 reply_msg.acpted_rply.ar_verf = _null_auth; 417 reply_msg.acpted_rply.ar_results.where = resultsp; 418 reply_msg.acpted_rply.ar_results.proc = xresults; 419 |
409 | |
410 for (;;) { | 420 for (;;) { |
411 switch (_poll(&cu->pfdp, 1, 412 __rpc_timeval_to_msec(&retransmit_time))) { 413 case 0: 414 time_waited.tv_sec += retransmit_time.tv_sec; 415 time_waited.tv_usec += retransmit_time.tv_usec; 416 while (time_waited.tv_usec >= 1000000) { 417 time_waited.tv_sec++; 418 time_waited.tv_usec -= 1000000; 419 } 420 /* update retransmit_time */ 421 if (retransmit_time.tv_sec < RPC_MAX_BACKOFF) { 422 retransmit_time.tv_usec *= 2; 423 retransmit_time.tv_sec *= 2; 424 while (retransmit_time.tv_usec >= 1000000) { 425 retransmit_time.tv_sec++; 426 retransmit_time.tv_usec -= 1000000; 427 } 428 } | 421 /* Decide how long to wait. */ 422 if (timercmp(&next_sendtime, &timeout, <)) 423 timersub(&next_sendtime, &time_waited, &tv); 424 else 425 timersub(&timeout, &time_waited, &tv); 426 if (tv.tv_sec < 0 || tv.tv_usec < 0) 427 tv.tv_sec = tv.tv_usec = 0; 428 TIMEVAL_TO_TIMESPEC(&tv, &ts); |
429 | 429 |
430 if ((time_waited.tv_sec < timeout.tv_sec) || 431 ((time_waited.tv_sec == timeout.tv_sec) && 432 (time_waited.tv_usec < timeout.tv_usec))) 433 goto send_again; 434 release_fd_lock(cu->cu_fd, mask); 435 return (cu->cu_error.re_status = RPC_TIMEDOUT); | 430 n = _kevent(cu->cu_kq, &cu->cu_kin, kin_len, &kv, 1, &ts); 431 /* We don't need to register the event again. */ 432 kin_len = 0; |
436 | 433 |
437 case -1: 438 if (errno == EBADF) { | 434 if (n == 1) { 435 if (kv.flags & EV_ERROR) { 436 cu->cu_error.re_errno = kv.data; 437 cu->cu_error.re_status = RPC_CANTRECV; 438 goto out; 439 } 440 /* We have some data now */ 441 do { 442 recvlen = _recvfrom(cu->cu_fd, cu->cu_inbuf, 443 cu->cu_recvsz, 0, NULL, NULL); 444 } while (recvlen < 0 && errno == EINTR); 445 if (recvlen < 0 && errno != EWOULDBLOCK) { |
439 cu->cu_error.re_errno = errno; | 446 cu->cu_error.re_errno = errno; |
440 release_fd_lock(cu->cu_fd, mask); 441 return (cu->cu_error.re_status = RPC_CANTRECV); | 447 cu->cu_error.re_status = RPC_CANTRECV; 448 goto out; |
442 } | 449 } |
443 if (errno != EINTR) { 444 errno = 0; /* reset it */ 445 continue; | 450 if (recvlen >= sizeof(u_int32_t) && 451 (cu->cu_async == TRUE || 452 *((u_int32_t *)(void *)(cu->cu_inbuf)) == 453 *((u_int32_t *)(void *)(cu->cu_outbuf)))) { 454 /* We now assume we have the proper reply. */ 455 break; |
446 } | 456 } |
447 /* interrupted by another signal, update time_waited */ 448 if (firsttimeout) { 449 /* 450 * Could have done gettimeofday before clnt_call 451 * but that means 1 more system call per each 452 * clnt_call, so do it after first time out 453 */ 454 if (gettimeofday(&startime, 455 (struct timezone *) NULL) == -1) { 456 errno = 0; 457 continue; 458 } 459 firsttimeout = 0; 460 errno = 0; 461 continue; 462 }; 463 if (gettimeofday(&curtime, 464 (struct timezone *) NULL) == -1) { 465 errno = 0; 466 continue; 467 }; 468 time_waited.tv_sec += curtime.tv_sec - startime.tv_sec; 469 time_waited.tv_usec += curtime.tv_usec - 470 startime.tv_usec; 471 while (time_waited.tv_usec < 0) { 472 time_waited.tv_sec--; 473 time_waited.tv_usec += 1000000; 474 }; 475 while (time_waited.tv_usec >= 1000000) { 476 time_waited.tv_sec++; 477 time_waited.tv_usec -= 1000000; 478 } 479 startime.tv_sec = curtime.tv_sec; 480 startime.tv_usec = curtime.tv_usec; 481 if ((time_waited.tv_sec > timeout.tv_sec) || 482 ((time_waited.tv_sec == timeout.tv_sec) && 483 (time_waited.tv_usec > timeout.tv_usec))) { 484 release_fd_lock(cu->cu_fd, mask); 485 return (cu->cu_error.re_status = RPC_TIMEDOUT); 486 } 487 errno = 0; /* reset it */ 488 continue; 489 }; 490 491 if (cu->pfdp.revents & POLLNVAL || (cu->pfdp.revents == 0)) { | 457 } 458 if (n == -1 && errno != EINTR) { 459 cu->cu_error.re_errno = errno; |
492 cu->cu_error.re_status = RPC_CANTRECV; | 460 cu->cu_error.re_status = RPC_CANTRECV; |
493 /* 494 * Note: we're faking errno here because we 495 * previously would have expected _poll() to 496 * return -1 with errno EBADF. Poll(BA_OS) 497 * returns 0 and sets the POLLNVAL revents flag 498 * instead. 499 */ 500 cu->cu_error.re_errno = errno = EBADF; 501 release_fd_lock(cu->cu_fd, mask); 502 return (-1); | 461 goto out; |
503 } | 462 } |
463 gettimeofday(&tv, NULL); 464 timersub(&tv, &starttime, &time_waited); |
|
504 | 465 |
505 /* We have some data now */ 506 do { 507 if (errno == EINTR) { 508 /* 509 * Must make sure errno was not already 510 * EINTR in case _recvfrom() returns -1. 511 */ 512 errno = 0; 513 } 514 recvlen = _recvfrom(cu->cu_fd, cu->cu_inbuf, 515 cu->cu_recvsz, 0, NULL, NULL); 516 } while (recvlen < 0 && errno == EINTR); 517 if (recvlen < 0) { 518 if (errno == EWOULDBLOCK) 519 continue; 520 cu->cu_error.re_errno = errno; 521 release_fd_lock(cu->cu_fd, mask); 522 return (cu->cu_error.re_status = RPC_CANTRECV); | 466 /* Check for timeout. */ 467 if (timercmp(&time_waited, &timeout, >)) { 468 cu->cu_error.re_status = RPC_TIMEDOUT; 469 goto out; |
523 } | 470 } |
524 if (recvlen < sizeof (u_int32_t)) 525 continue; 526 /* see if reply transaction id matches sent id */ 527 if (cu->cu_async == FALSE && 528 *((u_int32_t *)(void *)(cu->cu_inbuf)) != 529 *((u_int32_t *)(void *)(cu->cu_outbuf))) 530 continue; 531 /* we now assume we have the proper reply */ 532 break; | 471 472 /* Retransmit if necessary. */ 473 if (timercmp(&time_waited, &next_sendtime, >)) { 474 /* update retransmit_time */ 475 if (retransmit_time.tv_sec < RPC_MAX_BACKOFF) 476 timeradd(&retransmit_time, &retransmit_time, 477 &retransmit_time); 478 timeradd(&next_sendtime, &retransmit_time, 479 &next_sendtime); 480 goto send_again; 481 } |
533 } 534 inlen = (socklen_t)recvlen; 535 536 /* 537 * now decode and validate the response 538 */ 539 540 xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)inlen, XDR_DECODE); --- 30 unchanged lines hidden (view full) --- 571 goto call_again; 572 } 573 /* end of unsuccessful completion */ 574 } /* end of valid reply message */ 575 else { 576 cu->cu_error.re_status = RPC_CANTDECODERES; 577 578 } | 482 } 483 inlen = (socklen_t)recvlen; 484 485 /* 486 * now decode and validate the response 487 */ 488 489 xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)inlen, XDR_DECODE); --- 30 unchanged lines hidden (view full) --- 520 goto call_again; 521 } 522 /* end of unsuccessful completion */ 523 } /* end of valid reply message */ 524 else { 525 cu->cu_error.re_status = RPC_CANTDECODERES; 526 527 } |
528out: 529 if (cu->cu_kq >= 0) 530 _close(cu->cu_kq); 531 cu->cu_kq = -1; |
|
579 release_fd_lock(cu->cu_fd, mask); 580 return (cu->cu_error.re_status); 581} 582 583static void 584clnt_dg_geterr(cl, errp) 585 CLIENT *cl; 586 struct rpc_err *errp; --- 192 unchanged lines hidden (view full) --- 779 780 sigfillset(&newmask); 781 thr_sigsetmask(SIG_SETMASK, &newmask, &mask); 782 mutex_lock(&clnt_fd_lock); 783 while (dg_fd_locks[cu_fd]) 784 cond_wait(&dg_cv[cu_fd], &clnt_fd_lock); 785 if (cu->cu_closeit) 786 (void)_close(cu_fd); | 532 release_fd_lock(cu->cu_fd, mask); 533 return (cu->cu_error.re_status); 534} 535 536static void 537clnt_dg_geterr(cl, errp) 538 CLIENT *cl; 539 struct rpc_err *errp; --- 192 unchanged lines hidden (view full) --- 732 733 sigfillset(&newmask); 734 thr_sigsetmask(SIG_SETMASK, &newmask, &mask); 735 mutex_lock(&clnt_fd_lock); 736 while (dg_fd_locks[cu_fd]) 737 cond_wait(&dg_cv[cu_fd], &clnt_fd_lock); 738 if (cu->cu_closeit) 739 (void)_close(cu_fd); |
740 if (cu->cu_kq >= 0) 741 _close(cu->cu_kq); |
|
787 XDR_DESTROY(&(cu->cu_outxdrs)); 788 mem_free(cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz)); 789 if (cl->cl_netid && cl->cl_netid[0]) 790 mem_free(cl->cl_netid, strlen(cl->cl_netid) +1); 791 if (cl->cl_tp && cl->cl_tp[0]) 792 mem_free(cl->cl_tp, strlen(cl->cl_tp) +1); 793 mem_free(cl, sizeof (CLIENT)); 794 mutex_unlock(&clnt_fd_lock); --- 33 unchanged lines hidden (view full) --- 828static bool_t 829time_not_ok(t) 830 struct timeval *t; 831{ 832 return (t->tv_sec < -1 || t->tv_sec > 100000000 || 833 t->tv_usec < -1 || t->tv_usec > 1000000); 834} 835 | 742 XDR_DESTROY(&(cu->cu_outxdrs)); 743 mem_free(cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz)); 744 if (cl->cl_netid && cl->cl_netid[0]) 745 mem_free(cl->cl_netid, strlen(cl->cl_netid) +1); 746 if (cl->cl_tp && cl->cl_tp[0]) 747 mem_free(cl->cl_tp, strlen(cl->cl_tp) +1); 748 mem_free(cl, sizeof (CLIENT)); 749 mutex_unlock(&clnt_fd_lock); --- 33 unchanged lines hidden (view full) --- 783static bool_t 784time_not_ok(t) 785 struct timeval *t; 786{ 787 return (t->tv_sec < -1 || t->tv_sec > 100000000 || 788 t->tv_usec < -1 || t->tv_usec > 1000000); 789} 790 |
836 837/* 838 * Convert from timevals (used by select) to milliseconds (used by poll). 839 */ 840static int 841__rpc_timeval_to_msec(t) 842 struct timeval *t; 843{ 844 int t1, tmp; 845 846 /* 847 * We're really returning t->tv_sec * 1000 + (t->tv_usec / 1000) 848 * but try to do so efficiently. Note: 1000 = 1024 - 16 - 8. 849 */ 850 tmp = (int)t->tv_sec << 3; 851 t1 = -tmp; 852 t1 += t1 << 1; 853 t1 += tmp << 7; 854 if (t->tv_usec) 855 t1 += (int)(t->tv_usec / 1000); 856 857 return (t1); 858} | |