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

📄 rvselect.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 5 页
字号:
            /* 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 */
            fdUpdate.fd = fd->fd;
            fdUpdate.events = 0;
            fdUpdate.revents = 0;
            if (translatedEvents & RV_SELECT_READ)
                fdUpdate.events |= POLLIN;
            if (translatedEvents & RV_SELECT_WRITE)
                fdUpdate.events |= POLLOUT;

            /* Write the change to /dev/poll */
            if (write(selectEngine->fdDevPoll, &fdUpdate, sizeof(fdUpdate)) == sizeof(fdUpdate))
            {
                fd->devpollEvents = fdUpdate.events; /* Know what we're waiting for */

                RvLockGet(&selectEngine->lock);

                /* We've got one more fd in /dev/poll */
                selectEngine->maxFdInDevPoll++;

                RvLockRelease(&selectEngine->lock);
            }
            else
            {
                RvSelectLogError((&rvSelectLogSource,
                    "RvSelectAdd: Can't add fd=%d with %d", fd->fd, selectEvents));
                ret = RvSelectErrorCode(RV_ERROR_UNKNOWN);
            }
        }
    }
#endif

    if (ret == RV_OK)
    {
        /* Write down the events of this fd in its struct */
        fd->callback = eventsCb;
        fd->events = selectEvents;
#if (RV_OS_TYPE == RV_OS_TYPE_NUCLEUS)
        RvSocketSetSelectEngine(*RvFdGetSocket(fd), (void*)selectEngine);
#endif
        rvFdPreempt(selectEngine);
    }

    if ((ret != RV_OK) && allocatedBucketHash)
        fdBucketHashRemove(selectEngine, fd);

    RvSelectLogLeave((&rvSelectLogSource, "RvSelectAdd(fd=%d)=%d", fd->fd, ret));
    return ret;
}


/********************************************************************************************
 * RvSelectRemove
 *
 * purpose : Remove a file descriptor that is being checked by this engine
 * input   : selectEngine   - Events engine of this fd
 *           fd             - File descriptor to remove
 * output  : None
 * return  : RV_OK on success, other on failure
 * notes   : This function should only be called directly when the user wants the file
 *           descriptor to remain valid and active, but use it with a different events
 *           engine.
 *           Calling this function just before calling RvFdDestruct() on the same file
 *           descriptor will cause RvFdDestruct() to log an error message.
 ********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSelectRemove(
    IN RvSelectEngine*      selectEngine,
    IN RvSelectFd*          fd)
{
    RvStatus status = RV_OK;

    RvSelectLogEnter((&rvSelectLogSource, "RvSelectRemove(fd=%d)", fd->fd));

    if (fd->events != (RvSelectEvents)0)
    {
        /* Remove the events from the bucket hash */
        fd->events = (RvSelectEvents)0;
        status = fdBucketHashRemove(selectEngine, fd);
    }

#if (RV_SELECT_TYPE == RV_SELECT_WIN32_WSA)
    if (status == RV_OK)
    {
        MSG msg;

        /* Make sure the network sends no events on this fd */
        if (WSAAsyncSelect(fd->fd, selectEngine->hNetEventsWnd, 0, 0) != 0)
            status = RvSelectErrorCode(RV_ERROR_UNKNOWN);

        if (GetCurrentThreadId() == selectEngine->threadId)
        {
            /* Post an ending message - when we reach it - we're done here */
            PostMessage(selectEngine->hNetEventsWnd, FD_NET_LOOP_END, 0, 0);

            /* Clear current message queue from this socket */
            while (PeekMessage(&msg, selectEngine->hNetEventsWnd,
                FD_NET_MESSAGE, FD_NET_LOOP_END, PM_REMOVE))
            {
                if (LOWORD(msg.message) == FD_NET_LOOP_END)
                {
                    /* We reached the end of the queue - exit */
                    break;
                }

                /* Make sure that network events not related to this socket are being posted
                   back into the message queue */
                if (msg.wParam != (WPARAM)fd->fd)
                   PostMessage(selectEngine->hNetEventsWnd, FD_NET_MESSAGE, msg.wParam, msg.lParam);
            }
        }
    }


#elif (RV_SELECT_TYPE == RV_SELECT_WIN32_COMPLETION)


