diff --git a/Firmware/RTK_Everywhere/AP-Config/index.html b/Firmware/RTK_Everywhere/AP-Config/index.html
index 4127078fc..c3e2faeb5 100644
--- a/Firmware/RTK_Everywhere/AP-Config/index.html
+++ b/Firmware/RTK_Everywhere/AP-Config/index.html
@@ -1637,6 +1637,17 @@
+
+
+
+
+
+
+
diff --git a/Firmware/RTK_Everywhere/Developer.ino b/Firmware/RTK_Everywhere/Developer.ino
index a60ea93e2..516f21f5b 100644
--- a/Firmware/RTK_Everywhere/Developer.ino
+++ b/Firmware/RTK_Everywhere/Developer.ino
@@ -171,6 +171,8 @@ bool webServerStart(int httpPort = 80)
bool parseIncomingSettings() {return false;}
void sendStringToWebsocket(const char* stringToSend) {}
void stopWebServer() {}
+bool webServerSettingsCheckAndFree() {return false;}
+void webServerSettingsClone() {}
void webServerStop() {}
void webServerUpdate() {}
void webServerVerifyTables() {}
diff --git a/Firmware/RTK_Everywhere/Network.ino b/Firmware/RTK_Everywhere/Network.ino
index e15235dc9..fcf05c6ba 100644
--- a/Firmware/RTK_Everywhere/Network.ino
+++ b/Firmware/RTK_Everywhere/Network.ino
@@ -226,8 +226,8 @@ void menuTcpUdp()
if (settings.mdnsEnable)
systemPrintf("n) MDNS host name: %s\r\n", settings.mdnsHostName);
- systemPrint("a) Broadcast TCP/UDP Server packets over local WiFi or act as Access Point: ");
- systemPrintf("%s\r\n", settings.tcpUdpOverWiFiStation ? "WiFi" : "AP");
+ systemPrint("t) Broadcast TCP/UDP Server packets over local WiFi or act as Access Point: ");
+ systemPrintf("%s\r\n", settings.tcpOverWiFiStation ? "WiFi" : "AP");
systemPrint("u) Broadcast UDP Server packets over local WiFi or act as Access Point: ");
systemPrintf("%s\r\n", settings.udpOverWiFiStation ? "WiFi" : "AP");
@@ -326,9 +326,9 @@ void menuTcpUdp()
getUserInputString((char *)&settings.mdnsHostName, sizeof(settings.mdnsHostName));
}
- else if (incoming == 'a')
+ else if (incoming == 't')
{
- settings.tcpUdpOverWiFiStation ^= 1;
+ settings.tcpOverWiFiStation ^= 1;
wifiUpdateSettings();
}
diff --git a/Firmware/RTK_Everywhere/RTK_Everywhere.ino b/Firmware/RTK_Everywhere/RTK_Everywhere.ino
index c4b71e954..98af9be70 100644
--- a/Firmware/RTK_Everywhere/RTK_Everywhere.ino
+++ b/Firmware/RTK_Everywhere/RTK_Everywhere.ino
@@ -343,11 +343,6 @@ const TickType_t ringBuffer_longWait_ms = 300 / portTICK_PERIOD_MS;
SemaphoreHandle_t ringBufferSemaphore = NULL;
const char *ringBufferSemaphoreHolder = "None";
-// tcpServer semaphore - prevent tcpServerClientSendData (handleGnssDataTask) and tcpServerUpdate
-// from gatecrashing each other. See #695 for why this is needed.
-SemaphoreHandle_t tcpServerSemaphore = NULL;
-const char *tcpServerSemaphoreHolder = "None";
-
// Display used/free space in menu and config page
uint64_t sdCardSize;
uint64_t sdFreeSpace;
@@ -444,6 +439,7 @@ bool otaRequestFirmwareUpdate = false;
bool enableRCFirmware; // Goes true from AP config page
bool currentlyParsingData; // Goes true when we hit 750ms timeout with new data
+bool tcpServerInCasterMode;// True when TCP server is running in caster mode
// Give up connecting after this number of attempts
// Connection attempts are throttled to increase the time between attempts
diff --git a/Firmware/RTK_Everywhere/Tasks.ino b/Firmware/RTK_Everywhere/Tasks.ino
index 9e330b2e8..14362fbad 100644
--- a/Firmware/RTK_Everywhere/Tasks.ino
+++ b/Firmware/RTK_Everywhere/Tasks.ino
@@ -754,7 +754,7 @@ void processUart1Message(SEMP_PARSE_STATE *parse, uint16_t type)
// If BaseCasterOverride is enabled, remove everything but RTCM from the circular buffer
// to avoid saturating the downstream radio link that is consuming over a TCP (NTRIP Caster) connection
// Remove NMEA, etc after passing to the GNSS receiver library so that we still have SIV and other stats available
- if (settings.baseCasterOverride == true)
+ if (tcpServerInCasterMode)
{
if (type != RTK_RTCM_PARSER_INDEX)
{
diff --git a/Firmware/RTK_Everywhere/TcpServer.ino b/Firmware/RTK_Everywhere/TcpServer.ino
index 7f4385570..cbbf532dd 100644
--- a/Firmware/RTK_Everywhere/TcpServer.ino
+++ b/Firmware/RTK_Everywhere/TcpServer.ino
@@ -79,10 +79,30 @@ const char *const tcpServerStateName[] = {
"TCP_SERVER_STATE_WAIT_FOR_NETWORK",
"TCP_SERVER_STATE_RUNNING",
};
-
const int tcpServerStateNameEntries = sizeof(tcpServerStateName) / sizeof(tcpServerStateName[0]);
-const RtkMode_t tcpServerMode = RTK_MODE_BASE_FIXED | RTK_MODE_BASE_SURVEY_IN | RTK_MODE_ROVER;
+// Define the TCP server client states
+enum tcpServerClientStates
+{
+ TCP_SERVER_CLIENT_OFF = 0,
+ TCP_SERVER_CLIENT_WAIT_REQUEST,
+ TCP_SERVER_CLIENT_GET_REQUEST,
+ TCP_SERVER_CLIENT_SENDING_DATA,
+ // Insert new states here
+ TCP_SERVER_CLIENT_MAX // Last entry in the state list
+};
+
+const char *const tcpServerClientStateName[] = {
+ "TCP_SERVER_CLIENT_OFF",
+ "TCP_SERVER_CLIENT_WAIT_REQUEST",
+ "TCP_SERVER_CLIENT_GET_REQUEST",
+ "TCP_SERVER_CLIENT_SENDING_DATA",
+};
+const int tcpServerClientStateNameEntries = sizeof(tcpServerClientStateName) / sizeof(tcpServerClientStateName[0]);
+
+const RtkMode_t baseCasterMode = RTK_MODE_BASE_FIXED;
+const RtkMode_t tcpServerMode = RTK_MODE_ROVER
+ | RTK_MODE_BASE_SURVEY_IN;
//----------------------------------------
// Locals
@@ -90,15 +110,21 @@ const RtkMode_t tcpServerMode = RTK_MODE_BASE_FIXED | RTK_MODE_BASE_SURVEY_IN |
// TCP server
static NetworkServer *tcpServer = nullptr;
+static uint16_t tcpServerPort;
static uint8_t tcpServerState;
static uint32_t tcpServerTimer;
+static bool tcpServerWiFiSoftAp;
+static const char * tcpServerName;
// TCP server clients
static volatile uint8_t tcpServerClientConnected;
static volatile uint8_t tcpServerClientDataSent;
+static volatile uint8_t tcpServerClientSendingData;
+static uint32_t tcpServerClientTimer[TCP_SERVER_MAX_CLIENTS];
static volatile uint8_t tcpServerClientWriteError;
static NetworkClient *tcpServerClient[TCP_SERVER_MAX_CLIENTS];
static IPAddress tcpServerClientIpAddress[TCP_SERVER_MAX_CLIENTS];
+static uint8_t tcpServerClientState[TCP_SERVER_MAX_CLIENTS];
static volatile RING_BUFFER_OFFSET tcpServerClientTails[TCP_SERVER_MAX_CLIENTS];
//----------------------------------------
@@ -139,42 +165,24 @@ int32_t tcpServerClientSendData(int index, uint8_t *data, uint16_t length)
{
if (tcpServerClient[index])
{
- // Use a semaphore to prevent tcpServerUpdate from gatecrashing
- if (tcpServerSemaphore == NULL)
- tcpServerSemaphore = xSemaphoreCreateMutex(); // Create the mutex
-
- // Take the semaphore
- if (xSemaphoreTake(tcpServerSemaphore, 50 / portTICK_PERIOD_MS) == pdPASS)
+ length = tcpServerClient[index]->write(data, length);
+ if (length > 0)
{
- tcpServerSemaphoreHolder = "tcpServerClientSendData";
-
- length = tcpServerClient[index]->write(data, length);
+ // Update the data sent flag when data successfully sent
if (length > 0)
- {
- // Update the data sent flag when data successfully sent
- if (length > 0)
- tcpServerClientDataSent = tcpServerClientDataSent | (1 << index);
- if ((settings.debugTcpServer || PERIODIC_DISPLAY(PD_TCP_SERVER_CLIENT_DATA)) && (!inMainMenu))
- {
- PERIODIC_CLEAR(PD_TCP_SERVER_CLIENT_DATA);
- systemPrintf("TCP server wrote %d bytes to %s\r\n", length,
- tcpServerClientIpAddress[index].toString().c_str());
- }
- }
-
- // Failed to write the data
- else
- {
- // Done with this client connection
- tcpServerStopClient(index);
- length = 0;
- }
-
- xSemaphoreGive(tcpServerSemaphore);
+ tcpServerClientDataSent = tcpServerClientDataSent | (1 << index);
+ if ((settings.debugTcpServer || PERIODIC_DISPLAY(PD_TCP_SERVER_CLIENT_DATA)) && (!inMainMenu))
+ systemPrintf("%s wrote %d bytes to %s\r\n",
+ tcpServerName, length,
+ tcpServerClientIpAddress[index].toString().c_str());
}
+
+ // Failed to write the data
else
{
- systemPrintf("tcpServerClientSendData could not get semaphore - held by %s\r\n", tcpServerSemaphoreHolder);
+ // Done with this client connection
+ tcpServerStopClient(index);
+ length = 0;
}
}
return length;
@@ -185,23 +193,88 @@ int32_t tcpServerClientSendData(int index, uint8_t *data, uint16_t length)
//----------------------------------------
bool tcpServerEnabled(const char ** line)
{
+ bool casterMode;
bool enabled;
+ const char * name;
+ uint16_t port;
+ bool softAP;
do
{
+ // Determine if the server is enabled
enabled = false;
+ if ((settings.enableTcpServer
+ || settings.enableNtripCaster
+ || settings.baseCasterOverride) == false)
+ {
+ *line = ", Not enabled!";
+ break;
+ }
- // Verify the operating mode
- if (NEQ_RTK_MODE(tcpServerMode))
+ // Determine if the TCP server should be running
+ if ((EQ_RTK_MODE(tcpServerMode) && settings.enableTcpServer))
+ {
+ // TCP server running in Rover mode
+ name = "TCP Server";
+ casterMode = false;
+ port = settings.tcpServerPort;
+ softAP = false;
+ }
+
+ // Determine if the base caster should be running
+ else if (EQ_RTK_MODE(baseCasterMode)
+ && (settings.enableNtripCaster || settings.baseCasterOverride))
+ {
+ // TCP server running in caster mode
+ casterMode = true;
+
+ // Select the base caster WiFi mode and port number
+ if (settings.baseCasterOverride || (settings.tcpOverWiFiStation == false))
+ {
+ // Using soft AP
+ name = "Base Caster";
+ port = 2101;
+ softAP = true;
+ }
+ else
+ {
+ name = "NTRIP Caster";
+ // Using WiFi station
+ port = settings.tcpServerPort;
+ softAP = false;
+ }
+ }
+
+ // Wrong mode for TCP server or base caster operation
+ else
{
*line = ", Wrong mode!";
break;
}
- // Verify still enabled
- enabled = settings.enableTcpServer || settings.baseCasterOverride;
- if (enabled == false)
- *line = ", Not enabled!";
+ // Only change modes when in off state
+ if (tcpServerState == TCP_SERVER_STATE_OFF)
+ {
+ // Update the TCP server configuration
+ tcpServerName = name;
+ tcpServerInCasterMode = casterMode;
+ tcpServerPort = port;
+ tcpServerWiFiSoftAp = softAP;
+ }
+
+ // Shutdown and restart the TCP server when configuration changes
+ else if ((name != tcpServerName)
+ || (casterMode != tcpServerInCasterMode)
+ || (port != tcpServerPort)
+ || (softAP != tcpServerWiFiSoftAp))
+ {
+ *line = ", Wrong state to switch configuration!";
+ break;
+ }
+
+ // The server is enabled and in the correct mode
+ *line = "";
+ enabled = true;
} while (0);
return enabled;
}
@@ -223,7 +296,7 @@ int32_t tcpServerSendData(uint16_t dataHead)
tail = tcpServerClientTails[index];
// Determine if the client is connected
- if (!(tcpServerClientConnected & (1 << index)))
+ if ((tcpServerClientSendingData & (1 << index)) == 0)
tail = dataHead;
else
{
@@ -256,6 +329,8 @@ int32_t tcpServerSendData(uint16_t dataHead)
}
tcpServerClientTails[index] = tail;
}
+ if (PERIODIC_DISPLAY(PD_TCP_SERVER_CLIENT_DATA))
+ PERIODIC_CLEAR(PD_TCP_SERVER_CLIENT_DATA);
// Return the amount of space that TCP server client is using in the buffer
return usedSpace;
@@ -265,6 +340,168 @@ int32_t tcpServerSendData(uint16_t dataHead)
// TCP Server Routines
//----------------------------------------
+//----------------------------------------
+// Update the TCP server client state
+//----------------------------------------
+void tcpServerClientUpdate(uint8_t index)
+{
+ bool clientConnected;
+ bool dataSent;
+ char response[512];
+ int spot;
+
+ // Determine if the client data structure is in use
+ while (tcpServerClientConnected & (1 << index))
+ {
+ // The client data structure is in use
+ // Check for a working TCP server client connection
+ clientConnected = tcpServerClient[index]->connected();
+ dataSent = ((millis() - tcpServerClientTimer[index]) < TCP_SERVER_CLIENT_DATA_TIMEOUT)
+ || (tcpServerClientDataSent & (1 << index));
+ if ((clientConnected && dataSent) == false)
+ {
+ // Broken connection, shutdown the TCP server client link
+ tcpServerStopClient(index);
+ break;
+ }
+
+ // Periodically display this client connection
+ if (PERIODIC_DISPLAY(PD_TCP_SERVER_DATA) && (!inMainMenu))
+ systemPrintf("%s client %d connected to %s\r\n",
+ tcpServerName, index,
+ tcpServerClientIpAddress[index].toString().c_str());
+
+ // Process the client state
+ switch (tcpServerClientState[index])
+ {
+ // Wait until the request is received from the NTRIP client
+ case TCP_SERVER_CLIENT_WAIT_REQUEST:
+ if (tcpServerClient[index]->available())
+ {
+ // Indicate that data was received
+ tcpServerClientDataSent = tcpServerClientDataSent | (1 << index);
+ tcpServerClientTimer[index] = millis();
+ tcpServerClientState[index] = TCP_SERVER_CLIENT_GET_REQUEST;
+ }
+ break;
+
+ // Process the request from the NTRIP client
+ case TCP_SERVER_CLIENT_GET_REQUEST:
+ // Read response from client
+ spot = 0;
+ while (tcpServerClient[index]->available())
+ {
+ response[spot++] = tcpServerClient[index]->read();
+ if (spot == sizeof(response))
+ spot = 0; // Wrap
+ }
+ response[spot] = '\0'; // Terminate string
+
+ // Handle the mount point table request
+ if (strnstr(response, "GET / ", sizeof(response)) != NULL) // No mount point in header
+ {
+ if (settings.debugTcpServer)
+ systemPrintln("Mount point table requested.");
+
+ // Respond with a single mountpoint
+ const char fakeSourceTable[] =
+ "SOURCETABLE 200 OK\r\nServer: SparkPNT Caster/1.0\r\nContent-Type: "
+ "text/plain\r\nContent-Length: 96\r\n\r\nSTR;SparkBase;none;RTCM "
+ "3.0;none;none;none;none;none;none;none;none;none;none;none;B;N;none;none";
+
+ tcpServerClient[index]->write(fakeSourceTable, strlen(fakeSourceTable));
+
+ // Disconnect from client
+ tcpServerStopClient(index);
+ }
+
+ // Check for unknown request
+ else if (strnstr(response, "GET /", sizeof(response)) == NULL)
+ {
+ // Unknown response
+ if (settings.debugTcpServer)
+ systemPrintf("Unknown response: %s\r\n", response);
+
+ // Disconnect from client
+ tcpServerStopClient(index);
+ }
+
+ // Handle the mount point request, ignore the mount point and start sending data
+ else
+ {
+ // NTRIP Client is sending us their mount point. Begin sending RTCM.
+ if (settings.debugTcpServer)
+ systemPrintln("NTRIP Client connected - Sending ICY 200 OK");
+
+ // Successfully connected to the mount point
+ char confirmConnection[] = "ICY 200 OK\r\n";
+ tcpServerClient[index]->write(confirmConnection, strlen(confirmConnection));
+
+ // Start sending RTCM
+ tcpServerClientSendingData = tcpServerClientSendingData | (1 << index);
+ tcpServerClientState[index] = TCP_SERVER_CLIENT_SENDING_DATA;
+ }
+ break;
+
+ case TCP_SERVER_CLIENT_SENDING_DATA:
+ break;
+ }
+ break;
+ }
+
+ // Determine if the client data structure is not in use
+ while ((tcpServerClientConnected & (1 << index)) == 0)
+ {
+ // Data structure not in use
+ if(tcpServerClient[index] == nullptr)
+ {
+ tcpServerClient[index] = new NetworkClient;
+
+ // Check for allocation failure
+ if(tcpServerClient[index] == nullptr)
+ {
+ if (settings.debugTcpServer)
+ Serial.printf("ERROR: Failed to allocate %s client!\r\n", tcpServerName);
+ break;
+ }
+ }
+
+ // Check for another incoming TCP server client connection request
+ *tcpServerClient[index] = tcpServer->accept();
+
+ // Exit if no TCP server client found
+ if (!*tcpServerClient[index])
+ break;
+
+ // Get the remote IP address
+ tcpServerClientIpAddress[index] = tcpServerClient[index]->remoteIP();
+
+ // Display the connection
+ if ((settings.debugTcpServer || PERIODIC_DISPLAY(PD_TCP_SERVER_DATA)) && (!inMainMenu))
+ systemPrintf("%s client %d connected to %s\r\n",
+ tcpServerName, index,
+ tcpServerClientIpAddress[index].toString().c_str());
+
+ // Mark this client as connected
+ tcpServerClientConnected = tcpServerClientConnected | (1 << index);
+
+ // Start the data timer
+ tcpServerClientTimer[index] = millis();
+ tcpServerClientDataSent = tcpServerClientDataSent | (1 << index);
+
+ // Set the client state
+ if (tcpServerInCasterMode)
+ tcpServerClientState[index] = TCP_SERVER_CLIENT_WAIT_REQUEST;
+ else
+ {
+ // Make client online after any NTRIP injections so ring buffer can start outputting data to it
+ tcpServerClientSendingData = tcpServerClientSendingData | (1 << index);
+ tcpServerClientState[index] = TCP_SERVER_CLIENT_SENDING_DATA;
+ }
+ break;
+ }
+}
+
//----------------------------------------
// Update the state of the TCP server state machine
//----------------------------------------
@@ -282,7 +519,7 @@ void tcpServerSetState(uint8_t newState)
{
if (newState >= TCP_SERVER_STATE_MAX)
{
- systemPrintf("Unknown TCP Server state: %d\r\n", tcpServerState);
+ systemPrintf("Unknown %s state: %d\r\n", tcpServerName, tcpServerState);
reportFatalError("Unknown TCP Server state");
}
else
@@ -298,14 +535,10 @@ bool tcpServerStart()
IPAddress localIp;
if (settings.debugTcpServer && (!inMainMenu))
- systemPrintln("TCP server starting the server");
-
- uint16_t tcpPort = settings.tcpServerPort;
- if(settings.baseCasterOverride == true)
- tcpPort = 2101;
+ systemPrintf("%s starting the server\r\n", tcpServerName);
// Start the TCP server
- tcpServer = new NetworkServer(tcpPort, TCP_SERVER_MAX_CLIENTS);
+ tcpServer = new NetworkServer(tcpServerPort, TCP_SERVER_MAX_CLIENTS);
if (!tcpServer)
return false;
@@ -313,12 +546,8 @@ bool tcpServerStart()
online.tcpServer = true;
localIp = networkGetIpAddress();
- if (settings.enableNtripCaster || settings.baseCasterOverride)
- systemPrintf("TCP server online, IP address %s:%d, responding as NTRIP Caster\r\n", localIp.toString().c_str(),
- tcpPort);
- else
- systemPrintf("TCP server online, IP address %s:%d\r\n", localIp.toString().c_str(), tcpPort);
-
+ systemPrintf("%s online, IP address %s:%d\r\n", tcpServerName,
+ localIp.toString().c_str(), tcpServerPort);
return true;
}
@@ -333,7 +562,8 @@ void tcpServerStop()
if (online.tcpServer)
{
if (settings.debugTcpServer && (!inMainMenu))
- systemPrintf("TcpServer: Notifying GNSS UART task to stop sending data\r\n");
+ systemPrintf("%s: Notifying GNSS UART task to stop sending data\r\n",
+ tcpServerName);
// Notify the GNSS UART tasks of the TCP server shutdown
online.tcpServer = false;
@@ -353,7 +583,7 @@ void tcpServerStop()
{
// Stop the TCP server
if (settings.debugTcpServer && (!inMainMenu))
- systemPrintln("TcpServer: Stopping the server");
+ systemPrintf("%s: Stopping the server\r\n", tcpServerName);
tcpServer->stop();
delete tcpServer;
tcpServer = nullptr;
@@ -361,7 +591,7 @@ void tcpServerStop()
// Stop using the network
if (settings.debugTcpServer && (!inMainMenu))
- systemPrintln("TcpServer: Stopping network consumers");
+ systemPrintf("%s: Stopping network consumers\r\n", tcpServerName);
networkConsumerOffline(NETCONSUMER_TCP_SERVER);
if (tcpServerState != TCP_SERVER_STATE_OFF)
{
@@ -382,24 +612,28 @@ void tcpServerStopClient(int index)
bool connected;
bool dataSent;
+ // Stop sending data
+ tcpServerClientSendingData = tcpServerClientSendingData & ~(1 << index);
+
// Determine if a client was allocated
if (tcpServerClient[index])
{
// Done with this client connection
if ((settings.debugTcpServer || PERIODIC_DISPLAY(PD_TCP_SERVER_DATA)) && (!inMainMenu))
{
- PERIODIC_CLEAR(PD_TCP_SERVER_DATA);
-
// Determine the shutdown reason
connected = tcpServerClient[index]->connected()
&& (!(tcpServerClientWriteError & (1 << index)));
- dataSent = ((millis() - tcpServerTimer) < TCP_SERVER_CLIENT_DATA_TIMEOUT)
+ dataSent = ((millis() - tcpServerClientTimer[index]) < TCP_SERVER_CLIENT_DATA_TIMEOUT)
|| (tcpServerClientDataSent & (1 << index));
if (!dataSent)
- systemPrintf("TCP Server: No data sent over %d seconds\r\n", TCP_SERVER_CLIENT_DATA_TIMEOUT / 1000);
+ systemPrintf("%s: No data sent over %d seconds\r\n",
+ tcpServerName,
+ TCP_SERVER_CLIENT_DATA_TIMEOUT / 1000);
if (!connected)
- systemPrintf("TCP Server: Link to client broken\r\n");
- systemPrintf("TCP server client %d disconnected from %s\r\n", index,
+ systemPrintf("%s: Link to client broken\r\n", tcpServerName);
+ systemPrintf("%s client %d disconnected from %s\r\n",
+ tcpServerName, index,
tcpServerClientIpAddress[index].toString().c_str());
}
@@ -417,9 +651,7 @@ void tcpServerStopClient(int index)
//----------------------------------------
void tcpServerUpdate()
{
- bool clientConnected;
bool connected;
- bool dataSent;
bool enabled;
int index;
IPAddress ipAddress;
@@ -427,7 +659,8 @@ void tcpServerUpdate()
// Shutdown the TCP server when the mode or setting changes
DMW_st(tcpServerSetState, tcpServerState);
- connected = networkConsumerIsConnected(NETCONSUMER_TCP_SERVER);
+ connected = networkConsumerIsConnected(NETCONSUMER_TCP_SERVER)
+ || (tcpServerWiFiSoftAp && wifiSoftApOnline);
enabled = tcpServerEnabled(&line);
if ((tcpServerState > TCP_SERVER_STATE_OFF) && !enabled)
tcpServerStop();
@@ -464,11 +697,11 @@ void tcpServerUpdate()
if (enabled)
{
if (settings.debugTcpServer && (!inMainMenu))
- systemPrintln("TCP server start");
- if (settings.tcpUdpOverWiFiStation == true)
- networkConsumerAdd(NETCONSUMER_TCP_SERVER, NETWORK_ANY, __FILE__, __LINE__);
- else
+ systemPrintf("%s start/r/n", tcpServerName);
+ if (tcpServerWiFiSoftAp)
networkSoftApConsumerAdd(NETCONSUMER_TCP_SERVER, __FILE__, __LINE__);
+ else
+ networkConsumerAdd(NETCONSUMER_TCP_SERVER, NETWORK_ANY, __FILE__, __LINE__);
tcpServerSetState(TCP_SERVER_STATE_WAIT_FOR_NETWORK);
}
break;
@@ -476,7 +709,7 @@ void tcpServerUpdate()
// Wait until the network is connected
case TCP_SERVER_STATE_WAIT_FOR_NETWORK:
// Wait until the network is connected to the media
- if (connected || wifiSoftApOnline)
+ if (connected)
{
// Delay before starting the TCP server
if ((millis() - tcpServerTimer) >= (1 * 1000))
@@ -488,6 +721,8 @@ void tcpServerUpdate()
if (tcpServerStart())
{
networkUserAdd(NETCONSUMER_TCP_SERVER, __FILE__, __LINE__);
+ for (index = 0; index < TCP_SERVER_MAX_CLIENTS; index++)
+ tcpServerClientState[index] = TCP_SERVER_CLIENT_OFF;
tcpServerSetState(TCP_SERVER_STATE_RUNNING);
}
}
@@ -497,142 +732,22 @@ void tcpServerUpdate()
// Handle client connections and link failures
case TCP_SERVER_STATE_RUNNING:
// Determine if the network has failed
- if ((connected == false && wifiSoftApOnline == false) || (!settings.enableTcpServer && !settings.baseCasterOverride))
+ if (connected == false)
{
if ((settings.debugTcpServer || PERIODIC_DISPLAY(PD_TCP_SERVER_DATA)) && (!inMainMenu))
- {
- PERIODIC_CLEAR(PD_TCP_SERVER_DATA);
- systemPrintln("TCP server initiating shutdown");
- }
+ systemPrintf("%s initiating shutdown\r\n", tcpServerName);
// Network connection failed, attempt to restart the network
tcpServerStop();
+ if (PERIODIC_DISPLAY(PD_TCP_SERVER_DATA))
+ PERIODIC_CLEAR(PD_TCP_SERVER_DATA);
break;
}
// Walk the list of TCP server clients
for (index = 0; index < TCP_SERVER_MAX_CLIENTS; index++)
- {
- // Determine if the client data structure is in use
- if (tcpServerClientConnected & (1 << index))
- {
- // Data structure in use
- // Check for a working TCP server client connection
- clientConnected = tcpServerClient[index]->connected();
- dataSent = ((millis() - tcpServerTimer) < TCP_SERVER_CLIENT_DATA_TIMEOUT) ||
- (tcpServerClientDataSent & (1 << index));
- if (clientConnected && dataSent)
- {
- // Display this client connection
- if (PERIODIC_DISPLAY(PD_TCP_SERVER_DATA) && (!inMainMenu))
- {
- PERIODIC_CLEAR(PD_TCP_SERVER_DATA);
- systemPrintf("TCP server client %d connected to %s\r\n", index,
- tcpServerClientIpAddress[index].toString().c_str());
- }
- }
-
- // Shutdown the TCP server client link
- else
- tcpServerStopClient(index);
- }
- }
-
- // Walk the list of TCP server clients
- for (index = 0; index < TCP_SERVER_MAX_CLIENTS; index++)
- {
- // Determine if the client data structure is in use
- if (!(tcpServerClientConnected & (1 << index)))
- {
- if(tcpServerClient[index] == nullptr)
- tcpServerClient[index] = new NetworkClient;
-
- // Data structure not in use
- // Check for another TCP server client
- *tcpServerClient[index] = tcpServer->accept();
-
- // Exit if no TCP server client found
- if (! *tcpServerClient[index])
- break;
-
- // Start processing the new TCP server client connection
- tcpServerClientIpAddress[index] = tcpServerClient[index]->remoteIP();
-
- if ((settings.debugTcpServer || PERIODIC_DISPLAY(PD_TCP_SERVER_DATA)) && (!inMainMenu))
- {
- PERIODIC_CLEAR(PD_TCP_SERVER_DATA);
- systemPrintf("TCP server client %d connected to %s\r\n", index,
- tcpServerClientIpAddress[index].toString().c_str());
- }
-
- // If we are acting as an NTRIP Caster, intercept the initial communication from the client
- // and respond accordingly
- if (settings.enableNtripCaster || settings.baseCasterOverride)
- {
- // Use a semaphore to prevent tcpServerClientSendData from gatecrashing
- if (tcpServerSemaphore == NULL)
- tcpServerSemaphore = xSemaphoreCreateMutex(); // Create the mutex
-
- // Take the semaphore
- if (xSemaphoreTake(tcpServerSemaphore, 50 / portTICK_PERIOD_MS) == pdPASS)
- {
- tcpServerSemaphoreHolder = "tcpServerUpdate";
-
- // Read response from client
- char response[512];
- int spot = 0;
- while (tcpServerClient[index]->available())
- {
- response[spot++] = tcpServerClient[index]->read();
- if (spot == sizeof(response))
- spot = 0; // Wrap
- }
- response[spot] = '\0'; // Terminate string
-
- if (strnstr(response, "GET / ", sizeof(response)) != NULL) // No mount point in header
- {
- if (settings.debugTcpServer)
- systemPrintln("Mount point table requested.");
-
- // Respond with a single mountpoint
- const char fakeSourceTable[] =
- "SOURCETABLE 200 OK\r\nServer: SparkPNT Caster/1.0\r\nContent-Type: "
- "text/plain\r\nContent-Length: 96\r\n\r\nSTR;SparkBase;none;RTCM "
- "3.0;none;none;none;none;none;none;none;none;none;none;none;B;N;none;none";
-
- tcpServerClient[index]->write(fakeSourceTable, strlen(fakeSourceTable));
-
- tcpServerStopClient(index); // Disconnect from client
- }
- else if (strnstr(response, "GET /", sizeof(response)) != NULL) // Mount point in header
- {
- // NTRIP Client is sending us their mount point. Begin sending RTCM.
- if (settings.debugTcpServer)
- systemPrintln("NTRIP Client connected - Sending ICY 200 OK");
-
- char confirmConnection[] = "ICY 200 OK\r\n";
- tcpServerClient[index]->write(confirmConnection, strlen(confirmConnection));
- }
- else
- {
- // Unknown response
- if (settings.debugTcpServer)
- systemPrintf("Unknown response: %s\r\n", response);
- }
-
- xSemaphoreGive(tcpServerSemaphore);
- }
- else
- {
- systemPrintf("tcpServerUpdate could not get semaphore - held by %s\r\n", tcpServerSemaphoreHolder);
- }
- } // settings.enableNtripCaster == true || settings.baseCasterOverride == true
-
- // Make client online after any NTRIP injections so ring buffer can start outputting data to it
- tcpServerClientConnected = tcpServerClientConnected | (1 << index);
- tcpServerClientDataSent = tcpServerClientDataSent | (1 << index);
- }
- }
+ tcpServerClientUpdate(index);
+ PERIODIC_CLEAR(PD_TCP_SERVER_DATA);
// Check for data moving across the connections
if ((millis() - tcpServerTimer) >= TCP_SERVER_CLIENT_DATA_TIMEOUT)
@@ -647,7 +762,7 @@ void tcpServerUpdate()
// Periodically display the TCP state
if (PERIODIC_DISPLAY(PD_TCP_SERVER_STATE) && (!inMainMenu))
{
- systemPrintf("TCP Server state: %s%s\r\n",
+ systemPrintf("%s state: %s%s\r\n", tcpServerName,
tcpServerStateName[tcpServerState], line);
PERIODIC_CLEAR(PD_TCP_SERVER_STATE);
}
@@ -668,8 +783,12 @@ void tcpServerValidateTables()
sizeof(tcpServerClientConnected) * 8);
reportFatalError(line);
}
+
+ // Verify the state name tables
if (tcpServerStateNameEntries != TCP_SERVER_STATE_MAX)
reportFatalError("Fix tcpServerStateNameEntries to match tcpServerStates");
+ if (tcpServerClientStateNameEntries != TCP_SERVER_CLIENT_MAX)
+ reportFatalError("Fix tcpServerClientStateNameEntries to match tcpServerClientStates");
}
//----------------------------------------
diff --git a/Firmware/RTK_Everywhere/menuCommands.ino b/Firmware/RTK_Everywhere/menuCommands.ino
index f7927d72f..bc5422349 100644
--- a/Firmware/RTK_Everywhere/menuCommands.ino
+++ b/Firmware/RTK_Everywhere/menuCommands.ino
@@ -1968,10 +1968,10 @@ void createSettingsString(char *newSettings)
else
stringRecord(newSettings, "wifiConfigOverAP", 0); // 1 = AP mode, 0 = WiFi
- if (settings.tcpUdpOverWiFiStation == true)
- stringRecord(newSettings, "tcpUdpOverWiFiStation", 1); // 1 = WiFi mode, 0 = AP
+ if (settings.tcpOverWiFiStation == true)
+ stringRecord(newSettings, "tcpOverWiFiStation", 1); // 1 = WiFi mode, 0 = AP
else
- stringRecord(newSettings, "tcpUdpOverWiFiStation", 0); // 1 = WiFi mode, 0 = AP
+ stringRecord(newSettings, "tcpOverWiFiStation", 0); // 1 = WiFi mode, 0 = AP
if (settings.udpOverWiFiStation == true)
stringRecord(newSettings, "udpOverWiFiStation", 1); // 1 = WiFi mode, 0 = AP
diff --git a/Firmware/RTK_Everywhere/settings.h b/Firmware/RTK_Everywhere/settings.h
index d0d1ee180..623e44244 100644
--- a/Firmware/RTK_Everywhere/settings.h
+++ b/Firmware/RTK_Everywhere/settings.h
@@ -938,7 +938,7 @@ struct Settings
bool debugTcpServer = false;
bool enableTcpServer = false;
uint16_t tcpServerPort = 2948; // TCP server port, 2948 is GPS Daemon: http://tcp-udp-ports.com/port-2948.htm
- bool tcpUdpOverWiFiStation = true; // Controls if TCP/UDP settings should use Station or AP
+ bool tcpOverWiFiStation = true; // Should TCP server use Station (true) or AP (false)
bool udpOverWiFiStation = true; // Should UDP server use Station (true) or AP (false)
// Time Zone - Default to UTC
@@ -1586,7 +1586,7 @@ const RTK_Settings_Entry rtkSettingsEntries[] =
{ 0, 0, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.debugTcpServer, "debugTcpServer", },
{ 1, 1, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.enableTcpServer, "enableTcpServer", },
{ 1, 1, 0, 1, 1, 1, 1, 1, 1, _uint16_t, 0, & settings.tcpServerPort, "tcpServerPort", },
- { 1, 1, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.tcpUdpOverWiFiStation, "tcpUdpOverWiFiStation", },
+ { 1, 1, 0, 1, 1, 1, 1, 1, 1, _bool, 0, & settings.tcpOverWiFiStation, "tcpOverWiFiStation", },
// Time Zone
{ 0, 1, 0, 1, 1, 1, 1, 1, 1, _int8_t, 0, & settings.timeZoneHours, "timeZoneHours", },