Untitled

Anonymous
plain_text
01/16/2026 7:54 AM
8.9 KB
11
Indexable
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <stdbool.h>

#define MAX_MSG 1024
#define MAX_ROOMS 20
#define MAX_USERS 100

typedef struct {
    char name[50];
    struct sockaddr_in users[MAX_USERS];
    int user_count;
} ChatRoom;

ChatRoom rooms[MAX_ROOMS];
int room_count = 0;

int sockfd;
int running = 1;

pthread_mutex_t lock;


/* UTILITY SERVER */

int find_room(const char* name) {
    for (int i = 0; i < room_count; i++)
        if (strcmp(rooms[i].name, name) == 0)
            return i;
    return -1;
}

void add_room(const char* name) {
    if (room_count >= MAX_ROOMS) return;
    strcpy(rooms[room_count].name, name);
    rooms[room_count].user_count = 0;
    room_count++;
}

int user_in_room(int room_id, struct sockaddr_in* user) {
    for (int i = 0; i < rooms[room_id].user_count; i++) {
        if (rooms[room_id].users[i].sin_addr.s_addr == user->sin_addr.s_addr &&
            rooms[room_id].users[i].sin_port == user->sin_port)
            return 1;
    }
    return 0;
}

void join_room(int room_id, struct sockaddr_in* user) {
    if (!user_in_room(room_id, user)) {
        rooms[room_id].users[rooms[room_id].user_count++] = *user;
    }
}

void leave_room(int room_id, struct sockaddr_in* user) {
    for (int i = 0; i < rooms[room_id].user_count; i++) {
        if (rooms[room_id].users[i].sin_addr.s_addr == user->sin_addr.s_addr &&
            rooms[room_id].users[i].sin_port == user->sin_port) {
            rooms[room_id].users[i] = rooms[room_id].users[rooms[room_id].user_count - 1];
            rooms[room_id].user_count--;
            return;
        }
    }
}

void broadcast(int room_id, const char* msg, struct sockaddr_in* exclude) {
    for (int i = 0; i < rooms[room_id].user_count; i++) {
        if (exclude &&
            rooms[room_id].users[i].sin_addr.s_addr == exclude->sin_addr.s_addr &&
            rooms[room_id].users[i].sin_port == exclude->sin_port)
            continue;

        sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr*)&rooms[room_id].users[i], sizeof(rooms[room_id].users[i]));
    }
}

/*  THREAD SERVER */

void* server_thread(void* arg) {
    char buffer[MAX_MSG];
    struct sockaddr_in sender;
    socklen_t sender_len = sizeof(sender);

    while (running) {
        int n = recvfrom(sockfd, buffer, MAX_MSG, 0, (struct sockaddr*)&sender, &sender_len);
        if (n <= 0) continue;

        buffer[n] = '\0';

        pthread_mutex_lock(&lock);

        if (strncmp(buffer, "/create ", 8) == 0) {
            char room[50];
            sscanf(buffer + 8, "%s", room);

            if (find_room(room) == -1) {
                add_room(room);
                char msg[100];
                sprintf(msg, "Stanza '%s' creata.\n", room);
                sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr*)&sender, sender_len);
            } else {
                sendto(sockfd, "Stanza già esistente.\n", 23, 0, (struct sockaddr*)&sender, sender_len);
            }
        }

        else if (strncmp(buffer, "/join ", 6) == 0) {
            char room[50];
            sscanf(buffer + 6, "%s", room);

            int id = find_room(room);
            if (id == -1) {
                sendto(sockfd, "Stanza inesistente.\n", 20, 0, (struct sockaddr*)&sender, sender_len);
            } else {
                join_room(id, &sender);

                char msg[100];
                sprintf(msg, ">> %s è entrato nella stanza.\n", inet_ntoa(sender.sin_addr));
                broadcast(id, msg, NULL);

                sendto(sockfd, "Entrato nella stanza.\n", 22, 0, (struct sockaddr*)&sender, sender_len);
            }
        }

        else if (strncmp(buffer, "/leave", 6) == 0) {
            for (int i = 0; i < room_count; i++) {
                if (user_in_room(i, &sender)) {
                    leave_room(i, &sender);
                    char msg[100];
                    sprintf(msg, "<< %s è uscito dalla stanza.\n", inet_ntoa(sender.sin_addr));
                    broadcast(i, msg, NULL);
                }
            }
        }

        else if (strncmp(buffer, "/msg ", 5) == 0) {
            char* text = buffer + 5;

            for (int i = 0; i < room_count; i++) {
                if (user_in_room(i, &sender)) {
                    char msg[200];
                    sprintf(msg, "[%s] %s\n", inet_ntoa(sender.sin_addr), text);
                    broadcast(i, msg, NULL);
                }
            }
        }

        else if (strcmp(buffer, "/quit") == 0) {
            running = 0;
        }

        pthread_mutex_unlock(&lock);
    }

    return NULL;
}

/* CLIENT RECEIVER */

void* client_receiver(void* arg) {
    char buffer[MAX_MSG];
    struct sockaddr_in sender;
    socklen_t sender_len = sizeof(sender);

    while (running) {
        int n = recvfrom(sockfd, buffer, MAX_MSG, 0, (struct sockaddr*)&sender, &sender_len);
        if (n > 0) {
            buffer[n] = '\0';
            printf("\n%s> ", buffer);
            fflush(stdout);
        }
    }
    return NULL;
}

/*  MAIN  */

int     main() {
    int scelta;
    char ip[50];
    int port;

    pthread_mutex_init(&lock, 0);
    do{
        printf("MENU\n");

        printf("1) SERVER\n");

        printf("2) CLIENT\n");

        scanf("%d", &scelta);
    } while (scelta == 0);

    sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    if (scelta == 1) {
        printf("inserire la porta da utilizzare: ");
        scanf("%d", &port);

        struct sockaddr_in server_addr;
        server_addr.sin_family = AF_INET;
        server_addr.sin_addr.s_addr = INADDR_ANY;
        server_addr.sin_port = htons(port);

        bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
        printf("Server avviato sulla porta %d\n", port);

        pthread_t t;
        pthread_create(&t, NULL, server_thread, NULL);

        pthread_join(t, NULL);
    }

    else { /* CLIENT */
        printf("inserire l'ip del server: ");
        scanf("%s", ip);
        printf("inserire la porta del server: ");
        scanf("%d", &port);

        struct sockaddr_in server_addr;
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(port);
        inet_pton(AF_INET, ip, &server_addr.sin_addr);

        pthread_t t;
        pthread_create(&t, NULL, client_receiver, NULL);

        char msg[MAX_MSG];
        getchar();

        while (running) {
            printf("> ");
            fgets(msg, MAX_MSG, stdin);
            msg[strcspn(msg, "\n")] = 0;

            sendto(sockfd, msg, strlen(msg), 0,(struct sockaddr*)&server_addr, sizeof(server_addr));

            if (strcmp(msg, "/quit") == 0) {
                running = 0;
            }
        }
    }

    close(sockfd);
    pthread_mutex_destroy(&lock);
    return 0;
}
Editor is loading...
Leave a Comment