File transfer code in. Still being debugged.
This commit is contained in:
parent
029a37d87d
commit
1a9fcdaaf3
20 changed files with 560 additions and 99 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -9,6 +9,7 @@ bin/
|
||||||
obj/
|
obj/
|
||||||
retired/
|
retired/
|
||||||
test/
|
test/
|
||||||
|
doors/
|
||||||
|
|
||||||
*/out/
|
*/out/
|
||||||
|
|
||||||
|
|
13
LICENSE
13
LICENSE
|
@ -19,6 +19,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
Licenses Used By:
|
Licenses Used By:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Client
|
Client
|
||||||
======
|
======
|
||||||
|
|
||||||
|
@ -42,16 +43,16 @@ MemWatch
|
||||||
http://www.linkdata.se/sourcecode/memwatch/
|
http://www.linkdata.se/sourcecode/memwatch/
|
||||||
GPL2
|
GPL2
|
||||||
|
|
||||||
minicoro
|
|
||||||
--------
|
|
||||||
https://github.com/edubart/minicoro
|
|
||||||
Public Domain or MIT No Attribution
|
|
||||||
|
|
||||||
SDL2
|
SDL2
|
||||||
----
|
----
|
||||||
https://www.libsdl.org/
|
https://www.libsdl.org/
|
||||||
BSD 3-Clause
|
BSD 3-Clause
|
||||||
|
|
||||||
|
SDL2_image
|
||||||
|
----------
|
||||||
|
https://www.libsdl.org/
|
||||||
|
BSD 3-Clause
|
||||||
|
|
||||||
SHA256
|
SHA256
|
||||||
------
|
------
|
||||||
https://github.com/ilvn/SHA256
|
https://github.com/ilvn/SHA256
|
||||||
|
@ -78,6 +79,7 @@ https://github.com/bonybrown/tiny-AES128-C
|
||||||
Unlicense
|
Unlicense
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Font Converter
|
Font Converter
|
||||||
==============
|
==============
|
||||||
|
|
||||||
|
@ -92,6 +94,7 @@ https://github.com/nothings/stb
|
||||||
Public Domain
|
Public Domain
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Server
|
Server
|
||||||
======
|
======
|
||||||
|
|
||||||
|
|
BIN
client/assets/menu.xcf
(Stored with Git LFS)
BIN
client/assets/menu.xcf
(Stored with Git LFS)
Binary file not shown.
|
@ -71,6 +71,7 @@ HEADERS = \
|
||||||
$$SHARED/packets.h \
|
$$SHARED/packets.h \
|
||||||
src/config.h \
|
src/config.h \
|
||||||
$$SHARED/util.h \
|
$$SHARED/util.h \
|
||||||
|
src/file.h \
|
||||||
src/gui/msgbox.h \
|
src/gui/msgbox.h \
|
||||||
src/gui/timer.h \
|
src/gui/timer.h \
|
||||||
src/hangup.h \
|
src/hangup.h \
|
||||||
|
@ -123,6 +124,7 @@ SOURCES = \
|
||||||
$$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/memory.c \
|
$$SHARED/memory.c \
|
||||||
|
src/file.c \
|
||||||
src/gui/msgbox.c \
|
src/gui/msgbox.c \
|
||||||
src/gui/timer.c \
|
src/gui/timer.c \
|
||||||
src/hangup.c \
|
src/hangup.c \
|
||||||
|
|
188
client/src/file.c
Normal file
188
client/src/file.c
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "network.h"
|
||||||
|
#include "packet.h"
|
||||||
|
|
||||||
|
#include "taglist.h"
|
||||||
|
#include "window.h"
|
||||||
|
#include "label.h"
|
||||||
|
|
||||||
|
#include "file.h"
|
||||||
|
|
||||||
|
|
||||||
|
static uint8_t _channel = 0;
|
||||||
|
static uint8_t _dialogVisible = 0;
|
||||||
|
static int16_t _index = -1;
|
||||||
|
static char **_fileList = NULL;
|
||||||
|
static FILE *_handle = NULL;
|
||||||
|
static fileCallback _done = NULL;
|
||||||
|
static WindowT *_winFile = NULL;
|
||||||
|
static LabelT *_lblFile = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
static void fileCheckNext(void);
|
||||||
|
static void fileShowDialog(void);
|
||||||
|
static void fileShowError(char *message);
|
||||||
|
static void packetHandler(PacketDecodeDataT *packet);
|
||||||
|
|
||||||
|
|
||||||
|
void fileCacheCheck(fileCallback callback, char *vpaths[]) {
|
||||||
|
_done = callback;
|
||||||
|
_fileList = vpaths;
|
||||||
|
_index = -1;
|
||||||
|
_dialogVisible = 0;
|
||||||
|
_channel = netChannelGet(packetHandler);
|
||||||
|
|
||||||
|
fileCheckNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void fileCheckNext(void) {
|
||||||
|
PacketEncodeDataT encoded = { 0 };
|
||||||
|
char *packetData = NULL;
|
||||||
|
uint16_t length = 0;
|
||||||
|
uint32_t temp = 0;
|
||||||
|
char *shaPointer = NULL;
|
||||||
|
static char *badSHA = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
|
||||||
|
|
||||||
|
_index++;
|
||||||
|
|
||||||
|
if (_fileList[_index] == NULL) {
|
||||||
|
// End of list!
|
||||||
|
if (_dialogVisible) guiDelete(D(_winFile));
|
||||||
|
netChannelRelease(_channel);
|
||||||
|
_done();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check next file.
|
||||||
|
temp = FILE_REQUEST_CHECK;
|
||||||
|
shaPointer = cacheSha256Get(_fileList[_index]);
|
||||||
|
if (!shaPointer) shaPointer = badSHA;
|
||||||
|
packetData = packetContentPack(&length, "iss", temp, shaPointer, _fileList[_index]);
|
||||||
|
logWrite("Checking [%d] [%s] [%s]\n", temp, shaPointer, _fileList[_index]);
|
||||||
|
encoded.control = PACKET_CONTROL_DAT;
|
||||||
|
encoded.packetType = PACKET_TYPE_FILE_REQUEST;
|
||||||
|
encoded.channel = _channel;
|
||||||
|
encoded.encrypt = 0;
|
||||||
|
packetEncode(__packetThreadData, &encoded, packetData, length);
|
||||||
|
packetSend(__packetThreadData, &encoded);
|
||||||
|
DEL(packetData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void fileShowDialog(void) {
|
||||||
|
TagItemT uiFile[] = {
|
||||||
|
T_START,
|
||||||
|
T_WINDOW, O(_winFile),
|
||||||
|
T_TITLE, P("Updating Cache"),
|
||||||
|
T_WIDTH, 200, T_HEIGHT, 100,
|
||||||
|
T_LABEL, O(_lblFile),
|
||||||
|
T_X, 41, T_Y, 25,
|
||||||
|
T_TITLE, P("Downloading..."),
|
||||||
|
T_LABEL, T_DONE,
|
||||||
|
T_WINDOW, T_DONE,
|
||||||
|
T_END
|
||||||
|
};
|
||||||
|
|
||||||
|
tagListRun(uiFile);
|
||||||
|
_dialogVisible = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void fileShowError(char *message) {
|
||||||
|
// ***TODO*** Handle error. This is fatal.
|
||||||
|
if (_dialogVisible) guiDelete(D(_winFile));
|
||||||
|
netChannelRelease(_channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void packetHandler(PacketDecodeDataT *packet) {
|
||||||
|
FileResponseT response = 0;
|
||||||
|
uint32_t fileLength = 0;
|
||||||
|
PacketEncodeDataT encoded = { 0 };
|
||||||
|
char *packetData = NULL;
|
||||||
|
uint16_t length = 0;
|
||||||
|
uint32_t temp = 0;
|
||||||
|
|
||||||
|
logWrite("Got packet %d\n", packet->packetType);
|
||||||
|
|
||||||
|
if (packet->packetType == PACKET_TYPE_FILE_RESPONSE) {
|
||||||
|
// Extract the response type. We get more data later.
|
||||||
|
packetContentUnpack(packet->data, "i", &response);
|
||||||
|
logWrite("Got response %d [%d bytes]\n", response, sizeof(response));
|
||||||
|
switch (response) {
|
||||||
|
case FILE_RESPONSE_UNKNOWN:
|
||||||
|
logWrite("Unknown file transfer response.\n");
|
||||||
|
fileShowError("Unknown file transfer response.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FILE_RESPONSE_OKAY:
|
||||||
|
// This file is already up-to-date, move on to next.
|
||||||
|
logWrite("Got FILE_RESPONSE_OKAY\n");
|
||||||
|
fileCheckNext();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FILE_RESPONSE_SEND:
|
||||||
|
// Get file size.
|
||||||
|
logWrite("Got FILE_RESPONSE_SEND\n");
|
||||||
|
packetContentUnpack(packet->data, "ii", &response, &fileLength);
|
||||||
|
// Receive new file data.
|
||||||
|
if (!_dialogVisible) fileShowDialog();
|
||||||
|
// Are we starting a new file?
|
||||||
|
if (_handle == NULL) {
|
||||||
|
logWrite("Opening [%s]\n", _fileList[_index]);
|
||||||
|
_handle = cacheFOpen(_fileList[_index], "wb");
|
||||||
|
if (!_handle) {
|
||||||
|
fileShowError("Unable to write to cache.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Write data to file, skipping first two integers stored in packet.
|
||||||
|
logWrite("Writing %d bytes to [%s]\n", packet->length - 8, _fileList[_index]);
|
||||||
|
fwrite(&packet->data[8], packet->length - 8, 1, _handle);
|
||||||
|
// Is this file complete?
|
||||||
|
if (ftell(_handle) >= fileLength) {
|
||||||
|
logWrite("Closing [%s]\n", _fileList[_index]);
|
||||||
|
// Close this file.
|
||||||
|
cacheFClose(_handle);
|
||||||
|
_handle = NULL;
|
||||||
|
// Next file!
|
||||||
|
fileCheckNext();
|
||||||
|
} else {
|
||||||
|
logWrite("Sending FILE_REQUEST_NEXT\n");
|
||||||
|
// Tell the server we got this bit of data, send the next.
|
||||||
|
temp = FILE_REQUEST_NEXT;
|
||||||
|
packetData = packetContentPack(&length, "i", temp);
|
||||||
|
encoded.control = PACKET_CONTROL_DAT;
|
||||||
|
encoded.packetType = PACKET_TYPE_FILE_REQUEST;
|
||||||
|
encoded.channel = _channel;
|
||||||
|
encoded.encrypt = 0;
|
||||||
|
packetEncode(__packetThreadData, &encoded, packetData, length);
|
||||||
|
packetSend(__packetThreadData, &encoded);
|
||||||
|
DEL(packetData);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
packetDecodeDataDestroy(&packet);
|
||||||
|
}
|
34
client/src/file.h
Normal file
34
client/src/file.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* 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 FILE_H
|
||||||
|
#define FILE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef void (*fileCallback)(void);
|
||||||
|
|
||||||
|
|
||||||
|
void fileCacheCheck(fileCallback callback, char *vpaths[]);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // FILE_H
|
|
@ -292,8 +292,6 @@ static void tableSave(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void menuShow(void);
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
if (startup(argc, argv)) return 1;
|
if (startup(argc, argv)) return 1;
|
||||||
|
@ -301,8 +299,7 @@ int main(int argc, char *argv[]) {
|
||||||
// Perform "first run" setup tasks or start the client?
|
// Perform "first run" setup tasks or start the client?
|
||||||
if (hasValidSettings()) {
|
if (hasValidSettings()) {
|
||||||
// We have what we need, start the client.
|
// We have what we need, start the client.
|
||||||
//welcomeShow();
|
welcomeShow();
|
||||||
menuShow();
|
|
||||||
} else {
|
} else {
|
||||||
// Run the setup.
|
// Run the setup.
|
||||||
settingsShow(checkSettings);
|
settingsShow(checkSettings);
|
||||||
|
|
|
@ -30,11 +30,13 @@
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "hangup.h"
|
#include "hangup.h"
|
||||||
#include "welcome.h"
|
#include "welcome.h"
|
||||||
|
#include "file.h"
|
||||||
|
|
||||||
|
|
||||||
static void btnLogoffClick(WidgetT *widget);
|
static void btnLogoffClick(WidgetT *widget);
|
||||||
static void btnOptionsClick(WidgetT *widget);
|
static void btnOptionsClick(WidgetT *widget);
|
||||||
static void btnMsgBoxLogoff(MsgBoxButtonT button);
|
static void btnMsgBoxLogoff(MsgBoxButtonT button);
|
||||||
|
static void menuFilesReady(void);
|
||||||
static void picDoorClick(WidgetT *widget);
|
static void picDoorClick(WidgetT *widget);
|
||||||
static void setButtons(uint8_t enabled);
|
static void setButtons(uint8_t enabled);
|
||||||
|
|
||||||
|
@ -67,8 +69,6 @@ static void btnMsgBoxLogoff(MsgBoxButtonT button) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void btnOptionsClick(WidgetT *widget) {
|
static void btnOptionsClick(WidgetT *widget) {
|
||||||
(void)widget;
|
(void)widget;
|
||||||
// ***TODO***
|
// ***TODO***
|
||||||
|
@ -76,7 +76,10 @@ static void btnOptionsClick(WidgetT *widget) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void menuShow(void) {
|
static void menuFilesReady(void) {
|
||||||
|
char *dos = strdup(cacheFilenameGet("menu:dosgames.png"));
|
||||||
|
char *door = strdup(cacheFilenameGet("menu:doorgames.png"));
|
||||||
|
char *fiction = strdup(cacheFilenameGet("menu:interactivefiction.png"));
|
||||||
|
|
||||||
TagItemT uiMenu[] = {
|
TagItemT uiMenu[] = {
|
||||||
T_START,
|
T_START,
|
||||||
|
@ -86,18 +89,18 @@ void menuShow(void) {
|
||||||
T_WIDTH, 350, T_HEIGHT, 275,
|
T_WIDTH, 350, T_HEIGHT, 275,
|
||||||
|
|
||||||
T_PICTURE, O(_picDOS),
|
T_PICTURE, O(_picDOS),
|
||||||
T_FILENAME, P("dos.png"),
|
T_FILENAME, P(dos),
|
||||||
T_X, 18, T_Y, 18,
|
T_X, 18, T_Y, 18,
|
||||||
T_PICTURE, T_DONE,
|
T_PICTURE, T_DONE,
|
||||||
|
|
||||||
T_PICTURE, O(_picDoor),
|
T_PICTURE, O(_picDoor),
|
||||||
T_FILENAME, P("door.png"),
|
T_FILENAME, P(door),
|
||||||
T_X, 18, T_Y, 77,
|
T_X, 18, T_Y, 77,
|
||||||
T_CLICK, P(picDoorClick),
|
T_CLICK, P(picDoorClick),
|
||||||
T_PICTURE, T_DONE,
|
T_PICTURE, T_DONE,
|
||||||
|
|
||||||
T_PICTURE, O(_picIF),
|
T_PICTURE, O(_picIF),
|
||||||
T_FILENAME, P("if.png"),
|
T_FILENAME, P(fiction),
|
||||||
T_X, 18, T_Y, 136,
|
T_X, 18, T_Y, 136,
|
||||||
T_PICTURE, T_DONE,
|
T_PICTURE, T_DONE,
|
||||||
|
|
||||||
|
@ -118,6 +121,21 @@ void menuShow(void) {
|
||||||
};
|
};
|
||||||
|
|
||||||
tagListRun(uiMenu);
|
tagListRun(uiMenu);
|
||||||
|
|
||||||
|
DEL(fiction);
|
||||||
|
DEL(door);
|
||||||
|
DEL(dos);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void menuShow(void) {
|
||||||
|
char *fileList[] = {
|
||||||
|
"menu:dosgames.png",
|
||||||
|
"menu:doorgames.png",
|
||||||
|
"menu:interactivefiction.png",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
fileCacheCheck(menuFilesReady, fileList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
|
||||||
|
|
||||||
#define CACHE_VIRTUAL_PATH_MAX 512
|
#define CACHE_VIRTUAL_PATH_MAX 512 // Should match setting in the server's client/file.h
|
||||||
|
|
||||||
|
|
||||||
typedef struct CachePreMakeListS {
|
typedef struct CachePreMakeListS {
|
||||||
|
|
|
@ -21,8 +21,8 @@ TEMPLATE = subdirs
|
||||||
CONFIG *= ORDERED
|
CONFIG *= ORDERED
|
||||||
|
|
||||||
SUBDIRS = \
|
SUBDIRS = \
|
||||||
client
|
client \
|
||||||
# server
|
server
|
||||||
# precache
|
# precache
|
||||||
# font
|
# font
|
||||||
# primes
|
# primes
|
||||||
|
|
|
@ -61,7 +61,8 @@ HEADERS = \
|
||||||
src/os.h \
|
src/os.h \
|
||||||
src/rest.h \
|
src/rest.h \
|
||||||
src/database.h \
|
src/database.h \
|
||||||
src/server.h
|
src/server.h \
|
||||||
|
src/settings.h
|
||||||
|
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
$$SHARED/thirdparty/memwatch/memwatch.c \
|
$$SHARED/thirdparty/memwatch/memwatch.c \
|
||||||
|
@ -85,7 +86,8 @@ SOURCES = \
|
||||||
src/network.c \
|
src/network.c \
|
||||||
src/rest.c \
|
src/rest.c \
|
||||||
src/database.c \
|
src/database.c \
|
||||||
src/server.c
|
src/server.c \
|
||||||
|
src/settings.c
|
||||||
|
|
||||||
LIBS = \
|
LIBS = \
|
||||||
-L/usr/lib/x86_64-linux-gnu/ \
|
-L/usr/lib/x86_64-linux-gnu/ \
|
||||||
|
|
|
@ -52,6 +52,8 @@ typedef struct ClientThreadS {
|
||||||
void *peer;
|
void *peer;
|
||||||
// User State Stuff.
|
// User State Stuff.
|
||||||
uint8_t authenticated;
|
uint8_t authenticated;
|
||||||
|
FILE *handle; // ***TODO*** Needs to support more than one file transfer at a time.
|
||||||
|
uint32_t fileSize; // Length of current file being transferred.
|
||||||
} ClientThreadT;
|
} ClientThreadT;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,14 +19,13 @@
|
||||||
|
|
||||||
|
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
|
|
||||||
|
|
||||||
static void clientApiFileRequestCacheCheck(ClientThreadT *client, PacketDecodeDataT *data);
|
static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT *data);
|
||||||
static void clientApiFileRequestClose(ClientThreadT *client, PacketDecodeDataT *data);
|
static void clientApiFileRequestNext(ClientThreadT *client, PacketDecodeDataT *data);
|
||||||
static void clientApiFileRequestOpen(ClientThreadT *client, PacketDecodeDataT *data);
|
|
||||||
static void clientApiFileRequestRead(ClientThreadT *client, PacketDecodeDataT *data);
|
|
||||||
|
|
||||||
|
|
||||||
void clientApiFileRequest(ClientThreadT *client, PacketDecodeDataT *data) {
|
void clientApiFileRequest(ClientThreadT *client, PacketDecodeDataT *data) {
|
||||||
|
@ -36,30 +35,23 @@ void clientApiFileRequest(ClientThreadT *client, PacketDecodeDataT *data) {
|
||||||
uint16_t length = 0;
|
uint16_t length = 0;
|
||||||
|
|
||||||
// Must be logged in to do file operations.
|
// Must be logged in to do file operations.
|
||||||
if (!client->authenticated) {
|
if (client->authenticated) {
|
||||||
// Extract the request type. We get more data later.
|
// Extract the request type. We get more data later.
|
||||||
packetContentUnpack(data->data, "i", &request);
|
packetContentUnpack(data->data, "i", &request);
|
||||||
|
|
||||||
switch (request) {
|
switch (request) {
|
||||||
case FILE_REQUEST_CACHE_CHECK:
|
case FILE_REQUEST_CHECK:
|
||||||
clientApiFileRequestCacheCheck(client, data);
|
clientApiFileRequestCheck(client, data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FILE_REQUEST_OPEN:
|
case FILE_REQUEST_NEXT:
|
||||||
clientApiFileRequestOpen(client, data);
|
clientApiFileRequestNext(client, data);
|
||||||
break;
|
|
||||||
|
|
||||||
case FILE_REQUEST_READ:
|
|
||||||
clientApiFileRequestRead(client, data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FILE_REQUEST_CLOSE:
|
|
||||||
clientApiFileRequestClose(client, data);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// No idea what they want. First value is 0 for fail, 1 for success.
|
logWrite("Got FILE_REQUEST_UNKNOWN [%d] %d\n\r", request, data->length);
|
||||||
packetData = packetContentPack(&length, "i", 0);
|
// No idea what they want.
|
||||||
|
packetData = packetContentPack(&length, "i", FILE_RESPONSE_UNKNOWN);
|
||||||
// Build packet.
|
// Build packet.
|
||||||
encoded.control = PACKET_CONTROL_DAT;
|
encoded.control = PACKET_CONTROL_DAT;
|
||||||
encoded.packetType = PACKET_TYPE_FILE_RESPONSE;
|
encoded.packetType = PACKET_TYPE_FILE_RESPONSE;
|
||||||
|
@ -76,51 +68,99 @@ void clientApiFileRequest(ClientThreadT *client, PacketDecodeDataT *data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void clientApiFileRequestCacheCheck(ClientThreadT *client, PacketDecodeDataT *data) {
|
static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT *data) {
|
||||||
FileRequestsT request = 0;
|
FileRequestsT request = 0;
|
||||||
char *path = NULL;
|
char *path = NULL;
|
||||||
char *sha256 = NULL;
|
char *sha256 = NULL;
|
||||||
PacketEncodeDataT encoded = { 0 };
|
PacketEncodeDataT encoded = { 0 };
|
||||||
char *packetData = NULL;
|
char *packetData = NULL;
|
||||||
uint16_t length = 0;
|
uint16_t length = 0;
|
||||||
|
char buffer[1024] = { 0 };
|
||||||
|
char buffer2[1024] = { 0 };
|
||||||
|
uint32_t temp = 0;
|
||||||
|
|
||||||
|
logWrite("Got FILE_REQUEST_CHECK\n\r");
|
||||||
|
|
||||||
// Extract the request.
|
// Extract the request.
|
||||||
packetContentUnpack(data->data, "i", &request, &path, &sha256);
|
packetContentUnpack(data->data, "iss", &request, &sha256, &path);
|
||||||
|
logWrite("[%s] [%s]\n\r", sha256, path);
|
||||||
// Look up the entry and compare SHA.
|
|
||||||
|
|
||||||
|
// Look up the entry and compare SHA256.
|
||||||
|
dbFileSha256Get(path, buffer, FILE_VIRTUAL_PATH_MAX);
|
||||||
|
if (strcasecmp(sha256, buffer) == 0) {
|
||||||
|
logWrite("File is current. Sending FILE_RESPONSE_OKAY.\n\r");
|
||||||
|
// File is already current on client.
|
||||||
|
temp = FILE_RESPONSE_OKAY;
|
||||||
|
packetData = packetContentPack(&length, "i", temp);
|
||||||
|
encoded.control = PACKET_CONTROL_DAT;
|
||||||
|
encoded.packetType = PACKET_TYPE_FILE_RESPONSE;
|
||||||
|
encoded.channel = data->channel;
|
||||||
|
encoded.encrypt = 0;
|
||||||
|
packetEncode(client->packetThreadData, &encoded, packetData, length);
|
||||||
|
packetSend(client->packetThreadData, &encoded);
|
||||||
|
DEL(packetData);
|
||||||
|
} else {
|
||||||
|
logWrite("File needs updated.\n\r");
|
||||||
|
// Get real path.
|
||||||
|
dbFileRealPathGet(path, buffer, FILE_VIRTUAL_PATH_MAX);
|
||||||
|
snprintf(buffer2, 1024, "%s%s", __settingsFile, buffer);
|
||||||
|
// Open file & get file size.
|
||||||
|
client->handle = fopen(buffer2, "rb");
|
||||||
|
if (!client->handle) {
|
||||||
|
// ***TODO*** Handle error
|
||||||
|
}
|
||||||
|
fseek(client->handle, 0, SEEK_END);
|
||||||
|
client->fileSize = ftell(client->handle);
|
||||||
|
fseek(client->handle, 0, SEEK_SET);
|
||||||
|
// Start sending new file to client.
|
||||||
|
packetData = (char *)malloc(PACKET_MAX);
|
||||||
|
if (!packetData) {
|
||||||
|
// ***TODO*** Handle error
|
||||||
|
}
|
||||||
|
logWrite("Size is %d\n\r", client->fileSize);
|
||||||
|
clientApiFileRequestNext(client, data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void clientApiFileRequestClose(ClientThreadT *client, PacketDecodeDataT *data) {
|
static void clientApiFileRequestNext(ClientThreadT *client, PacketDecodeDataT *data) {
|
||||||
FileRequestsT request = 0;
|
uint32_t temp = 0;
|
||||||
PacketEncodeDataT encoded = { 0 };
|
PacketEncodeDataT encoded = { 0 };
|
||||||
char *packetData = NULL;
|
|
||||||
uint16_t length = 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void clientApiFileRequestOpen(ClientThreadT *client, PacketDecodeDataT *data) {
|
|
||||||
FileRequestsT request = 0;
|
|
||||||
char *path = NULL;
|
|
||||||
char *sha256 = NULL;
|
|
||||||
PacketEncodeDataT encoded = { 0 };
|
|
||||||
char *packetData = NULL;
|
|
||||||
uint16_t length = 0;
|
|
||||||
|
|
||||||
// Extract the request.
|
|
||||||
packetContentUnpack(data->data, "i", &request, &path);
|
|
||||||
|
|
||||||
// Look up the entry and fetch SHA.
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void clientApiFileRequestRead(ClientThreadT *client, PacketDecodeDataT *data) {
|
|
||||||
FileRequestsT request = 0;
|
|
||||||
PacketEncodeDataT encoded = { 0 };
|
|
||||||
char *packetData = NULL;
|
|
||||||
uint16_t length = 0;
|
uint16_t length = 0;
|
||||||
|
uint16_t dataSize = 0;
|
||||||
|
char packetData[PACKET_MAX];
|
||||||
|
|
||||||
|
// Do we have an open file?
|
||||||
|
if (client->handle) {
|
||||||
|
logWrite("Sending FILE_RESPONSE_SEND.\n\r");
|
||||||
|
// Add response type.
|
||||||
|
temp = FILE_RESPONSE_SEND;
|
||||||
|
memcpy(packetData, &temp, sizeof(int32_t));
|
||||||
|
|
||||||
|
// Add file length.
|
||||||
|
memcpy(&packetData[4], &client->fileSize, sizeof(int32_t));
|
||||||
|
|
||||||
|
// Add file data.
|
||||||
|
dataSize = client->fileSize - ftell(client->handle);
|
||||||
|
if (dataSize > PACKET_MAX - 8) {
|
||||||
|
// File is larger than a packet size.
|
||||||
|
dataSize = PACKET_MAX - 8; // 8 for two integers of response data.
|
||||||
|
fread(&packetData[8], dataSize, 1, client->handle);
|
||||||
|
} else {
|
||||||
|
// File remains will fit in this packet.
|
||||||
|
fread(&packetData[8], dataSize, 1, client->handle);
|
||||||
|
fclose(client->handle);
|
||||||
|
client->handle = NULL;
|
||||||
|
}
|
||||||
|
logWrite("Sending %d bytes\n\r", dataSize);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define FILE_VIRTUAL_PATH_MAX 512 // Should match setting in the client's cache.h
|
||||||
|
|
||||||
|
|
||||||
void clientApiFileRequest(ClientThreadT *client, PacketDecodeDataT *data);
|
void clientApiFileRequest(ClientThreadT *client, PacketDecodeDataT *data);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,102 @@ uint8_t dbDisconnect(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t dbFileRealPathGet(char *vpath, char *value, uint32_t max) {
|
||||||
|
char statement[STATEMENT_MAX];
|
||||||
|
char *p = statement;
|
||||||
|
MYSQL_RES *result = NULL;
|
||||||
|
MYSQL_ROW row;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&_mutex);
|
||||||
|
|
||||||
|
if (!_sql) {
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
p += sprintf(p, "SELECT realPath FROM files WHERE virtualPath='");
|
||||||
|
p += mysql_real_escape_string(_sql, p, vpath, strlen(vpath));
|
||||||
|
p += sprintf(p, "'");
|
||||||
|
if (mysql_real_query(_sql, statement, p - statement) != 0) {
|
||||||
|
logWrite("dbFileRealPathGet: %s\n", mysql_error(_sql));
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = mysql_store_result(_sql);
|
||||||
|
count = mysql_num_rows(result);
|
||||||
|
if (count != 1) {
|
||||||
|
logWrite("dbFileRealPathGet: Wrong number of rows returned: %d.\n", count);
|
||||||
|
mysql_free_result(result);
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((row = mysql_fetch_row(result)) == NULL) {
|
||||||
|
logWrite("dbFileRealPathGet: %s\n", mysql_error(_sql));
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(value, row[0], max);
|
||||||
|
|
||||||
|
mysql_free_result(result);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t dbFileSha256Get(char *vpath, char *value, uint32_t max) {
|
||||||
|
char statement[STATEMENT_MAX];
|
||||||
|
char *p = statement;
|
||||||
|
MYSQL_RES *result = NULL;
|
||||||
|
MYSQL_ROW row;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&_mutex);
|
||||||
|
|
||||||
|
if (!_sql) {
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
p += sprintf(p, "SELECT sha256 FROM files WHERE virtualPath='");
|
||||||
|
p += mysql_real_escape_string(_sql, p, vpath, strlen(vpath));
|
||||||
|
p += sprintf(p, "'");
|
||||||
|
if (mysql_real_query(_sql, statement, p - statement) != 0) {
|
||||||
|
logWrite("dbFileSha256Get: %s\n", mysql_error(_sql));
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = mysql_store_result(_sql);
|
||||||
|
count = mysql_num_rows(result);
|
||||||
|
if (count != 1) {
|
||||||
|
logWrite("dbFileSha256Get: Wrong number of rows returned: %d.\n", count);
|
||||||
|
mysql_free_result(result);
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((row = mysql_fetch_row(result)) == NULL) {
|
||||||
|
logWrite("dbFileSha256Get: %s\n", mysql_error(_sql));
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(value, row[0], max);
|
||||||
|
|
||||||
|
mysql_free_result(result);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&_mutex);
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t dbSettingsStringGet(char *host, char *key, char *value, uint32_t max) {
|
uint8_t dbSettingsStringGet(char *host, char *key, char *value, uint32_t max) {
|
||||||
char statement[STATEMENT_MAX];
|
char statement[STATEMENT_MAX];
|
||||||
char *p = statement;
|
char *p = statement;
|
||||||
|
|
|
@ -36,6 +36,8 @@ typedef struct DBTableS {
|
||||||
|
|
||||||
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);
|
uint8_t dbDisconnect(void);
|
||||||
|
uint8_t dbFileRealPathGet(char *vpath, char *value, uint32_t max);
|
||||||
|
uint8_t dbFileSha256Get(char *vpath, char *value, uint32_t max);
|
||||||
uint8_t dbSettingsStringGet(char *host, char *key, char *value, uint32_t max);
|
uint8_t dbSettingsStringGet(char *host, char *key, char *value, uint32_t max);
|
||||||
uint8_t dbSettingsValueGet(char *host, char *key, int32_t *value);
|
uint8_t dbSettingsValueGet(char *host, char *key, int32_t *value);
|
||||||
uint8_t dbTableGet(char *which, DBTableT ***table);
|
uint8_t dbTableGet(char *which, DBTableT ***table);
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "rest.h"
|
#include "rest.h"
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
#include "thirdparty/ini/src/ini.h"
|
#include "thirdparty/ini/src/ini.h"
|
||||||
|
|
||||||
|
@ -102,13 +103,6 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
char *configFile = NULL;
|
char *configFile = NULL;
|
||||||
char hostname[256] = { 0 };
|
char hostname[256] = { 0 };
|
||||||
char settingsFile[DB_CONFIG_ITEM_SIZE] = { 0 };
|
|
||||||
char settingsRest[DB_CONFIG_ITEM_SIZE] = { 0 };
|
|
||||||
char settingsUser[DB_CONFIG_ITEM_SIZE] = { 0 };
|
|
||||||
char settingsPass[DB_CONFIG_ITEM_SIZE] = { 0 };
|
|
||||||
int64_t settingsMaxClients = 0;
|
|
||||||
int64_t settingsPortNumber = 0;
|
|
||||||
int64_t settingsClientVersion = 0;
|
|
||||||
|
|
||||||
(void)argc;
|
(void)argc;
|
||||||
|
|
||||||
|
@ -130,22 +124,22 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch settings needed to start server.
|
// Fetch settings needed to start server.
|
||||||
if (!dbSettingsValueGet(hostname, "maxClients", (int32_t *)&settingsMaxClients)) utilDie("Unable to load maxClients.\n");
|
if (!dbSettingsValueGet(hostname, "maxClients", (int32_t *)&__settingsMaxClients)) utilDie("Unable to load maxClients.\n");
|
||||||
if (!dbSettingsValueGet(hostname, "portNumber", (int32_t *)&settingsPortNumber)) utilDie("Unable to load portNumber.\n");
|
if (!dbSettingsValueGet(hostname, "portNumber", (int32_t *)&__settingsPortNumber)) utilDie("Unable to load portNumber.\n");
|
||||||
if (!dbSettingsValueGet(hostname, "clientVersion", (int32_t *)&settingsClientVersion)) utilDie("Unable to load clientVersion.\n");
|
if (!dbSettingsValueGet(hostname, "clientVersion", (int32_t *)&__settingsClientVersion)) utilDie("Unable to load clientVersion.\n");
|
||||||
if (!dbSettingsStringGet(hostname, "fileLocation", settingsFile, DB_CONFIG_ITEM_SIZE)) utilDie("Unable to load file location.\n");
|
if (!dbSettingsStringGet(hostname, "fileLocation", __settingsFile, DB_CONFIG_ITEM_SIZE)) utilDie("Unable to load file location.\n");
|
||||||
if (!dbSettingsStringGet(hostname, "restEndpoint", settingsRest, DB_CONFIG_ITEM_SIZE)) utilDie("Unable to load REST URL.\n");
|
if (!dbSettingsStringGet(hostname, "restEndpoint", __settingsRest, DB_CONFIG_ITEM_SIZE)) utilDie("Unable to load REST URL.\n");
|
||||||
if (!dbSettingsStringGet(hostname, "restUser", settingsUser, DB_CONFIG_ITEM_SIZE)) utilDie("Unable to load REST user.\n");
|
if (!dbSettingsStringGet(hostname, "restUser", __settingsUser, DB_CONFIG_ITEM_SIZE)) utilDie("Unable to load REST user.\n");
|
||||||
if (!dbSettingsStringGet(hostname, "restPassword", settingsPass, DB_CONFIG_ITEM_SIZE)) utilDie("Unable to load REST password.\n");
|
if (!dbSettingsStringGet(hostname, "restPassword", __settingsPass, DB_CONFIG_ITEM_SIZE)) utilDie("Unable to load REST password.\n");
|
||||||
|
|
||||||
// Start up REST.
|
// Start up REST.
|
||||||
if (!restStartup(settingsRest, settingsUser, settingsPass)) {
|
if (!restStartup(__settingsRest, __settingsUser, __settingsPass)) {
|
||||||
logWrite("Unable to locate REST endpoint. Web site integration disabled.\n");
|
logWrite("Unable to locate REST endpoint. Web site integration disabled.\n");
|
||||||
__restAvailable = 0;
|
__restAvailable = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
clientStartup();
|
clientStartup();
|
||||||
serverStartup(settingsPortNumber, settingsMaxClients);
|
serverStartup(__settingsPortNumber, __settingsMaxClients);
|
||||||
logWrite("Server online.\n");
|
logWrite("Server online.\n");
|
||||||
|
|
||||||
// Run Console.
|
// Run Console.
|
||||||
|
|
30
server/src/settings.c
Normal file
30
server/src/settings.c
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
|
|
||||||
|
char __settingsFile[DB_CONFIG_ITEM_SIZE] = { 0 };
|
||||||
|
char __settingsRest[DB_CONFIG_ITEM_SIZE] = { 0 };
|
||||||
|
char __settingsUser[DB_CONFIG_ITEM_SIZE] = { 0 };
|
||||||
|
char __settingsPass[DB_CONFIG_ITEM_SIZE] = { 0 };
|
||||||
|
int64_t __settingsMaxClients = 0;
|
||||||
|
int64_t __settingsPortNumber = 0;
|
||||||
|
int64_t __settingsClientVersion = 0;
|
37
server/src/settings.h
Normal file
37
server/src/settings.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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 SETTINGS_H
|
||||||
|
#define SETTINGS_H
|
||||||
|
|
||||||
|
#include "os.h"
|
||||||
|
#include "database.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern char __settingsFile[DB_CONFIG_ITEM_SIZE];
|
||||||
|
extern char __settingsRest[DB_CONFIG_ITEM_SIZE];
|
||||||
|
extern char __settingsUser[DB_CONFIG_ITEM_SIZE];
|
||||||
|
extern char __settingsPass[DB_CONFIG_ITEM_SIZE];
|
||||||
|
extern int64_t __settingsMaxClients;
|
||||||
|
extern int64_t __settingsPortNumber;
|
||||||
|
extern int64_t __settingsClientVersion;
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SETTINGS_H
|
|
@ -60,13 +60,25 @@ typedef enum PacketTypeE {
|
||||||
PACKET_TYPE_COUNT
|
PACKET_TYPE_COUNT
|
||||||
} PacketTypeT;
|
} PacketTypeT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Client -> PACKET_TYPE_FILE_REQUEST FILE_REQUEST_CHECK SHA256 VPATH
|
||||||
|
* Server -> PACKET_TYPE_FILE_RESPONSE FILE_RESPONSE_OKAY
|
||||||
|
* - or -
|
||||||
|
* Server -> PACKET_TYPE_FILE_RESPONSE FILE_RESPONSE_SEND (4 bytes length) (data...)
|
||||||
|
* Client -> PACKET_TYPE_FILE_REQUEST FILE_REQUEST_NEXT
|
||||||
|
* (Repeat until received data matches the length.)
|
||||||
|
*/
|
||||||
typedef enum FileRequestsE {
|
typedef enum FileRequestsE {
|
||||||
FILE_REQUEST_UNKNOWN = 0,
|
FILE_REQUEST_UNKNOWN = 0,
|
||||||
FILE_REQUEST_CACHE_CHECK,
|
FILE_REQUEST_CHECK,
|
||||||
FILE_REQUEST_OPEN,
|
FILE_REQUEST_NEXT
|
||||||
FILE_REQUEST_READ,
|
|
||||||
FILE_REQUEST_CLOSE
|
|
||||||
} FileRequestsT;
|
} FileRequestsT;
|
||||||
|
|
||||||
|
typedef enum FileResponseE {
|
||||||
|
FILE_RESPONSE_UNKNOWN = 0,
|
||||||
|
FILE_RESPONSE_OKAY,
|
||||||
|
FILE_RESPONSE_SEND
|
||||||
|
} FileResponseT;
|
||||||
|
|
||||||
|
|
||||||
#endif // PACKETS_H
|
#endif // PACKETS_H
|
||||||
|
|
Loading…
Add table
Reference in a new issue