Client/Server data setup working!
This commit is contained in:
parent
d7dcd43c5f
commit
5a840ab1bf
8 changed files with 96 additions and 39 deletions
|
@ -260,12 +260,16 @@ int main(int argc, char *argv[]) {
|
|||
sh_new_strdup(__runtimeData.integers);
|
||||
sh_new_strdup(__runtimeData.strings);
|
||||
|
||||
// ***TODO*** Load tables from disk cache
|
||||
|
||||
//taskCreate(taskComDebugLoop, NULL);
|
||||
taskCreate(taskWelcome, NULL);
|
||||
taskCreate(taskGuiEventLoop, NULL);
|
||||
|
||||
taskRun();
|
||||
|
||||
// ***TODO*** Write tables from disk cache
|
||||
|
||||
// Free integer table.
|
||||
if (__runtimeData.integers) {
|
||||
while (shlen(__runtimeData.integers) > 0) {
|
||||
|
|
|
@ -85,39 +85,42 @@ void taskNetwork(void *data) {
|
|||
|
||||
do {
|
||||
|
||||
//***TODO*** Detect disconnection. Maybe have callbacks registered that can notify tasks?
|
||||
// ***TODO*** Detect disconnection. Maybe have callbacks registered that can notify tasks?
|
||||
|
||||
// Read pending bytes.
|
||||
r = comRead(__configData.serialCom - 1, buffer, 1024);
|
||||
if (r > 0) {
|
||||
// Decode them into packets.
|
||||
if (packetDecode(__packetThreadData, &decoded, buffer, r)) {
|
||||
// Is this a PONG? If so, ignore it.
|
||||
if (decoded.packetType == PACKET_TYPE_PONG) continue;
|
||||
|
||||
// Copy the packet out.
|
||||
NEW(PacketDecodeDataT, packet);
|
||||
packet->channel = decoded.channel;
|
||||
packet->length = decoded.length;
|
||||
packet->packetType = decoded.packetType;
|
||||
packet->data = (char *)malloc(decoded.length);
|
||||
memcpy(packet->data, decoded.data, decoded.length);
|
||||
|
||||
// Is there a list of packets for this channel already?
|
||||
r = hmgeti(_packets, packet->channel);
|
||||
if (r < 0) {
|
||||
// No. Create dynamic array for this channel.
|
||||
hmput(_packets, packet->channel, NULL);
|
||||
r = hmgeti(_packets, packet->channel);
|
||||
}
|
||||
// Add new packet to existing list.
|
||||
arrput(_packets[r].value, packet);
|
||||
// New data or not, process anything in the queue.
|
||||
if (packetDecode(__packetThreadData, &decoded, buffer, r)) {
|
||||
// Is this a PONG? If so, ignore it.
|
||||
if (decoded.packetType == PACKET_TYPE_PONG) {
|
||||
packetDecodeDataStaticDestroy(&decoded);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// No bytes pending, yield to UI.
|
||||
taskYield();
|
||||
|
||||
// Copy the packet out.
|
||||
NEW(PacketDecodeDataT, packet);
|
||||
packet->channel = decoded.channel;
|
||||
packet->length = decoded.length;
|
||||
packet->packetType = decoded.packetType;
|
||||
packet->data = (char *)malloc(decoded.length);
|
||||
memcpy(packet->data, decoded.data, decoded.length);
|
||||
|
||||
// Is there a list of packets for this channel already?
|
||||
r = hmgeti(_packets, packet->channel);
|
||||
if (r < 0) {
|
||||
// No. Create dynamic array for this channel.
|
||||
hmput(_packets, packet->channel, NULL);
|
||||
r = hmgeti(_packets, packet->channel);
|
||||
}
|
||||
// Add new packet to existing list.
|
||||
arrput(_packets[r].value, packet);
|
||||
|
||||
packetDecodeDataStaticDestroy(&decoded);
|
||||
}
|
||||
|
||||
// Yield to UI.
|
||||
taskYield();
|
||||
|
||||
// Send a ping to the server every 5 seconds, because, ping.
|
||||
if (__timerSecondTick) {
|
||||
pingTimeout++;
|
||||
|
|
|
@ -136,10 +136,6 @@ static void taskConnectClick(void *data) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Connected! Show icon.
|
||||
widgetVisibleSet(W(_picConnect), 1);
|
||||
taskYield();
|
||||
|
||||
// Start packet handler and negotiate encryption.
|
||||
taskCreate(taskNetwork, NULL);
|
||||
packetEncryptionSetup(__packetThreadData);
|
||||
|
@ -155,6 +151,8 @@ static void taskConnectClick(void *data) {
|
|||
return;
|
||||
}
|
||||
|
||||
// ***TODO*** Should probably cleanly handle a full server here with some kind of SERVER_FULL packet.
|
||||
|
||||
// Wait for version and table packets to arrive.
|
||||
timeout = 10;
|
||||
do {
|
||||
|
@ -170,6 +168,7 @@ static void taskConnectClick(void *data) {
|
|||
break;
|
||||
|
||||
case PACKET_TYPE_PROCEED:
|
||||
logWrite("Received PACKET_TYPE_PROCEED\n");
|
||||
waiting = 0;
|
||||
break;
|
||||
|
||||
|
@ -217,6 +216,14 @@ static void taskConnectClick(void *data) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Connected! Show icon.
|
||||
widgetVisibleSet(W(_picConnect), 1);
|
||||
timeout = 6; // Roughly 1.5 seconds.
|
||||
while (timeout > 0) {
|
||||
taskYield();
|
||||
if (__timerQuarterSecondTick) timeout--;
|
||||
}
|
||||
|
||||
// Switch to Login window.
|
||||
guiDelete(D(_winWelcome));
|
||||
taskCreate(taskLogin, NULL);
|
||||
|
|
|
@ -50,7 +50,7 @@ static uint8_t clientDequeuePacket(ClientThreadT *client) {
|
|||
// New data or not, process anything in the queue.
|
||||
if (packetDecode(client->packetThreadData, &decode, data, length)) {
|
||||
clientProcessPacket(client, &decode);
|
||||
DEL(decode.data);
|
||||
if (decode.data) DEL(decode.data);
|
||||
if (packet) {
|
||||
DEL(packet->data);
|
||||
DEL(packet);
|
||||
|
@ -257,8 +257,14 @@ void *clientThread(void *data) {
|
|||
}
|
||||
|
||||
// Clean up client data on the way out.
|
||||
while (arrlen(client->packetQueue) > 0) {
|
||||
if (client->packetQueue[0]->data) DEL(client->packetQueue[0]->data);
|
||||
arrdel(client->packetQueue, 0);
|
||||
}
|
||||
arrfree(client->packetQueue);
|
||||
pthread_mutex_destroy(&client->packetQueueMutex);
|
||||
packetThreadDataDestroy(&client->packetThreadData);
|
||||
DEL(client);
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
|
|
@ -64,7 +64,6 @@ void consoleRun(void) {
|
|||
uint8_t commandOk = 0;
|
||||
struct timespec remaining = { 0, 0 };
|
||||
struct timespec sleepTime = { 0, 1000000000/4 }; // 1/4th second
|
||||
size_t i = 0;
|
||||
|
||||
if (pthread_mutex_init(&_messageQueueMutex, NULL)) utilDie("Unable to create console message queue mutex.\n");
|
||||
|
||||
|
@ -168,8 +167,9 @@ void consoleRun(void) {
|
|||
}
|
||||
|
||||
// Anything left in the message queue?
|
||||
for (i=0; i<arrlenu(_consoleMessageQueue); i++) {
|
||||
free(_consoleMessageQueue[i]);
|
||||
while (arrlen(_consoleMessageQueue) > 0) {
|
||||
DEL(_consoleMessageQueue[0]);
|
||||
arrdel(_consoleMessageQueue, 0);
|
||||
}
|
||||
arrfree(_consoleMessageQueue);
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <pthread.h>
|
||||
|
||||
// Should be after system headers in this file.
|
||||
//#define MEMORY_CHECK_ENABLED
|
||||
#define MEMORY_CHECK_ENABLED
|
||||
#include "memory.h"
|
||||
|
||||
// Now our headers.
|
||||
|
|
|
@ -23,6 +23,24 @@
|
|||
// Encryption: https://erev0s.com/blog/tiny-aes-cbc-mode-pkcs7-padding-written-c
|
||||
|
||||
|
||||
/*
|
||||
* NOTE:
|
||||
*
|
||||
* The reliable transport / packet retry code has been commented out.
|
||||
* Structly speaking, it isn't needed. Enet handles reliable delivery
|
||||
* across the internet. The only place there can be corruption is
|
||||
* between a real serial port and the enet softmodem.
|
||||
*
|
||||
* In any case, if the code ends up being re-enabled, the sequence
|
||||
* numbers have no bounding and will run off the end of the history
|
||||
* array. Not only that, but due to the limited number of sequence
|
||||
* numbers available, there needs to be a sending queue added for
|
||||
* when the server attempts to send more packets than there are
|
||||
* history slots.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "packet.h"
|
||||
#include "primes.h"
|
||||
|
||||
|
@ -65,7 +83,7 @@ static uint8_t packetCRC(char *data, uint16_t length, uint8_t startAt) {
|
|||
|
||||
|
||||
uint8_t packetDecode(PacketThreadDataT *threadData, PacketDecodeDataT *decodeData, char *input, uint16_t inputLength) {
|
||||
uint8_t sequence = 0;
|
||||
//uint8_t sequence = 0;
|
||||
uint16_t unpadded = 0;
|
||||
int32_t x = 0;
|
||||
char c = 0;
|
||||
|
@ -107,6 +125,7 @@ uint8_t packetDecode(PacketThreadDataT *threadData, PacketDecodeDataT *decodeDat
|
|||
// Check CRC.
|
||||
if ((uint8_t)threadData->decodeBuffer[threadData->length - 1] != packetCRC(threadData->decodeBuffer, threadData->length - 1, 0)) continue;
|
||||
|
||||
/*
|
||||
// Get sequence value.
|
||||
sequence = ((uint8_t)threadData->decodeBuffer[0]) & 0x1f;
|
||||
|
||||
|
@ -151,6 +170,7 @@ uint8_t packetDecode(PacketThreadDataT *threadData, PacketDecodeDataT *decodeDat
|
|||
packetSend(threadData, &encoded);
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
// Fill decoded data fields.
|
||||
decodeData->packetType = threadData->decodeBuffer[1];
|
||||
|
@ -241,13 +261,21 @@ uint8_t packetDecode(PacketThreadDataT *threadData, PacketDecodeDataT *decodeDat
|
|||
void packetDecodeDataDestroy(PacketDecodeDataT **packet) {
|
||||
PacketDecodeDataT *d = *packet;
|
||||
|
||||
free(d->data);
|
||||
packetDecodeDataStaticDestroy(d);
|
||||
free(d);
|
||||
d = NULL;
|
||||
*packet = d;
|
||||
}
|
||||
|
||||
|
||||
void packetDecodeDataStaticDestroy(PacketDecodeDataT *packet) {
|
||||
if (packet->data) {
|
||||
free(packet->data);
|
||||
packet->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint16_t packetDHCompute(uint32_t a, uint32_t m, uint32_t n) {
|
||||
uint32_t r = 0;
|
||||
uint32_t y = 1;
|
||||
|
@ -282,9 +310,11 @@ uint8_t packetEncode(PacketThreadDataT *threadData, PacketEncodeDataT *data, cha
|
|||
data->dataPointer = NULL;
|
||||
data->length = 0;
|
||||
|
||||
/*
|
||||
if (data->control == PACKET_CONTROL_DAT) {
|
||||
data->sequence = threadData->sequence++;
|
||||
}
|
||||
*/
|
||||
|
||||
// Make needed header bytes.
|
||||
control = (((uint8_t)data->control) << 6) + (data->encrypt << 5) + (data->sequence & 0x1f);
|
||||
|
@ -387,9 +417,10 @@ void packetSend(PacketThreadDataT *threadData, PacketEncodeDataT *data) {
|
|||
logWrite("Invalid PACKET_CONTROL!\n\r");
|
||||
}
|
||||
|
||||
/*
|
||||
// Add to history?
|
||||
if (data->control == PACKET_CONTROL_DAT) {
|
||||
//***TODO*** Must change control to use CONTROL_RTX & fix framing changes
|
||||
// ***TODO*** Must change control to use CONTROL_RTX & fix framing changes
|
||||
threadData->history[threadData->historyPosition].sequence = data->sequence;
|
||||
threadData->history[threadData->historyPosition].length = data->length;
|
||||
memcpy(threadData->history[threadData->historyPosition].data, data->dataPointer, data->length);
|
||||
|
@ -398,6 +429,7 @@ void packetSend(PacketThreadDataT *threadData, PacketEncodeDataT *data) {
|
|||
threadData->historyPosition = 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Mark invalid so caller has to change it.
|
||||
data->control = PACKET_CONTROL_BAD;
|
||||
|
@ -414,9 +446,11 @@ PacketThreadDataT *packetThreadDataCreate(void *senderData) {
|
|||
|
||||
data = (PacketThreadDataT *)malloc(sizeof(PacketThreadDataT));
|
||||
if (data) {
|
||||
/*
|
||||
data->sequence = 0;
|
||||
data->lastRemoteSequence = 0;
|
||||
data->historyPosition = 0;
|
||||
*/
|
||||
data->decodeQueueHead = 0;
|
||||
data->decodeQueueTail = 0;
|
||||
data->newPacket = 1;
|
||||
|
|
|
@ -90,10 +90,12 @@ typedef struct PacketHistoryDataS {
|
|||
|
||||
typedef struct PacketThreadDataS {
|
||||
// Internal state per thread for packet processing.
|
||||
/*
|
||||
uint8_t sequence;
|
||||
uint8_t lastRemoteSequence;
|
||||
PacketHistoryDataT history[PACKET_SEQUENCE_MAX];
|
||||
uint8_t historyPosition;
|
||||
*/
|
||||
char decodeBuffer[PACKET_MAX];
|
||||
char encodeBuffer[PACKET_BUFFER_SIZE];
|
||||
char decodeQueue[PACKET_INPUT_QUEUE_SIZE];
|
||||
|
@ -119,6 +121,7 @@ typedef void (*packetSender)(char *data, uint32_t length, void *userData);
|
|||
|
||||
uint8_t packetDecode(PacketThreadDataT *threadData, PacketDecodeDataT *decodeData, char *input, uint16_t inputLength);
|
||||
void packetDecodeDataDestroy(PacketDecodeDataT **packet);
|
||||
void packetDecodeDataStaticDestroy(PacketDecodeDataT *packet);
|
||||
uint8_t packetEncode(PacketThreadDataT *threadData, PacketEncodeDataT *data, char *input, uint16_t length);
|
||||
uint8_t packetEncryptionReady(void);
|
||||
void packetEncryptionSetup(PacketThreadDataT *threadData);
|
||||
|
|
Loading…
Add table
Reference in a new issue