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

📄 rvsocket.c

📁 基于h323协议的软phone
💻 C
📖 第 1 页 / 共 5 页
字号:
/***********************************************************************
Filename   : rvsocket.c
Description: enables OS-independent BSD4.4 sockets operations.
************************************************************************
                Copyright (c) 2001 RADVISION Inc.
************************************************************************
NOTICE:
This document contains information that is proprietary to RADVISION LTD.
No part of this publication may be reproduced in any form whatsoever
without written prior approval by RADVISION LTD..

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

#if defined(__cplusplus)
extern "C" {
#endif

#include "rvstdio.h"
#include "rvaddress.h"
#include "rvsocket.h"
#include "rvthread.h"
#include "rvlog.h"


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


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



/* Some definitions which are different between operating systems */
#if (RV_SOCKET_TYPE == RV_SOCKET_WIN32_WSA)

#pragma warning (disable: 4702)

#pragma warning (push,3)
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma warning (pop)

#define RV_LINGER_VALUE_TYPE u_short
#define RV_MULTICASTTTL_VALUE_TYPE int
#define RV_IOCTL_ARGP_TYPE u_long
#define RV_SOCKADDR_PTR struct sockaddr *
#define RV_IP_MREQ struct ip_mreq
#define RvSocketClose closesocket

/* Get the error number of the last error in the system */
#define RvSocketErrNo WSAGetLastError()

/* See if the socket's last error was "would block" */
#define RvSocketErrorWouldBlock(err) (err == WSAEWOULDBLOCK)


#elif (RV_SOCKET_TYPE == RV_SOCKET_BSD)

#if (RV_OS_TYPE == RV_OS_TYPE_SOLARIS) || \
    (RV_OS_TYPE == RV_OS_TYPE_LINUX) || \
    (RV_OS_TYPE == RV_OS_TYPE_TRU64) || \
    (RV_OS_TYPE == RV_OS_TYPE_HPUX) || \
    (RV_OS_TYPE == RV_OS_TYPE_UNIXWARE)
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#if (RV_OS_TYPE == RV_OS_TYPE_UNIXWARE)
#include <sys/filio.h>
#endif

#elif (RV_OS_TYPE == RV_OS_TYPE_WINCE)
#include <windows.h>
#include <winsock.h>

#define RvSocketErrNo GetLastError()
#define ioctl ioctlsocket
#define close closesocket

#elif (RV_OS_TYPE == RV_OS_TYPE_VXWORKS)
#include <ioLib.h>
#include <inetLib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <netinet/tcp.h>
#include <errno.h>
#include <signal.h>

#elif (RV_OS_TYPE == RV_OS_TYPE_OSE)
#include <inet.h>

#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <errno.h>
#include <signal.h>
#endif

#define RV_LINGER_VALUE_TYPE int
#define RV_MULTICASTTTL_VALUE_TYPE RvUint8
#if (RV_OS_TYPE == RV_OS_TYPE_OSE)
#define RV_IOCTL_ARGP_TYPE char
#else
#define RV_IOCTL_ARGP_TYPE RvUint32
#endif
#define RV_SOCKADDR_PTR struct sockaddr *
#define RV_IP_MREQ struct ip_mreq
#define RvSocketClose close

/* Get the error number of the last error in the system */
#define RvSelectStrError(_error) strerror(_error)
#ifndef RvSocketErrNo
#define RvSocketErrNo errno
#endif

/* See if the socket's last error was "would block" */
#define RvSocketErrorWouldBlock(err) (err == EWOULDBLOCK)


#elif (RV_SOCKET_TYPE == RV_SOCKET_PSOS)

#include <pna.h>
#include <errno.h>

#define FIONREAD FIOREAD

#define RV_LINGER_VALUE_TYPE int
#define RV_MULTICASTTTL_VALUE_TYPE RvUint8
#define RV_IOCTL_ARGP_TYPE char
#define RV_SOCKADDR_PTR struct sockaddr_in *
#define RV_IP_MREQ struct ip_mreq
#define RvSocketClose close

