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

📄 quicknetdevice.cxx

📁 Vovida 社区开源的 SIP 协议源码
💻 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 QuickNetDevice_cxx_Version =    "$Id: QuickNetDevice.cxx,v 1.44 2002/03/19 21:40:16 jason Exp $";#include "global.h"/* stdlib */#include <iostream>#include <cstdio>#include <unistd.h>#include <sys/ioctl.h>#include <csignal>/* sockets */#include <sys/types.h>#include <sys/socket.h>#include <fcntl.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <cerrno>#include <linux/telephony.h>#include <linux/ixjuser.h>#include "VTime.hxx"#include "Rtp.hxx"#include "VCondition.h"/* error handling */#include "QuickNetDevice.hxx"#include "UaDeviceEvent.hxx"#include "UaConfiguration.hxx"// #define ULAW_PAYLOAD 1012#define ULAW_SAMPLE_RATE 240#define RESID_RTP_RATE 240#define NETWORK_RTP_RATE 160#define FLASH_TIMEOUT 1000000using namespace Vocal;//***************************************************************************// QuickNetDevice::QuickNetDevice// description:  Constructor.  opens the quicknet device.  initialize the//               hookstate.  resets the device to get it ready.//***************************************************************************QuickNetDevice::QuickNetDevice( const char* deviceName,                                Sptr < Fifo < Sptr < SipProxyEvent > > > inputQ,                                Sptr < Fifo < Sptr < SipProxyEvent > > > outputQ )        : ResGwDevice( deviceName, inputQ, outputQ ),        audioStack(0),        inRtpPkt(0),        ringbackFd( -1),        sendRingback(false),        cwBeep( 0 ),        cwCadenceOn( true ),        cwCnt( 0 ),        cwBeepOn( false ){    // initialize queues    sessionQ = outputQ;    myQ = inputQ;    // open hardware device    myFD = open(deviceName, O_RDWR);    if (myFD < 0)    {        cpLog( LOG_ERR, "Cannot open %s", deviceName );        exit( 1 );    }    // close and reopen to make sure device is not in a funny state    ioctl(myFD, IXJCTL_PORT, PORT_POTS);    ioctl(myFD, PHONE_REC_STOP);    ioctl(myFD, PHONE_PLAY_STOP);    ioctl(myFD, IXJCTL_AEC_STOP);    close(myFD);    myFD = open(deviceName, O_RDWR);    ioctl(myFD, IXJCTL_PORT, PORT_POTS);    if (myFD < 0)    {        cpLog( LOG_ERR, "Cannot re-open ", deviceName );        exit(1);    }    // initialize hookstate    if (ioctl(myFD, PHONE_HOOKSTATE))        hookStateOffhook = true;    else        hookStateOffhook = false;    // store the device name.    myDeviceName = deviceName;    stdinFD = fileno( stdin );    tcgetattr( stdinFD, &initialTerm );    struct termios termAttr = initialTerm;    termAttr.c_lflag &= ~ICANON;    termAttr.c_cc[VMIN] = 1;    termAttr.c_cc[VTIME] = 0;    if ( tcsetattr( stdinFD, TCSANOW, &termAttr ) != 0 )    {        cerr << "Unable to set new terminal mode."  << endl;        exit( -1 );    }    if( fcntl( stdinFD, F_SETFL, O_NONBLOCK ) == -1 )    {        cerr << "Unable to set stdin mode."  << endl;        exit( -1 );    }    // read in the call waiting beep from tone file    cpLog( LOG_DEBUG, "reading call waiting beep from Tone/cwbeep" );    int cwBeepFd = open("Tone/cwbeep", O_RDONLY);    if ( cwBeepFd == -1 )    {        cpLog( LOG_ERR, "can not open Tone/cwbeep" );        return;    }    cwBeep = new char[CWBEEP_ON_TIME];    int nsample = read(cwBeepFd, cwBeep, CWBEEP_ON_TIME);    if ( nsample != CWBEEP_ON_TIME )        cpLog( LOG_ERR, "Not enougth call waiting beep samples read" );    else        cpLog( LOG_DEBUG, "call waiting beep successfully read");    close(cwBeepFd);}  // end QuickNetDevice::QuickNetDevice()//***************************************************************************// QuickNetDevice::~QuickNetDevice// description:  Destructor//***************************************************************************QuickNetDevice::~QuickNetDevice(){    close(myFD);    tcsetattr( stdinFD, TCSANOW, &initialTerm );} // end QuickNetDevice::~QuickNetDevice()//***************************************************************************// QuickNetDevice::hardwareMain// description:  main processing loop of the hardware//***************************************************************************void*QuickNetDevice::hardwareMain (void* parms){    // process forever on behalf of QuickNetDevice hardware    fd_set readfds;    struct timeval tv;    int retval;    int maxFd = 128;  // should be 0 then increment as needed when addToFdSet    // reset file descriptor    FD_ZERO(&readfds);    addToFdSet(&readfds);    /**     * block on select for asyncronous events, but poll to process     * audio and signal requests from endpoints in message queue     * The following values were optimized by trial and error for     * the quicknet ixj-0.3.18gpl drivers.     */    tv.tv_sec = 0;    tv.tv_usec = 300;    if((retval = select(maxFd, &readfds, 0, 0, &tv)) < 0)    {        cpLog( LOG_ERR, "select() returned error %d", retval );    }    else    {        if(process(&readfds) < 0)        {            cpLog( LOG_ERR, "hardware encountered an error" );            assert(0);        }    }    if( myQ->size() > 0 )    {        cpLog( LOG_DEBUG, "Signal from call control" );        processSessionMsg( myQ->getNext() );    }    return 0;} // end QuickNetDevice::hardwareMain()voidQuickNetDevice::processUrlInput(){    char keystroke = '\0';    if( read( stdinFD, &keystroke, 1 ) == 0 )    {        return;    }    if( !hookStateOffhook )    {        cpLog( LOG_ERR, "The phone must be off-hook first" );        return;    // Ignore input is it is not off hook    }    Sptr < UaDeviceEvent > event = new UaDeviceEvent( sessionQ ) ;    assert( event != 0 );    if(myEntryState == EntryStateEnterUrl)    {        // the user is entering a URL, so do something else        switch( keystroke )        {            case '\x08':            case '\x7F':  // Backspace (\b) or Delete (DEL)            {                if( myTextEntry.length() > 0 )                {                    // xxx this is lame                    cout << "\b \b\b \b\b \b";                    cout.flush();                    myTextEntry.setchar(myTextEntry.length() - 1, ' ');                    myTextEntry.removeSpaces();                }                else                {                    cout << "\b \b\b \b";                    cout.flush();                }                break;            }            case '\x0A':  // Line Feed (\n) -> done            {                cpLog( LOG_DEBUG, "URL is %s", myTextEntry.logData() );                event->type = DeviceEventCallUrl;                event->text = myTextEntry;                myTextEntry = "";                myEntryState = EntryStateTelephoneUI;                break;            }            default:            {                if( keystroke >= '\x20' && keystroke <= '\x7E' )                {                    // Append a character between ' ' and '~'                    myTextEntry.setchar(myTextEntry.length(), keystroke);                }                else                {                    // Treat everything else as abort                    // e.g. '\1B':  // Esc -> abort                    myTextEntry = "";                    myEntryState = EntryStateTelephoneUI;                    cout << endl;                    cpLog( LOG_DEBUG, "Abort URL input" );                }                break;            }        }    }    if (event->type != DeviceEventUndefined)    {        assert( sessionQ != 0 );        event->callId = callId;        sessionQ->add( event );    }}//***************************************************************************// QuickNetDevice::process//// description:  process any events detected on the hardware (dtmf digit//               press, onhook & offhook, etc.) and reports the events back//               to the session via the fifo queue.//***************************************************************************intQuickNetDevice::process (fd_set* fd){    if( FD_ISSET( stdinFD, fd ) )    {        processUrlInput();        FD_CLR( stdinFD, fd );    }    vusleep(0);  // needed to stabilize hookstate readings    deviceMutex.lock();    if( ioctl(myFD, PHONE_HOOKSTATE) )    {        // user is offhook        if( hookStateOffhook == false )        {            // report change from onhook to offhook            hookStateOffhook = true;            reportEvent(sessionQ, DeviceEventHookUp);        }        // check for DTMF digit from hardware        if (ioctl(myFD, PHONE_DTMF_READY))        {            // new digit            switch (ioctl(myFD, PHONE_GET_DTMF))            {            case 0x01:                reportEvent(sessionQ, DeviceEventDtmf1);                break;            case 0x02:                reportEvent(sessionQ, DeviceEventDtmf2);                break;            case 0x03:                reportEvent(sessionQ, DeviceEventDtmf3);                break;            case 0x04:                reportEvent(sessionQ, DeviceEventDtmf4);                break;            case 0x05:                reportEvent(sessionQ, DeviceEventDtmf5);                break;            case 0x06:                reportEvent(sessionQ, DeviceEventDtmf6);                break;            case 0x07:                reportEvent(sessionQ, DeviceEventDtmf7);                break;            case 0x08:                reportEvent(sessionQ, DeviceEventDtmf8);                break;            case 0x09:                reportEvent(sessionQ, DeviceEventDtmf9);                break;            case 0x0A:                reportEvent(sessionQ, DeviceEventDtmfStar);                break;            case 0x0B:                reportEvent(sessionQ, DeviceEventDtmf0);                break;            case 0x0C:                reportEvent(sessionQ, DeviceEventDtmfHash);                break;            default:                cpLog(LOG_ERR, "Unrecognized DTMF digit from hardware");                break;            }        }    }    else    {        if( hookStateOffhook == true )        {            vusleep(20000);  // needed to stabilize hookstate readings            // read the hookstate again to make sure an onhook has been generated            if( !ioctl(myFD, PHONE_HOOKSTATE) )            {                deviceMutex.unlock();                onhookOrFlash();                deviceMutex.lock();            }        }    }    deviceMutex.unlock();    return 0;} // end QuickNetDevice::process()//***************************************************************************// QuickNetDevice::processRTP// description:  main processing loop for RTP//***************************************************************************voidQuickNetDevice::processRTP (){    deviceMutex.lock();    if (audioStack == 0)    {        vusleep(10000);        deviceMutex.unlock();        return ;    }    RtpSessionState sessionState = audioStack->getSessionState();    //only process receive if receive is enabled    if ( sessionState == rtp_session_recvonly ||            sessionState == rtp_session_sendrecv )    {        inRtpPkt = audioStack->receive ();        if (inRtpPkt)        {            if (inRtpPkt->getPayloadUsage() != RESID_RTP_RATE)                cpLog(LOG_DEBUG, "RtpStack API size doesn't match RESID_RTP_RATE");            char *vBuf;            if ( cwBeepOn )            {                vBuf = getCwBeep();                if ( vBuf == 0 )                    vBuf = inRtpPkt->getPayloadLoc();            }            else            {                vBuf = inRtpPkt->getPayloadLoc();            }            write (myFD, vBuf, RESID_RTP_RATE);            // need to delete since RTP stack doesn't do it any more            delete inRtpPkt; inRtpPkt = NULL;        }    }    if ( sessionState == rtp_session_sendonly ||            sessionState == rtp_session_sendrecv )    {	// cc = number of samples        int cc;		if ( sendRingback )	{	    cc = getRingbackTone( outBufferPkt, RESID_RTP_RATE);	}	else	{	    cc = read(myFD, outBufferPkt, RESID_RTP_RATE);	}		if (audioStack)        {            audioStack->transmitRaw (outBufferPkt, cc);        }    }    if (audioStack &&            sessionState != rtp_session_inactive &&            sessionState != rtp_session_undefined )    {        audioStack->processRTCP();    }    deviceMutex.unlock();}intQuickNetDevice::addToFdSet (fd_set* fd){    if ( ( audioActive || audioHalfActive ) && audioStack )

⌨️ 快捷键说明

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