#elif (RV_SELECT_TYPE == RV_SELECT_SELECT)
    if (status == RV_OK)
    {
#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))
            status = RvSelectErrorCode(RV_ERROR_OUTOFRANGE);
#endif  /* RV_RANGECHANGE */

        if (status == RV_OK)
        {
            RvLockGet(&selectEngine->lock);

            /* Remove this client */
            FD_CLR(fd->fd, &selectEngine->rdSet);
            FD_CLR(fd->fd, &selectEngine->wrSet);

            /* Update the maximum limit of select() if we have to */
            if (fd->fd == selectEngine->maxFdInSelect)
            {
                RvSocket minFd = (fd->fd - 1);
                while ((selectEngine->maxFdInSelect > 0) &&
                    (!FD_ISSET(minFd, &selectEngine->rdSet)) &&
                    (!FD_ISSET(minFd, &selectEngine->wrSet)))
                {
                    minFd--;
                    selectEngine->maxFdInSelect--;
                }
            }

            RvLockRelease(&selectEngine->lock);
        }
    }


#elif (RV_SELECT_TYPE == RV_SELECT_POLL)
    if (status == RV_OK)
    {
#ifdef RV_RANGECHECK
        if ((fd->fd < 0) || (fd->fd >= selectEngine->maxFd))
            status = RvSelectErrorCode(RV_ERROR_OUTOFRANGE);
#endif  /* RV_RANGECHANGE */

        if (status == RV_OK)
        {
            RvLockGet(&selectEngine->lock);

            selectEngine->maxFdInPoll--; /* We have one less */

            /* Remove this client from fdArray - we don't want holes in our array, so we'll
               just move the last one to fill in the gap */
            if (selectEngine->maxFdInPoll != fd->fdArrayIndex)
            {
                RvSelectFd* movedFd;

                /* It's not the last - fill it in */
                memcpy(selectEngine->fdArray + fd->fdArrayIndex,
                    selectEngine->fdArray + selectEngine->maxFdInPoll, sizeof(struct pollfd));

                /* We'll also need to move the fd itself... */
                movedFd = fdBucketHashFind(selectEngine, selectEngine->fdArray[fd->fdArrayIndex].fd);
                if (movedFd != NULL)
                {
                    movedFd->fdArrayIndex = fd->fdArrayIndex;
                }
                /* todo: handle errors */
            }

            RvLockRelease(&selectEngine->lock);
        }
    }


#elif (RV_SELECT_TYPE == RV_SELECT_DEVPOLL)
    if (status == RV_OK)
    {
        struct pollfd fdRemove;

#ifdef RV_RANGECHECK
        if ((fd->fd < 0) || (fd->fd >= selectEngine->maxFd))
            status = RvSelectErrorCode(RV_ERROR_OUTOFRANGE);
#endif  /* RV_RANGECHANGE */

        if (status == RV_OK)
        {
            fdRemove.fd = fd->fd;
            fdRemove.events = POLLREMOVE;
            fdRemove.revents = 0;

            /* Write the change to /dev/poll */
            if (write(selectEngine->fdDevPoll, &fdRemove, sizeof(fdRemove)) == sizeof(fdRemove))
            {
                RvLockGet(&selectEngine->lock);

                /* We've got one less fd in /dev/poll */
                selectEngine->maxFdInDevPoll--;

                RvLockRelease(&selectEngine->lock);
            }
            else
            {
                RvSelectLogError((&rvSelectLogSource,
                    "RvSelectRemove: Can't remove fd=%d", fd->fd));
                status = RvSelectErrorCode(RV_ERROR_UNKNOWN);
            }
        }
    }
#endif

    if (status == RV_OK)
        status = rvFdPreempt(selectEngine);

    RvSelectLogLeave((&rvSelectLogSource, "RvSelectRemove(fd=%d)=%d", fd->fd, status));
    return status;
}


