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

📄 rvselect.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 5 页
字号:
/***********************************************************************
Filename   : rvselect.c
Description: select interface (select, poll, /dev/poll, etc.)
************************************************************************
        Copyright (c) 2001 RADVISION Inc. and RADVISION Ltd.
************************************************************************
NOTICE:
This document contains information that is confidential and proprietary
to RADVISION Inc. and RADVISION Ltd.. No part of this document may be
reproduced in any form whatsoever without written prior approval by
RADVISION Inc. or RADVISION Ltd..

RADVISION Inc. and RADVISION Ltd. reserve the right to revise this
publication and make changes without obligation to notify any person of
such revisions or changes.
***********************************************************************/


#include "rvmemory.h"
#include "rvstdio.h"
#include "rvtime.h"
#include "rvsocket.h"
#include "rvlog.h"
#include "rvselect.h"


#if ((RV_SELECT_TYPE == RV_SELECT_WIN32_WSA) || (RV_SELECT_TYPE == RV_SELECT_WIN32_COMPLETION))


/* --------------------------------------- select() ----------------------------------- */
#elif (RV_SELECT_TYPE == RV_SELECT_SELECT)

#if (RV_OS_TYPE == RV_OS_TYPE_NUCLEUS)
#include <inc/nu_net.h>
#include <time.h>


#define RvSelectErrNo "error"

#define FD_SETSIZE 2048

#elif (RV_OS_TYPE == RV_OS_TYPE_OSE)
#include <inet.h>
/*#include <unistd.h>     for O_NONBLOCK */

#define RvSelectErrNo errno

#endif

#define SELECT_FD_SETSIZE FD_SETSIZE


/* --------------------------------------- poll() ----------------------------------- */
#elif (RV_SELECT_TYPE == RV_SELECT_POLL)

#include <sys/resource.h>


/* --------------------------------------- /dev/poll ----------------------------------- */
#elif (RV_SELECT_TYPE == RV_SELECT_DEVPOLL)

#include <sys/resource.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
#include <sys/devpoll.h>

#endif


#if ((RV_OS_TYPE == RV_OS_TYPE_SOLARIS) || \
     (RV_OS_TYPE == RV_OS_TYPE_TRU64) || \
     (RV_OS_TYPE == RV_OS_TYPE_LINUX) || \
     (RV_OS_TYPE == RV_OS_TYPE_EMBLINUX) || \
     (RV_OS_TYPE == RV_OS_TYPE_HPUX))

#include <fcntl.h>
#include <errno.h>

/* Handle OS error numbers */
#define RvSelectStrError(_error) strerror(_error)
#define RvSelectErrNo errno


#elif (RV_OS_TYPE == RV_OS_TYPE_UNIXWARE)

#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/select.h>

/* Handle OS error numbers */
#define RvSelectStrError(_error) strerror(_error)
#define RvSelectErrNo errno


#elif (RV_OS_TYPE == RV_OS_TYPE_VXWORKS)
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include <errno.h>

#define RvSelectErrNo errnoGet()

#elif (RV_OS_TYPE == RV_OS_TYPE_PSOS)
#include <errno.h>

#define RvSelectErrNo errno

#endif  /* RV_OS_TYPE */

#if (RV_OS_TYPE == RV_OS_TYPE_NUCLEUS)
#define RV_FD_SET NU_FD_Set
#else
#define RV_FD_SET FD_SET
#endif

/* Lets make error codes a little easier to type */
#define RvSelectErrorCode(_e) RvErrorCode(RV_ERROR_LIBCODE_CCORE, RV_CCORE_MODULE_SELECT, (_e))

/* Lets make log functions a little easier to type */
#define RvSelectLogExcep(funcParams)    RvLogExcep(&rvSelectLogSource, funcParams)
#define RvSelectLogError(funcParams)    RvLogError(&rvSelectLogSource, funcParams)
#define RvSelectLogWarning(funcParams)  RvLogWarning(&rvSelectLogSource, funcParams)
#define RvSelectLogInfo(funcParams)     RvLogInfo(&rvSelectLogSource, funcParams)
#define RvSelectLogDebug(funcParams)    RvLogDebug(&rvSelectLogSource, funcParams)
#define RvSelectLogEnter(funcParams)    RvLogEnter(&rvSelectLogSource, funcParams)
#define RvSelectLogLeave(funcParams)    RvLogLeave(&rvSelectLogSource, funcParams)


/* Log source for the connection manager */
static RvLogSource rvSelectLogSource;

#if (RV_OS_TYPE == RV_OS_TYPE_NUCLEUS)
static RvUint32 RvNuSelect(RvUint32 nfds, 
	        				 fd_set *readfds, 
			        		 fd_set *writefds, 
					         fd_set *exceptfds, 
					         struct timeval *timeout);
#endif

#if ((RV_SELECT_TYPE == RV_SELECT_SELECT) || \
    (RV_SELECT_TYPE == RV_SELECT_POLL) || \
    (RV_SELECT_TYPE == RV_SELECT_DEVPOLL))
/* Maximum number of file descriptors to allocate for Unix operating systems */
static RvUint32 rvSelectMaxDescriptors;

#endif



/* Return the string value of a given event */
/* This function is not declared as static to remove warnings on release compilations */
const char* fdGetEventStr(IN RvSelectEvents ev)
{
    switch (ev)
    {
        case RvSelectRead:     return "Read ";
        case RvSelectWrite:    return "Write ";
        case RvSelectAccept:   return "Accept ";
        case RvSelectConnect:  return "Connect ";
        case RvSelectClose:    return "Close ";
    }

    return "";
}



/********************************************************************************************
 *
 *                  Bucket Hash Functions
 *
 ********************************************************************************************/


/********************************************************************************************
 * fdBucketHashConstruct
 * purpose : Create the bucket hash for our use
 * input   : selectEngine   - Events engine to use
 *           maxHashSize    - Size of bucket hash to create
 * output  : none
 * return  : RV_OK on success, other on failure
 ********************************************************************************************/
static RvStatus fdBucketHashConstruct(
    IN RvSelectEngine*      selectEngine,
    IN RvUint32             maxHashSize)
{
    RvStatus result;

    /* Create the lock for synchronization */
    result = RvLockConstruct(&selectEngine->hashLock);
    if (result != RV_OK)
        return result;

    /* Allocate a bucket hash for use later on */
    selectEngine->maxHashSize = maxHashSize;
    result =  RvMemoryAlloc(NULL, (void**)&selectEngine->hash, sizeof(RvSelectFd*) * maxHashSize);

    if (result != RV_OK)
    {
        RvLockDestruct(&selectEngine->hashLock);
        return result;
    }

    memset(selectEngine->hash, 0, sizeof(RvSelectFd*) * maxHashSize);
    return result;
}


/********************************************************************************************
 * fdBucketHashDestruct
 * purpose : Kills the bucket hash
 * input   : selectEngine - Events engine to use
 * output  : none
 * return  : RV_OK on success, other on failure
 ********************************************************************************************/
static RvStatus fdBucketHashDestruct(
    IN RvSelectEngine*    selectEngine)
{
    RvLockDestruct(&selectEngine->hashLock);
    return RvMemoryFree(selectEngine->hash);
}


/********************************************************************************************
 * fdBucketHashFind
 * purpose : Find the file descriptor struct from its OS value
 *           This function looks inside the bucket hash for the specific OS value
 * input   : selectEngine - Events engine to use
 *           osFd           - OS fd value to search for
 * output  : none
 * return  : File descriptor struct on success, NULL on failure
 ********************************************************************************************/
static RvSelectFd* fdBucketHashFind(IN RvSelectEngine* selectEngine, IN RvSocket osFd)
{
    RvSelectFd* fdChecked;

    RvLockGet(&selectEngine->hashLock);

    fdChecked = selectEngine->hash[osFd % selectEngine->maxHashSize];

    while ((fdChecked != NULL) && (fdChecked->fd != osFd))
        fdChecked = fdChecked->nextInBucket; /* Search on */

    RvLockRelease(&selectEngine->hashLock);

    return fdChecked;
}


/********************************************************************************************
 * fdBucketHashAdd
 * purpose : Add the file descriptor to the bucket hash
 * input   : selectEngine - Events engine to use
 *           fd             - fd to add
 * output  : none
 * return  : RV_OK on success, other on failure
 ********************************************************************************************/
static RvStatus fdBucketHashAdd(IN RvSelectEngine* selectEngine, IN RvSelectFd* fd)
{
    RvSelectFd** bucket;

    RvLockGet(&selectEngine->hashLock);

    /* Find the bucket for this fd */
    bucket = &(selectEngine->hash[fd->fd % selectEngine->maxHashSize]);

    /* Put this fd first in this bucket */
    fd->nextInBucket = *bucket;
    *bucket = fd;

    RvLockRelease(&selectEngine->hashLock);
    return RV_OK;
}


