void client_disconnect(Client *client, bool send, const char *detail)
{
- client->state = CS_DISCONNECTED;
-
- if (send)
- send_command(client, SC_DISCONNECT);
-
pthread_mutex_lock(&client->mtx);
- close(client->fd);
- pthread_mutex_unlock(&client->mtx);
+ if (client->state != CS_DISCONNECTED) {
+ if (send)
+ write_u32(client->fd, SC_DISCONNECT);
- printf("Disconnected %s%s%s\n", INBRACES(detail));
+ client->state = CS_DISCONNECTED;
+ printf("Disconnected %s%s%s\n", INBRACES(detail));
+ close(client->fd);
+ }
+ pthread_mutex_unlock(&client->mtx);
}
static void *reciever_thread(void *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 (errno == EINTR)
+ client_disconnect(client, true, NULL);
+ else
+ client_disconnect(client, false, "network error");
if (client->name)
free(client->name);
break;
}
printf("%s\n", nodename);
+ } else if (strcmp(buffer, "kick") == 0) {
+ char target_name[NAME_MAX];
+ if (scanf("%s", target_name) == EOF)
+ return;
+ pthread_mutex_lock(&client->mtx);
+ if (write_u32(client->fd, SC_KICK))
+ write(client->fd, target_name, strlen(target_name) + 1);
+ pthread_mutex_unlock(&client->mtx);
} else {
printf("Invalid command: %s\n", buffer);
}
pthread_create(&recv_thread, NULL, &reciever_thread, &client);
client_loop(&client);
- perror("client_loop");
- if (client.state != CS_DISCONNECTED)
- client_disconnect(&client, true, NULL);
+ client_disconnect(&client, true, NULL);
pthread_join(recv_thread, NULL);
}
}
}
}
+
+void *linked_list_get(LinkedList *list, const char *key)
+{
+ for (LinkedListPair *pair = list->first; pair != NULL; pair = pair->next)
+ if (strcmp(pair->key, key) == 0)
+ return pair->value;
+ return NULL;
+}
return true;
}
-#include <stdio.h>
-
v3s32 map_node_to_block_pos(v3s32 pos, v3u8 *offset)
{
if (offset)
*offset = (v3u8) {(u32) pos.x % 16, (u32) pos.y % 16, (u32) pos.z % 16};
- printf("%d %d %d [ %d %d %d ]\n", pos.x, pos.y, pos.z, offset ? offset->x : 0, offset ? offset->y : 0, offset ? offset->z : 0);
return (v3s32) {floor((double) pos.x / 16), floor((double) pos.y / 16), floor((double) pos.z / 16)};
}
+#include <poll.h>
+
bool send_command(Client *client, RemoteCommand cmd)
{
pthread_mutex_lock(&client->mtx);
static void handle_packets(Client *client) {
while (client->state != CS_DISCONNECTED) {
+ struct pollfd pfd = {
+ .fd = client->fd,
+ .events = POLLIN,
+ .revents = 0,
+ };
+
+ int pstate = poll(&pfd, 1, 0);
+
+ if (pstate == -1) {
+ perror("poll");
+ return;
+ }
+
+ if (client->state == CS_DISCONNECTED)
+ return;
+
+ if (pstate == 0)
+ continue;
+
+ if (! (pfd.revents & POLLIN))
+ return;
+
HostCommand command;
if (! read_u32(client->fd, &command))
return;
if (! handler->func(client, good))
return;
} else {
- printf("Recieved invalid command %d (max = %d)\n", command, HOST_COMMAND_COUNT);
+ printf("Recieved invalid command %d\n", command);
}
}
}
MapBlock *block = map_get_block(client->server->map, pos, false);
if (block) {
- printf("Sending block %d %d %d\n", pos.x, pos.y, pos.z);
-
pthread_mutex_lock(&client->mtx);
bool ret = write_u32(client->fd, CC_BLOCK) && map_serialize_block(client->fd, block);
pthread_mutex_unlock(&client->mtx);
return true;
}
+static bool kick_handler(Client *client, bool good)
+{
+ char *target_name = read_string(client->fd, NAME_MAX);
+
+ if (! target_name)
+ return false;
+
+ if (good) {
+ Client *target = linked_list_get(&client->server->clients, target_name);
+ if (target)
+ server_disconnect_client(target, 0, "kicked");
+ }
+
+ free(target_name);
+ return true;
+}
+
CommandHandler command_handlers[SERVER_COMMAND_COUNT] = {
{0},
{&disconnect_handler, "DISCONNECT", CS_CREATED | CS_ACTIVE},
{&auth_handler, "AUTH", CS_CREATED},
{&getblock_handler, "GETBLOCK", CS_ACTIVE},
{&setnode_handler, "SETNODE", CS_ACTIVE},
+ {&kick_handler, "KICK", CS_ACTIVE},
};
SC_AUTH,
SC_GETBLOCK,
SC_SETNODE,
+ SC_KICK,
SERVER_COMMAND_COUNT,
} ServerCommand;