Skip to content

Commit

Permalink
Initial solution
Browse files Browse the repository at this point in the history
  • Loading branch information
nick-botticelli committed May 3, 2023
1 parent 375eb74 commit f7ea7a4
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 14 deletions.
2 changes: 1 addition & 1 deletion chatnode.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
ip = 127.0.0.1
port = 51966
username = Person4
username = Person3
9 changes: 9 additions & 0 deletions src/chat_node.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>

#include "debug.h"
#include "main.h"
Expand Down Expand Up @@ -66,6 +67,10 @@ inline void addNode(Node **nodeList, Node *node) {
while (curNode->nextNode != NULL) {
// Move to next node
curNode = curNode->nextNode;

// If node is already in the node list, do nothing
if (curNode == node)
return;
}

debug("curNode: %p", curNode);
Expand Down Expand Up @@ -125,6 +130,10 @@ inline void removeNode(Node **nodeList, Node *node) {
printf("%s has left the chat room.\n", curNode->username);

// Clean up old node
curNode->connected = false;
free(curNode->ip);
free(curNode->username);
close(curNode->sock);
free(curNode);

printNodeList(*nodeList);
Expand Down
42 changes: 35 additions & 7 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,19 @@ void *send_handler(void *nodeListRaw) {

debug("Command result action: %d", cmdResult.action);

if (cmdResult.action == ACTION_LEAVE || cmdResult.action == ACTION_SHUTDOWN)
if (cmdResult.action == ACTION_LEAVE) {
// Disconnect from all other nodes
Node *curNode = nodeList->initialNode ? nodeList->nextNode->nextNode : nodeList->nextNode;
while (curNode != NULL) {
curNode->connected = false;
close(curNode->sock);
curNode = curNode->nextNode;
}
printNodeList(nodeList);
}
else if (cmdResult.action == ACTION_SHUTDOWN) {
break;
}
}
}

Expand All @@ -94,26 +105,43 @@ void *send_handler(void *nodeListRaw) {

void *receive_handler(void *recHandlerDataRaw) {
ReceiveHandlerData *recHandlerData = (ReceiveHandlerData *) recHandlerDataRaw;
Node *nodeList = recHandlerData->nodeList;
Node *node = recHandlerData->curNode;

printNodeList(recHandlerData->nodeList);

while (true) {
Message message;

if (!recHandlerData->curNode->connected) {
if (!node->connected) {
debug("Node %p is not connected anymore!", node);
// If no longer connected, remove the node and exit thread
debug("Removing node!");
removeNode(&recHandlerData->nodeList, recHandlerData->curNode);

// Don't remove head of node list
if (node != nodeList) {
// Don't remove 2nd node if self node is not an initial node
if (nodeList->initialNode || node != nodeList->nextNode) {
debug("Removing node %p!", node);
removeNode(&nodeList, node);
break;
}
}

// For the node describing the original node to connect to, re-initialize the node for rejoining
node->sock = socket(AF_INET, SOCK_STREAM, 0);

break;
}

if (receiveMessage(recHandlerData->nodeList, recHandlerData->curNode, &message)) {
if (!handleClient(recHandlerData->nodeList, recHandlerData->curNode, message))
break;
if (receiveMessage(nodeList, node, &message)) {
if (!handleClient(nodeList, node, message)) {
exit(EXIT_SUCCESS); // Quick and dirty
}
}
}

free(recHandlerData);
debug("Receive handler for node %p has shut down.", node);

return NULL;
}
Expand Down
2 changes: 2 additions & 0 deletions src/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@ inline Message deserializeMessage(Node *nodeList, uint8_t *rawMessage, size_t ra
message.note = malloc(strlen((char *) rawMessage + 1)) + 1;
strcpy(message.note, (char *) rawMessage + 1);
break;
case MSG_LEAVE:
break;
default:
debug("Unknown message type recieved!");
break;
Expand Down
2 changes: 2 additions & 0 deletions src/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
* 5: Flag 3
* 6: Flag 4
* 7: Flag 5
*
* For use with getBit and setBit, the order is flipped!
*/
typedef uint8_t MessageHeader;

Expand Down
21 changes: 16 additions & 5 deletions src/receiver_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,15 @@ inline bool handleClient(Node *nodeList, Node *node, Message message) {
break;
case MSG_LEAVE:
debug("Leave received!");
// removeNode(&nodeList, node); // TODO: Not needed?

if (getBit(message.header, 0)) {
printf("The chat room is shutting down. Goodbye.");
printf("The chat room is shutting down. Goodbye.\n");
return false;
}

// Disconnect from node (mark for removal); this prevents any more messages from being received
node->connected = false;

break;
}

Expand All @@ -85,18 +89,25 @@ inline bool receiveMessage(Node *nodeList, Node *node, Message *messageOut) {
ssize_t rawMessageSize = recv(node->sock, &rawMessage, sizeof(rawMessage), 0);

if (rawMessageSize == -1) {
if (errno == EBADF) {
goto SOCKET_CLOSED;
}

debug("Error reading message?");
return false;
}
else if (rawMessageSize == 0) {
debug("Socket closed for node %p (%s)!", node, node->username);
node->connected = false;
return false;
goto SOCKET_CLOSED;
}

debug("received message!");

// Create message from received data
*messageOut = deserializeMessage(nodeList, rawMessage, rawMessageSize);
return true;

SOCKET_CLOSED:
debug("Socket closed for node %p (%s)!", node, node->username);
node->connected = false;
return false;
}
3 changes: 2 additions & 1 deletion src/sender_handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ inline bool connectToNode(Node *nodeList, Node *node, bool newJoin, Message *joi
connectSocket(nodeList, node);

if (node->connected) {
addNode(&nodeList, node);
debug("connectToNode(): new join: %d", newJoin);
*joinMessageOut = createJoinMessage(nodeList->username, nodeList->port, newJoin);
return true;
Expand Down Expand Up @@ -114,7 +115,7 @@ inline bool handleCommand(Node *nodeList, char *input, CommandResult *cmdResultO
}
else {
if (connectToNode(nodeList, nodeList->nextNode, true, &cmdResultOut->message))
printf("You successfully joined %s's chat room.\n", nodeList->nextNode->username);
printf("You successfully the chat room.\n");
else
return false;
}
Expand Down

0 comments on commit f7ea7a4

Please sign in to comment.