#include #include #include #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 poll_client(); } void * poll_client(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 * poll_server(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); } } void client_start(void) { char msg[1024]; int bread; int bwrit; int rc; sockaddr_in send_addr; struct timeval time_start; struct timeval time_end; struct hostent *host = gethostbyname(listen_ip_address.c_str()); auto *a = new wclient_args_t{}; bzero((char *)&send_addr, sizeof(send_addr)); send_addr.sin_family = AF_INET; send_addr.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr *)*host->h_addr_list)); send_addr.sin_port = htons(listen_port); socket_descriptor_client = socket(AF_INET, SOCK_STREAM, 0); attempt_client_connection: int stat = connect(socket_descriptor_client, (sockaddr *)&send_addr, sizeof(send_addr)); if (stat < 0) { log_append(log_path, "Error connecting to socket, retrying..."); goto attempt_client_connection; } log_append(log_path, "Connected to the server!"); bread = bwrit = 0; gettimeofday(&time_start, NULL); a->aux = socket_descriptor_client; rc = pthread_create(&client_wait_thread, nullptr, poll_server, a); pthread_detach(client_wait_thread); } int log_append(std::string p, std::string ln) { std::ofstream f; f.open(p, std::ios_base::app); if (!f.is_open()) return 1; f << ln << std::endl; f.close(); // "this probably would help but theres too much broken stuff right now to be sure" - scott // bool inclnum should be added to function if we do decide to use this block: //if (inclnum) // line_position++; return 0; }