| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  | #include "APRSISClient.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <cmath>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-18 17:24:07 -04:00
										 |  |  | #include "DriftingDateTime.h"
 | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  | #include "varicode.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-05 14:57:40 -04:00
										 |  |  | const int PACKET_TIMEOUT_SECONDS = 300; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  | APRSISClient::APRSISClient(QString host, quint16 port, QObject *parent): | 
					
						
							| 
									
										
										
										
											2018-09-21 14:43:02 -04:00
										 |  |  |     QTcpSocket(parent) | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-09-21 14:43:02 -04:00
										 |  |  |     setServer(host, port); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  |     connect(&m_timer, &QTimer::timeout, this, &APRSISClient::sendReports); | 
					
						
							| 
									
										
										
										
											2018-09-02 00:05:15 -04:00
										 |  |  |     m_timer.setInterval(60*1000); // every 60 seconds
 | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  |     m_timer.start(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | quint32 APRSISClient::hashCallsign(QString callsign){ | 
					
						
							|  |  |  |     // based on: https://github.com/hessu/aprsc/blob/master/src/passcode.c
 | 
					
						
							|  |  |  |     QByteArray rootCall = QString(callsign.split("-").first().toUpper()).toLocal8Bit() + '\0'; | 
					
						
							|  |  |  |     quint32 hash = 0x73E2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int i = 0; | 
					
						
							|  |  |  |     int len = rootCall.length(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while(i+1 < len){ | 
					
						
							|  |  |  |         hash ^= rootCall.at(i) << 8; | 
					
						
							|  |  |  |         hash ^= rootCall.at(i+1); | 
					
						
							|  |  |  |         i += 2; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return hash & 0x7FFF; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString APRSISClient::loginFrame(QString callsign){ | 
					
						
							|  |  |  |     auto loginFrame = QString("user %1 pass %2 ver %3\n"); | 
					
						
							|  |  |  |     loginFrame = loginFrame.arg(callsign); | 
					
						
							|  |  |  |     loginFrame = loginFrame.arg(hashCallsign(callsign)); | 
					
						
							| 
									
										
										
										
											2018-10-04 13:52:52 -04:00
										 |  |  |     loginFrame = loginFrame.arg("JS8Call"); | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  |     return loginFrame; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QList<QStringList> findall(QRegularExpression re, QString content){ | 
					
						
							|  |  |  |     int pos = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QList<QStringList> all; | 
					
						
							|  |  |  |     while(pos < content.length()){ | 
					
						
							|  |  |  |         auto match = re.match(content, pos); | 
					
						
							|  |  |  |         if(!match.hasMatch()){ | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         all.append(match.capturedTexts()); | 
					
						
							|  |  |  |         pos = match.capturedEnd(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return all; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | inline long | 
					
						
							|  |  |  | floordiv (long num, long den) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (0 < (num^den)) | 
					
						
							|  |  |  |     return num/den; | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       ldiv_t res = ldiv(num,den); | 
					
						
							|  |  |  |       return (res.rem)? res.quot-1 | 
					
						
							|  |  |  |                       : res.quot; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // convert an arbitrary length grid locator to a high precision lat/lon
 | 
					
						
							|  |  |  | QPair<float, float> APRSISClient::grid2deg(QString locator){ | 
					
						
							|  |  |  |     QString grid = locator.toUpper(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     float lat = -90; | 
					
						
							|  |  |  |     float lon = -90; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto lats = findall(QRegularExpression("([A-X])([A-X])"), grid); | 
					
						
							|  |  |  |     auto lons = findall(QRegularExpression("(\\d)(\\d)"), grid); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int valx[22]; | 
					
						
							|  |  |  |     int valy[22]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int i = 0; | 
					
						
							|  |  |  |     int tot = 0; | 
					
						
							|  |  |  |     char A = 'A'; | 
					
						
							|  |  |  |     foreach(QStringList matched, lats){ | 
					
						
							|  |  |  |         char x = matched.at(1).at(0).toLatin1(); | 
					
						
							|  |  |  |         char y = matched.at(2).at(0).toLatin1(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         valx[i*2] = x-A; | 
					
						
							|  |  |  |         valy[i*2] = y-A; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         i++; | 
					
						
							|  |  |  |         tot++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     i = 0; | 
					
						
							|  |  |  |     foreach(QStringList matched, lons){ | 
					
						
							|  |  |  |         int x = matched.at(1).toInt(); | 
					
						
							|  |  |  |         int y = matched.at(2).toInt(); | 
					
						
							|  |  |  |         valx[i*2+1]=x; | 
					
						
							|  |  |  |         valy[i*2+1]=y; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         i++; | 
					
						
							|  |  |  |         tot++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for(int i = 0; i < tot; i++){ | 
					
						
							|  |  |  |         int x = valx[i]; | 
					
						
							|  |  |  |         int y = valy[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         int z = i - 1; | 
					
						
							|  |  |  |         float scale = pow(10, floordiv(-(z-1), 2)) * pow(24, floordiv(-z, 2)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         lon += scale * x; | 
					
						
							|  |  |  |         lat += scale * y; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     lon *= 2; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return {lat, lon}; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // convert an arbitrary length grid locator to a high precision lat/lon in aprs format
 | 
					
						
							|  |  |  | QPair<QString, QString> APRSISClient::grid2aprs(QString grid){ | 
					
						
							|  |  |  |     auto geo = APRSISClient::grid2deg(grid); | 
					
						
							|  |  |  |     auto lat = geo.first; | 
					
						
							|  |  |  |     auto lon = geo.second; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString latDir = "N"; | 
					
						
							|  |  |  |     if(lat < 0){ | 
					
						
							|  |  |  |         lat *= -1; | 
					
						
							|  |  |  |         latDir = "S"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString lonDir = "E"; | 
					
						
							|  |  |  |     if(lon < 0){ | 
					
						
							|  |  |  |         lon *= -1; | 
					
						
							|  |  |  |         lonDir = "W"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     double iLat, fLat, iLon, fLon, iLatMin, fLatMin, iLonMin, fLonMin, iLatSec, iLonSec; | 
					
						
							|  |  |  |     fLat = modf(lat, &iLat); | 
					
						
							|  |  |  |     fLon = modf(lon, &iLon); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fLatMin = modf(fLat * 60, &iLatMin); | 
					
						
							|  |  |  |     fLonMin = modf(fLon * 60, &iLonMin); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     iLatSec = round(fLatMin * 60); | 
					
						
							|  |  |  |     iLonSec = round(fLonMin * 60); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if(iLatSec == 60){ | 
					
						
							|  |  |  |         iLatMin += 1; | 
					
						
							|  |  |  |         iLatSec = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if(iLonSec == 60){ | 
					
						
							|  |  |  |         iLonMin += 1; | 
					
						
							|  |  |  |         iLonSec = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if(iLatMin == 60){ | 
					
						
							|  |  |  |         iLat += 1; | 
					
						
							|  |  |  |         iLatMin = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if(iLonMin == 60){ | 
					
						
							|  |  |  |         iLon += 1; | 
					
						
							|  |  |  |         iLonMin = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     double aprsLat = iLat * 100 + iLatMin + (iLatSec / 60.0); | 
					
						
							|  |  |  |     double aprsLon = iLon * 100 + iLonMin + (iLonSec / 60.0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return { | 
					
						
							|  |  |  |         QString().sprintf("%07.2f%%1", aprsLat).arg(latDir), | 
					
						
							|  |  |  |         QString().sprintf("%08.2f%%1", aprsLon).arg(lonDir) | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-02 14:28:33 -04:00
										 |  |  | QString APRSISClient::stripSSID(QString call){ | 
					
						
							|  |  |  |     return QString(call.split("-").first().toUpper()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-21 14:43:02 -04:00
										 |  |  | QString APRSISClient::replaceCallsignSuffixWithSSID(QString call, QString base){ | 
					
						
							|  |  |  |     if(call != base){ | 
					
						
							|  |  |  |         QRegularExpression re("[/](?<ssid>(P|\\d+))"); | 
					
						
							|  |  |  |         auto matcher = re.globalMatch(call); | 
					
						
							|  |  |  |         if(matcher.hasNext()){ | 
					
						
							|  |  |  |             auto match = matcher.next(); | 
					
						
							|  |  |  |             auto ssid = match.captured("ssid"); | 
					
						
							|  |  |  |             if(ssid == "P"){ | 
					
						
							|  |  |  |                 ssid = "16"; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             call = base + "-" + ssid; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             call = base; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return call; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-30 15:01:43 -04:00
										 |  |  | void APRSISClient::enqueueSpot(QString theircall, QString grid, QString comment){ | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  |     if(m_localCall.isEmpty()) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto geo = APRSISClient::grid2aprs(grid); | 
					
						
							| 
									
										
										
										
											2018-10-04 13:52:52 -04:00
										 |  |  |     auto spotFrame = QString("%1>APRS,%2,TCPIP*:=%3/%4nJS8 %5\n"); | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  |     spotFrame = spotFrame.arg(theircall); | 
					
						
							| 
									
										
										
										
											2018-10-02 14:28:33 -04:00
										 |  |  |     spotFrame = spotFrame.arg(stripSSID(m_localCall)); | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  |     spotFrame = spotFrame.arg(geo.first); | 
					
						
							|  |  |  |     spotFrame = spotFrame.arg(geo.second); | 
					
						
							| 
									
										
										
										
											2018-08-30 15:01:43 -04:00
										 |  |  |     spotFrame = spotFrame.arg(comment.left(43)); | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  |     enqueueRaw(spotFrame); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-28 15:13:38 -04:00
										 |  |  | void APRSISClient::enqueueThirdParty(QString theircall, QString payload){ | 
					
						
							| 
									
										
										
										
											2018-09-10 10:12:42 -04:00
										 |  |  |     if(!isPasscodeValid()){ | 
					
						
							| 
									
										
										
										
											2018-09-05 11:33:50 -04:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-02 14:28:33 -04:00
										 |  |  |     auto frame = QString("%1>APRS,%2,TCPIP*:%3\n"); | 
					
						
							| 
									
										
										
										
											2018-08-28 15:13:38 -04:00
										 |  |  |     frame = frame.arg(theircall); | 
					
						
							| 
									
										
										
										
											2018-10-02 14:28:33 -04:00
										 |  |  |     frame = frame.arg(stripSSID(m_localCall)); | 
					
						
							| 
									
										
										
										
											2018-08-28 15:13:38 -04:00
										 |  |  |     frame = frame.arg(payload); | 
					
						
							|  |  |  |     enqueueRaw(frame); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  | void APRSISClient::enqueueRaw(QString aprsFrame){ | 
					
						
							| 
									
										
										
										
											2018-09-18 17:24:07 -04:00
										 |  |  |     m_frameQueue.enqueue({ aprsFrame, DriftingDateTime::currentDateTimeUtc() }); | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void APRSISClient::processQueue(bool disconnect){ | 
					
						
							| 
									
										
										
										
											2018-08-30 12:18:20 -04:00
										 |  |  |     // don't process queue if we haven't set our local callsign
 | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  |     if(m_localCall.isEmpty()) return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-30 12:18:20 -04:00
										 |  |  |     // don't process queue if there's nothing to process
 | 
					
						
							|  |  |  |     if(m_frameQueue.isEmpty()) return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-24 15:27:12 -04:00
										 |  |  |     // don't process queue if there's no host
 | 
					
						
							|  |  |  |     if(m_host.isEmpty() || m_port == 0){ | 
					
						
							|  |  |  |         // no host, so let's clear the queue and exit
 | 
					
						
							|  |  |  |         m_frameQueue.clear(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  |     // 1. connect (and read)
 | 
					
						
							|  |  |  |     // 2. login (and read)
 | 
					
						
							|  |  |  |     // 3. for each raw frame in queue, send
 | 
					
						
							|  |  |  |     // 4. disconnect
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if(state() != QTcpSocket::ConnectedState){ | 
					
						
							| 
									
										
										
										
											2018-09-21 14:43:02 -04:00
										 |  |  |         qDebug() << "APRSISClient Connecting:" << m_host << m_port; | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  |         connectToHost(m_host, m_port); | 
					
						
							|  |  |  |         if(!waitForConnected(5000)){ | 
					
						
							|  |  |  |             qDebug() << "APRSISClient Connection Error:" << errorString(); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-30 15:01:43 -04:00
										 |  |  |     auto re = QRegExp("(full|unavailable|busy)"); | 
					
						
							| 
									
										
										
										
											2018-08-30 14:31:31 -04:00
										 |  |  |     auto line = QString(readLine()); | 
					
						
							|  |  |  |     if(line.toLower().indexOf(re) >= 0){ | 
					
						
							|  |  |  |         qDebug() << "APRSISClient Connection Busy:" << line; | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  |     if(write(loginFrame(m_localCall).toLocal8Bit()) == -1){ | 
					
						
							|  |  |  |         qDebug() << "APRSISClient Write Login Error:" << errorString(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-30 14:31:31 -04:00
										 |  |  |     if(!waitForReadyRead(5000)){ | 
					
						
							|  |  |  |         qDebug() << "APRSISClient Login Error: Server Not Responding"; | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     line = QString(readAll()); | 
					
						
							|  |  |  |     if(line.toLower().indexOf(re) >= 0){ | 
					
						
							|  |  |  |         qDebug() << "APRSISClient Server Busy:" << line; | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-13 22:23:32 -04:00
										 |  |  |     QQueue<QPair<QString, QDateTime>> delayed; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  |     while(!m_frameQueue.isEmpty()){ | 
					
						
							| 
									
										
										
										
											2018-09-05 14:57:40 -04:00
										 |  |  |         auto pair = m_frameQueue.head(); | 
					
						
							|  |  |  |         auto frame = pair.first; | 
					
						
							|  |  |  |         auto timestamp = pair.second; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // if the packet is older than the timeout, drop it.
 | 
					
						
							| 
									
										
										
										
											2018-09-18 17:24:07 -04:00
										 |  |  |         if(timestamp.secsTo(DriftingDateTime::currentDateTimeUtc()) > PACKET_TIMEOUT_SECONDS){ | 
					
						
							| 
									
										
										
										
											2018-09-05 14:57:40 -04:00
										 |  |  |             qDebug() << "APRSISClient Packet Timeout:" << frame; | 
					
						
							|  |  |  |             m_frameQueue.dequeue(); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-08-30 14:31:31 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-13 22:23:32 -04:00
										 |  |  |         // random delay 25% of the time for throttling (a skip will add 60 seconds to the processing time)
 | 
					
						
							|  |  |  |         if(qrand() % 100 <= 25){ | 
					
						
							|  |  |  |             qDebug() << "APRSISClient Throttle: Skipping Frame"; | 
					
						
							|  |  |  |             delayed.enqueue(m_frameQueue.dequeue()); | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-05 14:57:40 -04:00
										 |  |  |         QByteArray data = frame.toLocal8Bit(); | 
					
						
							| 
									
										
										
										
											2018-08-30 14:31:31 -04:00
										 |  |  |         if(write(data) == -1){ | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  |             qDebug() << "APRSISClient Write Error:" << errorString(); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-30 14:31:31 -04:00
										 |  |  |         qDebug() << "APRSISClient Write:" << data; | 
					
						
							|  |  |  |         if(waitForReadyRead(5000)){ | 
					
						
							|  |  |  |             line = QString(readLine()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             qDebug() << "APRSISClient Read:" << line; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if(line.toLower().indexOf(re) >= 0){ | 
					
						
							|  |  |  |                 qDebug() << "APRSISClient Cannot Write Error:" << line; | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         m_frameQueue.dequeue(); | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-13 22:23:32 -04:00
										 |  |  |     // enqueue the delayed frames for later processing
 | 
					
						
							|  |  |  |     while(!delayed.isEmpty()){ | 
					
						
							|  |  |  |         m_frameQueue.enqueue(delayed.dequeue()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-27 21:19:38 -04:00
										 |  |  |     if(disconnect){ | 
					
						
							|  |  |  |         disconnectFromHost(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |