Server config load and graceful client exit
This commit is contained in:
@@ -2,12 +2,21 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/msg.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "commands.h"
|
||||
#include "signal.h"
|
||||
|
||||
// Wanted a graceful exit so need to keep this in global state
|
||||
static int client_queue_id_global = -1;
|
||||
static int server_queue_id_global = -1;
|
||||
static char client_id_global[COMMAND_LENGTH];
|
||||
static pid_t heartbeat_pid = -1;
|
||||
static pid_t input_pid = -1;
|
||||
|
||||
// Make a macro for this cause I'm not typing sizeof twice every time
|
||||
#define send(queue_id, msgbuf_ptr) msgsnd(queue_id, msgbuf_ptr, sizeof(*(msgbuf_ptr)) - sizeof(long), 0)
|
||||
@@ -30,6 +39,27 @@ static void cleanup_queue(int qid) {
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup_and_exit(int sig) {
|
||||
printf("\nLogging out... ");
|
||||
|
||||
if (server_queue_id_global != -1) {
|
||||
msgbuf_t logout = {.mtype = Logout, .sender = ""};
|
||||
strncpy(logout.sender, client_id_global, COMMAND_LENGTH - 1);
|
||||
msgsnd(server_queue_id_global, &logout, sizeof(logout) - sizeof(long), 0);
|
||||
}
|
||||
|
||||
// Burn the orphanage
|
||||
if (heartbeat_pid > 0)
|
||||
kill(heartbeat_pid, SIGTERM);
|
||||
if (input_pid > 0)
|
||||
kill(input_pid, SIGTERM);
|
||||
|
||||
cleanup_queue(client_queue_id_global);
|
||||
|
||||
printf("Bye!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void input_loop(int server_queue_id, const char *client_id) {
|
||||
while (1) {
|
||||
// Minimum length plus extra space fore command name and seperators
|
||||
@@ -88,9 +118,8 @@ static void input_loop(int server_queue_id, const char *client_id) {
|
||||
}
|
||||
} else if (strncmp(buffer, "/mute ", 6) == 0) {
|
||||
// handle mute
|
||||
} else if (strcmp(buffer, "/quit") == 0) {
|
||||
// TODO: Would be nice to have a way to gracefully logout and not just
|
||||
// depend on heartbeats, maybe
|
||||
} else if (strcmp(buffer, "/quit") == 0 || strcmp(buffer, "/exit") == 0 || strcmp(buffer, "/q") == 0) {
|
||||
return;
|
||||
} else if (strncmp(buffer, "/inbox", 8) == 0) {
|
||||
msgbuf_t msg = {.mtype = Inbox, .sender = ""};
|
||||
strncpy(msg.sender, client_id, COMMAND_LENGTH - 1);
|
||||
@@ -163,16 +192,29 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
printf("Login accepted. Welcome, %s!\n", resp.command);
|
||||
|
||||
if (fork() == 0) {
|
||||
strncpy(client_id_global, client_id, COMMAND_LENGTH - 1);
|
||||
client_queue_id_global = client_queue_id;
|
||||
server_queue_id_global = server_queue_id;
|
||||
|
||||
|
||||
heartbeat_pid = fork();
|
||||
if (heartbeat_pid == 0) {
|
||||
heartbeat_loop(server_queue_id, client_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fork() == 0) {
|
||||
input_pid = fork();
|
||||
if (input_pid == 0) {
|
||||
input_loop(server_queue_id, client_id);
|
||||
// The /quit command just returns from the input loop
|
||||
kill(getppid(), SIGTERM);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Setup them below the forks to avoid multiple triggers
|
||||
signal(SIGINT, cleanup_and_exit);
|
||||
signal(SIGTERM, cleanup_and_exit);
|
||||
|
||||
while (1) {
|
||||
msgbuf_t incoming;
|
||||
ssize_t got = msgrcv(client_queue_id, &incoming, sizeof(incoming) - sizeof(long), 0, 0);
|
||||
@@ -194,7 +236,7 @@ int main(int argc, char *argv[]) {
|
||||
// Check the command field for the list type
|
||||
if (strncmp(incoming.command, "active", COMMAND_LENGTH) == 0) {
|
||||
printf("Active clients:\n%s\n", incoming.message);
|
||||
} else if (strncmp(incoming.command, "group", COMMAND_LENGTH) == 0) {
|
||||
} else if (strncmp(incoming.command, "groups", COMMAND_LENGTH) == 0) {
|
||||
printf("All group members:\n%s\n", incoming.message);
|
||||
} else {
|
||||
printf("All clients:\n%s\n", incoming.message);
|
||||
|
||||
Reference in New Issue
Block a user