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