#include #include #include #include #include #include #include #include #include #include #include #include "chat.h" void clear_rows(int s, int e) { /* preserve cursor location */ int x_bef; int y_bef; getyx(stdscr, y_bef, x_bef); for (int i = s; i < e; i++) { move(i, 0); clrtoeol(); } move(y_bef, x_bef); } int file_disp(std::string p, int lnstart, int lncount) { std::ifstream f(p); if (!f) return 1; int i = 0; int ln_no = 0; std::string ln; clear_rows(0, lncount + 1); /* clear chat window */ while (getline(f, ln) && i <= ln_no + lnstart + 1) { if (i >= lnstart) { move(ln_no, 0); printw("%s", ln.c_str()); ln_no++; } i++; } move(CURSOR_DEFAULT_POSITION_Y, CURSOR_DEFAULT_POSITION_X); refresh(); return 0; } int count_lines(std::string p) { int c = 0; std::ifstream f(p); if (!f) return c; /* Apparently this is the most efficient way to count all lines in a file. How revolting! */ c = std::count(std::istreambuf_iterator(f), std::istreambuf_iterator(), '\n'); return c; } void * await_client(void *a) { wclient_args_t *args = static_cast(a); socket_descriptor_client = accept(socket_descriptor_server, (sockaddr *)&args->new_addr, &args->new_addr_siz); if (socket_descriptor_client >= 0) { log_append(log_path, "client connected"); if (count_lines(log_path) > LOG_LENGTH) line_position++; file_disp(log_path, line_position, LOG_LENGTH); } delete args; return client_poll(); } void * client_poll(void) { char msg[1024]; for (;;) { /* listen for msg from client */ memset(&msg, 0, sizeof(msg)); /* clear buf */ bytes_read += recv(socket_descriptor_client, (char *)&msg, sizeof(msg), 0); log_append(log_path, msg); if (count_lines(log_path) > LOG_LENGTH) line_position++; file_disp(log_path, line_position, LOG_LENGTH); } return nullptr; } void server_start(int port) { auto *a = new wclient_args_t{}; sockaddr_in srv_addr; sockaddr_in newsock; socklen_t newsock_siz = sizeof(newsock); int bstat; int rc; /* set up socket and connection tools */ bzero((char *)&srv_addr, sizeof(srv_addr)); srv_addr.sin_family = AF_INET; srv_addr.sin_addr.s_addr = htonl(INADDR_ANY); srv_addr.sin_port = htons(port); /* open stream-oriented socket w inet addr and track sock descriptor */ socket_descriptor_server = socket(AF_INET, SOCK_STREAM, 0); if (socket_descriptor_server < 0) goto panic_if_no_server_sock; /* bind sock to its local addr */ bstat = bind(socket_descriptor_server, (struct sockaddr *)&srv_addr, sizeof(srv_addr)); if (bstat < 0) goto panic_if_no_server_sock; log_append(log_path, "Waiting for a client to connect..."); /* listen for up to 5 simultaneous requests */ listen(socket_descriptor_server, 5); a->new_addr = newsock; a->new_addr_siz = newsock_siz; rc = pthread_create(&client_wait_thread, nullptr, await_client, a); pthread_detach(client_wait_thread); log_append(log_path, "Server started successfully."); gettimeofday(&time_start, NULL); return; panic_if_no_server_sock: endwin(); fprintf(stderr, "Fatal: Could not establish server socket!\n"); exit(1); } void server_stop(void) { long e = time_end.tv_sec - time_start.tv_sec; gettimeofday(&time_end, NULL); close(socket_descriptor_server); /* Don't just die silently */ puts("********Session********"); printf("Bytes written: %i\nBytes Read: %i\n", bytes_written, bytes_read); printf("Elapsed time: %ld\n secs\n", e); puts("Connection closed..."); } void client_stop(void) { long e = time_end.tv_sec - time_start.tv_sec; gettimeofday(&time_end, NULL); close(socket_descriptor_client); puts("********Session********"); printf("Bytes written: %i\nBytes read: %i\n", bytes_written, bytes_read); printf("Elapsed time: %ld\n secs\n", e); puts("Connection closed..."); } void * server_poll(void *args) { wclient_args_t *a = static_cast(args); int sock_desc = (int)a->aux; char msg[1024]; for (;;) { memset(&msg, 0, sizeof(msg)); bytes_read += recv(sock_desc, (char*)&msg, sizeof(msg), 0); log_append(log_path, msg); if (count_lines(log_path) > LOG_LENGTH) line_position++; file_disp(log_path, line_position, LOG_LENGTH); } }