Pushing broken PHP in hope for help.
This commit is contained in:
parent
597284e28f
commit
cb34b340ae
19 changed files with 561 additions and 57 deletions
|
@ -253,12 +253,33 @@ int main(int argc, char *argv[]) {
|
||||||
__packetThreadData = packetThreadDataCreate(NULL);
|
__packetThreadData = packetThreadDataCreate(NULL);
|
||||||
packetSenderRegister(comPacketSender);
|
packetSenderRegister(comPacketSender);
|
||||||
|
|
||||||
|
__runtimeData.integers = NULL;
|
||||||
|
__runtimeData.strings = NULL;
|
||||||
|
__runtimeData.protocolVersion = 0;
|
||||||
|
|
||||||
//taskCreate(taskComDebugLoop, NULL);
|
//taskCreate(taskComDebugLoop, NULL);
|
||||||
taskCreate(taskWelcome, NULL);
|
taskCreate(taskWelcome, NULL);
|
||||||
taskCreate(taskGuiEventLoop, NULL);
|
taskCreate(taskGuiEventLoop, NULL);
|
||||||
|
|
||||||
taskRun();
|
taskRun();
|
||||||
|
|
||||||
|
// Free integer table.
|
||||||
|
if (__runtimeData.integers) {
|
||||||
|
while (shlen(__runtimeData.integers) > 0) {
|
||||||
|
shdel(__runtimeData.integers, __runtimeData.integers[0].key);
|
||||||
|
}
|
||||||
|
shfree(__runtimeData.integers);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free string table.
|
||||||
|
if (__runtimeData.strings) {
|
||||||
|
while (shlen(__runtimeData.strings) > 0) {
|
||||||
|
DEL(__runtimeData.strings[0].value);
|
||||||
|
shdel(__runtimeData.strings, __runtimeData.strings[0].key);
|
||||||
|
}
|
||||||
|
shfree(__runtimeData.strings);
|
||||||
|
}
|
||||||
|
|
||||||
packetThreadDataDestroy(&__packetThreadData);
|
packetThreadDataDestroy(&__packetThreadData);
|
||||||
|
|
||||||
taskShutdown();
|
taskShutdown();
|
||||||
|
|
|
@ -25,8 +25,21 @@
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct StringMapS {
|
||||||
|
char *key;
|
||||||
|
char *value;
|
||||||
|
} StringMapT;
|
||||||
|
|
||||||
|
typedef struct IntegerMapS {
|
||||||
|
char *key;
|
||||||
|
int32_t value;
|
||||||
|
} IntegerMapT;
|
||||||
|
|
||||||
|
|
||||||
typedef struct RuntimeDataS {
|
typedef struct RuntimeDataS {
|
||||||
uint32_t protocolVersion;
|
uint32_t protocolVersion;
|
||||||
|
StringMapT *strings;
|
||||||
|
IntegerMapT *integers;
|
||||||
} RuntimeDataT;
|
} RuntimeDataT;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,9 @@ static void taskConnectClick(void *data) {
|
||||||
int32_t r = 0;
|
int32_t r = 0;
|
||||||
char buffer[1024] = { 0 };
|
char buffer[1024] = { 0 };
|
||||||
PacketDecodeDataT *decoded = NULL;
|
PacketDecodeDataT *decoded = NULL;
|
||||||
|
PacketEncodeDataT encoded = { 0 };
|
||||||
int16_t timeout = 0;
|
int16_t timeout = 0;
|
||||||
|
uint8_t waiting = 1;
|
||||||
|
|
||||||
(void)data;
|
(void)data;
|
||||||
|
|
||||||
|
@ -153,20 +155,62 @@ static void taskConnectClick(void *data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for version packet to arrive.
|
// Wait for version and table packets to arrive.
|
||||||
timeout = 10;
|
timeout = 10;
|
||||||
do {
|
do {
|
||||||
decoded = netGetPacket(0);
|
decoded = netGetPacket(0);
|
||||||
if (decoded) {
|
if (decoded) {
|
||||||
if (decoded->packetType == PACKET_TYPE_VERSION) {
|
switch (decoded->packetType) {
|
||||||
__runtimeData.protocolVersion = *(uint32_t *)decoded->data;
|
case PACKET_TYPE_NUMBER:
|
||||||
packetDecodeDataDestroy(&decoded);
|
// Store in number table.
|
||||||
break;
|
logWrite("Added integer: [%s] = [%d]\n", &decoded->data[4], (int32_t)decoded->data[0]);
|
||||||
|
shput(__runtimeData.integers, &decoded->data[4], (int32_t)decoded->data[0]);
|
||||||
|
// Reset timeout.
|
||||||
|
timeout = 10;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PACKET_TYPE_PROCEED:
|
||||||
|
waiting = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PACKET_TYPE_STRING:
|
||||||
|
// Store in string table.
|
||||||
|
logWrite("Added string: [%s] = [%s]\n", decoded->data, &decoded->data[strlen(decoded->data) + 1]);
|
||||||
|
shput(__runtimeData.strings, decoded->data, strdup(&decoded->data[strlen(decoded->data) + 1]));
|
||||||
|
// Reset timeout.
|
||||||
|
timeout = 10;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PACKET_TYPE_VERSION:
|
||||||
|
__runtimeData.protocolVersion = *(uint32_t *)decoded->data;
|
||||||
|
packetDecodeDataDestroy(&decoded);
|
||||||
|
// Do we need to update?
|
||||||
|
if (PACKET_PROTOCOL_VERSION == __runtimeData.protocolVersion) {
|
||||||
|
// Nope, we're good.
|
||||||
|
encoded.packetType = PACKET_TYPE_VERSION_OKAY;
|
||||||
|
} else {
|
||||||
|
// Version mismatch - upgrade time!
|
||||||
|
encoded.packetType = PACKET_TYPE_VERSION_BAD;
|
||||||
|
//***TODO***
|
||||||
|
}
|
||||||
|
encoded.control = PACKET_CONTROL_DAT;
|
||||||
|
encoded.channel = 0;
|
||||||
|
encoded.encrypt = 0;
|
||||||
|
packetEncode(__packetThreadData, &encoded, NULL, 0);
|
||||||
|
// Send GOOD or BAD.
|
||||||
|
packetSend(__packetThreadData, &encoded);
|
||||||
|
// Reset timeout.
|
||||||
|
timeout = 10;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
logWrite("Unexpected packet received: %d\n", decoded->packetType);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
taskYield();
|
taskYield();
|
||||||
if (__timerSecondTick) timeout--;
|
if (__timerSecondTick) timeout--;
|
||||||
} while (!guiHasStopped() && timeout >= 0);
|
} while (!guiHasStopped() && timeout >= 0 && waiting);
|
||||||
if (timeout < 0) {
|
if (timeout < 0) {
|
||||||
comClose(__configData.serialCom - 1);
|
comClose(__configData.serialCom - 1);
|
||||||
msgBoxOne("Negotiation Error", MSGBOX_ICON_INFORMATION, "Unable to fetch client settings!", "Okay", btnMsgBox);
|
msgBoxOne("Negotiation Error", MSGBOX_ICON_INFORMATION, "Unable to fetch client settings!", "Okay", btnMsgBox);
|
||||||
|
|
|
@ -6,6 +6,17 @@ return [
|
||||||
'extra' => false
|
'extra' => false
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
||||||
|
'kangaroopunch.kangaworld-integration' => [
|
||||||
|
'sql' => [
|
||||||
|
'host' => 'mysql',
|
||||||
|
'port' => 3306,
|
||||||
|
'data' => 'dosThing',
|
||||||
|
'user' => 'dosThing',
|
||||||
|
'pass' => 'password'
|
||||||
|
]
|
||||||
|
],
|
||||||
|
|
||||||
// For REST APIs.
|
// For REST APIs.
|
||||||
'api' => [
|
'api' => [
|
||||||
'basicAuth' => true,
|
'basicAuth' => true,
|
||||||
|
|
|
@ -6,4 +6,18 @@ function kpApiConfigGetConfig(&$response) {
|
||||||
$response['reason'] = 'Configuration entries returned.';
|
$response['reason'] = 'Configuration entries returned.';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function kpApiConfigGetNumbers(&$response) {
|
||||||
|
$response['config'] = collection('kwconfig')->filterBy('type', 'number');
|
||||||
|
$response['result'] = 'true';
|
||||||
|
$response['reason'] = 'Number entries returned.';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function kpApiConfigGetStrings(&$response) {
|
||||||
|
$response['config'] = collection('kwconfig')->filterBy('type', 'string');
|
||||||
|
$response['result'] = 'true';
|
||||||
|
$response['reason'] = 'String entries returned.';
|
||||||
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
11
kanga.world/site/plugins/kangaworld-integration/api/test.php
Normal file
11
kanga.world/site/plugins/kangaworld-integration/api/test.php
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function kpApiTest(&$response) {
|
||||||
|
|
||||||
|
$response['payload'] = collection('kwstrings');
|
||||||
|
$response['result'] = 'true';
|
||||||
|
$response['reason'] = 'Dataset returned.';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
return [
|
|
||||||
|
|
||||||
'kwconfig' => [
|
|
||||||
'label' => 'Kanga World Configuration',
|
|
||||||
'icon' => 'globe',
|
|
||||||
'menu' => true,
|
|
||||||
// update and delete dialogs
|
|
||||||
'dialogs' => [
|
|
||||||
require __DIR__ . '/dialogs/create.php',
|
|
||||||
require __DIR__ . '/dialogs/update.php',
|
|
||||||
require __DIR__ . '/dialogs/delete.php'
|
|
||||||
],
|
|
||||||
// dropdown with edit and delete buttons
|
|
||||||
'dropdowns' => [
|
|
||||||
require __DIR__ . '/dropdowns/kwconfig.php'
|
|
||||||
],
|
|
||||||
// search for settings
|
|
||||||
'searches' => [
|
|
||||||
'kwconfig' => require __DIR__ . '/searches/kwconfig.php'
|
|
||||||
],
|
|
||||||
// view route
|
|
||||||
'views' => [
|
|
||||||
require __DIR__ . '/views/kwconfig.php',
|
|
||||||
require __DIR__ . '/views/kwentry.php'
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
];
|
|
||||||
|
|
||||||
?>
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace KangarooPunch;
|
||||||
|
|
||||||
|
class KPunch {
|
||||||
|
|
||||||
|
public static function databaseGet() {
|
||||||
|
|
||||||
|
$db = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$host = option('kangaroopunch.kangaworld-integration.sql.host');
|
||||||
|
$port = option('kangaroopunch.kangaworld-integration.sql.port');
|
||||||
|
$data = option('kangaroopunch.kangaworld-integration.sql.data');
|
||||||
|
$user = option('kangaroopunch.kangaworld-integration.sql.user');
|
||||||
|
$pass = option('kangaroopunch.kangaworld-integration.sql.pass');
|
||||||
|
$db = new PDO("mysql:host=$host;port=$port;dbname=$data", $user, $pass);
|
||||||
|
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||||
|
} catch(PDOException $ex) {
|
||||||
|
$db = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $db;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function databaseQueryToJSON($db, $query, $options = null) {
|
||||||
|
|
||||||
|
$result = null;
|
||||||
|
|
||||||
|
if ($db) {
|
||||||
|
$statement = $db->prepare($query);
|
||||||
|
$statement->execute($options);
|
||||||
|
$resultset = array();
|
||||||
|
while ($row = $statement->fetch(PDO::FETCH_ASSOC)) {
|
||||||
|
$resultset[] = $row;
|
||||||
|
}
|
||||||
|
$result = json_encode($resultset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
|
@ -0,0 +1,90 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace KangarooPunch;
|
||||||
|
|
||||||
|
|
||||||
|
use KangarooPunch\KPunch;
|
||||||
|
use Kirby\Exception\InvalidArgumentException;
|
||||||
|
use Kirby\Exception\NotFoundException;
|
||||||
|
use Kirby\Toolkit\V;
|
||||||
|
|
||||||
|
|
||||||
|
class KwStrings {
|
||||||
|
|
||||||
|
public static function create(array $input): bool {
|
||||||
|
validate($input);
|
||||||
|
$db = KPunch::databaseGet();
|
||||||
|
KPunch::databaseQueryToJSON($db,
|
||||||
|
'INSERT INTO strings (name, data, description) VALUES (?, ?, ?)',
|
||||||
|
array(
|
||||||
|
$input['name'],
|
||||||
|
$input['data'],
|
||||||
|
$input['description']
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function delete(string $id): bool {
|
||||||
|
$db = KPunch::databaseGet();
|
||||||
|
KPunch::databaseQueryToJSON($db, 'DELETE FROM strings WHERE id = ?', array($id));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function find(string $id): array {
|
||||||
|
$db = KPunch::databaseGet();
|
||||||
|
$result = KPunch::databaseQueryToJSON($db, 'SELECT * FROM strings WHERE id = ?', array($id));
|
||||||
|
if ($result == null) {
|
||||||
|
throw new NotFoundException('The entry could not be found');
|
||||||
|
}
|
||||||
|
return json_decode($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function list(): array {
|
||||||
|
$db = KPunch::databaseGet();
|
||||||
|
return json_decode(KPunch::databaseQueryToJSON($db, 'SELECT * FROM strings'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function update(array $input): bool {
|
||||||
|
validate($input);
|
||||||
|
$db = KPunch::databaseGet();
|
||||||
|
KPunch::databaseQueryToJSON($db,
|
||||||
|
'UPDATE strings SET name = ?, data = ?, description = ? WHERE id = ?',
|
||||||
|
array(
|
||||||
|
$input['name'],
|
||||||
|
$input['data'],
|
||||||
|
$input['description'],
|
||||||
|
$input['id']
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static function validate($input) {
|
||||||
|
if (V::minlength($input['name'], 1) === false) {
|
||||||
|
throw new InvalidArgumentException('The name must not be empty');
|
||||||
|
}
|
||||||
|
if (V::maxlength($input['name'], 32) === false) {
|
||||||
|
throw new InvalidArgumentException('The name must not be longer than 32 characters');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (V::minlength($input['data'], 1) === false) {
|
||||||
|
throw new InvalidArgumentException('The data must not be empty');
|
||||||
|
}
|
||||||
|
if (V::maxlength($input['data'], 4096) === false) {
|
||||||
|
throw new InvalidArgumentException('The data must not be longer than 4096 characters');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (V::maxlength($input['description'], 255) === false) {
|
||||||
|
throw new InvalidArgumentException('The description must not be longer than 255 characters');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
|
@ -1,7 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
require __DIR__ . '/api/config.php';
|
require __DIR__ . '/../api/config.php';
|
||||||
require __DIR__ . '/api/user.php';
|
require __DIR__ . '/../api/test.php';
|
||||||
|
require __DIR__ . '/../api/user.php';
|
||||||
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -22,10 +23,22 @@ return [
|
||||||
|
|
||||||
switch (get('command')) {
|
switch (get('command')) {
|
||||||
|
|
||||||
|
case 'API_TEST':
|
||||||
|
kpApiTest($response);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'CONFIG_GET_CONFIG':
|
case 'CONFIG_GET_CONFIG':
|
||||||
kpApiConfigGetConfig($response);
|
kpApiConfigGetConfig($response);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'CONFIG_GET_NUMBERS':
|
||||||
|
kpApiConfigGetNumbers($response);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'CONFIG_GET_STRINGS':
|
||||||
|
kpApiConfigGetStrings($response);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'USER_CREATE':
|
case 'USER_CREATE':
|
||||||
kpApiUserCreate(get('name'), get('email'), get('password'), $response);
|
kpApiUserCreate(get('name'), get('email'), get('password'), $response);
|
||||||
break;
|
break;
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
'kwconfig' => [
|
||||||
|
'label' => 'Kanga World Configuration',
|
||||||
|
'icon' => 'globe',
|
||||||
|
'menu' => true,
|
||||||
|
// update and delete dialogs
|
||||||
|
'dialogs' => [
|
||||||
|
require __DIR__ . '/../dialogs/create.php',
|
||||||
|
require __DIR__ . '/../dialogs/update.php',
|
||||||
|
require __DIR__ . '/../dialogs/delete.php'
|
||||||
|
],
|
||||||
|
// dropdown with edit and delete buttons
|
||||||
|
'dropdowns' => [
|
||||||
|
require __DIR__ . '/../dropdowns/kwconfig.php'
|
||||||
|
],
|
||||||
|
// search for settings
|
||||||
|
'searches' => [
|
||||||
|
'kwconfig' => require __DIR__ . '/../searches/kwconfig.php'
|
||||||
|
],
|
||||||
|
// view route
|
||||||
|
'views' => [
|
||||||
|
require __DIR__ . '/../views/kwconfig.php',
|
||||||
|
require __DIR__ . '/../views/kwentry.php'
|
||||||
|
],
|
||||||
|
]
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
?>
|
|
@ -1,11 +1,16 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use KangarooPunch\KwConfig;
|
use KangarooPunch\KwConfig;
|
||||||
|
use KangarooPunch\KwStrings;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'kwconfig' => function($site) {
|
'kwconfig' => function($site) {
|
||||||
return new Collection(KwConfig::list());
|
return new Collection(KwConfig::list());
|
||||||
}
|
},
|
||||||
|
|
||||||
|
'kwstrings' => function($site) {
|
||||||
|
return new Collection(KwStrings::list());
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
?>
|
?>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'sql' => [
|
||||||
|
'host' => 'mysql',
|
||||||
|
'port' => 3306,
|
||||||
|
'data' => 'dosThing',
|
||||||
|
'user' => 'dosThing',
|
||||||
|
'pass' => 'password'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
?>
|
|
@ -1,15 +1,26 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
load([
|
load([
|
||||||
'KangarooPunch\KwConfig' => __DIR__ . '/classes/KwConfig.php'
|
'KangarooPunch\KPunch ' => __DIR__ . '/classes/KPunch.php',
|
||||||
|
'KangarooPunch\KwConfig' => __DIR__ . '/classes/KwConfig.php',
|
||||||
|
'KangarooPunch\KwStrings' => __DIR__ . '/classes/KwStrings.php'
|
||||||
]);
|
]);
|
||||||
|
*/
|
||||||
|
|
||||||
|
load([
|
||||||
|
'KangarooPunch\KPunch ' => 'KPunch.php',
|
||||||
|
'KangarooPunch\KwConfig' => 'KwConfig.php',
|
||||||
|
'KangarooPunch\KwStrings' => 'KwStrings.php'
|
||||||
|
], __DIR__ . '/classes');
|
||||||
|
|
||||||
|
|
||||||
Kirby::plugin('kangaroopunch/kangaworld-integration', [
|
Kirby::plugin('kangaroopunch/kangaworld-integration', [
|
||||||
|
|
||||||
'api' => require __DIR__ . '/api.php',
|
'api' => require __DIR__ . '/features/api.php',
|
||||||
'areas' => require __DIR__ . '/areas.php',
|
// 'areas' => require __DIR__ . '/features/areas.php',
|
||||||
'collections' => require __DIR__ . '/collections.php'
|
'collections' => require __DIR__ . '/features/collections.php',
|
||||||
|
'options' => require __DIR__ . '/features/options.php'
|
||||||
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ TEMPLATE = subdirs
|
||||||
CONFIG *= ORDERED
|
CONFIG *= ORDERED
|
||||||
|
|
||||||
SUBDIRS = \
|
SUBDIRS = \
|
||||||
# client \
|
client \
|
||||||
server
|
server
|
||||||
# font \
|
# font \
|
||||||
# primes
|
# primes
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
|
#include "rest.h"
|
||||||
|
|
||||||
|
|
||||||
static uint8_t clientDequeuePacket(ClientThreadT *client);
|
static uint8_t clientDequeuePacket(ClientThreadT *client);
|
||||||
|
@ -63,7 +64,15 @@ static uint8_t clientDequeuePacket(ClientThreadT *client) {
|
||||||
|
|
||||||
|
|
||||||
static void clientProcessPacket(ClientThreadT *client, PacketDecodeDataT *data) {
|
static void clientProcessPacket(ClientThreadT *client, PacketDecodeDataT *data) {
|
||||||
PacketEncodeDataT encoded = { 0 };
|
uint64_t i = 0;
|
||||||
|
uint64_t x = 0;
|
||||||
|
uint32_t y = 0;
|
||||||
|
uint64_t length = 0;
|
||||||
|
char *buffer = NULL;
|
||||||
|
PacketEncodeDataT encoded = { 0 };
|
||||||
|
json_object *response = NULL;
|
||||||
|
RestStringMapT *strings = NULL;
|
||||||
|
RestIntegerMapT *integers = NULL;
|
||||||
|
|
||||||
switch (data->packetType) {
|
switch (data->packetType) {
|
||||||
case PACKET_TYPE_CLIENT_SHUTDOWN:
|
case PACKET_TYPE_CLIENT_SHUTDOWN:
|
||||||
|
@ -86,6 +95,98 @@ static void clientProcessPacket(ClientThreadT *client, PacketDecodeDataT *data)
|
||||||
logWrite("Got PING, sent PONG\n\r");
|
logWrite("Got PING, sent PONG\n\r");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PACKET_TYPE_VERSION_BAD:
|
||||||
|
//***TODO***
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PACKET_TYPE_VERSION_OKAY:
|
||||||
|
logWrite("Got VERSION_OK.\n\r");
|
||||||
|
// Fetch string table from REST.
|
||||||
|
response = restRequest("CONFIG_GET_STRINGS", NULL);
|
||||||
|
if (!response) {
|
||||||
|
logWrite("Unable to fetch strings!\n\r");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
strings = restHelperConfigStringMapGet(response);
|
||||||
|
if (!strings) {
|
||||||
|
logWrite("Unable to map strings!\n\r");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
restRelease(response);
|
||||||
|
// Send string table to client.
|
||||||
|
logWrite("Sending strings.\n\r");
|
||||||
|
for (i=0; i<(unsigned)shlen(strings); i++) {
|
||||||
|
// Strings are encoded in a single buffer as: KEY\0DATA\0
|
||||||
|
x = strlen(strings[i].key);
|
||||||
|
y = strlen(strings[i].value);
|
||||||
|
length = x + y + 2;
|
||||||
|
buffer = (char *)malloc(length);
|
||||||
|
if (!buffer) {
|
||||||
|
logWrite("Unable to allocate buffer for string packet!\n\r");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memcpy(buffer, strings[i].key, x + 1);
|
||||||
|
memcpy(&buffer[x + 1], strings[i].value, y + 1);
|
||||||
|
// Build packet.
|
||||||
|
encoded.control = PACKET_CONTROL_DAT;
|
||||||
|
encoded.packetType = PACKET_TYPE_STRING;
|
||||||
|
encoded.channel = 0;
|
||||||
|
encoded.encrypt = 0;
|
||||||
|
packetEncode(client->packetThreadData, &encoded, buffer, length);
|
||||||
|
// Send it.
|
||||||
|
packetSend(client->packetThreadData, &encoded);
|
||||||
|
DEL(buffer);
|
||||||
|
}
|
||||||
|
restHelperConfigStringMapRelease(strings);
|
||||||
|
// Fetch number table from REST.
|
||||||
|
response = restRequest("CONFIG_GET_NUMBERS", NULL);
|
||||||
|
if (!response) {
|
||||||
|
logWrite("Unable to fetch numbers!\n\r");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
integers = restHelperConfigIntegerMapGet(response);
|
||||||
|
if (!integers) {
|
||||||
|
logWrite("Unable to map numbers!\n\r");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
restRelease(response);
|
||||||
|
// Send number table to client.
|
||||||
|
logWrite("Sending numbers.\n\r");
|
||||||
|
for (i=0; i<(unsigned)shlen(integers); i++) {
|
||||||
|
// Integers are encoded in a single buffer as: 1234DATA\0
|
||||||
|
// Integers are 64 bit until sent to the client when they are truncated to 32.
|
||||||
|
x = strlen(integers[i].key);
|
||||||
|
y = integers[i].value; // 64->32
|
||||||
|
length = x + 5;
|
||||||
|
buffer = (char *)malloc(length);
|
||||||
|
if (!buffer) {
|
||||||
|
logWrite("Unable to allocate buffer for number packet!\n\r");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memcpy(buffer, &y, 4);
|
||||||
|
memcpy(&buffer[4], integers[i].key, x + 1);
|
||||||
|
// Build packet.
|
||||||
|
encoded.control = PACKET_CONTROL_DAT;
|
||||||
|
encoded.packetType = PACKET_TYPE_NUMBER;
|
||||||
|
encoded.channel = 0;
|
||||||
|
encoded.encrypt = 0;
|
||||||
|
packetEncode(client->packetThreadData, &encoded, buffer, length);
|
||||||
|
// Send it.
|
||||||
|
packetSend(client->packetThreadData, &encoded);
|
||||||
|
DEL(buffer);
|
||||||
|
}
|
||||||
|
restHelperConfigIntegerMapRelease(integers);
|
||||||
|
// Build PROCEED packet.
|
||||||
|
encoded.control = PACKET_CONTROL_DAT;
|
||||||
|
encoded.packetType = PACKET_TYPE_PROCEED;
|
||||||
|
encoded.channel = 0;
|
||||||
|
encoded.encrypt = 0;
|
||||||
|
packetEncode(client->packetThreadData, &encoded, NULL, 0);
|
||||||
|
// Send it.
|
||||||
|
packetSend(client->packetThreadData, &encoded);
|
||||||
|
logWrite("Sending proceed.\n\r");
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
consoleMessageQueue("%ld: Channel %d Unknown Packet %d\n", client->threadIndex, data->channel, data->packetType);
|
consoleMessageQueue("%ld: Channel %d Unknown Packet %d\n", client->threadIndex, data->channel, data->packetType);
|
||||||
break;
|
break;
|
||||||
|
@ -136,6 +237,7 @@ void *clientThread(void *data) {
|
||||||
// Start communications with client as soon as encryption channel is ready.
|
// Start communications with client as soon as encryption channel is ready.
|
||||||
if (!versionSent) {
|
if (!versionSent) {
|
||||||
if (packetEncryptionReady()) {
|
if (packetEncryptionReady()) {
|
||||||
|
// Send required protocol version.
|
||||||
version.version = PACKET_PROTOCOL_VERSION;
|
version.version = PACKET_PROTOCOL_VERSION;
|
||||||
encoded.control = PACKET_CONTROL_DAT;
|
encoded.control = PACKET_CONTROL_DAT;
|
||||||
encoded.packetType = PACKET_TYPE_VERSION;
|
encoded.packetType = PACKET_TYPE_VERSION;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "rest.h"
|
#include "rest.h"
|
||||||
|
#include "array.h"
|
||||||
|
|
||||||
|
|
||||||
typedef struct RestResponseS {
|
typedef struct RestResponseS {
|
||||||
|
@ -52,14 +53,13 @@ int64_t restHelperConfigIntegerGet(json_object *object, char *name, int64_t defa
|
||||||
int64_t result = defaultValue;
|
int64_t result = defaultValue;
|
||||||
|
|
||||||
config = json_object_object_get(object, "config");
|
config = json_object_object_get(object, "config");
|
||||||
//logWrite("Config: %d %s\n", json_object_get_type(config), json_object_to_json_string_ext(config, JSON_C_TO_STRING_PRETTY));
|
|
||||||
if (config) {
|
if (config) {
|
||||||
data = json_object_object_get(config, "data");
|
data = json_object_object_get(config, "data");
|
||||||
//logWrite("Data: %d %s\n", json_object_get_type(data), json_object_to_json_string_ext(data, JSON_C_TO_STRING_PRETTY));
|
|
||||||
if (data) {
|
if (data) {
|
||||||
for (i=0; i<json_object_array_length(data); i++) {
|
for (i=0; i<json_object_array_length(data); i++) {
|
||||||
item = json_object_array_get_idx(data, i);
|
item = json_object_array_get_idx(data, i);
|
||||||
if (strcmp(name, json_object_get_string(json_object_object_get(item, "name"))) == 0) {
|
if (strcmp(name, json_object_get_string(json_object_object_get(item, "name"))) == 0) {
|
||||||
|
// Because of the way Kirby is sending us REST data, everything is a string. We have to convert it to an integer.
|
||||||
result = atol(json_object_get_string(json_object_object_get(item, "data")));
|
result = atol(json_object_get_string(json_object_object_get(item, "data")));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,95 @@ int64_t restHelperConfigIntegerGet(json_object *object, char *name, int64_t defa
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RestIntegerMapT *restHelperConfigIntegerMapGet(json_object *object) {
|
||||||
|
uint64_t i = 0;
|
||||||
|
json_object *config = NULL;
|
||||||
|
json_object *data = NULL;
|
||||||
|
json_object *item = NULL;
|
||||||
|
RestIntegerMapT *result = NULL;
|
||||||
|
|
||||||
|
config = json_object_object_get(object, "config");
|
||||||
|
if (config) {
|
||||||
|
data = json_object_object_get(config, "data");
|
||||||
|
if (data) {
|
||||||
|
for (i=0; i<json_object_array_length(data); i++) {
|
||||||
|
item = json_object_array_get_idx(data, i);
|
||||||
|
shput(result, json_object_get_string(json_object_object_get(item, "name")), atol(json_object_get_string(json_object_object_get(item, "data"))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void restHelperConfigIntegerMapRelease(RestIntegerMapT *map) {
|
||||||
|
while (shlen(map) > 0) {
|
||||||
|
shdel(map, map[0].key);
|
||||||
|
}
|
||||||
|
shfree(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
char *restHelperConfigStringGet(json_object *object, char *name, char *defaultValue) {
|
||||||
|
uint64_t i = 0;
|
||||||
|
json_object *config = NULL;
|
||||||
|
json_object *data = NULL;
|
||||||
|
json_object *item = NULL;
|
||||||
|
char *result = strdup(defaultValue);
|
||||||
|
|
||||||
|
config = json_object_object_get(object, "config");
|
||||||
|
if (config) {
|
||||||
|
data = json_object_object_get(config, "data");
|
||||||
|
if (data) {
|
||||||
|
for (i=0; i<json_object_array_length(data); i++) {
|
||||||
|
item = json_object_array_get_idx(data, i);
|
||||||
|
if (strcmp(name, json_object_get_string(json_object_object_get(item, "name"))) == 0) {
|
||||||
|
DEL(result);
|
||||||
|
result = strdup(json_object_get_string(json_object_object_get(item, "data")));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
RestStringMapT *restHelperConfigStringMapGet(json_object *object) {
|
||||||
|
uint64_t i = 0;
|
||||||
|
json_object *config = NULL;
|
||||||
|
json_object *data = NULL;
|
||||||
|
json_object *item = NULL;
|
||||||
|
RestStringMapT *result = NULL;
|
||||||
|
|
||||||
|
config = json_object_object_get(object, "config");
|
||||||
|
if (config) {
|
||||||
|
data = json_object_object_get(config, "data");
|
||||||
|
if (data) {
|
||||||
|
for (i=0; i<json_object_array_length(data); i++) {
|
||||||
|
item = json_object_array_get_idx(data, i);
|
||||||
|
shput(result, json_object_get_string(json_object_object_get(item, "name")), strdup(json_object_get_string(json_object_object_get(item, "data"))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void restHelperConfigStringMapRelease(RestStringMapT *map) {
|
||||||
|
while (shlen(map) > 0) {
|
||||||
|
DEL(map[0].value);
|
||||||
|
shdel(map, map[0].key);
|
||||||
|
}
|
||||||
|
shfree(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wunused-function" // It's used, but the compiler isn't picking it up because it's via a callback.
|
#pragma GCC diagnostic ignored "-Wunused-function" // It's used, but the compiler isn't picking it up because it's via a callback.
|
||||||
static void restMutexLocker(int mode, int n, const char *file, int line) {
|
static void restMutexLocker(int mode, int n, const char *file, int line) {
|
||||||
|
@ -119,10 +208,10 @@ json_object *restRequest(char *command, char *format, ...) {
|
||||||
}
|
}
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
//logWrite("Request: %s\n", json_object_to_json_string_ext(request, JSON_C_TO_STRING_PRETTY));
|
logWrite("Request: %s\n", json_object_to_json_string_ext(request, JSON_C_TO_STRING_PRETTY));
|
||||||
response = restUrlPost(request);
|
response = restUrlPost(request);
|
||||||
json_object_put(request);
|
json_object_put(request);
|
||||||
//logWrite("Response: %s\n", json_object_to_json_string_ext(response, JSON_C_TO_STRING_PRETTY));
|
logWrite("Response: %s\n", json_object_to_json_string_ext(response, JSON_C_TO_STRING_PRETTY));
|
||||||
|
|
||||||
if (response) {
|
if (response) {
|
||||||
if (json_object_get_boolean(json_object_object_get(response, "result")) != TRUE) {
|
if (json_object_get_boolean(json_object_object_get(response, "result")) != TRUE) {
|
||||||
|
|
|
@ -25,11 +25,27 @@
|
||||||
#include <json-c/json.h>
|
#include <json-c/json.h>
|
||||||
|
|
||||||
|
|
||||||
int64_t restHelperConfigIntegerGet(json_object *object, char *name, int64_t defaultValue);
|
typedef struct RestStringMapS {
|
||||||
void restRelease(json_object *object);
|
char *key;
|
||||||
json_object *restRequest(char *command, char *format, ...);
|
char *value;
|
||||||
void restShutdown(void);
|
} RestStringMapT;
|
||||||
uint8_t restStartup(char *url, char *user, char *password);
|
|
||||||
|
typedef struct RestIntegerMapS {
|
||||||
|
char *key;
|
||||||
|
int64_t value;
|
||||||
|
} RestIntegerMapT;
|
||||||
|
|
||||||
|
|
||||||
|
int64_t restHelperConfigIntegerGet(json_object *object, char *name, int64_t defaultValue);
|
||||||
|
RestIntegerMapT *restHelperConfigIntegerMapGet(json_object *object);
|
||||||
|
void restHelperConfigIntegerMapRelease(RestIntegerMapT *map);
|
||||||
|
//char *restHelperConfigStringGet(json_object *object, char *name, char *defaultValue);
|
||||||
|
RestStringMapT *restHelperConfigStringMapGet(json_object *object);
|
||||||
|
void restHelperConfigStringMapRelease(RestStringMapT *map);
|
||||||
|
void restRelease(json_object *object);
|
||||||
|
json_object *restRequest(char *command, char *format, ...);
|
||||||
|
void restShutdown(void);
|
||||||
|
uint8_t restStartup(char *url, char *user, char *password);
|
||||||
|
|
||||||
|
|
||||||
#endif // REST_H
|
#endif // REST_H
|
||||||
|
|
|
@ -41,6 +41,11 @@ typedef enum PacketTypeE {
|
||||||
PACKET_TYPE_DH_REQUEST,
|
PACKET_TYPE_DH_REQUEST,
|
||||||
PACKET_TYPE_DH_RESPONSE,
|
PACKET_TYPE_DH_RESPONSE,
|
||||||
PACKET_TYPE_VERSION,
|
PACKET_TYPE_VERSION,
|
||||||
|
PACKET_TYPE_VERSION_OKAY,
|
||||||
|
PACKET_TYPE_VERSION_BAD,
|
||||||
|
PACKET_TYPE_STRING,
|
||||||
|
PACKET_TYPE_NUMBER,
|
||||||
|
PACKET_TYPE_PROCEED,
|
||||||
PACKET_TYPE_LOGIN,
|
PACKET_TYPE_LOGIN,
|
||||||
PACKET_TYPE_COUNT
|
PACKET_TYPE_COUNT
|
||||||
} PacketTypeT;
|
} PacketTypeT;
|
||||||
|
|
Loading…
Add table
Reference in a new issue