bool CCallsignList::LoadFromFile(const char *filename) { bool ok = false; char sz[256]; // and load std::ifstream file (filename); if ( file.is_open() ) { Lock(); // empty list clear(); // fill with file content while ( file.getline(sz, sizeof(sz)).good() ) { // remove leading & trailing spaces char *szt = TrimWhiteSpaces(sz); // and load if not comment if ( (::strlen(szt) > 0) && (szt[0] != '#') ) { push_back(CCallsignListItem(CCallsign(szt), CIp(), NULL)); } } // close file file.close(); // keep file path m_Filename = filename; // update time GetLastModTime(&m_LastModTime); // and done Unlock(); ok = true; std::cout << "Gatekeeper loaded " << size() << " lines from " << filename << std::endl; } else { std::cout << "Gatekeeper cannot find " << filename << std::endl; } return ok; }
bool CDplusProtocol::OnDvHeaderPacketIn(CDvHeaderPacket *Header, const CIp &Ip) { bool newstream = false; // find the stream CPacketStream *stream = GetStream(Header->GetStreamId()); if ( stream == NULL ) { // no stream open yet, open a new one CCallsign via(Header->GetRpt1Callsign()); // first, check module is valid if ( g_Reflector.IsValidModule(Header->GetRpt1Module()) ) { // find this client CClient *client = g_Reflector.GetClients()->FindClient(Ip, PROTOCOL_DPLUS); if ( client != NULL ) { // now we know if it's a dextra dongle or a genuine dplus node if ( Header->GetRpt2Callsign().HasSameCallsignWithWildcard(CCallsign("XRF*")) ) { client->SetDextraDongle(); } // now we know its module, let's update it if ( !client->HasModule() ) { client->SetModule(Header->GetRpt1Module()); } // get client callsign via = client->GetCallsign(); // and try to open the stream if ( (stream = g_Reflector.OpenStream(Header, client)) != NULL ) { // keep the handle m_Streams.push_back(stream); newstream = true; } } // release g_Reflector.ReleaseClients(); // update last heard g_Reflector.GetUsers()->Hearing(Header->GetMyCallsign(), via, Header->GetRpt2Callsign()); g_Reflector.ReleaseUsers(); } else { std::cout << "DPlus node " << via << " link attempt on non-existing module" << std::endl; } } else { // stream already open // skip packet, but tickle the stream stream->Tickle(); // and delete packet delete Header; } // done return newstream; }
void CDeviceTcpSbs1::slotProcessData() { // NOTE: SBS-1 protocol: http://www.homepages.mcb.net/bones/SBS/Article/Barebones42_Socket_Data.htm // NOTE: as per QT documentation: "[...] within a slot connected to the readyRead() signal, readyRead() will not be reemitted" static const QRegExp __qRegExpYMD( "^(197\\d|19[89]\\d|[2-9]\\d\\d\\d)/(0?[1-9]|1[12])/(0?[1-9]|[12]\\d|3[01])$" ); static const QRegExp __qRegExpHMS( "^(0?\\d|1\\d|2[0-3]):(0?\\d|[1-5]\\d):(0?\\d|[1-5]\\d(\\.\\d+)?)$" ); //qDebug( "DEBUG[%s]: Begin", Q_FUNC_INFO ); QMutex* __pqMutexDataChange = QVCTRuntime::useMutexDataChange(); __pqMutexDataChange->lock(); do // data-processing loop { // Check data availability if( !pqTcpSocket->canReadLine() ) break; //qDebug( "DEBUG[%s]: SBS-1 data are waiting to be read", Q_FUNC_INFO ); // Retrieve data QString __qsDataLine = QString::fromAscii( pqTcpSocket->readLine().trimmed() ); //qDebug( "DEBUG[%s]: SBS-1 data successfully read; data=%s", Q_FUNC_INFO, qPrintable( __qsDataLine ) ); // Do not process data if paused if( bPaused ) continue; // Check data status if( __qsDataLine.isEmpty() ) continue; // We need a non-empty string emit signalActivity(); // Check SBS-1 data status int __iMSG; QStringList __qDataFields = __qsDataLine.split( "," ); if( __qDataFields.at( 0 ) != "MSG" ) continue; // We process only SBS-1's "MSG" message type if( __qDataFields.size() != 22 ) continue; // "MSG" message type ought to be 22-fields long if( ( __iMSG = __qDataFields.at( 1 ).toInt() ) > 4 ) continue; // Transmission types greater than "4" are useless to us if( __qDataFields.at( 21 ).toInt() < 0 && !bGroundTraffic ) continue; // Ignore ground traffic if( __qDataFields.at( 4 ).isEmpty() ) continue; // We need a valid "HexIdent" QString __qsSource = __qDataFields.at( 4 ); //qDebug( "DEBUG[%s]: SBS-1 data are available from source %s", Q_FUNC_INFO, qPrintable( __qsSource ) ); // Callsign lookup if( bCallsignLookup ) { QString __qsCallsign; double __fdTimestamp = microtime(); // Dictionary cleanup (every 300 seconds) if( __fdTimestamp - fdCallsignCleanupTimestamp > (double)300.0 ) { fdCallsignCleanupTimestamp = __fdTimestamp; QList<QString> __qListSource = qHashCallsign.keys(); for( QList<QString>::const_iterator __iqsSource = __qListSource.begin(); __iqsSource != __qListSource.end(); ++__iqsSource ) // Cleanup stale entries (older than 900 seconds) if( __fdTimestamp - qHashCallsign[ *__iqsSource ].fdTimestamp > (double)900.0 ) qHashCallsign.remove( *__iqsSource ); } // Actual lookup if( !__qDataFields.at( 10 ).isEmpty() ) { __qsCallsign = __qDataFields.at( 10 ).trimmed(); if( qHashCallsign.contains( __qsSource ) ) qHashCallsign[ __qsSource ].update( __qsCallsign, __fdTimestamp ); else qHashCallsign.insert( __qsSource, CCallsign( __qsCallsign, __fdTimestamp ) ); } else { if( !qHashCallsign.contains( __qsSource ) ) continue; __qsCallsign = qHashCallsign[ __qsSource ].get( __fdTimestamp ); } // Use looked-up callsign __qsSource = __qsCallsign; } if( __iMSG == 1 ) continue; // Parse SBS-1 data CDeviceDataFix __oDeviceDataFix( __qsSource ); __oDeviceDataFix.setSourceType( CDeviceDataSource::SBS ); __oDeviceDataFix.setCourseFromPosition( false ); bool __bDataAvailable = false; // ... time if( !__qDataFields.at( 6 ).isEmpty() && !__qDataFields.at( 7 ).isEmpty() && __qRegExpYMD.exactMatch( __qDataFields.at( 6 ) ) && __qRegExpHMS.exactMatch( __qDataFields.at( 7 ) ) ) { QDateTime __qDateTime; __qDateTime.setTimeSpec( eTimeZone == CUnitTimeZone::UTC ? Qt::UTC : Qt::LocalTime ); __qDateTime.setDate( QDate( __qRegExpYMD.cap(1).toInt(), __qRegExpYMD.cap(2).toInt(), __qRegExpYMD.cap(3).toInt() ) ); __qDateTime.setTime( QTime( __qRegExpHMS.cap(1).toInt(), __qRegExpHMS.cap(2).toInt(), __qRegExpHMS.cap(3).toInt(), !__qRegExpHMS.cap(4).isEmpty() ? 1000*__qRegExpHMS.cap(4).toDouble() : 0 ) ); __oDeviceDataFix.setTime( (double)__qDateTime.toTime_t() ); } else { // Let's default to use current system time (some SBS-1 devices do not set the date/time fields) __oDeviceDataFix.setTime( (double)QDateTime::currentDateTime().toTime_t() ); } // ... position / elevation // SBS-1 elevation: feet if( !__qDataFields.at( 14 ).isEmpty() && !__qDataFields.at( 15 ).isEmpty() ) { if( !__qDataFields.at( 11 ).isEmpty() ) { __oDeviceDataFix.setPosition( __qDataFields.at( 15 ).toDouble(), __qDataFields.at( 14 ).toDouble(), __qDataFields.at( 11 ).toDouble() * 0.3048 ); __oDeviceDataFix.setType( CDeviceDataFix::FIX_3D ); } else { __oDeviceDataFix.setPosition( __qDataFields.at( 15 ).toDouble(), __qDataFields.at( 14 ).toDouble() ); __oDeviceDataFix.setType( CDeviceDataFix::FIX_2D ); } __bDataAvailable = true; } // ... course if( !__qDataFields.at( 13 ).isEmpty() ) { __oDeviceDataFix.setBearing( __qDataFields.at( 13 ).toDouble() ); __bDataAvailable = true; } // ... speed // SBS-1 (horizontal) speed: knots // SBS-1 vertical speed: feet/minute if( !__qDataFields.at( 12 ).isEmpty() ) { if( !__qDataFields.at( 16 ).isEmpty() ) { __oDeviceDataFix.setSpeed( __qDataFields.at( 12 ).toDouble() / 1.94384449244, __qDataFields.at( 16 ).toDouble() / 196.8503937 ); } else { __oDeviceDataFix.setSpeed( __qDataFields.at( 12 ).toDouble() / 1.94384449244 ); } __bDataAvailable = true; } // ... hexident/callsign if( bCallsignLookup || !__qDataFields.at( 10 ).isEmpty() ) { __oDeviceDataFix.setText( bCallsignLookup ? "HEX:"+__qDataFields.at( 4 ) : "C/S:"+__qDataFields.at( 10 ) ); __bDataAvailable = true; } // [end] if( __bDataAvailable ) { emit signalDataFix( __oDeviceDataFix ); } } while( true ); // data-processing loop __pqMutexDataChange->unlock(); //qDebug( "DEBUG[%s]: End", Q_FUNC_INFO ); }