From 7dccc50b8798edfebf376abb580c185a170047ad Mon Sep 17 00:00:00 2001 From: Piotr Kozak Date: Tue, 6 Jan 2026 00:12:48 +0100 Subject: [PATCH] Added client listing --- client.c | 56 ++++++++++++++++++++++++++++++++--------------- server.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 97 insertions(+), 25 deletions(-) diff --git a/client.c b/client.c index 32c1201..9c44db5 100644 --- a/client.c +++ b/client.c @@ -81,12 +81,25 @@ static void input_loop(int server_queue_id, const char *client_id) { if (send(server_queue_id, &msg) == -1) { perror("msgsnd(/msg) failed"); } - } else if (strncmp(buffer, "/list", 5) == 0) { - // handle list + } else if (strncmp(buffer, "/list ", 6) == 0) { + char *offset = buffer + 6; + + if (strcmp(offset, "active") != 0 && strcmp(offset, "all") != 0) { + printf("Invalid list type. Use /list active or /list all\n"); + continue; + } + + msgbuf_t msg = {.mtype = List_clients, .sender = ""}; + strncpy(msg.sender, client_id, COMMAND_LENGTH - 1); + strncpy(msg.command, offset, COMMAND_LENGTH - 1); + if (send(server_queue_id, &msg) == -1) { + perror("msgsnd(/list) failed"); + } } else if (strncmp(buffer, "/mute ", 6) == 0) { // handle mute } else if (strcmp(buffer, "/quit") == 0) { - // exit + // TODO: Would be nice to have a way to gracefully logout and not just + // depend on heartbeats, maybe } else { printf("Unknown command\n"); } @@ -160,18 +173,6 @@ int main(int argc, char *argv[]) { return 0; } - // /* Send a test message to the server */ - // msgbuf_t test = {.mtype = Message, .command = "u:test2", .sender = ""}; - // strncpy(test.sender, client_id, COMMAND_LENGTH - 1); - // snprintf(test.message, MESSAGE_LENGTH, "Hello from %s", client_id); - - // if (msgsnd(server_queue_id, &test, sizeof(test) - sizeof(long), 0) == -1) { - // printf("DEBUG: test.mtype = %u\n", test.mtype); - // perror("failed while sending a test message"); - // cleanup_queue(client_queue_id); - // return 1; - // } - while (1) { msgbuf_t incoming; ssize_t got = msgrcv(client_queue_id, &incoming, @@ -190,12 +191,33 @@ int main(int argc, char *argv[]) { case Message: printf("%s: %s\n", incoming.sender, incoming.message); break; + case List_clients: { + // 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 { + printf("All clients:\n%s\n", incoming.message); + } + break; + } case Signal: + // Tell the user if the previous message was accepted and/or delivered + if (incoming.stype == ACK_ACCEPTED) { + printf("Message sent successfully.\n"); + } else if (incoming.stype == ACK_DELIVERED) { + printf("Message delivered to the %s.\n", incoming.command); + } else if (incoming.stype == ERR_USER_NOT_FOUND) { + printf("Your message could not be delivered: User not found.\n"); + } else { + // Display whatever if I forgot to handle something + printf("Your message could not be delivered: Error code %d.\n", + incoming.stype); + } break; default: - printf("Received unknown mtype=%ld stype=%d\n", (long)incoming.mtype, - incoming.stype); + printf("Received unknown command of mtype=%ld stype=%d\n", + (long)incoming.mtype, incoming.stype); break; } } diff --git a/server.c b/server.c index dd6c019..e490f50 100644 --- a/server.c +++ b/server.c @@ -125,7 +125,7 @@ int main(int argc, char **argv) { msgrcv(server_queue_id, &msgbuf, sizeof(msgbuf) - sizeof(long), 0, 0); switch (msgbuf.mtype) { - case Login: + case Login: { printf("Received login request for id: %s\n", msgbuf.sender); Client *client = NULL; for (int i = 0; i < client_count; i++) { @@ -172,11 +172,12 @@ int main(int argc, char **argv) { printf("User accepted: %s\n", msgbuf.sender); send(msg_queue_id, &response); break; - case Message: + } + case Message: { printf("Recieved message, checking which client\n"); // Find the client that sent the message then forward it to all the // specified recipients - client = NULL; + Client *client = NULL; for (int i = 0; i < client_count; i++) { if (strncmp(clients[i].id, msgbuf.sender, COMMAND_LENGTH) == 0) { client = &clients[i]; @@ -208,7 +209,7 @@ int main(int argc, char **argv) { if (target_type == 'u') { Client *target_client = NULL; for (int i = 0; i < client_count; i++) { - if (strncmp(clients[i].id, target_id, COMMAND_LENGTH) == 0) { + if (strncmp(clients[i].nickname, target_id, COMMAND_LENGTH) == 0) { target_client = &clients[i]; break; } @@ -267,8 +268,8 @@ int main(int argc, char **argv) { continue; } - printf("Forwarding message to user %s: %s\n", target_client->id, - msgbuf.message); + printf("Forwarding message from user %s to %s\n", client->nickname, + target_client->nickname); msgbuf_t forward_msg = { .mtype = Message, .sender = "", @@ -296,7 +297,9 @@ int main(int argc, char **argv) { } // TODO: Accepted and Delivered ack break; - case Logout: + } + case Logout: { + } case Hearbeat: for (int i = 0; i < client_count; i++) { if (strncmp(clients[i].id, msgbuf.sender, COMMAND_LENGTH) == 0 && @@ -318,8 +321,55 @@ int main(int argc, char **argv) { } } break; - case List_clients: + case List_clients: { + Client *client = NULL; + for (int i = 0; i < client_count; i++) { + if (strncmp(clients[i].id, msgbuf.sender, COMMAND_LENGTH) == 0) { + client = &clients[i]; + break; + } + } + + // TODO: Rethink if we even want to respond in such case + if (client == NULL || !client->logged_in) { + msgbuf_t response = { + .mtype = Message, + .stype = ERR_NOT_LOGGED_IN, + }; + send(read_status, &response); + continue; + } + + // Parse the command parameter + // Just check if the user wants the active clients + // Not worth checking if the other option is valid + bool active_only = false; + if (strncmp(msgbuf.command, "active", COMMAND_LENGTH) == 0) { + active_only = true; + } + char list_buffer[MESSAGE_LENGTH] = ""; + + for (int i = 0; i < client_count; i++) { + if (active_only && !clients[i].logged_in) + continue; + + // Even a tiny bit of formatting, we fancy like that + char line[COMMAND_LENGTH + 4]; + snprintf(line, COMMAND_LENGTH + 4, "- %s\n", clients[i].nickname); + strncat(list_buffer, line, MESSAGE_LENGTH - strlen(list_buffer) - 1); + } + + msgbuf_t response = { + .mtype = List_clients, + .command = "", + }; + + strncpy(response.command, active_only ? "active" : "all", COMMAND_LENGTH); + strncpy(response.message, list_buffer, MESSAGE_LENGTH); + send(client->queue_id, &response); break; + } + case Mute: case Unmute: break;