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

📄 udpstack.cxx

📁 RTP协议
💻 CXX
📖 第 1 页 / 共 3 页
字号:
/* ==================================================================== * The Vovida Software License, Version 1.0  *  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: *  * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. *  * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in *    the documentation and/or other materials provided with the *    distribution. *  * 3. The names "VOCAL", "Vovida Open Communication Application Library", *    and "Vovida Open Communication Application Library (VOCAL)" must *    not be used to endorse or promote products derived from this *    software without prior written permission. For written *    permission, please contact vocal@vovida.org. * * 4. Products derived from this software may not be called "VOCAL", nor *    may "VOCAL" appear in their name, without prior written *    permission of Vovida Networks, Inc. *  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. *  * ==================================================================== *  * This software consists of voluntary contributions made by Vovida * Networks, Inc. and many individuals on behalf of Vovida Networks, * Inc.  For more information on Vovida Networks, Inc., please see * <http://www.vovida.org/>. * */static const char* const UdpStack_cxx_Version =    "$Id: UdpStack.cxx,v 1.35.2.1 2003/01/30 22:39:10 bko Exp $";/* TODO List * - add sendTo function to allow you to specifiy different destinations * - add recvFrom function that tell you who the packet came from  * - add non blockinge version fo send and receive * - derive "ReliableUDP" stack that takes care of retransmissions * - look into using MSG_ERRQUEUE to check for ICMP errors * - check portability  * - support IP6  * - stress test  */#include "global.h"#include <fstream>#include <assert.h>#include <string.h> // for memset#include <errno.h>#include <iostream>#include <stdio.h>#include <netdb.h>#include <sys/types.h>#include <netinet/in.h> // for struct sockaddr_in#include <stdlib.h>#include <strstream>#include <arpa/inet.h>#include <sys/socket.h>#include "VTime.hxx"#include <unistd.h>#include <sys/uio.h>#ifndef __vxworks#include <fcntl.h>#endif#ifdef __APPLE__#include "TransportCommon.hxx"#endif#include "vovida-endian.h"#if defined(__svr4__)#include <xil/xil.h>#if (XIL_API_MINOR_VERSION - 0 == 3)typedef int socklen_t;#endif#endif#ifdef __FreeBSD__#include <isc/eventlib.h>#endif#ifdef __APPLE__typedef int socklen_t;#endif#include "UdpStack.hxx"#include "cpLog.h"#include "vsock.hxx"#include "LockHelper.hxx"#include "InitTransport.hxx"#include "NetworkConfig.hxx"// This is a file that contains multicast definitions for window support// contact nismail@cisco.com#ifdef WIN32#include "W32McastCfg.hxx"#endifstatic VMutex G_lock;static const char separator[7] = "\n****\n";UdpStack::UdpStack ( const NetworkAddress* desHost                     /* null if this is the server */ ,                     int minPort,                     int maxPort,                     UdpMode udpMode,                     bool log_flag,                     bool isMulticast)        :        packetLossProbability( float(0.0) ),        numBytesReceived (0),        numPacketsReceived (0),        numBytesTransmitted (0),        numPacketsTransmitted (0),        mode (sendrecv),        logFlag (log_flag),	blockingFlg(true){	initTransport();    data = new UdpStackPrivateData();    assert(data);    mode = udpMode;    data->socketFd = socket(NetworkConfig::instance().getAddrFamily(), SOCK_DGRAM, IPPROTO_UDP);    cpLog (LOG_DEBUG_STACK, "UdpStack socketFd = %d", data->socketFd);    if ( data->socketFd < 0 )    {#if !defined(WIN32)        int err = errno;        strstream errMsg;        errMsg << "UdpStack::::UdpStack error during socket creation:";        errMsg << "Reason " << strerror(err) << ends;        cpLog(LOG_ERR,  errMsg.str());        throw UdpStackException(errMsg.str());#else		int err = WSAGetLastError();		cpLog(LOG_ERR, "UdpStack: socket failed: %d", err);		assert(0);#endif    }    int buf1 = 1;    int len1 = sizeof(buf1);    int rcvbuf = 0;    int rcvbufnew = 240 * 1024;    int rcvbufnewlen = sizeof(rcvbufnew);    int sndbuf = 0;    unsigned int rcvbuflen = 1;    unsigned int sndbuflen = 1;#ifdef __linux__    struct protoent * protoent;    protoent = getprotobyname("icmp");    if (!protoent)    {        fprintf(stderr, "Cannot get icmp protocol\n");    }    else    {        if (setsockopt(data->socketFd, protoent->p_proto, SO_BSDCOMPAT,                       (char*)&buf1, len1)                == -1)        {            fprintf(stderr, "setsockopt error SO_BSDCOMPAT :%s\n",                    strerror(errno));        }#if 1        if (setsockopt(data->socketFd, SOL_SOCKET, SO_RCVBUF,                       (int *)&rcvbufnew, rcvbufnewlen)                == -1)        {            fprintf(stderr, "setsockopt error SO_RCVBUF :%s\n",                    strerror(errno));        }#endif        if (getsockopt(data->socketFd, SOL_SOCKET, SO_RCVBUF,                        (int*)&rcvbuf, &rcvbuflen) == -1)        {            fprintf(stderr, "getsockopt error SO_RCVBUF :%s\n",                    strerror(errno));        }        else        {            cpLog(LOG_DEBUG, "SO_RCVBUF = %d, rcvbuflen  =%d" , rcvbuf , rcvbuflen);        }        if (getsockopt(data->socketFd, SOL_SOCKET, SO_SNDBUF,                        (int*)&sndbuf, &sndbuflen) == -1)        {            fprintf(stderr, "getsockopt error SO_SNDBUF :%s\n",                    strerror(errno));        }        else        {            cpLog(LOG_DEBUG, "SO_SNDBUF = %d, sndbuflen = %d" , sndbuf , sndbuflen);        }    }#endif    if (isMulticast)    {        // set option to get rid of the "Address already in use" error        if (setsockopt(data->socketFd, SOL_SOCKET, SO_REUSEADDR,                       (char*)&buf1, len1)                == -1)        {            fprintf(stderr, "setsockopt error SO_REUSEADDR :%s",                    strerror(errno));        }#if defined(__FreeBSD__) || defined(__APPLE__)        if (setsockopt(data->socketFd, SOL_SOCKET, SO_REUSEPORT,                       (char*)&buf1, len1)                == -1)        {            fprintf(stderr, "setsockopt error SO_REUSEPORT :%s",                    strerror(errno));        }#endif    }    switch (mode)    {        case inactive :        {            cpLog(LOG_INFO, "Udp stack is inactive");            cpLog(LOG_ERR, "desHost is saved for future use.");            doClient(desHost);        }        break;        case sendonly :        {            if ( desHost )            {                // set the remote address                doClient(desHost);            }            else            {                cpLog(LOG_DEBUG_STACK, "sendonly Udp stack, desHost is needed by using setDestination()");            }        }        break;        case recvonly :        {            if ( desHost )            {                cpLog(LOG_ERR,                      "recvonly Udp stack, desHost is saved for future use.");                doClient(desHost);            }            else            {                // only receive, do bind socket to local port                doServer(minPort, maxPort);            }        }        break;        case sendrecv :        {            if ( desHost )            {                // receive and send,                // bind the socket to local port and set the remote address                doServer(minPort, maxPort);                doClient(desHost);            }            else            {                // only receive, do bind socket to local port                doServer(minPort, maxPort);                cpLog(LOG_DEBUG_STACK, "sendrecv Udp stack, desHost is needed by using setDestination()");            }        }        break;        default :        cpLog(LOG_ERR, "undefined mode for udp stack");        break;    }    //    logFlag = true;    strstream logFileNameRcv;    strstream logFileNameSnd;    if (logFlag)    {        in_log = new ofstream(logFileNameRcv.str(), ios::app);        if (!in_log)        {            cerr << "Cannot open file "            << logFileNameRcv.str() << endl;            logFileNameRcv.freeze(false);            logFlag = false;        }        else        {            in_log->write ("UdpRcv\n", 7);            strstream lcPort;            lcPort << "localPort: " << getTxPort() << "\n" << char(0);            in_log->write(lcPort.str(), strlen(lcPort.str()));            lcPort.freeze(false);            logFileNameRcv.freeze(false);            rcvCount = 0;        }        out_log = new ofstream(logFileNameSnd.str(), ios::app);        if (!out_log)        {            cerr << "Cannot open file "            << logFileNameSnd.str() << endl;            logFileNameSnd.freeze(false);            logFlag = false;        }        else        {            if (! logFlag)                logFlag = true;            out_log->write ("UdpSnd\n", 7);            logFileNameSnd.freeze(false);            sndCount = 0;        }    }}voidUdpStack::doServer ( int minPort,                     int maxPort )  // these are lcoal ports{    /*        cpLog (LOG_DEBUG_STACK, "UdpStack::doServer");        cpLog (LOG_DEBUG_STACK, "minPort = %d, maxPort = %d", minPort, maxPort);    */    LockHelper helper(_lock);    // this is a server    if ( (minPort == -1) && (maxPort == -1) )    {        minPort = 1024;        maxPort = 65534;    }    if ( maxPort == -1 )    {        maxPort = minPort;    }    // reset name now that the port range is defined    strstream aName;    aName << "-receiver-" << ":"    << "[" << minPort    << "-" << maxPort << "]"    << char(0);    setLclName( aName.str() );    aName.freeze(false);    // find a port to use    int portOk = false;    int err = 0;    int bError = false;    struct addrinfo hints;    struct addrinfo *sa;    memset(&hints, 0, sizeof(hints));    hints.ai_flags = AI_PASSIVE;    hints.ai_family = NetworkConfig::instance().getAddrFamily();    hints.ai_socktype = SOCK_DGRAM;    // here it assigns the port, the local port    // & bind the addr(INADDR_ANY+port) to the socket    for (int localPort = minPort; localPort <= maxPort; localPort++ )    {	char currport[6];	sprintf(currport, "%u", localPort);        cpLog(LOG_DEBUG_STACK, "getaddrinfo()");	int error = getaddrinfo(NULL, currport, &hints, &sa);	if (error) {		perror(gai_strerror(error));                continue;	}        cpLog(LOG_DEBUG, "Udp bind() fd =%d, port=%s", data->socketFd, currport); //port = %d(h_order), %d(n_order)", data->socketFd, localPort, (data->localAddr).sin6_port);        if (bind(data->socketFd, sa->ai_addr, sa->ai_addrlen))        {            err = errno;        #if !defined(WIN32)            if ( err == EADDRINUSE )            {        #else            /* Fix suggested by Anandprasanna Gaitonde, prasanna@controlnet.co.in */        //    err = WSAGetLastError();         //   if ( err == WSAEADDRINUSE )          //          #endif                freeaddrinfo(sa);                continue;  // this port is in use - try the next one            }            int err = errno;            strstream errMsg;            errMsg << "UdpStack<" << getLclName() << ">::UdpStack error during socket bind: ";            errMsg << strerror(err);            errMsg << char(0);		bError = true;            cpLog(LOG_ERR, "%s",  errMsg.str());        }        else        {            portOk = true;            memcpy(data->localAddr, sa->ai_addr, sa->ai_addrlen);	    bError = false;            if(sa->ai_family == AF_INET6)            {                cpLog(LOG_DEBUG, "(IPv6) Udp bound to fd = %d, port = %d",data->socketFd, localPort);                //Set the sockoption so that we get get source IP                //when running on the same host                int on=1;                setsockopt(data->socketFd, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on));            }            else            {                cpLog(LOG_DEBUG, "(IPv4) Udp bound to fd = %d, port = %d",data->socketFd, localPort);            }        }        freeaddrinfo(sa);	if (portOk) break;    }    if (bError) throw UdpStackException("fecked");//errMsg.str());    // deal with errors    if (!portOk)    {        // all ports are in use        //localPort = -1;        strstream errMsg;        errMsg << "UdpStack<" << getLclName()        << ">::UdpStack all ports in range "        << minPort << " to " << maxPort        << " are in use.";        errMsg << char(0);        cpLog(LOG_ERR, errMsg.str());        throw UdpStackExceptionPortsInUse(errMsg.str());        errMsg.freeze(false);        assert(0);    }    // reset name now that the port is defined    strstream aName2;    aName2 << "-receiver-" << ":" << minPort << char(0);    setLclName( aName2.str() );    aName2.freeze(false);}voidUdpStack::doClient ( const NetworkAddress* desHost) // This is the destination port{        //cpLog (LOG_DEBUG_STACK, "UdpStack::doClient");    //cpLog (LOG_DEBUG_STACK, "desHost = %s, desPort = %d",     //           desHost->getIpName().c_str(), desHost->getPort());    // this is a client    assert (desHost);    desHost->getSockAddr(data->remoteAddr);}voidUdpStack::connectPorts(){    if ((mode == recvonly) || (mode == inactive))    {        cpLog(LOG_ERR, "The UdpStack is recvonly or inactive.");        return ;    }    int result;    // conenct to server    if ((result = connect(data->socketFd,                          (struct sockaddr*) & (data->localAddr),                          sizeof(*data->localAddr))) != 0)    {        int err = errno;        strstream errMsg;        errMsg << "UdpStack<" << getLclName() << " " << getRmtName()        << ">::UdpStack error during socket connect: ";        errMsg << strerror(err);        errMsg << char(0);        cpLog(LOG_ERR,  errMsg.str());        throw UdpStackException(errMsg.str());        errMsg.freeze(false);        assert(0);    }}// After testing, this method currently is not working on Linux and Sun4// possibily because the system are not supporting it.// Now the work around is to call connect twice.voidUdpStack::disconnectPorts(){    if ((mode == recvonly) || (mode == inactive))    {        cpLog(LOG_ERR, "The UdpStack is recvonly or inactive.");        return ;    }

⌨️ 快捷键说明

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