📄 rvselect.c
字号:
{
RvSprintf(windowName, "%s%p", RV_FD_EVENTS_CLASS, selectEngine);
selectEngine->hNetEventsWnd =
CreateWindow(RV_FD_EVENTS_CLASS, windowName,
WS_OVERLAPPED | WS_MINIMIZE,
0, 0, 0, 0, NULL, NULL, NULL/*hInstance*/, NULL);
if (selectEngine->hNetEventsWnd == NULL)
{
CloseHandle(selectEngine->threadHandle);
status = RvSelectErrorCode(RV_ERROR_UNKNOWN);
}
}
if (status == RV_OK)
{
selectEngine->threadId = GetCurrentThreadId();
#ifdef SetWindowLongPtr
/* 64bit support for Windows */
SetWindowLongPtr(selectEngine->hNetEventsWnd, GWLP_USERDATA, (LONG_PTR)selectEngine);
#else
SetWindowLong(selectEngine->hNetEventsWnd, GWL_USERDATA, (LONG)selectEngine);
#endif
}
}
#elif (RV_SELECT_TYPE == RV_SELECT_WIN32_COMPLETION)
selectEngine->completionPort =
CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)0, 0);
if (selectEngine->completionPort == NULL)
status = RvSelectErrorCode(RV_ERROR_UNKNOWN);
#elif (RV_SELECT_TYPE == RV_SELECT_SELECT)
selectEngine->maxFd = rvSelectMaxDescriptors;
selectEngine->maxFdInSelect = 0;
/* Clear file descriptor sets */
FD_ZERO(&selectEngine->rdSet);
FD_ZERO(&selectEngine->wrSet);
FD_ZERO(&selectEngine->tmpRdSet);
FD_ZERO(&selectEngine->tmpWrSet);
#elif (RV_SELECT_TYPE == RV_SELECT_POLL)
selectEngine->maxFd = rvSelectMaxDescriptors;
selectEngine->maxFdInPoll = 0;
status = RvMemoryAlloc(NULL, (void**)&selectEngine->fdArray, sizeof(struct pollfd) * rvSelectMaxDescriptors);
#elif (RV_SELECT_TYPE == RV_SELECT_DEVPOLL)
selectEngine->maxFd = rvSelectMaxDescriptors;
selectEngine->maxFdInDevPoll = 0;
/* Open /dev/poll file descriptor we'll use */
if ((selectEngine->fdDevPoll = open("/dev/poll", O_RDWR)) < 0)
status = RvSelectErrorCode(RV_ERROR_UNKNOWN);
else
{
status = RvMemoryAlloc(NULL, (void**)&selectEngine->fdArray, sizeof(struct pollfd) * rvSelectMaxDescriptors);
if (status != RV_OK)
close(selectEngine->fdDevPoll);
}
#endif
status = rvFdPreemptionConstruct(selectEngine);
#if (RV_SELECT_PREEPEMTION_TYPE == RV_SOCKET_PREEMPTION_SOCKET) || \
(RV_SELECT_PREEPEMTION_TYPE == RV_SOCKET_PREEMPTION_PIPE)
if (status == RV_OK)
{
}
#endif
if (status != RV_OK)
{
fdBucketHashDestruct(selectEngine);
RvLockDestruct(&selectEngine->lock);
}
return status;
}
/********************************************************************************************
* RvSelectDestruct
*
* purpose : Destruct a file descriptor engine
* input : selectEngine - Events engine to destruct
* output : None
* return : RV_OK on success, other on failure
********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSelectDestruct(IN RvSelectEngine* selectEngine)
{
#if (RV_SELECT_TYPE == RV_SELECT_WIN32_WSA)
DestroyWindow(selectEngine->hNetEventsWnd);
CloseHandle(selectEngine->threadHandle);
#elif (RV_SELECT_TYPE == RV_SELECT_WIN32_COMPLETION)
CloseHandle(selectEngine->completionPort);
#elif (RV_SELECT_TYPE == RV_SELECT_SELECT)
/* Nothing special to do actually */
#elif (RV_SELECT_TYPE == RV_SELECT_POLL)
RvMemoryFree(selectEngine->fdArray);
#elif (RV_SELECT_TYPE == RV_SELECT_DEVPOLL)
close(selectEngine->fdDevPoll);
RvMemoryFree(selectEngine->fdArray);
#endif
rvFdPreemptionDestruct(selectEngine);
/* Deallocate the bucket hash we're using */
fdBucketHashDestruct(selectEngine);
/* Kill the lock */
RvLockDestruct(&selectEngine->lock);
RvLogSourceDestruct(RvLogGet(), &rvSelectLogSource);
return RV_OK;
}
/********************************************************************************************
* RvFdConstruct
*
* purpose : Construct a file descriptor for a given socket
* input : fd - File descriptor to construct
* s - Socket to use for this file descriptor
* output : None
* return : RV_OK on success, other on failure
********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvFdConstruct(
IN RvSelectFd* fd,
IN RvSocket* s)
{
#ifdef RV_NULLCHECK
if ((fd == NULL) || (s == NULL))
return RvSelectErrorCode(RV_ERROR_NULLPTR);
#endif
fd->fd = *s;
return RV_OK;
}
/********************************************************************************************
* RvFdDestruct
*
* purpose : Destruct a file descriptor of a given socket
* input : fd - File descriptor to destruct
* output : None
* return : RV_OK on success, other on failure
********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvFdDestruct(
IN RvSelectFd* fd)
{
RV_UNUSED_ARG(fd);
return RV_OK;
}
/********************************************************************************************
* RvFdGetSocket
*
* purpose : Get the socket associated with the file descriptor struct
* input : fd - File descriptor
* return : Socket associated with the file descriptor on success
* NULL on failure
********************************************************************************************/
RVCOREAPI
RvSocket* RVCALLCONV RvFdGetSocket(IN RvSelectFd* fd)
{
#ifdef RV_NULLCHECK
if (fd == NULL)
return NULL;
#endif
return &fd->fd;
}
/********************************************************************************************
* RvSelectGetEvents
*
* purpose : Return the list of events we're waiting on for a given file descriptor
* input : fd - File descriptor
* output : None
* return : Events we're waiting on
********************************************************************************************/
RVCOREAPI
RvSelectEvents RVCALLCONV RvSelectGetEvents(IN RvSelectFd* fd)
{
#ifdef RV_NULLCHECK
if (fd == NULL)
return (RvSelectEvents)0;
#endif
return fd->events;
}
/********************************************************************************************
* RvSelectFindFd
*
* purpose : Find the RvSelectFd object by the socket/file descriptor it's connected to.
* This one is used by H.323 to allow calls to seliCallOn() from the stack's
* API.
* input : selectEngine - Events engine to look in
* s - Socket/file descriptor object to find
* output : None
* return : RvSelectFd object if one exists, NULL otherwise.
********************************************************************************************/
RVCOREAPI
RvSelectFd* RVCALLCONV RvSelectFindFd(
IN RvSelectEngine* selectEngine,
IN RvSocket* s)
{
#ifdef RV_NULLCHECK
if ((selectEngine == NULL) || (s == NULL))
return NULL;
#endif
return fdBucketHashFind(selectEngine, *s);
}
/********************************************************************************************
* RvSelectAdd
*
* purpose : Add a new file descriptor to those being checked
* input : selectEngine - Events engine of this fd
* fd - File descriptor to check
* selectEvents - Events to check
* eventsCb - Callback to use when these events occur
* output : None
* return : RV_OK on success, other on failure
********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSelectAdd(
IN RvSelectEngine* selectEngine,
IN RvSelectFd* fd,
IN RvSelectEvents selectEvents,
IN RvSelectCb eventsCb)
{
RvBool allocatedBucketHash = RV_FALSE;
RvStatus ret = RV_OK;
RvSelectLogEnter((&rvSelectLogSource,
"RvSelectAdd(fd=%d,events=%s%s%s%s%s,cb=%p)", fd->fd,
fdGetEventStr((RvSelectEvents)(selectEvents & RvSelectRead)),
fdGetEventStr((RvSelectEvents)(selectEvents & RvSelectWrite)),
fdGetEventStr((RvSelectEvents)(selectEvents & RvSelectAccept)),
fdGetEventStr((RvSelectEvents)(selectEvents & RvSelectConnect)),
fdGetEventStr((RvSelectEvents)(selectEvents & RvSelectClose)),
eventsCb));
/* Add the events to the bucket hash */
ret = fdBucketHashAdd(selectEngine, fd);
if (ret == RV_OK)
allocatedBucketHash = RV_TRUE;
#if (RV_SELECT_TYPE == RV_SELECT_WIN32_WSA)
if (ret == RV_OK)
{
if (WSAAsyncSelect(fd->fd, selectEngine->hNetEventsWnd, FD_NET_MESSAGE, selectEvents) != 0)
ret = RvSelectErrorCode(RV_ERROR_UNKNOWN);
}
#elif (RV_SELECT_TYPE == RV_SELECT_WIN32_COMPLETION)
{
HANDLE ioCompletionPort;
ioCompletionPort = CreateIoCompletionPort((HANDLE)fd->fd,
selectEngine->completionPort, (ULONG_PTR)fd, 0);
if (ioCompletionPort == NULL)
ret = RvSelectErrorCode(RV_ERROR_UNKNOWN);
}
#elif (RV_SELECT_TYPE == RV_SELECT_SELECT)
if (ret == RV_OK)
{
RvSelectEvents translatedEvents;
#if (RV_OS_TYPE != RV_OS_TYPE_WINCE) && defined(RV_RANGECHECK)
/* Windows CE doesn't really care that the socket's fd value is within
the range of FD_SETSIZE. This is because the fd_set struct is actually
defined more like poll - a list of fd's to select and not a bits buffer.
If we'll range check for WinCE we'll just get errors after several socket
constructions. */
if ((fd->fd < 0) || (fd->fd >= selectEngine->maxFd))
ret = RvSelectErrorCode(RV_ERROR_OUTOFRANGE);
#endif /* (RV_OS_TYPE != RV_OS_TYPE_WINCE) && defined(RV_RANGECHECK) */
if (ret == RV_OK)
{
RvLockGet(&selectEngine->lock);
/* Update the maximum limit of select() if we have to */
if (fd->fd > selectEngine->maxFdInSelect)
selectEngine->maxFdInSelect = fd->fd;
/* Since Unix systems support only Read/Write events, we have to translate
the richer set of events we have */
translatedEvents = rvSelectToOS(selectEvents);
if (translatedEvents & RV_SELECT_READ)
RV_FD_SET(fd->fd, &selectEngine->rdSet);
if (translatedEvents & RV_SELECT_WRITE)
RV_FD_SET(fd->fd, &selectEngine->wrSet);
RvLockRelease(&selectEngine->lock);
}
}
#elif (RV_SELECT_TYPE == RV_SELECT_POLL)
if (ret == RV_OK)
{
RvSelectEvents translatedEvents;
struct pollfd* pollFdElem;
#ifdef RV_RANGECHECK
if ((fd->fd < 0) || (fd->fd >= selectEngine->maxFd))
ret = RvSelectErrorCode(RV_ERROR_OUTOFRANGE);
#endif /* RV_RANGECHANGE */
if (ret == RV_OK)
{
RvLockGet(&selectEngine->lock);
/* Find the entry to fill in */
pollFdElem = selectEngine->fdArray + selectEngine->maxFdInPoll;
/* Since Unix systems support only Read/Write events, we have to translate
the richer set of events we have */
translatedEvents = rvSelectToOS(selectEvents);
/* Fill in the pollfd element */
pollFdElem->fd = fd->fd;
pollFdElem->events = 0;
pollFdElem->revents = 0;
if (translatedEvents & RV_SELECT_READ)
pollFdElem->events |= POLLIN;
if (translatedEvents & RV_SELECT_WRITE)
pollFdElem->events |= POLLOUT;
/* Make sure to link the fd to this one */
fd->fdArrayIndex = selectEngine->maxFdInPoll;
/* Update the array size for poll() */
selectEngine->maxFdInPoll++;
RvLockRelease(&selectEngine->lock);
}
}
#elif (RV_SELECT_TYPE == RV_SELECT_DEVPOLL)
if (ret == RV_OK)
{
RvSelectEvents translatedEvents;
struct pollfd fdUpdate;
#ifdef RV_RANGECHECK
if ((fd->fd < 0) || (fd->fd >= selectEngine->maxFd))
ret = RvSelectErrorCode(RV_ERROR_OUTOFRANGE);
#endif /* RV_RANGECHANGE */
if (ret == RV_OK)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -