Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <signal.h>
- #include <sys/wait.h>
- #include <fcntl.h>
- #define MAX_MSG_SIZE 500
- #define MAX_NAME_SIZE 50
- #define FRIENDS_FILE "polz.txt"
- typedef struct {
- char name[MAX_NAME_SIZE];
- struct sockaddr_in addr;
- } Friend;
- Friend *friends = NULL;
- int num_friends = 0;
- int sock;
- char user_name[MAX_NAME_SIZE];
- void handle_sigint(int sig) {
- close(sock);
- if (friends) free(friends);
- exit(0);
- }
- void send_message(const char *msg, struct sockaddr_in *addr) {
- char buffer[MAX_MSG_SIZE];
- snprintf(buffer, MAX_MSG_SIZE, "%s%c%s%c", user_name, '\0', msg, '\0');
- sendto(sock, buffer, strlen(user_name) + 1 + strlen(msg) + 1, 0, (struct sockaddr *)addr, sizeof(*addr));
- }
- void add_friend(const char *name, struct sockaddr_in *addr) {
- for (int i = 0; i < num_friends; i++) {
- if (strcmp(friends[i].name, name) == 0 &&
- friends[i].addr.sin_addr.s_addr == addr->sin_addr.s_addr &&
- friends[i].addr.sin_port == addr->sin_port) {
- return; // Friend already exists
- }
- }
- friends = realloc(friends, (num_friends + 1) * sizeof(Friend));
- if (friends == NULL) {
- perror("Error reallocating memory");
- exit(1);
- }
- strcpy(friends[num_friends].name, name);
- friends[num_friends].addr = *addr;
- num_friends++;
- FILE *fp = fopen(FRIENDS_FILE, "a");
- if (fp != NULL) {
- fprintf(fp, "%s %s %d\n", name, inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
- fclose(fp);
- } else {
- perror("Error opening polz.txt");
- }
- }
- void load_friends() {
- FILE *fp = fopen(FRIENDS_FILE, "r");
- if (fp == NULL) {
- return; // No friends file, no friends to load
- }
- char name[MAX_NAME_SIZE];
- char ip[INET_ADDRSTRLEN];
- int port;
- while (fscanf(fp, "%s %s %d", name, ip, &port) == 3) {
- struct sockaddr_in addr;
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- inet_pton(AF_INET, ip, &addr.sin_addr);
- add_friend(name, &addr);
- }
- fclose(fp);
- }
- int is_friend(struct sockaddr_in *addr) {
- for (int i = 0; i < num_friends; i++) {
- if (friends[i].addr.sin_addr.s_addr == addr->sin_addr.s_addr &&
- friends[i].addr.sin_port == addr->sin_port) {
- return 1;
- }
- }
- return 0;
- }
- void receive_messages() {
- struct sockaddr_in src_addr;
- socklen_t addr_len = sizeof(src_addr);
- char buffer[MAX_MSG_SIZE];
- while (1) {
- int msg_len = recvfrom(sock, buffer, MAX_MSG_SIZE, 0, (struct sockaddr *)&src_addr, &addr_len);
- if (msg_len > 0) {
- buffer[msg_len] = '\0';
- char *name = buffer;
- char *msg = buffer + strlen(name) + 1;
- if (strcmp(msg, "#hi!") == 0) {
- send_message("#hello!", &src_addr);
- if (!is_friend(&src_addr)) {
- add_friend(name, &src_addr);
- }
- } else if (strcmp(msg, "#hello!") == 0) {
- if (!is_friend(&src_addr)) {
- add_friend(name, &src_addr);
- }
- } else {
- printf("%s: %s\n", name, msg);
- }
- }
- }
- }
- void send_to_all(const char *msg) {
- FILE *fp = fopen(FRIENDS_FILE, "r");
- if (fp == NULL) {
- perror("Error opening polz.txt");
- return;
- }
- char name[MAX_NAME_SIZE];
- char ip[INET_ADDRSTRLEN];
- int port;
- while (fscanf(fp, "%s %s %d", name, ip, &port) == 3) {
- if (strcmp(name, user_name) != 0) { // Don't send to self
- struct sockaddr_in addr;
- addr.sin_family = AF_INET;
- addr.sin_port = htons(port);
- inet_pton(AF_INET, ip, &addr.sin_addr);
- send_message(msg, &addr);
- }
- }
- fclose(fp);
- }
- void handle_command(const char *command) {
- if (strncmp(command, "@hi", 3) == 0) {
- char ip[INET_ADDRSTRLEN];
- int port;
- sscanf(command + 4, "%s %d", ip, &port);
- struct sockaddr_in new_friend;
- new_friend.sin_family = AF_INET;
- new_friend.sin_port = htons(port);
- inet_pton(AF_INET, ip, &new_friend.sin_addr);
- send_message("#hi!", &new_friend);
- } else if (strcmp(command, "@friends") == 0) {
- for (int i = 0; i < num_friends; i++) {
- if (strcmp(friends[i].name, user_name) != 0) {
- printf("%s %s %d\n", friends[i].name, inet_ntoa(friends[i].addr.sin_addr), ntohs(friends[i].addr.sin_port));
- }
- }
- } else if (strcmp(command, "@exit") == 0) {
- kill(0, SIGINT);
- }
- }
- int main(int argc, char *argv[]) {
- if (argc != 3) {
- fprintf(stderr, "Usage: %s <name> <port>\n", argv[0]);
- exit(1);
- }
- strcpy(user_name, argv[1]);
- int port = atoi(argv[2]);
- sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (sock == -1) {
- perror("Error creating socket");
- exit(1);
- }
- 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);
- if (bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
- perror("Error binding socket");
- exit(1);
- }
- signal(SIGINT, handle_sigint);
- if (fork() == 0) {
- receive_messages();
- exit(0);
- }
- load_friends();
- char input[MAX_MSG_SIZE];
- while (1) {
- fgets(input, sizeof(input), stdin);
- input[strcspn(input, "\n")] = '\0';
- if (input[0] == '@') {
- handle_command(input);
- } else {
- send_to_all(input);
- }
- }
- close(sock);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement