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(); }
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 ); } }
/** * 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; }
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(); } }
/** * 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; }
// // 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; } } }
// // 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(); }
// 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; }
// 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; }
// 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; }