#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //try to make the program work without this without doing anything awful but do it later #include "client.h" #include "disp.h" #include "log.h" #include "public.h" #include "server.h" using namespace std; int PORT_NUM = 8888; string IP_ADDRESS = "0.0.0.0"; const int DEFAULT_CUR_X = 2; // the x position of the preferred default cursor // position for message entry const int DEFAULT_CUR_Y = 12; // the x position of the preferred default cursor // position for message entry chatmode_t mode = NO_MODE; // what mode is this program in. 0 = nothing. 1 = server. 2 = client int serverSocketDescriptor; // a global variable for storing the server socket // descriptor. int clientSocketDescriptor; // This has not been used: // vector clientSocketDescriptors; // a global vector for storing client // socket descriptors // keep track of the session time using global variables struct timeval start1, end1; // also keep track of the amount of data sent as well int bytesRead, bytesWritten = 0; const int LOG_LENGTH = 10; // number of text log file lines to display int linePos = 0; // counter for what current position to use in the file string logFileName; // the name of the log file pthread_t client_wait_thread; struct waitClientArgs { sockaddr_in newSockAddr; socklen_t newSockAddrSize; int auxInt; // used in client mode because I didn't want to make another // struct to keep track of }; void usage(char *progname, bool *m); int main(int argc, char *argv[]) { /* * ch: getopt * exit: set to true when infinite loop is to end * userInput: character buffer for the user's next message * modeless: check whether a modeless exit was accidental */ int ch; bool exit = false; char *userInput = new char[1024]; bool modeless = false; if (argc == 1) { usage(argv[0], &modeless); goto leave; } while ((ch = getopt(argc, argv, "m:a:p:h")) != -1) switch (ch) { case 'm': if (!strncmp(optarg, "client", 6)) { logFileName = "client.txt"; mode = CLIENT_MODE; } else if (!strncmp(optarg, "server", 6)) { logFileName = "server.txt"; mode = SERVER_MODE; } else { usage(argv[0], &modeless); goto leave; } break; case 'a': IP_ADDRESS = optarg; break; case 'p': PORT_NUM = atoi(optarg); break; case 'h': default: usage(argv[0], &modeless); goto leave; break; } // putting this lower down to circumvent the terminal brick when the // socket was already in use results in all network functonality no // longer working. initscr(); // creates stdscr. important step use_default_colors(); // this apparently tells it to use default // terminal colors whenever there is no color // attribute applied // printw("Starting server..."); // you have to do this to make the scrolling still work correctly if // there was already content in the log file linePos = linesInFile(logFileName) - LOG_LENGTH + 1; switch (mode) { case CLIENT_MODE: writeToFile(logFileName, "CLIENT MODE"); setupClient(); linePos++; break; case SERVER_MODE: writeToFile(logFileName, "SERVER MODE"); setupServer(PORT_NUM); linePos++; break; default: goto leave; break; } while (!exit) { clear(); // Draw outer chat border box(stdscr, 0, 0); // Get screen size int height, width; getmaxyx(stdscr, height, width); // Draw separator line above input mvhline(height - 3, 1, 0, width - 2); // Labels mvprintw(0, 2, " Chat "); mvprintw(height - 3, 2, " Input "); // Display Chat Log displayFile(logFileName, linePos, LOG_LENGTH); // scroll along the screen if and when required so that it stays // in sync if (linesInFile(logFileName) > LOG_LENGTH) linePos++; // Input area move(height - 2, 2); clrtoeol(); printw("You: "); move(height - 2, 7); refresh(); getstr(userInput); writeToFile(logFileName, userInput); if (!strncmp(userInput, "/quit", 5)) exit = true; if (mode == 1) send(clientSocketDescriptor, (char *)userInput, strlen(userInput), 0); else send(clientSocketDescriptor, (char *)userInput, strlen(userInput), 0); } leave: endwin(); // closeServer(); switch (mode) { case SERVER_MODE: closeServer(); break; case CLIENT_MODE: closeServer(); break; default: if (!modeless) { puts("Warn: program appears to have successfully finished without ever " "setting mode."); return 1; } return 2; break; } return 0; } /* remember to call 'goto leave' after running */ void usage(char *progname, bool *m) // m:a:p:h { printf("\x1b[1mUsage:\x1b[0m\n" "\t%s client\t\x1b[3m# run as client\x1b[0m\n" "\t%s server\t\x1b[3m# run as server\x1b[0m\n" "\n\n" "\x1b[1mOptions:\x1b[0m\n" "\t\x1b[1m-m [client|server]\x1b[0m\tMode \x1b[1;31m(required)\x1b[0m\n" "\n" "\t\x1b[1m-a [255.255.255.255]\x1b[0m\tAddress\n" "\t\t\t\tserver mode: listen address \x1b[33m(default: 0.0.0.0)\x1b[0m\n" "\t\t\t\tclient mode: address of server \x1b[33m(default: 127.0.0.1)\x1b[0m\n" "\n" "\t\x1b[1m-p [0-65535]\x1b[0m\t\tPort number\n", progname, progname); *m = true; }