From fd3dc4dbe9fa906163e85fdf90cd047287d1e997 Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Thu, 4 Jul 2013 22:14:06 +0100 Subject: [PATCH 01/15] first iteration on #22 shimlib integration --- src/blackcore/network.h | 79 ++++++ src/blackcore/network_vatlib.cpp | 422 +++++++++++++++++++++++++++++++ src/blackcore/network_vatlib.h | 86 +++++++ 3 files changed, 587 insertions(+) create mode 100644 src/blackcore/network.h create mode 100644 src/blackcore/network_vatlib.cpp create mode 100644 src/blackcore/network_vatlib.h diff --git a/src/blackcore/network.h b/src/blackcore/network.h new file mode 100644 index 000000000..6e5c65954 --- /dev/null +++ b/src/blackcore/network.h @@ -0,0 +1,79 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/*! + \file +*/ + +#ifndef BLACKCORE_NETWORK_H +#define BLACKCORE_NETWORK_H + +#include "../blackmisc/pqfrequency.h" +#include "../blackmisc/coordinategeodetic.h" +#include "../blackmisc/pqlength.h" +#include "../blackmisc/pqtime.h" +#include +#include +#include +#include + +namespace BlackCore +{ + + class INetwork : public QObject + { + Q_OBJECT; + + public slots: + virtual void setServerDetails(const QString& hostname, quint16 port) = 0; + virtual void setUserCredentials(const QString& username, const QString& password) = 0; + virtual void initiateConnection() = 0; + virtual void terminateConnection() = 0; + virtual void sendPrivateTextMessage(const QString& callsign, const QString& msg) = 0; + virtual void sendRadioTextMessage(const QVector& freqs, const QString& msg) = 0; + //TODO virtual void sendInfoQuery(...) = 0; + //TODO virtual void replyToInfoQuery(...) = 0; + virtual void requestPlaneInfo(const QString& callsign) = 0; + //TODO virtual void setPlanePosition(...) = 0; + //TODO virtual void sendFlightPlan(...) = 0; + virtual void sendPlaneInfo(const QString& callsign, const QString& acTypeICAO, const QString& airlineICAO, const QString& livery) = 0; + virtual void ping(const QString& callsign) = 0; + virtual void requestMetar(const QString& airportICAO) = 0; + virtual void requestWeatherData(const QString& airportICAO) = 0; + + signals: + void atcPositionUpdate(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq, + const BlackMisc::Geo::CCoordinateGeodetic& pos, const BlackMisc::PhysicalQuantities::CLength& range); + void atcDisconnected(const QString& callsign); + void atisReplyReceived(const QString& callsign, const QString& data); + //TODO void cloudDataReceived(...); + void connectionStatusIdle(); + void connectionStatusConnecting(); + void connectionStatusConnected(); + void connectionStatusDisconnected(); + void connectionStatusError(); + //TODO void atisQueryReplyReceived(...); + //TODO void nameQueryReplyReceived(const QString& callsign, const QString& name); + //TODO void capabilitiesQueryReplyReceived(...); + void ipQueryReplyReceived(const QString& ip); + void fpQueryRequestReceived(const QString& callsign); + void freqQueryRequestReceived(const QString& callsign); + //TODO void interimPilotPositionUpdate(...); + void kicked(const QString& msg); + void metarReceived(const QString& data); + void pilotDisconnected(const QString& callsign); + void planeInfoReceived(const QString& callsign, const QString& acTypeICAO, const QString& airlineICAO, const QString& livery); + void planeInfoRequestReceived(const QString& callsign); + //TODO void pilotPositionUpdate(...); + void pong(const QString& callsign, const BlackMisc::PhysicalQuantities::CTime& elapsedTime); + void radioTextMessageReceived(const QString& callsign, const QString& msg, const QVector& freqs); + void privateTextMessageReceived(const QString& fromCallsign, const QString& toCallsign, const QString& msg); + //TODO void temperatureDataReceived(...); + //TODO void windDataReceived(...); + }; + +} //namespace BlackCore + +#endif //BLACKCORE_NETWORK_H diff --git a/src/blackcore/network_vatlib.cpp b/src/blackcore/network_vatlib.cpp new file mode 100644 index 000000000..24df8ba24 --- /dev/null +++ b/src/blackcore/network_vatlib.cpp @@ -0,0 +1,422 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "network_vatlib.h" +#include +#include +#include + +/* +Macro to convert a QString to a C string (const char*). +The C string will cease to be valid at the end of the current statement, so it can't be saved for later without making a copy. +Something like this is valid: + myPrint(C_STR(myQString)); +But this is not: + const char *s = C_STR(myQString); myPrint(s); +*/ +#define C_STR(s) ((s).toUtf8().constData()) //TODO ask Gary UTF-8 or ASCII for text that will be sent over FSD? + +namespace BlackCore +{ + + using namespace BlackMisc::PhysicalQuantities; + using namespace BlackMisc::Geo; + + NetworkVatlib::NetworkVatlib() + : m_net(Create_Cvatlib_Network()) + { + try + { + m_net->InstallOnConnectionStatusChangedEvent(onConnectionStatusChanged, this); + m_net->InstallOnTextMessageReceivedEvent(onTextMessageReceived, this); + m_net->InstallOnRadioMessageReceivedEvent(onRadioMessageReceived, this); + m_net->InstallOnPilotDisconnectedEvent(onPilotDisconnected, this); + m_net->InstallOnControllerDisconnectedEvent(onControllerDisconnected, this); + m_net->InstallOnPilotPositionUpdateEvent(onPilotPositionUpdate, this); + m_net->InstallOnInterimPilotPositionUpdateEvent(onInterimPilotPositionUpdate, this); + m_net->InstallOnAtcPositionUpdateEvent(onAtcPositionUpdate, this); + m_net->InstallOnKickedEvent(onKicked, this); + m_net->InstallOnPongEvent(onPong, this); + m_net->InstallOnMetarReceivedEvent(onMetarReceived, this); + m_net->InstallOnInfoQueryRequestReceivedEvent(onInfoQueryRequestReceived, this); + m_net->InstallOnInfoQueryReplyReceivedEvent(onInfoQueryReplyReceived, this); + m_net->InstallOnCapabilitiesReplyReceivedEvent(onCapabilitiesReplyReceived, this); + m_net->InstallOnAtisReplyReceivedEvent(onAtisReplyReceived, this); + m_net->InstallOnTemperatureDataReceivedEvent(onTemperatureDataReceived, this); + m_net->InstallOnErrorReceivedEvent(onErrorReceived, this); + m_net->InstallOnWindDataReceivedEvent(onWindDataReceived, this); + m_net->InstallOnCloudDataReceivedEvent(onCloudDataReceived, this); + m_net->InstallOnPilotInfoRequestReceivedEvent(onPilotInfoRequestReceived, this); + m_net->InstallOnPilotInfoReceivedEvent(onPilotInfoReceived, this); + + QString capabilities; + capabilities += m_net->capability_AtcInfo; + capabilities += "=1:"; + capabilities += m_net->capability_InterimPos; + capabilities += "=1:"; + capabilities += m_net->capability_ModelDesc; + capabilities += "=1"; + + m_net->CreateNetworkSession(CLIENT_NAME_VERSION, CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, + CLIENT_SIMULATOR_NAME, CLIENT_PUBLIC_ID, CLIENT_PRIVATE_KEY, C_STR(capabilities)); + + m_timer.start(c_updateIntervalMillisecs, this); + } + catch (...) { exceptionDispatcher(); } + } + + NetworkVatlib::~NetworkVatlib() + { + try + { + m_timer.stop(); + + if (m_net->IsNetworkConnected()) + { + m_net->LogoffAndDisconnect(0); + } + + m_net->DestroyNetworkSession(); + } + catch (...) { exceptionDispatcher(); } + } + + void NetworkVatlib::timerEvent(QTimerEvent*) + { + try + { + if (m_net->IsValid() && m_net->IsSessionExists()) + { + m_net->DoProcessing(); + } + } + catch (...) { exceptionDispatcher(); } + } + + void NetworkVatlib::exceptionDispatcher() + { + try + { + throw; + } + //catch (InvalidObjectException& e) //TODO ask Gary to confirm that trying to use an invalid Cvatlib_Network is always the result of a programmer error + //catch (ObjectNotSetupException& e) //TODO ask Gary what is "the setup function" mentioned in the ObjectNotSetupException documentation? + catch (NetworkNotConnectedException& e) + { + qDebug() << "NetworkNotConnectedException: " << e.what(); + } + catch (VatlibException& e) + { + Q_ASSERT_X(false, "NetworkVatlib", e.what()); + assert(false); + qDebug() << "VatlibException: " << e.what(); + } + catch (std::exception& e) + { + Q_ASSERT_X(false, "NetworkVatlib", e.what()); + assert(false); + qDebug() << "NetworkVatlib: std::exception: " << e.what(); + } + catch (...) + { + Q_ASSERT_X(false, "NetworkVatlib", "Unknown exception"); + assert(false); + qDebug() << "NetworkVatlib: unknown exception"; + } + } + + /********************************** * * * * * * * * * * * * * * * * * * * ************************************/ + /********************************** INetwork slots ************************************/ + /********************************** * * * * * * * * * * * * * * * * * * * ************************************/ + + void NetworkVatlib::setServerDetails(const QString& host, quint16 port) + { + m_serverHost = host; + m_serverPort = port; + } + + void NetworkVatlib::setUserCredentials(const QString& username, const QString& password) + { + m_username = username; + m_password = password; + } + + void NetworkVatlib::initiateConnection() + { + try + { + m_net->ConnectAndLogon(); + } + catch (...) { exceptionDispatcher(); } + } + + void NetworkVatlib::terminateConnection() + { + try + { + m_net->LogoffAndDisconnect(c_logoffTimeoutSeconds); //TODO ask Gary will this block? + } + catch (...) { exceptionDispatcher(); } + } + + void NetworkVatlib::sendPrivateTextMessage(const QString& callsign, const QString& msg) + { + try + { + m_net->SendPrivateTextMessage(C_STR(callsign), C_STR(msg)); + } + catch (...) { exceptionDispatcher(); } + } + + void NetworkVatlib::sendRadioTextMessage(const QVector& freqs, const QString& msg) + { + try + { + std::vector freqsVec; + for (int i = 0; i < freqs.size(); ++i) + { + freqsVec.push_back(freqs[i].value(CFrequencyUnit::kHz())); + } + m_net->SendRadioTextMessage(freqsVec.size(), freqsVec.data(), C_STR(msg)); + } + catch (...) { exceptionDispatcher(); } + } + + void NetworkVatlib::requestPlaneInfo(const QString& callsign) + { + try + { + m_net->RequestPlaneInfo(C_STR(callsign)); + } + catch (...) { exceptionDispatcher(); } + } + + void NetworkVatlib::sendPlaneInfo(const QString& callsign, const QString& acTypeICAO, const QString& airlineICAO, const QString& livery) + { + try + { + const QByteArray acTypeICAObytes = acTypeICAO.toUtf8(); //TODO ask Gary UTF-8 or ASCII? + const QByteArray airlineICAObytes = airlineICAO.toUtf8(); //TODO ask Gary UTF-8 or ASCII? + const QByteArray liverybytes = livery.toUtf8(); //TODO ask Gary UTF-8 or ASCII? + std::vector keysValues; + if (! acTypeICAO.isEmpty()) + { + keysValues.push_back(m_net->acinfo_Equipment); + keysValues.push_back(acTypeICAObytes.data()); + } + if (! airlineICAO.isEmpty()) + { + keysValues.push_back(m_net->acinfo_Airline); + keysValues.push_back(airlineICAObytes.data()); + } + if (! livery.isEmpty()) + { + keysValues.push_back(m_net->acinfo_Livery); + keysValues.push_back(liverybytes.data()); + } + keysValues.push_back(0); + m_net->SendPlaneInfo(C_STR(callsign), keysValues.data()); + } + catch (...) { exceptionDispatcher(); } + } + + void NetworkVatlib::ping(const QString& callsign) + { + try + { + m_net->PingUser(C_STR(callsign)); + } + catch (...) { exceptionDispatcher(); } + } + + void NetworkVatlib::requestMetar(const QString& airportICAO) + { + try + { + m_net->RequestMetar(C_STR(airportICAO)); + } + catch (...) { exceptionDispatcher(); } + } + + void NetworkVatlib::requestWeatherData(const QString& airportICAO) + { + try + { + m_net->RequestWeatherData(C_STR(airportICAO)); + } + catch (...) { exceptionDispatcher(); } + } + + /********************************** * * * * * * * * * * * * * * * * * * * ************************************/ + /********************************** shimlib callbacks ************************************/ + /********************************** * * * * * * * * * * * * * * * * * * * ************************************/ + + NetworkVatlib* cbvar_cast(void* cbvar) + { + return static_cast(cbvar); + } + + void NetworkVatlib::onConnectionStatusChanged(Cvatlib_Network*, Cvatlib_Network::connStatus, Cvatlib_Network::connStatus newStatus, void* cbvar) + { + switch (newStatus) + { + case Cvatlib_Network::connStatus_Idle: emit cbvar_cast(cbvar)->connectionStatusIdle(); break; + case Cvatlib_Network::connStatus_Connecting: emit cbvar_cast(cbvar)->connectionStatusConnecting(); break; + case Cvatlib_Network::connStatus_Connected: emit cbvar_cast(cbvar)->connectionStatusConnected(); break; + case Cvatlib_Network::connStatus_Disconnected: emit cbvar_cast(cbvar)->connectionStatusDisconnected(); break; + case Cvatlib_Network::connStatus_Error: emit cbvar_cast(cbvar)->connectionStatusError(); break; + } + } + + void NetworkVatlib::onTextMessageReceived(Cvatlib_Network*, const char* from, const char* to, const char* msg, void* cbvar) + { + emit cbvar_cast(cbvar)->privateTextMessageReceived(from, to, msg); + } + + void NetworkVatlib::onRadioMessageReceived(Cvatlib_Network*, const char* from, INT numFreq, INT* freqList, const char* msg, void* cbvar) + { + QVector freqs; + for (int i = 0; i < numFreq; ++i) + { + freqs.push_back(CFrequency(freqList[i], CFrequencyUnit::kHz())); + } + emit cbvar_cast(cbvar)->radioTextMessageReceived(from, msg, freqs); + } + + void NetworkVatlib::onPilotDisconnected(Cvatlib_Network*, const char* callsign, void* cbvar) + { + emit cbvar_cast(cbvar)->pilotDisconnected(callsign); + } + + void NetworkVatlib::onControllerDisconnected(Cvatlib_Network*, const char* callsign, void* cbvar) + { + emit cbvar_cast(cbvar)->atcDisconnected(callsign); + } + + void NetworkVatlib::onPilotPositionUpdate(Cvatlib_Network*, const char* callsign, Cvatlib_Network::PilotPosUpdate pos, void* cbvar) + { + //TODO + } + + void NetworkVatlib::onInterimPilotPositionUpdate(Cvatlib_Network*, const char* callsign, Cvatlib_Network::PilotPosUpdate pos, void* cbvar) + { + //TODO + } + + void NetworkVatlib::onAtcPositionUpdate(Cvatlib_Network*, const char* callsign, Cvatlib_Network::ATCPosUpdate pos, void* cbvar) + { + emit cbvar_cast(cbvar)->atcPositionUpdate(callsign, CFrequency(pos.frequency, CFrequencyUnit::kHz()), + CCoordinateGeodetic(pos.lat, pos.lon, 0), CLength(pos.visibleRange, CLengthUnit::NM())); + } + + void NetworkVatlib::onKicked(Cvatlib_Network*, const char* reason, void* cbvar) + { + emit cbvar_cast(cbvar)->kicked(reason); + } + + void NetworkVatlib::onPong(Cvatlib_Network*, const char* callsign, INT elapsedTime, void* cbvar) + { + emit cbvar_cast(cbvar)->pong(callsign, CTime(elapsedTime, CTimeUnit::ms())); //TODO ask Gary to confirm time unit + } + + void NetworkVatlib::onMetarReceived(Cvatlib_Network*, const char* data, void* cbvar) + { + emit cbvar_cast(cbvar)->metarReceived(data); + } + + void NetworkVatlib::onInfoQueryRequestReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::infoQuery type, const char* data, void* cbvar) + { + switch (type) + { + case Cvatlib_Network::infoQuery_FP: emit cbvar_cast(cbvar)->fpQueryRequestReceived(callsign); break; + case Cvatlib_Network::infoQuery_Freq: emit cbvar_cast(cbvar)->freqQueryRequestReceived(callsign); break; + //TODO ask Gary whether we need to reply to UserInfo, Server, Name, Capabilities, or IP queries + } + } + + void NetworkVatlib::onInfoQueryReplyReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::infoQuery type, const char* data, const char* data2, void* cbvar) + { + switch (type) + { + case Cvatlib_Network::infoQuery_ATIS: break; //TODO ask Gary do we handle this here or in onAtisReplyReceived or both? + case Cvatlib_Network::infoQuery_Name: break; //TODO ask Gary what are the meanings of data and data2 in this context? + case Cvatlib_Network::infoQuery_Capabilities: break; //TODO ask Gary do we handle this here or in onCapabilitiesReplyReceived or both? + case Cvatlib_Network::infoQuery_IP: emit cbvar_cast(cbvar)->ipQueryReplyReceived(data); break; + } + } + + void NetworkVatlib::onCapabilitiesReplyReceived(Cvatlib_Network*, const char* callsign, const char** keysValues, void* cbvar) + { + //TODO + } + + void NetworkVatlib::onAtisReplyReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::atisLineType type, const char* data, void* cbvar) + { + emit cbvar_cast(cbvar)->atisReplyReceived(callsign, data); + } + + void NetworkVatlib::onTemperatureDataReceived(Cvatlib_Network*, Cvatlib_Network::TempLayer layers[4], INT pressure, void* cbvar) + { + //TODO + } + + void NetworkVatlib::onErrorReceived(Cvatlib_Network*, Cvatlib_Network::error type, const char* msg, const char* data, void* cbvar) + { + switch (type) + { + case Cvatlib_Network::error_Ok: return; + case Cvatlib_Network::error_CallsignTaken: qCritical() << "The requested callsign is already taken"; break; + case Cvatlib_Network::error_CallsignInvalid: qCritical() << "The requested callsign is not valid"; break; + case Cvatlib_Network::error_Registered: break; //TODO ask Gary to explain meaning + case Cvatlib_Network::error_Syntax: assert(false); qWarning() << "VATSIM shim library: Syntax error: " << data; break; + case Cvatlib_Network::error_SourceInvalid: break; //TODO ask Gary to explain meaning + case Cvatlib_Network::error_CIDPasswdInvalid: qCritical() << "Wrong user ID or password"; break; + case Cvatlib_Network::error_CallsignNotExists: qDebug() << "Shim lib: " << msg << " (" << data << ")"; break; + case Cvatlib_Network::error_NoFP: break; //TODO ask Gary under what circumstance this can happen + case Cvatlib_Network::error_NoWeather: break; //TODO ask Gary to explain meaning + case Cvatlib_Network::error_ProtoVersion: qCritical() << "This server uses an unsupported protocol version"; break; + case Cvatlib_Network::error_LevelTooHigh: qCritical() << "You are not authorized to use the requested pilot rating"; break; //TODO ask Gary to confirm meaning + case Cvatlib_Network::error_ServerFull: qCritical() << "The server is full"; break; + case Cvatlib_Network::error_CIDSuspended: qCritical() << "Your user account is suspended"; break; + case Cvatlib_Network::error_InvalidControl: break; //TODO ask Gary to explain meaning + case Cvatlib_Network::error_InvalidPosition: qCritical() << "You are not authorized to use the requested pilot rating"; break; + case Cvatlib_Network::error_SoftwareNotAuthorized: qCritical() << "This client software has not been authorized for use on this network"; break; + default: assert(false); qWarning() << "VATSIM shim library: " << msg << "(error " << type << ")"; break; + } + } + + void NetworkVatlib::onWindDataReceived(Cvatlib_Network*, Cvatlib_Network::WindLayer layers[4], void* cbvar) + { + //TODO + } + + void NetworkVatlib::onCloudDataReceived(Cvatlib_Network*, Cvatlib_Network::CloudLayer layers[2], Cvatlib_Network::StormLayer storm, float vis, void* cbvar) + { + //TODO + } + + void NetworkVatlib::onPilotInfoRequestReceived(Cvatlib_Network*, const char* callsign, void* cbvar) + { + emit cbvar_cast(cbvar)->planeInfoRequestReceived(callsign); + } + + void NetworkVatlib::onPilotInfoReceived(Cvatlib_Network* net, const char* callsign, const char** keysValues, void* cbvar) + { + QString acTypeICAO; + QString airlineICAO; + QString livery; + while (*keysValues) + { + QString key (*keysValues); + keysValues++; + if (key == net->acinfo_Equipment) { acTypeICAO = *keysValues; } + else if (key == net->acinfo_Airline) { airlineICAO = *keysValues; } + else if (key == net->acinfo_Livery) { livery = *keysValues; } + keysValues++; + } + emit cbvar_cast(cbvar)->planeInfoReceived(callsign, acTypeICAO, airlineICAO, livery); + } + +} //namespace BlackCore diff --git a/src/blackcore/network_vatlib.h b/src/blackcore/network_vatlib.h new file mode 100644 index 000000000..4a106e9ad --- /dev/null +++ b/src/blackcore/network_vatlib.h @@ -0,0 +1,86 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/*! + \file +*/ + +#ifndef BLACKCORE_NETWORK_VATLIB_H +#define BLACKCORE_NETWORK_VATLIB_H + +#include "network.h" +#include "../../vatlib/vatlib.h" +#include +#include + +namespace BlackCore +{ + + class NetworkVatlib : public INetwork + { + Q_OBJECT; + + public: + NetworkVatlib(); + virtual ~NetworkVatlib(); + + protected: //QObject overrides + virtual void timerEvent(QTimerEvent*); + + public: //INetwork slots overrides + virtual void setServerDetails(const QString& hostname, quint16 port); + virtual void setUserCredentials(const QString& username, const QString& password); + virtual void initiateConnection(); + virtual void terminateConnection(); + virtual void sendPrivateTextMessage(const QString& callsign, const QString& msg); + virtual void sendRadioTextMessage(const QVector& freqs, const QString& msg); + virtual void requestPlaneInfo(const QString& callsign); + virtual void sendPlaneInfo(const QString& callsign, const QString& acTypeICAO, const QString& airlineICAO, const QString& livery); + virtual void ping(const QString& callsign); + virtual void requestMetar(const QString& airportICAO); + virtual void requestWeatherData(const QString& airportICAO); + + private: //shimlib callbacks + static void onConnectionStatusChanged(Cvatlib_Network*, Cvatlib_Network::connStatus oldStatus, Cvatlib_Network::connStatus newStatus, void* cbvar); + static void onTextMessageReceived(Cvatlib_Network*, const char* from, const char* to, const char* msg, void* cbvar); + static void onRadioMessageReceived(Cvatlib_Network*, const char* from, INT numFreq, INT* freqList, const char* msg, void* cbvar); + static void onPilotDisconnected(Cvatlib_Network*, const char* callsign, void* cbvar); + static void onControllerDisconnected(Cvatlib_Network*, const char* callsign, void* cbvar); + static void onPilotPositionUpdate(Cvatlib_Network*, const char* callsign, Cvatlib_Network::PilotPosUpdate pos, void* cbvar); + static void onInterimPilotPositionUpdate(Cvatlib_Network*, const char* callsign, Cvatlib_Network::PilotPosUpdate pos, void* cbvar); + static void onAtcPositionUpdate(Cvatlib_Network*, const char* callsign, Cvatlib_Network::ATCPosUpdate pos, void* cbvar); + static void onKicked(Cvatlib_Network*, const char* reason, void* cbvar); + static void onPong(Cvatlib_Network*, const char* callsign, INT elapsedTime, void* cbvar); + static void onMetarReceived(Cvatlib_Network*, const char* data, void* cbvar); + static void onInfoQueryRequestReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::infoQuery type, const char* data, void* cbvar); + static void onInfoQueryReplyReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::infoQuery type, const char* data, const char* data2, void* cbvar); + static void onCapabilitiesReplyReceived(Cvatlib_Network*, const char* callsign, const char** keysValues, void* cbvar); + static void onAtisReplyReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::atisLineType type, const char* data, void* cbvar); + static void onTemperatureDataReceived(Cvatlib_Network*, Cvatlib_Network::TempLayer layers[4], INT pressure, void* cbvar); + static void onErrorReceived(Cvatlib_Network*, Cvatlib_Network::error type, const char* msg, const char* data, void* cbvar); + static void onWindDataReceived(Cvatlib_Network*, Cvatlib_Network::WindLayer layers[4], void* cbvar); + static void onCloudDataReceived(Cvatlib_Network*, Cvatlib_Network::CloudLayer layers[2], Cvatlib_Network::StormLayer storm, float vis, void* cbvar); + static void onPilotInfoRequestReceived(Cvatlib_Network*, const char* callsign, void* cbvar); + static void onPilotInfoReceived(Cvatlib_Network*, const char* callsign, const char** keysValues, void* cbvar); + + private: + void exceptionDispatcher(); + + private: + QScopedPointer m_net; + + QBasicTimer m_timer; + static int const c_updateIntervalMillisecs = 100; + static int const c_logoffTimeoutSeconds = 5; + + QString m_serverHost; + quint16 m_serverPort; + QString m_username; + QString m_password; + }; + +} //namespace BlackCore + +#endif //BLACKCORE_NETWORK_VATLIB_H From ab71d75683f6e07dafd992cadede0787c7551a9b Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Fri, 5 Jul 2013 16:42:35 +0100 Subject: [PATCH 02/15] groundwork for I18N of text sent over FSD (refs #22) --- src/blackcore/network_vatlib.cpp | 96 +++++++++++++++++--------------- src/blackcore/network_vatlib.h | 6 ++ 2 files changed, 57 insertions(+), 45 deletions(-) diff --git a/src/blackcore/network_vatlib.cpp b/src/blackcore/network_vatlib.cpp index 24df8ba24..fe242d6a1 100644 --- a/src/blackcore/network_vatlib.cpp +++ b/src/blackcore/network_vatlib.cpp @@ -8,16 +8,6 @@ #include #include -/* -Macro to convert a QString to a C string (const char*). -The C string will cease to be valid at the end of the current statement, so it can't be saved for later without making a copy. -Something like this is valid: - myPrint(C_STR(myQString)); -But this is not: - const char *s = C_STR(myQString); myPrint(s); -*/ -#define C_STR(s) ((s).toUtf8().constData()) //TODO ask Gary UTF-8 or ASCII for text that will be sent over FSD? - namespace BlackCore { @@ -25,10 +15,15 @@ namespace BlackCore using namespace BlackMisc::Geo; NetworkVatlib::NetworkVatlib() - : m_net(Create_Cvatlib_Network()) + : m_net(Create_Cvatlib_Network()), + m_fsdTextCodec(QTextCodec::codecForName("latin1")) { try { + Q_ASSERT_X(m_fsdTextCodec, "NetworkVatlib", "Missing default wire text encoding"); + assert(m_fsdTextCodec); + //TODO reinit m_fsdTextCodec from WireTextEncoding config setting if present + m_net->InstallOnConnectionStatusChangedEvent(onConnectionStatusChanged, this); m_net->InstallOnTextMessageReceivedEvent(onTextMessageReceived, this); m_net->InstallOnRadioMessageReceivedEvent(onRadioMessageReceived, this); @@ -60,7 +55,7 @@ namespace BlackCore capabilities += "=1"; m_net->CreateNetworkSession(CLIENT_NAME_VERSION, CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, - CLIENT_SIMULATOR_NAME, CLIENT_PUBLIC_ID, CLIENT_PRIVATE_KEY, C_STR(capabilities)); + CLIENT_SIMULATOR_NAME, CLIENT_PUBLIC_ID, CLIENT_PRIVATE_KEY, toFSD(capabilities)); m_timer.start(c_updateIntervalMillisecs, this); } @@ -95,6 +90,16 @@ namespace BlackCore catch (...) { exceptionDispatcher(); } } + QByteArray NetworkVatlib::toFSD(QString qstr) const + { + return m_fsdTextCodec->fromUnicode(qstr); + } + + QString NetworkVatlib::fromFSD(const char* cstr) const + { + return m_fsdTextCodec->toUnicode(cstr); + } + void NetworkVatlib::exceptionDispatcher() { try @@ -165,7 +170,7 @@ namespace BlackCore { try { - m_net->SendPrivateTextMessage(C_STR(callsign), C_STR(msg)); + m_net->SendPrivateTextMessage(toFSD(callsign), toFSD(msg)); } catch (...) { exceptionDispatcher(); } } @@ -179,7 +184,7 @@ namespace BlackCore { freqsVec.push_back(freqs[i].value(CFrequencyUnit::kHz())); } - m_net->SendRadioTextMessage(freqsVec.size(), freqsVec.data(), C_STR(msg)); + m_net->SendRadioTextMessage(freqsVec.size(), freqsVec.data(), toFSD(msg)); } catch (...) { exceptionDispatcher(); } } @@ -188,7 +193,7 @@ namespace BlackCore { try { - m_net->RequestPlaneInfo(C_STR(callsign)); + m_net->RequestPlaneInfo(toFSD(callsign)); } catch (...) { exceptionDispatcher(); } } @@ -197,27 +202,27 @@ namespace BlackCore { try { - const QByteArray acTypeICAObytes = acTypeICAO.toUtf8(); //TODO ask Gary UTF-8 or ASCII? - const QByteArray airlineICAObytes = airlineICAO.toUtf8(); //TODO ask Gary UTF-8 or ASCII? - const QByteArray liverybytes = livery.toUtf8(); //TODO ask Gary UTF-8 or ASCII? + const QByteArray acTypeICAObytes = toFSD(acTypeICAO); + const QByteArray airlineICAObytes = toFSD(airlineICAO); + const QByteArray liverybytes = toFSD(livery); std::vector keysValues; if (! acTypeICAO.isEmpty()) { keysValues.push_back(m_net->acinfo_Equipment); - keysValues.push_back(acTypeICAObytes.data()); + keysValues.push_back(acTypeICAObytes); } if (! airlineICAO.isEmpty()) { keysValues.push_back(m_net->acinfo_Airline); - keysValues.push_back(airlineICAObytes.data()); + keysValues.push_back(airlineICAObytes); } if (! livery.isEmpty()) { keysValues.push_back(m_net->acinfo_Livery); - keysValues.push_back(liverybytes.data()); + keysValues.push_back(liverybytes); } keysValues.push_back(0); - m_net->SendPlaneInfo(C_STR(callsign), keysValues.data()); + m_net->SendPlaneInfo(toFSD(callsign), keysValues.data()); } catch (...) { exceptionDispatcher(); } } @@ -226,7 +231,7 @@ namespace BlackCore { try { - m_net->PingUser(C_STR(callsign)); + m_net->PingUser(toFSD(callsign)); } catch (...) { exceptionDispatcher(); } } @@ -235,7 +240,7 @@ namespace BlackCore { try { - m_net->RequestMetar(C_STR(airportICAO)); + m_net->RequestMetar(toFSD(airportICAO)); } catch (...) { exceptionDispatcher(); } } @@ -244,7 +249,7 @@ namespace BlackCore { try { - m_net->RequestWeatherData(C_STR(airportICAO)); + m_net->RequestWeatherData(toFSD(airportICAO)); } catch (...) { exceptionDispatcher(); } } @@ -272,7 +277,7 @@ namespace BlackCore void NetworkVatlib::onTextMessageReceived(Cvatlib_Network*, const char* from, const char* to, const char* msg, void* cbvar) { - emit cbvar_cast(cbvar)->privateTextMessageReceived(from, to, msg); + emit cbvar_cast(cbvar)->privateTextMessageReceived(cbvar_cast(cbvar)->fromFSD(from), cbvar_cast(cbvar)->fromFSD(to), cbvar_cast(cbvar)->fromFSD(msg)); } void NetworkVatlib::onRadioMessageReceived(Cvatlib_Network*, const char* from, INT numFreq, INT* freqList, const char* msg, void* cbvar) @@ -282,17 +287,17 @@ namespace BlackCore { freqs.push_back(CFrequency(freqList[i], CFrequencyUnit::kHz())); } - emit cbvar_cast(cbvar)->radioTextMessageReceived(from, msg, freqs); + emit cbvar_cast(cbvar)->radioTextMessageReceived(cbvar_cast(cbvar)->fromFSD(from), cbvar_cast(cbvar)->fromFSD(msg), freqs); } void NetworkVatlib::onPilotDisconnected(Cvatlib_Network*, const char* callsign, void* cbvar) { - emit cbvar_cast(cbvar)->pilotDisconnected(callsign); + emit cbvar_cast(cbvar)->pilotDisconnected(cbvar_cast(cbvar)->fromFSD(callsign)); } void NetworkVatlib::onControllerDisconnected(Cvatlib_Network*, const char* callsign, void* cbvar) { - emit cbvar_cast(cbvar)->atcDisconnected(callsign); + emit cbvar_cast(cbvar)->atcDisconnected(cbvar_cast(cbvar)->fromFSD(callsign)); } void NetworkVatlib::onPilotPositionUpdate(Cvatlib_Network*, const char* callsign, Cvatlib_Network::PilotPosUpdate pos, void* cbvar) @@ -307,31 +312,31 @@ namespace BlackCore void NetworkVatlib::onAtcPositionUpdate(Cvatlib_Network*, const char* callsign, Cvatlib_Network::ATCPosUpdate pos, void* cbvar) { - emit cbvar_cast(cbvar)->atcPositionUpdate(callsign, CFrequency(pos.frequency, CFrequencyUnit::kHz()), + emit cbvar_cast(cbvar)->atcPositionUpdate(cbvar_cast(cbvar)->fromFSD(callsign), CFrequency(pos.frequency, CFrequencyUnit::kHz()), CCoordinateGeodetic(pos.lat, pos.lon, 0), CLength(pos.visibleRange, CLengthUnit::NM())); } void NetworkVatlib::onKicked(Cvatlib_Network*, const char* reason, void* cbvar) { - emit cbvar_cast(cbvar)->kicked(reason); + emit cbvar_cast(cbvar)->kicked(cbvar_cast(cbvar)->fromFSD(reason)); } void NetworkVatlib::onPong(Cvatlib_Network*, const char* callsign, INT elapsedTime, void* cbvar) { - emit cbvar_cast(cbvar)->pong(callsign, CTime(elapsedTime, CTimeUnit::ms())); //TODO ask Gary to confirm time unit + emit cbvar_cast(cbvar)->pong(cbvar_cast(cbvar)->fromFSD(callsign), CTime(elapsedTime, CTimeUnit::ms())); //TODO ask Gary to confirm time unit } void NetworkVatlib::onMetarReceived(Cvatlib_Network*, const char* data, void* cbvar) { - emit cbvar_cast(cbvar)->metarReceived(data); + emit cbvar_cast(cbvar)->metarReceived(cbvar_cast(cbvar)->fromFSD(data)); } void NetworkVatlib::onInfoQueryRequestReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::infoQuery type, const char* data, void* cbvar) { switch (type) { - case Cvatlib_Network::infoQuery_FP: emit cbvar_cast(cbvar)->fpQueryRequestReceived(callsign); break; - case Cvatlib_Network::infoQuery_Freq: emit cbvar_cast(cbvar)->freqQueryRequestReceived(callsign); break; + case Cvatlib_Network::infoQuery_FP: emit cbvar_cast(cbvar)->fpQueryRequestReceived(cbvar_cast(cbvar)->fromFSD(callsign)); break; + case Cvatlib_Network::infoQuery_Freq: emit cbvar_cast(cbvar)->freqQueryRequestReceived(cbvar_cast(cbvar)->fromFSD(callsign)); break; //TODO ask Gary whether we need to reply to UserInfo, Server, Name, Capabilities, or IP queries } } @@ -343,7 +348,7 @@ namespace BlackCore case Cvatlib_Network::infoQuery_ATIS: break; //TODO ask Gary do we handle this here or in onAtisReplyReceived or both? case Cvatlib_Network::infoQuery_Name: break; //TODO ask Gary what are the meanings of data and data2 in this context? case Cvatlib_Network::infoQuery_Capabilities: break; //TODO ask Gary do we handle this here or in onCapabilitiesReplyReceived or both? - case Cvatlib_Network::infoQuery_IP: emit cbvar_cast(cbvar)->ipQueryReplyReceived(data); break; + case Cvatlib_Network::infoQuery_IP: emit cbvar_cast(cbvar)->ipQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(data)); break; } } @@ -354,7 +359,7 @@ namespace BlackCore void NetworkVatlib::onAtisReplyReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::atisLineType type, const char* data, void* cbvar) { - emit cbvar_cast(cbvar)->atisReplyReceived(callsign, data); + emit cbvar_cast(cbvar)->atisReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); } void NetworkVatlib::onTemperatureDataReceived(Cvatlib_Network*, Cvatlib_Network::TempLayer layers[4], INT pressure, void* cbvar) @@ -370,10 +375,10 @@ namespace BlackCore case Cvatlib_Network::error_CallsignTaken: qCritical() << "The requested callsign is already taken"; break; case Cvatlib_Network::error_CallsignInvalid: qCritical() << "The requested callsign is not valid"; break; case Cvatlib_Network::error_Registered: break; //TODO ask Gary to explain meaning - case Cvatlib_Network::error_Syntax: assert(false); qWarning() << "VATSIM shim library: Syntax error: " << data; break; + case Cvatlib_Network::error_Syntax: assert(false); qWarning() << "VATSIM shim library: Syntax error: " << cbvar_cast(cbvar)->fromFSD(data); break; case Cvatlib_Network::error_SourceInvalid: break; //TODO ask Gary to explain meaning case Cvatlib_Network::error_CIDPasswdInvalid: qCritical() << "Wrong user ID or password"; break; - case Cvatlib_Network::error_CallsignNotExists: qDebug() << "Shim lib: " << msg << " (" << data << ")"; break; + case Cvatlib_Network::error_CallsignNotExists: qDebug() << "Shim lib: " << cbvar_cast(cbvar)->fromFSD(msg) << " (" << cbvar_cast(cbvar)->fromFSD(data) << ")"; break; case Cvatlib_Network::error_NoFP: break; //TODO ask Gary under what circumstance this can happen case Cvatlib_Network::error_NoWeather: break; //TODO ask Gary to explain meaning case Cvatlib_Network::error_ProtoVersion: qCritical() << "This server uses an unsupported protocol version"; break; @@ -383,7 +388,7 @@ namespace BlackCore case Cvatlib_Network::error_InvalidControl: break; //TODO ask Gary to explain meaning case Cvatlib_Network::error_InvalidPosition: qCritical() << "You are not authorized to use the requested pilot rating"; break; case Cvatlib_Network::error_SoftwareNotAuthorized: qCritical() << "This client software has not been authorized for use on this network"; break; - default: assert(false); qWarning() << "VATSIM shim library: " << msg << "(error " << type << ")"; break; + default: assert(false); qWarning() << "VATSIM shim library: " << cbvar_cast(cbvar)->fromFSD(msg) << "(error " << type << ")"; break; } } @@ -399,14 +404,14 @@ namespace BlackCore void NetworkVatlib::onPilotInfoRequestReceived(Cvatlib_Network*, const char* callsign, void* cbvar) { - emit cbvar_cast(cbvar)->planeInfoRequestReceived(callsign); + emit cbvar_cast(cbvar)->planeInfoRequestReceived(cbvar_cast(cbvar)->fromFSD(callsign)); } void NetworkVatlib::onPilotInfoReceived(Cvatlib_Network* net, const char* callsign, const char** keysValues, void* cbvar) { - QString acTypeICAO; - QString airlineICAO; - QString livery; + const char* acTypeICAO; + const char* airlineICAO; + const char* livery; while (*keysValues) { QString key (*keysValues); @@ -416,7 +421,8 @@ namespace BlackCore else if (key == net->acinfo_Livery) { livery = *keysValues; } keysValues++; } - emit cbvar_cast(cbvar)->planeInfoReceived(callsign, acTypeICAO, airlineICAO, livery); + emit cbvar_cast(cbvar)->planeInfoReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(acTypeICAO), + cbvar_cast(cbvar)->fromFSD(airlineICAO), cbvar_cast(cbvar)->fromFSD(livery)); } } //namespace BlackCore diff --git a/src/blackcore/network_vatlib.h b/src/blackcore/network_vatlib.h index 4a106e9ad..d55d1069b 100644 --- a/src/blackcore/network_vatlib.h +++ b/src/blackcore/network_vatlib.h @@ -14,6 +14,7 @@ #include "../../vatlib/vatlib.h" #include #include +#include namespace BlackCore { @@ -68,6 +69,9 @@ namespace BlackCore private: void exceptionDispatcher(); + QByteArray toFSD(QString qstr) const; + QString fromFSD(const char* cstr) const; + private: QScopedPointer m_net; @@ -79,6 +83,8 @@ namespace BlackCore quint16 m_serverPort; QString m_username; QString m_password; + + QTextCodec* m_fsdTextCodec; }; } //namespace BlackCore From 009bba1e54690aea1eab423bc8b13d83f56f11db Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Fri, 5 Jul 2013 18:48:58 +0100 Subject: [PATCH 03/15] error-handling tweaks (refs #22) --- src/blackcore/network_vatlib.cpp | 39 ++++++++++++++------------------ 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/src/blackcore/network_vatlib.cpp b/src/blackcore/network_vatlib.cpp index fe242d6a1..058f4dd74 100644 --- a/src/blackcore/network_vatlib.cpp +++ b/src/blackcore/network_vatlib.cpp @@ -6,7 +6,6 @@ #include "network_vatlib.h" #include #include -#include namespace BlackCore { @@ -21,7 +20,6 @@ namespace BlackCore try { Q_ASSERT_X(m_fsdTextCodec, "NetworkVatlib", "Missing default wire text encoding"); - assert(m_fsdTextCodec); //TODO reinit m_fsdTextCodec from WireTextEncoding config setting if present m_net->InstallOnConnectionStatusChangedEvent(onConnectionStatusChanged, this); @@ -106,29 +104,22 @@ namespace BlackCore { throw; } - //catch (InvalidObjectException& e) //TODO ask Gary to confirm that trying to use an invalid Cvatlib_Network is always the result of a programmer error - //catch (ObjectNotSetupException& e) //TODO ask Gary what is "the setup function" mentioned in the ObjectNotSetupException documentation? catch (NetworkNotConnectedException& e) { + // this could be caused by a race condition during normal operation, so not an error qDebug() << "NetworkNotConnectedException: " << e.what(); } catch (VatlibException& e) { - Q_ASSERT_X(false, "NetworkVatlib", e.what()); - assert(false); - qDebug() << "VatlibException: " << e.what(); + qFatal("VatlibException: %s", e.what()); } catch (std::exception& e) { - Q_ASSERT_X(false, "NetworkVatlib", e.what()); - assert(false); - qDebug() << "NetworkVatlib: std::exception: " << e.what(); + qFatal("NetworkVatlib: std::exception: %s", e.what()); } catch (...) { - Q_ASSERT_X(false, "NetworkVatlib", "Unknown exception"); - assert(false); - qDebug() << "NetworkVatlib: unknown exception"; + qFatal("NetworkVatlib: unknown exception"); } } @@ -374,21 +365,25 @@ namespace BlackCore case Cvatlib_Network::error_Ok: return; case Cvatlib_Network::error_CallsignTaken: qCritical() << "The requested callsign is already taken"; break; case Cvatlib_Network::error_CallsignInvalid: qCritical() << "The requested callsign is not valid"; break; - case Cvatlib_Network::error_Registered: break; //TODO ask Gary to explain meaning - case Cvatlib_Network::error_Syntax: assert(false); qWarning() << "VATSIM shim library: Syntax error: " << cbvar_cast(cbvar)->fromFSD(data); break; - case Cvatlib_Network::error_SourceInvalid: break; //TODO ask Gary to explain meaning case Cvatlib_Network::error_CIDPasswdInvalid: qCritical() << "Wrong user ID or password"; break; - case Cvatlib_Network::error_CallsignNotExists: qDebug() << "Shim lib: " << cbvar_cast(cbvar)->fromFSD(msg) << " (" << cbvar_cast(cbvar)->fromFSD(data) << ")"; break; - case Cvatlib_Network::error_NoFP: break; //TODO ask Gary under what circumstance this can happen - case Cvatlib_Network::error_NoWeather: break; //TODO ask Gary to explain meaning case Cvatlib_Network::error_ProtoVersion: qCritical() << "This server uses an unsupported protocol version"; break; - case Cvatlib_Network::error_LevelTooHigh: qCritical() << "You are not authorized to use the requested pilot rating"; break; //TODO ask Gary to confirm meaning + case Cvatlib_Network::error_LevelTooHigh: qCritical() << "You are not authorized to use the requested pilot rating"; break; case Cvatlib_Network::error_ServerFull: qCritical() << "The server is full"; break; case Cvatlib_Network::error_CIDSuspended: qCritical() << "Your user account is suspended"; break; - case Cvatlib_Network::error_InvalidControl: break; //TODO ask Gary to explain meaning case Cvatlib_Network::error_InvalidPosition: qCritical() << "You are not authorized to use the requested pilot rating"; break; case Cvatlib_Network::error_SoftwareNotAuthorized: qCritical() << "This client software has not been authorized for use on this network"; break; - default: assert(false); qWarning() << "VATSIM shim library: " << cbvar_cast(cbvar)->fromFSD(msg) << "(error " << type << ")"; break; + + case Cvatlib_Network::error_Syntax: qWarning() << "Malformed packet: Syntax error: %s" << cbvar_cast(cbvar)->fromFSD(data); break; + case Cvatlib_Network::error_SourceInvalid: qDebug() << "Server: source invalid (" << cbvar_cast(cbvar)->fromFSD(data); break; + case Cvatlib_Network::error_CallsignNotExists: qDebug() << "Shim lib: " << cbvar_cast(cbvar)->fromFSD(msg) << " (" << cbvar_cast(cbvar)->fromFSD(data) << ")"; break; + case Cvatlib_Network::error_NoFP: qDebug() << "Server: no flight plan"; break; + case Cvatlib_Network::error_NoWeather: qDebug() << "Server: requested weather profile does not exist"; break; + + // we have no idea what these mean + case Cvatlib_Network::error_Registered: + case Cvatlib_Network::error_InvalidControl: qWarning() << "Server: " << cbvar_cast(cbvar)->fromFSD(msg); break; + + default: qFatal("VATSIM shim library: %s (error %d)", cbvar_cast(cbvar)->fromFSD(msg), type); break; } } From 82f5661aa684ed34bc9de606de2b47e49d489748 Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Fri, 5 Jul 2013 21:11:44 +0100 Subject: [PATCH 04/15] info queries and replies, and misc tidy-up (refs #22) --- src/blackcore/network.h | 18 +++++- src/blackcore/network_vatlib.cpp | 94 ++++++++++++++++++++++++++++---- src/blackcore/network_vatlib.h | 7 +++ 3 files changed, 106 insertions(+), 13 deletions(-) diff --git a/src/blackcore/network.h b/src/blackcore/network.h index 6e5c65954..7be2d1234 100644 --- a/src/blackcore/network.h +++ b/src/blackcore/network.h @@ -26,6 +26,9 @@ namespace BlackCore { Q_OBJECT; + public: + virtual ~INetwork() {} + public slots: virtual void setServerDetails(const QString& hostname, quint16 port) = 0; virtual void setUserCredentials(const QString& username, const QString& password) = 0; @@ -33,8 +36,13 @@ namespace BlackCore virtual void terminateConnection() = 0; virtual void sendPrivateTextMessage(const QString& callsign, const QString& msg) = 0; virtual void sendRadioTextMessage(const QVector& freqs, const QString& msg) = 0; - //TODO virtual void sendInfoQuery(...) = 0; - //TODO virtual void replyToInfoQuery(...) = 0; + virtual void sendIpQuery() = 0; + virtual void sendFreqQuery(const QString& callsign) = 0; + virtual void sendServerQuery(const QString& callsign) = 0; + virtual void sendAtcQuery(const QString& callsign) = 0; + virtual void sendNameQuery(const QString& callsign) = 0; + virtual void replyToFreqQuery(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq) = 0; + virtual void replyToNameQuery(const QString& callsign, const QString& realname) = 0; virtual void requestPlaneInfo(const QString& callsign) = 0; //TODO virtual void setPlanePosition(...) = 0; //TODO virtual void sendFlightPlan(...) = 0; @@ -58,8 +66,12 @@ namespace BlackCore //TODO void nameQueryReplyReceived(const QString& callsign, const QString& name); //TODO void capabilitiesQueryReplyReceived(...); void ipQueryReplyReceived(const QString& ip); - void fpQueryRequestReceived(const QString& callsign); + void freqQueryReplyReceived(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq); + void serverQueryReplyReceived(const QString& callsign, const QString& hostname); + void atcQueryReplyReceived(const QString& callsign, bool isATC); + void nameQueryReplyReceived(const QString& callsign, const QString& realname); void freqQueryRequestReceived(const QString& callsign); + void nameQueryRequestReceived(const QString& callsign); //TODO void interimPilotPositionUpdate(...); void kicked(const QString& msg); void metarReceived(const QString& data); diff --git a/src/blackcore/network_vatlib.cpp b/src/blackcore/network_vatlib.cpp index 058f4dd74..5684a87c2 100644 --- a/src/blackcore/network_vatlib.cpp +++ b/src/blackcore/network_vatlib.cpp @@ -6,6 +6,17 @@ #include "network_vatlib.h" #include #include +#include + +static_assert(! std::is_abstract::value, "Must implement all pure virtuals"); + +//TODO just placeholders to allow this to compile +#define CLIENT_NAME_VERSION "BlackBox 0.1" +#define CLIENT_VERSION_MAJOR 0 +#define CLIENT_VERSION_MINOR 1 +#define CLIENT_SIMULATOR_NAME "None" +#define CLIENT_PUBLIC_ID 0 +#define CLIENT_PRIVATE_KEY "" namespace BlackCore { @@ -152,7 +163,7 @@ namespace BlackCore { try { - m_net->LogoffAndDisconnect(c_logoffTimeoutSeconds); //TODO ask Gary will this block? + m_net->LogoffAndDisconnect(c_logoffTimeoutSeconds); } catch (...) { exceptionDispatcher(); } } @@ -180,6 +191,69 @@ namespace BlackCore catch (...) { exceptionDispatcher(); } } + void NetworkVatlib::sendIpQuery() + { + try + { + m_net->SendInfoQuery(Cvatlib_Network::infoQuery_IP, ""/*TODO ask Gary*/); + } + catch (...) { exceptionDispatcher(); } + } + + void NetworkVatlib::sendFreqQuery(const QString& callsign) + { + try + { + m_net->SendInfoQuery(Cvatlib_Network::infoQuery_Freq, toFSD(callsign)); + } + catch (...) { exceptionDispatcher(); } + } + + void NetworkVatlib::sendServerQuery(const QString& callsign) + { + try + { + m_net->SendInfoQuery(Cvatlib_Network::infoQuery_Server, toFSD(callsign)); + } + catch (...) { exceptionDispatcher(); } + } + + void NetworkVatlib::sendAtcQuery(const QString& callsign) + { + try + { + m_net->SendInfoQuery(Cvatlib_Network::infoQuery_ATC, toFSD(callsign)); + } + catch (...) { exceptionDispatcher(); } + } + + void NetworkVatlib::sendNameQuery(const QString& callsign) + { + try + { + m_net->SendInfoQuery(Cvatlib_Network::infoQuery_Name, toFSD(callsign)); + } + catch (...) { exceptionDispatcher(); } + } + + void NetworkVatlib::replyToFreqQuery(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq) + { + try + { + m_net->ReplyToInfoQuery(Cvatlib_Network::infoQuery_Freq, toFSD(callsign), toFSD(""/*TODO*/)); + } + catch (...) { exceptionDispatcher(); } + } + + void NetworkVatlib::replyToNameQuery(const QString& callsign, const QString& realname) + { + try + { + m_net->ReplyToInfoQuery(Cvatlib_Network::infoQuery_Name, toFSD(callsign), toFSD(realname)); + } + catch (...) { exceptionDispatcher(); } + } + void NetworkVatlib::requestPlaneInfo(const QString& callsign) { try @@ -314,7 +388,7 @@ namespace BlackCore void NetworkVatlib::onPong(Cvatlib_Network*, const char* callsign, INT elapsedTime, void* cbvar) { - emit cbvar_cast(cbvar)->pong(cbvar_cast(cbvar)->fromFSD(callsign), CTime(elapsedTime, CTimeUnit::ms())); //TODO ask Gary to confirm time unit + emit cbvar_cast(cbvar)->pong(cbvar_cast(cbvar)->fromFSD(callsign), CTime(elapsedTime, CTimeUnit::s())); } void NetworkVatlib::onMetarReceived(Cvatlib_Network*, const char* data, void* cbvar) @@ -322,13 +396,12 @@ namespace BlackCore emit cbvar_cast(cbvar)->metarReceived(cbvar_cast(cbvar)->fromFSD(data)); } - void NetworkVatlib::onInfoQueryRequestReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::infoQuery type, const char* data, void* cbvar) + void NetworkVatlib::onInfoQueryRequestReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::infoQuery type, const char*, void* cbvar) { switch (type) { - case Cvatlib_Network::infoQuery_FP: emit cbvar_cast(cbvar)->fpQueryRequestReceived(cbvar_cast(cbvar)->fromFSD(callsign)); break; case Cvatlib_Network::infoQuery_Freq: emit cbvar_cast(cbvar)->freqQueryRequestReceived(cbvar_cast(cbvar)->fromFSD(callsign)); break; - //TODO ask Gary whether we need to reply to UserInfo, Server, Name, Capabilities, or IP queries + case Cvatlib_Network::infoQuery_Name: emit cbvar_cast(cbvar)->nameQueryRequestReceived(cbvar_cast(cbvar)->fromFSD(callsign)); break; } } @@ -336,10 +409,11 @@ namespace BlackCore { switch (type) { - case Cvatlib_Network::infoQuery_ATIS: break; //TODO ask Gary do we handle this here or in onAtisReplyReceived or both? - case Cvatlib_Network::infoQuery_Name: break; //TODO ask Gary what are the meanings of data and data2 in this context? - case Cvatlib_Network::infoQuery_Capabilities: break; //TODO ask Gary do we handle this here or in onCapabilitiesReplyReceived or both? - case Cvatlib_Network::infoQuery_IP: emit cbvar_cast(cbvar)->ipQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(data)); break; + case Cvatlib_Network::infoQuery_Freq: emit cbvar_cast(cbvar)->freqQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), CFrequency(0/*TODO ask Gary*/, CFrequencyUnit::kHz())); break; + case Cvatlib_Network::infoQuery_Server: emit cbvar_cast(cbvar)->serverQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break; + case Cvatlib_Network::infoQuery_ATC: emit cbvar_cast(cbvar)->atcQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), *data == 'Y'); break; //TODO ask Gary + case Cvatlib_Network::infoQuery_Name: emit cbvar_cast(cbvar)->nameQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break; + case Cvatlib_Network::infoQuery_IP: emit cbvar_cast(cbvar)->ipQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(data)); break; //TODO ask Gary can this refer to another pilot? } } @@ -348,7 +422,7 @@ namespace BlackCore //TODO } - void NetworkVatlib::onAtisReplyReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::atisLineType type, const char* data, void* cbvar) + void NetworkVatlib::onAtisReplyReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::atisLineType, const char* data, void* cbvar) { emit cbvar_cast(cbvar)->atisReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); } diff --git a/src/blackcore/network_vatlib.h b/src/blackcore/network_vatlib.h index d55d1069b..1628b1873 100644 --- a/src/blackcore/network_vatlib.h +++ b/src/blackcore/network_vatlib.h @@ -37,6 +37,13 @@ namespace BlackCore virtual void terminateConnection(); virtual void sendPrivateTextMessage(const QString& callsign, const QString& msg); virtual void sendRadioTextMessage(const QVector& freqs, const QString& msg); + virtual void sendIpQuery(); + virtual void sendFreqQuery(const QString& callsign); + virtual void sendServerQuery(const QString& callsign); + virtual void sendAtcQuery(const QString& callsign); + virtual void sendNameQuery(const QString& callsign); + virtual void replyToFreqQuery(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq); + virtual void replyToNameQuery(const QString& callsign, const QString& realname); virtual void requestPlaneInfo(const QString& callsign); virtual void sendPlaneInfo(const QString& callsign, const QString& acTypeICAO, const QString& airlineICAO, const QString& livery); virtual void ping(const QString& callsign); From e64e7b75c2921326ac8f4be468ebdb2f53fe370d Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Sat, 6 Jul 2013 00:30:45 +0100 Subject: [PATCH 05/15] a little bit more on info queries and replies (refs #22) --- src/blackcore/network_vatlib.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/blackcore/network_vatlib.cpp b/src/blackcore/network_vatlib.cpp index 5684a87c2..fd2139c50 100644 --- a/src/blackcore/network_vatlib.cpp +++ b/src/blackcore/network_vatlib.cpp @@ -195,7 +195,7 @@ namespace BlackCore { try { - m_net->SendInfoQuery(Cvatlib_Network::infoQuery_IP, ""/*TODO ask Gary*/); + m_net->SendInfoQuery(Cvatlib_Network::infoQuery_IP, "SERVER"); } catch (...) { exceptionDispatcher(); } } @@ -240,7 +240,10 @@ namespace BlackCore { try { - m_net->ReplyToInfoQuery(Cvatlib_Network::infoQuery_Freq, toFSD(callsign), toFSD(""/*TODO*/)); + CFrequency freqCopy = freq; + freqCopy.switchUnit(CFrequencyUnit::MHz()); + + m_net->ReplyToInfoQuery(Cvatlib_Network::infoQuery_Freq, toFSD(callsign), toFSD(freqCopy.unitValueToQStringRounded(6))); } catch (...) { exceptionDispatcher(); } } @@ -409,11 +412,11 @@ namespace BlackCore { switch (type) { - case Cvatlib_Network::infoQuery_Freq: emit cbvar_cast(cbvar)->freqQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), CFrequency(0/*TODO ask Gary*/, CFrequencyUnit::kHz())); break; + case Cvatlib_Network::infoQuery_Freq: emit cbvar_cast(cbvar)->freqQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), CFrequency(cbvar_cast(cbvar)->fromFSD(data).toFloat(), CFrequencyUnit::MHz())); break; case Cvatlib_Network::infoQuery_Server: emit cbvar_cast(cbvar)->serverQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break; - case Cvatlib_Network::infoQuery_ATC: emit cbvar_cast(cbvar)->atcQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), *data == 'Y'); break; //TODO ask Gary + case Cvatlib_Network::infoQuery_ATC: emit cbvar_cast(cbvar)->atcQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(data2), *data == 'Y'); break; case Cvatlib_Network::infoQuery_Name: emit cbvar_cast(cbvar)->nameQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break; - case Cvatlib_Network::infoQuery_IP: emit cbvar_cast(cbvar)->ipQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(data)); break; //TODO ask Gary can this refer to another pilot? + case Cvatlib_Network::infoQuery_IP: emit cbvar_cast(cbvar)->ipQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(data)); break; } } From b8f26dce4a36acaf6f9220a89ef02f90197ce129 Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Wed, 31 Jul 2013 21:51:18 +0100 Subject: [PATCH 06/15] refs #22 * Implemented a few more signals * Support for storing the INetwork object in the IContext * Improved exception handling * Fixed some mistakes --- src/blackcore/network.h | 21 +++-- src/blackcore/network_vatlib.cpp | 130 +++++++++++++++++++++---------- src/blackcore/network_vatlib.h | 8 +- 3 files changed, 111 insertions(+), 48 deletions(-) diff --git a/src/blackcore/network.h b/src/blackcore/network.h index 7be2d1234..90a466234 100644 --- a/src/blackcore/network.h +++ b/src/blackcore/network.h @@ -24,14 +24,25 @@ namespace BlackCore class INetwork : public QObject { - Q_OBJECT; + Q_OBJECT public: + BLACK_INTERFACE(BlackCore::INetwork) + virtual ~INetwork() {} + enum + { + AcceptsAtisResponses = 1 << 0, + SupportsInterimPosUpdates = 1 << 1, + SupportsModelDescriptions = 1 << 2, + }; + public slots: virtual void setServerDetails(const QString& hostname, quint16 port) = 0; virtual void setUserCredentials(const QString& username, const QString& password) = 0; + virtual void setCallsign(const QString& callsign) = 0; + virtual void setRealName(const QString& name) = 0; virtual void initiateConnection() = 0; virtual void terminateConnection() = 0; virtual void sendPrivateTextMessage(const QString& callsign, const QString& msg) = 0; @@ -40,7 +51,9 @@ namespace BlackCore virtual void sendFreqQuery(const QString& callsign) = 0; virtual void sendServerQuery(const QString& callsign) = 0; virtual void sendAtcQuery(const QString& callsign) = 0; + virtual void sendAtisQuery(const QString& callsign) = 0; virtual void sendNameQuery(const QString& callsign) = 0; + virtual void sendCapabilitiesQuery(const QString& callsign) = 0; virtual void replyToFreqQuery(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq) = 0; virtual void replyToNameQuery(const QString& callsign, const QString& realname) = 0; virtual void requestPlaneInfo(const QString& callsign) = 0; @@ -55,21 +68,19 @@ namespace BlackCore void atcPositionUpdate(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq, const BlackMisc::Geo::CCoordinateGeodetic& pos, const BlackMisc::PhysicalQuantities::CLength& range); void atcDisconnected(const QString& callsign); - void atisReplyReceived(const QString& callsign, const QString& data); //TODO void cloudDataReceived(...); void connectionStatusIdle(); void connectionStatusConnecting(); void connectionStatusConnected(); void connectionStatusDisconnected(); void connectionStatusError(); - //TODO void atisQueryReplyReceived(...); - //TODO void nameQueryReplyReceived(const QString& callsign, const QString& name); - //TODO void capabilitiesQueryReplyReceived(...); void ipQueryReplyReceived(const QString& ip); void freqQueryReplyReceived(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq); void serverQueryReplyReceived(const QString& callsign, const QString& hostname); void atcQueryReplyReceived(const QString& callsign, bool isATC); + void atisQueryReplyReceived(const QString& callsign, const QString& data); void nameQueryReplyReceived(const QString& callsign, const QString& realname); + void capabilitiesQueryReplyReceived(const QString& callsign, quint32 flags); void freqQueryRequestReceived(const QString& callsign); void nameQueryRequestReceived(const QString& callsign); //TODO void interimPilotPositionUpdate(...); diff --git a/src/blackcore/network_vatlib.cpp b/src/blackcore/network_vatlib.cpp index fd2139c50..dab444836 100644 --- a/src/blackcore/network_vatlib.cpp +++ b/src/blackcore/network_vatlib.cpp @@ -24,6 +24,8 @@ namespace BlackCore using namespace BlackMisc::PhysicalQuantities; using namespace BlackMisc::Geo; + void exceptionDispatcher(const char* caller); + NetworkVatlib::NetworkVatlib() : m_net(Create_Cvatlib_Network()), m_fsdTextCodec(QTextCodec::codecForName("latin1")) @@ -33,6 +35,17 @@ namespace BlackCore Q_ASSERT_X(m_fsdTextCodec, "NetworkVatlib", "Missing default wire text encoding"); //TODO reinit m_fsdTextCodec from WireTextEncoding config setting if present + QString capabilities; + capabilities += m_net->capability_AtcInfo; + capabilities += "=1:"; + capabilities += m_net->capability_InterimPos; + capabilities += "=1:"; + capabilities += m_net->capability_ModelDesc; + capabilities += "=1"; + + m_net->CreateNetworkSession(CLIENT_NAME_VERSION, CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, + CLIENT_SIMULATOR_NAME, CLIENT_PUBLIC_ID, CLIENT_PRIVATE_KEY, toFSD(capabilities)); + m_net->InstallOnConnectionStatusChangedEvent(onConnectionStatusChanged, this); m_net->InstallOnTextMessageReceivedEvent(onTextMessageReceived, this); m_net->InstallOnRadioMessageReceivedEvent(onRadioMessageReceived, this); @@ -55,20 +68,9 @@ namespace BlackCore m_net->InstallOnPilotInfoRequestReceivedEvent(onPilotInfoRequestReceived, this); m_net->InstallOnPilotInfoReceivedEvent(onPilotInfoReceived, this); - QString capabilities; - capabilities += m_net->capability_AtcInfo; - capabilities += "=1:"; - capabilities += m_net->capability_InterimPos; - capabilities += "=1:"; - capabilities += m_net->capability_ModelDesc; - capabilities += "=1"; - - m_net->CreateNetworkSession(CLIENT_NAME_VERSION, CLIENT_VERSION_MAJOR, CLIENT_VERSION_MINOR, - CLIENT_SIMULATOR_NAME, CLIENT_PUBLIC_ID, CLIENT_PRIVATE_KEY, toFSD(capabilities)); - m_timer.start(c_updateIntervalMillisecs, this); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } NetworkVatlib::~NetworkVatlib() @@ -84,7 +86,7 @@ namespace BlackCore m_net->DestroyNetworkSession(); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } void NetworkVatlib::timerEvent(QTimerEvent*) @@ -96,7 +98,7 @@ namespace BlackCore m_net->DoProcessing(); } } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } QByteArray NetworkVatlib::toFSD(QString qstr) const @@ -109,28 +111,28 @@ namespace BlackCore return m_fsdTextCodec->toUnicode(cstr); } - void NetworkVatlib::exceptionDispatcher() + void exceptionDispatcher(const char* caller) { try { throw; } - catch (NetworkNotConnectedException& e) + catch (const NetworkNotConnectedException& e) { // this could be caused by a race condition during normal operation, so not an error - qDebug() << "NetworkNotConnectedException: " << e.what(); + qDebug() << "NetworkNotConnectedException caught in " << caller << "\n" << e.what(); } - catch (VatlibException& e) + catch (const VatlibException& e) { - qFatal("VatlibException: %s", e.what()); + qFatal("VatlibException caught in %s\n%s", caller, e.what()); } - catch (std::exception& e) + catch (const std::exception& e) { - qFatal("NetworkVatlib: std::exception: %s", e.what()); + qFatal("std::exception caught in %s\n%s", caller, e.what()); } catch (...) { - qFatal("NetworkVatlib: unknown exception"); + qFatal("Unknown exception caught in %s", caller); } } @@ -150,13 +152,31 @@ namespace BlackCore m_password = password; } + void NetworkVatlib::setCallsign(const QString& callsign) + { + m_callsign = callsign; + } + + void NetworkVatlib::setRealName(const QString& name) + { + m_realname = name; + } + void NetworkVatlib::initiateConnection() { try { + Cvatlib_Network::PilotConnectionInfo info; + info.callsign = m_callsign.toStdString().c_str(); + info.name = m_realname.toStdString().c_str(); + info.rating = Cvatlib_Network::pilotRating_Unknown; //TODO + info.sim = Cvatlib_Network::simType_XPlane; //TODO + + m_net->SetPilotLoginInfo(m_serverHost.toStdString().c_str(), m_serverPort, + m_username.toStdString().c_str(), m_password.toStdString().c_str(), info); m_net->ConnectAndLogon(); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } void NetworkVatlib::terminateConnection() @@ -165,7 +185,7 @@ namespace BlackCore { m_net->LogoffAndDisconnect(c_logoffTimeoutSeconds); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } void NetworkVatlib::sendPrivateTextMessage(const QString& callsign, const QString& msg) @@ -174,7 +194,7 @@ namespace BlackCore { m_net->SendPrivateTextMessage(toFSD(callsign), toFSD(msg)); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } void NetworkVatlib::sendRadioTextMessage(const QVector& freqs, const QString& msg) @@ -188,7 +208,7 @@ namespace BlackCore } m_net->SendRadioTextMessage(freqsVec.size(), freqsVec.data(), toFSD(msg)); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } void NetworkVatlib::sendIpQuery() @@ -197,7 +217,7 @@ namespace BlackCore { m_net->SendInfoQuery(Cvatlib_Network::infoQuery_IP, "SERVER"); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } void NetworkVatlib::sendFreqQuery(const QString& callsign) @@ -206,7 +226,7 @@ namespace BlackCore { m_net->SendInfoQuery(Cvatlib_Network::infoQuery_Freq, toFSD(callsign)); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } void NetworkVatlib::sendServerQuery(const QString& callsign) @@ -215,7 +235,7 @@ namespace BlackCore { m_net->SendInfoQuery(Cvatlib_Network::infoQuery_Server, toFSD(callsign)); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } void NetworkVatlib::sendAtcQuery(const QString& callsign) @@ -224,7 +244,16 @@ namespace BlackCore { m_net->SendInfoQuery(Cvatlib_Network::infoQuery_ATC, toFSD(callsign)); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } + } + + void NetworkVatlib::sendAtisQuery(const QString& callsign) + { + try + { + m_net->SendInfoQuery(Cvatlib_Network::infoQuery_ATIS, toFSD(callsign)); + } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } void NetworkVatlib::sendNameQuery(const QString& callsign) @@ -233,7 +262,16 @@ namespace BlackCore { m_net->SendInfoQuery(Cvatlib_Network::infoQuery_Name, toFSD(callsign)); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } + } + + void NetworkVatlib::sendCapabilitiesQuery(const QString& callsign) + { + try + { + m_net->SendInfoQuery(Cvatlib_Network::infoQuery_Capabilities, toFSD(callsign)); + } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } void NetworkVatlib::replyToFreqQuery(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq) @@ -245,7 +283,7 @@ namespace BlackCore m_net->ReplyToInfoQuery(Cvatlib_Network::infoQuery_Freq, toFSD(callsign), toFSD(freqCopy.unitValueToQStringRounded(6))); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } void NetworkVatlib::replyToNameQuery(const QString& callsign, const QString& realname) @@ -254,7 +292,7 @@ namespace BlackCore { m_net->ReplyToInfoQuery(Cvatlib_Network::infoQuery_Name, toFSD(callsign), toFSD(realname)); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } void NetworkVatlib::requestPlaneInfo(const QString& callsign) @@ -263,7 +301,7 @@ namespace BlackCore { m_net->RequestPlaneInfo(toFSD(callsign)); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } void NetworkVatlib::sendPlaneInfo(const QString& callsign, const QString& acTypeICAO, const QString& airlineICAO, const QString& livery) @@ -292,7 +330,7 @@ namespace BlackCore keysValues.push_back(0); m_net->SendPlaneInfo(toFSD(callsign), keysValues.data()); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } void NetworkVatlib::ping(const QString& callsign) @@ -301,7 +339,7 @@ namespace BlackCore { m_net->PingUser(toFSD(callsign)); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } void NetworkVatlib::requestMetar(const QString& airportICAO) @@ -310,7 +348,7 @@ namespace BlackCore { m_net->RequestMetar(toFSD(airportICAO)); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } void NetworkVatlib::requestWeatherData(const QString& airportICAO) @@ -319,7 +357,7 @@ namespace BlackCore { m_net->RequestWeatherData(toFSD(airportICAO)); } - catch (...) { exceptionDispatcher(); } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } } /********************************** * * * * * * * * * * * * * * * * * * * ************************************/ @@ -420,14 +458,24 @@ namespace BlackCore } } - void NetworkVatlib::onCapabilitiesReplyReceived(Cvatlib_Network*, const char* callsign, const char** keysValues, void* cbvar) + void NetworkVatlib::onCapabilitiesReplyReceived(Cvatlib_Network* net, const char* callsign, const char** keysValues, void* cbvar) { - //TODO + quint32 flags = 0; + while (*keysValues) + { + const char* key = keysValues[0]; + const char* value = keysValues[1]; + if (key == net->capability_AtcInfo) { flags |= AcceptsAtisResponses; } + else if (key == net->capability_InterimPos) { flags |= SupportsInterimPosUpdates; } + else if (key == net->capability_ModelDesc) { flags |= SupportsModelDescriptions; } + keysValues += 2; + } + emit cbvar_cast(cbvar)->capabilitiesQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), flags); } void NetworkVatlib::onAtisReplyReceived(Cvatlib_Network*, const char* callsign, Cvatlib_Network::atisLineType, const char* data, void* cbvar) { - emit cbvar_cast(cbvar)->atisReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); + emit cbvar_cast(cbvar)->atisQueryReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); } void NetworkVatlib::onTemperatureDataReceived(Cvatlib_Network*, Cvatlib_Network::TempLayer layers[4], INT pressure, void* cbvar) diff --git a/src/blackcore/network_vatlib.h b/src/blackcore/network_vatlib.h index 1628b1873..563df06ce 100644 --- a/src/blackcore/network_vatlib.h +++ b/src/blackcore/network_vatlib.h @@ -33,6 +33,8 @@ namespace BlackCore public: //INetwork slots overrides virtual void setServerDetails(const QString& hostname, quint16 port); virtual void setUserCredentials(const QString& username, const QString& password); + virtual void setCallsign(const QString& callsign); + virtual void setRealName(const QString& name); virtual void initiateConnection(); virtual void terminateConnection(); virtual void sendPrivateTextMessage(const QString& callsign, const QString& msg); @@ -41,7 +43,9 @@ namespace BlackCore virtual void sendFreqQuery(const QString& callsign); virtual void sendServerQuery(const QString& callsign); virtual void sendAtcQuery(const QString& callsign); + virtual void sendAtisQuery(const QString& callsign); virtual void sendNameQuery(const QString& callsign); + virtual void sendCapabilitiesQuery(const QString& callsign); virtual void replyToFreqQuery(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq); virtual void replyToNameQuery(const QString& callsign, const QString& realname); virtual void requestPlaneInfo(const QString& callsign); @@ -74,8 +78,6 @@ namespace BlackCore static void onPilotInfoReceived(Cvatlib_Network*, const char* callsign, const char** keysValues, void* cbvar); private: - void exceptionDispatcher(); - QByteArray toFSD(QString qstr) const; QString fromFSD(const char* cstr) const; @@ -90,6 +92,8 @@ namespace BlackCore quint16 m_serverPort; QString m_username; QString m_password; + QString m_callsign; + QString m_realname; QTextCodec* m_fsdTextCodec; }; From 930be03fa6ad8cb63826ab47d3bfd4eab34f8b91 Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Wed, 31 Jul 2013 22:02:41 +0100 Subject: [PATCH 07/15] sample console-based client to demonstrate INetwork interface (refs #22) --- client.pro | 1 + samples/CMakeLists.txt | 1 + samples/cli_client/CMakeLists.txt | 7 + samples/cli_client/client.cpp | 422 +++++++++++++++++++++++ samples/cli_client/client.h | 111 ++++++ samples/cli_client/main.cpp | 27 ++ samples/cli_client/reader.cpp | 21 ++ samples/cli_client/reader.h | 26 ++ samples/cli_client/sample_cli_client.pro | 27 ++ 9 files changed, 643 insertions(+) create mode 100644 samples/cli_client/CMakeLists.txt create mode 100644 samples/cli_client/client.cpp create mode 100644 samples/cli_client/client.h create mode 100644 samples/cli_client/main.cpp create mode 100644 samples/cli_client/reader.cpp create mode 100644 samples/cli_client/reader.h create mode 100644 samples/cli_client/sample_cli_client.pro diff --git a/client.pro b/client.pro index e08006914..9e99ccbf5 100644 --- a/client.pro +++ b/client.pro @@ -43,6 +43,7 @@ equals(WITH_DRIVER_XPLANE, ON) { } equals(WITH_SAMPLES, ON) { + SUBDIRS += samples/cli_client/sample_cli_client.pro SUBDIRS += samples/com_client/sample_com_client.pro SUBDIRS += samples/com_server/sample_com_server.pro SUBDIRS += samples/config/sample_config.pro diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 44a4acf0e..aea2cf9fb 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -1,4 +1,5 @@ ADD_SUBDIRECTORY(logging) +ADD_SUBDIRECTORY(cli_client) ADD_SUBDIRECTORY(com_server) ADD_SUBDIRECTORY(com_client) ADD_SUBDIRECTORY(geodetic2ecef) diff --git a/samples/cli_client/CMakeLists.txt b/samples/cli_client/CMakeLists.txt new file mode 100644 index 000000000..5b9dbd0bf --- /dev/null +++ b/samples/cli_client/CMakeLists.txt @@ -0,0 +1,7 @@ +FILE(GLOB SRC *.cpp) +SET(HEADERS *.h) + +ADD_EXECUTABLE(sample_cli_client ${SRC}) + +TARGET_LINK_LIBRARIES(sample_cli_client blackmisc ${QT_LIBRARIES}) +SET_TARGET_PROPERTIES(sample_cli_client PROPERTIES PROJECT_LABEL "Samples - CLI Client") \ No newline at end of file diff --git a/samples/cli_client/client.cpp b/samples/cli_client/client.cpp new file mode 100644 index 000000000..062608ec0 --- /dev/null +++ b/samples/cli_client/client.cpp @@ -0,0 +1,422 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "client.h" +#include "blackmisc/context.h" +#include +#include + +Client::Client() + : m_net(BlackMisc::IContext::getInstance().singleton()) +{ + using namespace BlackCore; + connect(m_net, &INetwork::atcPositionUpdate, this, &Client::atcPositionUpdate); + connect(m_net, &INetwork::atcDisconnected, this, &Client::atcDisconnected); + connect(m_net, &INetwork::connectionStatusIdle, this, &Client::connectionStatusIdle); + connect(m_net, &INetwork::connectionStatusConnecting, this, &Client::connectionStatusConnecting); + connect(m_net, &INetwork::connectionStatusConnected, this, &Client::connectionStatusConnected); + connect(m_net, &INetwork::connectionStatusDisconnected, this, &Client::connectionStatusDisconnected); + connect(m_net, &INetwork::connectionStatusError, this, &Client::connectionStatusError); + connect(m_net, &INetwork::ipQueryReplyReceived, this, &Client::ipQueryReplyReceived); + connect(m_net, &INetwork::freqQueryReplyReceived, this, &Client::freqQueryReplyReceived); + connect(m_net, &INetwork::serverQueryReplyReceived, this, &Client::serverQueryReplyReceived); + connect(m_net, &INetwork::atcQueryReplyReceived, this, &Client::atcQueryReplyReceived); + connect(m_net, &INetwork::atisQueryReplyReceived, this, &Client::atisQueryReplyReceived); + connect(m_net, &INetwork::nameQueryReplyReceived, this, &Client::nameQueryReplyReceived); + connect(m_net, &INetwork::capabilitiesQueryReplyReceived, this, &Client::capabilitiesQueryReplyReceived); + connect(m_net, &INetwork::freqQueryRequestReceived, this, &Client::freqQueryRequestReceived); + connect(m_net, &INetwork::nameQueryRequestReceived, this, &Client::nameQueryRequestReceived); + connect(m_net, &INetwork::kicked, this, &Client::kicked); + connect(m_net, &INetwork::metarReceived, this, &Client::metarReceived); + connect(m_net, &INetwork::pilotDisconnected, this, &Client::pilotDisconnected); + connect(m_net, &INetwork::planeInfoReceived, this, &Client::planeInfoReceived); + connect(m_net, &INetwork::planeInfoRequestReceived, this, &Client::planeInfoRequestReceived); + connect(m_net, &INetwork::pong, this, &Client::pong); + connect(m_net, &INetwork::radioTextMessageReceived, this, &Client::radioTextMessageReceived); + connect(m_net, &INetwork::privateTextMessageReceived, this, &Client::privateTextMessageReceived); + + connect(this, &Client::setServerDetails, m_net, &INetwork::setServerDetails); + connect(this, &Client::setUserCredentials, m_net, &INetwork::setUserCredentials); + connect(this, &Client::setCallsign, m_net, &INetwork::setCallsign); + connect(this, &Client::setRealName, m_net, &INetwork::setRealName); + connect(this, &Client::initiateConnection, m_net, &INetwork::initiateConnection); + connect(this, &Client::terminateConnection, m_net, &INetwork::terminateConnection); + connect(this, &Client::sendPrivateTextMessage, m_net, &INetwork::sendPrivateTextMessage); + connect(this, &Client::sendRadioTextMessage, m_net, &INetwork::sendRadioTextMessage); + connect(this, &Client::sendIpQuery, m_net, &INetwork::sendIpQuery); + connect(this, &Client::sendFreqQuery, m_net, &INetwork::sendFreqQuery); + connect(this, &Client::sendServerQuery, m_net, &INetwork::sendServerQuery); + connect(this, &Client::sendAtcQuery, m_net, &INetwork::sendAtcQuery); + connect(this, &Client::sendAtisQuery, m_net, &INetwork::sendAtisQuery); + connect(this, &Client::sendNameQuery, m_net, &INetwork::sendNameQuery); + connect(this, &Client::sendCapabilitiesQuery, m_net, &INetwork::sendCapabilitiesQuery); + connect(this, &Client::replyToFreqQuery, m_net, &INetwork::replyToFreqQuery); + connect(this, &Client::replyToNameQuery, m_net, &INetwork::replyToNameQuery); + connect(this, &Client::requestPlaneInfo, m_net, &INetwork::requestPlaneInfo); + connect(this, &Client::sendPlaneInfo, m_net, &INetwork::sendPlaneInfo); + connect(this, &Client::ping, m_net, &INetwork::ping); + connect(this, &Client::requestMetar, m_net, &INetwork::requestMetar); + connect(this, &Client::requestWeatherData, m_net, &INetwork::requestWeatherData); + + using namespace std::placeholders; + m_commands["help"] = std::bind(&Client::help, this, _1); + m_commands["echo"] = std::bind(&Client::echo, this, _1); + m_commands["exit"] = std::bind(&Client::exit, this, _1); + m_commands["setserver"] = std::bind(&Client::setServerDetailsCmd, this, _1); + m_commands["setuser"] = std::bind(&Client::setUserCredentialsCmd, this, _1); + m_commands["setcallsign"] = std::bind(&Client::setCallsignCmd, this, _1); + m_commands["setrealname"] = std::bind(&Client::setRealNameCmd, this, _1); + m_commands["initconnect"] = std::bind(&Client::initiateConnectionCmd, this, _1); + m_commands["termconnect"] = std::bind(&Client::terminateConnectionCmd, this, _1); + m_commands["privmsg"] = std::bind(&Client::sendPrivateTextMessageCmd, this, _1); + m_commands["textmsg"] = std::bind(&Client::sendRadioTextMessageCmd, this, _1); + m_commands["ip"] = std::bind(&Client::sendIpQueryCmd, this, _1); + m_commands["freq"] = std::bind(&Client::sendFreqQueryCmd, this, _1); + m_commands["server"] = std::bind(&Client::sendServerQueryCmd, this, _1); + m_commands["atc"] = std::bind(&Client::sendAtcQueryCmd, this, _1); + m_commands["atis"] = std::bind(&Client::sendAtisQueryCmd, this, _1); + m_commands["name"] = std::bind(&Client::sendNameQueryCmd, this, _1); + m_commands["caps"] = std::bind(&Client::sendCapabilitiesQueryCmd, this, _1); + m_commands["freqreply"] = std::bind(&Client::replyToFreqQueryCmd, this, _1); + m_commands["namereply"] = std::bind(&Client::replyToNameQueryCmd, this, _1); + m_commands["planeinfo"] = std::bind(&Client::requestPlaneInfoCmd, this, _1); + m_commands["planeinforeply"] = std::bind(&Client::sendPlaneInfoCmd, this, _1); + m_commands["ping"] = std::bind(&Client::pingCmd, this, _1); + m_commands["metar"] = std::bind(&Client::requestMetarCmd, this, _1); + m_commands["weather"] = std::bind(&Client::requestWeatherDataCmd, this, _1); +} + +void Client::command(QString line) +{ + QTextStream stream (&line, QIODevice::ReadOnly); + QString cmd; + stream >> cmd; + + auto found = m_commands.find(cmd); + if (found == m_commands.end()) + { + std::cout << "No such command" << std::endl; + } + else + { + (*found)(stream); + } +} + +/****************************************************************************/ +/************ Commands *************/ +/****************************************************************************/ + +void Client::help(QTextStream&) +{ + std::cout << "Commands:" << std::endl; + auto keys = m_commands.keys(); + for (auto i = keys.begin(); i != keys.end(); ++i) + { + std::cout << " " << i->toStdString() << std::endl; + } +} + +void Client::echo(QTextStream& line) +{ + std::cout << "echo: " << line.readAll().toStdString() << std::endl; +} + +void Client::exit(QTextStream&) +{ + emit quit(); +} + +void Client::setServerDetailsCmd(QTextStream& args) +{ + QString hostname; + quint16 port; + args >> hostname >> port; + emit setServerDetails(hostname, port); +} + +void Client::setUserCredentialsCmd(QTextStream& args) +{ + QString username; + QString password; + args >> username >> password; + emit setUserCredentials(username, password); +} + +void Client::setCallsignCmd(QTextStream& args) +{ + QString callsign; + args >> callsign; + emit setCallsign(callsign); +} + +void Client::setRealNameCmd(QTextStream& args) +{ + emit setRealName(args.readAll()); +} + +void Client::initiateConnectionCmd(QTextStream&) +{ + emit initiateConnection(); +} + +void Client::terminateConnectionCmd(QTextStream&) +{ + emit terminateConnection(); +} + +void Client::sendPrivateTextMessageCmd(QTextStream& args) +{ + QString callsign; + args >> callsign; + args.skipWhiteSpace(); + emit sendPrivateTextMessage(callsign, args.readAll()); +} + +void Client::sendRadioTextMessageCmd(QTextStream& args) +{ + QString freqsBlob; + args >> freqsBlob; + QStringList freqStrings = freqsBlob.split("|"); + QVector freqs; + for (auto i = freqStrings.begin(); i != freqStrings.end(); ++i) + { + freqs.push_back(BlackMisc::PhysicalQuantities::CFrequency(i->toDouble(), BlackMisc::PhysicalQuantities::CFrequencyUnit::MHz())); + } + emit sendRadioTextMessage(freqs, args.readAll()); +} + +void Client::sendIpQueryCmd(QTextStream&) +{ + emit sendIpQuery(); +} + +void Client::sendFreqQueryCmd(QTextStream& args) +{ + QString callsign; + args >> callsign; + emit sendFreqQuery(callsign); +} + +void Client::sendServerQueryCmd(QTextStream& args) +{ + QString callsign; + args >> callsign; + emit sendServerQuery(callsign); +} + +void Client::sendAtcQueryCmd(QTextStream& args) +{ + QString callsign; + args >> callsign; + emit sendAtcQuery(callsign); +} + +void Client::sendAtisQueryCmd(QTextStream& args) +{ + QString callsign; + args >> callsign; + emit sendAtisQuery(callsign); +} + +void Client::sendNameQueryCmd(QTextStream& args) +{ + QString callsign; + args >> callsign; + emit sendNameQuery(callsign); +} + +void Client::sendCapabilitiesQueryCmd(QTextStream& args) +{ + QString callsign; + args >> callsign; + emit sendCapabilitiesQuery(callsign); +} + +void Client::replyToFreqQueryCmd(QTextStream& args) +{ + QString callsign; + double num; + args >> callsign >> num; + BlackMisc::PhysicalQuantities::CFrequency freq (num, BlackMisc::PhysicalQuantities::CFrequencyUnit::kHz()); + emit replyToFreqQuery(callsign, freq); +} + +void Client::replyToNameQueryCmd(QTextStream& args) +{ + QString callsign; + QString realname; + args >> callsign >> realname; + emit replyToNameQuery(callsign, realname); +} + +void Client::requestPlaneInfoCmd(QTextStream& args) +{ + QString callsign; + args >> callsign; + emit requestPlaneInfo(callsign); +} + +void Client::sendPlaneInfoCmd(QTextStream& args) +{ + QString callsign; + QString acTypeICAO; + QString airlineICAO; + QString livery; + args >> callsign >> acTypeICAO >> airlineICAO >> livery; + emit sendPlaneInfo(callsign, acTypeICAO, airlineICAO, livery); +} + +void Client::pingCmd(QTextStream& args) +{ + QString callsign; + args >> callsign; + emit ping(callsign); +} + +void Client::requestMetarCmd(QTextStream& args) +{ + QString airportICAO; + args >> airportICAO; + emit requestMetar(airportICAO); +} + +void Client::requestWeatherDataCmd(QTextStream& args) +{ + QString airportICAO; + args >> airportICAO; + emit requestWeatherData(airportICAO); +} + +/****************************************************************************/ +/************ Slots to receive signals from INetwork *************/ +/****************************************************************************/ + +void Client::atcPositionUpdate(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq, + const BlackMisc::Geo::CCoordinateGeodetic& pos, const BlackMisc::PhysicalQuantities::CLength& range) +{ + std::cout << "POSITION " << callsign.toStdString() << " " << freq << " " << pos << " " << range << std::endl; +} + +void Client::atcDisconnected(const QString& callsign) +{ + std::cout << "ATC_DISCONNECTED " << callsign.toStdString() << std::endl; +} + +void Client::connectionStatusIdle() +{ + std::cout << "CONN_STATUS_IDLE" << std::endl; +} + +void Client::connectionStatusConnecting() +{ + std::cout << "CONN_STATUS_CONNECTING" << std::endl; +} + +void Client::connectionStatusConnected() +{ + std::cout << "CONN_STATUS_CONNECTED" << std::endl; +} + +void Client::connectionStatusDisconnected() +{ + std::cout << "CONN_STATUS_DISCONNECTED" << std::endl; +} + +void Client::connectionStatusError() +{ + std::cout << "CONN_STATUS_ERROR" << std::endl; +} + +void Client::ipQueryReplyReceived(const QString& ip) +{ + std::cout << "IP_REPLY " << ip.toStdString() << std::endl; +} + +void Client::freqQueryReplyReceived(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq) +{ + std::cout << "FREQ_REPLY " << callsign.toStdString() << " " << freq << std::endl; +} + +void Client::serverQueryReplyReceived(const QString& callsign, const QString& hostname) +{ + std::cout << "SERVER_REPLY " << callsign.toStdString() << " " << hostname.toStdString() << std::endl; +} + +void Client::atcQueryReplyReceived(const QString& callsign, bool isATC) +{ + std::cout << "ATC_REPLY " << callsign.toStdString() << (isATC ? " yes" : " no") << std::endl; +} + +void Client::atisQueryReplyReceived(const QString& callsign, const QString& data) +{ + std::cout << "ATIS_REPLY " << callsign.toStdString() << " " << data.toStdString() << std::endl; +} + +void Client::nameQueryReplyReceived(const QString& callsign, const QString& realname) +{ + std::cout << "NAME_REPLY " << callsign.toStdString() << " " << realname.toStdString() << std::endl; +} + +void Client::capabilitiesQueryReplyReceived(const QString& callsign, quint32 flags) +{ + std::cout << "CAPS_REPLY " << callsign.toStdString() << " " << flags << std::endl; +} + +void Client::freqQueryRequestReceived(const QString& callsign) +{ + std::cout << "FREQ_QUERY " << callsign.toStdString() << std::endl; +} + +void Client::nameQueryRequestReceived(const QString& callsign) +{ + std::cout << "NAME_QUERY " << callsign.toStdString() << std::endl; +} + +void Client::kicked(const QString& msg) +{ + std::cout << "KICKED " << msg.toStdString() << std::endl; +} + +void Client::metarReceived(const QString& data) +{ + std::cout << "METAR " << data.toStdString() << std::endl; +} + +void Client::pilotDisconnected(const QString& callsign) +{ + std::cout << "PILOT_DISCONNECTED " << callsign.toStdString() << std::endl; +} + +void Client::planeInfoReceived(const QString& callsign, const QString& acTypeICAO, const QString& airlineICAO, const QString& livery) +{ + std::cout << "PLANE_INFO_REPLY " << callsign.toStdString() << " " << acTypeICAO.toStdString() << " " << airlineICAO.toStdString() << " " << livery.toStdString() << std::endl; +} + +void Client::planeInfoRequestReceived(const QString& callsign) +{ + std::cout << "PLANE_INFO_QUERY " << callsign.toStdString() << std::endl; +} + +void Client::pong(const QString& callsign, const BlackMisc::PhysicalQuantities::CTime& elapsedTime) +{ + std::cout << "PONG " << callsign.toStdString() << " " << elapsedTime << std::endl; +} + +void Client::radioTextMessageReceived(const QString& callsign, const QString& msg, const QVector& freqs) +{ + QString freqsBlob = freqs[0].toQString(); + for (auto i = freqs.begin() + 1; i != freqs.end(); ++i) + { + freqsBlob.append("|"); + freqsBlob.append(i->toQString()); + } + std::cout << "TEXT_MSG " << callsign.toStdString() << " " << freqsBlob.toStdString() << " " << msg.toStdString() << std::endl; +} + +void Client::privateTextMessageReceived(const QString& fromCallsign, const QString& toCallsign, const QString& msg) +{ + std::cout << "PRIV_MSG " << fromCallsign.toStdString() << " -> " << toCallsign.toStdString() << msg.toStdString() << std::endl; +} diff --git a/samples/cli_client/client.h b/samples/cli_client/client.h new file mode 100644 index 000000000..65f6eaf8a --- /dev/null +++ b/samples/cli_client/client.h @@ -0,0 +1,111 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef __BLACKSAMPLE_CLI_CLIENT_H__ +#define __BLACKSAMPLE_CLI_CLIENT_H__ + +#include +#include +#include +#include +#include "blackcore/network.h" + +class Client : public QObject +{ + Q_OBJECT + +public: + Client(); + +signals: + void quit(); + +public slots: + void command(QString line); + +private: //commands + void help(QTextStream& args); + void echo(QTextStream& args); + void exit(QTextStream& args); + void setServerDetailsCmd(QTextStream& args); + void setUserCredentialsCmd(QTextStream& args); + void setCallsignCmd(QTextStream& args); + void setRealNameCmd(QTextStream& args); + void initiateConnectionCmd(QTextStream& args); + void terminateConnectionCmd(QTextStream& args); + void sendPrivateTextMessageCmd(QTextStream& args); + void sendRadioTextMessageCmd(QTextStream& args); + void sendIpQueryCmd(QTextStream& args); + void sendFreqQueryCmd(QTextStream& args); + void sendServerQueryCmd(QTextStream& args); + void sendAtcQueryCmd(QTextStream& args); + void sendAtisQueryCmd(QTextStream& args); + void sendNameQueryCmd(QTextStream& args); + void sendCapabilitiesQueryCmd(QTextStream& args); + void replyToFreqQueryCmd(QTextStream& args); + void replyToNameQueryCmd(QTextStream& args); + void requestPlaneInfoCmd(QTextStream& args); + void sendPlaneInfoCmd(QTextStream& args); + void pingCmd(QTextStream& args); + void requestMetarCmd(QTextStream& args); + void requestWeatherDataCmd(QTextStream& args); + +signals: //to send to INetwork + void setServerDetails(const QString& hostname, quint16 port); + void setUserCredentials(const QString& username, const QString& password); + void setCallsign(const QString& callsign); + void setRealName(const QString& name); + void initiateConnection(); + void terminateConnection(); + void sendPrivateTextMessage(const QString& callsign, const QString& msg); + void sendRadioTextMessage(const QVector& freqs, const QString& msg); + void sendIpQuery(); + void sendFreqQuery(const QString& callsign); + void sendServerQuery(const QString& callsign); + void sendAtcQuery(const QString& callsign); + void sendAtisQuery(const QString& callsign); + void sendNameQuery(const QString& callsign); + void sendCapabilitiesQuery(const QString& callsign); + void replyToFreqQuery(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq); + void replyToNameQuery(const QString& callsign, const QString& realname); + void requestPlaneInfo(const QString& callsign); + void sendPlaneInfo(const QString& callsign, const QString& acTypeICAO, const QString& airlineICAO, const QString& livery); + void ping(const QString& callsign); + void requestMetar(const QString& airportICAO); + void requestWeatherData(const QString& airportICAO); + +public slots: //to receive from INetwork + void atcPositionUpdate(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq, + const BlackMisc::Geo::CCoordinateGeodetic& pos, const BlackMisc::PhysicalQuantities::CLength& range); + void atcDisconnected(const QString& callsign); + void connectionStatusIdle(); + void connectionStatusConnecting(); + void connectionStatusConnected(); + void connectionStatusDisconnected(); + void connectionStatusError(); + void ipQueryReplyReceived(const QString& ip); + void freqQueryReplyReceived(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq); + void serverQueryReplyReceived(const QString& callsign, const QString& hostname); + void atcQueryReplyReceived(const QString& callsign, bool isATC); + void atisQueryReplyReceived(const QString& callsign, const QString& data); + void nameQueryReplyReceived(const QString& callsign, const QString& realname); + void capabilitiesQueryReplyReceived(const QString& callsign, quint32 flags); + void freqQueryRequestReceived(const QString& callsign); + void nameQueryRequestReceived(const QString& callsign); + void kicked(const QString& msg); + void metarReceived(const QString& data); + void pilotDisconnected(const QString& callsign); + void planeInfoReceived(const QString& callsign, const QString& acTypeICAO, const QString& airlineICAO, const QString& livery); + void planeInfoRequestReceived(const QString& callsign); + void pong(const QString& callsign, const BlackMisc::PhysicalQuantities::CTime& elapsedTime); + void radioTextMessageReceived(const QString& callsign, const QString& msg, const QVector& freqs); + void privateTextMessageReceived(const QString& fromCallsign, const QString& toCallsign, const QString& msg); + +private: + QMap> m_commands; + BlackCore::INetwork* m_net; +}; + +#endif //__BLACKSAMPLE_CLI_CLIENT_H__ diff --git a/samples/cli_client/main.cpp b/samples/cli_client/main.cpp new file mode 100644 index 000000000..1c7ed9f11 --- /dev/null +++ b/samples/cli_client/main.cpp @@ -0,0 +1,27 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "blackcore/network_vatlib.h" +#include "client.h" +#include "reader.h" +#include +#include + +int main(int argc, char *argv[]) +{ + QCoreApplication app (argc, argv); + BlackMisc::CApplicationContext myApplicationContext; + BlackMisc::IContext::getInstance().setSingleton(new BlackMisc::CDebug()); + BlackMisc::IContext::getInstance().setSingleton(new BlackCore::NetworkVatlib()); + + Client client; + LineReader reader; + QObject::connect(&reader, SIGNAL(command(const QString&)), &client, SLOT(command(const QString&))); + QObject::connect(&client, SIGNAL(quit()), &reader, SLOT(terminate())); + QObject::connect(&client, SIGNAL(quit()), &app, SLOT(quit())); + + reader.start(); + app.exec(); +} diff --git a/samples/cli_client/reader.cpp b/samples/cli_client/reader.cpp new file mode 100644 index 000000000..c7bfbc7f8 --- /dev/null +++ b/samples/cli_client/reader.cpp @@ -0,0 +1,21 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "reader.h" +#include + +void LineReader::run() +{ + QFile file; + file.open(stdin, QIODevice::ReadOnly | QIODevice::Text); + forever + { + QString line = file.readLine(); + if (! line.isEmpty()) + { + emit command(line); + } + } +} \ No newline at end of file diff --git a/samples/cli_client/reader.h b/samples/cli_client/reader.h new file mode 100644 index 000000000..29ee715ed --- /dev/null +++ b/samples/cli_client/reader.h @@ -0,0 +1,26 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef __BLACKSAMPLE_CLI_CLIENT_READER_H__ +#define __BLACKSAMPLE_CLI_CLIENT_READER_H__ + +#include +#include + +class LineReader : public QThread +{ + Q_OBJECT + +public: + LineReader() {} + +protected: + void run(); + +signals: + void command(const QString& line); +}; + +#endif //__BLACKSAMPLE_CLI_CLIENT_READER_H__ \ No newline at end of file diff --git a/samples/cli_client/sample_cli_client.pro b/samples/cli_client/sample_cli_client.pro new file mode 100644 index 000000000..e58e01d85 --- /dev/null +++ b/samples/cli_client/sample_cli_client.pro @@ -0,0 +1,27 @@ +QT += core +QT -= gui + +TARGET = sample_cli_client +TEMPLATE = app + +CONFIG += console +CONFIG -= app_bundle + +DEPENDPATH += . ../../src +INCLUDEPATH += . ../../src + +SOURCES += *.cpp +HEADERS += *.h + +LIBS += -L../../lib -lblackcore -lblackmisc +LIBS += -L../../../vatlib -lvatlib + +win32:!win32-g++*: PRE_TARGETDEPS += ../../lib/blackmisc.lib \ + ../../lib/blackcore.lib \ + ../../../vatlib/vatlib.lib +else: PRE_TARGETDEPS += ../../lib/libblackmisc.a \ + ../../lib/libblackcore.a \ + ../../../vatlib/libvatlib.a + #TODO standardize dependency locations + +DESTDIR = ../../bin From d1e35c0b27ccb08313e60e6afc4517da0d801984 Mon Sep 17 00:00:00 2001 From: gmt2001 Date: Sun, 4 Aug 2013 01:54:03 -0400 Subject: [PATCH 08/15] refs #22 Fix leading space and trailing LF in real name Use proper const char* to const char* copy in NetworkVatlib::initiateConnection() --- samples/cli_client/client.cpp | 2 +- src/blackcore/network_vatlib.cpp | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/samples/cli_client/client.cpp b/samples/cli_client/client.cpp index 062608ec0..c885d0bdb 100644 --- a/samples/cli_client/client.cpp +++ b/samples/cli_client/client.cpp @@ -154,7 +154,7 @@ void Client::setCallsignCmd(QTextStream& args) void Client::setRealNameCmd(QTextStream& args) { - emit setRealName(args.readAll()); + emit setRealName(args.readLine().mid(1)); //readLine returns the entire line up to, but excluding, the LF character. mid(int) is the QString equivilent of a substring(start), used here to remove a space } void Client::initiateConnectionCmd(QTextStream&) diff --git a/src/blackcore/network_vatlib.cpp b/src/blackcore/network_vatlib.cpp index dab444836..6327a3cd6 100644 --- a/src/blackcore/network_vatlib.cpp +++ b/src/blackcore/network_vatlib.cpp @@ -166,12 +166,23 @@ namespace BlackCore { try { + //Proper way to copy a const char* to a const char*. Copy it to a char* then assign the char* to the const char* + const size_t len1 = strlen(m_callsign.toStdString().c_str()); //Get the length + char* tmp1 = new char[len1 + 1]; //Allocate the char* + strncpy(tmp1, m_callsign.toStdString().c_str(), len1); //Copy the const char* to the char* + tmp1[len1] = '\0'; //Insurance of null termination + + const size_t len2 = strlen(m_realname.toStdString().c_str()); + char* tmp2 = new char[len2 + 1]; + strncpy(tmp2, m_realname.toStdString().c_str(), len2); + tmp2[len2] = '\0'; + Cvatlib_Network::PilotConnectionInfo info; - info.callsign = m_callsign.toStdString().c_str(); - info.name = m_realname.toStdString().c_str(); + info.callsign = tmp1; //Assign char* to const char* + info.name = tmp2; info.rating = Cvatlib_Network::pilotRating_Unknown; //TODO info.sim = Cvatlib_Network::simType_XPlane; //TODO - + m_net->SetPilotLoginInfo(m_serverHost.toStdString().c_str(), m_serverPort, m_username.toStdString().c_str(), m_password.toStdString().c_str(), info); m_net->ConnectAndLogon(); From 56e05b55a9804e4e3d90d707d191a5173b2efa6b Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Sun, 4 Aug 2013 17:49:46 +0100 Subject: [PATCH 09/15] Normalized handling of leading/trailing whitespace in sample app (refs #22) --- samples/cli_client/client.cpp | 3 ++- samples/cli_client/reader.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/samples/cli_client/client.cpp b/samples/cli_client/client.cpp index c885d0bdb..b51b6cb52 100644 --- a/samples/cli_client/client.cpp +++ b/samples/cli_client/client.cpp @@ -93,6 +93,7 @@ void Client::command(QString line) QTextStream stream (&line, QIODevice::ReadOnly); QString cmd; stream >> cmd; + stream.skipWhiteSpace(); auto found = m_commands.find(cmd); if (found == m_commands.end()) @@ -154,7 +155,7 @@ void Client::setCallsignCmd(QTextStream& args) void Client::setRealNameCmd(QTextStream& args) { - emit setRealName(args.readLine().mid(1)); //readLine returns the entire line up to, but excluding, the LF character. mid(int) is the QString equivilent of a substring(start), used here to remove a space + emit setRealName(args.readAll()); } void Client::initiateConnectionCmd(QTextStream&) diff --git a/samples/cli_client/reader.cpp b/samples/cli_client/reader.cpp index c7bfbc7f8..a6ad50885 100644 --- a/samples/cli_client/reader.cpp +++ b/samples/cli_client/reader.cpp @@ -12,7 +12,7 @@ void LineReader::run() file.open(stdin, QIODevice::ReadOnly | QIODevice::Text); forever { - QString line = file.readLine(); + QString line = file.readLine().trimmed(); if (! line.isEmpty()) { emit command(line); From 0c310227b48180cdad6bd3bda3532541409a26db Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Sun, 4 Aug 2013 17:58:05 +0100 Subject: [PATCH 10/15] refs #22 * storing callsign and realname as QByteArray instead of QString makes it easier to ensure that C-strings passed to the shim have lifetimes coincident with the shim * added a bit more error handling and invariant enforcement * now we terminate the connection automatically on fatal errors * added first doxygen comment (first of many) --- src/blackcore/network.h | 7 +++ src/blackcore/network_vatlib.cpp | 81 +++++++++++++++++++------------- src/blackcore/network_vatlib.h | 10 +++- 3 files changed, 64 insertions(+), 34 deletions(-) diff --git a/src/blackcore/network.h b/src/blackcore/network.h index 90a466234..87164e5aa 100644 --- a/src/blackcore/network.h +++ b/src/blackcore/network.h @@ -22,6 +22,13 @@ namespace BlackCore { + /*! + * Interface to a connection to a multi-user flight simulation and ATC network. + * + * \warning If an INetwork signal is connected to a slot, and that slot emits a signal + * which is connected to an INetwork slot, then at least one of those connections + * must be a Qt::QueuedConnection. + */ class INetwork : public QObject { Q_OBJECT diff --git a/src/blackcore/network_vatlib.cpp b/src/blackcore/network_vatlib.cpp index 6327a3cd6..3c3e5de13 100644 --- a/src/blackcore/network_vatlib.cpp +++ b/src/blackcore/network_vatlib.cpp @@ -28,10 +28,13 @@ namespace BlackCore NetworkVatlib::NetworkVatlib() : m_net(Create_Cvatlib_Network()), + m_status(Cvatlib_Network::connStatus_Idle), m_fsdTextCodec(QTextCodec::codecForName("latin1")) { try { + connect(this, SIGNAL(terminate()), this, SLOT(terminateConnection()), Qt::QueuedConnection); + Q_ASSERT_X(m_fsdTextCodec, "NetworkVatlib", "Missing default wire text encoding"); //TODO reinit m_fsdTextCodec from WireTextEncoding config setting if present @@ -75,15 +78,18 @@ namespace BlackCore NetworkVatlib::~NetworkVatlib() { + m_timer.stop(); + try { - m_timer.stop(); - if (m_net->IsNetworkConnected()) { m_net->LogoffAndDisconnect(0); } - + } + catch (...) { exceptionDispatcher(Q_FUNC_INFO); } + try + { m_net->DestroyNetworkSession(); } catch (...) { exceptionDispatcher(Q_FUNC_INFO); } @@ -142,52 +148,57 @@ namespace BlackCore void NetworkVatlib::setServerDetails(const QString& host, quint16 port) { + Q_ASSERT_X(isDisconnected(), "NetworkVatlib", "Can't change server details while still connected"); + m_serverHost = host; m_serverPort = port; } void NetworkVatlib::setUserCredentials(const QString& username, const QString& password) { + Q_ASSERT_X(isDisconnected(), "NetworkVatlib", "Can't change login details while still connected"); + m_username = username; m_password = password; } void NetworkVatlib::setCallsign(const QString& callsign) { - m_callsign = callsign; + Q_ASSERT_X(isDisconnected(), "NetworkVatlib", "Can't change callsign while still connected"); + + m_callsign = toFSD(callsign); } void NetworkVatlib::setRealName(const QString& name) { - m_realname = name; + Q_ASSERT_X(isDisconnected(), "NetworkVatlib", "Can't change name while still connected"); + + m_realname = toFSD(name); } void NetworkVatlib::initiateConnection() { + Q_ASSERT_X(isDisconnected(), "NetworkVatlib", "Can't connect while still connected"); + try { - //Proper way to copy a const char* to a const char*. Copy it to a char* then assign the char* to the const char* - const size_t len1 = strlen(m_callsign.toStdString().c_str()); //Get the length - char* tmp1 = new char[len1 + 1]; //Allocate the char* - strncpy(tmp1, m_callsign.toStdString().c_str(), len1); //Copy the const char* to the char* - tmp1[len1] = '\0'; //Insurance of null termination - - const size_t len2 = strlen(m_realname.toStdString().c_str()); - char* tmp2 = new char[len2 + 1]; - strncpy(tmp2, m_realname.toStdString().c_str(), len2); - tmp2[len2] = '\0'; - + m_status = Cvatlib_Network::connStatus_Connecting; //paranoia + Cvatlib_Network::PilotConnectionInfo info; - info.callsign = tmp1; //Assign char* to const char* - info.name = tmp2; + info.callsign = m_callsign.data(); + info.name = m_realname.data(); info.rating = Cvatlib_Network::pilotRating_Unknown; //TODO info.sim = Cvatlib_Network::simType_XPlane; //TODO - m_net->SetPilotLoginInfo(m_serverHost.toStdString().c_str(), m_serverPort, - m_username.toStdString().c_str(), m_password.toStdString().c_str(), info); + m_net->SetPilotLoginInfo(toFSD(m_serverHost).data(), m_serverPort, + toFSD(m_username).data(), toFSD(m_password).data(), info); m_net->ConnectAndLogon(); } - catch (...) { exceptionDispatcher(Q_FUNC_INFO); } + catch (...) + { + m_status = Cvatlib_Network::connStatus_Idle; + exceptionDispatcher(Q_FUNC_INFO); + } } void NetworkVatlib::terminateConnection() @@ -382,6 +393,8 @@ namespace BlackCore void NetworkVatlib::onConnectionStatusChanged(Cvatlib_Network*, Cvatlib_Network::connStatus, Cvatlib_Network::connStatus newStatus, void* cbvar) { + cbvar_cast(cbvar)->m_status = newStatus; + switch (newStatus) { case Cvatlib_Network::connStatus_Idle: emit cbvar_cast(cbvar)->connectionStatusIdle(); break; @@ -498,17 +511,17 @@ namespace BlackCore { switch (type) { - case Cvatlib_Network::error_Ok: return; - case Cvatlib_Network::error_CallsignTaken: qCritical() << "The requested callsign is already taken"; break; - case Cvatlib_Network::error_CallsignInvalid: qCritical() << "The requested callsign is not valid"; break; - case Cvatlib_Network::error_CIDPasswdInvalid: qCritical() << "Wrong user ID or password"; break; - case Cvatlib_Network::error_ProtoVersion: qCritical() << "This server uses an unsupported protocol version"; break; - case Cvatlib_Network::error_LevelTooHigh: qCritical() << "You are not authorized to use the requested pilot rating"; break; - case Cvatlib_Network::error_ServerFull: qCritical() << "The server is full"; break; - case Cvatlib_Network::error_CIDSuspended: qCritical() << "Your user account is suspended"; break; - case Cvatlib_Network::error_InvalidPosition: qCritical() << "You are not authorized to use the requested pilot rating"; break; - case Cvatlib_Network::error_SoftwareNotAuthorized: qCritical() << "This client software has not been authorized for use on this network"; break; + case Cvatlib_Network::error_CallsignTaken: qCritical() << "The requested callsign is already taken"; goto terminate; + case Cvatlib_Network::error_CallsignInvalid: qCritical() << "The requested callsign is not valid"; goto terminate; + case Cvatlib_Network::error_CIDPasswdInvalid: qCritical() << "Wrong user ID or password"; goto terminate; + case Cvatlib_Network::error_ProtoVersion: qCritical() << "This server uses an unsupported protocol version"; goto terminate; + case Cvatlib_Network::error_LevelTooHigh: qCritical() << "You are not authorized to use the requested pilot rating"; goto terminate; + case Cvatlib_Network::error_ServerFull: qCritical() << "The server is full"; goto terminate; + case Cvatlib_Network::error_CIDSuspended: qCritical() << "Your user account is suspended"; goto terminate; + case Cvatlib_Network::error_InvalidPosition: qCritical() << "You are not authorized to use the requested pilot rating"; goto terminate; + case Cvatlib_Network::error_SoftwareNotAuthorized: qCritical() << "This client software has not been authorized for use on this network"; goto terminate; + case Cvatlib_Network::error_Ok: break; case Cvatlib_Network::error_Syntax: qWarning() << "Malformed packet: Syntax error: %s" << cbvar_cast(cbvar)->fromFSD(data); break; case Cvatlib_Network::error_SourceInvalid: qDebug() << "Server: source invalid (" << cbvar_cast(cbvar)->fromFSD(data); break; case Cvatlib_Network::error_CallsignNotExists: qDebug() << "Shim lib: " << cbvar_cast(cbvar)->fromFSD(msg) << " (" << cbvar_cast(cbvar)->fromFSD(data) << ")"; break; @@ -519,8 +532,12 @@ namespace BlackCore case Cvatlib_Network::error_Registered: case Cvatlib_Network::error_InvalidControl: qWarning() << "Server: " << cbvar_cast(cbvar)->fromFSD(msg); break; - default: qFatal("VATSIM shim library: %s (error %d)", cbvar_cast(cbvar)->fromFSD(msg), type); break; + default: qFatal("VATSIM shim library: %s (error %d)", cbvar_cast(cbvar)->fromFSD(msg), type); goto terminate; } + + return; + terminate: + emit cbvar_cast(cbvar)->terminate(); } void NetworkVatlib::onWindDataReceived(Cvatlib_Network*, Cvatlib_Network::WindLayer layers[4], void* cbvar) diff --git a/src/blackcore/network_vatlib.h b/src/blackcore/network_vatlib.h index 563df06ce..1f186c7e1 100644 --- a/src/blackcore/network_vatlib.h +++ b/src/blackcore/network_vatlib.h @@ -15,6 +15,7 @@ #include #include #include +#include namespace BlackCore { @@ -80,9 +81,14 @@ namespace BlackCore private: QByteArray toFSD(QString qstr) const; QString fromFSD(const char* cstr) const; + bool isDisconnected() const { return m_status == Cvatlib_Network::connStatus_Idle || m_status == Cvatlib_Network::connStatus_Disconnected; } + + signals: + void terminate(); private: QScopedPointer m_net; + Cvatlib_Network::connStatus m_status; QBasicTimer m_timer; static int const c_updateIntervalMillisecs = 100; @@ -92,8 +98,8 @@ namespace BlackCore quint16 m_serverPort; QString m_username; QString m_password; - QString m_callsign; - QString m_realname; + QByteArray m_callsign; + QByteArray m_realname; QTextCodec* m_fsdTextCodec; }; From eade49799b67a177a32bbecc97eb718e4889bb7c Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Fri, 9 Aug 2013 00:49:12 +0100 Subject: [PATCH 11/15] corrected error message --- src/blackcore/network_vatlib.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blackcore/network_vatlib.cpp b/src/blackcore/network_vatlib.cpp index 3c3e5de13..367a86156 100644 --- a/src/blackcore/network_vatlib.cpp +++ b/src/blackcore/network_vatlib.cpp @@ -514,7 +514,7 @@ namespace BlackCore case Cvatlib_Network::error_CallsignTaken: qCritical() << "The requested callsign is already taken"; goto terminate; case Cvatlib_Network::error_CallsignInvalid: qCritical() << "The requested callsign is not valid"; goto terminate; case Cvatlib_Network::error_CIDPasswdInvalid: qCritical() << "Wrong user ID or password"; goto terminate; - case Cvatlib_Network::error_ProtoVersion: qCritical() << "This server uses an unsupported protocol version"; goto terminate; + case Cvatlib_Network::error_ProtoVersion: qCritical() << "This server does not support our protocol version"; goto terminate; case Cvatlib_Network::error_LevelTooHigh: qCritical() << "You are not authorized to use the requested pilot rating"; goto terminate; case Cvatlib_Network::error_ServerFull: qCritical() << "The server is full"; goto terminate; case Cvatlib_Network::error_CIDSuspended: qCritical() << "Your user account is suspended"; goto terminate; From e194773c5bb56573cdc1c0de7fed4c3efa4f108c Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Fri, 9 Aug 2013 00:55:46 +0100 Subject: [PATCH 12/15] CAtcListManager class --- src/blackcore/atclistmgr.cpp | 39 +++++++++ src/blackcore/atclistmgr.h | 95 ++++++++++++++++++++++ src/blackmisc/atclist.h | 111 ++++++++++++++++++++++++++ tests/blackcore/blackcoretest.h | 10 ++- tests/blackcore/testblackcoremain.cpp | 5 ++ tests/blackcore/testnetmediators.cpp | 44 ++++++++++ tests/blackcore/testnetmediators.h | 61 ++++++++++++++ 7 files changed, 364 insertions(+), 1 deletion(-) create mode 100644 src/blackcore/atclistmgr.cpp create mode 100644 src/blackcore/atclistmgr.h create mode 100644 src/blackmisc/atclist.h create mode 100644 tests/blackcore/testnetmediators.cpp create mode 100644 tests/blackcore/testnetmediators.h diff --git a/src/blackcore/atclistmgr.cpp b/src/blackcore/atclistmgr.cpp new file mode 100644 index 000000000..5a0a67528 --- /dev/null +++ b/src/blackcore/atclistmgr.cpp @@ -0,0 +1,39 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "atclistmgr.h" +#include "network.h" + +BlackCore::CAtcListManager::CAtcListManager(const BlackCoreTest::EnableTesting&) +{ +} + +BlackCore::CAtcListManager::CAtcListManager() +{ + INetwork *net = BlackMisc::IContext::getInstance().singleton(); + + connect(net, &INetwork::atcPositionUpdate, this, &CAtcListManager::update, Qt::QueuedConnection); + connect(net, &INetwork::atcDisconnected, this, &CAtcListManager::remove, Qt::QueuedConnection); + connect(net, &INetwork::connectionStatusDisconnected, this, &CAtcListManager::clear, Qt::QueuedConnection); +} + +void BlackCore::CAtcListManager::update(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq, + const BlackMisc::Geo::CCoordinateGeodetic& pos, const BlackMisc::PhysicalQuantities::CLength& range) +{ + m_list.insert(BlackMisc::CAtcListEntry(callsign, freq, pos, range)); + emit listChanged(m_list); +} + +void BlackCore::CAtcListManager::remove(const QString& callsign) +{ + m_list.remove(callsign); + emit listChanged(m_list); +} + +void BlackCore::CAtcListManager::clear() +{ + m_list.clear(); + emit listChanged(m_list); +} \ No newline at end of file diff --git a/src/blackcore/atclistmgr.h b/src/blackcore/atclistmgr.h new file mode 100644 index 000000000..9079b9ba4 --- /dev/null +++ b/src/blackcore/atclistmgr.h @@ -0,0 +1,95 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/*! + \file +*/ + +#ifndef BLACKCORE_ATCLISTMGR_H +#define BLACKCORE_ATCLISTMGR_H + +#include "blackmisc/atclist.h" +#include + +namespace BlackCoreTest +{ + class EnableTesting; +} + +namespace BlackCore +{ + + /*! + * Abstract base class that manages and provides access to a list of available ATC stations. + */ + class IAtcListManager : public QObject + { + Q_OBJECT + Q_PROPERTY(BlackMisc::CAtcList list READ getList NOTIFY listChanged) + + public: + BLACK_INTERFACE(BlackCore::IAtcListManager) + + /*! + * Virtual destructor. + */ + virtual ~IAtcListManager() {} + + /*! + * Immutable getter. + * \return + */ + virtual const BlackMisc::CAtcList &getList() const = 0; + + signals: + /*! + * Emitted whenever there is a change in the ATC list. + * \param list The new list + */ + void listChanged(const BlackMisc::CAtcList &list); + }; + + /*! + * Concrete ATC list manager. Implementation of IAtcListManager. + * + * Has a dependency on INetwork. An INetwork must be available through the IContext singleton. + */ + class CAtcListManager : public IAtcListManager + { + Q_OBJECT + + public: + /*! + * Constructor. + */ + CAtcListManager(); + + virtual const BlackMisc::CAtcList& getList() const { return m_list; } + + public slots: + /*! + * CAtcListManager is responsible for connecting these slots. + * \{ + */ + void update(const QString& callsign, const BlackMisc::PhysicalQuantities::CFrequency& freq, + const BlackMisc::Geo::CCoordinateGeodetic& pos, const BlackMisc::PhysicalQuantities::CLength& range); + void remove(const QString& callsign); + void clear(); + /*! \} */ + + public: + /*! + * Constructor that does not connect INetwork signals to CAtcListManager slots. + * \warning Only used for testing purposes. + */ + explicit CAtcListManager(const BlackCoreTest::EnableTesting&); + + private: + BlackMisc::CAtcList m_list; + }; + +}//namespace BlackCore + +#endif //BLACKCORE_ATCLISTMGR_H \ No newline at end of file diff --git a/src/blackmisc/atclist.h b/src/blackmisc/atclist.h new file mode 100644 index 000000000..f6f14a145 --- /dev/null +++ b/src/blackmisc/atclist.h @@ -0,0 +1,111 @@ +/* Copyright (C) 2013 VATSIM Community / authors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/*! + \file +*/ + +#ifndef BLACKMISC_ATCLIST_H +#define BLACKMISC_ATCLIST_H + +#include "pqfrequency.h" +#include "pqlength.h" +#include "coordinategeodetic.h" +#include "context.h" +#include +#include +#include + +namespace BlackMisc +{ + + /*! + * Value object encapsulating information about an ATC station. + */ + class CAtcListEntry + { + public: + /*! + * Default constructor. + */ + CAtcListEntry() {} + + /*! + * Constructor. + */ + CAtcListEntry(const QString &callsign, const BlackMisc::PhysicalQuantities::CFrequency &freq, + const BlackMisc::Geo::CCoordinateGeodetic &pos, const BlackMisc::PhysicalQuantities::CLength &range) + : m_callsign(callsign), m_freq(freq), m_pos(pos), m_range(range) + {} + + /*! + * Get callsign. + * \return + */ + const QString &getCallsign() const { return m_callsign; } + + /*! + * Get frequency. + * \return + */ + const BlackMisc::PhysicalQuantities::CFrequency &getFrequency() const { return m_freq; } + + /*! + * Get the position of the center of the controller's area of visibility. + * \return + */ + const BlackMisc::Geo::CCoordinateGeodetic &getPosition() const { return m_pos; } + + /*! + * Get the radius of the controller's area of visibility. + * \return + */ + const BlackMisc::PhysicalQuantities::CLength &getAtcRange() const { return m_range; } + + private: + QString m_callsign; + BlackMisc::PhysicalQuantities::CFrequency m_freq; + BlackMisc::Geo::CCoordinateGeodetic m_pos; + BlackMisc::PhysicalQuantities::CLength m_range; + }; + + /*! + * Value object encapsulating a list of ATC stations. + */ + class CAtcList + { + public: + /*! + * Immutable getter for the internal map. + * \return + */ + const QMap &constMap() const { return m_map; } + + /*! + * Insert an ATC station into the list. + * \param entry + */ + void insert(const CAtcListEntry &entry) { m_map.insert(entry.getCallsign(), entry); } + + /*! + * Remove an ATC station from the list. + * \param callsign + */ + void remove(const QString &callsign) { m_map.remove(callsign); } + + /*! + * Remove all ATC stations from the list. + */ + void clear() { m_map.clear(); } + + private: + QMap m_map; + }; + +} //namespace BlackMisc + +Q_DECLARE_METATYPE(BlackMisc::CAtcList) + +#endif //BLACKMISC_ATCLIST_H \ No newline at end of file diff --git a/tests/blackcore/blackcoretest.h b/tests/blackcore/blackcoretest.h index 87965024d..825995de7 100644 --- a/tests/blackcore/blackcoretest.h +++ b/tests/blackcore/blackcoretest.h @@ -7,10 +7,18 @@ #define BLACKCORETEST_H /*! - * @namespace BlackCoreTest + * \namespace BlackCoreTest * Unit tests for BlackCore. Unit tests do have their own namespace, so * the regular namespace BlackCore is completely free of unit tests. * Add any new tests to TestMain::unitMain as shown there. */ +namespace BlackCoreTest +{ + /*! + * An "option type" used to alter the construction of objects under test. + */ + class EnableTesting {}; +} + #endif // guard diff --git a/tests/blackcore/testblackcoremain.cpp b/tests/blackcore/testblackcoremain.cpp index 82468ac72..4e1251dea 100644 --- a/tests/blackcore/testblackcoremain.cpp +++ b/tests/blackcore/testblackcoremain.cpp @@ -5,6 +5,7 @@ #include "testblackcoremain.h" #include "testinterpolator.h" +#include "testnetmediators.h" namespace BlackCoreTest { @@ -19,6 +20,10 @@ int CBlackCoreTestMain::unitMain(int argc, char *argv[]) CTestInterpolator interpolatorTests; status |= QTest::qExec(&interpolatorTests, argc, argv); } + { + CTestNetMediators mediatorTests; + status |= QTest::qExec(&mediatorTests, argc, argv); + } return status; } } // namespace diff --git a/tests/blackcore/testnetmediators.cpp b/tests/blackcore/testnetmediators.cpp new file mode 100644 index 000000000..6a2c765a2 --- /dev/null +++ b/tests/blackcore/testnetmediators.cpp @@ -0,0 +1,44 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "testnetmediators.h" +#include + +namespace BlackCoreTest +{ + + using namespace BlackCore; + using namespace BlackMisc; + using namespace BlackMisc::PhysicalQuantities; + using namespace BlackMisc::Geo; + + void CTestNetMediators::atcListManagerTest() + { + CAtcListManager mgr ( (EnableTesting()) ); //extra pair of parentheses to disambiguate most vexing parse + AtcListConsumer cons; + + QObject::connect(&mgr, &IAtcListManager::listChanged, &cons, &AtcListConsumer::listChanged); + + QVERIFY(cons.m_list.constMap().size() == 0); + mgr.update("EGLL_TWR", CFrequency(118.7, CFrequencyUnit::MHz()), CCoordinateGeodetic(51.4775, 0.46139, 0), CLength(50, CLengthUnit::m())); + QVERIFY(cons.m_list.constMap().size() == 1); + mgr.update("EGLL_GND", CFrequency(121.9, CFrequencyUnit::MHz()), CCoordinateGeodetic(51.4775, 0.46139, 0), CLength(20, CLengthUnit::m())); + QVERIFY(cons.m_list.constMap().size() == 2); + mgr.update("EGLL_TWR", CFrequency(118.5, CFrequencyUnit::MHz()), CCoordinateGeodetic(51.4775, 0.46139, 0), CLength(50, CLengthUnit::m())); + QVERIFY(cons.m_list.constMap().size() == 2); + mgr.remove("EGLL_TWR"); + QVERIFY(cons.m_list.constMap().size() == 1); + mgr.clear(); + QVERIFY(cons.m_list.constMap().size() == 0); + + mgr.update("EGLL_TWR", CFrequency(118.5, CFrequencyUnit::MHz()), CCoordinateGeodetic(51.4775, 0.46139, 0), CLength(50, CLengthUnit::m())); + QVERIFY(cons.m_list.constMap().contains("EGLL_TWR")); + QVERIFY(cons.m_list.constMap()["EGLL_TWR"].getCallsign() == "EGLL_TWR"); + QVERIFY(cons.m_list.constMap()["EGLL_TWR"].getFrequency() == CFrequency(118.5, CFrequencyUnit::MHz())); + QVERIFY(cons.m_list.constMap()["EGLL_TWR"].getPosition() == CCoordinateGeodetic(51.4775, 0.46139, 0)); + QVERIFY(cons.m_list.constMap()["EGLL_TWR"].getAtcRange() == CLength(50, CLengthUnit::m())); + } + +} //namespace BlackCoreTest \ No newline at end of file diff --git a/tests/blackcore/testnetmediators.h b/tests/blackcore/testnetmediators.h new file mode 100644 index 000000000..210eff6c7 --- /dev/null +++ b/tests/blackcore/testnetmediators.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2013 VATSIM Community / contributors + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BLACKCORETEST_TESTNETMEDIATORS_H +#define BLACKCORETEST_TESTNETMEDIATORS_H + +#include "blackcore/atclistmgr.h" +#include "blackcoretest.h" +#include + +namespace BlackCoreTest +{ + + /*! + * Network mediator classes tests + */ + class CTestNetMediators : public QObject + { + Q_OBJECT + + public: + /*! + * Constructor. + * \param parent + */ + explicit CTestNetMediators(QObject *parent = 0) : QObject(parent) {} + + private slots: + /*! + * Test CAtcListManager + */ + void atcListManagerTest(); + }; + + /*! + * Helper class that connects to CAtcListManager signals + */ + class AtcListConsumer : public QObject + { + Q_OBJECT + + public: + //! List is updated by the slot + BlackMisc::CAtcList m_list; + + public slots: + /*! + * Slot updates the list + * \param list + */ + void listChanged(const BlackMisc::CAtcList &list) + { + m_list = list; + } + }; + +} //namespace BlackCoreTest + +#endif //BLACKCORETEST_TESTNETMEDIATORS_H \ No newline at end of file From 4edd28e0fa089d09d3c551a964fd2513a74662b9 Mon Sep 17 00:00:00 2001 From: gmt2001 Date: Sat, 24 Aug 2013 09:41:45 -0400 Subject: [PATCH 13/15] Fix for always getting suspended message --- src/blackcore/network_vatlib.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blackcore/network_vatlib.cpp b/src/blackcore/network_vatlib.cpp index 3c3e5de13..9f3e2dad3 100644 --- a/src/blackcore/network_vatlib.cpp +++ b/src/blackcore/network_vatlib.cpp @@ -187,7 +187,7 @@ namespace BlackCore Cvatlib_Network::PilotConnectionInfo info; info.callsign = m_callsign.data(); info.name = m_realname.data(); - info.rating = Cvatlib_Network::pilotRating_Unknown; //TODO + info.rating = Cvatlib_Network::pilotRating_Student; //TODO info.sim = Cvatlib_Network::simType_XPlane; //TODO m_net->SetPilotLoginInfo(toFSD(m_serverHost).data(), m_serverPort, From 0107d245239c5c8c6d6d1c966fd9cf3067116b4c Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Thu, 22 Aug 2013 17:56:35 +0100 Subject: [PATCH 14/15] create a dummy implementation of INetwork for testing purposes, and use it in the atc list unittest --- src/blackcore/atclistmgr.cpp | 4 ---- src/blackcore/atclistmgr.h | 12 ----------- src/blackcore/network.h | 30 ++++++++++++++++++++++++++++ tests/blackcore/blackcoretest.h | 8 -------- tests/blackcore/testnetmediators.cpp | 25 ++++++++++++++++------- tests/blackcore/testnetmediators.h | 14 +++++++++++++ 6 files changed, 62 insertions(+), 31 deletions(-) diff --git a/src/blackcore/atclistmgr.cpp b/src/blackcore/atclistmgr.cpp index 5a0a67528..622b0444b 100644 --- a/src/blackcore/atclistmgr.cpp +++ b/src/blackcore/atclistmgr.cpp @@ -6,10 +6,6 @@ #include "atclistmgr.h" #include "network.h" -BlackCore::CAtcListManager::CAtcListManager(const BlackCoreTest::EnableTesting&) -{ -} - BlackCore::CAtcListManager::CAtcListManager() { INetwork *net = BlackMisc::IContext::getInstance().singleton(); diff --git a/src/blackcore/atclistmgr.h b/src/blackcore/atclistmgr.h index 9079b9ba4..bbd4af67f 100644 --- a/src/blackcore/atclistmgr.h +++ b/src/blackcore/atclistmgr.h @@ -13,11 +13,6 @@ #include "blackmisc/atclist.h" #include -namespace BlackCoreTest -{ - class EnableTesting; -} - namespace BlackCore { @@ -79,13 +74,6 @@ namespace BlackCore void clear(); /*! \} */ - public: - /*! - * Constructor that does not connect INetwork signals to CAtcListManager slots. - * \warning Only used for testing purposes. - */ - explicit CAtcListManager(const BlackCoreTest::EnableTesting&); - private: BlackMisc::CAtcList m_list; }; diff --git a/src/blackcore/network.h b/src/blackcore/network.h index 87164e5aa..2264ae6c7 100644 --- a/src/blackcore/network.h +++ b/src/blackcore/network.h @@ -104,6 +104,36 @@ namespace BlackCore //TODO void windDataReceived(...); }; + /*! + * Dummy implementation of INetwork used for testing. + */ + class NetworkDummy : public INetwork + { + public: //INetwork slots overrides + virtual void setServerDetails(const QString&, quint16) {} + virtual void setUserCredentials(const QString&, const QString&) {} + virtual void setCallsign(const QString&) {} + virtual void setRealName(const QString&) {} + virtual void initiateConnection() {} + virtual void terminateConnection() {} + virtual void sendPrivateTextMessage(const QString&, const QString&) {} + virtual void sendRadioTextMessage(const QVector&, const QString&) {} + virtual void sendIpQuery() {} + virtual void sendFreqQuery(const QString&) {} + virtual void sendServerQuery(const QString&) {} + virtual void sendAtcQuery(const QString&) {} + virtual void sendAtisQuery(const QString&) {} + virtual void sendNameQuery(const QString&) {} + virtual void sendCapabilitiesQuery(const QString&) {} + virtual void replyToFreqQuery(const QString&, const BlackMisc::PhysicalQuantities::CFrequency&) {} + virtual void replyToNameQuery(const QString&, const QString&) {} + virtual void requestPlaneInfo(const QString&) {} + virtual void sendPlaneInfo(const QString&, const QString&, const QString&, const QString&) {} + virtual void ping(const QString&) {} + virtual void requestMetar(const QString&) {} + virtual void requestWeatherData(const QString&) {} + }; + } //namespace BlackCore #endif //BLACKCORE_NETWORK_H diff --git a/tests/blackcore/blackcoretest.h b/tests/blackcore/blackcoretest.h index 825995de7..8f2534db8 100644 --- a/tests/blackcore/blackcoretest.h +++ b/tests/blackcore/blackcoretest.h @@ -13,12 +13,4 @@ * Add any new tests to TestMain::unitMain as shown there. */ -namespace BlackCoreTest -{ - /*! - * An "option type" used to alter the construction of objects under test. - */ - class EnableTesting {}; -} - #endif // guard diff --git a/tests/blackcore/testnetmediators.cpp b/tests/blackcore/testnetmediators.cpp index 6a2c765a2..6941ad0e7 100644 --- a/tests/blackcore/testnetmediators.cpp +++ b/tests/blackcore/testnetmediators.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "testnetmediators.h" +#include "blackmisc/context.h" #include namespace BlackCoreTest @@ -14,26 +15,36 @@ namespace BlackCoreTest using namespace BlackMisc::PhysicalQuantities; using namespace BlackMisc::Geo; + void CTestNetMediators::initTestCase() + { + BlackMisc::IContext::getInstance().setSingleton(&m_networkDummy); + } + + void CTestNetMediators::cleanupTestCase() + { + BlackMisc::IContext::getInstance().releaseSingleton(); + } + void CTestNetMediators::atcListManagerTest() { - CAtcListManager mgr ( (EnableTesting()) ); //extra pair of parentheses to disambiguate most vexing parse + CAtcListManager mgr; AtcListConsumer cons; QObject::connect(&mgr, &IAtcListManager::listChanged, &cons, &AtcListConsumer::listChanged); QVERIFY(cons.m_list.constMap().size() == 0); - mgr.update("EGLL_TWR", CFrequency(118.7, CFrequencyUnit::MHz()), CCoordinateGeodetic(51.4775, 0.46139, 0), CLength(50, CLengthUnit::m())); + emit m_networkDummy.atcPositionUpdate("EGLL_TWR", CFrequency(118.7, CFrequencyUnit::MHz()), CCoordinateGeodetic(51.4775, 0.46139, 0), CLength(50, CLengthUnit::m())); QVERIFY(cons.m_list.constMap().size() == 1); - mgr.update("EGLL_GND", CFrequency(121.9, CFrequencyUnit::MHz()), CCoordinateGeodetic(51.4775, 0.46139, 0), CLength(20, CLengthUnit::m())); + emit m_networkDummy.atcPositionUpdate("EGLL_GND", CFrequency(121.9, CFrequencyUnit::MHz()), CCoordinateGeodetic(51.4775, 0.46139, 0), CLength(20, CLengthUnit::m())); QVERIFY(cons.m_list.constMap().size() == 2); - mgr.update("EGLL_TWR", CFrequency(118.5, CFrequencyUnit::MHz()), CCoordinateGeodetic(51.4775, 0.46139, 0), CLength(50, CLengthUnit::m())); + emit m_networkDummy.atcPositionUpdate("EGLL_TWR", CFrequency(118.5, CFrequencyUnit::MHz()), CCoordinateGeodetic(51.4775, 0.46139, 0), CLength(50, CLengthUnit::m())); QVERIFY(cons.m_list.constMap().size() == 2); - mgr.remove("EGLL_TWR"); + emit m_networkDummy.atcDisconnected("EGLL_TWR"); QVERIFY(cons.m_list.constMap().size() == 1); - mgr.clear(); + emit m_networkDummy.connectionStatusDisconnected(); QVERIFY(cons.m_list.constMap().size() == 0); - mgr.update("EGLL_TWR", CFrequency(118.5, CFrequencyUnit::MHz()), CCoordinateGeodetic(51.4775, 0.46139, 0), CLength(50, CLengthUnit::m())); + emit m_networkDummy.atcPositionUpdate("EGLL_TWR", CFrequency(118.5, CFrequencyUnit::MHz()), CCoordinateGeodetic(51.4775, 0.46139, 0), CLength(50, CLengthUnit::m())); QVERIFY(cons.m_list.constMap().contains("EGLL_TWR")); QVERIFY(cons.m_list.constMap()["EGLL_TWR"].getCallsign() == "EGLL_TWR"); QVERIFY(cons.m_list.constMap()["EGLL_TWR"].getFrequency() == CFrequency(118.5, CFrequencyUnit::MHz())); diff --git a/tests/blackcore/testnetmediators.h b/tests/blackcore/testnetmediators.h index 210eff6c7..7cfac4993 100644 --- a/tests/blackcore/testnetmediators.h +++ b/tests/blackcore/testnetmediators.h @@ -8,6 +8,7 @@ #include "blackcore/atclistmgr.h" #include "blackcoretest.h" +#include "blackcore/network.h" #include namespace BlackCoreTest @@ -28,10 +29,23 @@ namespace BlackCoreTest explicit CTestNetMediators(QObject *parent = 0) : QObject(parent) {} private slots: + /*! + * Called before the first test. + */ + void initTestCase(); + /*! * Test CAtcListManager */ void atcListManagerTest(); + + /*! + * Called after the last test. + */ + void cleanupTestCase(); + + private: + BlackCore::NetworkDummy m_networkDummy; }; /*! From 31955f09135900c3ffda943a5bc2aa77a278cafc Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Wed, 28 Aug 2013 23:26:57 +0100 Subject: [PATCH 15/15] fixed missing space character in fsd sample --- samples/cli_client/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/cli_client/client.cpp b/samples/cli_client/client.cpp index b51b6cb52..9e06e66d8 100644 --- a/samples/cli_client/client.cpp +++ b/samples/cli_client/client.cpp @@ -419,5 +419,5 @@ void Client::radioTextMessageReceived(const QString& callsign, const QString& ms void Client::privateTextMessageReceived(const QString& fromCallsign, const QString& toCallsign, const QString& msg) { - std::cout << "PRIV_MSG " << fromCallsign.toStdString() << " -> " << toCallsign.toStdString() << msg.toStdString() << std::endl; + std::cout << "PRIV_MSG " << fromCallsign.toStdString() << " -> " << toCallsign.toStdString() << " " << msg.toStdString() << std::endl; }