/********************************************************************************************
 * fdBucketHashRemove
 * purpose : Remove the file descriptor from the bucket hash
 * input   : selectEngine - Events engine to use
 *           fd             - fd to remove
 * output  : none
 * return  : RV_OK on success, other on failure
 ********************************************************************************************/
static RvStatus fdBucketHashRemove(IN RvSelectEngine* selectEngine, IN RvSelectFd* fd)
{
    RvStatus ret = RV_OK;
    RvSelectFd** bucket;
    RvSelectFd* prev; /* Previous fd in the bucket - NULL if we found the first one */
    RvSelectFd* curFd; /* Current checked fd in the bucket */

    RvLockGet(&selectEngine->hashLock);

    /* Find this fd in bucket hash and remember its previous one */
    prev = NULL;
    bucket = &(selectEngine->hash[fd->fd % selectEngine->maxHashSize]);
    curFd = *bucket;
    while ((curFd != NULL) && (curFd->fd != fd->fd))
    {
        prev = curFd;
        curFd = curFd->nextInBucket;
    }

    if (curFd != NULL)
    {
        /* Remove this fd from the bucket hash */
        if (prev != NULL)
            prev->nextInBucket = curFd->nextInBucket; /* Not first in bucket */
        else
            *bucket = curFd->nextInBucket; /* First in bucket - update the first one */
    }
    else
    {
        /* Seems like we can't find this fd */
        ret = RvSelectErrorCode(RV_ERROR_BADPARAM);
    }

    RvLockRelease(&selectEngine->hashLock);

    return ret;
}






/********************************************************************************************
 *
 *                  Preemption Functions
 *
 ********************************************************************************************/
#if (RV_SELECT_PREEPEMTION_TYPE == RV_SOCKET_PREEMPTION_SOCKET) || \
    (RV_SELECT_PREEPEMTION_TYPE == RV_SOCKET_PREEMPTION_PIPE)
static void rvFdPreemptionCallback(
    IN RvSelectEngine*      selectEngine,
    IN RvSelectFd*          fd,
    IN RvSelectEvents       selectEvent,
    IN RvBool               error)
{
    RvUint8 buf[100];
    RvSize_t bytesRead;
    RvStatus ret = RV_OK;

    RV_UNUSED_ARG(selectEngine);
    RV_UNUSED_ARG(selectEvent);
    RV_UNUSED_ARG(error);

    /* Clear the events in this pipe/socket - it served its purpose */
    bytesRead = sizeof(buf);
    while ((bytesRead == sizeof(buf)) && (ret == RV_OK))
    {
#if (RV_SELECT_PREEPEMTION_TYPE == RV_SOCKET_PREEMPTION_SOCKET)
        ret = RvSocketReceiveBuffer(&fd->fd, buf, sizeof(buf), &bytesRead, NULL);
#elif (RV_SELECT_PREEPEMTION_TYPE == RV_SOCKET_PREEMPTION_PIPE)
        if (read(fd->fd, buf, sizeof(buf)) <= 0)
            ret = RV_ERROR_UNKNOWN; /* We're done clearing the pipe */
#endif
    }
}


/********************************************************************************************
 * rvFdPreemptionConstruct
 * purpose : Construct a preemption fd to use when we want to stop a select() loop from
 *           blocking.
 * input   : selectEngine - Events engine to use
 * output  : none
 * return  : RV_OK on success, other on failure
 ********************************************************************************************/
static RvStatus rvFdPreemptionConstruct(
    IN RvSelectEngine   *selectEngine)
{
    RvStatus status;

#if (RV_SELECT_PREEPEMTION_TYPE == RV_SOCKET_PREEMPTION_SOCKET)
    {
        RvUint8 localIp[4] = {127,0,0,1};
        RvUint32* ipPtr = (RvUint32*)localIp;

        RvAddressConstructIpv4(&selectEngine->localAddress, *ipPtr, RV_ADDRESS_IPV4_ANYPORT);

        status = RvSocketConstruct(&selectEngine->preemptionSocket, RV_ADDRESS_TYPE_IPV4, RvSocketProtocolUdp);
        if (status != RV_OK)
            return status;

⌨️ 快捷键说明

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