/********************************************************************************************
 * RvSelectUpdate
 *
 * purpose : Update the events of callback used for a given file descriptor
 * input   : selectEngine   - Events engine of this fd
 *           fd             - File descriptor to update
 *           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 RvSelectUpdate(
    IN RvSelectEngine*      selectEngine,
    IN RvSelectFd*          fd,
    IN RvSelectEvents       selectEvents,
    IN RvSelectCb           eventsCb)
{
    RvStatus status = RV_OK;
    RvBool anyChanges = RV_FALSE;

    RvSelectLogEnter((&rvSelectLogSource,
        "RvSelectUpdate(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));

#if (RV_SELECT_TYPE == RV_SELECT_WIN32_WSA)
    {
        if (WSAAsyncSelect(fd->fd, selectEngine->hNetEventsWnd, FD_NET_MESSAGE, selectEvents) == 0)
            anyChanges = RV_TRUE;
        else
            status = RvSelectErrorCode(RV_ERROR_UNKNOWN);
    }

#elif (RV_SELECT_TYPE == RV_SELECT_WIN32_COMPLETION)


#elif (RV_SELECT_TYPE == RV_SELECT_SELECT)
    {
        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))
            status = RvSelectErrorCode(RV_ERROR_OUTOFRANGE);
#endif  /* RV_RANGECHECK */

        if (status == RV_OK)
        {
            /* Since Unix systems support only Read/Write events, we have to translate
               the richer set of events we have */
            translatedEvents = rvSelectToOS(selectEvents);
            anyChanges = RV_TRUE; /* Always think we have changes - simplify matters */

            RvLockGet(&selectEngine->lock);

            if (translatedEvents & RV_SELECT_READ)
                RV_FD_SET(fd->fd, &selectEngine->rdSet);
            else
                FD_CLR(fd->fd, &selectEngine->rdSet);
            if (translatedEvents & RV_SELECT_WRITE)
                RV_FD_SET(fd->fd, &selectEngine->wrSet);
            else
                FD_CLR(fd->fd, &selectEngine->wrSet);

            RvLockRelease(&selectEngine->lock);
        }
    }


#elif (RV_SELECT_TYPE == RV_SELECT_POLL)
    {
        RvSelectEvents translatedEvents;
        struct pollfd* pollFdElem;
        short newEvents;

#ifdef RV_RANGECHECK
        if ((fd->fd < 0) || (fd->fd >= selectEngine->maxFd))
            status = RvSelectErrorCode(RV_ERROR_OUTOFRANGE);
#endif  /* RV_RANGECHANGE */

        if (status == RV_OK)
        {
            /* Find the entry to fill in */
            pollFdElem = selectEngine->fdArray + fd->fdArrayIndex;

#ifdef RV_OTHERCHECK
            /* Make sure we're updating the right fd */
            if (pollFdElem->fd != fd->fd)
            {
                RvSelectLogExcep((&rvSelectLogSource,
                    "RvSelectUpdate: Updating fd=%d with fd=%d.", pollFdElem->fd, fd->fd));
                status = RV_ERROR_BADPARAM;
            }
#endif

            /* Since Unix systems support only Read/Write events, we have to translate
               the richer set of events we have */
            translatedEvents = rvSelectToOS(selectEvents);
            newEvents = 0;
            if (translatedEvents & RV_SELECT_READ)
                newEvents |= POLLIN;
            if (translatedEvents & RV_SELECT_WRITE)
                newEvents |= POLLOUT;

            if (newEvents != pollFdElem->events)
            {
                /* Fill in the pollfd element - it's updated now */
                pollFdElem->revents = 0;
                pollFdElem->events = newEvents;
                anyChanges = RV_TRUE;
            }
        }
    }


#elif (RV_SELECT_TYPE == RV_SELECT_DEVPOLL)
    if (status == RV_OK)
    {
        RvSelectEvents translatedEvents;
        struct pollfd fdUpdate[2];
        RvSize_t writeSize;
        int updateIndex;
        short newEvents;

#ifdef RV_RANGECHECK
        if ((fd->fd < 0) || (fd->fd >= selectEngine->maxFd))
            status = RvSelectErrorCode(RV_ERROR_OUTOFRANGE);
#endif  /* RV_RANGECHANGE */

        if (status == RV_OK)
        {
            /* Since Unix systems support only Read/Write events, we have to translate
               the richer set of events we have */
            translatedEvents = rvSelectToOS(selectEvents);
            newEvents = 0;
            if (translatedEvents & RV

⌨️ 快捷键说明

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