📄 sockgen.c
字号:
}
#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 + -