Tons of bugs fixed. Derp.

This commit is contained in:
Scott Duensing 2022-04-04 20:20:09 -05:00
parent 4f3a73bf12
commit 61ab16512f
16 changed files with 182 additions and 52 deletions

View file

@ -26,11 +26,11 @@ mkdir -p \
obj/client/src/system \
obj/client/src/dos \
obj/client/src/gui \
obj/client/src/thirdparty/SHA256 \
obj/client/src/thirdparty/serial \
obj/shared/thirdparty/memwatch \
obj/shared/thirdparty/blowfish-api \
obj/shared/thirdparty/ini/src \
obj/shared/thirdparty/SHA256 \
obj/shared/thirdparty/tiny-AES-c \
obj/shared/thirdparty/tiny-AES128-C

View file

@ -21,7 +21,9 @@
TEMPLATE = app
CONFIG -= qt
CONFIG += ASAN
CONFIG += \
ASAN \
c99
DESTDIR = $$OUT_PWD/bin
SHARED = $$PWD/../shared
@ -71,6 +73,7 @@ HEADERS = \
$$SHARED/primes.h \
$$SHARED/packet.h \
$$SHARED/packets.h \
../shared/macros.h \
src/browser.h \
src/config.h \
$$SHARED/util.h \

View file

@ -73,6 +73,8 @@ void fileCacheCheck(fileCallback callback, char *vpaths[]) {
FileListT *newList = NULL;
uint16_t i = 0;
BEGIN
// Add new entries to anything already in the queue.
NEW(FileListT, newList);
newList->callback = callback;
@ -90,6 +92,8 @@ void fileCacheCheck(fileCallback callback, char *vpaths[]) {
}
fileCheckNext();
END
}
@ -102,6 +106,8 @@ static void fileCheckNext(void) {
char *shaPointer = NULL;
static char *badSHA = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
BEGIN
do {
// This is ugly since both lists kind of depend on each other.
doRecheck = 0;
@ -110,9 +116,11 @@ static void fileCheckNext(void) {
if (_current == NULL) {
// End of queue?
if (arrlen(_fileList) == 0) {
logWrite("End of file queue.\n");
arrfree(_fileList);
if (_dialogVisible) guiDelete(D(_winFile));
netChannelRelease(_channel);
_channel = 0;
return;
}
@ -127,6 +135,7 @@ static void fileCheckNext(void) {
// End of current queue file list?
if (arrlen(_current->files) == 0) {
// End of list!
logWrite("End of file list.\n");
arrfree(_current->files);
_current->callback();
DEL(_current);
@ -136,6 +145,7 @@ static void fileCheckNext(void) {
// No. Get next file.
_file = _current->files[0];
arrdel(_current->files, 0);
logWrite("File to check: %s\n", _file);
}
} while (doRecheck);
@ -151,6 +161,8 @@ static void fileCheckNext(void) {
packetEncode(__packetThreadData, &encoded, packetData, length);
packetSend(__packetThreadData, &encoded);
DEL(packetData);
END
}
@ -184,6 +196,7 @@ static void fileShowError(char *message) {
// Show error. This is fatal.
if (_dialogVisible) guiDelete(D(_winFile));
netChannelRelease(_channel);
_channel = 0;
msgBoxOne("Uh Oh!", MSGBOX_ICON_QUESTION, message, "Okay", btnMsgBoxOkay);
}
@ -195,6 +208,8 @@ static void packetHandler(PacketDecodeDataT *packet) {
uint16_t length = 0;
uint32_t temp = 0;
BEGIN
if (packet->packetType == PACKET_TYPE_FILE_RESPONSE) {
// Extract the response type. We get more data later.
packetContentUnpack(packet->data, "i", &response);
@ -218,6 +233,7 @@ static void packetHandler(PacketDecodeDataT *packet) {
if (!_dialogVisible) fileShowDialog();
// Are we starting a new file?
if (_handle == NULL) {
logWrite("Creating file %s\n", _file);
_handle = cacheFOpen(_file, "wb");
if (!_handle) {
fileShowError("Unable to write to cache.");
@ -225,9 +241,11 @@ static void packetHandler(PacketDecodeDataT *packet) {
}
}
// Write data to file, skipping first integer stored in packet.
logWrite("Writing %d bytes\n", packet->length - 4);
fwrite(&packet->data[4], packet->length - 4, 1, _handle);
// Is this file complete?
if (ftell(_handle) >= _currentLength) {
logWrite("Closing file %s\n", _file);
// Close this file.
cacheFClose(_handle);
_handle = NULL;
@ -256,6 +274,8 @@ static void packetHandler(PacketDecodeDataT *packet) {
}
packetDecodeDataDestroy(&packet);
END
}
@ -264,6 +284,8 @@ static void timTimerTimeout(WidgetT *widget) {
(void)widget;
BEGIN
// Download timed out.
timerStop(_timTimer);
@ -284,4 +306,6 @@ static void timTimerTimeout(WidgetT *widget) {
arrfree(_fileList);
if (missing) fileShowError("Unable to download needed files.");
END
}

View file

@ -80,6 +80,7 @@ void imageCacheIfNeeded(char *cacheFilename, char *sha256) {
char *rawSha = NULL;
FILE *f = NULL;
// This function expects a cache filename, not a real filesystem filename!
len = strlen(cacheFilename);
@ -96,7 +97,7 @@ void imageCacheIfNeeded(char *cacheFilename, char *sha256) {
temp = (char *)malloc(strlen(cacheFilename) + 5);
if (!temp) return;
sprintf(temp, "%s.raw", cacheFilename);
rawSha = cacheSha256Get(temp);
rawSha = strdup(cacheSha256Get(temp));
if (!rawSha || strcmp(rawSha, sha256) != 0) {
// The decompressed file either does not exist or the SHA does not match the file we're checking.
logWrite("Unpacking %s - %s\n", cacheFilenameGet(cacheFilename), cacheFilename);

View file

@ -117,6 +117,8 @@ static void btnMsgBoxContinue(MsgBoxButtonT button) {
static void loginFilesReady(void) {
char *p;
BEGIN
//***TODO*** Load into database if changed.
p = cacheSha256Get("generated:client.dat");
@ -173,6 +175,8 @@ static void loginFilesReady(void) {
textboxValueSet(_txtUser, "test");
textboxValueSet(_txtPass, "test");
END
}
@ -183,6 +187,8 @@ void loginShow() {
NULL
};
BEGIN
// Keep old SHA to know if we need to reload after updating.
p = cacheSha256Get("generated:client.dat");
if (p) {
@ -192,6 +198,8 @@ void loginShow() {
}
fileCacheCheck(loginFilesReady, fileList);
END
}
@ -199,6 +207,8 @@ static void packetHandler(PacketDecodeDataT *packet) {
char *packetData;
int32_t success;
BEGIN
switch (packet->packetType) {
case PACKET_TYPE_LOGIN_RESULT:
packetContentUnpack(packet->data, "is", &success, &packetData);
@ -220,6 +230,8 @@ static void packetHandler(PacketDecodeDataT *packet) {
}
packetDecodeDataDestroy(&packet);
END
}
@ -238,6 +250,8 @@ static void timLoginProgress(WidgetT *widget) {
PacketEncodeDataT encoded;
TimerT *t = (TimerT *)widget;
BEGIN
switch (_state) {
case S_START_LOGIN:
setButtons(0);
@ -260,5 +274,7 @@ static void timLoginProgress(WidgetT *widget) {
msgBoxOne("Uh Oh!", MSGBOX_ICON_ERROR, "No response received.", "Okay", btnMsgBoxContinue);
break;
}
END
}

View file

@ -298,6 +298,8 @@ extern void browserShow(void);
int main(int argc, char *argv[]) {
// Don't call BEGIN - no point.
if (startup(argc, argv)) return 1;
// Perform "first run" setup tasks or start the client?
@ -311,5 +313,7 @@ int main(int argc, char *argv[]) {
settingsShow(checkSettings);
}
// Can't call END here - log is already closed.
return 0;
}

View file

@ -96,6 +96,8 @@ static void menuFilesReady(void) {
uint16_t y = vbeDisplayHeightGet() - 49;
char *p;
BEGIN
//***TODO*** Load into database if changed.
p = cacheSha256Get("generated:games.dat");
@ -127,6 +129,8 @@ static void menuFilesReady(void) {
_picProfile = pictureNew(x, y, "menu:48profile.png");
pictureClickHandlerSet(_picProfile, picProfileClick);
guiAttach(guiRootGet(), W(_picProfile));
END
}
@ -143,6 +147,8 @@ void menuShow(void) {
NULL
};
BEGIN
// Keep old SHA to know if we need to reload after updating.
p = cacheSha256Get("generated:games.dat");
if (p) {
@ -152,6 +158,8 @@ void menuShow(void) {
}
fileCacheCheck(menuFilesReady, fileList);
END
}

View file

@ -133,6 +133,8 @@ static void packetHandler(PacketDecodeDataT *packet) {
uint32_t length;
char *packetData;
BEGIN
// Reset timeout.
timerReset(_timProgress);
@ -154,6 +156,8 @@ static void packetHandler(PacketDecodeDataT *packet) {
}
packetDecodeDataDestroy(&packet);
END
}
@ -165,6 +169,8 @@ static void setButtons(uint8_t enabled) {
void signupShow(void) {
BEGIN
TagItemT uiSignUp[] = {
T_START,
T_WINDOW, O(_winSignUp),
@ -256,6 +262,8 @@ void signupShow(void) {
textboxValueSet(_txtUser, "test");
textboxValueSet(_txtPass1, "test");
textboxValueSet(_txtPass2, "test");
END
}
@ -265,6 +273,8 @@ static void timSignUpProgress(WidgetT *widget) {
uint8_t *packetData;
TimerT *t = (TimerT *)widget;
BEGIN
switch (_state) {
case S_START_SIGNUP:
packetData = packetContentPack(&length, "sssss",
@ -292,6 +302,8 @@ static void timSignUpProgress(WidgetT *widget) {
msgBoxOne("Uh Oh!", MSGBOX_ICON_ERROR, "No response received.", "Okay", btnMsgBoxContinue);
break;
}
END
}

View file

@ -250,6 +250,7 @@ uint8_t cachePreUnpack(char *name) {
uint32_t length = 0;
uint32_t total = 0;
int8_t buffer[8192] = { 0 };
int8_t sha[65] = { 0 };
uint8_t hv[32] = { 0 };
char virtualPath[CACHE_VIRTUAL_PATH_MAX] = { 0 };
@ -267,8 +268,8 @@ uint8_t cachePreUnpack(char *name) {
} while (virtualPath[i - 1] != 0);
// Read SHA256.
fread(hv, 1, sizeof(hv), in);
for (i=0; i<32; i++) sprintf((char *)&buffer[i * 2], "%02x", hv[i]);
buffer[64] = 0;
for (i=0; i<32; i++) sprintf((char *)&sha[i * 2], "%02x", hv[i]);
sha[64] = 0;
// Read length.
fread(&length, 1, sizeof(uint32_t), in);
// Get filename from cache manager & create missing directories.
@ -279,7 +280,7 @@ uint8_t cachePreUnpack(char *name) {
osMkDirP(temp);
DEL(temp);
} while (osFileExists(entryDir));
cacheEntryAdd((char *)buffer, entryName, virtualPath);
cacheEntryAdd((char *)sha, entryName, virtualPath);
out = fopen(entryDir, "wb");
if (out) {
// Copy out data.
@ -294,7 +295,7 @@ uint8_t cachePreUnpack(char *name) {
fwrite(buffer, 1, i, out);
} while (length > 0);
fclose(out);
imageCacheIfNeeded(virtualPath, (char *)buffer);
imageCacheIfNeeded(virtualPath, (char *)sha);
} else {
result = FAIL;
}

View file

@ -68,10 +68,10 @@ static sqlite3_stmt *dbSqlBind(char *sql, char *format, va_list args) {
uint8_t dbExecute(char *sql, char *format, ...) {
char *error;
char *error = NULL;
int32_t r;
va_list args;
sqlite3_stmt *stmt;
sqlite3_stmt *stmt = NULL;
if (format == NULL) {
// No parameters, just run it.
@ -81,20 +81,25 @@ uint8_t dbExecute(char *sql, char *format, ...) {
stmt = dbSqlBind(sql, format, args);
va_end(args);
r = (sqlite3_step(stmt) == SQLITE_DONE ? SQLITE_OK : SQLITE_ERROR);
sqlite3_finalize(stmt);
}
if (r == SQLITE_ERROR) logWrite("DB: %s\n", error);
if (stmt) sqlite3_finalize(stmt);
return r == SQLITE_OK ? SUCCESS : FAIL;
}
uint8_t dbQuerySingle(char rformat, void **result, char *sql, char *format, ...) {
va_list args;
sqlite3_stmt *stmt;
sqlite3_stmt *stmt = NULL;
int32_t r;
static double d;
static int32_t i;
static char *v;
static char *v = NULL;
if (v) DEL(v);
if (format == NULL) {
// No parameters, just run it.
@ -122,6 +127,7 @@ uint8_t dbQuerySingle(char rformat, void **result, char *sql, char *format, ...)
case 'v':
v = (char *)sqlite3_column_text(stmt, 0);
if (v) v = strdup(v); // Make a copy so it doesn't get clobbered.
*result = v;
break;
@ -132,6 +138,8 @@ uint8_t dbQuerySingle(char rformat, void **result, char *sql, char *format, ...)
}
}
sqlite3_finalize(stmt);
return r == SQLITE_OK ? SUCCESS : FAIL;
}

View file

@ -73,33 +73,15 @@ void linuxOsStartup(void);
#endif
// Should be after system headers in this file.
#define MEMORY_CHECK_ENABLED
#include "memory.h"
#include "macros.h"
// Now our headers.
#include "log.h"
#include "util.h"
#include "packet.h"
#include "cache.h"
// Allocation helpers.
#define NEW(t,v) (v)=(t*)calloc(1, sizeof(t))
#define DEL(v) { if (v) { free(v); v = NULL; } }
#define SUCCESS 1
#define FAIL 0
// Some helper defines.
#define DIVISIBLE_BY_EIGHT(x) ((((x) >> 3) << 3) == (x))
#define HIGH_BYTE(b) ((uint8_t)(((b) & 0xFF00) >> 8))
#define LOW_BYTE(b) ((uint8_t)((b) & 0x00FF))
#ifndef PacketThreadDataT
typedef struct PacketThreadDataS PacketThreadDataT;
#endif
extern PacketThreadDataT *__packetThreadData; // Declared in main.c

View file

@ -123,6 +123,8 @@ static void btnSettingsClick(WidgetT *widget) {
static void packetHandler(PacketDecodeDataT *packet) {
PacketEncodeDataT encoded;
BEGIN
// Reset timeout.
timerReset(_timProgress);
@ -160,6 +162,8 @@ static void packetHandler(PacketDecodeDataT *packet) {
}
packetDecodeDataDestroy(&packet);
END
}
@ -180,6 +184,8 @@ void welcomeShow(void) {
// 450x128 logo
BEGIN
TagItemT uiWelcome[] = {
T_START,
T_WINDOW, O(_winWelcome),
@ -234,6 +240,8 @@ void welcomeShow(void) {
};
tagListRun(uiWelcome);
END
}
@ -244,6 +252,8 @@ static void timWelcomeProgress(WidgetT *widget) {
static char buffer[1024] = { 0 };
static uint16_t offset = 0;
BEGIN
switch (_state) {
case S_START_CONNECT:
// Ghost all buttons.
@ -361,4 +371,6 @@ static void timWelcomeProgress(WidgetT *widget) {
loginShow();
break;
}
END
}

View file

@ -50,6 +50,8 @@ static void clientApiFileFailed(ClientThreadT *client, PacketDecodeDataT *data)
void clientApiFileRequest(ClientThreadT *client, PacketDecodeDataT *data) {
FileRequestsT request = 0;
BEGIN
// Extract the request type. We get more data later.
packetContentUnpack(data->data, "i", &request);
@ -67,6 +69,8 @@ void clientApiFileRequest(ClientThreadT *client, PacketDecodeDataT *data) {
clientApiFileFailed(client, data);
break;
}
END
}
@ -84,6 +88,8 @@ static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT *
DbFileInfoT *info = NULL;
uint8_t mustAuth = 1;
BEGIN
// Is something still open?
if (client->handle) {
fclose(client->handle);
@ -101,12 +107,14 @@ static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT *
// Are they allowed to check this file while un-authenticated?
if (!client->authenticated && mustAuth) {
logWrite("Unauthenticated user requested file: %s\n", path);
clientApiFileFailed(client, data);
return;
}
// Look up the entry and compare SHA256.
if (strcasecmp(sha256, shaInDB) == 0) {
logWrite("SHAs match for %s\n", path);
// File is already current on client.
temp = FILE_RESPONSE_OKAY;
packetData = packetContentPack(&length, "i", temp);
@ -118,6 +126,7 @@ static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT *
packetSend(client->packetThreadData, &encoded);
DEL(packetData);
} else {
logWrite("SHAs do NOT match for %s\n", path);
// Get real path by flipping colons to slashes.
temp = 0;
while (path[temp] != 0) {
@ -133,6 +142,7 @@ static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT *
// Open file & get file size.
client->handle = fopen(buffer2, "rb");
if (!client->handle) {
logWrite("Unable to open file: %s\n", buffer2);
DEL(sha256);
DEL(path);
// ***TODO*** Handle error
@ -142,6 +152,8 @@ static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT *
client->fileSize = ftell(client->handle);
fseek(client->handle, 0, SEEK_SET);
logWrite("Sending %s - %d bytes\n", buffer2, client->fileSize);
// Send file metadata to start transfer
temp = FILE_RESPONSE_SEND;
packetData = packetContentPack(&length, "iis", temp, client->fileSize, shaInDB);
@ -159,6 +171,8 @@ static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT *
// Start sending actual file data.
clientApiFileRequestNext(client, data);
}
END
}
@ -168,6 +182,8 @@ static void clientApiFileRequestNext(ClientThreadT *client, PacketDecodeDataT *d
uint16_t length = 0;
uint8_t packetData[PACKET_MAX];
BEGIN
// Do we have an open file?
if (client->handle) {
// Add response type.
@ -179,10 +195,12 @@ static void clientApiFileRequestNext(ClientThreadT *client, PacketDecodeDataT *d
length = client->fileSize - ftell(client->handle);
if (length > PACKET_MAX - (10 + sizeof(int32_t))) {
// File is larger than a packet size.
logWrite("Sending file fraction %d bytes\n", length);
length = PACKET_MAX - (10 + sizeof(int32_t)); // 4 for integer of response type. 10 more because a full PACKET_MAX causes issues.
fread(&packetData[sizeof(int32_t)], length, 1, client->handle);
} else {
// File remains will fit in this packet.
logWrite("Sending file end %d bytes\n", length);
fread(&packetData[sizeof(int32_t)], length, 1, client->handle);
fclose(client->handle);
client->handle = NULL;
@ -197,4 +215,6 @@ static void clientApiFileRequestNext(ClientThreadT *client, PacketDecodeDataT *d
// Send it.
packetSend(client->packetThreadData, &encoded);
}
END
}

View file

@ -1,4 +1,4 @@
/*
/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
@ -278,7 +278,7 @@ static void dbFileSha256Create(char *file, char *buf) {
sha256_done(&hash, (uint8_t *)buffer);
for (bytes = 0; bytes < 32; bytes++) {
sprintf(hex, "%0x", (uint8_t)buffer[bytes]);
sprintf(hex, "%02x", (uint8_t)buffer[bytes]);
strcat(buf, hex);
}
buf[64] = 0;

View file

@ -31,23 +31,7 @@
#include <unistd.h>
#include <pthread.h>
// Should be after system headers in this file.
#define MEMORY_CHECK_ENABLED
#include "memory.h"
// Now our headers.
#include "log.h"
#include "util.h"
// Allocation helpers.
#define NEW(t,v) (v)=(t*)malloc(sizeof(t))
#define DEL(v) {free(v); v=NULL;}
#define SUCCESS 1
#define FAIL 0
#define MAX_PATH 1024
#include "macros.h"
// Declared in main.c

55
shared/macros.h Normal file
View file

@ -0,0 +1,55 @@
/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef MACROS_H
#define MACROS_H
#include <stdio.h>
// Should be after system headers in this file.
#define MEMORY_CHECK_ENABLED
#include "memory.h"
// Now our headers.
#include "log.h"
#include "util.h"
// Debug helpers.
#define BEGIN logWrite("BEGIN - %s @ %s (%d)\n", __FILE__, __func__, __LINE__);
#define END logWrite("END - %s @ %s (%d)\n", __FILE__, __func__, __LINE__);
// Allocation helpers.
#define NEW(t,v) (v)=(t*)malloc(sizeof(t))
#define DEL(v) {free(v); v=NULL;}
// Some helper defines.
#define DIVISIBLE_BY_EIGHT(x) ((((x) >> 3) << 3) == (x))
#define HIGH_BYTE(b) ((uint8_t)(((b) & 0xFF00) >> 8))
#define LOW_BYTE(b) ((uint8_t)((b) & 0x00FF))
#define SUCCESS 1
#define FAIL 0
#define MAX_PATH 1024
#endif // MACROS_H