Beispiel #1
0
void shutdownNoTerminate(const ShutdownTaskArgs& shutdownArgs) {
    decltype(shutdownTasks) localTasks;

    {
        stdx::lock_guard<stdx::mutex> lock(shutdownMutex);

        if (globalInShutdownDeprecated())
            return;

        setShutdownFlag();
        shutdownTasksInProgress = true;
        shutdownTasksThreadId = stdx::this_thread::get_id();

        localTasks.swap(shutdownTasks);
    }

    runTasks(std::move(localTasks), shutdownArgs);

    {
        stdx::lock_guard<stdx::mutex> lock(shutdownMutex);
        shutdownTasksInProgress = false;
        shutdownExitCode.emplace(EXIT_CLEAN);
    }

    shutdownTasksComplete.notify_all();
}
Beispiel #2
0
GpsClient::GpsClient( const ushort portIn )
{
    device           = "";
    ioSpeedTerminal  = B0;
    ioSpeedDevice    = 0;
    ipcPort          = portIn;
    fd               = -1;
    forwardGpsData   = true;
    connectionLost   = true;
    shutdown         = false;
    datapointer      = databuffer;
    dbsize           = 0;
    badSentences     = 0;
    activateTimeout  = false;

    // establish a connection to the server
    if( ipcPort )
    {
        if( clientData.connect2Server( IPC_IP, ipcPort ) == -1 )
        {
            qCritical() << "Command channel Connection to Cumulus Server failed!"
                        << "Fatal error, terminate process!" << endl;

            setShutdownFlag(true);
            return;
        }

        if( clientForward.connect2Server( IPC_IP, ipcPort ) == -1 )
        {
            qCritical() << "Forward channel Connection to Cumulus Server failed!"
                        << "Fatal error, terminate process!";

            setShutdownFlag(true);
            return;
        }

        // Set forward channel to non blocking IO
        int fc = clientForward.getSock();
        fcntl( fc, F_SETFL, O_NONBLOCK );
    }
}
Beispiel #3
0
/**
 * Send a message via data socket to the server. The protocol consists of two
 * parts. First the message length is transmitted as unsigned integer, after
 * that the actual message as 8 bit character string.
 */
void GpsClient::writeServerMsg( const char *msg )
{
    uint msgLen = strlen( msg );

    int done = clientData.writeMsg( (char *) &msgLen, sizeof(msgLen) );

    done = clientData.writeMsg( (char *) msg, msgLen );

    if( done < 0 )
    {
        // Error occurred, make shutdown of process
        setShutdownFlag(true);
    }

    return;
}
Beispiel #4
0
void shutdown(ExitCode code, const ShutdownTaskArgs& shutdownArgs) {
    decltype(shutdownTasks) localTasks;

    {
        stdx::unique_lock<stdx::mutex> lock(shutdownMutex);

        if (shutdownTasksInProgress) {
            // Someone better have called shutdown in some form already.
            invariant(globalInShutdownDeprecated());

            // Re-entrant calls to shutdown are not allowed.
            invariant(shutdownTasksThreadId != stdx::this_thread::get_id());

            ExitCode originallyRequestedCode = shutdownExitCode.get();
            if (code != originallyRequestedCode) {
                log() << "While running shutdown tasks with the intent to exit with code "
                      << originallyRequestedCode << ", an additional shutdown request arrived with "
                                                    "the intent to exit with a different exit code "
                      << code << "; ignoring the conflicting exit code";
            }

            // Wait for the shutdown tasks to complete
            while (shutdownTasksInProgress)
                shutdownTasksComplete.wait(lock);

            logAndQuickExit_inlock();
        }

        setShutdownFlag();
        shutdownExitCode.emplace(code);
        shutdownTasksInProgress = true;
        shutdownTasksThreadId = stdx::this_thread::get_id();

        localTasks.swap(shutdownTasks);
    }

    runTasks(std::move(localTasks), shutdownArgs);

    {
        stdx::lock_guard<stdx::mutex> lock(shutdownMutex);
        shutdownTasksInProgress = false;

        shutdownTasksComplete.notify_all();

        logAndQuickExit_inlock();
    }
}
Beispiel #5
0
/**
 * Sends a data message via the forward channel to the server. The protocol consists
 * of two parts. First the message length is transmitted as unsigned integer,
 * after that the actual message as 8 bit character string.
 */
