Many config-loading memory fixes and group join/leave
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
#include "bits/types/struct_timeval.h"
|
||||
#include "sys/ipc.h"
|
||||
#include "sys/shm.h"
|
||||
#include <fcntl.h>
|
||||
@@ -98,8 +97,9 @@ int main(int argc, char **argv) {
|
||||
|
||||
for (int i = 0; i < group_count; i++) {
|
||||
strncpy(groups[i].name, config.groups[i].name, COMMAND_LENGTH - 2);
|
||||
groups[i].client_count = config.groups[i].member_count;
|
||||
groups[i].members = malloc(sizeof(Client_t *) * config.groups[i].member_count);
|
||||
// Allocate space for all clients to be able to join, not just initial members
|
||||
groups[i].client_count = client_count;
|
||||
groups[i].members = calloc(client_count, sizeof(Client_t *));
|
||||
for (int j = 0; j < config.groups[i].member_count; j++) {
|
||||
// Find the client with the given id
|
||||
for (int k = 0; k < client_count; k++) {
|
||||
@@ -236,12 +236,14 @@ int main(int argc, char **argv) {
|
||||
// Now we have to decode if we are to forward this message to a user or a
|
||||
// group. A group is indicated by a # at the start of the command
|
||||
char target_type = msgbuf.command[0];
|
||||
Client_t **recipients = malloc(sizeof(Client_t *) * client_count - 1); // We won't send to ourselves so one less
|
||||
Client_t **recipients = malloc(sizeof(Client_t *) * (client_count - 1)); // We won't send to ourselves so one less
|
||||
|
||||
if (target_type != '#') {
|
||||
recipients[0] = NULL; // Initialize to NULL in case no match is found
|
||||
for (int i = 0; i < client_count; i++) {
|
||||
if (strncmp(clients[i].nickname, msgbuf.command, COMMAND_LENGTH) == 0) {
|
||||
recipients[0] = &clients[i];
|
||||
recipients[1] = NULL; // Mark end of list
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -263,6 +265,7 @@ int main(int argc, char **argv) {
|
||||
.stype = ERR_USER_NOT_FOUND,
|
||||
};
|
||||
send(client->queue_id, &response);
|
||||
free(recipients);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -280,6 +283,18 @@ 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);
|
||||
free(recipients);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Now forward the message to all recipients
|
||||
for (int i = 0; i < client_count - 1; i++) {
|
||||
Client_t *target_client = recipients[i];
|
||||
@@ -329,6 +344,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
printf("Forwarding message: %s\n", msgbuf.message);
|
||||
}
|
||||
free(recipients);
|
||||
break;
|
||||
}
|
||||
case Logout: {
|
||||
@@ -381,7 +397,7 @@ int main(int argc, char **argv) {
|
||||
for (int i = 0; i < group_count; i++) {
|
||||
bool isMember = false;
|
||||
for (int j = 0; j < groups[i].client_count; j++) {
|
||||
if (strncmp(groups[i].members[j]->id, client->id, COMMAND_LENGTH) == 0) {
|
||||
if (groups[i].members[j] != NULL && strncmp(groups[i].members[j]->id, client->id, COMMAND_LENGTH) == 0) {
|
||||
isMember = true;
|
||||
break;
|
||||
}
|
||||
@@ -487,7 +503,152 @@ int main(int argc, char **argv) {
|
||||
client->saved_message_count = 0;
|
||||
break;
|
||||
}
|
||||
// Command field contains the group name
|
||||
case JoinGroup: {
|
||||
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;
|
||||
|
||||
printf("Request to join for group: %s\n", msgbuf.command);
|
||||
|
||||
Group_t *target_group = NULL;
|
||||
for (int i = 0; i < group_count; i++) {
|
||||
printf("Comparing group[%d].name='%s' (len=%zu) with command='%s' (len=%zu)\n", i, groups[i].name,
|
||||
strlen(groups[i].name), msgbuf.command, strlen(msgbuf.command));
|
||||
if (strcmp(groups[i].name, msgbuf.command) == 0) {
|
||||
target_group = &groups[i];
|
||||
printf("Group match found!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Target group not found
|
||||
if (target_group == NULL) {
|
||||
printf("Target group %s not found\n", msgbuf.command);
|
||||
msgbuf_t response = {
|
||||
.mtype = JoinGroup,
|
||||
.stype = ERR_USER_NOT_FOUND,
|
||||
};
|
||||
send(client->queue_id, &response);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if user is already in the group
|
||||
bool is_in_group = false;
|
||||
printf("Group '%s' has %d member slots\n", target_group->name, target_group->client_count);
|
||||
for (int i = 0; i < target_group->client_count; i++) {
|
||||
if (target_group->members[i] != NULL) {
|
||||
printf(" Slot %d: %s\n", i, target_group->members[i]->id);
|
||||
if (strncmp(client->id, target_group->members[i]->id, COMMAND_LENGTH) == 0) {
|
||||
is_in_group = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
printf(" Slot %d: NULL\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_in_group) {
|
||||
msgbuf_t response = {.mtype = JoinGroup, .stype = ERR_ALREADY_IN_GROUP};
|
||||
send(client->queue_id, &response);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only after we know that the user isn't in the group, by going over the whole list, we can add them
|
||||
// We could do that in the loop above, if there was a guarantee of there not being gaps in the array
|
||||
// This should be a linked list... well it's too late now...
|
||||
bool added = false;
|
||||
for (int i = 0; i < target_group->client_count; i++) {
|
||||
if (target_group->members[i] == NULL) {
|
||||
target_group->members[i] = client;
|
||||
msgbuf_t response = {
|
||||
.mtype = JoinGroup,
|
||||
.stype = ACK_ACCEPTED,
|
||||
};
|
||||
send(client->queue_id, &response);
|
||||
printf("Client %s joined group %s\n", client->id, target_group->name);
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!added) {
|
||||
msgbuf_t response = {
|
||||
.mtype = JoinGroup,
|
||||
.stype = ERR_USER_NOT_FOUND, // Reusing errors, why not
|
||||
};
|
||||
send(client->queue_id, &response);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LeaveGroup: {
|
||||
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;
|
||||
|
||||
printf("Request to leave group: %s\n", msgbuf.command);
|
||||
|
||||
Group_t *target_group = NULL;
|
||||
for (int i = 0; i < group_count; i++) {
|
||||
printf("Comparing group[%d].name='%s' with command='%s'\n", i, groups[i].name, msgbuf.command);
|
||||
if (strcmp(groups[i].name, msgbuf.command) == 0) {
|
||||
target_group = &groups[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Target group not found
|
||||
if (target_group == NULL) {
|
||||
printf("Target group %s not found\n", msgbuf.command);
|
||||
msgbuf_t response = {
|
||||
.mtype = LeaveGroup,
|
||||
.stype = ERR_USER_NOT_FOUND,
|
||||
};
|
||||
send(client->queue_id, &response);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool was_in_group = false;
|
||||
for (int i = 0; i < target_group->client_count; i++) {
|
||||
if (target_group->members[i] != NULL &&
|
||||
strncmp(client->id, target_group->members[i]->id, COMMAND_LENGTH) == 0) {
|
||||
target_group->members[i] = NULL;
|
||||
msgbuf_t response = {
|
||||
.mtype = LeaveGroup,
|
||||
.stype = ACK_ACCEPTED,
|
||||
};
|
||||
send(client->queue_id, &response);
|
||||
printf("Client %s left group %s\n", client->id, target_group->name);
|
||||
was_in_group = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!was_in_group) {
|
||||
msgbuf_t response = {
|
||||
.mtype = LeaveGroup,
|
||||
.stype = ERR_USER_NOT_FOUND, // Could add ERR_NOT_IN_GROUP error code
|
||||
};
|
||||
send(client->queue_id, &response);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Mute:
|
||||
|
||||
case Unmute:
|
||||
break;
|
||||
case Signal:
|
||||
|
||||
Reference in New Issue
Block a user