Still reworking new connection sequence.
This commit is contained in:
parent
049f81ed50
commit
4f3a73bf12
21 changed files with 408 additions and 258 deletions
6
LICENSE
6
LICENSE
|
@ -133,6 +133,11 @@ MemWatch
|
||||||
http://www.linkdata.se/sourcecode/memwatch/
|
http://www.linkdata.se/sourcecode/memwatch/
|
||||||
GPL2
|
GPL2
|
||||||
|
|
||||||
|
SHA256
|
||||||
|
------
|
||||||
|
https://github.com/ilvn/SHA256
|
||||||
|
MIT
|
||||||
|
|
||||||
stb_ds.h
|
stb_ds.h
|
||||||
--------
|
--------
|
||||||
https://github.com/nothings/stb
|
https://github.com/nothings/stb
|
||||||
|
@ -147,4 +152,3 @@ tiny-AES128-C
|
||||||
-------------
|
-------------
|
||||||
https://github.com/bonybrown/tiny-AES128-C
|
https://github.com/bonybrown/tiny-AES128-C
|
||||||
Unlicense
|
Unlicense
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ HEADERS = \
|
||||||
$$SHARED/thirdparty/ini/src/ini.h \
|
$$SHARED/thirdparty/ini/src/ini.h \
|
||||||
$$SHARED/thirdparty/tiny-AES-c/aes.h \
|
$$SHARED/thirdparty/tiny-AES-c/aes.h \
|
||||||
$$SHARED/thirdparty/tiny-AES128-C/pkcs7_padding.h \
|
$$SHARED/thirdparty/tiny-AES128-C/pkcs7_padding.h \
|
||||||
|
$$SHARED/thirdparty/SHA256/sha256.h \
|
||||||
$$SHARED/primes.h \
|
$$SHARED/primes.h \
|
||||||
$$SHARED/packet.h \
|
$$SHARED/packet.h \
|
||||||
$$SHARED/packets.h \
|
$$SHARED/packets.h \
|
||||||
|
@ -83,7 +84,6 @@ HEADERS = \
|
||||||
src/signup.h \
|
src/signup.h \
|
||||||
src/system/cache.h \
|
src/system/cache.h \
|
||||||
src/system/db.h \
|
src/system/db.h \
|
||||||
src/thirdparty/SHA256/sha256.h \
|
|
||||||
src/thirdparty/minicoro/minicoro.h \
|
src/thirdparty/minicoro/minicoro.h \
|
||||||
src/system/comport.h \
|
src/system/comport.h \
|
||||||
src/settings.h \
|
src/settings.h \
|
||||||
|
@ -126,6 +126,7 @@ SOURCES = \
|
||||||
$$SHARED/packet.c \
|
$$SHARED/packet.c \
|
||||||
$$SHARED/thirdparty/tiny-AES-c/aes.c \
|
$$SHARED/thirdparty/tiny-AES-c/aes.c \
|
||||||
$$SHARED/thirdparty/tiny-AES128-C/pkcs7_padding.c \
|
$$SHARED/thirdparty/tiny-AES128-C/pkcs7_padding.c \
|
||||||
|
$$SHARED/thirdparty/SHA256/sha256.c \
|
||||||
$$SHARED/memory.c \
|
$$SHARED/memory.c \
|
||||||
src/browser.c \
|
src/browser.c \
|
||||||
src/file.c \
|
src/file.c \
|
||||||
|
@ -160,7 +161,6 @@ SOURCES = \
|
||||||
src/gui/label.c \
|
src/gui/label.c \
|
||||||
src/config.c \
|
src/config.c \
|
||||||
src/main.c \
|
src/main.c \
|
||||||
src/thirdparty/SHA256/sha256.c \
|
|
||||||
src/welcome.c \
|
src/welcome.c \
|
||||||
src/login.c \
|
src/login.c \
|
||||||
src/menu.c \
|
src/menu.c \
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "comport.h"
|
#include "comport.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "taglist.h"
|
#include "taglist.h"
|
||||||
|
#include "file.h"
|
||||||
|
|
||||||
#include "login.h"
|
#include "login.h"
|
||||||
#include "signup.h"
|
#include "signup.h"
|
||||||
|
@ -42,6 +43,8 @@ typedef enum LoginStateE {
|
||||||
} LoginStateT;
|
} LoginStateT;
|
||||||
|
|
||||||
|
|
||||||
|
static char *_shaClientDat = NULL;
|
||||||
|
|
||||||
static WindowT *_winLogin = NULL;
|
static WindowT *_winLogin = NULL;
|
||||||
static TextboxT *_txtUser = NULL;
|
static TextboxT *_txtUser = NULL;
|
||||||
static TextboxT *_txtPass = NULL;
|
static TextboxT *_txtPass = NULL;
|
||||||
|
@ -58,6 +61,7 @@ static void btnLoginClick(WidgetT *widget);
|
||||||
static void btnSignUpClick(WidgetT *widget);
|
static void btnSignUpClick(WidgetT *widget);
|
||||||
static void btnMsgBoxCancel(MsgBoxButtonT button);
|
static void btnMsgBoxCancel(MsgBoxButtonT button);
|
||||||
static void btnMsgBoxContinue(MsgBoxButtonT button);
|
static void btnMsgBoxContinue(MsgBoxButtonT button);
|
||||||
|
static void loginFilesReady(void);
|
||||||
static void packetHandler(PacketDecodeDataT *packet);
|
static void packetHandler(PacketDecodeDataT *packet);
|
||||||
static void setButtons(uint8_t enabled);
|
static void setButtons(uint8_t enabled);
|
||||||
static void timLoginProgress(WidgetT *widget);
|
static void timLoginProgress(WidgetT *widget);
|
||||||
|
@ -110,7 +114,11 @@ static void btnMsgBoxContinue(MsgBoxButtonT button) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void loginShow() {
|
static void loginFilesReady(void) {
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
//***TODO*** Load into database if changed.
|
||||||
|
p = cacheSha256Get("generated:client.dat");
|
||||||
|
|
||||||
// ***TODO*** We used to have a FORGOT PASSWORD link here, too.
|
// ***TODO*** We used to have a FORGOT PASSWORD link here, too.
|
||||||
|
|
||||||
|
@ -168,6 +176,25 @@ void loginShow() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loginShow() {
|
||||||
|
char *p;
|
||||||
|
char *fileList[] = {
|
||||||
|
"generated:client.dat",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
// Keep old SHA to know if we need to reload after updating.
|
||||||
|
p = cacheSha256Get("generated:client.dat");
|
||||||
|
if (p) {
|
||||||
|
_shaClientDat = strdup(p);
|
||||||
|
} else {
|
||||||
|
_shaClientDat = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fileCacheCheck(loginFilesReady, fileList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void packetHandler(PacketDecodeDataT *packet) {
|
static void packetHandler(PacketDecodeDataT *packet) {
|
||||||
char *packetData;
|
char *packetData;
|
||||||
int32_t success;
|
int32_t success;
|
||||||
|
|
|
@ -45,6 +45,8 @@ static void picLogoffClick(WidgetT *widget);
|
||||||
static void picProfileClick(WidgetT *widget);
|
static void picProfileClick(WidgetT *widget);
|
||||||
|
|
||||||
|
|
||||||
|
static char *_shaGamesDat = NULL;
|
||||||
|
|
||||||
static PictureT *_picChat = NULL;
|
static PictureT *_picChat = NULL;
|
||||||
static PictureT *_picEmail = NULL;
|
static PictureT *_picEmail = NULL;
|
||||||
static PictureT *_picForums = NULL;
|
static PictureT *_picForums = NULL;
|
||||||
|
@ -92,6 +94,10 @@ static void menuEnable(uint8_t enable) {
|
||||||
static void menuFilesReady(void) {
|
static void menuFilesReady(void) {
|
||||||
uint16_t x = vbeDisplayWidthGet() - 49;
|
uint16_t x = vbeDisplayWidthGet() - 49;
|
||||||
uint16_t y = vbeDisplayHeightGet() - 49;
|
uint16_t y = vbeDisplayHeightGet() - 49;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
//***TODO*** Load into database if changed.
|
||||||
|
p = cacheSha256Get("generated:games.dat");
|
||||||
|
|
||||||
_picLogoff = pictureNew(x, y, "menu:48logoff.png");
|
_picLogoff = pictureNew(x, y, "menu:48logoff.png");
|
||||||
pictureClickHandlerSet(_picLogoff, picLogoffClick);
|
pictureClickHandlerSet(_picLogoff, picLogoffClick);
|
||||||
|
@ -125,6 +131,7 @@ static void menuFilesReady(void) {
|
||||||
|
|
||||||
|
|
||||||
void menuShow(void) {
|
void menuShow(void) {
|
||||||
|
char *p;
|
||||||
char *fileList[] = {
|
char *fileList[] = {
|
||||||
"menu:48chat.png",
|
"menu:48chat.png",
|
||||||
"menu:48email.png",
|
"menu:48email.png",
|
||||||
|
@ -132,8 +139,18 @@ void menuShow(void) {
|
||||||
"menu:48games.png",
|
"menu:48games.png",
|
||||||
"menu:48logoff.png",
|
"menu:48logoff.png",
|
||||||
"menu:48profile.png",
|
"menu:48profile.png",
|
||||||
|
"generated:games.dat",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Keep old SHA to know if we need to reload after updating.
|
||||||
|
p = cacheSha256Get("generated:games.dat");
|
||||||
|
if (p) {
|
||||||
|
_shaGamesDat = strdup(p);
|
||||||
|
} else {
|
||||||
|
_shaGamesDat = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
fileCacheCheck(menuFilesReady, fileList);
|
fileCacheCheck(menuFilesReady, fileList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -122,17 +122,11 @@ static void btnSettingsClick(WidgetT *widget) {
|
||||||
|
|
||||||
static void packetHandler(PacketDecodeDataT *packet) {
|
static void packetHandler(PacketDecodeDataT *packet) {
|
||||||
PacketEncodeDataT encoded;
|
PacketEncodeDataT encoded;
|
||||||
char *temp;
|
|
||||||
|
|
||||||
// Reset timeout.
|
// Reset timeout.
|
||||||
timerReset(_timProgress);
|
timerReset(_timProgress);
|
||||||
|
|
||||||
switch (packet->packetType) {
|
switch (packet->packetType) {
|
||||||
case PACKET_TYPE_NUMBER:
|
|
||||||
// Store in number table.
|
|
||||||
shput(__runtimeData.integers, &packet->data[4], (int32_t)packet->data[0]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PACKET_TYPE_PROCEED:
|
case PACKET_TYPE_PROCEED:
|
||||||
// Connected! Show icon.
|
// Connected! Show icon.
|
||||||
widgetVisibleSet(W(_picConnect), 1);
|
widgetVisibleSet(W(_picConnect), 1);
|
||||||
|
@ -141,17 +135,6 @@ static void packetHandler(PacketDecodeDataT *packet) {
|
||||||
_state = S_WAIT_FOR_ICON;
|
_state = S_WAIT_FOR_ICON;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PACKET_TYPE_STRING:
|
|
||||||
// Do we have this string already?
|
|
||||||
temp = shget(__runtimeData.strings, packet->data);
|
|
||||||
if (temp) {
|
|
||||||
DEL(temp);
|
|
||||||
shdel(__runtimeData.strings, packet->data);
|
|
||||||
}
|
|
||||||
// Store in string table.
|
|
||||||
shput(__runtimeData.strings, packet->data, strdup((char *)&packet->data[strlen((char *)packet->data) + 1]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PACKET_TYPE_VERSION:
|
case PACKET_TYPE_VERSION:
|
||||||
packetContentUnpack(packet->data, "i", &__runtimeData.protocolVersion);
|
packetContentUnpack(packet->data, "i", &__runtimeData.protocolVersion);
|
||||||
// Do we need to update?
|
// Do we need to update?
|
||||||
|
|
59
schema.sql
59
schema.sql
|
@ -65,10 +65,11 @@ CREATE TABLE `files` (
|
||||||
`sha256` varchar(64) NOT NULL,
|
`sha256` varchar(64) NOT NULL,
|
||||||
`modified` datetime NOT NULL,
|
`modified` datetime NOT NULL,
|
||||||
`description` varchar(255) NOT NULL DEFAULT '',
|
`description` varchar(255) NOT NULL DEFAULT '',
|
||||||
|
`authenticated` tinyint(1) NOT NULL DEFAULT 1,
|
||||||
`touched` tinyint(1) NOT NULL DEFAULT 0,
|
`touched` tinyint(1) NOT NULL DEFAULT 0,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY `pathIndex` (`path`)
|
UNIQUE KEY `pathIndex` (`path`)
|
||||||
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;
|
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=latin1;
|
||||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
--
|
--
|
||||||
|
@ -81,33 +82,33 @@ DROP TABLE IF EXISTS `games`;
|
||||||
CREATE TABLE `games` (
|
CREATE TABLE `games` (
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
`active` tinyint(1) NOT NULL DEFAULT 0,
|
`active` tinyint(1) NOT NULL DEFAULT 0,
|
||||||
`title` varchar(255) DEFAULT NULL,
|
`title` varchar(255) NOT NULL DEFAULT '',
|
||||||
`developer` varchar(255) DEFAULT NULL,
|
`developer` varchar(255) NOT NULL DEFAULT '',
|
||||||
`publisher` varchar(255) DEFAULT NULL,
|
`publisher` varchar(255) NOT NULL DEFAULT '',
|
||||||
`description` text DEFAULT NULL,
|
`description` text NOT NULL DEFAULT '',
|
||||||
`releaseDate` datetime DEFAULT NULL,
|
`releaseDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
`stars` double DEFAULT NULL,
|
`stars` double NOT NULL DEFAULT -1,
|
||||||
`starCount` int(11) DEFAULT NULL,
|
`starCount` int(11) NOT NULL DEFAULT -1,
|
||||||
`rating` varchar(255) DEFAULT NULL,
|
`rating` varchar(255) NOT NULL DEFAULT 'Not Rated.',
|
||||||
`series` varchar(255) DEFAULT NULL,
|
`series` varchar(255) NOT NULL DEFAULT '',
|
||||||
`origin` varchar(255) DEFAULT NULL,
|
`origin` varchar(255) NOT NULL DEFAULT '',
|
||||||
`region` varchar(255) DEFAULT NULL,
|
`region` varchar(255) NOT NULL DEFAULT '',
|
||||||
`shortName` varchar(8) DEFAULT NULL,
|
`shortName` varchar(8) NOT NULL,
|
||||||
`type` varchar(8) DEFAULT NULL,
|
`type` varchar(8) NOT NULL,
|
||||||
`maxPlayers` int(11) DEFAULT 2,
|
`maxPlayers` int(11) NOT NULL DEFAULT 2,
|
||||||
`joinable` tinyint(1) DEFAULT 0,
|
`joinable` tinyint(1) NOT NULL DEFAULT 0,
|
||||||
`mobyGames` varchar(255) DEFAULT NULL,
|
`mobyGames` varchar(255) NOT NULL,
|
||||||
`wiki` varchar(255) DEFAULT NULL,
|
`wiki` varchar(255) NOT NULL,
|
||||||
`manual` varchar(255) DEFAULT NULL,
|
`manual` varchar(255) NOT NULL,
|
||||||
`root` varchar(255) DEFAULT NULL,
|
`root` varchar(255) NOT NULL,
|
||||||
`worksWith` varchar(255) DEFAULT NULL,
|
`worksWith` varchar(255) NOT NULL,
|
||||||
`configSys` text DEFAULT NULL,
|
`configSys` text NOT NULL,
|
||||||
`autoexecBat` text DEFAULT NULL,
|
`autoexecBat` text NOT NULL,
|
||||||
`options` text DEFAULT NULL,
|
`options` text NOT NULL,
|
||||||
`mods` text DEFAULT NULL,
|
`mods` text NOT NULL,
|
||||||
`notes` text DEFAULT NULL,
|
`notes` text NOT NULL,
|
||||||
`added` datetime DEFAULT NULL,
|
`added` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
`modified` datetime DEFAULT NULL,
|
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||||
`touched` tinyint(1) NOT NULL DEFAULT 0,
|
`touched` tinyint(1) NOT NULL DEFAULT 0,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `active_index` (`active`)
|
KEY `active_index` (`active`)
|
||||||
|
@ -145,4 +146,4 @@ CREATE TABLE `users` (
|
||||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||||
|
|
||||||
-- Dump completed on 2022-03-21 20:14:03
|
-- Dump completed on 2022-03-22 19:52:16
|
||||||
|
|
|
@ -51,7 +51,7 @@ HEADERS = \
|
||||||
$$SHARED/packets.h \
|
$$SHARED/packets.h \
|
||||||
$$SHARED/thirdparty/tiny-AES-c/aes.h \
|
$$SHARED/thirdparty/tiny-AES-c/aes.h \
|
||||||
$$SHARED/thirdparty/tiny-AES128-C/pkcs7_padding.h \
|
$$SHARED/thirdparty/tiny-AES128-C/pkcs7_padding.h \
|
||||||
src/thirdparty/sha256.c/sha256.h \
|
$$SHARED/thirdparty/SHA256/sha256.h \
|
||||||
src/client.h \
|
src/client.h \
|
||||||
src/client/file.h \
|
src/client/file.h \
|
||||||
src/client/login.h \
|
src/client/login.h \
|
||||||
|
@ -78,7 +78,7 @@ SOURCES = \
|
||||||
$$SHARED/packet.c \
|
$$SHARED/packet.c \
|
||||||
$$SHARED/thirdparty/tiny-AES-c/aes.c \
|
$$SHARED/thirdparty/tiny-AES-c/aes.c \
|
||||||
$$SHARED/thirdparty/tiny-AES128-C/pkcs7_padding.c \
|
$$SHARED/thirdparty/tiny-AES128-C/pkcs7_padding.c \
|
||||||
src/thirdparty/sha256.c/sha256.c \
|
$$SHARED/thirdparty/SHA256/sha256.c \
|
||||||
src/client.c \
|
src/client.c \
|
||||||
src/client/file.c \
|
src/client/file.c \
|
||||||
src/client/login.c \
|
src/client/login.c \
|
||||||
|
|
|
@ -24,46 +24,49 @@
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void clientApiFileFailed(ClientThreadT *client, PacketDecodeDataT *data);
|
||||||
static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT *data);
|
static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT *data);
|
||||||
static void clientApiFileRequestNext(ClientThreadT *client, PacketDecodeDataT *data);
|
static void clientApiFileRequestNext(ClientThreadT *client, PacketDecodeDataT *data);
|
||||||
|
|
||||||
|
|
||||||
void clientApiFileRequest(ClientThreadT *client, PacketDecodeDataT *data) {
|
static void clientApiFileFailed(ClientThreadT *client, PacketDecodeDataT *data) {
|
||||||
FileRequestsT request = 0;
|
|
||||||
PacketEncodeDataT encoded = { 0 };
|
PacketEncodeDataT encoded = { 0 };
|
||||||
uint8_t *packetData = NULL;
|
uint8_t *packetData = NULL;
|
||||||
uint16_t length = 0;
|
uint16_t length = 0;
|
||||||
|
|
||||||
// Must be logged in to do file operations.
|
packetData = packetContentPack(&length, "i", FILE_RESPONSE_UNKNOWN);
|
||||||
if (client->authenticated) {
|
// Build packet.
|
||||||
// Extract the request type. We get more data later.
|
encoded.control = PACKET_CONTROL_DAT;
|
||||||
packetContentUnpack(data->data, "i", &request);
|
encoded.packetType = PACKET_TYPE_FILE_RESPONSE;
|
||||||
|
encoded.channel = data->channel;
|
||||||
|
encoded.encrypt = 0;
|
||||||
|
packetEncode(client->packetThreadData, &encoded, packetData, length);
|
||||||
|
// Send it.
|
||||||
|
packetSend(client->packetThreadData, &encoded);
|
||||||
|
DEL(packetData);
|
||||||
|
}
|
||||||
|
|
||||||
switch (request) {
|
|
||||||
case FILE_REQUEST_CHECK:
|
|
||||||
clientApiFileRequestCheck(client, data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FILE_REQUEST_NEXT:
|
void clientApiFileRequest(ClientThreadT *client, PacketDecodeDataT *data) {
|
||||||
clientApiFileRequestNext(client, data);
|
FileRequestsT request = 0;
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
// Extract the request type. We get more data later.
|
||||||
// No idea what they want.
|
packetContentUnpack(data->data, "i", &request);
|
||||||
packetData = packetContentPack(&length, "i", FILE_RESPONSE_UNKNOWN);
|
|
||||||
// Build packet.
|
|
||||||
encoded.control = PACKET_CONTROL_DAT;
|
|
||||||
encoded.packetType = PACKET_TYPE_FILE_RESPONSE;
|
|
||||||
encoded.channel = data->channel;
|
|
||||||
encoded.encrypt = 0;
|
|
||||||
packetEncode(client->packetThreadData, &encoded, packetData, length);
|
|
||||||
// Send it.
|
|
||||||
packetSend(client->packetThreadData, &encoded);
|
|
||||||
DEL(packetData);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // authenticated
|
switch (request) {
|
||||||
|
case FILE_REQUEST_CHECK:
|
||||||
|
clientApiFileRequestCheck(client, data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FILE_REQUEST_NEXT:
|
||||||
|
clientApiFileRequestNext(client, data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// No idea what they want.
|
||||||
|
clientApiFileFailed(client, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,6 +81,8 @@ static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT *
|
||||||
char buffer[1024] = { 0 };
|
char buffer[1024] = { 0 };
|
||||||
char buffer2[2064] = { 0 };
|
char buffer2[2064] = { 0 };
|
||||||
uint32_t temp = 0;
|
uint32_t temp = 0;
|
||||||
|
DbFileInfoT *info = NULL;
|
||||||
|
uint8_t mustAuth = 1;
|
||||||
|
|
||||||
// Is something still open?
|
// Is something still open?
|
||||||
if (client->handle) {
|
if (client->handle) {
|
||||||
|
@ -88,8 +93,19 @@ static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT *
|
||||||
// Extract the request.
|
// Extract the request.
|
||||||
packetContentUnpack(data->data, "iss", &request, &sha256, &path);
|
packetContentUnpack(data->data, "iss", &request, &sha256, &path);
|
||||||
|
|
||||||
|
// Get file info we need.
|
||||||
|
info = dbFileInfoGet(path);
|
||||||
|
strncpy(shaInDB, info->sha, 128);
|
||||||
|
mustAuth = info->authenticated;
|
||||||
|
dbFileInfoRelease(&info);
|
||||||
|
|
||||||
|
// Are they allowed to check this file while un-authenticated?
|
||||||
|
if (!client->authenticated && mustAuth) {
|
||||||
|
clientApiFileFailed(client, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Look up the entry and compare SHA256.
|
// Look up the entry and compare SHA256.
|
||||||
dbFileSha256Get(path, shaInDB, 128);
|
|
||||||
if (strcasecmp(sha256, shaInDB) == 0) {
|
if (strcasecmp(sha256, shaInDB) == 0) {
|
||||||
// File is already current on client.
|
// File is already current on client.
|
||||||
temp = FILE_RESPONSE_OKAY;
|
temp = FILE_RESPONSE_OKAY;
|
||||||
|
|
|
@ -125,9 +125,9 @@ void consoleRun(void) {
|
||||||
}
|
}
|
||||||
// Help.
|
// Help.
|
||||||
if (!strcasecmp(command, "HELP") || !strcasecmp(command, "?")) {
|
if (!strcasecmp(command, "HELP") || !strcasecmp(command, "?")) {
|
||||||
sendToConsole("HELP or ? - This message.\n");
|
sendToConsole("HELP or ? - This message.\n");
|
||||||
sendToConsole("SHUTDOWN - Stop the server.\n");
|
sendToConsole("SHUTDOWN - Stop the server.\n");
|
||||||
sendToConsole("UPDATE [what] - Update client data.\n");
|
sendToConsole("UPDATE - Update client data.\n");
|
||||||
commandOk = 1;
|
commandOk = 1;
|
||||||
}
|
}
|
||||||
// Shutdown.
|
// Shutdown.
|
||||||
|
@ -137,7 +137,7 @@ void consoleRun(void) {
|
||||||
}
|
}
|
||||||
// Update.
|
// Update.
|
||||||
if (!strcasecmp(command, "UPDATE")) {
|
if (!strcasecmp(command, "UPDATE")) {
|
||||||
update(p);
|
update();
|
||||||
commandOk = 1;
|
commandOk = 1;
|
||||||
}
|
}
|
||||||
// Did we grok it?
|
// Did we grok it?
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <crypt.h>
|
#include <crypt.h>
|
||||||
|
|
||||||
#include "thirdparty/sha256.c/sha256.h"
|
#include "thirdparty/SHA256/sha256.h"
|
||||||
|
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
|
@ -37,24 +37,12 @@
|
||||||
#define STATEMENT_MAX 2048
|
#define STATEMENT_MAX 2048
|
||||||
|
|
||||||
|
|
||||||
typedef struct DbFileInfoS {
|
|
||||||
uint64_t id;
|
|
||||||
char *path;
|
|
||||||
uint64_t length;
|
|
||||||
char *sha;
|
|
||||||
char *modified;
|
|
||||||
uint8_t touched;
|
|
||||||
} DbFileInfoT;
|
|
||||||
|
|
||||||
|
|
||||||
static MYSQL *_sql = NULL;
|
static MYSQL *_sql = NULL;
|
||||||
static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
|
||||||
static DbFileInfoT *dbFileInfoGet(char *vpath);
|
static void dbFileInfoSet(DbFileInfoT *info);
|
||||||
static void dbFileInfoRelease(DbFileInfoT **info);
|
static void dbFileSha256Create(char *file, char *buf);
|
||||||
static void dbFileInfoSet(DbFileInfoT *info);
|
|
||||||
static void dbFileSha256Create(char *file, char *buf);
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t dbConnect(char *host, uint16_t port, char *database, char *user, char *password) {
|
uint8_t dbConnect(char *host, uint16_t port, char *database, char *user, char *password) {
|
||||||
|
@ -77,6 +65,69 @@ uint8_t dbConnect(char *host, uint16_t port, char *database, char *user, char *p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dbClientConfigRelease(DbClientConfigT **config) {
|
||||||
|
DbClientConfigT *c = *config;
|
||||||
|
|
||||||
|
if (c) {
|
||||||
|
DEL(c->name);
|
||||||
|
DEL(c->data);
|
||||||
|
DEL(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DbClientConfigT **dbClientConfigGet(void) {
|
||||||
|
char statement[STATEMENT_MAX];
|
||||||
|
char *p = statement;
|
||||||
|
MYSQL_RES *result = NULL;
|
||||||
|
MYSQL_ROW row = NULL;
|
||||||
|
int count = 0;
|
||||||
|
DbClientConfigT *record = NULL;
|
||||||
|
DbClientConfigT **config = NULL;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&_mutex);
|
||||||
|
|
||||||
|
if (!_sql) {
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
p += sprintf(p, "SELECT name, data FROM client");
|
||||||
|
if (mysql_real_query(_sql, statement, p - statement) != 0) {
|
||||||
|
logWrite("dbClientConfigGet: %s\n", mysql_error(_sql));
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = mysql_store_result(_sql);
|
||||||
|
for (count = 0; count < (int)mysql_num_rows(result); count++) {
|
||||||
|
if ((row = mysql_fetch_row(result)) == NULL) {
|
||||||
|
logWrite("dbClientConfigGet: %s\n", mysql_error(_sql));
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
while (arrlen(config) > 0) {
|
||||||
|
record = config[0];
|
||||||
|
dbClientConfigRelease(&record);
|
||||||
|
arrdel(config, 0);
|
||||||
|
}
|
||||||
|
arrfree(config);
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NEW(DbClientConfigT, record);
|
||||||
|
record->name = strdup(row[0]);
|
||||||
|
record->data = strdup(row[1]);
|
||||||
|
arrput(config, record);
|
||||||
|
}
|
||||||
|
|
||||||
|
mysql_free_result(result);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t dbDisconnect(void) {
|
uint8_t dbDisconnect(void) {
|
||||||
if (_sql) {
|
if (_sql) {
|
||||||
mysql_close(_sql);
|
mysql_close(_sql);
|
||||||
|
@ -89,7 +140,7 @@ uint8_t dbDisconnect(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static DbFileInfoT *dbFileInfoGet(char *vpath) {
|
DbFileInfoT *dbFileInfoGet(char *vpath) {
|
||||||
char statement[STATEMENT_MAX];
|
char statement[STATEMENT_MAX];
|
||||||
char *p = statement;
|
char *p = statement;
|
||||||
MYSQL_RES *result = NULL;
|
MYSQL_RES *result = NULL;
|
||||||
|
@ -110,7 +161,7 @@ static DbFileInfoT *dbFileInfoGet(char *vpath) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
p += sprintf(p, "SELECT id, path, length, sha256, modified, touched FROM files WHERE path='");
|
p += sprintf(p, "SELECT id, path, length, sha256, modified, authenticated, touched FROM files WHERE path='");
|
||||||
p += mysql_real_escape_string(_sql, p, vpath, strlen(vpath));
|
p += mysql_real_escape_string(_sql, p, vpath, strlen(vpath));
|
||||||
p += sprintf(p, "'");
|
p += sprintf(p, "'");
|
||||||
if (mysql_real_query(_sql, statement, p - statement) != 0) {
|
if (mysql_real_query(_sql, statement, p - statement) != 0) {
|
||||||
|
@ -139,12 +190,13 @@ static DbFileInfoT *dbFileInfoGet(char *vpath) {
|
||||||
pthread_mutex_unlock(&_mutex);
|
pthread_mutex_unlock(&_mutex);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
info->id = atol(row[0]);
|
info->id = atol(row[0]);
|
||||||
info->path = strdup(row[1]);
|
info->path = strdup(row[1]);
|
||||||
info->length = atol(row[2]);
|
info->length = atol(row[2]);
|
||||||
info->sha = strdup(row[3]);
|
info->sha = strdup(row[3]);
|
||||||
info->modified = strdup(row[4]);
|
info->modified = strdup(row[4]);
|
||||||
info->touched = atoi(row[5]);
|
info->authenticated = atoi(row[5]);
|
||||||
|
info->touched = atoi(row[6]);
|
||||||
|
|
||||||
mysql_free_result(result);
|
mysql_free_result(result);
|
||||||
|
|
||||||
|
@ -154,7 +206,7 @@ static DbFileInfoT *dbFileInfoGet(char *vpath) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void dbFileInfoRelease(DbFileInfoT **info) {
|
void dbFileInfoRelease(DbFileInfoT **info) {
|
||||||
DbFileInfoT *i = *info;
|
DbFileInfoT *i = *info;
|
||||||
|
|
||||||
if (i) {
|
if (i) {
|
||||||
|
@ -206,11 +258,11 @@ static void dbFileInfoSet(DbFileInfoT *info) {
|
||||||
|
|
||||||
|
|
||||||
static void dbFileSha256Create(char *file, char *buf) {
|
static void dbFileSha256Create(char *file, char *buf) {
|
||||||
FILE *f = NULL;
|
FILE *f = NULL;
|
||||||
char buffer[1024] = { 0 };
|
char buffer[1024] = { 0 };
|
||||||
char hex[3] = { 0 };
|
char hex[3] = { 0 };
|
||||||
size_t bytes = 0;
|
size_t bytes = 0;
|
||||||
sha256_t hash = { 0 };
|
sha256_context hash = { 0 };
|
||||||
|
|
||||||
// buf has to be at least 65 bytes.
|
// buf has to be at least 65 bytes.
|
||||||
buf[0] = 0;
|
buf[0] = 0;
|
||||||
|
@ -220,29 +272,106 @@ static void dbFileSha256Create(char *file, char *buf) {
|
||||||
|
|
||||||
sha256_init(&hash);
|
sha256_init(&hash);
|
||||||
while (bytes = fread(buffer, 1, sizeof(buffer), f), bytes > 0) {
|
while (bytes = fread(buffer, 1, sizeof(buffer), f), bytes > 0) {
|
||||||
sha256_update(&hash, (unsigned char *)buffer, bytes);
|
sha256_hash(&hash, (uint8_t *)buffer, bytes);
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
sha256_final(&hash, (unsigned char *)buffer);
|
sha256_done(&hash, (uint8_t *)buffer);
|
||||||
|
|
||||||
for (bytes = 0; bytes < 32; bytes++) {
|
for (bytes = 0; bytes < 32; bytes++) {
|
||||||
sprintf(hex, "%0x", (unsigned char)buffer[bytes]);
|
sprintf(hex, "%0x", (uint8_t)buffer[bytes]);
|
||||||
strcat(buf, hex);
|
strcat(buf, hex);
|
||||||
}
|
}
|
||||||
buf[64] = 0;
|
buf[64] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t dbFileSha256Get(char *vpath, char *value, uint32_t max) {
|
void dbGameRelease(DbGameT **game) {
|
||||||
DbFileInfoT *info = dbFileInfoGet(vpath);
|
DbGameT *g = *game;
|
||||||
|
|
||||||
if (info) {
|
if (g) {
|
||||||
strncpy(value, info->sha, max);
|
DEL(g->title);
|
||||||
dbFileInfoRelease(&info);
|
DEL(g->publisher);
|
||||||
return SUCCESS;
|
DEL(g->developer);
|
||||||
|
DEL(g->description);
|
||||||
|
DEL(g->releaseDate);
|
||||||
|
DEL(g->rating);
|
||||||
|
DEL(g->series);
|
||||||
|
DEL(g->origin);
|
||||||
|
DEL(g->shortName);
|
||||||
|
DEL(g);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DbGameT **dbGamesGet(void) {
|
||||||
|
char statement[STATEMENT_MAX];
|
||||||
|
char *p = statement;
|
||||||
|
MYSQL_RES *result = NULL;
|
||||||
|
MYSQL_ROW row = NULL;
|
||||||
|
int32_t count = 0;
|
||||||
|
int32_t i = 0;
|
||||||
|
DbGameT **gameList = NULL;
|
||||||
|
DbGameT *game = NULL;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&_mutex);
|
||||||
|
|
||||||
|
if (!_sql) {
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FAIL;
|
p += sprintf(p,
|
||||||
|
"SELECT title, publisher, developer, description, releaseDate, "
|
||||||
|
"rating, series, origin, shortName, type, maxPlayers, joinable "
|
||||||
|
"FROM games WHERE active=1");
|
||||||
|
if (mysql_real_query(_sql, statement, p - statement) != 0) {
|
||||||
|
logWrite("dbGamesGet: %s\n", mysql_error(_sql));
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = mysql_store_result(_sql);
|
||||||
|
count = mysql_num_rows(result);
|
||||||
|
|
||||||
|
if (count > 0) {
|
||||||
|
for (i=0; i<count; i++) {
|
||||||
|
if ((row = mysql_fetch_row(result)) == NULL) {
|
||||||
|
logWrite("dbGamesGet: %s\n", mysql_error(_sql));
|
||||||
|
mysql_free_result(result);
|
||||||
|
while (arrlen(gameList) > 0) {
|
||||||
|
game = gameList[0];
|
||||||
|
dbGameRelease(&game);
|
||||||
|
arrdel(gameList, 0);
|
||||||
|
}
|
||||||
|
arrfree(gameList);
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
NEW(DbGameT, game);
|
||||||
|
game->title = strdup(row[0]);
|
||||||
|
game->publisher = strdup(row[1]);
|
||||||
|
game->developer = strdup(row[2]);
|
||||||
|
game->description = strdup(row[3]);
|
||||||
|
game->releaseDate = strdup(row[4]);
|
||||||
|
game->rating = strdup(row[5]);
|
||||||
|
game->series = strdup(row[6]);
|
||||||
|
game->origin = strdup(row[7]);
|
||||||
|
game->shortName = strdup(row[8]);
|
||||||
|
game->type = GAME_TYPE_UNKNOWN;
|
||||||
|
game->maxPlayers = atoi(row[10]);
|
||||||
|
game->joinable = atoi(row[11]);
|
||||||
|
if (!strcasecmp(row[9], "DOOR")) game->type = GAME_TYPE_DOOR;
|
||||||
|
if (!strcasecmp(row[9], "SERIAL")) game->type = GAME_TYPE_SERIAL;
|
||||||
|
if (!strcasecmp(row[9], "IPX")) game->type = GAME_TYPE_IPX;
|
||||||
|
if (!strcasecmp(row[9], "FICTION")) game->type = GAME_TYPE_FICTION;
|
||||||
|
arrput(gameList, game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mysql_free_result(result);
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
|
||||||
|
return gameList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -307,53 +436,6 @@ uint8_t dbSettingsValueGet(char *host, char *key, int32_t *value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t dbTableGet(char *which, DBTableT ***table) {
|
|
||||||
char statement[STATEMENT_MAX];
|
|
||||||
char *p = statement;
|
|
||||||
MYSQL_RES *result = NULL;
|
|
||||||
MYSQL_ROW row;
|
|
||||||
int count;
|
|
||||||
DBTableT *record = NULL;
|
|
||||||
|
|
||||||
// By "table" we mean string or number table, not a database table.
|
|
||||||
|
|
||||||
pthread_mutex_lock(&_mutex);
|
|
||||||
|
|
||||||
if (!_sql) {
|
|
||||||
pthread_mutex_unlock(&_mutex);
|
|
||||||
return FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
p += sprintf(p, "SELECT name, data FROM ");
|
|
||||||
p += mysql_real_escape_string(_sql, p, which, strlen(which));
|
|
||||||
if (mysql_real_query(_sql, statement, p - statement) != 0) {
|
|
||||||
logWrite("dbTableGet: %s\n", mysql_error(_sql));
|
|
||||||
pthread_mutex_unlock(&_mutex);
|
|
||||||
return FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = mysql_store_result(_sql);
|
|
||||||
for (count = 0; count < (int)mysql_num_rows(result); count++) {
|
|
||||||
if ((row = mysql_fetch_row(result)) == NULL) {
|
|
||||||
logWrite("dbTableGet: %s\n", mysql_error(_sql));
|
|
||||||
pthread_mutex_unlock(&_mutex);
|
|
||||||
return FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
NEW(DBTableT, record);
|
|
||||||
record->name = strdup(row[0]);
|
|
||||||
record->data = strdup(row[1]);
|
|
||||||
arrput(*table, record);
|
|
||||||
}
|
|
||||||
|
|
||||||
mysql_free_result(result);
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&_mutex);
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t dbUpdateFileData(char *file, uint64_t len, char *time) {
|
uint8_t dbUpdateFileData(char *file, uint64_t len, char *time) {
|
||||||
DbFileInfoT *info = NULL;
|
DbFileInfoT *info = NULL;
|
||||||
char prefix[1064] = { 0 };
|
char prefix[1064] = { 0 };
|
||||||
|
|
|
@ -28,25 +28,63 @@
|
||||||
#define DB_CONFIG_ITEM_SIZE 1024
|
#define DB_CONFIG_ITEM_SIZE 1024
|
||||||
|
|
||||||
|
|
||||||
typedef struct DBTableS {
|
typedef enum DbGameTypeE {
|
||||||
|
GAME_TYPE_UNKNOWN = 0,
|
||||||
|
GAME_TYPE_DOOR,
|
||||||
|
GAME_TYPE_SERIAL,
|
||||||
|
GAME_TYPE_IPX,
|
||||||
|
GAME_TYPE_FICTION
|
||||||
|
} DbGameTypeT;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct DbClientConfigS {
|
||||||
char *name;
|
char *name;
|
||||||
char *data;
|
char *data;
|
||||||
} DBTableT;
|
} DbClientConfigT;
|
||||||
|
|
||||||
|
typedef struct DbFileInfoS {
|
||||||
|
uint64_t id;
|
||||||
|
char *path;
|
||||||
|
uint64_t length;
|
||||||
|
char *sha;
|
||||||
|
char *modified;
|
||||||
|
uint8_t authenticated;
|
||||||
|
uint8_t touched;
|
||||||
|
} DbFileInfoT;
|
||||||
|
|
||||||
|
typedef struct DbGameS {
|
||||||
|
char *title;
|
||||||
|
char *publisher;
|
||||||
|
char *developer;
|
||||||
|
char *description;
|
||||||
|
char *releaseDate;
|
||||||
|
char *rating;
|
||||||
|
char *series;
|
||||||
|
char *origin;
|
||||||
|
char *shortName;
|
||||||
|
DbGameTypeT type;
|
||||||
|
uint8_t maxPlayers;
|
||||||
|
uint8_t joinable;
|
||||||
|
} DbGameT;
|
||||||
|
|
||||||
|
|
||||||
uint8_t dbConnect(char *host, uint16_t port, char *database, char *user, char *password);
|
uint8_t dbConnect(char *host, uint16_t port, char *database, char *user, char *password);
|
||||||
uint8_t dbDisconnect(void);
|
void dbClientConfigRelease(DbClientConfigT **config);
|
||||||
uint8_t dbFileSha256Get(char *vpath, char *value, uint32_t max);
|
DbClientConfigT **dbClientConfigGet(void);
|
||||||
uint8_t dbSettingsStringGet(char *host, char *key, char *value, uint32_t max);
|
uint8_t dbDisconnect(void);
|
||||||
uint8_t dbSettingsValueGet(char *host, char *key, int32_t *value);
|
DbFileInfoT *dbFileInfoGet(char *vpath);
|
||||||
uint8_t dbTableGet(char *which, DBTableT ***table);
|
void dbFileInfoRelease(DbFileInfoT **info);
|
||||||
uint8_t dbUpdateFileData(char *file, uint64_t len, char *time);
|
void dbGameRelease(DbGameT **game);
|
||||||
uint8_t dbUpdateFilesFinish(void);
|
DbGameT **dbGamesGet(void);
|
||||||
uint8_t dbUpdateFilesStart(void);
|
uint8_t dbSettingsStringGet(char *host, char *key, char *value, uint32_t max);
|
||||||
uint8_t dbUserCreate(char *first, char *last, char *user, char *pass, char *email);
|
uint8_t dbSettingsValueGet(char *host, char *key, int32_t *value);
|
||||||
uint8_t dbUserEmailExists(char *email);
|
uint8_t dbUpdateFileData(char *file, uint64_t len, char *time);
|
||||||
uint8_t dbUserLogin(char *user, char *password);
|
uint8_t dbUpdateFilesFinish(void);
|
||||||
uint8_t dbUserNameExists(char *user);
|
uint8_t dbUpdateFilesStart(void);
|
||||||
|
uint8_t dbUserCreate(char *first, char *last, char *user, char *pass, char *email);
|
||||||
|
uint8_t dbUserEmailExists(char *email);
|
||||||
|
uint8_t dbUserLogin(char *user, char *password);
|
||||||
|
uint8_t dbUserNameExists(char *user);
|
||||||
|
|
||||||
|
|
||||||
#endif // DATABASE_H
|
#endif // DATABASE_H
|
||||||
|
|
|
@ -31,87 +31,50 @@
|
||||||
#include "update.h"
|
#include "update.h"
|
||||||
|
|
||||||
|
|
||||||
typedef void *(*UpdateThreadT)(void *);
|
|
||||||
|
|
||||||
|
|
||||||
static pthread_t _updateThreadHandle = { 0 };
|
static pthread_t _updateThreadHandle = { 0 };
|
||||||
static uint8_t _updateThreadRunning = 0;
|
static uint8_t _updateThreadRunning = 0;
|
||||||
static uint8_t _updateAllRunning = 0;
|
|
||||||
|
|
||||||
|
|
||||||
static void *updateAll(void *data);
|
static void *updateAll(void *path);
|
||||||
static void *updateConfig(void *data);
|
static void updateConfig(void);
|
||||||
static void *updateFiles(void *path);
|
static void updateFiles(void *path);
|
||||||
static int32_t updateFileEntry(const char *filepath, const struct stat *info, const int typeflag, struct FTW *pathinfo);
|
static int32_t updateFileEntry(const char *filepath, const struct stat *info, const int typeflag, struct FTW *pathinfo);
|
||||||
static void *updateGames(void *data);
|
static void updateGames(void);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void update(char *params) {
|
void update(void) {
|
||||||
|
|
||||||
char *p = NULL;
|
|
||||||
pthread_attr_t updateThreadAttributes = { 0 };
|
pthread_attr_t updateThreadAttributes = { 0 };
|
||||||
UpdateThreadT updateThread = NULL;
|
|
||||||
|
|
||||||
if (params == NULL) {
|
|
||||||
consoleMessageQueue("UPDATE [what] - where [what] is:\n");
|
|
||||||
consoleMessageQueue(" ALL - Update everything.\n");
|
|
||||||
consoleMessageQueue(" CONFIG - Rebuild client configuration.\n");
|
|
||||||
consoleMessageQueue(" FILES [path] - Update file data from [path].\n");
|
|
||||||
consoleMessageQueue(" GAMES - Rebuild game database.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is there a space in the parameters line?
|
|
||||||
p = strstr(params, " ");
|
|
||||||
if (p) {
|
|
||||||
// Replace it with zero, move P to next character for more parameters.
|
|
||||||
*p = 0;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_updateThreadRunning) {
|
if (_updateThreadRunning) {
|
||||||
consoleMessageQueue("An update is already running. Wait until it completes.\n\r");
|
consoleMessageQueue("An update is already running. Wait until it completes.\n\r");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcasecmp(params, "ALL")) { updateThread = updateAll; _updateAllRunning = 1; }
|
|
||||||
if (!strcasecmp(params, "CONFIG")) { updateThread = updateConfig; _updateAllRunning = 0; }
|
|
||||||
if (!strcasecmp(params, "FILES")) { updateThread = updateFiles; _updateAllRunning = 0; }
|
|
||||||
if (!strcasecmp(params, "GAMES")) { updateThread = updateGames; _updateAllRunning = 0; }
|
|
||||||
|
|
||||||
if (!updateThread) {
|
|
||||||
consoleMessageQueue("Unknown UPDATE option! Type UPDATE for help.\n\r");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start update thread.
|
// Start update thread.
|
||||||
_updateThreadRunning = 1;
|
_updateThreadRunning = 1;
|
||||||
if (pthread_attr_init(&updateThreadAttributes) != 0) utilDie("Unable to create update thread attributes.\n");
|
if (pthread_attr_init(&updateThreadAttributes) != 0) utilDie("Unable to create update thread attributes.\n");
|
||||||
pthread_attr_setdetachstate(&updateThreadAttributes, PTHREAD_CREATE_JOINABLE);
|
pthread_attr_setdetachstate(&updateThreadAttributes, PTHREAD_CREATE_JOINABLE);
|
||||||
if (pthread_create(&_updateThreadHandle, &updateThreadAttributes, updateThread, (void *)p) != 0) utilDie("Unable to start update thread.\n");
|
if (pthread_create(&_updateThreadHandle, &updateThreadAttributes, updateAll, NULL) != 0) utilDie("Unable to start update thread.\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *updateAll(void *data) {
|
static void *updateAll(void *data) {
|
||||||
(void)data;
|
(void)data;
|
||||||
|
|
||||||
updateConfig(NULL);
|
updateConfig();
|
||||||
|
updateGames();
|
||||||
updateFiles("/");
|
updateFiles("/");
|
||||||
updateGames(NULL);
|
|
||||||
|
|
||||||
pthread_exit(NULL);
|
pthread_exit(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *updateConfig(void *data) {
|
static void updateConfig(void) {
|
||||||
DBTableT *record = NULL;
|
DbClientConfigT *record = NULL;
|
||||||
DBTableT **table = NULL;
|
char file[MAX_PATH] = { 0 };
|
||||||
char file[MAX_PATH] = { 0 };
|
FILE *f = NULL;
|
||||||
FILE *f = NULL;
|
DbClientConfigT **config = NULL;
|
||||||
|
|
||||||
(void)data;
|
|
||||||
|
|
||||||
consoleMessageQueue("Updating client configuration data.\n");
|
consoleMessageQueue("Updating client configuration data.\n");
|
||||||
|
|
||||||
|
@ -119,28 +82,24 @@ static void *updateConfig(void *data) {
|
||||||
f = fopen(file, "wb");
|
f = fopen(file, "wb");
|
||||||
if (f) {
|
if (f) {
|
||||||
// Fetch string table from DB.
|
// Fetch string table from DB.
|
||||||
if (dbTableGet("client", &table) == SUCCESS) {
|
config = dbClientConfigGet();
|
||||||
while (arrlen(table)) {
|
if (config) {
|
||||||
record = table[0];
|
while (arrlen(config)) {
|
||||||
arrdel(table, 0);
|
record = config[0];
|
||||||
|
arrdel(config, 0);
|
||||||
// Write to config file that is sent to the client.
|
// Write to config file that is sent to the client.
|
||||||
fwrite(record->name, strlen(record->name) + 1, 1, f);
|
fwrite(record->name, strlen(record->name) + 1, 1, f);
|
||||||
fwrite(record->data, strlen(record->data) + 1, 1, f);
|
fwrite(record->data, strlen(record->data) + 1, 1, f);
|
||||||
DEL(record->name);
|
dbClientConfigRelease(&record);
|
||||||
DEL(record->data);
|
|
||||||
DEL(record);
|
|
||||||
}
|
}
|
||||||
arrfree(table);
|
arrfree(config);
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_updateAllRunning) pthread_exit(NULL);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *updateFiles(void *data) {
|
static void updateFiles(void *data) {
|
||||||
char file[MAX_PATH] = { 0 };
|
char file[MAX_PATH] = { 0 };
|
||||||
char *path = (char *)data;
|
char *path = (char *)data;
|
||||||
int32_t result = 0;
|
int32_t result = 0;
|
||||||
|
@ -161,9 +120,6 @@ static void *updateFiles(void *data) {
|
||||||
result = nftw(file, updateFileEntry, 15, FTW_PHYS);
|
result = nftw(file, updateFileEntry, 15, FTW_PHYS);
|
||||||
dbUpdateFilesFinish();
|
dbUpdateFilesFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_updateAllRunning) pthread_exit(NULL);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -252,11 +208,39 @@ static int32_t updateFileEntry(const char *filepath, const struct stat *info, co
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *updateGames(void *data) {
|
static void updateGames(void) {
|
||||||
(void)data;
|
DbGameT **gameList = NULL;
|
||||||
|
DbGameT *game = NULL;
|
||||||
|
char file[MAX_PATH] = { 0 };
|
||||||
|
FILE *f = NULL;
|
||||||
|
uint8_t c = 0;
|
||||||
|
|
||||||
consoleMessageQueue("Updating client game database.\n");
|
consoleMessageQueue("Updating client game database.\n");
|
||||||
|
|
||||||
if (!_updateAllRunning) pthread_exit(NULL);
|
snprintf(file, MAX_PATH, "%s/files/generated/games.dat", __settingsFile);
|
||||||
return NULL;
|
f = fopen(file, "wb");
|
||||||
|
if (f) {
|
||||||
|
gameList = dbGamesGet();
|
||||||
|
while (arrlen(gameList) > 0) {
|
||||||
|
game = gameList[0];
|
||||||
|
|
||||||
|
fwrite(game->title, strlen(game->title) + 1, 1, f);
|
||||||
|
fwrite(game->publisher, strlen(game->publisher) + 1, 1, f);
|
||||||
|
fwrite(game->developer, strlen(game->developer) + 1, 1, f);
|
||||||
|
fwrite(game->description, strlen(game->description) + 1, 1, f);
|
||||||
|
fwrite(game->releaseDate, strlen(game->releaseDate) + 1, 1, f);
|
||||||
|
fwrite(game->rating, strlen(game->rating) + 1, 1, f);
|
||||||
|
fwrite(game->series, strlen(game->series) + 1, 1, f);
|
||||||
|
fwrite(game->origin, strlen(game->origin) + 1, 1, f);
|
||||||
|
fwrite(game->shortName, strlen(game->shortName) + 1, 1, f);
|
||||||
|
c = game->type; fputc(c, f);
|
||||||
|
c = game->maxPlayers; fputc(c, f);
|
||||||
|
c = game->joinable; fputc(c, f);
|
||||||
|
|
||||||
|
dbGameRelease(&game);
|
||||||
|
arrdel(gameList, 0);
|
||||||
|
}
|
||||||
|
arrfree(gameList);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#define UPDATE_H
|
#define UPDATE_H
|
||||||
|
|
||||||
|
|
||||||
void update(char *params);
|
void update(void);
|
||||||
|
|
||||||
|
|
||||||
#endif // UPDATE_H
|
#endif // UPDATE_H
|
||||||
|
|
|
@ -49,12 +49,10 @@ typedef enum PacketTypeE {
|
||||||
// Packets received by only the client:
|
// Packets received by only the client:
|
||||||
PACKET_TYPE_FILE_RESPONSE,
|
PACKET_TYPE_FILE_RESPONSE,
|
||||||
PACKET_TYPE_LOGIN_RESULT,
|
PACKET_TYPE_LOGIN_RESULT,
|
||||||
PACKET_TYPE_NUMBER,
|
|
||||||
PACKET_TYPE_PING,
|
PACKET_TYPE_PING,
|
||||||
PACKET_TYPE_PROCEED,
|
PACKET_TYPE_PROCEED,
|
||||||
PACKET_TYPE_SERVER_SHUTDOWN,
|
PACKET_TYPE_SERVER_SHUTDOWN,
|
||||||
PACKET_TYPE_SIGNUP_RESULT,
|
PACKET_TYPE_SIGNUP_RESULT,
|
||||||
PACKET_TYPE_STRING,
|
|
||||||
|
|
||||||
// How many packet types do we recognize?
|
// How many packet types do we recognize?
|
||||||
PACKET_TYPE_COUNT
|
PACKET_TYPE_COUNT
|
||||||
|
|
Loading…
Add table
Reference in a new issue