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

📄 sockgen.c

📁 嵌入式Linux系统用的web server,开源代码,非常好用
💻 C
📖 第 1 页 / 共 2 页
字号:
}
#endif /* ! UEMF */

/******************************************************************************/
/*
 *	Define the events of interest
 */

void socketRegisterInterest(socket_t *sp, int handlerMask)
{
	a_assert(sp);

	sp->handlerMask = handlerMask;
#ifndef UEMF
	if (handlerMask) {
		sp->fileHandle = emfCreateFileHandler(sp->sock, handlerMask,
			(emfFileProc *) socketEventProc, (void *) sp->sid);
	} else {
		emfDeleteFileHandler(sp->fileHandle);
		sp->fileHandle = -1;
	}
#endif /* ! UEMF */
}

/******************************************************************************/
/*
 *	Wait until an event occurs on a socket. Return 1 on success, 0 on failure.
 *	or -1 on exception (UEMF only)
 */

int socketWaitForEvent(socket_t *sp, int handlerMask, int *errCode)
{
	int	mask;

	a_assert(sp);

	mask = sp->handlerMask;
	sp->handlerMask |= handlerMask;
	while (socketSelect(sp->sid, 1000)) {
		if (sp->currentEvents & (handlerMask | SOCKET_EXCEPTION)) {
			break;
		}
	}
	sp->handlerMask = mask;
	if (sp->currentEvents & SOCKET_EXCEPTION) {
		return -1;
	} else if (sp->currentEvents & handlerMask) {
		return 1;
	}
	if (errCode) {
		*errCode = errno = EWOULDBLOCK;
	}
	return 0;
}

/******************************************************************************/
/*
 *	Return TRUE if there is a socket with an event ready to process,
 */

int socketReady(int sid)
{
	socket_t 	*sp;
	int			all;

	all = 0;
	if (sid < 0) {
		sid = 0;
		all = 1;
	}

	for (; sid < socketMax; sid++) {
		if ((sp = socketList[sid]) == NULL) {
			if (! all) {
				break;
			} else {
				continue;
			}
		} 
		if (sp->flags & SOCKET_CONNRESET) {
			socketCloseConnection(sid);
			return 0;
		}
		if (sp->currentEvents & sp->handlerMask) {
			return 1;
		}
/*
 *		If there is input data, also call select to test for new events
 */
		if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid) > 0) {
			socketSelect(sid, 0);
			return 1;
		}
		if (! all) {
			break;
		}
	}
	return 0;
}

/******************************************************************************/
/*
 * 	Wait for a handle to become readable or writable and return a number of 
 *	noticed events. Timeout is in milliseconds.
 */

#if (defined (WIN) || defined (CE) || defined (NW))

int socketSelect(int sid, int timeout)
{
	struct timeval	tv;
	socket_t		*sp;
	fd_set		 	readFds, writeFds, exceptFds;
	int 			nEvents;
	int				all, socketHighestFd;	/* Highest socket fd opened */

	FD_ZERO(&readFds);
	FD_ZERO(&writeFds);
	FD_ZERO(&exceptFds);
	socketHighestFd = -1;

	tv.tv_sec = timeout / 1000;
	tv.tv_usec = (timeout % 1000) * 1000;

/*
 *	Set the select event masks for events to watch
 */
	all = nEvents = 0;

	if (sid < 0) {
		all++;
		sid = 0;
	}

	for (; sid < socketMax; sid++) {
		if ((sp = socketList[sid]) == NULL) {
			continue;
		}
		a_assert(sp);
/*
 * 		Set the appropriate bit in the ready masks for the sp->sock.
 */
		if (sp->handlerMask & SOCKET_READABLE) {
			FD_SET(sp->sock, &readFds);
			nEvents++;
			if (socketInputBuffered(sid) > 0) {
				tv.tv_sec = 0;
				tv.tv_usec = 0;
			}
		}
		if (sp->handlerMask & SOCKET_WRITABLE) {
			FD_SET(sp->sock, &writeFds);
			nEvents++;
		}
		if (sp->handlerMask & SOCKET_EXCEPTION) {
			FD_SET(sp->sock, &exceptFds);
			nEvents++;
		}
		if (! all) {
			break;
		}
	}

/*
 *	Windows select() fails if no descriptors are set, instead of just sleeping
 *	like other, nice select() calls. So, if WIN, sleep.
 */
	if (nEvents == 0) {
		Sleep(timeout);
		return 0;
	}

/*
 * 	Wait for the event or a timeout.
 */
	nEvents = select(socketHighestFd+1, &readFds, &writeFds, &exceptFds, &tv);

	if (all) {
		sid = 0;
	}
	for (; sid < socketMax; sid++) {
		if ((sp = socketList[sid]) == NULL) {
			continue;
		}

		if (FD_ISSET(sp->sock, &readFds) || socketInputBuffered(sid) > 0) {
				sp->currentEvents |= SOCKET_READABLE;
		}
		if (FD_ISSET(sp->sock, &writeFds)) {
				sp->currentEvents |= SOCKET_WRITABLE;
		}
		if (FD_ISSET(sp->sock, &exceptFds)) {
				sp->currentEvents |= SOCKET_EXCEPTION;
		}
		if (! all) {
			break;
		}
	}

	return nEvents;
}

