Added muting and unmuting
This commit is contained in:
@@ -143,7 +143,31 @@ static void input_loop(int server_queue_id, const char *client_id) {
|
||||
perror("msgsnd(/leave) failed");
|
||||
}
|
||||
} 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) {
|
||||
return;
|
||||
} 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");
|
||||
cleanup_queue(client_queue_id);
|
||||
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");
|
||||
cleanup_queue(client_queue_id);
|
||||
return 1;
|
||||
@@ -222,7 +246,6 @@ int main(int argc, char *argv[]) {
|
||||
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);
|
||||
@@ -296,7 +319,7 @@ int main(int argc, char *argv[]) {
|
||||
printf("Message sent successfully.\n");
|
||||
} else if (incoming.stype == ACK_DELIVERED) {
|
||||
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");
|
||||
} else {
|
||||
// Display whatever if I forgot to handle something
|
||||
@@ -306,7 +329,7 @@ int main(int argc, char *argv[]) {
|
||||
case JoinGroup:
|
||||
if (incoming.stype == ACK_ACCEPTED) {
|
||||
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");
|
||||
} else if (incoming.stype == ERR_ALREADY_IN_GROUP) {
|
||||
printf("You are already in this group.\n");
|
||||
@@ -317,12 +340,32 @@ int main(int argc, char *argv[]) {
|
||||
case LeaveGroup:
|
||||
if (incoming.stype == ACK_ACCEPTED) {
|
||||
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");
|
||||
} else {
|
||||
printf("Failed to leave group: Unknown error (code %d).\n", incoming.stype);
|
||||
}
|
||||
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:
|
||||
printf("Received unknown command of mtype=%ld stype=%d\n", (long)incoming.mtype, incoming.stype);
|
||||
break;
|
||||
|
||||
+2
-2
@@ -25,8 +25,8 @@ typedef enum {
|
||||
ERR_NOT_LOGGED_IN,
|
||||
ERR_ALREADY_LOGGED_IN,
|
||||
ERR_ALREADY_IN_GROUP,
|
||||
ERR_USER_NOT_FOUND,
|
||||
ERR_USER_MUTED,
|
||||
ERR_NOT_FOUND,
|
||||
ERR_ALREADY_MUTED,
|
||||
ERR_INVALID_FORMAT
|
||||
} Signal_t;
|
||||
|
||||
|
||||
@@ -26,7 +26,10 @@ typedef struct {
|
||||
typedef struct {
|
||||
char id[COMMAND_LENGTH];
|
||||
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
|
||||
// like # (reserved for groups)
|
||||
int queue_id;
|
||||
@@ -88,7 +91,10 @@ int main(int argc, char **argv) {
|
||||
for (int i = 0; i < client_count; i++) {
|
||||
strncpy(clients[i].id, config.clients[i].client_id, COMMAND_LENGTH - 1);
|
||||
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);
|
||||
clients[i].queue_id = -1;
|
||||
clients[i].last_seen = 0;
|
||||
@@ -168,7 +174,7 @@ int main(int argc, char **argv) {
|
||||
printf("User not found: %s\n", msgbuf.sender);
|
||||
msgbuf_t response = {
|
||||
.mtype = Login,
|
||||
.stype = ERR_USER_NOT_FOUND,
|
||||
.stype = ERR_NOT_FOUND,
|
||||
};
|
||||
|
||||
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);
|
||||
msgbuf_t response = {
|
||||
.mtype = Message,
|
||||
.stype = ERR_USER_NOT_FOUND,
|
||||
.stype = ERR_NOT_FOUND,
|
||||
};
|
||||
send(client->queue_id, &response);
|
||||
free(recipients);
|
||||
@@ -272,9 +278,27 @@ int main(int argc, char **argv) {
|
||||
// Forward the message to all group members except the sender
|
||||
int recipient_idx = 0;
|
||||
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) {
|
||||
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];
|
||||
}
|
||||
|
||||
@@ -285,12 +309,21 @@ int main(int argc, char **argv) {
|
||||
|
||||
// Check if we found any recipients
|
||||
if (recipients[0] == NULL) {
|
||||
printf("Target user %s not found\n", msgbuf.command);
|
||||
msgbuf_t response = {
|
||||
.mtype = Signal,
|
||||
.stype = ERR_USER_NOT_FOUND,
|
||||
};
|
||||
send(client->queue_id, &response);
|
||||
if (target_type == '#') {
|
||||
printf("Group message sent but no recipients received it (all muted or group empty)\n");
|
||||
msgbuf_t response = {
|
||||
.mtype = Signal,
|
||||
.stype = ACK_ACCEPTED,
|
||||
};
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
@@ -302,8 +335,21 @@ int main(int argc, char **argv) {
|
||||
if (target_client == NULL)
|
||||
break;
|
||||
|
||||
// Check if the target is online or not, if they are not, store the
|
||||
// message
|
||||
// Check if target_client has muted the sender
|
||||
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) {
|
||||
saved_message_t *saved_msg = NULL;
|
||||
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);
|
||||
msgbuf_t response = {
|
||||
.mtype = JoinGroup,
|
||||
.stype = ERR_USER_NOT_FOUND,
|
||||
.stype = ERR_NOT_FOUND,
|
||||
};
|
||||
send(client->queue_id, &response);
|
||||
continue;
|
||||
@@ -582,7 +628,7 @@ int main(int argc, char **argv) {
|
||||
if (!added) {
|
||||
msgbuf_t response = {
|
||||
.mtype = JoinGroup,
|
||||
.stype = ERR_USER_NOT_FOUND, // Reusing errors, why not
|
||||
.stype = ERR_NOT_FOUND, // Reusing errors, why not
|
||||
};
|
||||
send(client->queue_id, &response);
|
||||
}
|
||||
@@ -616,7 +662,7 @@ int main(int argc, char **argv) {
|
||||
printf("Target group %s not found\n", msgbuf.command);
|
||||
msgbuf_t response = {
|
||||
.mtype = LeaveGroup,
|
||||
.stype = ERR_USER_NOT_FOUND,
|
||||
.stype = ERR_NOT_FOUND,
|
||||
};
|
||||
send(client->queue_id, &response);
|
||||
continue;
|
||||
@@ -641,16 +687,182 @@ int main(int argc, char **argv) {
|
||||
if (!was_in_group) {
|
||||
msgbuf_t response = {
|
||||
.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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
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:
|
||||
// Signals are sent from server to client, not the other way around
|
||||
// so we ignore them here lol
|
||||
|
||||
Reference in New Issue
Block a user