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
|
||||
|
||||
LIBS = \
|
||||
-lSDL2
|
||||
-lSDL2 \
|
||||
-lSDL2_image
|
||||
|
||||
OTHER_FILES = \
|
||||
$$DOS_HEADERS \
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
|
||||
#define ENET_IMPLEMENTATION
|
||||
#include "thirdparty/enet/include/enet.h"
|
||||
|
@ -72,6 +73,8 @@ static uint16_t _bufferHead = 0;
|
|||
static uint16_t _bufferTail = 0;
|
||||
static uint8_t _connected = 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);
|
||||
|
@ -79,6 +82,7 @@ static void comBufferShow(void);
|
|||
static void comModem(uint8_t c);
|
||||
static void processEvent(void);
|
||||
static void processNetworkEvent(void);
|
||||
static void vbeScreenshot(void);
|
||||
|
||||
|
||||
long biostime(int cmd, long newtime) {
|
||||
|
@ -453,6 +457,8 @@ static void processEvent(void) {
|
|||
_keyPressed = 1;
|
||||
_debounce = 1;
|
||||
}
|
||||
// Screenshot?
|
||||
if (e.key.keysym.scancode == SDL_SCANCODE_F10) _takeScreenshot = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -553,6 +559,11 @@ void vbePresent(void) {
|
|||
// No network activity. Just sleep.
|
||||
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) {
|
||||
if (_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);
|
||||
_surface = SDL_GetWindowSurface(_window);
|
||||
_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_SetWindowSize(_window, xRes * _windowScale, yRes * _windowScale);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "button.h"
|
||||
#include "msgbox.h"
|
||||
|
||||
#include "runtime.h"
|
||||
#include "config.h"
|
||||
#include "comport.h"
|
||||
#include "network.h"
|
||||
|
@ -131,14 +132,14 @@ void taskLogin(void *data) {
|
|||
T_TITLE, P("User Name:"),
|
||||
T_X, 42, T_Y, 10,
|
||||
T_WIDTH, 200,
|
||||
T_LENGTH, 16,
|
||||
T_LENGTH, shget(__runtimeData.integers, "maxUser"),
|
||||
T_TEXTBOX, T_DONE,
|
||||
|
||||
T_TEXTBOX, O(_txtPass),
|
||||
T_TITLE, P(" Password:"),
|
||||
T_X, 42, T_Y, 40,
|
||||
T_WIDTH, 200,
|
||||
T_LENGTH, 16,
|
||||
T_LENGTH, shget(__runtimeData.integers, "maxPass"),
|
||||
T_MASK, '*',
|
||||
T_TEXTBOX, T_DONE,
|
||||
|
||||
|
|
|
@ -78,7 +78,6 @@ void netStartup(void) {
|
|||
|
||||
void taskNetwork(void *data) {
|
||||
int32_t r = 0;
|
||||
int8_t pingTimeout = 0;
|
||||
char buffer[1024] = { 0 };
|
||||
PacketDecodeDataT *packet = NULL;
|
||||
PacketDecodeDataT decoded = { 0 };
|
||||
|
@ -96,10 +95,24 @@ void taskNetwork(void *data) {
|
|||
r = comRead(__configData.serialCom - 1, buffer, 1024);
|
||||
// New data or not, process anything in the queue.
|
||||
if (packetDecode(__packetThreadData, &decoded, buffer, r)) {
|
||||
// Is this a PONG? If so, ignore it.
|
||||
if (decoded.packetType == PACKET_TYPE_PONG) {
|
||||
packetDecodeDataStaticDestroy(&decoded);
|
||||
continue;
|
||||
|
||||
// Is this something we care about?
|
||||
switch (decoded.packetType) {
|
||||
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.
|
||||
|
@ -126,20 +139,6 @@ void taskNetwork(void *data) {
|
|||
// Yield to UI.
|
||||
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);
|
||||
|
||||
// Free any unclaimed packets.
|
||||
|
|
|
@ -107,7 +107,7 @@ void taskSignUp(void *data) {
|
|||
T_TITLE, P(" User Name:"),
|
||||
T_X, 40, T_Y, 64,
|
||||
T_WIDTH, 300,
|
||||
T_LENGTH, 16,
|
||||
T_LENGTH, shget(__runtimeData.integers, "maxUser"),
|
||||
T_TEXTBOX, T_DONE,
|
||||
|
||||
T_TEXTBOX, O(_txtPass1),
|
||||
|
@ -115,7 +115,7 @@ void taskSignUp(void *data) {
|
|||
T_TITLE, P(" Password:"),
|
||||
T_X, 40, T_Y, 94,
|
||||
T_WIDTH, 300,
|
||||
T_LENGTH, 16,
|
||||
T_LENGTH, shget(__runtimeData.integers, "maxPass"),
|
||||
T_MASK, '*',
|
||||
T_TEXTBOX, T_DONE,
|
||||
|
||||
|
@ -124,7 +124,7 @@ void taskSignUp(void *data) {
|
|||
T_TITLE, P(" Password (again):"),
|
||||
T_X, 40, T_Y, 124,
|
||||
T_WIDTH, 300,
|
||||
T_LENGTH, 16,
|
||||
T_LENGTH, shget(__runtimeData.integers, "maxPass"),
|
||||
T_MASK, '*',
|
||||
T_TEXTBOX, T_DONE,
|
||||
|
||||
|
@ -133,8 +133,7 @@ void taskSignUp(void *data) {
|
|||
T_TITLE, P(" REAL First Name:"),
|
||||
T_X, 40, T_Y, 154,
|
||||
T_WIDTH, 300,
|
||||
T_LENGTH, 16,
|
||||
T_MASK, '*',
|
||||
T_LENGTH, shget(__runtimeData.integers, "maxName"),
|
||||
T_TEXTBOX, T_DONE,
|
||||
|
||||
T_TEXTBOX, O(_txtLast),
|
||||
|
@ -142,8 +141,7 @@ void taskSignUp(void *data) {
|
|||
T_TITLE, P(" REAL Last Name:"),
|
||||
T_X, 40, T_Y, 184,
|
||||
T_WIDTH, 300,
|
||||
T_LENGTH, 16,
|
||||
T_MASK, '*',
|
||||
T_LENGTH, shget(__runtimeData.integers, "maxName"),
|
||||
T_TEXTBOX, T_DONE,
|
||||
|
||||
T_TEXTBOX, O(_txtEmail),
|
||||
|
@ -151,8 +149,7 @@ void taskSignUp(void *data) {
|
|||
T_TITLE, P(" VALID E-Mail:"),
|
||||
T_X, 40, T_Y, 214,
|
||||
T_WIDTH, 300,
|
||||
T_LENGTH, 16,
|
||||
T_MASK, '*',
|
||||
T_LENGTH, shget(__runtimeData.integers, "maxEmail"),
|
||||
T_TEXTBOX, T_DONE,
|
||||
|
||||
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
|
||||
description: Standard Kanga World user
|
||||
|
||||
permissions:
|
||||
access:
|
||||
panel: false
|
||||
panel: false
|
||||
|
||||
extends: sections/userdata
|
||||
|
|
|
@ -30,7 +30,7 @@ return function ($kirby) {
|
|||
];
|
||||
|
||||
// INVALID DATA
|
||||
if($invalid = invalid($data, $rules, $messages)) {
|
||||
if ($invalid = invalid($data, $rules, $messages)) {
|
||||
|
||||
$alert = $invalid;
|
||||
$error = true;
|
||||
|
@ -43,6 +43,9 @@ return function ($kirby) {
|
|||
|
||||
try {
|
||||
|
||||
// A lot of this code is duplicated in:
|
||||
// site/plugins/kangaworld-integration/api/user.php
|
||||
|
||||
// CREATE USER
|
||||
$user = $kirby->users()->create([
|
||||
'email' => $data['email'],
|
||||
|
@ -53,7 +56,6 @@ return function ($kirby) {
|
|||
|
||||
// CHECK EMAIL ACTIVATION
|
||||
if (option('user.email.activation', false) === true) {
|
||||
|
||||
$user->update([
|
||||
'emailActivation' => false,
|
||||
'emailActivationToken' => $token
|
||||
|
|
|
@ -1,18 +1,54 @@
|
|||
<?php
|
||||
|
||||
function kpApiUserCreate($name, $email, $password, &$response) {
|
||||
function kpApiUserCreate($first, $last, $username, $email, $password, &$response) {
|
||||
try {
|
||||
kirby()->users()->create([
|
||||
'name' => $name,
|
||||
'email' => $email,
|
||||
'password' => $password,
|
||||
'language' => 'en',
|
||||
'role' => 'user'
|
||||
]);
|
||||
$response['result'] = 'true';
|
||||
$response['reason'] = 'User created.';
|
||||
// Check for duplicate username.
|
||||
$user = kirby()->users()->filterBy('name', $username);
|
||||
if ($user->first()) {
|
||||
$response['result'] = 'false';
|
||||
$response['reason'] = 'User name already exists.';
|
||||
} else {
|
||||
// Save Kirby attributes.
|
||||
$user = kirby()->users()->create([
|
||||
'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) {
|
||||
$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;
|
||||
|
||||
case 'USER_CREATE':
|
||||
kpApiUserCreate(get('name'), get('email'), get('password'), $response);
|
||||
kpApiUserCreate(get('first'), get('last'), get('user'), get('email'), get('pass'), $response);
|
||||
break;
|
||||
|
||||
case 'USER_GET':
|
||||
|
|
|
@ -64,15 +64,19 @@ static uint8_t clientDequeuePacket(ClientThreadT *client) {
|
|||
|
||||
|
||||
static void clientProcessPacket(ClientThreadT *client, PacketDecodeDataT *data) {
|
||||
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;
|
||||
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;
|
||||
struct timespec timer = { 0 };
|
||||
double d = 0;
|
||||
PacketTypeSignUpT *signup = NULL;
|
||||
PacketTypeSignUpResultT signupResult = { 0 };
|
||||
|
||||
switch (data->packetType) {
|
||||
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);
|
||||
break;
|
||||
|
||||
case PACKET_TYPE_PING:
|
||||
// Build PONG packet.
|
||||
encoded.control = PACKET_CONTROL_DAT;
|
||||
encoded.packetType = PACKET_TYPE_PONG;
|
||||
encoded.channel = 0;
|
||||
encoded.encrypt = 0;
|
||||
packetEncode(client->packetThreadData, &encoded, NULL, 0);
|
||||
// Send it.
|
||||
packetSend(client->packetThreadData, &encoded);
|
||||
case PACKET_TYPE_PONG:
|
||||
// Time round-trip.
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &timer);
|
||||
d = (timer.tv_sec - client->pingStart.tv_sec) * 1e9;
|
||||
d = (d + (timer.tv_nsec - client->pingStart.tv_nsec)) * 1e-9;
|
||||
client->pingStats[client->pingHead] = d;
|
||||
client->pingHead++;
|
||||
if (client->pingHead >= PING_STATS_SIZE) client->pingHead = 0;
|
||||
// ***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;
|
||||
|
||||
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;
|
||||
|
||||
case PACKET_TYPE_VERSION_BAD:
|
||||
|
@ -230,6 +271,9 @@ void *clientThread(void *data) {
|
|||
struct timespec sleepTime = { 0, 1000000000/100 }; // 1/100th second.
|
||||
PacketTypeVersionT version = { 0 };
|
||||
uint8_t versionSent = 0;
|
||||
time_t ticks = { 0 };
|
||||
time_t lastTicks = { 0 };
|
||||
int8_t pingTimeout = 0;
|
||||
|
||||
// Process packets until we're done.
|
||||
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.
|
||||
nanosleep(&remaining, &sleepTime);
|
||||
}
|
||||
}
|
||||
|
||||
// ***TODO*** Write ping stats to database.
|
||||
|
||||
// Clean up client data on the way out.
|
||||
while (arrlen(client->packetQueue) > 0) {
|
||||
if (client->packetQueue[0]->data) DEL(client->packetQueue[0]->data);
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#include "packet.h"
|
||||
|
||||
|
||||
#define PING_STATS_SIZE 100
|
||||
|
||||
|
||||
typedef struct ClientRawPacketS {
|
||||
char *data;
|
||||
uint32_t length;
|
||||
|
@ -39,6 +42,12 @@ typedef struct ClientThreadS {
|
|||
PacketThreadDataT *packetThreadData;
|
||||
ClientRawPacketT **packetQueue;
|
||||
pthread_mutex_t packetQueueMutex;
|
||||
struct timespec pingStart;
|
||||
double pingStats[PING_STATS_SIZE];
|
||||
uint8_t pingHead;
|
||||
double pingAverage;
|
||||
double pingHigh;
|
||||
double pingLow;
|
||||
void *peer;
|
||||
} ClientThreadT;
|
||||
|
||||
|
|
|
@ -118,6 +118,11 @@ void *serverThread(void *data) {
|
|||
client->running = 1;
|
||||
client->packetQueue = NULL;
|
||||
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));
|
||||
pthread_mutex_init(&client->packetQueueMutex, NULL);
|
||||
// Keep our client in the peer data for later.
|
||||
|
|
Loading…
Add table
Reference in a new issue