/* Get the error number of the last error in the system */
#define RvSocketErrNo errno

#define sa_family sin_family

/* See if the socket's last error was "would block" */
#define RvSocketErrorWouldBlock(err) (err == EWOULDBLOCK)


#elif (RV_SOCKET_TYPE == RV_SOCKET_NUCLEUS)

#include <nucleus.h>
#include <inc/nu_net.h>
#include <inc/tcp.h>

#include "rvselect.h"
#include "rvtimer.h"

#define SOCK_STREAM NU_TYPE_STREAM
#define SOCK_DGRAM NU_TYPE_DGRAM

#define RV_LINGER_VALUE_TYPE int
#define RV_MULTICASTTTL_VALUE_TYPE RvUint8
#define RV_IOCTL_ARGP_TYPE RvUint32
#define RV_SOCKADDR_PTR struct sockaddr_in *
#define RV_IP_MREQ IP_MREQ
#define RvSocketClose NU_Close_Socket

/* Replace the following with their Nucleus counterparts */
#define htonl TLS_Longswap
#define ntohl TLS_Longswap
#define htons TLS_Intswap
#define ntohs TLS_Intswap

#define AF_INET NU_FAMILY_IP
/* redefine structure names */
#define sockaddr_in addr_struct
#define sin_family family
#define sin_port port
#define sin_addr id.is_ip_addrs

#define in_addr SCK_IP_ADDR_STRUCT
#define s_addr sck_ip_addr

#ifndef RvSocketErrNo
#define RvSocketErrNo "error"
#endif

typedef enum
{
    RvSocketState_Idle,
    RvSocketState_Connecting,
    RvSocketState_Connected,
    RvSocketState_Closing,
    RvSocketState_Closed
} RvSocketState;

typedef enum
{
    RvThreadState_Idle,
    RvThreadState_Running,
    RvThreadState_Stopped
} RvThreadState;

typedef struct
{
    RvTimer*        timer;
    RvSocketState   socketState;
    RvThreadState   threadState;
    RvThread        threadId;
    RvAddress       sockAddress;
    RvSelectEngine* selectEngine;
} connectionInfo;

/* Array of information on each connection, used only by nucleus implementation */
connectionInfo* nuConInfo;      /* todo: change to hash table (key- socket) */

RvTimerQueue timerQueue;

/* NUCLEUS can't bind to 0. We have to find a specific port for NUCLEUS. If someone
   tries to bind NUCLEUS to port 0, we just use this global port range object. */
static RvPortRange RvSocketPortRange;

static void RvSocketTaskClean(IN RvSocket socket);
static void RvSocketEventsTask(RvThread *th, void* data);
static void RvSocketEvTimerExp(RvSocket socket);
RvStatus RvSocketCallback(IN RvSocket socketId, IN RvUint16 event);

#define RV_SOCKET_LOCK()    RV_OK
#define RV_SOCKET_UNLOCK()    RV_OK

#endif



/********************************************************************************************
 * RvSocketProtocolData
 * Structure of a connection manager protocol. This holds information about the different
 * types of supported network protocols.
 ********************************************************************************************/
typedef struct
{
  const RvChar* protocolName; /* Name of the protocol */
  int           protocol; /* The protocol itself */
  int           protocolType; /* Type of protocol */
} RvSocketProtocolData;



/* Information about the different types of network protocols supported */
static RvSocketProtocolData rvSocketProtocolInfo[] =
{
    {"UDP", IPPROTO_UDP,    SOCK_DGRAM},
    {"TCP", IPPROTO_TCP,    SOCK_STREAM}
};




/* Make sure SD_SEND is defined as 1. We use this when calling shutdown() to notify the TCP
   stack that we don't intend to send anything more. */
#ifndef SD_SEND
#define SD_SEND 1
#endif