#else /* not WIN || CE || NW */

int socketSelect(int sid, int timeout)
{
	socket_t		*sp;
	struct timeval	tv;
	fd_mask 		*readFds, *writeFds, *exceptFds;
	int 			all, len, nwords, index, bit, nEvents;

/*
 *	Allocate and zero the select masks
 */
	nwords = (socketHighestFd + NFDBITS) / NFDBITS;
	len = nwords * sizeof(int);

	readFds = balloc(B_L, len);
	memset(readFds, 0, len);
	writeFds = balloc(B_L, len);
	memset(writeFds, 0, len);
	exceptFds = balloc(B_L, len);
	memset(exceptFds, 0, len);

	tv.tv_sec = timeout / 1000;
	tv.tv_usec = (timeout % 1000) * 1000;

/*
 *	Set the select event masks for events to watch
 */
	all = nEvents = 0;

	if (sid < 0) {
		all++;
		sid = 0;
	}

	for (; sid < socketMax; sid++) {
		if ((sp = socketList[sid]) == NULL) {
			if (all == 0) {
				break;
			} else {
				continue;
			}
		}
		a_assert(sp);

/*
 * 		Initialize the ready masks and compute the mask offsets.
 */
		index = sp->sock / (NBBY * sizeof(fd_mask));
		bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));
		
/*
 * 		Set the appropriate bit in the ready masks for the sp->sock.
 */
		if (sp->handlerMask & SOCKET_READABLE) {
			readFds[index] |= bit;
			nEvents++;
			if (socketInputBuffered(sid) > 0) {
				tv.tv_sec = 0;
				tv.tv_usec = 0;
			}
		}
		if (sp->handlerMask & SOCKET_WRITABLE) {
			writeFds[index] |= bit;
			nEvents++;
		}
		if (sp->handlerMask & SOCKET_EXCEPTION) {
			exceptFds[index] |= bit;
			nEvents++;
		}
		if (! all) {
			break;
		}
	}

/*
 * 	Wait for the event or a timeout. Reset nEvents to be the number of actual
 *	events now.
 */
	nEvents = select(socketHighestFd + 1, (fd_set *) readFds,
		(fd_set *) writeFds, (fd_set *) exceptFds, &tv);

	if (nEvents > 0) {
		if (all) {
			sid = 0;
		}
		for (; sid < socketMax; sid++) {
			if ((sp = socketList[sid]) == NULL) {
				if (all == 0) {
					break;
				} else {
					continue;
				}
			}

			index = sp->sock / (NBBY * sizeof(fd_mask));
			bit = 1 << (sp->sock % (NBBY * sizeof(fd_mask)));

			if (readFds[index] & bit || socketInputBuffered(sid) > 0) {
				sp->currentEvents |= SOCKET_READABLE;
			}
			if (writeFds[index] & bit) {
				sp->currentEvents |= SOCKET_WRITABLE;
			}
			if (exceptFds[index] & bit) {
				sp->currentEvents |= SOCKET_EXCEPTION;
			}
			if (! all) {
				break;
			}
		}
	}

	bfree(B_L, readFds);
	bfree(B_L, writeFds);
	bfree(B_L, exceptFds);

	return nEvents;
}
#endif /* WIN || CE */

/******************************************************************************/
/*
 *	Process socket events
 */

void socketProcess(int sid)
{
	socket_t	*sp;
	int			all;

	all = 0;
	if (sid < 0) {
		all = 1;
		sid = 0;
	}
/*
 * 	Process each socket
 */
	for (; sid < socketMax; sid++) {
		if ((sp = socketList[sid]) == NULL) {
			if (! all) {
				break;
			} else {
				continue;
			}
		}
		if (socketReady(sid)) {
			socketDoEvent(sp);
		}
		if (! all) {
			break;
		}
	}
}

