Skip to content

Commit b7285c3

Browse files
committed
TcpServer: Use client states to wait for and process caster request
1 parent b2963d5 commit b7285c3

File tree

1 file changed

+121
-60
lines changed

1 file changed

+121
-60
lines changed

Firmware/RTK_Everywhere/TcpServer.ino

Lines changed: 121 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,27 @@ const char *const tcpServerStateName[] = {
7979
"TCP_SERVER_STATE_WAIT_FOR_NETWORK",
8080
"TCP_SERVER_STATE_RUNNING",
8181
};
82-
8382
const int tcpServerStateNameEntries = sizeof(tcpServerStateName) / sizeof(tcpServerStateName[0]);
8483

84+
// Define the TCP server client states
85+
enum tcpServerClientStates
86+
{
87+
TCP_SERVER_CLIENT_OFF = 0,
88+
TCP_SERVER_CLIENT_WAIT_REQUEST,
89+
TCP_SERVER_CLIENT_GET_REQUEST,
90+
TCP_SERVER_CLIENT_SENDING_DATA,
91+
// Insert new states here
92+
TCP_SERVER_CLIENT_MAX // Last entry in the state list
93+
};
94+
95+
const char *const tcpServerClientStateName[] = {
96+
"TCP_SERVER_CLIENT_OFF",
97+
"TCP_SERVER_CLIENT_WAIT_REQUEST",
98+
"TCP_SERVER_CLIENT_GET_REQUEST",
99+
"TCP_SERVER_CLIENT_SENDING_DATA",
100+
};
101+
const int tcpServerClientStateNameEntries = sizeof(tcpServerClientStateName) / sizeof(tcpServerClientStateName[0]);
102+
85103
const RtkMode_t baseCasterMode = RTK_MODE_BASE_FIXED;
86104
const RtkMode_t tcpServerMode = RTK_MODE_ROVER
87105
| RTK_MODE_BASE_SURVEY_IN;
@@ -105,6 +123,7 @@ static uint32_t tcpServerClientTimer[TCP_SERVER_MAX_CLIENTS];
105123
static volatile uint8_t tcpServerClientWriteError;
106124
static NetworkClient *tcpServerClient[TCP_SERVER_MAX_CLIENTS];
107125
static IPAddress tcpServerClientIpAddress[TCP_SERVER_MAX_CLIENTS];
126+
static uint8_t tcpServerClientState[TCP_SERVER_MAX_CLIENTS];
108127
static volatile RING_BUFFER_OFFSET tcpServerClientTails[TCP_SERVER_MAX_CLIENTS];
109128

