From a5867c49d10d0c315381c3a45c210eba20f1b476 Mon Sep 17 00:00:00 2001 From: Dane MacFadden Date: Thu, 28 Aug 2025 12:04:57 -0600 Subject: [PATCH] removed global variables and passed them to threads as arguments instead --- main.c | 273 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 153 insertions(+), 120 deletions(-) diff --git a/main.c b/main.c index 7de4201..5d45352 100644 --- a/main.c +++ b/main.c @@ -21,67 +21,46 @@ #include #include #include -#include #include - -/* threading stuff */ -LIST *receivelist, *sendlist; -pthread_t input_thread, send_thread, receive_thread, output_thread; -pthread_mutex_t sendmut, receivemut, sendcvmut, receivecvmut, rendermut; -pthread_cond_t sendcv, receivecv; -char closed[] = "Connection closed."; - -/* networking stuff */ -int confd, sockfd; -char s[INET6_ADDRSTRLEN]; - -/* notcurses stuff */ -struct notcurses *nc; -struct ncplane *chatlog, *prompt, *stdn; -unsigned int rows, cols; +#include "context.h" /* Accept input from the user and add it to the send list */ -void *input() { +void *input(void *arg) { char *msg; struct ncinput ni; uint32_t character; int i; - + CONTEXT *context = (CONTEXT *)arg; + while (1) { /* Get a message from the user */ msg = malloc(512); memset(msg, 0, 512); i = 0; - ncplane_printf_yx(prompt, 0, 0, "Type a message: "); + ncplane_printf_yx(context->plane_prompt, 0, 0, "Type a message: "); - pthread_mutex_lock(&rendermut); - notcurses_render(nc); - pthread_mutex_unlock(&rendermut); + pthread_mutex_lock(&context->mut_render); + notcurses_render(context->ctx_nc); + pthread_mutex_unlock(&context->mut_render); /* Loop to get input */ while (1) { - character = notcurses_get(nc, NULL, &ni); + character = notcurses_get(context->ctx_nc, NULL, &ni); if (character == NCKEY_ENTER) { /* Add to sendlist when user presses enter */ - pthread_mutex_lock(&sendmut); - ListAppend(sendlist, msg); - pthread_mutex_unlock(&sendmut); + pthread_mutex_lock(&context->mut_send); + ListAppend(context->ctx_sendlist, msg); + pthread_mutex_unlock(&context->mut_send); - ncplane_erase_region(prompt, 0, 16, 1, cols); + ncplane_erase_region(context->plane_prompt, 0, 16, 1, + context->ctx_cols); - pthread_mutex_lock(&rendermut); - notcurses_render(nc); - pthread_mutex_unlock(&rendermut); + pthread_mutex_lock(&context->mut_render); + notcurses_render(context->ctx_nc); + pthread_mutex_unlock(&context->mut_render); break; } - /* Unsure why this doesn't create a scrolling effect */ - else if (character == NCKEY_SCROLL_UP) { - ncplane_scrollup(chatlog, -1); - } - else if (character == NCKEY_SCROLL_DOWN) { - ncplane_scrollup(chatlog, 1); - } else if (character == NCKEY_BACKSPACE && i > 0) { i--; msg[i] = '\0'; @@ -92,137 +71,145 @@ void *input() { } /* Print the message as the user types it */ - ncplane_erase_region(prompt, 0, 0, 1, cols); - ncplane_printf_yx(prompt, 0, 0, "Type a message: %s", msg); + ncplane_erase_region(context->plane_prompt, 0, 0, 1, context->ctx_cols); + ncplane_printf_yx(context->plane_prompt, 0, 0, "Type a message: %s", msg); - pthread_mutex_lock(&rendermut); - notcurses_render(nc); - pthread_mutex_unlock(&rendermut); + pthread_mutex_lock(&context->mut_render); + notcurses_render(context->ctx_nc); + pthread_mutex_unlock(&context->mut_render); } /* Wake up thread if it was waiting to have a msg to send */ - if (ListCount(sendlist) == 1) { - pthread_cond_signal(&sendcv); + if (ListCount(context->ctx_sendlist) == 1) { + pthread_cond_signal(&context->cv_send); } } return 0; } /* Take an item off the send list and send it to the other user */ -void *sender() { +void *sender(void *arg) { char *msg, *header; int bytes; - + CONTEXT *context = (CONTEXT *)arg; + while (1) { /* Check if the list has any content to send * If not, wait for some to arrive */ - if (ListCount(sendlist) == 0) { - pthread_mutex_lock(&sendcvmut); - pthread_cond_wait(&sendcv, &sendcvmut); - pthread_mutex_unlock(&sendcvmut); + if (ListCount(context->ctx_sendlist) == 0) { + pthread_mutex_lock(&context->mut_sendcv); + pthread_cond_wait(&context->cv_send, &context->mut_sendcv); + pthread_mutex_unlock(&context->mut_sendcv); } + msg = malloc(512); header = malloc(519); memset(msg, 0, 512); memset(header, 0, 519); + /* Obtain mutex, get and then remove message * from the list, unlock mutex, * send message. */ - pthread_mutex_unlock(&sendmut); - ListFirst(sendlist); - strcpy(msg, (char*)ListCurr(sendlist)); - ListRemove(sendlist); - pthread_mutex_unlock(&sendmut); + pthread_mutex_unlock(&context->mut_send); + ListFirst(context->ctx_sendlist); + strcpy(msg, (char*)ListCurr(context->ctx_sendlist)); + ListRemove(context->ctx_sendlist); + pthread_mutex_unlock(&context->mut_send); - bytes = send(confd, msg, 512, 0); + bytes = send(context->ctx_confd, msg, 512, 0); + + /* Stop execution if the user closes the connection */ + if ((strncmp(msg, "/c", 2)) == 0 || bytes == -1) { + pthread_cancel(*context->thread_in); + pthread_cancel(*context->thread_out); + pthread_cancel(*context->thread_recv); + pthread_exit(&context->ctx_closed); + } /* Append message to header and add to print list */ strcpy(header, "You: "); strncat(header, msg, strlen(msg)); - pthread_mutex_lock(&receivemut); - ListAppend(receivelist, header); - pthread_mutex_unlock(&receivemut); + + pthread_mutex_lock(&context->mut_recv); + ListAppend(context->ctx_recvlist, header); + pthread_mutex_unlock(&context->mut_recv); /* Wake thread waiting for message to print */ - if (ListCount(receivelist) == 1) { - pthread_cond_signal(&receivecv); - } - - /* Stop execution if the user closes the connection */ - if ((strncmp(msg, "/c", 2)) == 0 || bytes == -1) { - pthread_cancel(receive_thread); - pthread_cancel(input_thread); - pthread_cancel(output_thread); - pthread_exit(&closed); + if (ListCount(context->ctx_recvlist) == 1) { + pthread_cond_signal(&context->cv_recv); } } return 0; } /* Receive messages, add to print queue */ -void *receiver() { - char *buf, *header; +void *receiver(void *arg) { + char *msg, *header; int bytes; - + CONTEXT *context = (CONTEXT *)arg; + while (1) { - buf = malloc(512); - header = malloc(strlen(s) + 514); - memset(buf, 0, 512); - memset(header, 0, strlen(s) + 514); - strcpy(header, s); - strncat(header, ": ", 3); + msg = malloc(512); + header = malloc(strlen(context->ip) + 514); + memset(msg, 0, 512); + memset(header, 0, strlen(context->ip) + 514); - bytes = recv(confd, buf, 512, 0); - strncat(header, buf, strlen(buf)); + bytes = recv(context->ctx_confd, msg, 512, 0); /* Stop execution if the user closes the connection */ - if ((strncmp(buf, "/c", 2)) == 0) { - pthread_cancel(send_thread); - pthread_cancel(input_thread); - pthread_cancel(output_thread); - pthread_exit(&closed); + if ((strncmp(msg, "/c", 2)) == 0) { + pthread_cancel(*context->thread_send); + pthread_cancel(*context->thread_in); + pthread_cancel(*context->thread_out); + pthread_exit(&context->ctx_closed); } + strncpy(header, context->ip, strlen(context->ip)); + strcat(header, ": "); + strncat(header, msg, strlen(msg)); + /* Add message to list for other thread to print */ if (bytes != -1) { - pthread_mutex_lock(&receivemut); - ListAppend(receivelist, header); - pthread_mutex_unlock(&receivemut); + pthread_mutex_lock(&context->mut_recv); + ListAppend(context->ctx_recvlist, header); + pthread_mutex_unlock(&context->mut_recv); } /* Signal output thread, if it was waiting for something to print */ - if (ListCount(receivelist) == 1) { - pthread_cond_signal(&receivecv); + if (ListCount(context->ctx_recvlist) == 1) { + pthread_cond_signal(&context->cv_recv); } } return 0; } /* Remove a msg from the receivelist and display it */ -void *output() { +void *output(void *arg) { char *msg; + CONTEXT *context = (CONTEXT *)arg; + while (1) { - msg = malloc(512 + strlen(s)); + msg = malloc(512 + strlen(context->ip)); /* Block if there's nothing to output */ - if (ListCount(receivelist) == 0) { - pthread_mutex_lock(&receivecvmut); - pthread_cond_wait(&receivecv, &receivecvmut); - pthread_mutex_unlock(&receivecvmut); + if (ListCount(context->ctx_recvlist) == 0) { + pthread_mutex_lock(&context->mut_recvcv); + pthread_cond_wait(&context->cv_recv, &context->mut_recvcv); + pthread_mutex_unlock(&context->mut_recvcv); } /* Remove a message from the list and print it to chatlog */ - pthread_mutex_lock(&receivemut); - ListFirst(receivelist); - strcpy(msg, (char*)ListCurr(receivelist)); - ListRemove(receivelist); - pthread_mutex_unlock(&receivemut); + pthread_mutex_lock(&context->mut_recv); + ListFirst(context->ctx_recvlist); + strcpy(msg, (char*)ListCurr(context->ctx_recvlist)); + ListRemove(context->ctx_recvlist); + pthread_mutex_unlock(&context->mut_recv); - ncplane_printf(chatlog, "%s\n", msg); + ncplane_printf(context->plane_log, "%s\n", msg); - pthread_mutex_lock(&rendermut); - notcurses_render(nc); - pthread_mutex_unlock(&rendermut); + pthread_mutex_lock(&context->mut_render); + notcurses_render(context->ctx_nc); + pthread_mutex_unlock(&context->mut_render); } return 0; } @@ -236,6 +223,9 @@ void *get_in_addr(struct sockaddr *sa) { } int main(int argc, char* argv[]) { + /* networking stuff */ + int confd, sockfd; + char s[INET6_ADDRSTRLEN]; char *remote_machine, *local_port, *remote_port; socklen_t sin_size; struct addrinfo *p, *q; @@ -244,11 +234,24 @@ int main(int argc, char* argv[]) { struct sockaddr_storage their_addr; int status; int yes = 1; - + + /* threading stuff */ + LIST *receivelist, *sendlist; + pthread_t input_thread, send_thread, receive_thread, output_thread; + pthread_mutex_t sendmut, receivemut, sendcvmut, receivecvmut, rendermut; + pthread_cond_t sendcv, receivecv; + char closed[] = "Connection closed."; + + /* notcurses stuff */ + struct notcurses *nc; + struct ncplane *chatlog, *prompt, *stdn; + unsigned int rows, cols; + + struct notcurses_options opts = { .flags = NCOPTION_SUPPRESS_BANNERS }; - struct ncplane_options nopts = { + struct ncplane_options clopts = { .y = 0, .x = 0, .rows = 0, @@ -352,7 +355,7 @@ int main(int argc, char* argv[]) { if (connect(confd, q->ai_addr, q->ai_addrlen) == -1) { perror("Client: connect"); - close(sockfd); + close(confd); continue; } break; @@ -411,29 +414,59 @@ int main(int argc, char* argv[]) { } notcurses_stddim_yx(nc, &rows, &cols); - nopts.rows = rows; - nopts.cols = cols; + clopts.rows = rows; + clopts.cols = cols; popts.cols = cols; popts.y = rows - 1; notcurses_cursor_disable(nc); - if ((chatlog = ncplane_create(stdn, &nopts)) == NULL) { + if ((chatlog = ncplane_create(stdn, &clopts)) == NULL) { return -1; } if ((prompt = ncplane_create(stdn, &popts)) == NULL) { return -1; } ncplane_set_scrolling(chatlog, true); - pthread_create(&input_thread, NULL, input, NULL); - pthread_create(&send_thread, NULL, sender, NULL); - pthread_create(&output_thread, NULL, output, NULL); - pthread_create(&receive_thread, NULL, receiver, NULL); - pthread_join(send_thread, NULL); - pthread_join(receive_thread, NULL); + CONTEXT context = { + .ctx_recvlist = receivelist, + .ctx_sendlist = sendlist, + + .thread_in = &input_thread, + .thread_out = &output_thread, + .thread_recv = &receive_thread, + .thread_send = &send_thread, + + .mut_send = sendmut, + .mut_recv = receivemut, + .mut_sendcv = sendcvmut, + .mut_recvcv = receivecvmut, + .mut_render = rendermut, + + .cv_send = sendcv, + .cv_recv = receivecv, + + .ip = s, + .ctx_confd = confd, + + .ctx_nc = nc, + .plane_log = chatlog, + .plane_prompt = prompt, + .ctx_rows = rows, + .ctx_cols = cols, + .ctx_closed = closed, + }; + + pthread_create(&input_thread, NULL, input, &context); + pthread_create(&send_thread, NULL, sender, &context); + pthread_create(&output_thread, NULL, output, &context); + pthread_create(&receive_thread, NULL, receiver, &context); + pthread_join(input_thread, NULL); pthread_join(output_thread, NULL); - + pthread_join(send_thread, NULL); + pthread_join(receive_thread, NULL); + pthread_cond_destroy(&sendcv); pthread_cond_destroy(&receivecv); @@ -447,6 +480,6 @@ int main(int argc, char* argv[]) { ListFree(receivelist); ListFree(sendlist); notcurses_stop(nc); - printf("Connection closed.\n"); + printf("%s\n", closed); return 0; }