Added muting and unmuting

This commit is contained in:
2026-01-26 22:07:17 +01:00
parent bebc068762
commit 6ecbdfa9fa
3 changed files with 281 additions and 26 deletions
+49 -6
View File
@@ -143,7 +143,31 @@ static void input_loop(int server_queue_id, const char *client_id) {
perror("msgsnd(/leave) failed"); perror("msgsnd(/leave) failed");
} }
} else if (strncmp(buffer, "/mute ", 6) == 0) { } else if (strncmp(buffer, "/mute ", 6) == 0) {
// handle mute char *nickname = buffer + 6;
if (strlen(nickname) == 0) {
printf("Nickname cannot be empty\n");
continue;
}
msgbuf_t msg = {.mtype = Mute, .sender = ""};
strncpy(msg.sender, client_id, COMMAND_LENGTH - 1);
strncpy(msg.command, nickname, COMMAND_LENGTH - 1);
if (send(server_queue_id, &msg) == -1) {
perror("msgsnd(/mute) failed");
}
} else if (strncmp(buffer, "/unmute ", 8) == 0) {
char *nickname = buffer + 8;
if (strlen(nickname) == 0) {
printf("Nickname cannot be empty\n");
continue;
}
msgbuf_t msg = {.mtype = Unmute, .sender = ""};
strncpy(msg.sender, client_id, COMMAND_LENGTH - 1);
strncpy(msg.command, nickname, COMMAND_LENGTH - 1);
if (send(server_queue_id, &msg) == -1) {
perror("msgsnd(/unmute) failed");
}
} else if (strcmp(buffer, "/quit") == 0 || strcmp(buffer, "/exit") == 0 || strcmp(buffer, "/q") == 0) { } else if (strcmp(buffer, "/quit") == 0 || strcmp(buffer, "/exit") == 0 || strcmp(buffer, "/q") == 0) {
return; return;
} else if (strncmp(buffer, "/inbox", 8) == 0) { } else if (strncmp(buffer, "/inbox", 8) == 0) {
@@ -210,7 +234,7 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "Login failed: User already logged in\n"); fprintf(stderr, "Login failed: User already logged in\n");
cleanup_queue(client_queue_id); cleanup_queue(client_queue_id);
return 1; return 1;
} else if (resp.stype == ERR_USER_NOT_FOUND) { } else if (resp.stype == ERR_NOT_FOUND) {
fprintf(stderr, "Login failed: User not found\n"); fprintf(stderr, "Login failed: User not found\n");
cleanup_queue(client_queue_id); cleanup_queue(client_queue_id);
return 1; return 1;
@@ -222,7 +246,6 @@ int main(int argc, char *argv[]) {
client_queue_id_global = client_queue_id; client_queue_id_global = client_queue_id;
server_queue_id_global = server_queue_id; server_queue_id_global = server_queue_id;
heartbeat_pid = fork(); heartbeat_pid = fork();
if (heartbeat_pid == 0) { if (heartbeat_pid == 0) {
heartbeat_loop(server_queue_id, client_id); heartbeat_loop(server_queue_id, client_id);
@@ -296,7 +319,7 @@ int main(int argc, char *argv[]) {
printf("Message sent successfully.\n"); printf("Message sent successfully.\n");
} else if (incoming.stype == ACK_DELIVERED) { } else if (incoming.stype == ACK_DELIVERED) {
printf("Message delivered to %s.\n", incoming.sender); printf("Message delivered to %s.\n", incoming.sender);
} else if (incoming.stype == ERR_USER_NOT_FOUND) { } else if (incoming.stype == ERR_NOT_FOUND) {
printf("Your message could not be delivered: User not found.\n"); printf("Your message could not be delivered: User not found.\n");
} else { } else {
// Display whatever if I forgot to handle something // Display whatever if I forgot to handle something
@@ -306,7 +329,7 @@ int main(int argc, char *argv[]) {
case JoinGroup: case JoinGroup:
if (incoming.stype == ACK_ACCEPTED) { if (incoming.stype == ACK_ACCEPTED) {
printf("Successfully joined the group.\n"); printf("Successfully joined the group.\n");
} else if (incoming.stype == ERR_USER_NOT_FOUND) { } else if (incoming.stype == ERR_NOT_FOUND) {
printf("Group does not exist.\n"); printf("Group does not exist.\n");
} else if (incoming.stype == ERR_ALREADY_IN_GROUP) { } else if (incoming.stype == ERR_ALREADY_IN_GROUP) {
printf("You are already in this group.\n"); printf("You are already in this group.\n");
@@ -317,12 +340,32 @@ int main(int argc, char *argv[]) {
case LeaveGroup: case LeaveGroup:
if (incoming.stype == ACK_ACCEPTED) { if (incoming.stype == ACK_ACCEPTED) {
printf("Successfully left the group.\n"); printf("Successfully left the group.\n");
} else if (incoming.stype == ERR_USER_NOT_FOUND) { } else if (incoming.stype == ERR_NOT_FOUND) {
printf("Group does not exist.\n"); printf("Group does not exist.\n");
} else { } else {
printf("Failed to leave group: Unknown error (code %d).\n", incoming.stype); printf("Failed to leave group: Unknown error (code %d).\n", incoming.stype);
} }
break; break;
case Mute:
if (incoming.stype == ACK_ACCEPTED) {
printf("Successfully muted %s.\n", incoming.command);
} else if (incoming.stype == ERR_NOT_FOUND) {
printf("%s not found.\n", incoming.command);
} else if (incoming.stype == ERR_ALREADY_IN_GROUP) {
printf("%s is already muted.\n", incoming.command);
} else {
printf("Failed to mute: Unknown error (code %d).\n", incoming.stype);
}
break;
case Unmute:
if (incoming.stype == ACK_ACCEPTED) {
printf("Successfully unmuted %s.\n", incoming.command);
} else if (incoming.stype == ERR_NOT_FOUND) {
printf("%s wasn't muted.\n", incoming.command);
} else {
printf("Failed to unmute: Unknown error (code %d).\n", incoming.stype);
}
break;
default: default:
printf("Received unknown command of 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; break;
+2 -2
View File
@@ -25,8 +25,8 @@ typedef enum {
ERR_NOT_LOGGED_IN, ERR_NOT_LOGGED_IN,
ERR_ALREADY_LOGGED_IN, ERR_ALREADY_LOGGED_IN,
ERR_ALREADY_IN_GROUP, ERR_ALREADY_IN_GROUP,
ERR_USER_NOT_FOUND, ERR_NOT_FOUND,
ERR_USER_MUTED, ERR_ALREADY_MUTED,
ERR_INVALID_FORMAT ERR_INVALID_FORMAT
} Signal_t; } Signal_t;
+230 -18
View File
@@ -26,7 +26,10 @@ typedef struct {
typedef struct { typedef struct {
char id[COMMAND_LENGTH]; char id[COMMAND_LENGTH];
bool logged_in; bool logged_in;
char *muted_clients; char (*muted_clients)[COMMAND_LENGTH];
int muted_count;
char (*muted_groups)[COMMAND_LENGTH];
int muted_groups_count;
char nickname[COMMAND_LENGTH]; // Nicknames cannot contain special characters char nickname[COMMAND_LENGTH]; // Nicknames cannot contain special characters
// like # (reserved for groups) // like # (reserved for groups)
int queue_id; int queue_id;
@@ -88,7 +91,10 @@ int main(int argc, char **argv) {
for (int i = 0; i < client_count; i++) { for (int i = 0; i < client_count; i++) {
strncpy(clients[i].id, config.clients[i].client_id, COMMAND_LENGTH - 1); strncpy(clients[i].id, config.clients[i].client_id, COMMAND_LENGTH - 1);
clients[i].logged_in = false; clients[i].logged_in = false;
clients[i].muted_clients = NULL; clients[i].muted_clients = calloc(client_count, COMMAND_LENGTH);
clients[i].muted_count = 0;
clients[i].muted_groups = calloc(group_count, COMMAND_LENGTH);
clients[i].muted_groups_count = 0;
strncpy(clients[i].nickname, config.clients[i].nickname, COMMAND_LENGTH - 1); strncpy(clients[i].nickname, config.clients[i].nickname, COMMAND_LENGTH - 1);
clients[i].queue_id = -1; clients[i].queue_id = -1;
clients[i].last_seen = 0; clients[i].last_seen = 0;
@@ -168,7 +174,7 @@ int main(int argc, char **argv) {
printf("User not found: %s\n", msgbuf.sender); printf("User not found: %s\n", msgbuf.sender);
msgbuf_t response = { msgbuf_t response = {
.mtype = Login, .mtype = Login,
.stype = ERR_USER_NOT_FOUND, .stype = ERR_NOT_FOUND,
}; };
send(msg_queue_id, &response); send(msg_queue_id, &response);
@@ -262,7 +268,7 @@ int main(int argc, char **argv) {
printf("Target group %s not found\n", msgbuf.command + 1); printf("Target group %s not found\n", msgbuf.command + 1);
msgbuf_t response = { msgbuf_t response = {
.mtype = Message, .mtype = Message,
.stype = ERR_USER_NOT_FOUND, .stype = ERR_NOT_FOUND,
}; };
send(client->queue_id, &response); send(client->queue_id, &response);
free(recipients); free(recipients);
@@ -272,9 +278,27 @@ int main(int argc, char **argv) {
// Forward the message to all group members except the sender // Forward the message to all group members except the sender
int recipient_idx = 0; int recipient_idx = 0;
for (int i = 0; i < target_group->client_count; i++) { for (int i = 0; i < target_group->client_count; i++) {
if (target_group->members[i] == NULL)
continue;
if (strncmp(target_group->members[i]->id, client->id, COMMAND_LENGTH) == 0) { if (strncmp(target_group->members[i]->id, client->id, COMMAND_LENGTH) == 0) {
continue; continue;
} }
// Check if this member has muted the group
bool has_muted_group = false;
for (int j = 0; j < target_group->members[i]->muted_groups_count; j++) {
if (strcmp(target_group->members[i]->muted_groups[j], target_group->name) == 0) {
has_muted_group = true;
break;
}
}
if (has_muted_group) {
printf("Group message to %s blocked (group %s is muted)\n",
target_group->members[i]->nickname, target_group->name);
continue;
}
recipients[recipient_idx++] = target_group->members[i]; recipients[recipient_idx++] = target_group->members[i];
} }
@@ -285,12 +309,21 @@ int main(int argc, char **argv) {
// Check if we found any recipients // Check if we found any recipients
if (recipients[0] == NULL) { if (recipients[0] == NULL) {
printf("Target user %s not found\n", msgbuf.command); if (target_type == '#') {
msgbuf_t response = { printf("Group message sent but no recipients received it (all muted or group empty)\n");
.mtype = Signal, msgbuf_t response = {
.stype = ERR_USER_NOT_FOUND, .mtype = Signal,
}; .stype = ACK_ACCEPTED,
send(client->queue_id, &response); };
send(client->queue_id, &response);
} else {
printf("Target user %s not found\n", msgbuf.command);
msgbuf_t response = {
.mtype = Signal,
.stype = ERR_NOT_FOUND,
};
send(client->queue_id, &response);
}
free(recipients); free(recipients);
continue; continue;
} }
@@ -302,8 +335,21 @@ int main(int argc, char **argv) {
if (target_client == NULL) if (target_client == NULL)
break; break;
// Check if the target is online or not, if they are not, store the // Check if target_client has muted the sender
// message bool is_muted = false;
for (int j = 0; j < target_client->muted_count; j++) {
if (strcmp(target_client->muted_clients[j], client->nickname) == 0) {
is_muted = true;
break;
}
}
if (is_muted) {
printf("Message from %s to %s blocked (muted)\n", client->nickname, target_client->nickname);
continue; // Skip this recipient, discard the message
}
// Check if the target is online or not, if they are not, store the message
if (!target_client->logged_in) { if (!target_client->logged_in) {
saved_message_t *saved_msg = NULL; saved_message_t *saved_msg = NULL;
if (target_client->saved_message_count >= 20) { if (target_client->saved_message_count >= 20) {
@@ -534,7 +580,7 @@ int main(int argc, char **argv) {
printf("Target group %s not found\n", msgbuf.command); printf("Target group %s not found\n", msgbuf.command);
msgbuf_t response = { msgbuf_t response = {
.mtype = JoinGroup, .mtype = JoinGroup,
.stype = ERR_USER_NOT_FOUND, .stype = ERR_NOT_FOUND,
}; };
send(client->queue_id, &response); send(client->queue_id, &response);
continue; continue;
@@ -582,7 +628,7 @@ int main(int argc, char **argv) {
if (!added) { if (!added) {
msgbuf_t response = { msgbuf_t response = {
.mtype = JoinGroup, .mtype = JoinGroup,
.stype = ERR_USER_NOT_FOUND, // Reusing errors, why not .stype = ERR_NOT_FOUND, // Reusing errors, why not
}; };
send(client->queue_id, &response); send(client->queue_id, &response);
} }
@@ -616,7 +662,7 @@ int main(int argc, char **argv) {
printf("Target group %s not found\n", msgbuf.command); printf("Target group %s not found\n", msgbuf.command);
msgbuf_t response = { msgbuf_t response = {
.mtype = LeaveGroup, .mtype = LeaveGroup,
.stype = ERR_USER_NOT_FOUND, .stype = ERR_NOT_FOUND,
}; };
send(client->queue_id, &response); send(client->queue_id, &response);
continue; continue;
@@ -641,16 +687,182 @@ int main(int argc, char **argv) {
if (!was_in_group) { if (!was_in_group) {
msgbuf_t response = { msgbuf_t response = {
.mtype = LeaveGroup, .mtype = LeaveGroup,
.stype = ERR_USER_NOT_FOUND, // Could add ERR_NOT_IN_GROUP error code .stype = ERR_NOT_FOUND, // Could add ERR_NOT_IN_GROUP error code
}; };
send(client->queue_id, &response); send(client->queue_id, &response);
} }
break; break;
} }
case Mute: case Mute: {
Client_t *client = NULL;
for (int i = 0; i < client_count; i++) {
if (strncmp(clients[i].id, msgbuf.sender, COMMAND_LENGTH) == 0) {
client = &clients[i];
break;
}
}
case Unmute: if (client == NULL || !client->logged_in)
continue;
// Check if muting a group (starts with #) or a user
if (msgbuf.command[0] == '#') {
// Muting a group
char *group_name = msgbuf.command + 1; // Skip the #
// Find the group
Group_t *target_group = NULL;
for (int i = 0; i < group_count; i++) {
if (strcmp(groups[i].name, group_name) == 0) {
target_group = &groups[i];
break;
}
}
if (target_group == NULL) {
msgbuf_t response = {.mtype = Mute, .stype = ERR_NOT_FOUND};
strncpy(response.command, msgbuf.command, COMMAND_LENGTH);
send(client->queue_id, &response);
continue;
}
// Check if already muted
bool already_muted = false;
for (int i = 0; i < client->muted_groups_count; i++) {
if (strcmp(client->muted_groups[i], group_name) == 0) {
already_muted = true;
break;
}
}
if (already_muted) {
msgbuf_t response = {.mtype = Mute, .stype = ERR_ALREADY_IN_GROUP};
strncpy(response.command, msgbuf.command, COMMAND_LENGTH);
send(client->queue_id, &response);
continue;
}
// Add to muted groups list
if (client->muted_groups_count < group_count) {
strncpy(client->muted_groups[client->muted_groups_count], group_name, COMMAND_LENGTH - 1);
client->muted_groups_count++;
msgbuf_t response = {.mtype = Mute, .stype = ACK_ACCEPTED};
strncpy(response.command, msgbuf.command, COMMAND_LENGTH);
send(client->queue_id, &response);
printf("Client %s muted group %s\n", client->id, group_name);
}
} else {
// Muting a user
Client_t *target = NULL;
for (int i = 0; i < client_count; i++) {
if (strcmp(clients[i].nickname, msgbuf.command) == 0) {
target = &clients[i];
break;
}
}
if (target == NULL) {
msgbuf_t response = {.mtype = Mute, .stype = ERR_NOT_FOUND};
send(client->queue_id, &response);
continue;
}
// Check if already muted
bool already_muted = false;
for (int i = 0; i < client->muted_count; i++) {
if (strcmp(client->muted_clients[i], target->nickname) == 0) {
already_muted = true;
break;
}
}
if (already_muted) {
msgbuf_t response = {.mtype = Mute, .stype = ERR_ALREADY_IN_GROUP};
send(client->queue_id, &response);
continue;
}
// Add to muted list
if (client->muted_count < client_count) {
strncpy(client->muted_clients[client->muted_count], target->nickname, COMMAND_LENGTH - 1);
client->muted_count++;
msgbuf_t response = {.mtype = Mute, .stype = ACK_ACCEPTED};
strncpy(response.command, msgbuf.command, COMMAND_LENGTH);
send(client->queue_id, &response);
printf("Client %s muted %s\n", client->id, target->nickname);
}
}
break; break;
}
case Unmute: {
Client_t *client = NULL;
for (int i = 0; i < client_count; i++) {
if (strncmp(clients[i].id, msgbuf.sender, COMMAND_LENGTH) == 0) {
client = &clients[i];
break;
}
}
if (client == NULL || !client->logged_in)
continue;
// Check if unmuting a group (starts with #) or a user
if (msgbuf.command[0] == '#') {
char *group_name = msgbuf.command + 1;
int muted_index = -1;
for (int i = 0; i < client->muted_groups_count; i++) {
if (strcmp(client->muted_groups[i], group_name) == 0) {
muted_index = i;
break;
}
}
if (muted_index == -1) {
msgbuf_t response = {.mtype = Unmute, .stype = ERR_NOT_FOUND};
strncpy(response.command, msgbuf.command, COMMAND_LENGTH);
send(client->queue_id, &response);
continue;
}
// Remove from muted groups list by shifting remaining elements
for (int i = muted_index; i < client->muted_groups_count - 1; i++) {
strncpy(client->muted_groups[i], client->muted_groups[i + 1], COMMAND_LENGTH);
}
client->muted_groups_count--;
msgbuf_t response = {.mtype = Unmute, .stype = ACK_ACCEPTED, .command = ""};
strncpy(response.command, msgbuf.command, COMMAND_LENGTH);
send(client->queue_id, &response);
printf("Client %s unmuted group %s\n", client->id, group_name);
} else {
int muted_index = -1;
for (int i = 0; i < client->muted_count; i++) {
if (strcmp(client->muted_clients[i], msgbuf.command) == 0) {
muted_index = i;
break;
}
}
if (muted_index == -1) {
msgbuf_t response = {.mtype = Unmute, .stype = ERR_NOT_FOUND};
strncpy(response.command, msgbuf.command, COMMAND_LENGTH);
send(client->queue_id, &response);
continue;
}
// Remove from muted list by shifting remaining elements
for (int i = muted_index; i < client->muted_count - 1; i++) {
strncpy(client->muted_clients[i], client->muted_clients[i + 1], COMMAND_LENGTH);
}
client->muted_count--;
msgbuf_t response = {.mtype = Unmute, .stype = ACK_ACCEPTED};
strncpy(response.command, msgbuf.command, COMMAND_LENGTH);
send(client->queue_id, &response);
printf("Client %s unmuted %s\n", client->id, msgbuf.command);
}
break;
}
case Signal: case Signal:
// Signals are sent from server to client, not the other way around // Signals are sent from server to client, not the other way around
// so we ignore them here lol // so we ignore them here lol