110129
//----------------------------------------
@@ -350,83 +369,119 @@ void tcpServerClientUpdate(uint8_t index)
350369
systemPrintf("%s client %d connected to %s\r\n",
351370
tcpServerName, index,
352371
tcpServerClientIpAddress[index].toString().c_str());
372+
373+
// Process the client state
374+
switch (tcpServerClientState[index])
375+
{
376+
// Wait until the request is received from the NTRIP client
377+
case TCP_SERVER_CLIENT_WAIT_REQUEST:
378+
if (tcpServerClient[index]->available())
379+
{
380+
// Indicate that data was received
381+
tcpServerClientDataSent = tcpServerClientDataSent | (1 << index);
382+
tcpServerClientTimer[index] = millis();
383+
tcpServerClientState[index] = TCP_SERVER_CLIENT_GET_REQUEST;
384+
}
385+
break;
386+
387+
// Process the request from the NTRIP client
388+
case TCP_SERVER_CLIENT_GET_REQUEST:
389+
// Read response from client
390+
spot = 0;
391+
while (tcpServerClient[index]->available())
392+
{
393+
response[spot++] = tcpServerClient[index]->read();
394+
if (spot == sizeof(response))
395+
spot = 0; // Wrap
396+
}
397+
response[spot] = '\0'; // Terminate string
398+
399+
// Handle the mount point table request
400+
if (strnstr(response, "GET / ", sizeof(response)) != NULL) // No mount point in header
401+
{
402+
if (settings.debugTcpServer)
403+
systemPrintln("Mount point table requested.");
404+
405+
// Respond with a single mountpoint
406+
const char fakeSourceTable[] =
407+
"SOURCETABLE 200 OK\r\nServer: SparkPNT Caster/1.0\r\nContent-Type: "
408+
"text/plain\r\nContent-Length: 96\r\n\r\nSTR;SparkBase;none;RTCM "
409+
"3.0;none;none;none;none;none;none;none;none;none;none;none;B;N;none;none";
410+
411+
tcpServerClient[index]->write(fakeSourceTable, strlen(fakeSourceTable));
412+
413+
// Disconnect from client
414+
tcpServerStopClient(index);
415+
}
416+
417+
// Check for unknown request
418+
else if (strnstr(response, "GET /", sizeof(response)) == NULL)
419+
{
420+
// Unknown response
421+
if (settings.debugTcpServer)
422+
systemPrintf("Unknown response: %s\r\n", response);
423+
424+
// Disconnect from client
425+
tcpServerStopClient(index);
426+
}
427+
428+
// Handle the mount point request, ignore the mount point and start sending data
429+
else
430+
{
431+
// NTRIP Client is sending us their mount point. Begin sending RTCM.
432+
if (settings.debugTcpServer)
433+
systemPrintln("NTRIP Client connected - Sending ICY 200 OK");
434+
435+
// Successfully connected to the mount point
436+
char confirmConnection[] = "ICY 200 OK\r\n";
437+
tcpServerClient[index]->write(confirmConnection, strlen(confirmConnection));
438+
439+
// Start sending RTCM
440+
tcpServerClientState[index] = TCP_SERVER_CLIENT_SENDING_DATA;
441+
}
442+
break;
443+
444+
case TCP_SERVER_CLIENT_SENDING_DATA:
445+
break;
446+
}
353447
break;
354448
}
355449

