TNT/src/chat_room.c

140 lines
3.5 KiB
C

#include "chat_room.h"
#include "config_defaults.h"
/* Global chat room instance */
chat_room_t *g_room = NULL;
static int room_capacity_from_env(void) {
return tnt_config_env_int(&TNT_CONFIG_MAX_CONNECTIONS);
}
/* Initialize chat room */
chat_room_t* room_create(void) {
chat_room_t *room = calloc(1, sizeof(chat_room_t));
if (!room) return NULL;
pthread_rwlock_init(&room->lock, NULL);
room->client_capacity = room_capacity_from_env();
room->clients = calloc(room->client_capacity, sizeof(struct client *));
if (!room->clients) {
free(room);
return NULL;
}
/* Load messages from file */
room->message_count = message_load(&room->messages, MAX_MESSAGES);
return room;
}
/* Destroy chat room */
void room_destroy(chat_room_t *room) {
if (!room) return;
pthread_rwlock_wrlock(&room->lock);
free(room->clients);
free(room->messages);
pthread_rwlock_unlock(&room->lock);
pthread_rwlock_destroy(&room->lock);
free(room);
}
/* Add client to room */
int room_add_client(chat_room_t *room, struct client *client) {
pthread_rwlock_wrlock(&room->lock);
if (room->client_count >= room->client_capacity) {
pthread_rwlock_unlock(&room->lock);
return -1;
}
room->clients[room->client_count++] = client;
pthread_rwlock_unlock(&room->lock);
return 0;
}
/* Remove client from room */
void room_remove_client(chat_room_t *room, struct client *client) {
pthread_rwlock_wrlock(&room->lock);
for (int i = 0; i < room->client_count; i++) {
if (room->clients[i] == client) {
/* Shift remaining clients */
for (int j = i; j < room->client_count - 1; j++) {
room->clients[j] = room->clients[j + 1];
}
room->client_count--;
break;
}
}
pthread_rwlock_unlock(&room->lock);
}
/* Add message to room history (caller must hold write lock) */
static void room_add_message(chat_room_t *room, const message_t *msg) {
if (room->message_count >= MAX_MESSAGES) {
memmove(&room->messages[0], &room->messages[1],
(MAX_MESSAGES - 1) * sizeof(message_t));
room->message_count = MAX_MESSAGES - 1;
}
room->messages[room->message_count++] = *msg;
}
/* Broadcast message to all clients */
void room_broadcast(chat_room_t *room, const message_t *msg) {
pthread_rwlock_wrlock(&room->lock);
room_add_message(room, msg);
room->update_seq++;
pthread_rwlock_unlock(&room->lock);
}
/* Get message by index (thread-safe value copy) */
bool room_get_message(chat_room_t *room, int index, message_t *out) {
if (!room || !out) return false;
pthread_rwlock_rdlock(&room->lock);
bool found = false;
if (index >= 0 && index < room->message_count) {
*out = room->messages[index];
found = true;
}
pthread_rwlock_unlock(&room->lock);
return found;
}
/* Get total message count */
int room_get_message_count(chat_room_t *room) {
pthread_rwlock_rdlock(&room->lock);
int count = room->message_count;
pthread_rwlock_unlock(&room->lock);
return count;
}
/* Get online client count */
int room_get_client_count(chat_room_t *room) {
pthread_rwlock_rdlock(&room->lock);
int count = room->client_count;
pthread_rwlock_unlock(&room->lock);
return count;
}
uint64_t room_get_update_seq(chat_room_t *room) {
uint64_t seq;
pthread_rwlock_rdlock(&room->lock);
seq = room->update_seq;
pthread_rwlock_unlock(&room->lock);
return seq;
}