Compare commits
8 Commits
868aaccf28
...
master
Author | SHA1 | Date | |
---|---|---|---|
291a727dd3 | |||
a565c7ef29 | |||
fa1e8610f8 | |||
9c87de7196 | |||
34861b4644 | |||
a83338e8db | |||
5bc6c575fc | |||
c8c9a34aab |
14
README.md
Normal file
14
README.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
## Chat server
|
||||||
|
This is a simple, barely-working chat server (which uses a custom protocol). It is written in C, and relies on BSD sockets.
|
||||||
|
|
||||||
|
##Usage
|
||||||
|
To use it, compile the program with `make`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
- Finish README
|
||||||
|
- Implement password authentication
|
||||||
|
- Fix bugs with message string manipulation (the actual message isn't being stored correctly, and contains extra characters).
|
||||||
|
- Do additional testing to ensure that everything works correctly (it probably doesn't).
|
174
main.c
174
main.c
@@ -16,6 +16,7 @@
|
|||||||
#define BUFFER_SIZE 10000
|
#define BUFFER_SIZE 10000
|
||||||
#define MAX_CONNECTIONS 100
|
#define MAX_CONNECTIONS 100
|
||||||
#define DATA_SIZE 50000
|
#define DATA_SIZE 50000
|
||||||
|
#define MESSAGE_SIZE 50000
|
||||||
|
|
||||||
User** create_user_list(char* filename);
|
User** create_user_list(char* filename);
|
||||||
void sigint_handler(int dummy);
|
void sigint_handler(int dummy);
|
||||||
@@ -80,6 +81,9 @@ int main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i=1; i < MAX_CONNECTIONS; i++) {
|
for (int i=1; i < MAX_CONNECTIONS; i++) {
|
||||||
|
|
||||||
|
memset(data,0x00,DATA_SIZE);
|
||||||
|
|
||||||
if (FD_ISSET(conn_sockets[i],&read_fd_set)) {
|
if (FD_ISSET(conn_sockets[i],&read_fd_set)) {
|
||||||
|
|
||||||
while ( strstr(buffer,"END_OF_DATA") == NULL ) {
|
while ( strstr(buffer,"END_OF_DATA") == NULL ) {
|
||||||
@@ -93,78 +97,128 @@ int main() {
|
|||||||
strcat(data, buffer);
|
strcat(data, buffer);
|
||||||
}
|
}
|
||||||
strcat(data,"\0");
|
strcat(data,"\0");
|
||||||
if (from_user[i] == NULL) {
|
|
||||||
from_user[i] = fetch_user(fetch_from_string(data,"IAM"));
|
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) {
|
if (from_user[i] == NULL) {
|
||||||
printf("Please identify yourself.\n");
|
from_user[i] = fetch_user(fetch_from_string(data,"IAM"));
|
||||||
close(conn_sockets[i]);
|
if (from_user[i] == NULL) {
|
||||||
continue;
|
printf("Please identify yourself.\n");
|
||||||
} else {
|
close(conn_sockets[i]);
|
||||||
printf("You are %s\n",from_user[i]->username);
|
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) {
|
if (to_user[i] == NULL) {
|
||||||
printf("Invalid user or message format.\n");
|
to_user[i] = fetch_user(fetch_from_string(data,"TO"));
|
||||||
close(conn_sockets[i]);
|
if (to_user[i] == NULL) {
|
||||||
continue;
|
printf("Invalid user or message format.\n");
|
||||||
} else {
|
close(conn_sockets[i]);
|
||||||
printf("Message intended for %s\n",to_user[i]->username);
|
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;
|
||||||
|
|
||||||
char* message_string = fetch_message_string(data);
|
continue_for_loop:
|
||||||
if (message_string == NULL) {
|
memset(data,0,DATA_SIZE);
|
||||||
printf("Invalid message.\n");
|
memset(buffer,0,BUFFER_SIZE);
|
||||||
return -10;
|
to_user[i] = NULL;
|
||||||
}
|
from_user[i] = NULL;
|
||||||
|
|
||||||
printf("Your message is: %s\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);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
close(conn_sockets[i]);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
continue_for_loop:
|
|
||||||
data[0] = '\0'; /* This effectively clears the string, since the first element is null. */
|
|
||||||
to_user[i] = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (stop_running == true) {
|
if (stop_running == true) {
|
||||||
printf("Stopping...\n");
|
printf("Stopping...\n");
|
||||||
for (int i=MAX_CONNECTIONS-1; i>= 0; i--) {
|
for (int i=MAX_CONNECTIONS-1; i>= 0; i--) {
|
||||||
close(i);
|
close(i);
|
||||||
close(conn_sockets[i]);
|
close(conn_sockets[i]);
|
||||||
|
}
|
||||||
|
return 130;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return 130;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Message message = new_message("Hello, this is a text message",users[0],users[1]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// printf("Message was: %s\nSentfrom: %s\nSent to: %s\nWith password: %s\nSent at: %s\n",message.text, message.sender.username, message.recipient.username, message.recipient.password, asctime(&message.timeinfo));
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +250,9 @@ User** create_user_list(char* filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sigint_handler(int dummy) {
|
void sigint_handler(int dummy) {
|
||||||
stop_running = true;
|
stop_running = true;
|
||||||
|
printf("sigint_handler is stopping...\n");
|
||||||
|
exit(130);
|
||||||
}
|
}
|
||||||
|
|
||||||
User* fetch_user(char* username) {
|
User* fetch_user(char* username) {
|
||||||
|
@@ -22,10 +22,10 @@ Message* new_message(char* string, User* from, User* to) {
|
|||||||
// *(new_message->recipient) = *to;
|
// *(new_message->recipient) = *to;
|
||||||
|
|
||||||
time_t rawtime;
|
time_t rawtime;
|
||||||
struct tm timeinfo;
|
struct tm* timeinfo;
|
||||||
|
|
||||||
time(&rawtime);
|
time(&rawtime);
|
||||||
timeinfo = *localtime(&rawtime);
|
timeinfo = localtime(&rawtime);
|
||||||
|
|
||||||
new_message->timeinfo = timeinfo;
|
new_message->timeinfo = timeinfo;
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@ typedef struct Message_s Message;
|
|||||||
|
|
||||||
struct Message_s {
|
struct Message_s {
|
||||||
char* text;
|
char* text;
|
||||||
struct tm timeinfo;
|
struct tm* timeinfo;
|
||||||
User* sender;
|
User* sender;
|
||||||
User* recipient;
|
User* recipient;
|
||||||
};
|
};
|
||||||
|
@@ -25,39 +25,57 @@ char* fetch_from_string(char* message, char* indicator) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
char* fetch_message_string(char* message) {
|
char* fetch_message_string(char* message) {
|
||||||
int num_of_terminators;
|
|
||||||
|
|
||||||
char* start = strstr(message,"START_OF_MESSAGE");
|
char* message_copy = malloc(strlen(message));
|
||||||
|
strcpy(message_copy,message);
|
||||||
|
|
||||||
|
int num_of_terminators = 0;
|
||||||
|
int start_index = 0;
|
||||||
|
int end_index = 0;
|
||||||
|
int message_length = 0;
|
||||||
|
|
||||||
|
|
||||||
|
char* start = strstr(message_copy,"START_OF_MESSAGE");
|
||||||
if (start == NULL) {
|
if (start == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
int start_index = start - message;
|
start_index = start - message_copy;
|
||||||
start_index += strlen("START_OF_MESSAGE");
|
start_index += strlen("START_OF_MESSAGE");
|
||||||
|
|
||||||
while (*(message + start_index) == '\n' || *(message + start_index) == '\r') {
|
while (*(message_copy + start_index) == '\n' || *(message_copy + start_index) == '\r') {
|
||||||
start_index++;
|
start_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* end = strstr(message,"END_OF_MESSAGE");
|
char* end = strstr(message_copy,"END_OF_MESSAGE");
|
||||||
if (end == NULL) {
|
if (end == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
int end_index = end - message;
|
end_index = end - message_copy;
|
||||||
|
|
||||||
if (*(message+ end_index-2) = '\r') {
|
if (*(message_copy + end_index-2) == '\r') {
|
||||||
num_of_terminators = 2;
|
num_of_terminators = 2;
|
||||||
} else {
|
} else {
|
||||||
num_of_terminators = 1;
|
num_of_terminators = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int message_length = end_index - start_index;
|
end_index -= num_of_terminators;
|
||||||
char* message_string = malloc(message_length + 1);
|
|
||||||
|
|
||||||
for (int i=0;i < message_length-num_of_terminators; i++) { /* The reason the upper-bound is message_length-1 is because the last
|
message_length = end_index - start_index;
|
||||||
|
char* message_string = malloc(message_length + 2);
|
||||||
|
|
||||||
|
printf("Message goes from %d to %d\n",start_index,end_index);
|
||||||
|
|
||||||
|
for (int i=0; i<message_length; i++) { /* The reason the upper-bound is message_length-1 is because the last
|
||||||
character is a new-line, which the user would not have typed. */
|
character is a new-line, which the user would not have typed. */
|
||||||
*(message_string + i) = *(message + start_index + i);
|
|
||||||
|
*(message_string + i) = *(message_copy + start_index + i);
|
||||||
|
printf("%c",*(message_string + i));
|
||||||
}
|
}
|
||||||
|
|
||||||
*(message_string + (message_length - num_of_terminators)) = '\0';
|
strcat(message_string,"\0");
|
||||||
|
|
||||||
|
// printf("%s\n",message_string);
|
||||||
|
|
||||||
|
// *(message_string + (message_length - num_of_terminators)) = '\0';
|
||||||
return message_string;
|
return message_string;
|
||||||
}
|
}
|
||||||
|
2
stack.c
2
stack.c
@@ -35,7 +35,7 @@ void stack_push(Stack* stack,void* element) {
|
|||||||
|
|
||||||
void* stack_pop(Stack* stack) {
|
void* stack_pop(Stack* stack) {
|
||||||
assert( !(stack_isEmpty(stack)) );
|
assert( !(stack_isEmpty(stack)) );
|
||||||
free(stack->data + stack->top_index);
|
// free(stack->data + stack->top_index);
|
||||||
stack->top_index--;
|
stack->top_index--;
|
||||||
void* to_return = *(stack->data + stack->top_index);
|
void* to_return = *(stack->data + stack->top_index);
|
||||||
*(stack->data + stack->top_index) = NULL;
|
*(stack->data + stack->top_index) = NULL;
|
||||||
|
Reference in New Issue
Block a user