356450
// Determine if the client data structure is not in use
357451
while ((tcpServerClientConnected & (1 << index)) == 0)
358452
{
453+
// Data structure not in use
359454
if(tcpServerClient[index] == nullptr)
360455
tcpServerClient[index] = new NetworkClient;
361456

362-
// Data structure not in use
363457
// Check for another TCP server client
364458
*tcpServerClient[index] = tcpServer->accept();
365459

366460
// Exit if no TCP server client found
367-
if (*tcpServerClient[index])
368-
{
369-
// TCP server client found
370-
// Start processing the new TCP server client connection
371-
tcpServerClientIpAddress[index] = tcpServerClient[index]->remoteIP();
372-
if ((settings.debugTcpServer || PERIODIC_DISPLAY(PD_TCP_SERVER_DATA)) && (!inMainMenu))
373-
systemPrintf("%s client %d connected to %s\r\n",
374-
tcpServerName, index,
375-
tcpServerClientIpAddress[index].toString().c_str());
376-
377-
// If we are acting as an NTRIP Caster, intercept the initial communication from the client
378-
// and respond accordingly
379-
if (tcpServerInCasterMode)
380-
{
381-
// Read response from client
382-
spot = 0;
383-
while (tcpServerClient[index]->available())
384-
{
385-
response[spot++] = tcpServerClient[index]->read();
386-
if (spot == sizeof(response))
387-
spot = 0; // Wrap
388-
}
389-
response[spot] = '\0'; // Terminate string
390-
391-
if (strnstr(response, "GET / ", sizeof(response)) != NULL) // No mount point in header
392-
{
393-
if (settings.debugTcpServer)
394-
systemPrintln("Mount point table requested.");
395-
396-
// Respond with a single mountpoint
397-
const char fakeSourceTable[] =
398-
"SOURCETABLE 200 OK\r\nServer: SparkPNT Caster/1.0\r\nContent-Type: "
399-
"text/plain\r\nContent-Length: 96\r\n\r\nSTR;SparkBase;none;RTCM "
400-
"3.0;none;none;none;none;none;none;none;none;none;none;none;B;N;none;none";
401-
402-
tcpServerClient[index]->write(fakeSourceTable, strlen(fakeSourceTable));
461+
if (!*tcpServerClient[index])
462+
break;
403463

404-
tcpServerStopClient(index); // Disconnect from client
405-
}
406-
else if (strnstr(response, "GET /", sizeof(response)) != NULL) // Mount point in header
407-
{
408-
// NTRIP Client is sending us their mount point. Begin sending RTCM.
409-
if (settings.debugTcpServer)
410-
systemPrintln("NTRIP Client connected - Sending ICY 200 OK");
464+
// TCP server client found
465+
// Start processing the new TCP server client connection
466+
tcpServerClientIpAddress[index] = tcpServerClient[index]->remoteIP();
467+
if ((settings.debugTcpServer || PERIODIC_DISPLAY(PD_TCP_SERVER_DATA)) && (!inMainMenu))
468+
systemPrintf("%s client %d connected to %s\r\n",
469+
tcpServerName, index,
470+
tcpServerClientIpAddress[index].toString().c_str());
411471

412-
char confirmConnection[] = "ICY 200 OK\r\n";
413-
tcpServerClient[index]->write(confirmConnection, strlen(confirmConnection));
414-
}
415-
else
416-
{
417-
// Unknown response
418-
if (settings.debugTcpServer)
419-
systemPrintf("Unknown response: %s\r\n", response);
420-
}
421-
} // tcpServerInCasterMode
472+
// Mark this client as connected
473+
tcpServerClientConnected = tcpServerClientConnected | (1 << index);
422474

423-
// Start the data timer
424-
tcpServerClientTimer[index] = millis();
475+
// Start the data timer
476+
tcpServerClientTimer[index] = millis();
477+
tcpServerClientDataSent = tcpServerClientDataSent | (1 << index);
425478

479+
// Set the client state
480+
if (tcpServerInCasterMode)
481+
tcpServerClientState[index] = TCP_SERVER_CLIENT_WAIT_REQUEST;
482+
else
426483
// Make client online after any NTRIP injections so ring buffer can start outputting data to it
427-
tcpServerClientConnected = tcpServerClientConnected | (1 << index);
428-
tcpServerClientDataSent = tcpServerClientDataSent | (1 << index);
429-
}
484+
tcpServerClientState[index] = TCP_SERVER_CLIENT_SENDING_DATA;
430485
break;
431486
}
432487
}
@@ -647,6 +702,8 @@ void tcpServerUpdate()
647702
if (tcpServerStart())
648703
{
649704
networkUserAdd(NETCONSUMER_TCP_SERVER, __FILE__, __LINE__);
705+
for (index = 0; index < TCP_SERVER_MAX_CLIENTS; index++)
706+
tcpServerClientState[index] = TCP_SERVER_CLIENT_OFF;
650707
tcpServerSetState(TCP_SERVER_STATE_RUNNING);
651708
}
652709
}
@@ -707,8 +764,12 @@ void tcpServerValidateTables()
707764
sizeof(tcpServerClientConnected) * 8);
708765
reportFatalError(line);
709766
}
767+
768+
// Verify the state name tables
710769
if (tcpServerStateNameEntries != TCP_SERVER_STATE_MAX)
711770
reportFatalError("Fix tcpServerStateNameEntries to match tcpServerStates");
771+
if (tcpServerClientStateNameEntries != TCP_SERVER_CLIENT_MAX)
772+
reportFatalError("Fix tcpServerClientStateNameEntries to match tcpServerClientStates");
712773
}
713774

714775
//----------------------------------------

0 commit comments

Comments
 (0)