diff options
author | peter <peter@FreeBSD.org> | 1996-12-30 15:07:33 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1996-12-30 15:07:33 +0000 |
commit | 595f765cbc2f92007739b1ef8898d613e70f6718 (patch) | |
tree | 5b73498aa46f7ea36a01a83d5a0c5154d7d03eda /lib/libc/rpc | |
parent | 3a2a3df0037afee2560451ad24f04c5da5e3d72a (diff) | |
download | FreeBSD-src-595f765cbc2f92007739b1ef8898d613e70f6718.zip FreeBSD-src-595f765cbc2f92007739b1ef8898d613e70f6718.tar.gz |
- major overhaul to make this deal with unlimited fd's.
- kill non-FD_SETSIZE code
Obtained from: a diff of FreeBSD vs. OpenBSD/NetBSD rpc code.
Note, there was a nasty bug with our old code here. It would trash the
stack if a fd > 31 was passed in. It was using a "long" as though it
was an "fd_set", ie: it was assuming that a long was 256 bits wide. :-(
This has been lurking here for a while, since the FD_SETSIZE #ifdef's
were first implemented.
Diffstat (limited to 'lib/libc/rpc')
-rw-r--r-- | lib/libc/rpc/svc.c | 124 |
1 files changed, 68 insertions, 56 deletions
diff --git a/lib/libc/rpc/svc.c b/lib/libc/rpc/svc.c index 05f82d3..da3e42a 100644 --- a/lib/libc/rpc/svc.c +++ b/lib/libc/rpc/svc.c @@ -30,7 +30,7 @@ #if defined(LIBC_SCCS) && !defined(lint) /*static char *sccsid = "from: @(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro";*/ /*static char *sccsid = "from: @(#)svc.c 2.4 88/08/11 4.0 RPCSRC";*/ -static char *rcsid = "$Id: svc.c,v 1.5 1996/06/11 17:22:50 jraynard Exp $"; +static char *rcsid = "$Id: svc.c,v 1.6 1996/08/12 14:00:24 peter Exp $"; #endif /* @@ -49,18 +49,13 @@ static char *rcsid = "$Id: svc.c,v 1.5 1996/06/11 17:22:50 jraynard Exp $"; #include <rpc/rpc.h> #include <rpc/pmap_clnt.h> -#ifdef FD_SETSIZE static SVCXPRT **xports; -#else -#define NOFILE 32 - -static SVCXPRT *xports[NOFILE]; -#endif /* def FD_SETSIZE */ +static int xportssize; #define NULL_SVC ((struct svc_callout *)0) #define RQCRED_SIZE 400 /* this size is excessive */ -int _rpc_dtablesize(void); +#define max(a, b) (a > b ? a : b) /* * The services list @@ -77,6 +72,9 @@ static struct svc_callout { static struct svc_callout *svc_find(); +int __svc_fdsetsize; +fd_set *__svc_fdset; + /* *************** SVCXPRT related stuff **************** */ /* @@ -88,23 +86,42 @@ xprt_register(xprt) { register int sock = xprt->xp_sock; -#ifdef FD_SETSIZE - if (xports == NULL) { - xports = (SVCXPRT **) - mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *)); - memset(xports, 0, FD_SETSIZE * sizeof(SVCXPRT *)); + if (sock + 1 > __svc_fdsetsize) { + int bytes = howmany(sock + 1, NFDBITS) * sizeof(fd_mask); + fd_set *fds; + + fds = (fd_set *)malloc(bytes); + memset(fds, 0, bytes); + if (__svc_fdset) { + memcpy(fds, __svc_fdset, howmany(__svc_fdsetsize, + NFDBITS) * sizeof(fd_mask)); + free(__svc_fdset); + } + __svc_fdset = fds; + __svc_fdsetsize = howmany(sock+1, NFDBITS); } - if (sock < _rpc_dtablesize()) { - xports[sock] = xprt; + + if (sock < FD_SETSIZE) FD_SET(sock, &svc_fdset); + FD_SET(sock, __svc_fdset); + + if (xports == NULL || sock + 1 > xportssize) { + SVCXPRT **xp; + int size = FD_SETSIZE; + + if (sock + 1 > size) + size = sock + 1; + xp = (SVCXPRT **)mem_alloc(size * sizeof(SVCXPRT *)); + memset(xp, 0, size * sizeof(SVCXPRT *)); + if (xports) { + memcpy(xp, xports, xportssize * sizeof(SVCXPRT *)); + free(xports); + } + xportssize = size; + xports = xp; } -#else - if (sock < NOFILE) { - xports[sock] = xprt; - svc_fds |= (1 << sock); - } -#endif /* def FD_SETSIZE */ - + xports[sock] = xprt; + svc_maxfd = max(svc_maxfd, sock); } /* @@ -116,17 +133,21 @@ xprt_unregister(xprt) { register int sock = xprt->xp_sock; -#ifdef FD_SETSIZE - if ((sock < _rpc_dtablesize()) && (xports[sock] == xprt)) { - xports[sock] = (SVCXPRT *)0; - FD_CLR(sock, &svc_fdset); - } -#else - if ((sock < NOFILE) && (xports[sock] == xprt)) { + if (xports[sock] == xprt) { xports[sock] = (SVCXPRT *)0; - svc_fds &= ~(1 << sock); + if (sock < FD_SETSIZE) + FD_CLR(sock, &svc_fdset); + FD_CLR(sock, __svc_fdset); + if (sock == svc_maxfd) { + for (svc_maxfd--; svc_maxfd >= 0; svc_maxfd--) + if (xports[svc_maxfd]) + break; + } + /* + * XXX could use svc_maxfd as a hint to + * decrease the size of __svc_fdset + */ } -#endif /* def FD_SETSIZE */ } @@ -373,29 +394,27 @@ void svc_getreq(rdfds) int rdfds; { -#ifdef FD_SETSIZE fd_set readfds; FD_ZERO(&readfds); readfds.fds_bits[0] = rdfds; svc_getreqset(&readfds); -#else - int readfds = rdfds & svc_fds; - - svc_getreqset(&readfds); -#endif /* def FD_SETSIZE */ } +void svc_getreqset2 __P((fd_set *, int)); + void svc_getreqset(readfds) -#ifdef FD_SETSIZE fd_set *readfds; { -#else - int *readfds; + svc_getreqset2(readfds, FD_SETSIZE); +} + +void +svc_getreqset2(readfds, width) + fd_set *readfds; + int width; { - int readfds_local = *readfds; -#endif /* def FD_SETSIZE */ enum xprt_stat stat; struct rpc_msg msg; int prog_found; @@ -403,30 +422,23 @@ svc_getreqset(readfds) u_long high_vers; struct svc_req r; register SVCXPRT *xprt; - register u_long mask; register int bit; - register u_long *maskp; - register int setsize; register int sock; + register fd_mask mask, *maskp; char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE]; msg.rm_call.cb_cred.oa_base = cred_area; msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]); -#ifdef FD_SETSIZE - setsize = _rpc_dtablesize(); - maskp = (u_long *)readfds->fds_bits; - for (sock = 0; sock < setsize; sock += NFDBITS) { + maskp = readfds->fds_bits; + for (sock = 0; sock < width; sock += NFDBITS) { for (mask = *maskp++; (bit = ffs(mask)); mask ^= (1 << (bit - 1))) { /* sock has input waiting */ xprt = xports[sock + bit - 1]; -#else - for (sock = 0; readfds_local != 0; sock++, readfds_local >>= 1) { - if ((readfds_local & 1) != 0) { - /* sock has input waiting */ - xprt = xports[sock]; -#endif /* def FD_SETSIZE */ + if (xprt == NULL) + /* But do we control sock? */ + continue; /* now receive msgs from xprtprt (support batch calls) */ do { if (SVC_RECV(xprt, &msg)) { @@ -447,7 +459,7 @@ svc_getreqset(readfds) } /* now match message with a registered service*/ prog_found = FALSE; - low_vers = 0 - 1; + low_vers = (u_long) - 1; high_vers = 0; for (s = svc_head; s != NULL_SVC; s = s->sc_next) { if (s->sc_prog == r.rq_prog) { |