/******************************************************************************/
/*
 *	Process an event on the event queue
 */

static int socketDoEvent(socket_t *sp)
{
	ringq_t		*rq;
	int 		sid;

	a_assert(sp);

	sid = sp->sid;
	if (sp->currentEvents & SOCKET_READABLE) {
		if (sp->flags & SOCKET_LISTENING) { 
			socketAccept(sp);
			sp->currentEvents = 0;
			return 1;
		} 

	} else {
/*
 *		If there is still read data in the buffers, trigger the read handler
 *		NOTE: this may busy spin if the read handler doesn't read the data
 */
		if (sp->handlerMask & SOCKET_READABLE && socketInputBuffered(sid) > 0) {
			sp->currentEvents |= SOCKET_READABLE;
		}
	}


/*
 *	If now writable and flushing in the background, continue flushing
 */
	if (sp->currentEvents & SOCKET_WRITABLE) {
		if (sp->flags & SOCKET_FLUSHING) {
			rq = &sp->outBuf;
			if (ringqLen(rq) > 0) {
				socketFlush(sp->sid);
			} else {
				sp->flags &= ~SOCKET_FLUSHING;
			}
		}
	}

/*
 *	Now invoke the users socket handler. NOTE: the handler may delete the
 *	socket, so we must be very careful after calling the handler.
 */
	if (sp->handler && (sp->handlerMask & sp->currentEvents)) {
		(sp->handler)(sid, sp->handlerMask & sp->currentEvents, 
			sp->handler_data);
/*
 *		Make sure socket pointer is still valid, then reset the currentEvents.
 */ 
		if (socketList && sid < socketMax && socketList[sid] == sp) {
			sp->currentEvents = 0;
		}
	}
	return 1;
}

/******************************************************************************/
/*
 *	Set the socket blocking mode
 */

int socketSetBlock(int sid, int on)
{
	socket_t		*sp;
	unsigned long	flag;
	int				iflag;
	int				oldBlock;

	flag = iflag = !on;

	if ((sp = socketPtr(sid)) == NULL) {
		a_assert(0);
		return 0;
	}
	oldBlock = (sp->flags & SOCKET_BLOCK);
	sp->flags &= ~(SOCKET_BLOCK);
	if (on) {
		sp->flags |= SOCKET_BLOCK;
	}

/*
 *	Put the socket into block / non-blocking mode
 */
	if (sp->flags & SOCKET_BLOCK) {
#if (defined (CE) || defined (WIN))
		ioctlsocket(sp->sock, FIONBIO, &flag);
#elif (defined (ECOS))
		int off;
		off = 0;
		ioctl(sp->sock, FIONBIO, &off);
#elif (defined (VXWORKS) || defined (NW))
		ioctl(sp->sock, FIONBIO, (int)&iflag);
#else
		fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) & ~O_NONBLOCK);
#endif

	} else {
#if (defined (CE) || defined (WIN))
		ioctlsocket(sp->sock, FIONBIO, &flag);
#elif (defined (ECOS))
		int on;
		on = 1;
		ioctl(sp->sock, FIONBIO, &on);
#elif (defined (VXWORKS) || defined (NW))
		ioctl(sp->sock, FIONBIO, (int)&iflag);
#else
		fcntl(sp->sock, F_SETFL, fcntl(sp->sock, F_GETFL) | O_NONBLOCK);
#endif
	}
	return oldBlock;
}

/******************************************************************************/
/*
 *	Return true if a readable socket has buffered data. - not public
 */

int socketDontBlock()
{
	socket_t	*sp;
	int			i;

	for (i = 0; i < socketMax; i++) {
		if ((sp = socketList[i]) == NULL || 
				(sp->handlerMask & SOCKET_READABLE) == 0) {
			continue;
		}
		if (socketInputBuffered(i) > 0) {
			return 1;
		}
	}
	return 0;
}

/******************************************************************************/
/*
 *	Return true if a particular socket buffered data. - not public
 */

int socketSockBuffered(int sock)
{
	socket_t	*sp;
	int			i;

	for (i = 0; i < socketMax; i++) {
		if ((sp = socketList[i]) == NULL || sp->sock != sock) {
			continue;
		}
		return socketInputBuffered(i);
	}
	return 0;
}

#endif /* (!WIN) | LITTLEFOOT | WEBS */

/******************************************************************************/


⌨️ 快捷键说明

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