Add CLI client
parent
539323eef3
commit
c63f419e35
8
Makefile
8
Makefile
|
@ -1,11 +1,11 @@
|
|||
COMMON = array.o binsearch.o linkedlist.o map.o util.o types.o
|
||||
SERVER = $(COMMON) server.o server_command_handlers.o
|
||||
CLIENT = $(COMMON) client.o
|
||||
COMMON = array.o binsearch.o linkedlist.o map.o signal.o util.o types.o
|
||||
SERVER = $(COMMON) server.o servercommands.o
|
||||
CLIENT = $(COMMON) client.o clientcommands.o
|
||||
|
||||
all: Dragonblocks DragonblocksServer
|
||||
|
||||
Dragonblocks: $(CLIENT)
|
||||
cc -g -o Dragonblocks $(CLIENT)
|
||||
cc -g -o Dragonblocks $(CLIENT) -pthread
|
||||
|
||||
DragonblocksServer: $(SERVER)
|
||||
cc -g -o DragonblocksServer $(SERVER) -pthread
|
||||
|
|
170
client.c
170
client.c
|
@ -1,17 +1,160 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include "map.h"
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <sched.h>
|
||||
#include "client.h"
|
||||
#include "signal.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "network.c"
|
||||
|
||||
void client_disconnect(Client *client, bool send, const char *detail)
|
||||
{
|
||||
if (send)
|
||||
send_command(client, SC_DISCONNECT);
|
||||
|
||||
pthread_mutex_lock(&client->mtx);
|
||||
client->state = CS_DISCONNECTED;
|
||||
close(client->fd);
|
||||
pthread_mutex_unlock(&client->mtx);
|
||||
|
||||
printf("Disconnected %s%s%s\n", INBRACES(detail));
|
||||
}
|
||||
|
||||
static void *reciever_thread(void *cliptr)
|
||||
{
|
||||
Client *client = cliptr;
|
||||
|
||||
handle_packets(client);
|
||||
|
||||
if (client->state != CS_DISCONNECTED) {
|
||||
if (errno == EINTR)
|
||||
client_disconnect(client, true, NULL);
|
||||
else
|
||||
client_disconnect(client, false, "network error");
|
||||
}
|
||||
|
||||
if (client->name)
|
||||
free(client->name);
|
||||
|
||||
pthread_mutex_destroy(&client->mtx);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void client_loop(Client *client)
|
||||
{
|
||||
while (client->state != CS_DISCONNECTED) {
|
||||
if (client->state == CS_CREATED) {
|
||||
printf("Enter name: ");
|
||||
fflush(stdout);
|
||||
char name[NAME_MAX];
|
||||
if (scanf("%s", name) == EOF)
|
||||
return;
|
||||
client->name = strdup(name);
|
||||
pthread_mutex_lock(&client->mtx);
|
||||
if (write_u32(client->fd, SC_AUTH) && write(client->fd, client->name, strlen(name) + 1)) {
|
||||
client->state = CS_AUTH;
|
||||
printf("Authenticating...\n");
|
||||
}
|
||||
pthread_mutex_unlock(&client->mtx);
|
||||
} else if (client->state == CS_ACTIVE) {
|
||||
printf("%s: ", client->name);
|
||||
fflush(stdout);
|
||||
char buffer[BUFSIZ] = {0};
|
||||
if (scanf("%s", buffer) == EOF)
|
||||
return;
|
||||
if (strcmp(buffer, "disconnect") == 0) {
|
||||
return;
|
||||
} else if (strcmp(buffer, "setnode") == 0) {
|
||||
v3s32 pos;
|
||||
char node[BUFSIZ] = {0};
|
||||
if (scanf("%d %d %d %s", &pos.x, &pos.y, &pos.z, node) == EOF)
|
||||
return;
|
||||
Node node_type = NODE_INVALID;
|
||||
if (strcmp(node, "air") == 0)
|
||||
node_type = NODE_AIR;
|
||||
else if (strcmp(node, "grass") == 0)
|
||||
node_type = NODE_GRASS;
|
||||
else if (strcmp(node, "dirt") == 0)
|
||||
node_type = NODE_DIRT;
|
||||
else if (strcmp(node, "stone") == 0)
|
||||
node_type = NODE_STONE;
|
||||
if (node_type == NODE_INVALID) {
|
||||
printf("Invalid node\n");
|
||||
} else {
|
||||
pthread_mutex_lock(&client->mtx);
|
||||
if (write_u32(client->fd, SC_SETNODE) && write_v3s32(client->fd, pos))
|
||||
write_u32(client->fd, node_type);
|
||||
pthread_mutex_unlock(&client->mtx);
|
||||
}
|
||||
} else if (strcmp(buffer, "getnode") == 0) {
|
||||
v3s32 pos;
|
||||
if (scanf("%d %d %d", &pos.x, &pos.y, &pos.z) == EOF)
|
||||
return;
|
||||
pthread_mutex_lock(&client->mtx);
|
||||
if (write_u32(client->fd, SC_GETBLOCK))
|
||||
write_v3s32(client->fd, (v3s32) {pos.x / 16, pos.y / 16, pos.z / 16});
|
||||
pthread_mutex_unlock(&client->mtx);
|
||||
} else if (strcmp(buffer, "printnode") == 0) {
|
||||
v3s32 pos;
|
||||
if (scanf("%d %d %d", &pos.x, &pos.y, &pos.z) == EOF)
|
||||
return;
|
||||
MapNode node = map_get_node(client->map, pos);
|
||||
const char *nodename;
|
||||
switch (node.type) {
|
||||
case NODE_UNLOADED:
|
||||
nodename = "unloaded";
|
||||
break;
|
||||
case NODE_AIR:
|
||||
nodename = "air";
|
||||
break;
|
||||
case NODE_GRASS:
|
||||
nodename = "grass";
|
||||
break;
|
||||
case NODE_DIRT:
|
||||
nodename = "dirt";
|
||||
break;
|
||||
case NODE_STONE:
|
||||
nodename = "stone";
|
||||
break;
|
||||
case NODE_INVALID:
|
||||
nodename = "invalid";
|
||||
break;
|
||||
}
|
||||
printf("%s\n", nodename);
|
||||
} else {
|
||||
printf("Invalid command: %s\n", buffer);
|
||||
}
|
||||
} else {
|
||||
sched_yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
program_name = argv[0];
|
||||
|
||||
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
Client client = {
|
||||
.fd = -1,
|
||||
.map = NULL,
|
||||
.name = NULL,
|
||||
.state = CS_CREATED,
|
||||
};
|
||||
|
||||
if (sockfd == -1)
|
||||
pthread_mutex_init(&client.mtx, NULL);
|
||||
|
||||
client.fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
if (client.fd == -1)
|
||||
syscall_error("socket");
|
||||
|
||||
if (argc <= 1)
|
||||
|
@ -28,21 +171,20 @@ int main(int argc, char **argv)
|
|||
.sin_addr = addr_buf,
|
||||
};
|
||||
|
||||
if (connect(sockfd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
||||
if (connect(client.fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
||||
syscall_error("connect");
|
||||
|
||||
Map *map = map_create(NULL);
|
||||
init_signal_handlers();
|
||||
|
||||
MapBlock *block = map_deserialize_block(sockfd);
|
||||
if (block)
|
||||
map_create_block(map, (v3s32) {0, 0, 0}, block);
|
||||
else
|
||||
internal_error("invalid block recieved");
|
||||
client.map = map_create();
|
||||
|
||||
MapNode node = map_get_node(map, (v3s32) {0, 0, 0});
|
||||
printf("%d\n", node.type);
|
||||
pthread_t recv_thread;
|
||||
pthread_create(&recv_thread, NULL, &reciever_thread, &client);
|
||||
|
||||
close(sockfd);
|
||||
client_loop(&client);
|
||||
|
||||
map_delete(map);
|
||||
if (client.state != CS_DISCONNECTED)
|
||||
client_disconnect(&client, true, NULL);
|
||||
|
||||
pthread_join(recv_thread, NULL);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef _CLIENT_H_
|
||||
#define _CLIENT_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <pthread.h>
|
||||
#include "servercommands.h"
|
||||
#include "clientcommands.h"
|
||||
#include "network.h"
|
||||
#include "map.h"
|
||||
|
||||
typedef struct Client
|
||||
{
|
||||
int fd;
|
||||
char *name;
|
||||
Map *map;
|
||||
ClientState state;
|
||||
pthread_mutex_t mtx;
|
||||
} Client;
|
||||
|
||||
void client_disconnect(Client *client, bool send, const char *detail);
|
||||
|
||||
#endif
|
|
@ -1,4 +0,0 @@
|
|||
#! /bin/bash
|
||||
|
||||
# AUTH Name SETNODE x = 0 y = 0 z = 0 DIRT GETBLOCK x = 0 y = 0 z = 0 DISCONNECT
|
||||
echo -ne "\0\0\0\x02Fleckenstein\0\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\x03\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01" | nc localhost 4000 | hexdump
|
|
@ -1,12 +0,0 @@
|
|||
#ifndef _CLIENT_COMMAND_H_
|
||||
#define _CLIENT_COMMAND_H_
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CC_DISCONNECT,
|
||||
CC_AUTH_SUCCESS,
|
||||
CC_AUTH_FAILURE,
|
||||
CC_BLOCK,
|
||||
} ClientCommand;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,44 @@
|
|||
#include <stdio.h>
|
||||
#include "client.h"
|
||||
#include "types.h"
|
||||
|
||||
static bool disconnect_handler(Client *client, bool good)
|
||||
{
|
||||
if (good)
|
||||
client_disconnect(client, false, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool auth_handler(Client *client, bool good)
|
||||
{
|
||||
u8 success;
|
||||
if (! read_u8(client->fd, &success))
|
||||
return false;
|
||||
|
||||
if (! good)
|
||||
return true;
|
||||
|
||||
if (success) {
|
||||
printf("Authenticated successfully\n");
|
||||
client->state = CS_ACTIVE;
|
||||
} else {
|
||||
printf("Authentication failed, please try again\n");
|
||||
client->state = CS_CREATED;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool block_handler(Client *client, bool good)
|
||||
{
|
||||
if (good)
|
||||
return map_deserialize_block(client->fd, client->map);
|
||||
return true;
|
||||
}
|
||||
|
||||
CommandHandler command_handlers[CLIENT_COMMAND_COUNT] = {
|
||||
{0},
|
||||
{&disconnect_handler, "DISCONNECT", CS_CREATED | CS_AUTH | CS_ACTIVE},
|
||||
{&auth_handler, "AUTH", CS_AUTH},
|
||||
{&block_handler, "BLOCK", CS_ACTIVE},
|
||||
};
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef _CLIENT_COMMAND_H_
|
||||
#define _CLIENT_COMMAND_H_
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CLIENT_COMMAND_NULL,
|
||||
CC_DISCONNECT,
|
||||
CC_AUTH,
|
||||
CC_BLOCK,
|
||||
CLIENT_COMMAND_COUNT
|
||||
} ClientCommand;
|
||||
|
||||
#ifdef _SERVER_H_
|
||||
typedef ClientCommand RemoteCommand;
|
||||
#endif
|
||||
|
||||
#ifdef _CLIENT_H_
|
||||
typedef ClientCommand HostCommand;
|
||||
#define HOST_COMMAND_COUNT CLIENT_COMMAND_COUNT
|
||||
#endif
|
||||
|
||||
#endif
|
40
map.c
40
map.c
|
@ -68,20 +68,6 @@ MapBlock *map_get_block(Map *map, v3s32 pos, bool create)
|
|||
return block;
|
||||
}
|
||||
|
||||
void map_create_block(Map *map, v3s32 pos, MapBlock *block)
|
||||
{
|
||||
block->pos = pos;
|
||||
|
||||
MapSector *sector = map_get_sector(map, (v2s32) {pos.x, pos.z}, true);
|
||||
BinsearchResult res = binsearch(&pos.y, sector->blocks.ptr, sector->blocks.siz, &block_compare);
|
||||
if (res.success) {
|
||||
raw_delete_block(sector->blocks.ptr[res.index]);
|
||||
sector->blocks.ptr[res.index] = block;
|
||||
} else {
|
||||
array_insert(§or->blocks, block, res.index);
|
||||
}
|
||||
}
|
||||
|
||||
bool map_deserialize_node(int fd, MapNode *node)
|
||||
{
|
||||
Node type;
|
||||
|
@ -99,6 +85,9 @@ bool map_deserialize_node(int fd, MapNode *node)
|
|||
|
||||
bool map_serialize_block(int fd, MapBlock *block)
|
||||
{
|
||||
if (! write_v3s32(fd, block->pos))
|
||||
return false;
|
||||
|
||||
ITERATE_MAPBLOCK {
|
||||
if (! write_u32(fd, block->data[x][y][z].type))
|
||||
return false;
|
||||
|
@ -107,16 +96,30 @@ bool map_serialize_block(int fd, MapBlock *block)
|
|||
return true;
|
||||
}
|
||||
|
||||
MapBlock *map_deserialize_block(int fd)
|
||||
bool map_deserialize_block(int fd, Map *map)
|
||||
{
|
||||
MapBlock *block = malloc(sizeof(MapBlock));
|
||||
|
||||
if (! read_v3s32(fd, &block->pos))
|
||||
return false;
|
||||
|
||||
ITERATE_MAPBLOCK {
|
||||
if (! map_deserialize_node(fd, &block->data[x][y][z])) {
|
||||
free(block);
|
||||
return NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return block;
|
||||
|
||||
MapSector *sector = map_get_sector(map, (v2s32) {block->pos.x, block->pos.z}, true);
|
||||
BinsearchResult res = binsearch(&block->pos.y, sector->blocks.ptr, sector->blocks.siz, &block_compare);
|
||||
if (res.success) {
|
||||
raw_delete_block(sector->blocks.ptr[res.index]);
|
||||
sector->blocks.ptr[res.index] = block;
|
||||
} else {
|
||||
array_insert(§or->blocks, block, res.index);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
MapNode map_get_node(Map *map, v3s32 pos)
|
||||
|
@ -145,10 +148,9 @@ void map_node_clear(MapNode *node)
|
|||
linked_list_clear(&node->meta);
|
||||
}
|
||||
|
||||
Map *map_create(FILE *file)
|
||||
Map *map_create()
|
||||
{
|
||||
Map *map = malloc(sizeof(Map));
|
||||
map->file = file;
|
||||
map->sectors = array_create();
|
||||
|
||||
return map;
|
||||
|
|
9
map.h
9
map.h
|
@ -1,7 +1,6 @@
|
|||
#ifndef _MAP_H_
|
||||
#define _MAP_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include "array.h"
|
||||
#include "linkedlist.h"
|
||||
|
@ -32,16 +31,14 @@ typedef struct
|
|||
typedef struct
|
||||
{
|
||||
Array sectors;
|
||||
FILE *file;
|
||||
} Map;
|
||||
|
||||
MapSector *map_get_sector(Map *map, v2s32 pos, bool create);
|
||||
MapBlock *map_get_block(Map *map, v3s32 pos, bool create);
|
||||
void map_create_block(Map *map, v3s32 pos, MapBlock *block);
|
||||
|
||||
bool map_deserialize_node(int fd, MapNode *buf);
|
||||
bool map_serialize_block(int fd, MapBlock *);
|
||||
MapBlock *map_deserialize_block(int fd);
|
||||
bool map_serialize_block(int fd, MapBlock *block);
|
||||
bool map_deserialize_block(int fd, Map *map);
|
||||
|
||||
void map_delete_block(MapBlock *); // ToDo
|
||||
void map_unload_block(MapBlock *); // ToDo
|
||||
|
@ -51,7 +48,7 @@ void map_set_node(Map *map, v3s32 pos, MapNode node);
|
|||
MapNode map_node_create(Node type);
|
||||
void map_node_clear(MapNode *node);
|
||||
|
||||
Map *map_create(FILE *file);
|
||||
Map *map_create();
|
||||
void map_delete(Map *map);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
bool send_command(Client *client, RemoteCommand cmd)
|
||||
{
|
||||
pthread_mutex_lock(&client->mtx);
|
||||
bool ret = write_u32(client->fd, cmd);
|
||||
pthread_mutex_unlock(&client->mtx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void handle_packets(Client *client) {
|
||||
while (client->state != CS_DISCONNECTED) {
|
||||
HostCommand command;
|
||||
if (! read_u32(client->fd, &command))
|
||||
break;
|
||||
|
||||
CommandHandler *handler = NULL;
|
||||
|
||||
if (command < HOST_COMMAND_COUNT)
|
||||
handler = &command_handlers[command];
|
||||
|
||||
if (handler && handler->func) {
|
||||
bool good = client->state & handler->state_flags;
|
||||
if (! good)
|
||||
printf("Recieved %s command, but client is in invalid state: %d\n", handler->name, client->state);
|
||||
if (! handler->func(client, good))
|
||||
break;
|
||||
} else {
|
||||
printf("Recieved invalid command %d (max = %d)\n", command, HOST_COMMAND_COUNT);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef _NETWORK_H_
|
||||
#define _NETWORK_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#define NAME_MAX 64
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CS_CREATED = 0x01,
|
||||
CS_AUTH = 0x02,
|
||||
CS_ACTIVE = 0x04,
|
||||
CS_DISCONNECTED = 0x08,
|
||||
} ClientState;
|
||||
|
||||
struct Client;
|
||||
|
||||
typedef struct {
|
||||
bool (*func)(struct Client *client, bool good);
|
||||
const char *name;
|
||||
int state_flags;
|
||||
} CommandHandler;
|
||||
|
||||
extern CommandHandler command_handlers[];
|
||||
|
||||
bool send_command(struct Client *client, RemoteCommand cmd);
|
||||
|
||||
#endif
|
72
server.c
72
server.c
|
@ -1,29 +1,19 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <endian.h>
|
||||
#include <pthread.h>
|
||||
#include "linkedlist.h"
|
||||
#include "map.h"
|
||||
#include "server.h"
|
||||
#include "server_commands.h"
|
||||
#include "server_command_handlers.h"
|
||||
#include "servercommands.h"
|
||||
#include "signal.h"
|
||||
#include "util.h"
|
||||
#define ever (;;)
|
||||
|
||||
bool server_send_command(Client *client, ClientCommand command)
|
||||
{
|
||||
pthread_mutex_lock(&client->mtx);
|
||||
bool ret = write_s32(client->fd, command);
|
||||
pthread_mutex_unlock(&client->mtx);
|
||||
return ret;
|
||||
}
|
||||
#include "network.c"
|
||||
|
||||
char *server_get_client_name(Client *client)
|
||||
{
|
||||
|
@ -36,16 +26,16 @@ void server_disconnect_client(Client *client, int flags, const char *detail)
|
|||
linked_list_delete(&client->server->clients, client->name);
|
||||
|
||||
if (! (flags & DISCO_NO_MESSAGE))
|
||||
printf("Disconnected %s %s%s%s\n", server_get_client_name(client), detail ? "(" : "", detail ? detail : "", detail ? ")" : "");
|
||||
printf("Disconnected %s %s%s%s\n", server_get_client_name(client), INBRACES(detail));
|
||||
|
||||
if (! (flags & DISCO_NO_SEND))
|
||||
server_send_command(client, CC_DISCONNECT);
|
||||
send_command(client, CC_DISCONNECT);
|
||||
|
||||
client->state = CS_DISCONNECTED;
|
||||
|
||||
pthread_mutex_lock(&client->mtx);
|
||||
close(client->fd);
|
||||
pthread_mutex_unlock(&client->mtx);
|
||||
|
||||
client->state = CS_DISCONNECTED;
|
||||
}
|
||||
|
||||
void server_shutdown(Server *srv)
|
||||
|
@ -63,35 +53,14 @@ void server_shutdown(Server *srv)
|
|||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static void *client_handler_thread(void *clientptr)
|
||||
static void *reciever_thread(void *clientptr)
|
||||
{
|
||||
Client *client = clientptr;
|
||||
|
||||
while (client->state != CS_DISCONNECTED) {
|
||||
|
||||
ServerCommand command;
|
||||
if (! read_u32(client->fd, &command))
|
||||
break;
|
||||
|
||||
ServerCommandHandler *handler = NULL;
|
||||
|
||||
if (command < SERVER_COMMAND_COUNT)
|
||||
handler = &server_command_handlers[command];
|
||||
|
||||
if (handler && handler->func) {
|
||||
if (client->state & handler->state_flags) {
|
||||
if (! handler->func(client))
|
||||
break;
|
||||
} else {
|
||||
printf("Recieved %s command from client %s, but client is in invalid state: %d\n", handler->name, server_get_client_name(client), client->state);
|
||||
}
|
||||
} else {
|
||||
printf("Recieved invalid command %d from client %s\n", command, server_get_client_name(client));
|
||||
}
|
||||
}
|
||||
handle_packets(client);
|
||||
|
||||
if (client->state != CS_DISCONNECTED)
|
||||
server_disconnect_client(client, DISCO_NO_SEND, "connection error");
|
||||
server_disconnect_client(client, DISCO_NO_SEND, "network error");
|
||||
|
||||
if (client->name)
|
||||
free(client->name);
|
||||
|
@ -125,17 +94,7 @@ static void accept_client(Server *srv)
|
|||
pthread_mutex_init(&client->mtx, NULL);
|
||||
|
||||
pthread_t thread;
|
||||
pthread_create(&thread, NULL, &client_handler_thread, client);
|
||||
}
|
||||
|
||||
static void interrupt_handler(int sig)
|
||||
{
|
||||
fprintf(stderr, "%s\n", strsignal(sig));
|
||||
}
|
||||
|
||||
static void silent_handler(int sig)
|
||||
{
|
||||
(void) sig;
|
||||
pthread_create(&thread, NULL, &reciever_thread, client);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
@ -170,14 +129,7 @@ int main(int argc, char **argv)
|
|||
if (listen(server.sockfd, 3) == -1)
|
||||
syscall_error("listen");
|
||||
|
||||
struct sigaction sigact_interrupt = {0};
|
||||
sigact_interrupt.sa_handler = &interrupt_handler;
|
||||
sigaction(SIGINT, &sigact_interrupt, NULL);
|
||||
sigaction(SIGTERM, &sigact_interrupt, NULL);
|
||||
|
||||
struct sigaction sigact_silent = {0};
|
||||
sigact_silent.sa_handler = &silent_handler;
|
||||
sigaction(SIGPIPE, &sigact_silent, NULL);
|
||||
init_signal_handlers();
|
||||
|
||||
server.map = map_create(NULL);
|
||||
|
||||
|
|
16
server.h
16
server.h
|
@ -2,9 +2,11 @@
|
|||
#define _SERVER_H_
|
||||
|
||||
#include <pthread.h>
|
||||
#include "client_commands.h"
|
||||
#include "clientcommands.h"
|
||||
#include "servercommands.h"
|
||||
#include "linkedlist.h"
|
||||
#include "map.h"
|
||||
#include "network.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -13,19 +15,12 @@ typedef struct
|
|||
LinkedList clients;
|
||||
} Server;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CS_CREATED = 0x01,
|
||||
CS_ACTIVE = 0x02,
|
||||
CS_DISCONNECTED = 0x04,
|
||||
} ClientState;
|
||||
|
||||
typedef struct
|
||||
typedef struct Client
|
||||
{
|
||||
int fd;
|
||||
char *name;
|
||||
Server *server;
|
||||
ClientState state;
|
||||
int fd;
|
||||
pthread_mutex_t mtx;
|
||||
} Client;
|
||||
|
||||
|
@ -36,7 +31,6 @@ typedef enum
|
|||
DISCO_NO_MESSAGE = 0x04,
|
||||
} DiscoFlag;
|
||||
|
||||
bool server_send_command(Client *client, ClientCommand command);
|
||||
char *server_get_client_name(Client *client);
|
||||
void server_disconnect_client(Client *client, int flags, const char *detail);
|
||||
void server_shutdown(Server *srv);
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
#ifndef _SERVER_COMMAND_HANDLERS_H_
|
||||
#define _SERVER_COMMAND_HANDLERS_H_
|
||||
|
||||
#include "server.h"
|
||||
|
||||
typedef struct {
|
||||
bool (*func)(Client *client);
|
||||
const char *name;
|
||||
int state_flags;
|
||||
} ServerCommandHandler;
|
||||
|
||||
extern ServerCommandHandler server_command_handlers[];
|
||||
|
||||
#endif
|
|
@ -1,44 +1,57 @@
|
|||
#include <stdio.h>
|
||||
#include "util.h"
|
||||
#include <stdlib.h>
|
||||
#include "server.h"
|
||||
#include "server_commands.h"
|
||||
#include "server_command_handlers.h"
|
||||
#include "util.h"
|
||||
|
||||
static bool disconnect_handler(Client *client)
|
||||
static bool disconnect_handler(Client *client, bool good)
|
||||
{
|
||||
server_disconnect_client(client, 0, NULL);
|
||||
if (good)
|
||||
server_disconnect_client(client, DISCO_NO_SEND, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool auth_handler(Client *client)
|
||||
static bool auth_handler(Client *client, bool good)
|
||||
{
|
||||
char *name = read_string(client->fd, NAME_MAX);
|
||||
|
||||
if (! name)
|
||||
return false;
|
||||
|
||||
if (! good) {
|
||||
free(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
u8 success;
|
||||
|
||||
if (linked_list_put(&client->server->clients, name, client)) {
|
||||
client->name = name;
|
||||
client->state = CS_ACTIVE;
|
||||
printf("Auth success: %s\n", server_get_client_name(client));
|
||||
if (! server_send_command(client, CC_AUTH_SUCCESS))
|
||||
return false;
|
||||
success = 1;
|
||||
} else {
|
||||
printf("Auth failure: %s\n", server_get_client_name(client));
|
||||
if (! server_send_command(client, CC_AUTH_FAILURE))
|
||||
return false;
|
||||
free(name);
|
||||
success = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
pthread_mutex_lock(&client->mtx);
|
||||
bool ret = write_u32(client->fd, CC_AUTH) && write_u8(client->fd, success);
|
||||
pthread_mutex_unlock(&client->mtx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool getblock_handler(Client *client)
|
||||
static bool getblock_handler(Client *client, bool good)
|
||||
{
|
||||
v3s32 pos;
|
||||
|
||||
if (! read_v3s32(client->fd, &pos))
|
||||
return false;
|
||||
|
||||
if (! good)
|
||||
return true;
|
||||
|
||||
MapBlock *block = map_get_block(client->server->map, pos, false);
|
||||
if (block) {
|
||||
pthread_mutex_lock(&client->mtx);
|
||||
|
@ -51,7 +64,7 @@ static bool getblock_handler(Client *client)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool setnode_handler(Client *client)
|
||||
static bool setnode_handler(Client *client, bool good)
|
||||
{
|
||||
v3s32 pos;
|
||||
|
||||
|
@ -63,12 +76,13 @@ static bool setnode_handler(Client *client)
|
|||
if (! map_deserialize_node(client->fd, &node))
|
||||
return false;
|
||||
|
||||
map_set_node(client->server->map, pos, node);
|
||||
if (good)
|
||||
map_set_node(client->server->map, pos, node);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ServerCommandHandler server_command_handlers[SERVER_COMMAND_COUNT] = {
|
||||
CommandHandler command_handlers[SERVER_COMMAND_COUNT] = {
|
||||
{0},
|
||||
{&disconnect_handler, "DISCONNECT", CS_CREATED | CS_ACTIVE},
|
||||
{&auth_handler, "AUTH", CS_CREATED},
|
|
@ -1,8 +1,6 @@
|
|||
#ifndef _SERVER_COMMAND_H_
|
||||
#define _SERVER_COMMAND_H_
|
||||
|
||||
#define NAME_MAX 64
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SERVER_COMMAND_NULL,
|
||||
|
@ -13,4 +11,13 @@ typedef enum
|
|||
SERVER_COMMAND_COUNT,
|
||||
} ServerCommand;
|
||||
|
||||
#ifdef _CLIENT_H_
|
||||
typedef ServerCommand RemoteCommand;
|
||||
#endif
|
||||
|
||||
#ifdef _SERVER_H_
|
||||
typedef ServerCommand HostCommand;
|
||||
#define HOST_COMMAND_COUNT SERVER_COMMAND_COUNT
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,26 @@
|
|||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static void interrupt_handler(int sig)
|
||||
{
|
||||
fprintf(stderr, "%s\n", strsignal(sig));
|
||||
}
|
||||
|
||||
static void silent_handler(int sig)
|
||||
{
|
||||
(void) sig;
|
||||
}
|
||||
|
||||
static struct sigaction sigact_interrupt = {0};
|
||||
static struct sigaction sigact_silent = {0};
|
||||
|
||||
void init_signal_handlers()
|
||||
{
|
||||
sigact_interrupt.sa_handler = &interrupt_handler;
|
||||
sigaction(SIGINT, &sigact_interrupt, NULL);
|
||||
sigaction(SIGTERM, &sigact_interrupt, NULL);
|
||||
|
||||
sigact_silent.sa_handler = &silent_handler;
|
||||
sigaction(SIGPIPE, &sigact_silent, NULL);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef _SIGNAL_H_
|
||||
#define _SIGNAL_H_
|
||||
|
||||
void init_signal_handlers();
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue