166 lines
5.4 KiB
C
166 lines
5.4 KiB
C
/*
|
|
* 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 "database.h"
|
|
#include "settings.h"
|
|
|
|
#include "file.h"
|
|
|
|
|
|
static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT *data);
|
|
static void clientApiFileRequestNext(ClientThreadT *client, PacketDecodeDataT *data);
|
|
|
|
|
|
void clientApiFileRequest(ClientThreadT *client, PacketDecodeDataT *data) {
|
|
FileRequestsT request = 0;
|
|
PacketEncodeDataT encoded = { 0 };
|
|
char *packetData = NULL;
|
|
uint16_t length = 0;
|
|
|
|
// Must be logged in to do file operations.
|
|
if (client->authenticated) {
|
|
// Extract the request type. We get more data later.
|
|
packetContentUnpack(data->data, "i", &request);
|
|
|
|
switch (request) {
|
|
case FILE_REQUEST_CHECK:
|
|
clientApiFileRequestCheck(client, data);
|
|
break;
|
|
|
|
case FILE_REQUEST_NEXT:
|
|
clientApiFileRequestNext(client, data);
|
|
break;
|
|
|
|
default:
|
|
logWrite("Got FILE_REQUEST_UNKNOWN [%d] %d\n\r", request, data->length);
|
|
// No idea what they want.
|
|
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
|
|
}
|
|
|
|
|
|
static void clientApiFileRequestCheck(ClientThreadT *client, PacketDecodeDataT *data) {
|
|
FileRequestsT request = 0;
|
|
char *path = NULL;
|
|
char *sha256 = NULL;
|
|
PacketEncodeDataT encoded = { 0 };
|
|
char *packetData = NULL;
|
|
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.
|
|
packetContentUnpack(data->data, "iss", &request, &sha256, &path);
|
|
logWrite("[%s] [%s]\n\r", sha256, path);
|
|
|
|
// 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 clientApiFileRequestNext(ClientThreadT *client, PacketDecodeDataT *data) {
|
|
uint32_t temp = 0;
|
|
PacketEncodeDataT encoded = { 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);
|
|
}
|
|
}
|