/* Maximum size of sockaddr struct size we can handle */
#if RV_SOCKET_HAS_IPV6
#define RV_SOCKET_SOCKADDR_SIZE sizeof(struct sockaddr_storage)
#else
#define RV_SOCKET_SOCKADDR_SIZE sizeof(struct sockaddr_in)
#endif





/********************************************************************************************
 *
 *               Private functions - Socket sharer for pSOS
 *
 *
 * The following code implements a socket sharing service required to
 * circumvent thread-local socket concepts like PSoS/PNA.  Other OS's
 * don't use this service at all.
 *
 * The service creates and destroys all sockets from it's thread and
 * allows other threads to request socket sharing.  Once a thread has
 * shared a given socket, the information is cached so future references
 * to the socket from that thread do not access the service.
 *
 ********************************************************************************************/

#if (RV_SOCKET_USE_SHARER == 1)

typedef enum
{
    RvSocketSharerCommandExit, /* Exit socket sharer thread */
    RvSocketSharerCommandCreate, /* Create a new socket */
    RvSocketSharerCommandDestroy, /* Close a socket */
    RvSocketSharerCommandShare, /* Share an existing socket */
} RvSocketSharerCommand;

typedef struct
{
    /* The following fields are used for the command the sharer thread should process */
    RvSocketSharerCommand   command; /* Command to process */
    RvSocket*               socket; /* Socket we're dealing with */

    /* Creation parameters */
    RvAddressType       addressType; /* Address type for creation command */
    RvSocketProtocol    protocolType; /* Protocol type for creation command */

    /* Sharing parameters */
    RvThreadId          task; /* Task to share this socket with for sharing command */
    RvSocket*           sharableSocket; /* Resulting shared socket handle */
} RvSocketSharerCmd;


typedef struct
{
    RvLock              lock; /* Lock for the sharer operations */
    RvThread            thread; /* Socket sharer thread */
    RvSemaphore         requestSem; /* Semaphore posted to the sharer thread */
    RvSemaphore         responseSem; /* Semaphore posted from the sharer thread */
    RvSocketSharerCmd   cmd; /* Command to process in sharer thread */
    int                 result; /* Result of the processed command */
} RvSocketSharer;


static RvSocketSharer RvSharer; /* Socket sharer to use */


static void RvSocketSharerThread(IN RvThread* th, IN void* data)
{
    RvSocketSharer* sharer = (RvSocketSharer *)data;
    RvStatus res;
    RvBool exitThread = RV_FALSE;

    RV_UNUSED_ARG(th);

    while (!exitThread)
    {
        /* Let's wait until we have a request to process */
        res = RvSemaphoreWait(&sharer->requestSem);
        if (res != RV_OK)
            break;

        /* Process the command */
        switch (sharer->cmd.command)
        {
        case RvSocketSharerCommandExit:
            exitThread = RV_TRUE;
            break;
        case RvSocketSharerCommandCreate:
            sharer->result = RvSocketConstructHere(sharer->cmd.socket, sharer->cmd.addressType,
                sharer->cmd.protocolType);
            break;
        case RvSocketSharerCommandDestroy:
            sharer->result = RvSocketClose(*(sharer->cmd.socket));
            break;
        case RvSocketSharerCommandShare:
#if (RV_SOCKET_TYPE == RV_SOCKET_PSOS)
            *sharer->cmd.sharableSocket = shr_socket(sharer->cmd.socket, sharer->cmd.task);
            sharer->result = RV_OK; /* todo: check shr_socket result! */
#else
            *sharer->cmd.sharableSocket = *(sharer->cmd.socket);
            sharer->result = RV_OK;
#endif
            break;
        }

        /* Let's make sure the client doesn't wait any longer - we're done with this command */
        res = RvSemaphorePost(&sharer->responseSem);
        if (res != RV_OK)
            break;
    }
}


static RvStatus RvSocketSharerInit(void)
{
    RvStatus res;

    res = RvLockConstruct(&RvSharer.lock);
    if (res != RV_OK)
        return res;

⌨️ 快捷键说明

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