void GpsClient::writeForwardMsg( const char *msg )
{
    static QString method = "GpsClient::writeForwardMsg():";

    // The message to be transfered starts with the message length.
    uint msgLen = strlen( msg );

    QByteArray ba = QByteArray::fromRawData( (const char *) &msgLen, sizeof(msgLen) );
    ba.append( msg );

    // We use non blocking IO for the transfer. Therefore we have to consider some
    // special return codes.
    int done = clientForward.writeMsg( (char *) ba.data(), ba.size() );

    if( done < 0 )
    {
        if( errno == EWOULDBLOCK )
        {
            // The write call would block because the transfer queue is full.
            // In this case we discard the message.
            qWarning() << method
                       << "Write would block, drop Message!";
        }
        else
        {
            // Fatal error occurred, make shutdown of process.
            setShutdownFlag(true);
        }
    }

#ifdef DEBUG
    qDebug() << method << msg;
#endif

    return;
}
Beispiel #6
0
//
// Create the real Server, passing in the configured parameters
//
void ParkService::run()
{
    int UdpPort;
    int TcpPort;
    int RtpBase;
    UtlString bindIp;
    int MaxSessions;
    UtlBoolean OneButtonBLF;
    UtlString   domain;
    UtlString   realm;
    UtlString   user;
    SipLineMgr* lineMgr = NULL;
    int Lifetime;
    int BlindXferWait;
    int KeepAliveTime;

   loadConfig(
       UdpPort,
       TcpPort,
       RtpBase,
       bindIp,
       MaxSessions,
       OneButtonBLF,
       domain,
       realm,
       user,
       lineMgr,
       Lifetime,
       BlindXferWait,
       KeepAliveTime
       );

   // initialize other pieces

    // This is not configurable, as consultative transfers should
    // succeed or fail immediately.
    int ConsXferWait;
    ConsXferWait = CONS_XFER_WAIT;

    // Bind the SIP user agent to a port and start it up
    SipUserAgent* userAgent = new SipUserAgent(TcpPort,
                                               UdpPort,
                                               TcpPort+1,
                                               NULL, // publicAddress
                                               user.isNull() ? NULL : user.data(), // default user
                                               bindIp,
                                               domain.isNull() ? NULL : domain.data(), // outbound proxy
                                               NULL, // sipDirectoryServers (deprecated)
                                               NULL, // sipRegistryServers (deprecated)
                                               NULL, // authenicateRealm
                                               NULL, // authenticateDb
                                               NULL, // authorizeUserIds (deprecated)
                                               NULL, // authorizePasswords (deprecated)
                                               lineMgr
                                               );
    userAgent->setUserAgentHeaderProperty("sipXecs/park");
    userAgent->start();

    if (!userAgent->isOk())
    {
       OsSysLog::add(LOG_FACILITY, PRI_EMERG, "SipUserAgent failed to initialize, requesting shutdown");
       setShutdownFlag(true);
    }

    // Read the list of codecs from the configuration file.
    SdpCodecFactory codecFactory;
    initCodecs(&codecFactory, &getConfigDb());

    // Initialize and start up the media subsystem
    mpStartUp(MP_SAMPLE_RATE, MP_SAMPLES_PER_FRAME, 6 * MaxSessions, &getConfigDb());
    MpMediaTask::getMediaTask(MaxSessions);

#ifdef INCLUDE_RTCP
    CRTCManager::getRTCPControl();
#endif //INCLUDE_RTCP

    mpStartTasks();

    // Instantiate the call processing subsystem
    UtlString localAddress;
    int localPort ;
    userAgent->getLocalAddress(&localAddress, &localPort) ;
    if (localAddress.isNull())
        OsSocket::getHostIp(&localAddress);

    // Construct an address to be used in outgoing requests (primarily
    // INVITEs stimulated by REFERs).
    UtlString outgoingAddress;
    {
       char buffer[100];
       sprintf(buffer, "sip:sipXpark@%s:%d", localAddress.data(),
               portIsValid(UdpPort) ? UdpPort : TcpPort);
       outgoingAddress = buffer;
    }
    CallManager callManager(FALSE,
                           NULL,
                           TRUE,                              // early media in 180 ringing
                           &codecFactory,
                           RtpBase,                           // rtp start
                           RtpBase + (2 * MaxSessions),       // rtp end
                           localAddress,
                           localAddress,
                           userAgent,
                           0,                                 // sipSessionReinviteTimer
                           NULL,                              // mgcpStackTask
                           outgoingAddress,                   // defaultCallExtension
                           Connection::RING,                  // availableBehavior
                           NULL,                              // unconditionalForwardUrl
                           -1,                                // forwardOnNoAnswerSeconds
                           NULL,                              // forwardOnNoAnswerUrl
                           Connection::BUSY,                  // busyBehavior
                           NULL,                              // sipForwardOnBusyUrl
                           NULL,                              // speedNums
                           CallManager::SIP_CALL,             // phonesetOutgoingCallProtocol
                           4,                                 // numDialPlanDigits
                           CallManager::NEAR_END_HOLD,        // holdType
                           5000,                              // offeringDelay
                           "",                                // pLocal
                           CP_MAXIMUM_RINGING_EXPIRE_SECONDS, // inviteExpiresSeconds
                           QOS_LAYER3_LOW_DELAY_IP_TOS,       // expeditedIpTos
                           MaxSessions,                       // maxCalls
                           sipXmediaFactoryFactory(NULL));    // CpMediaInterfaceFactory



    // Create a listener (application) to deal with call
    // processing events (e.g. incoming call and hang ups)
    OrbitListener listener(&callManager, Lifetime, BlindXferWait, KeepAliveTime, ConsXferWait);

    callManager.addTaoListener(&listener);
    listener.start();

    // Create the SIP Subscribe Server
    SipPersistentSubscriptionMgr
       subscriptionMgr(SUBSCRIPTION_COMPONENT_PARK,
                       domain,
                       "subscription"); // Component for holding the subscription data
    SipSubscribeServerEventHandler policyHolder; // Component for granting the subscription rights
    SipPublishContentMgr publisher; // Component for publishing the event contents

    SipSubscribeServer subscribeServer(SipSubscribeServer::terminationReasonSilent,
                                       *userAgent, publisher,
                                       subscriptionMgr, policyHolder);
    subscribeServer.enableEventType(DIALOG_EVENT_TYPE, NULL, NULL, NULL,
                                    SipSubscribeServer::standardVersionCallback,
                                    TRUE // dialogEvents only produces full content.
       );
    subscribeServer.start();

    // Create the DialogEventPublisher.
    // Use the sipX domain as the hostport of resource-IDs of the
    // published events, as that will be the request-URIs of SUBSCRIBEs.
    DialogEventPublisher dialogEvents(&callManager, &publisher, domain, PORT_NONE, OneButtonBLF);
    callManager.addTaoListener(&dialogEvents);
    dialogEvents.start();

    // Start up the call processing system
    callManager.start();

    // Loop forever until signaled to shut down

    int numTwoSecIntervals = 0;
    int CleanLoopWaitTimeSecs = 10;

    while (!getShutdownFlag())
    {
       OsTask::delay(2000);

       if (2*numTwoSecIntervals >= CleanLoopWaitTimeSecs)
       {
           numTwoSecIntervals = 0;
           if (OsSysLog::willLog(FAC_PARK, PRI_DEBUG))
           {
               OsSysLog::add(LOG_FACILITY, PRI_DEBUG,
                             "park main "
                             "logging call status"
                             );
               callManager.printCalls(0) ;
               listener.dumpCallsAndTransfers();
           }
       }
       else
       {
           numTwoSecIntervals += 1;
       }

    }

}
Beispiel #7
0
//
// Create the real Server, passing in the configured parameters
//
void ProxyService::run()
{
    int proxyTcpPort;
    int proxyUdpPort;
    int proxyTlsPort;
    UtlString bindIp;
    int maxForwards;
    UtlString domainName;
    UtlString proxyRecordRoute;
    UtlString routeName;
    UtlString authScheme;
    UtlString ipAddress;
    bool enableCallStateLogObserver;
    bool enableCallStateDbObserver;
    int dnsSrvTimeout = -1; //seconds
    int maxNumSrvRecords = -1;
    UtlString callStateLogFileName;
    UtlBoolean recurseOnlyOne300 = FALSE;
    UtlString hostAliases;
    int      staleTcpTimeout = 3600;
    UtlString callStateDbHostName;
    UtlString callStateDbName;
    UtlString callStateDbUserName;
    UtlString callStateDbDriver;
    ForwardRules forwardingRules;

    loadInitialConfig(
          proxyTcpPort,
          proxyUdpPort,
          proxyTlsPort,
          bindIp,
          maxForwards,
          domainName,
          proxyRecordRoute,
          routeName,
          authScheme,
          ipAddress,
          enableCallStateLogObserver,
          enableCallStateDbObserver,
          dnsSrvTimeout,
          maxNumSrvRecords,
          callStateLogFileName,
          recurseOnlyOne300,
          hostAliases,
          staleTcpTimeout,
          callStateDbHostName,
          callStateDbName,
          callStateDbUserName,
          callStateDbDriver,
          forwardingRules
          );

   // initialize other pieces
#ifdef TEST_PRINT
    { // scope the test stuff
        SipMessage foo;
        const char* uri = "sip:10.1.20.3:5100";
        const char* method = SIP_ACK_METHOD;
        const char* eventType = SIP_EVENT_CONFIG;
        foo.setRequestData(method,
                           uri, //uri,
                           "sip:[email protected]", // fromField,
                           "\"lajdflsdk ff\"<sip:[email protected]>", // toField,
                           "lkadsj902387", // callId,
                           123, // CSeq,
                           "sip:10.1.1.123");// contactUrl

        // Set the event type
        foo.setHeaderValue(SIP_EVENT_FIELD,
                            eventType, // event type
                            0);

        Url msgUrl(uri);
        UtlString routeTo;
        UtlString routeType;
        bool authRequired;
        OsStatus routeStatus = forwardingRules.getRoute(msgUrl,
                                                        foo,
                                                        routeTo,
                                                        routeType,
                                                        authRequired);

        Url msgRouteToUri(routeTo);
        osPrintf("Message:\n\tmethod: %s\n\turi: %s\n\tevent: %s\nRouted:\n\tstring: %s\n\turi: %s\n\ttype: %s\n",
            method, uri, eventType, routeTo.data(), msgRouteToUri.toString().data(), routeType.data());
        if(routeStatus != OS_SUCCESS)
            osPrintf("forwardingRules.getRoute returned: %d\n",
                    routeStatus);
    }
#endif // TEST_PRINT

    // Start the sip stack
    mpSipUserAgent = new SipUserAgent(
        proxyTcpPort,
        proxyUdpPort,
        proxyTlsPort,
        NULL, // public IP address (not used in proxy)
        NULL, // default user (not used in proxy)
        bindIp,
        NULL, // outbound proxy
        NULL, // directory server
        NULL, // registry server
        NULL, // auth realm
        NULL, // auth DB
        NULL, // auth user IDs
        NULL, // auth passwords
        NULL, // line mgr
        SIP_DEFAULT_RTT, // first resend timeout
        FALSE, // default to proxy transaction
        SIPUA_DEFAULT_SERVER_UDP_BUFFER_SIZE, // socket layer read buffer size
        SIPUA_DEFAULT_SERVER_OSMSG_QUEUE_SIZE, // OsServerTask message queue size
        FALSE, // Use Next Available Port
        TRUE,  // Perform message checks
        TRUE,  // Use symmetric signaling
        SipUserAgent::HANDLE_OPTIONS_AUTOMATICALLY);


    if (!mpSipUserAgent->isOk())
    {
        OsSysLog::add(FAC_SIP, PRI_EMERG, "SipUserAgent reported a problem, setting shutdown flag...");
        setShutdownFlag(true);
    }
    mpSipUserAgent->setDnsSrvTimeout(dnsSrvTimeout);
    mpSipUserAgent->setMaxSrvRecords(maxNumSrvRecords);
    mpSipUserAgent->setUserAgentHeaderProperty("sipXecs/sipXproxy");
    mpSipUserAgent->setMaxForwards(maxForwards);
    mpSipUserAgent->setMaxTcpSocketIdleTime(staleTcpTimeout);
    mpSipUserAgent->setHostAliases(hostAliases);
    mpSipUserAgent->setRecurseOnlyOne300Contact(recurseOnlyOne300);
    // load and set configurable parameters
    loadConfig();

    // Do not start the SipUserAgent until its message listeners are
    // set up by the creation of the SipRouter below.

    UtlString buffer;

    // Create the CSE observer, either writing to file or database
    SipXProxyCseObserver* cseObserver = NULL;
    CallStateEventWriter* pEventWriter = NULL;
    if (enableCallStateLogObserver)
    {
       // Set up the call state event log file
       pEventWriter = new CallStateEventWriter_XML(callStateLogFileName.data());
    }
    else if (enableCallStateDbObserver)
    {
       pEventWriter = new CallStateEventWriter_DB(callStateDbName.data(),
                                                  callStateDbHostName.data(),
                                                  callStateDbUserName,
                                                  callStateDbDriver);
    }

    if (pEventWriter)
    {
       // get the identifier for this observer
       int protocol = OsSocket::UDP;
       UtlString domainName;
       int port;
       mpSipUserAgent->getViaInfo(protocol, domainName, port);

       char portString[12];
       sprintf(portString,":%d", port);
       domainName.append(portString);

       // and start the observer
       cseObserver = new SipXProxyCseObserver(*mpSipUserAgent, domainName, pEventWriter);
       cseObserver->start();
    }
    else
    {
      // Only log error if any event logging was enabled
      if (enableCallStateLogObserver || enableCallStateDbObserver)
      {
         OsSysLog::add(FAC_SIP, PRI_ERR,
                       "SipAuthProxyMain:: EventWriter could not be allocated"
                       );
         enableCallStateLogObserver = false;
         enableCallStateDbObserver = false;
      }
    }

    // Create a router to route stuff either
    // to a local server or on out to the real world
    SipRouter* pRouter = new SipRouter(*mpSipUserAgent,
                                       forwardingRules,
                                       getConfigDb());

    // Start the router running
    pRouter->start();

    // Do not exit, let the proxy do its stuff
    while( !getShutdownFlag() )
    {
      OsTask::delay(2000);
    }

    // This is a server task so gracefully shutdown the
    // router task by deleting it.
    delete pRouter ;

    // Stop the SipUserAgent.
    mpSipUserAgent->shutdown();
    // And delete it, too.
    delete mpSipUserAgent ;

    // flush and close the call state event log
    if (enableCallStateLogObserver || enableCallStateDbObserver)
    {
      if (cseObserver)
      {
         delete cseObserver;
      }
      if (pEventWriter)
      {
         delete pEventWriter;
      }
    }

    // End the singleton threads.
    OsTimerTask::destroyTimerTask();
    OsStunAgentTask::releaseInstance();

   // now deregister this process's database references from the IMDB
   closeIMDBConnections();
}
Beispiel #8
0
// Reads a server message from the socket. The protocol consists of
// two parts. First the message length is read as unsigned
// integer, after that the actual message as 8 bit character string.
void GpsClient::readServerMsg()
{
    static const char* method = "GpsClient::readServerMsg():";

    uint msgLen = 0;

    uint done = clientData.readMsg( &msgLen, sizeof(msgLen) );

    if( done < sizeof(msgLen) )
    {
        qWarning() << method << "MSG length" << done << "too short";
        setShutdownFlag(true);
        return; // Error occurred
    }

    if( msgLen > 512 )
    {
        // such messages length are not defined. we will ignore that.
        qWarning() << method
                   << "message" << msgLen << "too large, ignoring it!";

        setShutdownFlag(true);
        return; // Error occurred
    }

    char *buf = new char[msgLen+1];

    memset( buf, 0, msgLen+1 );

    done = clientData.readMsg( buf, msgLen );

    if( done <= 0 )
    {
        qWarning() << method << "MSG data" << done << "too short";
        delete [] buf;
        setShutdownFlag(true);
        return; // Error occurred
    }

#ifdef DEBUG
    qDebug() << method << "Received Message:" << buf;
#endif

    // Split the received message into its two parts. Space is used as separator
    // between the command word and the optional content of the message.
    QString qbuf( buf );

    delete[] buf;
    buf = 0;

    int spaceIdx = qbuf.indexOf( QChar(' ') );

    QStringList args;

    if( spaceIdx == -1 || qbuf.size() == spaceIdx )
    {
        args.append(qbuf);
        args.append("");
    }
    else
    {
        args.append(qbuf.left(spaceIdx));
        args.append(qbuf.mid(spaceIdx+1));
    }

    // look, what the server is requesting
    if( MSG_MAGIC == args[0] )
    {
        // check protocol versions, reply with pos or neg
        if( MSG_PROTOCOL != args[1] )
        {
            qCritical() << method
                        << "Client-Server protocol mismatch!"
                        << "Client:" << MSG_PROTOCOL
                        << "Server:" << args[1];

            writeServerMsg( MSG_NEG );
            setShutdownFlag(true);
            return;
        }

        writeServerMsg( MSG_POS );
    }
    else if( MSG_OPEN == args[0] )
    {
        QStringList devArgs = args[1].split(QChar(' '));

        if( devArgs.size() == 2 )
        {
            // Initialization of GPS device is requested. The message
            // consists of two parts separated by spaces.
            // 1) device name
            // 2) io speed
            bool res = openGps( devArgs[0].toLatin1().data(), devArgs[1].toUInt() );

            if( res )
            {
                writeServerMsg( MSG_POS );
            }
            else
            {
                writeServerMsg( MSG_NEG );
            }
        }
    }
    else if( MSG_CLOSE == args[0] )
    {
        // Close GPS device is requested
        closeGps();
        writeServerMsg( MSG_POS );
    }
    else if( MSG_FGPS_ON == args[0] )
    {
        // Switches on GPS data forwarding to the server.
        forwardGpsData = true;
        writeServerMsg( MSG_POS );
    }
    else if( MSG_FGPS_OFF == args[0] )
    {
        // Switches off GPS data forwarding to the server.
        forwardGpsData = false;
        writeServerMsg( MSG_POS );
    }
    else if( MSG_SM == args[0] && args.count() == 2 )
    {
        // Sent message to the GPS device
        int res = writeGpsData( args[1].toLatin1().data() );

        if( res == -1 )
        {
            writeServerMsg( MSG_NEG );
        }
        else
        {
            writeServerMsg( MSG_POS );
        }
    }
    else if( MSG_GPS_KEYS == args[0] && args.count() == 2 )
    {
        // Well known GPS message keys are received.
        QStringList keys = args[1].split( ",", QString::SkipEmptyParts );

        // Clear old content.
        gpsMessageFilter.clear();

        for( int i = 0; i < keys.size(); i++ )
        {
            gpsMessageFilter.insert( keys.at(i) );
        }

        // qDebug() << "GPS-Keys:" << gpsMessageFilter;
        writeServerMsg( MSG_POS );
    }
    else if( MSG_SHD == args[0] )
    {
        // Shutdown is requested by the server. This message will not be
        // acknowledged!
        setShutdownFlag(true);
    }

#ifdef FLARM

    else if( MSG_FLARM_FLIGHT_LIST_REQ == args[0] )
    {
        // Flarm flight list is requested
        writeServerMsg( MSG_POS );
        getFlarmFlightList();
    }
    else if( MSG_FLARM_FLIGHT_DOWNLOAD == args[0] && args.count() == 2 )
    {
        // Flarm flight download is requested
        writeServerMsg( MSG_POS );
        getFlarmIgcFiles(args[1]);
    }
    else if( MSG_FLARM_RESET == args[0] )
    {
        // Flarm reset is requested
        writeServerMsg( MSG_POS );
        flarmReset();
    }

#endif

    else
    {
        qWarning() << method << "Unknown message received:" << qbuf;
        writeServerMsg( MSG_NEG );
    }

    return;
}
Beispiel #9
0
// Opens the connection to the GPS. All old messages in the queue are removed.
bool GpsClient::openGps( const char *deviceIn, const uint ioSpeedIn )
{
    // qDebug() << "GpsClient::openGps:" << deviceIn << "," << ioSpeedIn;

    device          = deviceIn;
    ioSpeedDevice   = ioSpeedIn;
    ioSpeedTerminal = getBaudrate(ioSpeedIn);
    badSentences    = 0;
    unknownsReported.clear();

    if( deviceIn == (const char *) 0 || strlen(deviceIn) == 0 )
    {
        // no valid device has been passed
        return false;
    }

    // reset buffer pointer
    datapointer = databuffer;
    dbsize      = 0;
    memset( databuffer, 0, sizeof(databuffer) );

    if( fd != -1 )
    {
        // closes an existing connection before opening a new one
        closeGps();
        sleep(2);
    }

#ifdef BLUEZ

    // Define a reg. expression for a Bluetooth address like "XX:XX:XX:XX:XX:XX"
    QRegExp regExp("([0-9A-Fa-f]{2,2}:){5,5}[0-9A-Fa-f]{2,2}");

    if( QString(deviceIn).contains(QRegExp( regExp )) )
    {
        fd = socket( AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM );

        // NON blocking io is requested!
        fcntl( fd, F_SETFL, O_NONBLOCK );

        struct sockaddr_rc addr;

        memset( &addr, 0, sizeof (addr) );

        addr.rc_family = AF_BLUETOOTH;

        // 1 is the default channel for a connection to the BT daemon
        addr.rc_channel = (uint8_t) 1;
        str2ba( deviceIn, &addr.rc_bdaddr );

        if( connect( fd, (struct sockaddr *) &addr, sizeof (addr)) == -1 &&
                errno != EINPROGRESS )
        {
            qCritical() << "GpsClient::openGps(): BT connect error"
                        << errno << "," << strerror(errno);

            close( fd );
            fd = -1;

            last = QTime();
            setShutdownFlag(true);
            return false;
        }

        // Stop supervision control to give the BT daemon time for connection.
        // The first data read will activate it again.
        last = QTime();
        return true;
    }

#endif

    // create a fifo for the nmea simulator, if device starts not with /dev/
    if( strncmp( "/dev/", deviceIn, strlen("/dev/") ) != 0 )
    {
        int ret = mkfifo( device.data(), S_IRUSR | S_IWUSR );

        if( ret && errno != EEXIST )
        {
            perror("mkfifo");
        }
    }

    fd = open( device.data(), O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK );

    if( fd == -1 )
    {
        perror( "Open GPS device:" );

        // Could not open the serial device.
#ifdef ERROR_LOG
        qWarning() << "openGps: Unable to open GPS device"
                   << device << "at transfer rate"
                   << ioSpeedIn;
#endif

        last.start(); // store time point for restart control
        return false;
    }

    if( ! isatty(fd) )
    {
        // Fifo needs no serial initialization.
        // Write a notice for the user about that fact
        if( device.startsWith("/dev/") )
        {
            qDebug() << "GpsClient::openGps: Device '"
                     << deviceIn
                     << "' is not a TTY!";
        }
    }
    else
    {
        tcgetattr(fd, &oldtio); // get current options from port

        // copy current values into new structure for changes
        memcpy( &newtio, &oldtio, sizeof(newtio) );

        // http://www.mkssoftware.com/docs/man5/struct_termios.5.asp
        //
        // Prepare serial port settings for raw mode. That is important
        // otherwise Flarm binary communication do not work!
        //
        // - no canonical input (no line oriented input)
        // - 8 data bits
        // - no parity
        // - no interpretation of special characters
        // - no hardware control

        // Port control modes
        // CS8    8 bits per byte
        // CLOCAL Ignore modem status lines
        // CREAD  Enable receiver
        newtio.c_cflag = CS8 | CLOCAL | CREAD;

        // Port input modes
        // raw input without any special handling
        newtio.c_iflag = 0;

        // Port output modes
        // raw output without any special handling
        newtio.c_oflag = 0;

        // Port local modes
        // raw input/output without any special handling
        newtio.c_lflag = 0;

        // The values of the MIN and TIME members of the c_cc array of the termios
        // structure are used to determine how to process the bytes received.
        //
        // MIN represents the minimum number of bytes that should be received when
        // the read() function returns successfully.
        //
        // TIME is a timer of 0.1 second granularity (or as close to that value as
        // can be accommodated) that is used to time out bursty and short-term data
        // transmissions.
        newtio.c_cc[VMIN]  = 1;
        newtio.c_cc[VTIME] = 0;

        // AP: Note, the setting of the speed must be done at last
        // because the manipulation of the c_iflag and c_oflag can
        // destroy the already assigned values! Needed me several hours
        // to find out that. Setting the baud rate under c_cflag seems
        // also to work.
        cfsetispeed( &newtio, ioSpeedTerminal ); // set baud rate for input
        cfsetospeed( &newtio, ioSpeedTerminal ); // set baud rate for output

        tcflush(fd, TCIOFLUSH);
        tcsetattr(fd, TCSANOW, &newtio);

        fcntl(fd, F_SETFL, FNDELAY); // NON blocking io is requested
    }

    last.start(); // store time point for supervision control
    return true;
}
Beispiel #10
0
// Processes incoming read events. They can come from the server or
// from the GPS device.
void GpsClient::processEvent( fd_set *fdMask )
{
    if( ipcPort )
    {
        int sfd = clientData.getSock();

        if( sfd != -1 && FD_ISSET( sfd, fdMask ) )
        {
            int loops = 0;

            // Try to process several messages from the client in order. That
            // is more effective as to wait for a new select call.
            while( loops++ < 32 )
            {
                readServerMsg();

                if( shutdown == true )
                {
                    break;
                }

                // Check, if more bytes are available in the receiver buffer because we
                // use blocking IO.
                int bytes = 0;

                // Number of bytes currently in the socket receiver buffer.
                if( ioctl( sfd, FIONREAD, &bytes) == -1 )
                {
                    qWarning() << "GpsClient::processEvent():"
                               << "ioctl() returns with Errno="
                               << errno
                               << "," << strerror(errno);
                    break;
                }

                if( bytes <= 0 )
                {
                    break;
                }
            }
        }
    }

    if( fd != -1 && FD_ISSET( fd, fdMask ) )
    {
        if( readGpsData() == false )
        {
            // problem occurred, likely buffer overrun. we do restart the GPS
            // receiving.
            int error = errno; // Save errno
            closeGps();

            if( error == ECONNREFUSED )
            {
                // BT devices can reject a connection try. If we don't return here
                // we run in an endless loop.
                setShutdownFlag(true);
            }
            else
            {
                sleep(3);
                // reopen connection
                openGps( device.data(), ioSpeedDevice );
            }
        }
    }
}
//
// Create the real Appearance Agent, passing in the configured parameters
//
void AppearanceAgentService::run()
{
   int udpPort;
   int tcpPort;
   UtlString bindIp;
   UtlString appearanceGroupFile;
   UtlString domainName;
   UtlString realm;
   int refreshInterval;
   int resubscribeInterval;
   int minResubscribeInterval;
   int seizedResubscribeInterval;
   int serverMinExpiration;
   int serverDefaultExpiration;
   int serverMaxExpiration;

   loadConfig(udpPort,
         tcpPort,
         bindIp,
         appearanceGroupFile,
         domainName,
         realm,
         refreshInterval,
         resubscribeInterval,
         minResubscribeInterval,
         seizedResubscribeInterval,
         serverMinExpiration,
         serverDefaultExpiration,
         serverMaxExpiration);

   // add the ~~sipXsaa credentials so that sipXsaa can respond to challenges
   SipLineMgr* lineMgr = addCredentials(domainName, realm);
   if (NULL == lineMgr)
   {
      OsSysLog::add(FAC_SAA, PRI_CRIT, "failed to add SAA credentials - exiting");
      setShutdownFlag(true);
   }

   if (!getShutdownFlag())
   {
      // Initialize the AppearanceAgent.
      // (Use tcpPort as the TLS port, too.)
      mAppearanceAgent = new AppearanceAgent(this, domainName, realm, lineMgr,
                          tcpPort, udpPort, tcpPort, bindIp,
                          &appearanceGroupFile,
                          refreshInterval,
                          resubscribeInterval, minResubscribeInterval, seizedResubscribeInterval,
                          SAA_PUBLISH_DELAY,
                          20,
                          serverMinExpiration,
                          serverDefaultExpiration,
                          serverMaxExpiration);
      mAppearanceAgent->start();

      // Loop forever until signaled to shut down
      while (!getShutdownFlag())
      {
         OsTask::delay(2 * OsTime::MSECS_PER_SEC);
      }

      // Shut down the server.
      mAppearanceAgent->shutdown();
   }

   // Delete the LineMgr Object
   delete lineMgr;
}