You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

292 lines
7.6 KiB
C

2 years ago
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>
#include <unistd.h>
#include <signal.h>
#include "message.h"
#include "user.h"
#include "easysock.h"
#include "file_helpers.h"
#include "message_helpers.h"
#include "stack.h"
#define BUFFER_SIZE 10000
#define MAX_CONNECTIONS 100
#define DATA_SIZE 50000
#define MESSAGE_SIZE 50000
2 years ago
User** create_user_list(char* filename);
void sigint_handler(int dummy);
User* fetch_user(char* username);
int user_to_index(User* user);
bool user_equals(User* this, User* other);
User** users;
int num_users;
bool stop_running;
2 years ago
int main() {
stop_running = false;
signal(SIGINT,sigint_handler);
struct sockaddr temp_addr;
socklen_t temp_addrlen;
2 years ago
fd_set read_fd_set;
int conn_sockets[MAX_CONNECTIONS] = {-1};
User* to_user[MAX_CONNECTIONS] = {NULL};
User* from_user[MAX_CONNECTIONS] = {NULL};
FD_ZERO(&read_fd_set); char buffer[BUFFER_SIZE];
char data[DATA_SIZE];
num_users = num_of_lines("user_file.txt");
users = create_user_list("user_file.txt");
Stack* message_stack[num_users];
for (int i=0;i < num_users; i++) {
message_stack[i] = new_stack(10);
}
struct sockaddr addr_struct;
int server_sock = create_local(4,'T',"127.0.0.1",30000,&addr_struct);
conn_sockets[0] = server_sock;
assert(listen(server_sock,MAX_CONNECTIONS) == 0);
while (true) {
FD_ZERO(&read_fd_set);
for (int i=0; i < MAX_CONNECTIONS; i++) {
if (conn_sockets[i] > 0) {
FD_SET(conn_sockets[i],&read_fd_set);
}
}
int num_conns = select(FD_SETSIZE, &read_fd_set, NULL, NULL, NULL);
if (num_conns > 0) {
if (FD_ISSET(conn_sockets[0],&read_fd_set)) {
int client_sock = accept(conn_sockets[0],&temp_addr,&temp_addrlen);
for (int i=0;i < MAX_CONNECTIONS; i++) {
if (conn_sockets[i] <= 0) {
conn_sockets[i] = client_sock;
break;
}
}
}
for (int i=1; i < MAX_CONNECTIONS; i++) {
memset(data,0x00,DATA_SIZE);
if (FD_ISSET(conn_sockets[i],&read_fd_set)) {
while ( strstr(buffer,"END_OF_DATA") == NULL ) {
int num_bytes_read = recv(conn_sockets[i],buffer,sizeof(buffer),0);
if (num_bytes_read <= 0) {
close(conn_sockets[i]);
conn_sockets[i] = 0;
to_user[i] = NULL;
goto continue_for_loop;
}
strcat(data, buffer);
}
strcat(data,"\0");
buffer[0] = '\0'; /* Clear the buffer */
char* send_or_receive = malloc(10);
int k=0;
while (*(data + k) != '\n') {
k++;
}
memcpy(send_or_receive,data,k);
if (strstr(send_or_receive, "SENDING") != NULL) {
if (from_user[i] == NULL) {
from_user[i] = fetch_user(fetch_from_string(data,"IAM"));
if (from_user[i] == NULL) {
printf("Please identify yourself.\n");
close(conn_sockets[i]);
continue;
} else {
printf("You are %s\n",from_user[i]->username);
}
}
if (to_user[i] == NULL) {
to_user[i] = fetch_user(fetch_from_string(data,"TO"));
if (to_user[i] == NULL) {
printf("Invalid user or message format.\n");
close(conn_sockets[i]);
continue;
} else {
printf("Message intended for %s\n",to_user[i]->username);
}
}
char* message_string = malloc(sizeof(char) * MESSAGE_SIZE);
memset(message_string, 0x00, MESSAGE_SIZE);
message_string = fetch_message_string(data);
if (message_string == NULL) {
printf("Invalid message.\n");
return -10;
}
printf("Your message is: \n------------------\n%s\n------------------\n",message_string);
if (user_to_index(to_user[i]) < 0) {
printf("Recipient user does not exist!\n");
return -20;
}
Message* message = new_message(message_string,from_user[i],to_user[i]);
stack_push( message_stack[user_to_index(to_user[i])],message );
printf("Message has been pushed onto stack for %s\n",to_user[i]->username);
} else if (strstr(send_or_receive, "RECEIVING") != NULL) {
if (from_user[i] == NULL) {
from_user[i] = fetch_user(fetch_from_string(data,"IAM"));
if (from_user[i] == NULL) {
printf("Please identify yourself.\n");
close(conn_sockets[i]);
continue;
} else {
printf("You are %s\n",from_user[i]->username);
}
}
int num_of_messages;
char* num_of_messages_string = fetch_from_string(data,"GETLAST");
if (num_of_messages_string == NULL) {
printf("Invalid GET request.\n");
return -30;
} else {
if (strstr(num_of_messages_string,"ALL") != NULL) {
num_of_messages = stack_size(message_stack[user_to_index(from_user[i])]);
} else {
num_of_messages = atoi(num_of_messages_string);
}
}
if (num_of_messages > stack_size(message_stack[user_to_index(from_user[i])])) {
num_of_messages = stack_size(message_stack[user_to_index(from_user[i])]);
}
for (int k=0;k<num_of_messages;k++) {
Message* message = stack_pop(message_stack[user_to_index(from_user[i])]);
printf("You have a message from %s"
", sent at %s"
": \"%s\"\n",
message->sender->username,
asctime(message->timeinfo),
message->text);
}
} else {
printf("You are not sending or receiving.\n");
}
close(conn_sockets[i]);
conn_sockets[i] = -1;
continue_for_loop:
memset(data,0,DATA_SIZE);
memset(buffer,0,BUFFER_SIZE);
to_user[i] = NULL;
from_user[i] = NULL;
}
}
if (stop_running == true) {
printf("Stopping...\n");
for (int i=MAX_CONNECTIONS-1; i>= 0; i--) {
close(i);
close(conn_sockets[i]);
}
return 130;
}
}
}
}
2 years ago
User** create_user_list(char* filename) {
/* Structure of user file - <username> <password> on every line */
int num_users = num_of_lines(filename);
char* file_str = file_to_string(filename);
char* token = malloc(sizeof(char) * 30);
User** users = malloc (num_users * sizeof(User*));
for (int i=0;i<num_users;i++) {
(*(users+i)) = malloc(sizeof(User));
}
token = strtok(file_str," \r\n");
for (int i=0;i<num_users;i++) {
2 years ago
(*(users + i))->username = strdup(token);
token = strtok(NULL," \r\n");
2 years ago
(*(users + i))->password = strdup(token);
token = strtok(NULL," \r\n");
}
return users;
}
void sigint_handler(int dummy) {
stop_running = true;
printf("sigint_handler is stopping...\n");
exit(130);
}
User* fetch_user(char* username) {
if (username == NULL) {
return NULL;
}
for (int i=0;i<num_users;i++) {
if (strcmp(users[i]->username, username) == 0) {
return users[i];
}
}
return NULL;
}
int user_to_index(User* user) {
int index = -1;
for (int i=0;i < num_users; i++) {
if (user_equals(users[i],user) == true) {
index = i;
break;
}
}
return index;
}
bool user_equals(User* this, User* other) {
if (( strcmp(this->username,other->username) == 0 ) && ( strcmp(this->password,other->password) == 0 )) {
return true;
} else {
return false;
}
}