aboutsummaryrefslogtreecommitdiffstats
path: root/lib/libc/rpc/svc.c
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>1996-12-30 15:07:33 +0000
committerPeter Wemm <peter@FreeBSD.org>1996-12-30 15:07:33 +0000
commitae1e6afd3175b6e659b1cfcc8c80c91b23f50506 (patch)
tree5b73498aa46f7ea36a01a83d5a0c5154d7d03eda /lib/libc/rpc/svc.c
parent39f377845f429d04c0e306b29eadff32c1dc3509 (diff)
downloadsrc-ae1e6afd3175b6e659b1cfcc8c80c91b23f50506.tar.gz
src-ae1e6afd3175b6e659b1cfcc8c80c91b23f50506.zip
- 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.
Notes
Notes: svn path=/head/; revision=21087
Diffstat (limited to 'lib/libc/rpc/svc.c')
-rw-r--r--lib/libc/rpc/svc.c124
1 files changed, 68 insertions, 56 deletions
diff --git a/lib/libc/rpc/svc.c b/lib/libc/rpc/svc.c
index 05f82d315472..da3e42a3bcea 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) {