Basic packet system done.
This commit is contained in:
@ -50,6 +50,7 @@ errorret_t clientConnect(const clientconnect_t connect) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CLIENT.type = connect.type;
|
CLIENT.type = connect.type;
|
||||||
|
packetQueueInit(&CLIENT.packetQueue);
|
||||||
|
|
||||||
switch(connect.type) {
|
switch(connect.type) {
|
||||||
case CLIENT_TYPE_NETWORKED:
|
case CLIENT_TYPE_NETWORKED:
|
||||||
@ -64,6 +65,38 @@ errorret_t clientConnect(const clientconnect_t connect) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clientUpdate() {
|
||||||
|
packet_t packet;
|
||||||
|
int32_t ret;
|
||||||
|
errorret_t err;
|
||||||
|
|
||||||
|
if(CLIENT.state == CLIENT_STATE_DISCONNECTED) return;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ret = packetQueuePopIn(
|
||||||
|
&CLIENT.packetQueue,
|
||||||
|
&packet
|
||||||
|
);
|
||||||
|
|
||||||
|
if(ret == 0) break;
|
||||||
|
|
||||||
|
if(ret < 0) {
|
||||||
|
clientDisconnect();
|
||||||
|
consolePrint("Failed to pop packet");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = packetClientProcess(&packet, &CLIENT);
|
||||||
|
|
||||||
|
if(err != ERROR_OK) {
|
||||||
|
clientDisconnect();
|
||||||
|
consolePrint("Failed to process packet %s", errorString());
|
||||||
|
errorFlush();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} while(true);
|
||||||
|
}
|
||||||
|
|
||||||
void clientDisconnect() {
|
void clientDisconnect() {
|
||||||
if(CLIENT.state == CLIENT_STATE_DISCONNECTED) return;
|
if(CLIENT.state == CLIENT_STATE_DISCONNECTED) return;
|
||||||
|
|
||||||
|
@ -55,6 +55,11 @@ void clientInit();
|
|||||||
*/
|
*/
|
||||||
errorret_t clientConnect(const clientconnect_t connect);
|
errorret_t clientConnect(const clientconnect_t connect);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the client state.
|
||||||
|
*/
|
||||||
|
void clientUpdate();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disconnects the client from the server.
|
* Disconnects the client from the server.
|
||||||
*/
|
*/
|
||||||
|
@ -18,7 +18,6 @@ errorret_t networkedClientConnect(
|
|||||||
errorret_t err;
|
errorret_t err;
|
||||||
char_t *ip = "127.0.0.1";
|
char_t *ip = "127.0.0.1";
|
||||||
|
|
||||||
|
|
||||||
assertNotNull(client, "Client is NULL");
|
assertNotNull(client, "Client is NULL");
|
||||||
assertTrue(client->type == CLIENT_TYPE_NETWORKED, "Client is not networked");
|
assertTrue(client->type == CLIENT_TYPE_NETWORKED, "Client is not networked");
|
||||||
assertIsMainThread("Client connect must be on main thread");
|
assertIsMainThread("Client connect must be on main thread");
|
||||||
@ -328,7 +327,6 @@ void * networkedClientReadThread(void *arg) {
|
|||||||
pthread_cond_signal(&client->networked.cond);
|
pthread_cond_signal(&client->networked.cond);
|
||||||
pthread_mutex_unlock(&client->networked.lock);
|
pthread_mutex_unlock(&client->networked.lock);
|
||||||
|
|
||||||
// Main loop
|
|
||||||
while(client->state == CLIENT_STATE_CONNECTED) {
|
while(client->state == CLIENT_STATE_CONNECTED) {
|
||||||
pthread_mutex_lock(&client->networked.readLock);
|
pthread_mutex_lock(&client->networked.readLock);
|
||||||
|
|
||||||
@ -340,7 +338,10 @@ void * networkedClientReadThread(void *arg) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Received packet type: %d, length: %d\n", packet.type, packet.length);
|
packetQueuePushIn(
|
||||||
|
&client->packetQueue,
|
||||||
|
&packet
|
||||||
|
);
|
||||||
|
|
||||||
pthread_mutex_unlock(&client->networked.readLock);
|
pthread_mutex_unlock(&client->networked.readLock);
|
||||||
}
|
}
|
||||||
@ -353,7 +354,11 @@ void * networkedClientReadThread(void *arg) {
|
|||||||
pthread_mutex_unlock(&client->networked.lock);
|
pthread_mutex_unlock(&client->networked.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void * networkedClientWriteThread(void *arg) { // Renamed from networkedClientRightThread
|
void * networkedClientWriteThread(void *arg) {
|
||||||
|
packet_t packet;
|
||||||
|
int32_t ret;
|
||||||
|
errorret_t err;
|
||||||
|
|
||||||
assertNotNull(arg, "Write thread argument is NULL");
|
assertNotNull(arg, "Write thread argument is NULL");
|
||||||
assertNotMainThread("Write thread must not be on main thread");
|
assertNotMainThread("Write thread must not be on main thread");
|
||||||
|
|
||||||
@ -363,13 +368,35 @@ void * networkedClientWriteThread(void *arg) { // Renamed from networkedClientRi
|
|||||||
"Write thread argument is not networked"
|
"Write thread argument is not networked"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Perform additional operations
|
|
||||||
while(client->state == CLIENT_STATE_CONNECTED) {
|
while(client->state == CLIENT_STATE_CONNECTED) {
|
||||||
pthread_mutex_lock(&client->networked.writeLock); // Lock before writing
|
pthread_mutex_lock(&client->networked.writeLock);
|
||||||
|
|
||||||
// Add logic for the write thread here
|
ret = packetQueuePopOut(
|
||||||
// Example: Writing packets to the client
|
&client->packetQueue,
|
||||||
// networkedClientWritePacket(client, &somePacket);
|
&packet
|
||||||
|
);
|
||||||
|
|
||||||
|
if(ret == 0) {
|
||||||
|
pthread_mutex_unlock(&client->networked.writeLock);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ret < 0) {
|
||||||
|
consolePrint("Failed to pop packet from queue %s", errorString());
|
||||||
|
errorFlush();
|
||||||
|
client->state = CLIENT_STATE_DISCONNECTING;
|
||||||
|
pthread_mutex_unlock(&client->networked.writeLock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = networkedClientWritePacket(client, &packet);
|
||||||
|
if(err) {
|
||||||
|
consolePrint("Failed to write packet %s", errorString());
|
||||||
|
errorFlush();
|
||||||
|
client->state = CLIENT_STATE_DISCONNECTING;
|
||||||
|
pthread_mutex_unlock(&client->networked.writeLock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&client->networked.writeLock); // Unlock after writing
|
pthread_mutex_unlock(&client->networked.writeLock); // Unlock after writing
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include "packet/packet.h"
|
#include "packet/packetqueue.h"
|
||||||
|
|
||||||
typedef struct client_s client_t;
|
typedef struct client_s client_t;
|
||||||
typedef struct clientconnect_s clientconnect_t;
|
typedef struct clientconnect_s clientconnect_t;
|
||||||
|
17
src/main.c
17
src/main.c
@ -34,9 +34,14 @@ int32_t main(const int32_t argc, const char **argv) {
|
|||||||
|
|
||||||
entityInit(&GAME.entities[GAME.entityCount++], ENTITY_TYPE_PLAYER);
|
entityInit(&GAME.entities[GAME.entityCount++], ENTITY_TYPE_PLAYER);
|
||||||
|
|
||||||
|
float_t lastPing = -1;
|
||||||
|
float_t time = 0;
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
inputUpdate();
|
inputUpdate();
|
||||||
consoleUpdate();
|
consoleUpdate();
|
||||||
|
serverUpdate();
|
||||||
|
clientUpdate();
|
||||||
|
|
||||||
if(!CONSOLE.open) {
|
if(!CONSOLE.open) {
|
||||||
for(uint32_t i = 0; i < GAME.entityCount; i++) {
|
for(uint32_t i = 0; i < GAME.entityCount; i++) {
|
||||||
@ -47,8 +52,18 @@ int32_t main(const int32_t argc, const char **argv) {
|
|||||||
|
|
||||||
renderresult_t result = renderDraw();
|
renderresult_t result = renderDraw();
|
||||||
if(result != RENDER_OK) break;
|
if(result != RENDER_OK) break;
|
||||||
|
|
||||||
if(exitRequested) break;
|
if(exitRequested) break;
|
||||||
|
|
||||||
|
time += GetFrameTime();
|
||||||
|
if(time - lastPing > 1.0f) {
|
||||||
|
lastPing = time;
|
||||||
|
|
||||||
|
if(CLIENT.state != CLIENT_STATE_CONNECTED) continue;
|
||||||
|
packet_t packet;
|
||||||
|
packetPingCreate(&packet);
|
||||||
|
packetQueuePushOut(&CLIENT.packetQueue, &packet);
|
||||||
|
lastPing = time;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
serverDispose();
|
serverDispose();
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
|
#include "client/client.h"
|
||||||
|
#include "server/server.h"
|
||||||
|
|
||||||
void packetInit(
|
void packetInit(
|
||||||
packet_t *packet,
|
packet_t *packet,
|
||||||
@ -26,4 +28,46 @@ void packetInit(
|
|||||||
|
|
||||||
packet->type = type;
|
packet->type = type;
|
||||||
packet->length = length;
|
packet->length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t packetClientProcess(
|
||||||
|
const packet_t *packet,
|
||||||
|
client_t *client
|
||||||
|
) {
|
||||||
|
assertNotNull(packet, "Packet is NULL");
|
||||||
|
assertNotNull(client, "Client is NULL");
|
||||||
|
assertTrue(
|
||||||
|
client->type == CLIENT_TYPE_NETWORKED,
|
||||||
|
"Client is not networked"
|
||||||
|
);
|
||||||
|
assertIsMainThread("Client process must be on main thread");
|
||||||
|
|
||||||
|
switch(packet->type) {
|
||||||
|
case PACKET_TYPE_PING:
|
||||||
|
return packetPingClientProcess(packet, client);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return error("Unknown packet type %d", packet->type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t packetServerProcess(
|
||||||
|
const packet_t *packet,
|
||||||
|
serverclient_t *client
|
||||||
|
) {
|
||||||
|
assertNotNull(packet, "Packet is NULL");
|
||||||
|
assertNotNull(client, "Client is NULL");
|
||||||
|
assertTrue(
|
||||||
|
client->server->type == SERVER_TYPE_NETWORKED,
|
||||||
|
"Server is not networked"
|
||||||
|
);
|
||||||
|
assertIsMainThread("Server client process must be on main thread");
|
||||||
|
|
||||||
|
switch(packet->type) {
|
||||||
|
case PACKET_TYPE_PING:
|
||||||
|
return packetPingServerProcess(packet, client);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return error("Unknown packet type %d", packet->type);
|
||||||
|
}
|
||||||
}
|
}
|
@ -42,4 +42,30 @@ void packetInit(
|
|||||||
packet_t *packet,
|
packet_t *packet,
|
||||||
const packettype_t type,
|
const packettype_t type,
|
||||||
const uint32_t length
|
const uint32_t length
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes a packet for a given client. Will auto-decide the correct method to
|
||||||
|
* handle the process
|
||||||
|
*
|
||||||
|
* @param packet Pointer to the packet structure to process.
|
||||||
|
* @param client Pointer to the client structure.
|
||||||
|
* @return ERROR_OK on success, or an error code on failure.
|
||||||
|
*/
|
||||||
|
errorret_t packetClientProcess(
|
||||||
|
const packet_t *packet,
|
||||||
|
client_t *client
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes a packet for a given server client. Will auto-decide the correct
|
||||||
|
* method to handle the process
|
||||||
|
*
|
||||||
|
* @param packet Pointer to the packet structure to process.
|
||||||
|
* @param client Pointer to the server client structure.
|
||||||
|
* @return ERROR_OK on success, or an error code on failure.
|
||||||
|
*/
|
||||||
|
errorret_t packetServerProcess(
|
||||||
|
const packet_t *packet,
|
||||||
|
serverclient_t *client
|
||||||
);
|
);
|
@ -8,19 +8,33 @@
|
|||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
|
#include "server/server.h"
|
||||||
|
|
||||||
void packetPingCreate(packet_t *packet) {
|
void packetPingCreate(packet_t *packet) {
|
||||||
packetInit(packet, PACKET_TYPE_PING, sizeof(packetping_t));
|
packetInit(packet, PACKET_TYPE_PING, sizeof(packetping_t));
|
||||||
packet->data.ping.number = GetRandomValue(0, INT32_MAX);
|
packet->data.ping.number = GetRandomValue(0, INT32_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
errorret_t packetPingClient(packet_t *packet) {
|
errorret_t packetPingClientProcess(
|
||||||
assertNotNull(packet, "Packet is NULL");
|
const packet_t *packet,
|
||||||
assertTrue(packet->type == PACKET_TYPE_PING, "Packet type is not PING");
|
client_t *client
|
||||||
|
) {
|
||||||
|
printf("Client got Pong!\n");
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
errorret_t packetPingServerProcess(
|
||||||
|
const packet_t *packet,
|
||||||
|
serverclient_t *client
|
||||||
|
) {
|
||||||
if(packet->length != sizeof(packetping_t)) {
|
if(packet->length != sizeof(packetping_t)) {
|
||||||
return error("Ping packet length is not %d", sizeof(packetping_t));
|
return error("Ping packet length is not %d", sizeof(packetping_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf("Server got Ping!\n");
|
||||||
|
|
||||||
|
packet_t pong;
|
||||||
|
packetPingCreate(&pong);
|
||||||
|
packetQueuePushOut(&client->packetQueue, &pong);
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
@ -8,6 +8,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
|
|
||||||
|
typedef struct client_s client_t;
|
||||||
|
typedef struct serverclient_s serverclient_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32_t number;
|
int32_t number;
|
||||||
} packetping_t;
|
} packetping_t;
|
||||||
@ -20,9 +23,25 @@ typedef struct {
|
|||||||
void packetPingCreate(packet_t *packet);
|
void packetPingCreate(packet_t *packet);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a ping packet received FROM a server INTO a client.
|
* Validates a ping packet received FROM a client INTO a server.
|
||||||
*
|
*
|
||||||
* @param packet Pointer to the packet structure to handle.
|
* @param packet Pointer to the packet structure to validate.
|
||||||
|
* @param client Pointer to the server client structure.
|
||||||
* @return ERROR_OK on success, or an error code on failure.
|
* @return ERROR_OK on success, or an error code on failure.
|
||||||
*/
|
*/
|
||||||
errorret_t packetPingClient(packet_t *packet);
|
errorret_t packetPingClientProcess(
|
||||||
|
const packet_t *packet,
|
||||||
|
client_t *client
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a ping packet received FROM a client INTO a server.
|
||||||
|
*
|
||||||
|
* @param packet Pointer to the packet structure to handle.
|
||||||
|
* @param client Pointer to the server client structure.
|
||||||
|
* @return ERROR_OK on success, or an error code on failure.
|
||||||
|
*/
|
||||||
|
errorret_t packetPingServerProcess(
|
||||||
|
const packet_t *packet,
|
||||||
|
serverclient_t *client
|
||||||
|
);
|
@ -12,52 +12,75 @@
|
|||||||
void packetQueueInit(packetqueue_t *queue) {
|
void packetQueueInit(packetqueue_t *queue) {
|
||||||
assertNotNull(queue, "Packet queue is NULL");
|
assertNotNull(queue, "Packet queue is NULL");
|
||||||
memoryZero(queue, sizeof(packetqueue_t));
|
memoryZero(queue, sizeof(packetqueue_t));
|
||||||
|
pthread_mutex_init(&queue->lock, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void packetQueuePushIn(packetqueue_t *queue, const packet_t *packet) {
|
void packetQueuePushIn(packetqueue_t *queue, const packet_t *packet) {
|
||||||
assertNotNull(queue, "Packet queue is NULL");
|
assertNotNull(queue, "Packet queue is NULL");
|
||||||
assertNotNull(packet, "Packet is NULL");
|
assertNotNull(packet, "Packet is NULL");
|
||||||
|
pthread_mutex_lock(&queue->lock);
|
||||||
assertTrue(
|
assertTrue(
|
||||||
queue->packetsInCount < PACKET_QUEUE_MAX_SIZE, "Inbound packet queue is full"
|
queue->packetsInCount < PACKET_QUEUE_MAX_SIZE, "Inbound packet queue is full"
|
||||||
);
|
);
|
||||||
|
|
||||||
queue->packetsIn[queue->packetsInCount++] = *packet;
|
queue->packetsIn[queue->packetsInCount++] = *packet;
|
||||||
|
pthread_mutex_unlock(&queue->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void packetQueuePushOut(packetqueue_t *queue, const packet_t *packet) {
|
void packetQueuePushOut(packetqueue_t *queue, const packet_t *packet) {
|
||||||
assertNotNull(queue, "Packet queue is NULL");
|
assertNotNull(queue, "Packet queue is NULL");
|
||||||
assertNotNull(packet, "Packet is NULL");
|
assertNotNull(packet, "Packet is NULL");
|
||||||
|
pthread_mutex_lock(&queue->lock);
|
||||||
assertTrue(
|
assertTrue(
|
||||||
queue->packetsOutCount < PACKET_QUEUE_MAX_SIZE, "Outbound packet queue is full"
|
queue->packetsOutCount < PACKET_QUEUE_MAX_SIZE, "Outbound packet queue is full"
|
||||||
);
|
);
|
||||||
|
|
||||||
queue->packetsOut[queue->packetsOutCount++] = *packet;
|
queue->packetsOut[queue->packetsOutCount++] = *packet;
|
||||||
|
pthread_mutex_unlock(&queue->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
int packetQueuePopIn(packetqueue_t *queue, packet_t *packet) {
|
int32_t packetQueuePopIn(packetqueue_t *queue, packet_t *packet) {
|
||||||
assertNotNull(queue, "Packet queue is NULL");
|
assertNotNull(queue, "Packet queue is NULL");
|
||||||
assertNotNull(packet, "Packet is NULL");
|
assertNotNull(packet, "Packet is NULL");
|
||||||
|
|
||||||
if(queue->packetsInCount == 0) return 0;
|
pthread_mutex_lock(&queue->lock);
|
||||||
|
if(queue->packetsInCount == 0) {
|
||||||
|
pthread_mutex_unlock(&queue->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
*packet = queue->packetsIn[0];
|
*packet = queue->packetsIn[0];
|
||||||
for(uint32_t i = 1; i < queue->packetsInCount; i++) {
|
if(queue->packetsInCount > 1) {
|
||||||
queue->packetsIn[i - 1] = queue->packetsIn[i];
|
memoryCopy(
|
||||||
|
&queue->packetsIn[0],
|
||||||
|
&queue->packetsIn[1],
|
||||||
|
(queue->packetsInCount - 1) * sizeof(packet_t)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
queue->packetsInCount--;
|
queue->packetsInCount--;
|
||||||
|
pthread_mutex_unlock(&queue->lock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int packetQueuePopOut(packetqueue_t *queue, packet_t *packet) {
|
int32_t packetQueuePopOut(packetqueue_t *queue, packet_t *packet) {
|
||||||
assertNotNull(queue, "Packet queue is NULL");
|
assertNotNull(queue, "Packet queue is NULL");
|
||||||
assertNotNull(packet, "Packet is NULL");
|
assertNotNull(packet, "Packet is NULL");
|
||||||
|
|
||||||
if(queue->packetsOutCount == 0) return 0;
|
pthread_mutex_lock(&queue->lock);
|
||||||
|
if(queue->packetsOutCount == 0) {
|
||||||
|
pthread_mutex_unlock(&queue->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
*packet = queue->packetsOut[0];
|
*packet = queue->packetsOut[0];
|
||||||
for(uint32_t i = 1; i < queue->packetsOutCount; i++) {
|
if(queue->packetsOutCount > 1) {
|
||||||
queue->packetsOut[i - 1] = queue->packetsOut[i];
|
memoryCopy(
|
||||||
|
&queue->packetsOut[0],
|
||||||
|
&queue->packetsOut[1],
|
||||||
|
(queue->packetsOutCount - 1) * sizeof(packet_t)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
queue->packetsOutCount--;
|
queue->packetsOutCount--;
|
||||||
|
pthread_mutex_unlock(&queue->lock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "packet/packet.h"
|
#include "packet/packet.h"
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#define PACKET_QUEUE_MAX_SIZE 512
|
#define PACKET_QUEUE_MAX_SIZE 512
|
||||||
|
|
||||||
@ -15,6 +16,7 @@ typedef struct {
|
|||||||
uint32_t packetsInCount;
|
uint32_t packetsInCount;
|
||||||
packet_t packetsOut[PACKET_QUEUE_MAX_SIZE];
|
packet_t packetsOut[PACKET_QUEUE_MAX_SIZE];
|
||||||
uint32_t packetsOutCount;
|
uint32_t packetsOutCount;
|
||||||
|
pthread_mutex_t lock;
|
||||||
} packetqueue_t;
|
} packetqueue_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,7 +49,7 @@ void packetQueuePushOut(packetqueue_t *queue, const packet_t *packet);
|
|||||||
* @param packet Pointer to the packet to store the popped packet.
|
* @param packet Pointer to the packet to store the popped packet.
|
||||||
* @return 1 if a packet was popped, 0 otherwise.
|
* @return 1 if a packet was popped, 0 otherwise.
|
||||||
*/
|
*/
|
||||||
int packetQueuePopIn(packetqueue_t *queue, packet_t *packet);
|
int32_t packetQueuePopIn(packetqueue_t *queue, packet_t *packet);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pops a packet from the outbound packet queue.
|
* Pops a packet from the outbound packet queue.
|
||||||
@ -56,4 +58,4 @@ int packetQueuePopIn(packetqueue_t *queue, packet_t *packet);
|
|||||||
* @param packet Pointer to the packet to store the popped packet.
|
* @param packet Pointer to the packet to store the popped packet.
|
||||||
* @return 1 if a packet was popped, 0 otherwise.
|
* @return 1 if a packet was popped, 0 otherwise.
|
||||||
*/
|
*/
|
||||||
int packetQueuePopOut(packetqueue_t *queue, packet_t *packet);
|
int32_t packetQueuePopOut(packetqueue_t *queue, packet_t *packet);
|
@ -26,7 +26,7 @@ errorret_t networkedServerClientAccept(
|
|||||||
client->networked.socket = accept.networked.socket;
|
client->networked.socket = accept.networked.socket;
|
||||||
|
|
||||||
// Set timeout to 8 seconds
|
// Set timeout to 8 seconds
|
||||||
client->networked.timeout.tv_sec = 8;
|
client->networked.timeout.tv_sec = 4;
|
||||||
client->networked.timeout.tv_usec = 0;
|
client->networked.timeout.tv_usec = 0;
|
||||||
|
|
||||||
// Initialize mutexs
|
// Initialize mutexs
|
||||||
@ -282,7 +282,9 @@ void * networkedServerClientReadThread(void *arg) {
|
|||||||
packetWelcomeCreate(&packet);
|
packetWelcomeCreate(&packet);
|
||||||
err = networkedServerClientWritePacket(client, &packet);
|
err = networkedServerClientWritePacket(client, &packet);
|
||||||
if(err != ERROR_OK) {
|
if(err != ERROR_OK) {
|
||||||
networkedServerClientCloseOnThread(client, "Failed to send welcome message");
|
networkedServerClientCloseOnThread(
|
||||||
|
client, "Failed to send welcome message"
|
||||||
|
);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,6 +307,16 @@ void * networkedServerClientReadThread(void *arg) {
|
|||||||
while(client->state == SERVER_CLIENT_STATE_CONNECTED) {
|
while(client->state == SERVER_CLIENT_STATE_CONNECTED) {
|
||||||
pthread_mutex_lock(&client->networked.readLock);
|
pthread_mutex_lock(&client->networked.readLock);
|
||||||
|
|
||||||
|
err = networkedServerClientReadPacket(client, &packet);
|
||||||
|
if(err != ERROR_OK) {
|
||||||
|
consolePrint("Failed to read packet %s", errorString());
|
||||||
|
errorFlush();
|
||||||
|
pthread_mutex_unlock(&client->networked.readLock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
packetQueuePushIn(&client->packetQueue, &packet);
|
||||||
|
|
||||||
pthread_mutex_unlock(&client->networked.readLock);
|
pthread_mutex_unlock(&client->networked.readLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,6 +328,10 @@ void * networkedServerClientReadThread(void *arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void * networkedServerClientWriteThread(void *arg) {
|
void * networkedServerClientWriteThread(void *arg) {
|
||||||
|
packet_t packet;
|
||||||
|
int32_t ret;
|
||||||
|
errorret_t err;
|
||||||
|
|
||||||
assertNotNull(arg, "Client is NULL");
|
assertNotNull(arg, "Client is NULL");
|
||||||
assertNotMainThread("Client thread must not be main thread");
|
assertNotMainThread("Client thread must not be main thread");
|
||||||
assertTrue(
|
assertTrue(
|
||||||
@ -332,6 +348,33 @@ void * networkedServerClientWriteThread(void *arg) {
|
|||||||
while(client->state == SERVER_CLIENT_STATE_CONNECTED) {
|
while(client->state == SERVER_CLIENT_STATE_CONNECTED) {
|
||||||
pthread_mutex_lock(&client->networked.writeLock);
|
pthread_mutex_lock(&client->networked.writeLock);
|
||||||
|
|
||||||
|
ret = packetQueuePopOut(
|
||||||
|
&client->packetQueue,
|
||||||
|
&packet
|
||||||
|
);
|
||||||
|
|
||||||
|
if(ret == 0) {
|
||||||
|
pthread_mutex_unlock(&client->networked.writeLock);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ret < 0) {
|
||||||
|
consolePrint("Failed to pop packet %s", errorString());
|
||||||
|
errorFlush();
|
||||||
|
client->state = SERVER_CLIENT_STATE_DISCONNECTING;
|
||||||
|
pthread_mutex_unlock(&client->networked.writeLock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = networkedServerClientWritePacket(client, &packet);
|
||||||
|
if(err != ERROR_OK) {
|
||||||
|
consolePrint("Failed to write packet %s", errorString());
|
||||||
|
errorFlush();
|
||||||
|
client->state = SERVER_CLIENT_STATE_DISCONNECTING;
|
||||||
|
pthread_mutex_unlock(&client->networked.writeLock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(&client->networked.writeLock);
|
pthread_mutex_unlock(&client->networked.writeLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +96,16 @@ uint8_t serverGetClientCount() {
|
|||||||
return clientCount;
|
return clientCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void serverUpdate() {
|
||||||
|
assertIsMainThread("Server update must be on main thread");
|
||||||
|
if(SERVER.state != SERVER_STATE_RUNNING) return;
|
||||||
|
|
||||||
|
// Update all clients
|
||||||
|
for(uint8_t i = 0; i < SERVER_MAX_CLIENTS; i++) {
|
||||||
|
serverClientUpdate(&SERVER.clients[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void serverStop() {
|
void serverStop() {
|
||||||
assertIsMainThread("Server stop must be on main thread");
|
assertIsMainThread("Server stop must be on main thread");
|
||||||
if(SERVER.state == SERVER_STATE_STOPPED) return;
|
if(SERVER.state == SERVER_STATE_STOPPED) return;
|
||||||
|
@ -72,6 +72,11 @@ errorret_t serverStart(const serverstart_t start);
|
|||||||
*/
|
*/
|
||||||
uint8_t serverGetClientCount();
|
uint8_t serverGetClientCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a (main thread) update to process clients on the server.
|
||||||
|
*/
|
||||||
|
void serverUpdate();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop the server
|
* Stop the server
|
||||||
*
|
*
|
||||||
|
@ -35,6 +35,34 @@ errorret_t serverClientAccept(
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void serverClientUpdate(serverclient_t *client) {
|
||||||
|
assertNotNull(client, "Client is NULL");
|
||||||
|
assertIsMainThread("Server client update must be on main thread");
|
||||||
|
|
||||||
|
if(client->state != SERVER_CLIENT_STATE_CONNECTED) return;
|
||||||
|
|
||||||
|
packet_t packet;
|
||||||
|
int32_t ret = 1;
|
||||||
|
|
||||||
|
// Process packets
|
||||||
|
do {
|
||||||
|
ret = packetQueuePopIn(
|
||||||
|
&client->packetQueue,
|
||||||
|
&packet
|
||||||
|
);
|
||||||
|
|
||||||
|
if(ret == 0) break;
|
||||||
|
|
||||||
|
if(ret < 0) {
|
||||||
|
serverClientClose(client);
|
||||||
|
consolePrint("Failed to pop packet");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
packetServerProcess(&packet, client);
|
||||||
|
} while(true);
|
||||||
|
}
|
||||||
|
|
||||||
void serverClientClose(serverclient_t *client) {
|
void serverClientClose(serverclient_t *client) {
|
||||||
assertNotNull(client, "Client is NULL");
|
assertNotNull(client, "Client is NULL");
|
||||||
assertIsMainThread("Server client close must be on main thread");
|
assertIsMainThread("Server client close must be on main thread");
|
||||||
|
@ -48,6 +48,14 @@ errorret_t serverClientAccept(
|
|||||||
const serverclientaccept_t accept
|
const serverclientaccept_t accept
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the main thread updating of this server client. This is where all
|
||||||
|
* the packets will be handled and processed.
|
||||||
|
*
|
||||||
|
* @param client Pointer to the server client structure.
|
||||||
|
*/
|
||||||
|
void serverClientUpdate(serverclient_t *client);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the connection to a server client. Waits for the thread to finish.
|
* Closes the connection to a server client. Waits for the thread to finish.
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user