diff --git a/servermain.cpp b/servermain.cpp index 115bead..e0be201 100644 --- a/servermain.cpp +++ b/servermain.cpp @@ -598,15 +598,36 @@ void servermain::loadSettings() serverConfig.controlPort = settings->value("ServerControlPort", 50001).toInt(); serverConfig.civPort = settings->value("ServerCivPort", 50002).toInt(); serverConfig.audioPort = settings->value("ServerAudioPort", 50003).toInt(); - int numUsers = settings->value("ServerNumUsers", 2).toInt(); + serverConfig.users.clear(); - for (int f = 0; f < numUsers; f++) - { - SERVERUSER user; - user.username = settings->value("ServerUsername_" + QString::number(f), "").toString(); - user.password = settings->value("ServerPassword_" + QString::number(f), "").toString(); - user.userType = settings->value("ServerUserType_" + QString::number(f), 0).toInt(); - serverConfig.users.append(user); + + int numUsers = settings->beginReadArray("Users"); + if (numUsers > 0) { + { + for (int f = 0; f < numUsers; f++) + { + settings->setArrayIndex(f); + SERVERUSER user; + user.username = settings->value("Username", "").toString(); + user.password = settings->value("Password", "").toString(); + user.userType = settings->value("UserType", 0).toInt(); + serverConfig.users.append(user); + } + } + settings->endArray(); + } + else { + /* Support old way of storing users*/ + settings->endArray(); + numUsers = settings->value("ServerNumUsers", 2).toInt(); + for (int f = 0; f < numUsers; f++) + { + SERVERUSER user; + user.username = settings->value("ServerUsername_" + QString::number(f), "").toString(); + user.password = settings->value("ServerPassword_" + QString::number(f), "").toString(); + user.userType = settings->value("ServerUserType_" + QString::number(f), 0).toInt(); + serverConfig.users.append(user); + } } serverRxSetup.isinput = true; diff --git a/udphandler.cpp b/udphandler.cpp index 08bae80..8671997 100644 --- a/udphandler.cpp +++ b/udphandler.cpp @@ -6,8 +6,10 @@ udpHandler::udpHandler(udpPreferences prefs, audioSetup rx, audioSetup tx) : controlPort(prefs.controlLANPort), - civPort(50002), - audioPort(50003), + civPort(0), + audioPort(0), + civLocalPort(0), + audioLocalPort(0), rxSetup(rx), txSetup(tx) { @@ -55,7 +57,7 @@ udpHandler::udpHandler(udpPreferences prefs, audioSetup rx, audioSetup tx) : void udpHandler::init() { - udpBase::init(); // Perform UDP socket initialization. + udpBase::init(0); // Perform UDP socket initialization. // Connect socket to my dataReceived function. QUdpSocket::connect(udp, &QUdpSocket::readyRead, this, &udpHandler::dataReceived); @@ -219,7 +221,7 @@ void udpHandler::dataReceived() gotAuthOK = true; if (!streamOpened) { - sendRequestStream(); + sendRequestStream(); } } @@ -272,6 +274,27 @@ void udpHandler::dataReceived() else { civPort = qFromBigEndian(in->civport); audioPort = qFromBigEndian(in->audioport); + if (!streamOpened) { + + civ = new udpCivData(localIP, radioIP, civPort, civLocalPort); + + // TX is not supported + if (txSampleRates < 2) { + txSetup.samplerate = 0; + txSetup.codec = 0; + } + audio = new udpAudio(localIP, radioIP, audioPort, audioLocalPort, rxSetup, txSetup); + + QObject::connect(civ, SIGNAL(receive(QByteArray)), this, SLOT(receiveFromCivStream(QByteArray))); + QObject::connect(audio, SIGNAL(haveAudioData(audioPacket)), this, SLOT(receiveAudioData(audioPacket))); + QObject::connect(this, SIGNAL(haveChangeLatency(quint16)), audio, SLOT(changeLatency(quint16))); + QObject::connect(this, SIGNAL(haveSetVolume(unsigned char)), audio, SLOT(setVolume(unsigned char))); + + streamOpened = true; + } + qInfo(logUdp()) << this->metaObject()->className() << "Got serial and audio request success, device name: " << devName; + + } } break; @@ -365,32 +388,13 @@ void udpHandler::dataReceived() sendControl(false, 0x00, in->seq); // Respond with an idle } else { - setCurrentRadio(0); } } else if (!in->busy && numRadios == 1) { status.message = devName + " available"; - - if (civPort == 0) { - qInfo(logUdp()) << this->metaObject()->className() << "civPort not yet configured!"; - } - - if (radios[0].commoncap == 0x8010) { - memcpy(macaddress, radios[0].macaddress, 6); - useGuid = false; - } - else { - useGuid = true; - guid = radios[0].guid; - } - - devName = radios[0].name; - audioType = radios[0].audio; - civId = radios[0].civ; - rxSampleRates = radios[0].rxsample; - txSampleRates = radios[0].txsample; - sendRequestStream(); // Send initial stream request. + + setCurrentRadio(0); } } else if (streamOpened) @@ -398,7 +402,7 @@ void udpHandler::dataReceived() a CONNINFO packet, send our details to confirm we still want the stream */ { // Received while stream is open. - sendRequestStream(); + //sendRequestStream(); } break; } @@ -451,6 +455,21 @@ void udpHandler::dataReceived() void udpHandler::setCurrentRadio(int radio) { qInfo(logUdp()) << "Got Radio" << radio; + qInfo(logUdp()) << "Find available local ports"; + + /* This seems to be the only way to find some available local ports. + The problem is we need to know the local AND remote ports but send the + local port to the server first and it replies with the remote ports! */ + if (civLocalPort == 0 || audioLocalPort == 0) { + QUdpSocket* tempudp = new QUdpSocket(); + tempudp->bind(); // Bind to random port. + civLocalPort = tempudp->localPort(); + tempudp->close(); + tempudp->bind(); + audioLocalPort = tempudp->localPort(); + tempudp->close(); + delete tempudp; + } int baudrate = qFromBigEndian(radios[radio].baudrate); emit haveBaudRate(baudrate); @@ -469,25 +488,6 @@ void udpHandler::setCurrentRadio(int radio) { rxSampleRates = radios[radio].rxsample; txSampleRates = radios[radio].txsample; - if (!streamOpened) { - - civ = new udpCivData(localIP, radioIP, civPort); - - // TX is not supported - if (txSampleRates < 2) { - txSetup.samplerate = 0; - txSetup.codec = 0; - } - audio = new udpAudio(localIP, radioIP, audioPort, rxSetup, txSetup); - QObject::connect(civ, SIGNAL(receive(QByteArray)), this, SLOT(receiveFromCivStream(QByteArray))); - QObject::connect(audio, SIGNAL(haveAudioData(audioPacket)), this, SLOT(receiveAudioData(audioPacket))); - QObject::connect(this, SIGNAL(haveChangeLatency(quint16)), audio, SLOT(changeLatency(quint16))); - QObject::connect(this, SIGNAL(haveSetVolume(unsigned char)), audio, SLOT(setVolume(unsigned char))); - - streamOpened = true; - } - qInfo(logUdp()) << this->metaObject()->className() << "Got serial and audio request success, device name: " << devName; - sendRequestStream(); } @@ -525,8 +525,8 @@ void udpHandler::sendRequestStream() memcpy(&p.username, usernameEncoded.constData(), usernameEncoded.length()); p.rxsample = qToBigEndian((quint32)rxSetup.samplerate); p.txsample = qToBigEndian((quint32)txSetup.samplerate); - p.civport = qToBigEndian((quint32)civPort); - p.audioport = qToBigEndian((quint32)audioPort); + p.civport = qToBigEndian((quint32)civLocalPort); + p.audioport = qToBigEndian((quint32)audioLocalPort); p.txbuffer = qToBigEndian((quint32)txSetup.latency); p.convert = 1; sendTrackedPacket(QByteArray::fromRawData((const char*)p.packet, sizeof(p))); @@ -597,14 +597,14 @@ void udpHandler::sendToken(uint8_t magic) // Class that manages all Civ Data to/from the rig -udpCivData::udpCivData(QHostAddress local, QHostAddress ip, quint16 civPort) +udpCivData::udpCivData(QHostAddress local, QHostAddress ip, quint16 civPort,quint16 localPort=0) { qInfo(logUdp()) << "Starting udpCivData"; localIP = local; port = civPort; radioIP = ip; - udpBase::init(); // Perform connection + udpBase::init(localPort); // Perform connection QUdpSocket::connect(udp, &QUdpSocket::readyRead, this, &udpCivData::dataReceived); @@ -793,7 +793,7 @@ void udpCivData::dataReceived() // Audio stream -udpAudio::udpAudio(QHostAddress local, QHostAddress ip, quint16 audioPort, audioSetup rxSetup, audioSetup txSetup) +udpAudio::udpAudio(QHostAddress local, QHostAddress ip, quint16 audioPort, quint16 lport, audioSetup rxSetup, audioSetup txSetup) { qInfo(logUdp()) << "Starting udpAudio"; this->localIP = local; @@ -804,7 +804,7 @@ udpAudio::udpAudio(QHostAddress local, QHostAddress ip, quint16 audioPort, audio enableTx = false; } - init(); // Perform connection + init(lport); // Perform connection QUdpSocket::connect(udp, &QUdpSocket::readyRead, this, &udpAudio::dataReceived); @@ -1065,11 +1065,11 @@ void udpAudio::dataReceived() -void udpBase::init() +void udpBase::init(quint16 lport) { timeStarted.start(); udp = new QUdpSocket(this); - udp->bind(); // Bind to random port. + udp->bind(lport); // Bind to random port. localPort = udp->localPort(); qInfo(logUdp()) << "UDP Stream bound to local port:" << localPort << " remote port:" << port; uint32_t addr = localIP.toIPv4Address(); @@ -1078,7 +1078,6 @@ void udpBase::init() retransmitTimer = new QTimer(); connect(retransmitTimer, &QTimer::timeout, this, &udpBase::sendRetransmitRequest); retransmitTimer->start(RETRANSMIT_PERIOD); - } udpBase::~udpBase() diff --git a/udphandler.h b/udphandler.h index 298047f..bdf44cf 100644 --- a/udphandler.h +++ b/udphandler.h @@ -60,7 +60,9 @@ class udpBase : public QObject public: ~udpBase(); - void init(); + void init(quint16 local); + + void reconnect(); void dataReceived(QByteArray r); void sendPing(); @@ -142,7 +144,7 @@ class udpCivData : public udpBase Q_OBJECT public: - udpCivData(QHostAddress local, QHostAddress ip, quint16 civPort); + udpCivData(QHostAddress local, QHostAddress ip, quint16 civPort, quint16 lport); ~udpCivData(); QMutex serialmutex; @@ -168,7 +170,7 @@ class udpAudio : public udpBase Q_OBJECT public: - udpAudio(QHostAddress local, QHostAddress ip, quint16 aport, audioSetup rxSetup, audioSetup txSetup); + udpAudio(QHostAddress local, QHostAddress ip, quint16 aport, quint16 lport, audioSetup rxSetup, audioSetup txSetup); ~udpAudio(); int audioLatency = 0; @@ -271,6 +273,9 @@ private: quint16 civPort; quint16 audioPort; + quint16 civLocalPort; + quint16 audioLocalPort; + audioSetup rxSetup; audioSetup txSetup; diff --git a/wfmain.cpp b/wfmain.cpp index 557af65..c9bfef0 100644 --- a/wfmain.cpp +++ b/wfmain.cpp @@ -1622,16 +1622,38 @@ void wfmain::loadSettings() serverConfig.controlPort = settings->value("ServerControlPort", 50001).toInt(); serverConfig.civPort = settings->value("ServerCivPort", 50002).toInt(); serverConfig.audioPort = settings->value("ServerAudioPort", 50003).toInt(); - int numUsers = settings->value("ServerNumUsers", 2).toInt(); + serverConfig.users.clear(); - for (int f = 0; f < numUsers; f++) - { - SERVERUSER user; - user.username = settings->value("ServerUsername_" + QString::number(f), "").toString(); - user.password = settings->value("ServerPassword_" + QString::number(f), "").toString(); - user.userType = settings->value("ServerUserType_" + QString::number(f), 0).toInt(); - serverConfig.users.append(user); + + int numUsers = settings->beginReadArray("Users"); + if (numUsers > 0) { + { + for (int f = 0; f < numUsers; f++) + { + settings->setArrayIndex(f); + SERVERUSER user; + user.username = settings->value("Username", "").toString(); + user.password = settings->value("Password", "").toString(); + user.userType = settings->value("UserType", 0).toInt(); + serverConfig.users.append(user); + } + } + settings->endArray(); } + else { + /* Support old way of storing users*/ + settings->endArray(); + numUsers = settings->value("ServerNumUsers", 2).toInt(); + for (int f = 0; f < numUsers; f++) + { + SERVERUSER user; + user.username = settings->value("ServerUsername_" + QString::number(f), "").toString(); + user.password = settings->value("ServerPassword_" + QString::number(f), "").toString(); + user.userType = settings->value("ServerUserType_" + QString::number(f), 0).toInt(); + serverConfig.users.append(user); + } + } + ui->serverEnableCheckbox->setChecked(serverConfig.enabled); ui->serverControlPortText->setText(QString::number(serverConfig.controlPort)); @@ -2004,18 +2026,32 @@ void wfmain::saveSettings() settings->setValue("ServerControlPort", serverConfig.controlPort); settings->setValue("ServerCivPort", serverConfig.civPort); settings->setValue("ServerAudioPort", serverConfig.audioPort); - settings->setValue("ServerNumUsers", serverConfig.users.count()); settings->setValue("ServerAudioOutput", serverTxSetup.name); settings->setValue("ServerAudioInput", serverRxSetup.name); + /* Remove old format users*/ + int numUsers = settings->value("ServerNumUsers", 0).toInt(); + if (numUsers > 0) { + settings->remove("ServerNumUsers"); + for (int f = 0; f < numUsers; f++) + { + settings->remove("ServerUsername_" + QString::number(f)); + settings->remove("ServerPassword_" + QString::number(f)); + settings->remove("ServerUserType_" + QString::number(f)); + } + } + + settings->beginWriteArray("Users"); for (int f = 0; f < serverConfig.users.count(); f++) { - settings->setValue("ServerUsername_" + QString::number(f), serverConfig.users[f].username); - settings->setValue("ServerPassword_" + QString::number(f), serverConfig.users[f].password); - settings->setValue("ServerUserType_" + QString::number(f), serverConfig.users[f].userType); + settings->setArrayIndex(f); + settings->setValue("Username", serverConfig.users[f].username); + settings->setValue("Password", serverConfig.users[f].password); + settings->setValue("UserType", serverConfig.users[f].userType); } + settings->endArray(); qInfo() << "Server config stored"; settings->endGroup(); diff --git a/wfserver.vcxproj b/wfserver.vcxproj index e78371d..6fb6b46 100644 --- a/wfserver.vcxproj +++ b/wfserver.vcxproj @@ -57,7 +57,7 @@ Sync release\ MaxSpeed - _CONSOLE;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.2d";BUILD_WFSERVER;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX="/usr/local";GITSHORT="9f059c9";HOST="wfview.org";UNAME="build";NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions) + _CONSOLE;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.2d";BUILD_WFSERVER;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX="/usr/local";GITSHORT="ff47fbd";HOST="wfview.org";UNAME="build";NDEBUG;QT_NO_DEBUG;%(PreprocessorDefinitions) false MultiThreadedDLL @@ -85,7 +85,7 @@ 0 - _CONSOLE;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.2d\";BUILD_WFSERVER;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX=\"/usr/local\";GITSHORT=\"9f059c9\";HOST=\"wfview.org\";UNAME=\"build\";NDEBUG;QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) + _CONSOLE;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.2d\";BUILD_WFSERVER;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX=\"/usr/local\";GITSHORT=\"ff47fbd\";HOST=\"wfview.org\";UNAME=\"build\";NDEBUG;QT_NO_DEBUG;QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;%(PreprocessorDefinitions) msvc./$(Configuration)/moc_predefs.hMoc'ing %(Identity)...output$(Configuration)moc_%(Filename).cppdefaultRcc'ing %(Identity)...$(Configuration)qrc_%(Filename).cpp @@ -99,7 +99,7 @@ Sync debug\ Disabled - _CONSOLE;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.2d";BUILD_WFSERVER;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX="/usr/local";GITSHORT="9f059c9";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions) + _CONSOLE;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION="1.2d";BUILD_WFSERVER;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX="/usr/local";GITSHORT="ff47fbd";HOST="wfview.org";UNAME="build";%(PreprocessorDefinitions) false MultiThreadedDebugDLL true @@ -124,7 +124,7 @@ 0 - _CONSOLE;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.2d\";BUILD_WFSERVER;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX=\"/usr/local\";GITSHORT=\"9f059c9\";HOST=\"wfview.org\";UNAME=\"build\";QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) + _CONSOLE;UNICODE;_UNICODE;WIN32;_ENABLE_EXTENDED_ALIGNED_STORAGE;WFVIEW_VERSION=\"1.2d\";BUILD_WFSERVER;QT_DEPRECATED_WARNINGS;QCUSTOMPLOT_COMPILE_LIBRARY;USE_SSE;USE_SSE2;OUTSIDE_SPEEX;RANDOM_PREFIX=wf;PREFIX=\"/usr/local\";GITSHORT=\"ff47fbd\";HOST=\"wfview.org\";UNAME=\"build\";QT_MULTIMEDIA_LIB;QT_PRINTSUPPORT_LIB;QT_WIDGETS_LIB;QT_GUI_LIB;QT_SERIALPORT_LIB;QT_NETWORK_LIB;QT_CORE_LIB;_DEBUG;%(PreprocessorDefinitions) msvc./$(Configuration)/moc_predefs.hMoc'ing %(Identity)...output$(Configuration)moc_%(Filename).cppdefaultRcc'ing %(Identity)...$(Configuration)qrc_%(Filename).cpp diff --git a/wfview.sln b/wfview.sln index ff4a8cd..d1ee00c 100644 --- a/wfview.sln +++ b/wfview.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 16.0.30804.86 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wfview", "wfview.vcxproj", "{326108AD-FA9D-3AAF-8D3E-062C4DDC34E2}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wfserver", "wfserver.vcxproj", "{00E054F8-A1D4-3ECA-A8D6-DFC8A68AFD56}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x86 = Debug|x86 @@ -15,6 +17,10 @@ Global {326108AD-FA9D-3AAF-8D3E-062C4DDC34E2}.Debug|x86.Build.0 = Debug|Win32 {326108AD-FA9D-3AAF-8D3E-062C4DDC34E2}.Release|x86.ActiveCfg = Release|Win32 {326108AD-FA9D-3AAF-8D3E-062C4DDC34E2}.Release|x86.Build.0 = Release|Win32 + {00E054F8-A1D4-3ECA-A8D6-DFC8A68AFD56}.Debug|x86.ActiveCfg = Debug|Win32 + {00E054F8-A1D4-3ECA-A8D6-DFC8A68AFD56}.Debug|x86.Build.0 = Debug|Win32 + {00E054F8-A1D4-3ECA-A8D6-DFC8A68AFD56}.Release|x86.ActiveCfg = Release|Win32 + {00E054F8-A1D4-3ECA-A8D6-DFC8A68AFD56}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE