⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sockd_io.c

📁 sock protocol ,it is useful!
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1997, 1998, 1999 *      Inferno Nettverk A/S, Norway.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. The above copyright notice, this list of conditions and the following *    disclaimer must appear in all copies of the software, derivative works *    or modified versions, and any portions thereof, aswell as in all *    supporting documentation. * 2. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *      This product includes software developed by *      Inferno Nettverk A/S, Norway. * 3. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Inferno Nettverk A/S requests users of this software to return to * *  Software Distribution Coordinator  or  sdc@inet.no *  Inferno Nettverk A/S *  Oslo Research Park *  Gaustadal閑n 21 *  N-0349 Oslo *  Norway * * any improvements or extensions that they make and grant Inferno Nettverk A/S * the rights to redistribute these changes. * */#include "common.h"static const char rcsid[] ="$Id: sockd_io.c,v 1.165 1999/12/29 08:58:54 michaels Exp $";/* * Accept io objects from mother and does io on them.  We never * send back ancillary data, only ordinary data, so no need for * locking here even on broken systems (#ifdef HAVE_SENDMSG_DEADLOCK). */__BEGIN_DECLSstatic intallocated __P((void));/* * Returns the number of allocated (active) io's */static struct sockd_io_t *io_getset __P((fd_set *set));/* * Goes through our list until it finds a io object where atleast one of the * descriptors is set. * Returns NULL if none found. */static struct sockd_io_t *io_finddescriptor __P((int d));/* * Finds the io object where one of the descriptors matches "fd". */static intio_fillset __P((fd_set *set, int antiflags));/* * Sets all descriptors in our list in the set "set".  If "flags" * is set, io's with any of the flags in "flags" set will be excluded. * Returns the highest descriptor in our list, or -1 if we don't * have any descriptors open currently. */static voidio_clearset __P((const struct sockd_io_t *io, fd_set *set));/* * Clears all filedescriptors in "io" from "set". */static voiddoio __P((int mother, struct sockd_io_t *io, fd_set *rset, fd_set *wset,			 int flags));/* * Does i/o over the descriptors in "io", in to out and out to in. * "mother" is write connection to mother if we need to send a ack. * "io" is the object to do i/o over, * "flags" is the flags to set on the actual i/o calls * (read()/write(), recvfrom()/sendto()), currently only MSG_OOB. * If any of the calls fails the "io" is deleted. */static intio_rw __P((struct sockd_io_direction_t *in, struct sockd_io_direction_t *out,			  int *bad, char *buf, int flags));/* * Transfers data from "in" to "out" using flag "flags".  The data * transfered uses "buf" as a buffer, which must be big enough to * hold the data transfered. * The function never transfers more that the receive low watermark of * "out". * Returns: *		On success: bytes transfered or 0 for eof. *		On failure: -1.  "bad" is set to the value of the descriptor that *						failure was first detected on. */static voiddelete_io __P((int mother, struct sockd_io_t *io, int fd, int status));/* * deletes the io object "io".  "fd" is the descriptor on which "status" * was returned.  If "fd" is negative, it's ignored. * If "mother" is >= 0 the deletion of "io" is ACK'ed to her. * "status" can have one of these values and is normally intended to be the * result from a io call (read/write/etc). *		IO_ERRORUNKNOWN:	unknown error. *		IO_TIMEOUT		:	connection timed out.  ("fd" argument is ignored). *		IO_ERROR			:  error using "fd". *		IO_CLOSE			:	socket was closed. *		> 0				:  short read/write */static voidproctitleupdate __P((void));/* * Updates the title of this process. */static struct timeval *io_gettimeout __P((struct timeval *timeout));/* * If there is a timeout on the current clients for how long to exist * without doing i/o, this function fills in "timeout" with the appropriate * timeout. * Returns: *		If there is a timeout: pointer to filled in "timeout". *		If there is no timeout: NULL. */static struct sockd_io_t *io_gettimedout __P((void));/* * Scans all clients for one that has timed out according to config * settings. * Returns: *		If timed out client found: pointer to it. *		Else: NULL. */static voidcheckmother __P((struct sockd_mother_t *mother, fd_set *readset));/* * Checks if "mother" is set in "readset" and if so receives * a io from "mother".  Closes "mother" if there is an error. */static voidsiginfo __P((int sig));/* * Print information about our current connections. *//* Solaris sometimes fails to return srcaddress in recvfrom(). */#define UDPFROMLENCHECK(socket, fromlen) \	do { \		if (fromlen == 0) { \			static int failures; \\			swarnx("%s: system error: did not get address in recvfrom()", \			function); \\			if (++failures > 5) { \				swarnx("%s: running Solaris <= 2.5.1 are we?  " \				"giving up after %d failures", function, failures); \				delete_io(mother, io, (socket), IO_ERROR); \				failures = 0; \			} \			return; \		} \	} while (lintnoloop_sockd_h)__END_DECLSstatic struct sockd_io_t iov[SOCKD_IOMAX];	/* each child has these io's. */static int ioc = ELEMENTS(iov);voidrun_io(mother)	struct sockd_mother_t *mother;{	const char *function = "run_io()";	struct sigaction sigact;	int p;	sigemptyset(&sigact.sa_mask);	sigact.sa_flags	= SA_RESTART;	sigact.sa_handler = siginfo;#if HAVE_SIGNAL_SIGINFO	if (sigaction(SIGINFO, &sigact, NULL) != 0)		serr(EXIT_FAILURE, "%s: sigaction(SIGINFO)", function);#endif  /* HAVE_SIGNAL_SIGINFO */	/* same handler, for systems without SIGINFO. */	if (sigaction(SIGUSR1, &sigact, NULL) != 0)		serr(EXIT_FAILURE, "%s: sigaction(SIGINFO)", function);	proctitleupdate();	/* CONSTCOND */	while (1) {		int rbits, bits;		fd_set rset, wset, xset, newrset, controlset, tmpset;		struct sockd_io_t *io;		struct timeval timeout;		io_fillset(&xset, MSG_OOB);		rbits = io_fillset(&rset, 0);		if (mother->s != -1) {			FD_SET(mother->s, &rset);			rbits = MAX(rbits, mother->s);		}		else /* no mother.  Do we have any other descriptors to work with? */			if (rbits == -1) {				SASSERTX(allocated() == 0);				slog(LOG_DEBUG, "%s: can't find mother and no io's", function);				sockdexit(-EXIT_FAILURE);			}		/*		 * first find descriptors that are readable; we won't write if		 * we can't read.  Also select for exceptions so we can tell		 * the i/o function if there's one pending later.		 */		++rbits;		switch (selectn(rbits, &rset, NULL, &xset, io_gettimeout(&timeout))) {			case -1:				SERR(-1);				/* NOTREACHED */			case 0:				if ((io = io_gettimedout()) != NULL)					delete_io(mother->ack, io, -1, IO_TIMEOUT);				/* else: should only be possible if sighup received. */				continue;		}		checkmother(mother, &rset);		/*		 * This is tricky but we need to check for write separately to		 * avoid busylooping.		 * The problem is that if the descriptor is ready for reading but		 * the corresponding descriptor to write out on is not ready we will		 * be busylooping; above select will keep returning descriptors set,		 * but we will not be able to write (and thus read) them.		 * We therefore only set in wset the descriptors that have the		 * corresponding read descriptor readable so that when the		 * below select() returns, the io objects we get from wset will		 * be both readable and writable.		 *		 * Another problem is that if while we wait for writability, a new		 * descriptor becomes readable, we thus can't block forever here.		 * We solve this by in the below select() also checking for		 * readability, but now only the descriptors that were not found		 * to be readable in the previous select().		 * This means that a positive return from below select does not		 * necessarily indicate we have i/o to do, but it does mean we		 * either have it or a new descriptor became readable; in either		 * case, something has happened.		 * Reason we do not check for exceptions in this select is that		 * there is nothing we do about them until the descriptor becomes		 * readable too, thus any new exceptions will be in newrset before		 * we have reason to care about them.		 */		/* descriptors to check for readability; those not already set. */		bits = io_fillset(&tmpset, 0);		bits = fdsetop(bits + 1, '^', &rset, &tmpset, &newrset);		if (mother->s != -1) { /* mother status may change too. */			FD_SET(mother->s, &newrset);			bits = MAX(bits, mother->s);		}		/*		 * descriptors to check for writability aswell as		 * controldescriptors to check for readability.		 */		FD_ZERO(&wset);		FD_ZERO(&controlset);		for (p = 0; p < rbits; ++p) {			if (!FD_ISSET(p, &rset)) { /* only write after read. */				FD_CLR(p, &xset);	/* don't care about xset without rset */				continue;			}			io = io_finddescriptor(p);			SASSERTX(io != NULL);			if (io->in.s == p) {				/* read from in requires out to be writable. */				FD_SET(io->out.s, &wset);				bits = MAX(bits, io->out.s);			}			else if (io->out.s == p) {				/* read from out requires in to be writable. */				FD_SET(io->in.s, &wset);				bits = MAX(bits, io->in.s);			}			else {				SASSERTX(io->control.s == p);				FD_SET(io->control.s, &controlset);				/* also readable without matching writable. */				FD_SET(io->control.s, &newrset);				bits = MAX(bits, io->control.s);			}		}		if (bits++ < 0) {			SASSERTX(allocated() == 0			&& mother->s == mother->ack && mother->s < 0);			continue;		}		switch (selectn(bits, &newrset, &wset, NULL, io_gettimeout(&timeout))) {			case -1:				SERR(-1);				/* NOTREACHED */			case 0:				if ((io = io_gettimedout()) != NULL)					delete_io(mother->ack, io, -1, IO_TIMEOUT);				/* else: should only be possible if sighup received. */				continue;		}		checkmother(mother, &rset);		tmpset = controlset;		fdsetop(bits, '&', &newrset, &tmpset, &controlset);		/*		 * newrset; descriptors readable, all new apart from controldescriptors.		 *				Don't do anything with them here, loop around and check for		 *				writability first.		 *		 *	controlset; subset of newrset containing control descriptors		 *					that are readable.		 *		 * rset; descriptors readable, not necessarily with a match in wset.		 *		 * xset; subset of rset with exceptions pending.		 *		 * wset;	descriptors writable with a matching in rset/xset,		 *			what we can do i/o over.		 */		/*		 * First check all io's which have an exception pending.		 * Getting a io here does not mean we can do i/o over it		 * however.		 */		while ((io = io_getset(&xset)) != NULL) {			slog(LOG_DEBUG, "select(): exception set");			doio(mother->ack, io, &xset, &wset, MSG_OOB);			io_clearset(io, &xset);			io_clearset(io, &wset);			/* xset is subset of rset so clear rset too. */			io_clearset(io, &rset);		}		/*		 * Get all io's which are writable.  They will have a matching		 * descriptor that is readable.		 */		while ((io = io_getset(&wset)) != NULL) {			doio(mother->ack, io, &rset, &wset, 0);			io_clearset(io, &rset);			io_clearset(io, &wset);			/* xset is subset of rset so clear xset too. */			io_clearset(io, &xset);		}		/*		 * Get all io's which have controldescriptors that are readable.		 */		while ((io = io_getset(&controlset)) != NULL) {			fd_set nullset;			FD_ZERO(&nullset);			doio(mother->ack, io, &controlset, &nullset, 0);			io_clearset(io, &controlset);			/* controlset is subset of newrset so clear newrset too. */			io_clearset(io, &newrset);		}		/* possible future optimization: if newrset not empty, use it? */	}}static voiddelete_io(mother, io, fd, status)	int mother;	struct sockd_io_t *io;	int fd;	int status;{	const char *function = "delete_io()";	const int errno_s = errno;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -