Signup almost working server-side.
This commit is contained in:
parent
7174d36eb9
commit
ba1fe40938
15 changed files with 314 additions and 66 deletions
|
@ -150,7 +150,8 @@ SOURCES = \
|
||||||
src/welcome.c
|
src/welcome.c
|
||||||
|
|
||||||
LIBS = \
|
LIBS = \
|
||||||
-lSDL2
|
-lSDL2 \
|
||||||
|
-lSDL2_image
|
||||||
|
|
||||||
OTHER_FILES = \
|
OTHER_FILES = \
|
||||||
$$DOS_HEADERS \
|
$$DOS_HEADERS \
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
#include <SDL2/SDL_image.h>
|
||||||
|
|
||||||
#define ENET_IMPLEMENTATION
|
#define ENET_IMPLEMENTATION
|
||||||
#include "thirdparty/enet/include/enet.h"
|
#include "thirdparty/enet/include/enet.h"
|
||||||
|
@ -72,6 +73,8 @@ static uint16_t _bufferHead = 0;
|
||||||
static uint16_t _bufferTail = 0;
|
static uint16_t _bufferTail = 0;
|
||||||
static uint8_t _connected = 0;
|
static uint8_t _connected = 0;
|
||||||
static char _command[COM_BUFFER_SIZE] = { 0 };
|
static char _command[COM_BUFFER_SIZE] = { 0 };
|
||||||
|
static uint32_t _pixelFormat = SDL_PIXELFORMAT_RGBA8888;
|
||||||
|
static uint8_t _takeScreenshot = 0;
|
||||||
|
|
||||||
|
|
||||||
static void comAddToBuffer(char *data, uint16_t len);
|
static void comAddToBuffer(char *data, uint16_t len);
|
||||||
|
@ -79,6 +82,7 @@ static void comBufferShow(void);
|
||||||
static void comModem(uint8_t c);
|
static void comModem(uint8_t c);
|
||||||
static void processEvent(void);
|
static void processEvent(void);
|
||||||
static void processNetworkEvent(void);
|
static void processNetworkEvent(void);
|
||||||
|
static void vbeScreenshot(void);
|
||||||
|
|
||||||
|
|
||||||
long biostime(int cmd, long newtime) {
|
long biostime(int cmd, long newtime) {
|
||||||
|
@ -453,6 +457,8 @@ static void processEvent(void) {
|
||||||
_keyPressed = 1;
|
_keyPressed = 1;
|
||||||
_debounce = 1;
|
_debounce = 1;
|
||||||
}
|
}
|
||||||
|
// Screenshot?
|
||||||
|
if (e.key.keysym.scancode == SDL_SCANCODE_F10) _takeScreenshot = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -553,6 +559,11 @@ void vbePresent(void) {
|
||||||
// No network activity. Just sleep.
|
// No network activity. Just sleep.
|
||||||
SDL_Delay(32);
|
SDL_Delay(32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_takeScreenshot) {
|
||||||
|
_takeScreenshot = 0;
|
||||||
|
vbeScreenshot();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -562,6 +573,37 @@ int16_t vbeInfoShow(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void vbeScreenshot(void) {
|
||||||
|
int32_t x = 0;
|
||||||
|
char filename[16] = { 0 };
|
||||||
|
void *pixels = NULL;
|
||||||
|
SDL_Surface *surface = NULL;
|
||||||
|
SDL_Surface *save = NULL;
|
||||||
|
FILE *check = NULL;
|
||||||
|
|
||||||
|
while (x <= 999) {
|
||||||
|
snprintf(filename, 16, "shot%03d.png", x);
|
||||||
|
check = fopen(filename, "rb");
|
||||||
|
if (check) {
|
||||||
|
x++;
|
||||||
|
fclose(check);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x > 999) utilDie("Seriously? You have 1000 screenshots in this folder? Remove some.");
|
||||||
|
|
||||||
|
surface = SDL_GetWindowSurface(_window);
|
||||||
|
pixels = (uint8_t *)malloc(surface->w * surface->h * surface->format->BytesPerPixel);
|
||||||
|
SDL_RenderReadPixels(_renderer, &surface->clip_rect, surface->format->format, pixels, surface->w * surface->format->BytesPerPixel);
|
||||||
|
save = SDL_CreateRGBSurfaceFrom(pixels, surface->w, surface->h, surface->format->BitsPerPixel, surface->w * surface->format->BytesPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask);
|
||||||
|
IMG_SavePNG(save, filename);
|
||||||
|
SDL_FreeSurface(save);
|
||||||
|
SDL_FreeSurface(surface);
|
||||||
|
free(pixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int16_t vbeShutdown(void) {
|
int16_t vbeShutdown(void) {
|
||||||
if (_texture) {
|
if (_texture) {
|
||||||
SDL_DestroyTexture(_texture);
|
SDL_DestroyTexture(_texture);
|
||||||
|
@ -601,7 +643,7 @@ uint8_t vbeStartup(uint16_t xRes, uint16_t yRes, uint8_t bpp) {
|
||||||
_window = SDL_CreateWindow("GUI Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, xRes, yRes, SDL_WINDOW_ALLOW_HIGHDPI);
|
_window = SDL_CreateWindow("GUI Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, xRes, yRes, SDL_WINDOW_ALLOW_HIGHDPI);
|
||||||
_surface = SDL_GetWindowSurface(_window);
|
_surface = SDL_GetWindowSurface(_window);
|
||||||
_renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED);
|
_renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED);
|
||||||
_texture = SDL_CreateTexture(_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, xRes, yRes);
|
_texture = SDL_CreateTexture(_renderer, _pixelFormat, SDL_TEXTUREACCESS_STREAMING, xRes, yRes);
|
||||||
|
|
||||||
SDL_RenderSetLogicalSize(_renderer, xRes, yRes);
|
SDL_RenderSetLogicalSize(_renderer, xRes, yRes);
|
||||||
SDL_SetWindowSize(_window, xRes * _windowScale, yRes * _windowScale);
|
SDL_SetWindowSize(_window, xRes * _windowScale, yRes * _windowScale);
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "button.h"
|
#include "button.h"
|
||||||
#include "msgbox.h"
|
#include "msgbox.h"
|
||||||
|
|
||||||
|
#include "runtime.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "comport.h"
|
#include "comport.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
|
@ -131,14 +132,14 @@ void taskLogin(void *data) {
|
||||||
T_TITLE, P("User Name:"),
|
T_TITLE, P("User Name:"),
|
||||||
T_X, 42, T_Y, 10,
|
T_X, 42, T_Y, 10,
|
||||||
T_WIDTH, 200,
|
T_WIDTH, 200,
|
||||||
T_LENGTH, 16,
|
T_LENGTH, shget(__runtimeData.integers, "maxUser"),
|
||||||
T_TEXTBOX, T_DONE,
|
T_TEXTBOX, T_DONE,
|
||||||
|
|
||||||
T_TEXTBOX, O(_txtPass),
|
T_TEXTBOX, O(_txtPass),
|
||||||
T_TITLE, P(" Password:"),
|
T_TITLE, P(" Password:"),
|
||||||
T_X, 42, T_Y, 40,
|
T_X, 42, T_Y, 40,
|
||||||
T_WIDTH, 200,
|
T_WIDTH, 200,
|
||||||
T_LENGTH, 16,
|
T_LENGTH, shget(__runtimeData.integers, "maxPass"),
|
||||||
T_MASK, '*',
|
T_MASK, '*',
|
||||||
T_TEXTBOX, T_DONE,
|
T_TEXTBOX, T_DONE,
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,6 @@ void netStartup(void) {
|
||||||
|
|
||||||
void taskNetwork(void *data) {
|
void taskNetwork(void *data) {
|
||||||
int32_t r = 0;
|
int32_t r = 0;
|
||||||
int8_t pingTimeout = 0;
|
|
||||||
char buffer[1024] = { 0 };
|
char buffer[1024] = { 0 };
|
||||||
PacketDecodeDataT *packet = NULL;
|
PacketDecodeDataT *packet = NULL;
|
||||||
PacketDecodeDataT decoded = { 0 };
|
PacketDecodeDataT decoded = { 0 };
|
||||||
|
@ -96,10 +95,24 @@ void taskNetwork(void *data) {
|
||||||
r = comRead(__configData.serialCom - 1, buffer, 1024);
|
r = comRead(__configData.serialCom - 1, buffer, 1024);
|
||||||
// New data or not, process anything in the queue.
|
// New data or not, process anything in the queue.
|
||||||
if (packetDecode(__packetThreadData, &decoded, buffer, r)) {
|
if (packetDecode(__packetThreadData, &decoded, buffer, r)) {
|
||||||
// Is this a PONG? If so, ignore it.
|
|
||||||
if (decoded.packetType == PACKET_TYPE_PONG) {
|
// Is this something we care about?
|
||||||
packetDecodeDataStaticDestroy(&decoded);
|
switch (decoded.packetType) {
|
||||||
continue;
|
case PACKET_TYPE_PING:
|
||||||
|
// Reply with PONG
|
||||||
|
encoded.control = PACKET_CONTROL_DAT;
|
||||||
|
encoded.packetType = PACKET_TYPE_PONG;
|
||||||
|
encoded.channel = 0;
|
||||||
|
encoded.encrypt = 0;
|
||||||
|
packetEncode(__packetThreadData, &encoded, NULL, 0);
|
||||||
|
packetSend(__packetThreadData, &encoded);
|
||||||
|
packetDecodeDataStaticDestroy(&decoded);
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Silences a warning.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the packet out.
|
// Copy the packet out.
|
||||||
|
@ -126,20 +139,6 @@ void taskNetwork(void *data) {
|
||||||
// Yield to UI.
|
// Yield to UI.
|
||||||
taskYield();
|
taskYield();
|
||||||
|
|
||||||
// Send a ping to the server every 5 seconds, because, ping.
|
|
||||||
if (__timerSecondTick) {
|
|
||||||
pingTimeout++;
|
|
||||||
if (pingTimeout > 5) {
|
|
||||||
pingTimeout = 0;
|
|
||||||
encoded.control = PACKET_CONTROL_DAT;
|
|
||||||
encoded.packetType = PACKET_TYPE_PING;
|
|
||||||
encoded.channel = 0;
|
|
||||||
encoded.encrypt = 0;
|
|
||||||
packetEncode(__packetThreadData, &encoded, NULL, 0); // Must encode each packet - no reusing encoded data.
|
|
||||||
packetSend(__packetThreadData, &encoded);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} while (!guiHasStopped() && _netRunning);
|
} while (!guiHasStopped() && _netRunning);
|
||||||
|
|
||||||
// Free any unclaimed packets.
|
// Free any unclaimed packets.
|
||||||
|
|
|
@ -107,7 +107,7 @@ void taskSignUp(void *data) {
|
||||||
T_TITLE, P(" User Name:"),
|
T_TITLE, P(" User Name:"),
|
||||||
T_X, 40, T_Y, 64,
|
T_X, 40, T_Y, 64,
|
||||||
T_WIDTH, 300,
|
T_WIDTH, 300,
|
||||||
T_LENGTH, 16,
|
T_LENGTH, shget(__runtimeData.integers, "maxUser"),
|
||||||
T_TEXTBOX, T_DONE,
|
T_TEXTBOX, T_DONE,
|
||||||
|
|
||||||
T_TEXTBOX, O(_txtPass1),
|
T_TEXTBOX, O(_txtPass1),
|
||||||
|
@ -115,7 +115,7 @@ void taskSignUp(void *data) {
|
||||||
T_TITLE, P(" Password:"),
|
T_TITLE, P(" Password:"),
|
||||||
T_X, 40, T_Y, 94,
|
T_X, 40, T_Y, 94,
|
||||||
T_WIDTH, 300,
|
T_WIDTH, 300,
|
||||||
T_LENGTH, 16,
|
T_LENGTH, shget(__runtimeData.integers, "maxPass"),
|
||||||
T_MASK, '*',
|
T_MASK, '*',
|
||||||
T_TEXTBOX, T_DONE,
|
T_TEXTBOX, T_DONE,
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ void taskSignUp(void *data) {
|
||||||
T_TITLE, P(" Password (again):"),
|
T_TITLE, P(" Password (again):"),
|
||||||
T_X, 40, T_Y, 124,
|
T_X, 40, T_Y, 124,
|
||||||
T_WIDTH, 300,
|
T_WIDTH, 300,
|
||||||
T_LENGTH, 16,
|
T_LENGTH, shget(__runtimeData.integers, "maxPass"),
|
||||||
T_MASK, '*',
|
T_MASK, '*',
|
||||||
T_TEXTBOX, T_DONE,
|
T_TEXTBOX, T_DONE,
|
||||||
|
|
||||||
|
@ -133,8 +133,7 @@ void taskSignUp(void *data) {
|
||||||
T_TITLE, P(" REAL First Name:"),
|
T_TITLE, P(" REAL First Name:"),
|
||||||
T_X, 40, T_Y, 154,
|
T_X, 40, T_Y, 154,
|
||||||
T_WIDTH, 300,
|
T_WIDTH, 300,
|
||||||
T_LENGTH, 16,
|
T_LENGTH, shget(__runtimeData.integers, "maxName"),
|
||||||
T_MASK, '*',
|
|
||||||
T_TEXTBOX, T_DONE,
|
T_TEXTBOX, T_DONE,
|
||||||
|
|
||||||
T_TEXTBOX, O(_txtLast),
|
T_TEXTBOX, O(_txtLast),
|
||||||
|
@ -142,8 +141,7 @@ void taskSignUp(void *data) {
|
||||||
T_TITLE, P(" REAL Last Name:"),
|
T_TITLE, P(" REAL Last Name:"),
|
||||||
T_X, 40, T_Y, 184,
|
T_X, 40, T_Y, 184,
|
||||||
T_WIDTH, 300,
|
T_WIDTH, 300,
|
||||||
T_LENGTH, 16,
|
T_LENGTH, shget(__runtimeData.integers, "maxName"),
|
||||||
T_MASK, '*',
|
|
||||||
T_TEXTBOX, T_DONE,
|
T_TEXTBOX, T_DONE,
|
||||||
|
|
||||||
T_TEXTBOX, O(_txtEmail),
|
T_TEXTBOX, O(_txtEmail),
|
||||||
|
@ -151,8 +149,7 @@ void taskSignUp(void *data) {
|
||||||
T_TITLE, P(" VALID E-Mail:"),
|
T_TITLE, P(" VALID E-Mail:"),
|
||||||
T_X, 40, T_Y, 214,
|
T_X, 40, T_Y, 214,
|
||||||
T_WIDTH, 300,
|
T_WIDTH, 300,
|
||||||
T_LENGTH, 16,
|
T_LENGTH, shget(__runtimeData.integers, "maxEmail"),
|
||||||
T_MASK, '*',
|
|
||||||
T_TEXTBOX, T_DONE,
|
T_TEXTBOX, T_DONE,
|
||||||
|
|
||||||
T_BUTTON, O(_btnCancel),
|
T_BUTTON, O(_btnCancel),
|
||||||
|
|
81
kanga.world/site/blueprints/sections/userdata.yml
Normal file
81
kanga.world/site/blueprints/sections/userdata.yml
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
columns:
|
||||||
|
left:
|
||||||
|
width: 1/2
|
||||||
|
fields:
|
||||||
|
firstname:
|
||||||
|
label: First Name
|
||||||
|
width: 1/2
|
||||||
|
type: text
|
||||||
|
lastname:
|
||||||
|
label: Last Name
|
||||||
|
width: 1/2
|
||||||
|
type: text
|
||||||
|
street:
|
||||||
|
label: Street
|
||||||
|
type: text
|
||||||
|
city:
|
||||||
|
label: City
|
||||||
|
type: text
|
||||||
|
width: 1/2
|
||||||
|
state:
|
||||||
|
label: State
|
||||||
|
type: text
|
||||||
|
width: 1/2
|
||||||
|
zip:
|
||||||
|
label: ZIP
|
||||||
|
type: text
|
||||||
|
width: 1/4
|
||||||
|
country:
|
||||||
|
label: Country
|
||||||
|
type: text
|
||||||
|
width: 3/4
|
||||||
|
|
||||||
|
right:
|
||||||
|
width: 1/2
|
||||||
|
fields:
|
||||||
|
website:
|
||||||
|
label: Website
|
||||||
|
type: url
|
||||||
|
steam:
|
||||||
|
label: Steam
|
||||||
|
type: text
|
||||||
|
placeholder: username
|
||||||
|
width: 1/2
|
||||||
|
epic:
|
||||||
|
label: Epic Games
|
||||||
|
type: text
|
||||||
|
placeholder: username
|
||||||
|
width: 1/2
|
||||||
|
xbox:
|
||||||
|
label: Xbox Live
|
||||||
|
type: text
|
||||||
|
placeholder: username
|
||||||
|
width: 1/2
|
||||||
|
playstation:
|
||||||
|
label: PlayStation Network
|
||||||
|
type: text
|
||||||
|
placeholder: username
|
||||||
|
width: 1/2
|
||||||
|
nintendo:
|
||||||
|
label: Nintendo
|
||||||
|
type: text
|
||||||
|
placeholder: friendcode
|
||||||
|
width: 1/2
|
||||||
|
facebook:
|
||||||
|
label: Facebook
|
||||||
|
type: text
|
||||||
|
icon: facebook
|
||||||
|
placeholder: username
|
||||||
|
width: 1/2
|
||||||
|
twitter:
|
||||||
|
label: Twitter
|
||||||
|
type: text
|
||||||
|
icon: twitter
|
||||||
|
placeholder: @username
|
||||||
|
width: 1/2
|
||||||
|
instagram:
|
||||||
|
label: Instagram
|
||||||
|
type: text
|
||||||
|
icon: instagram
|
||||||
|
placeholder: username
|
||||||
|
width: 1/2
|
8
kanga.world/site/blueprints/users/admin.yml
Normal file
8
kanga.world/site/blueprints/users/admin.yml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
title: Administrator
|
||||||
|
description: Kanga World administrator
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
access:
|
||||||
|
panel: true
|
||||||
|
|
||||||
|
extends: sections/userdata
|
|
@ -1,4 +1,8 @@
|
||||||
title: User
|
title: User
|
||||||
|
description: Standard Kanga World user
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
access:
|
access:
|
||||||
panel: false
|
panel: false
|
||||||
|
|
||||||
|
extends: sections/userdata
|
||||||
|
|
|
@ -30,7 +30,7 @@ return function ($kirby) {
|
||||||
];
|
];
|
||||||
|
|
||||||
// INVALID DATA
|
// INVALID DATA
|
||||||
if($invalid = invalid($data, $rules, $messages)) {
|
if ($invalid = invalid($data, $rules, $messages)) {
|
||||||
|
|
||||||
$alert = $invalid;
|
$alert = $invalid;
|
||||||
$error = true;
|
$error = true;
|
||||||
|
@ -43,6 +43,9 @@ return function ($kirby) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
// A lot of this code is duplicated in:
|
||||||
|
// site/plugins/kangaworld-integration/api/user.php
|
||||||
|
|
||||||
// CREATE USER
|
// CREATE USER
|
||||||
$user = $kirby->users()->create([
|
$user = $kirby->users()->create([
|
||||||
'email' => $data['email'],
|
'email' => $data['email'],
|
||||||
|
@ -53,7 +56,6 @@ return function ($kirby) {
|
||||||
|
|
||||||
// CHECK EMAIL ACTIVATION
|
// CHECK EMAIL ACTIVATION
|
||||||
if (option('user.email.activation', false) === true) {
|
if (option('user.email.activation', false) === true) {
|
||||||
|
|
||||||
$user->update([
|
$user->update([
|
||||||
'emailActivation' => false,
|
'emailActivation' => false,
|
||||||
'emailActivationToken' => $token
|
'emailActivationToken' => $token
|
||||||
|
|
|
@ -1,18 +1,54 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
function kpApiUserCreate($name, $email, $password, &$response) {
|
function kpApiUserCreate($first, $last, $username, $email, $password, &$response) {
|
||||||
try {
|
try {
|
||||||
kirby()->users()->create([
|
// Check for duplicate username.
|
||||||
'name' => $name,
|
$user = kirby()->users()->filterBy('name', $username);
|
||||||
'email' => $email,
|
if ($user->first()) {
|
||||||
'password' => $password,
|
$response['result'] = 'false';
|
||||||
'language' => 'en',
|
$response['reason'] = 'User name already exists.';
|
||||||
'role' => 'user'
|
} else {
|
||||||
]);
|
// Save Kirby attributes.
|
||||||
$response['result'] = 'true';
|
$user = kirby()->users()->create([
|
||||||
$response['reason'] = 'User created.';
|
'name' => $username,
|
||||||
|
'email' => $email,
|
||||||
|
'password' => $password,
|
||||||
|
'language' => 'en',
|
||||||
|
'role' => 'user'
|
||||||
|
]);
|
||||||
|
// Send activation email.
|
||||||
|
// This duplicates a lot of code from site/controllers/register.php
|
||||||
|
$token = Str::random(16);
|
||||||
|
$link = kirby()->site()->url() . "/user/activate/" . $token;
|
||||||
|
$email = kirby()->email([
|
||||||
|
'to' => $email,
|
||||||
|
'from' => option('user.email.activation.sender'),
|
||||||
|
'subject' => option('user.email.activation.sender', 'Account Activation Link'),
|
||||||
|
'template' => 'account-activation',
|
||||||
|
'data' => [
|
||||||
|
'link' => $link,
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
// Save our extended attributes.
|
||||||
|
$user->update([
|
||||||
|
'firstname' => $first,
|
||||||
|
'lastname' => $last,
|
||||||
|
'emailActivation' => false,
|
||||||
|
'emailActivationToken' => $token
|
||||||
|
]);
|
||||||
|
// Save SQL attributes.
|
||||||
|
// ***TODO***
|
||||||
|
|
||||||
|
// Return result.
|
||||||
|
$response['result'] = 'true';
|
||||||
|
$response['reason'] = 'User created. Check your E-mail for activation instructions.';
|
||||||
|
}
|
||||||
} catch(Exception $e) {
|
} catch(Exception $e) {
|
||||||
$response['reason'] = $e->getMessage();
|
if (strpos($e->getMessage(), "email")) {
|
||||||
|
$response['reason'] = 'E-mail already exists.';
|
||||||
|
} else {
|
||||||
|
$response['reason'] = $e->getMessage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ return [
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'USER_CREATE':
|
case 'USER_CREATE':
|
||||||
kpApiUserCreate(get('name'), get('email'), get('password'), $response);
|
kpApiUserCreate(get('first'), get('last'), get('user'), get('email'), get('pass'), $response);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'USER_GET':
|
case 'USER_GET':
|
||||||
|
|
|
@ -64,15 +64,19 @@ static uint8_t clientDequeuePacket(ClientThreadT *client) {
|
||||||
|
|
||||||
|
|
||||||
static void clientProcessPacket(ClientThreadT *client, PacketDecodeDataT *data) {
|
static void clientProcessPacket(ClientThreadT *client, PacketDecodeDataT *data) {
|
||||||
uint64_t i = 0;
|
uint64_t i = 0;
|
||||||
uint64_t x = 0;
|
uint64_t x = 0;
|
||||||
uint32_t y = 0;
|
uint32_t y = 0;
|
||||||
uint64_t length = 0;
|
uint64_t length = 0;
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
PacketEncodeDataT encoded = { 0 };
|
PacketEncodeDataT encoded = { 0 };
|
||||||
json_object *response = NULL;
|
json_object *response = NULL;
|
||||||
RestStringMapT *strings = NULL;
|
RestStringMapT *strings = NULL;
|
||||||
RestIntegerMapT *integers = NULL;
|
RestIntegerMapT *integers = NULL;
|
||||||
|
struct timespec timer = { 0 };
|
||||||
|
double d = 0;
|
||||||
|
PacketTypeSignUpT *signup = NULL;
|
||||||
|
PacketTypeSignUpResultT signupResult = { 0 };
|
||||||
|
|
||||||
switch (data->packetType) {
|
switch (data->packetType) {
|
||||||
case PACKET_TYPE_CLIENT_SHUTDOWN:
|
case PACKET_TYPE_CLIENT_SHUTDOWN:
|
||||||
|
@ -83,19 +87,56 @@ static void clientProcessPacket(ClientThreadT *client, PacketDecodeDataT *data)
|
||||||
consoleMessageQueue("%ld: Channel %d %s %s\n", client->threadIndex, data->channel, ((PacketTypeLoginT *)data->data)->user, ((PacketTypeLoginT *)data->data)->pass);
|
consoleMessageQueue("%ld: Channel %d %s %s\n", client->threadIndex, data->channel, ((PacketTypeLoginT *)data->data)->user, ((PacketTypeLoginT *)data->data)->pass);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PACKET_TYPE_PING:
|
case PACKET_TYPE_PONG:
|
||||||
// Build PONG packet.
|
// Time round-trip.
|
||||||
encoded.control = PACKET_CONTROL_DAT;
|
clock_gettime(CLOCK_MONOTONIC_RAW, &timer);
|
||||||
encoded.packetType = PACKET_TYPE_PONG;
|
d = (timer.tv_sec - client->pingStart.tv_sec) * 1e9;
|
||||||
encoded.channel = 0;
|
d = (d + (timer.tv_nsec - client->pingStart.tv_nsec)) * 1e-9;
|
||||||
encoded.encrypt = 0;
|
client->pingStats[client->pingHead] = d;
|
||||||
packetEncode(client->packetThreadData, &encoded, NULL, 0);
|
client->pingHead++;
|
||||||
// Send it.
|
if (client->pingHead >= PING_STATS_SIZE) client->pingHead = 0;
|
||||||
packetSend(client->packetThreadData, &encoded);
|
// ***TODO*** Probably need a mutex here.
|
||||||
|
if (d > client->pingHigh) client->pingHigh = d;
|
||||||
|
if (d < client->pingLow) client->pingLow = d;
|
||||||
|
client->pingAverage = 0;
|
||||||
|
x = 0;
|
||||||
|
for (i=0; i<PING_STATS_SIZE; i++) {
|
||||||
|
if (client->pingStats[i] != 0) {
|
||||||
|
x++;
|
||||||
|
client->pingAverage += client->pingStats[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
client->pingAverage /= (double)x;
|
||||||
|
consoleMessageQueue("%ld: Ping: %f Low: %f Average: %f High: %f\n", client->threadIndex, d, client->pingLow, client->pingAverage, client->pingHigh);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PACKET_TYPE_SIGNUP:
|
case PACKET_TYPE_SIGNUP:
|
||||||
//***TODO***
|
signup = (PacketTypeSignUpT *)data->data;
|
||||||
|
response = restRequest("USER_CREATE", "sssss",
|
||||||
|
"first", signup->first,
|
||||||
|
"last", signup->last,
|
||||||
|
"user", signup->user,
|
||||||
|
"pass", signup->pass,
|
||||||
|
"email", signup->email
|
||||||
|
);
|
||||||
|
if (response) {
|
||||||
|
signupResult.success = (json_object_get_boolean(json_object_object_get(response, "result")) == TRUE) ? 1 : 0;
|
||||||
|
buffer = (char *)json_object_get_string(json_object_object_get(response, "reason"));
|
||||||
|
} else {
|
||||||
|
// Something bad happened.
|
||||||
|
signupResult.success = 0;
|
||||||
|
buffer = "Unknown error. Sorry.";
|
||||||
|
}
|
||||||
|
memcpy(signupResult.message, buffer, strlen(buffer));
|
||||||
|
if (response) restRelease(response);
|
||||||
|
// Build packet.
|
||||||
|
encoded.control = PACKET_CONTROL_DAT;
|
||||||
|
encoded.packetType = PACKET_TYPE_SIGNUP_RESULT;
|
||||||
|
encoded.channel = 0;
|
||||||
|
encoded.encrypt = 0;
|
||||||
|
packetEncode(client->packetThreadData, &encoded, (char *)&signupResult, sizeof(PacketTypeSignUpResultT));
|
||||||
|
// Send it.
|
||||||
|
packetSend(client->packetThreadData, &encoded);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PACKET_TYPE_VERSION_BAD:
|
case PACKET_TYPE_VERSION_BAD:
|
||||||
|
@ -230,6 +271,9 @@ void *clientThread(void *data) {
|
||||||
struct timespec sleepTime = { 0, 1000000000/100 }; // 1/100th second.
|
struct timespec sleepTime = { 0, 1000000000/100 }; // 1/100th second.
|
||||||
PacketTypeVersionT version = { 0 };
|
PacketTypeVersionT version = { 0 };
|
||||||
uint8_t versionSent = 0;
|
uint8_t versionSent = 0;
|
||||||
|
time_t ticks = { 0 };
|
||||||
|
time_t lastTicks = { 0 };
|
||||||
|
int8_t pingTimeout = 0;
|
||||||
|
|
||||||
// Process packets until we're done.
|
// Process packets until we're done.
|
||||||
while (client->running) {
|
while (client->running) {
|
||||||
|
@ -250,11 +294,30 @@ void *clientThread(void *data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ping the client every 5 seconds.
|
||||||
|
ticks = time(NULL);
|
||||||
|
if (ticks != lastTicks) {
|
||||||
|
lastTicks = ticks;
|
||||||
|
pingTimeout++;
|
||||||
|
if (pingTimeout >= 5) {
|
||||||
|
pingTimeout = 0;
|
||||||
|
encoded.control = PACKET_CONTROL_DAT;
|
||||||
|
encoded.packetType = PACKET_TYPE_PING;
|
||||||
|
encoded.channel = 0;
|
||||||
|
encoded.encrypt = 0;
|
||||||
|
packetEncode(client->packetThreadData, &encoded, (char *)&version, sizeof(PacketTypeVersionT));
|
||||||
|
packetSend(client->packetThreadData, &encoded);
|
||||||
|
clock_gettime(CLOCK_MONOTONIC_RAW, &client->pingStart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Don't eat all the CPU.
|
// Don't eat all the CPU.
|
||||||
nanosleep(&remaining, &sleepTime);
|
nanosleep(&remaining, &sleepTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ***TODO*** Write ping stats to database.
|
||||||
|
|
||||||
// Clean up client data on the way out.
|
// Clean up client data on the way out.
|
||||||
while (arrlen(client->packetQueue) > 0) {
|
while (arrlen(client->packetQueue) > 0) {
|
||||||
if (client->packetQueue[0]->data) DEL(client->packetQueue[0]->data);
|
if (client->packetQueue[0]->data) DEL(client->packetQueue[0]->data);
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define PING_STATS_SIZE 100
|
||||||
|
|
||||||
|
|
||||||
typedef struct ClientRawPacketS {
|
typedef struct ClientRawPacketS {
|
||||||
char *data;
|
char *data;
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
|
@ -39,6 +42,12 @@ typedef struct ClientThreadS {
|
||||||
PacketThreadDataT *packetThreadData;
|
PacketThreadDataT *packetThreadData;
|
||||||
ClientRawPacketT **packetQueue;
|
ClientRawPacketT **packetQueue;
|
||||||
pthread_mutex_t packetQueueMutex;
|
pthread_mutex_t packetQueueMutex;
|
||||||
|
struct timespec pingStart;
|
||||||
|
double pingStats[PING_STATS_SIZE];
|
||||||
|
uint8_t pingHead;
|
||||||
|
double pingAverage;
|
||||||
|
double pingHigh;
|
||||||
|
double pingLow;
|
||||||
void *peer;
|
void *peer;
|
||||||
} ClientThreadT;
|
} ClientThreadT;
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,11 @@ void *serverThread(void *data) {
|
||||||
client->running = 1;
|
client->running = 1;
|
||||||
client->packetQueue = NULL;
|
client->packetQueue = NULL;
|
||||||
client->peer = event.peer;
|
client->peer = event.peer;
|
||||||
|
client->pingHead = 0;
|
||||||
|
client->pingAverage = 0;
|
||||||
|
client->pingHigh = 0;
|
||||||
|
client->pingLow = 9999;
|
||||||
|
for (i=0; i<PING_STATS_SIZE; i++) client->pingStats[i] = 0;
|
||||||
memset(&client->packetQueueMutex, 1, sizeof(pthread_mutex_t));
|
memset(&client->packetQueueMutex, 1, sizeof(pthread_mutex_t));
|
||||||
pthread_mutex_init(&client->packetQueueMutex, NULL);
|
pthread_mutex_init(&client->packetQueueMutex, NULL);
|
||||||
// Keep our client in the peer data for later.
|
// Keep our client in the peer data for later.
|
||||||
|
|
Loading…
Add table
Reference in a new issue