From 4131de177e36b19b20b8bbdb7bd43b18b6e22690 Mon Sep 17 00:00:00 2001 From: Joursoir Date: Wed, 9 Dec 2020 19:34:04 +0000 Subject: clui: architecture go to base class for clients; fix bugs --- src/client/ClientBase.cpp | 28 ++++++--- src/client/ClientBase.hpp | 8 ++- src/client/clui/Client.cpp | 65 +++++++++++++++++++ src/client/clui/Client.hpp | 55 ++++++++++++++++ src/client/clui/Makefile | 4 +- src/client/clui/client.cpp | 35 ----------- src/client/clui/clui.cpp | 28 ++++----- src/client/clui/clui.hpp | 8 +-- src/client/clui/main.cpp | 37 +++++++++++ src/client/clui/user.cpp | 153 --------------------------------------------- src/client/clui/user.hpp | 32 ---------- 11 files changed, 201 insertions(+), 252 deletions(-) create mode 100644 src/client/clui/Client.cpp create mode 100644 src/client/clui/Client.hpp delete mode 100644 src/client/clui/client.cpp create mode 100644 src/client/clui/main.cpp delete mode 100644 src/client/clui/user.cpp delete mode 100644 src/client/clui/user.hpp (limited to 'src/client') diff --git a/src/client/ClientBase.cpp b/src/client/ClientBase.cpp index fed4c32..aa54365 100644 --- a/src/client/ClientBase.cpp +++ b/src/client/ClientBase.cpp @@ -9,8 +9,8 @@ #include "ClientBase.hpp" -ClientBase::ClientBase(const char* ip, int port) : in_buf_used(0), - out_buf_used(0), exit_flag(false) +ClientBase::ClientBase(const char* ip, int port) + : out_buf_used(0), exit_flag(false), connection(true) { fd = CreateSocket(ip, port); } @@ -50,6 +50,8 @@ int ClientBase::CreateSocket(const char* ip, int port) int ClientBase::Run() { + if(exit_flag) + return 0; HandleActions(); int recive = read(fd, out_buffer+out_buf_used, @@ -62,9 +64,11 @@ int ClientBase::Run() else if(recive > 0) out_buf_used += recive; else { - strcpy(out_buffer, "Server closed the connection. Use ESC to exit."); - ShowMessage(out_buffer); - //room->AddMessage(out_buffer, system_msg); + if(connection) { + strcpy(out_buffer, "Server closed the connection. Use ESC to exit."); + AddMessage(out_buffer, system_msg); + connection = false; + } } if(out_buf_used > 0) { @@ -82,14 +86,22 @@ int ClientBase::Run() buf += 1; } - //room->AddMessage(buf, spec_msg); - ShowMessage(buf); + AddMessage(buf, spec_msg); memmove(out_buffer, out_buffer + i + 1, out_buf_used - i - 1); out_buf_used -= i + 1; break; } } } - return 1; +} + +void ClientBase::SendMessage(const char *msg) +{ + int len = strlen(msg) + 1; + char *buf = new char[len]; + strcpy(buf, msg); + buf[len-1] = '\n'; + + write(fd, buf, len * sizeof(char)); } \ No newline at end of file diff --git a/src/client/ClientBase.hpp b/src/client/ClientBase.hpp index 425929f..387505c 100644 --- a/src/client/ClientBase.hpp +++ b/src/client/ClientBase.hpp @@ -6,21 +6,23 @@ class ClientBase { protected: int fd; - char in_buffer[max_usermsg_len]; // for input - int in_buf_used; char out_buffer[max_msg_len]; // for message int out_buf_used; bool exit_flag; + bool connection; public: ClientBase(const char* ip, int port); virtual ~ClientBase(); int ConstuctorError() const { return fd > -1 ? 0 : 1; } int Run(); + void BreakLoop() { exit_flag = true; } + virtual void HandleActions() {} - virtual void ShowMessage(const char *msg) {} + virtual void AddMessage(const char *msg, int type) {} + void SendMessage(const char *msg); private: int CreateSocket(const char* ip, int port); }; diff --git a/src/client/clui/Client.cpp b/src/client/clui/Client.cpp new file mode 100644 index 0000000..36859ce --- /dev/null +++ b/src/client/clui/Client.cpp @@ -0,0 +1,65 @@ +#include + +#include "Client.hpp" +#include "clui.hpp" + +const int key_enter = 10; +const int key_escape = 27; +const int key_backspace = 127; + +void Client::HandleActions() +{ + int key = room->InputGetch(); + switch(key) + { + case key_escape: { + this->BreakLoop(); + break; + } + case ' '...'~': { // ascii table 32...126 + AddCharToBuffer(key); + room->AddCharToSendMsg(key); + break; + } + case '\n': { // send message + if(in_buf_used <= 0) + return; + SendMessage(in_buffer); + memset(in_buffer, 0, (in_buf_used+1)*sizeof(char)); + in_buf_used = 0; + + room->InputClear(); + room->SetInputCursor(1, 1); + break; + } + case key_backspace: { + RemoveCharFromBuffer(); + room->RemoveCharFromMsg(); + break; + } + default: break; + } +} + +void Client::AddMessage(const char *msg, int type) +{ + room->AddMessage(msg, type); +} + +void Client::AddCharToBuffer(char ch) +{ + if(in_buf_used >= max_usermsg_len-1) + return; + + in_buffer[in_buf_used] = ch; + in_buf_used++; +} + +void Client::RemoveCharFromBuffer() +{ + if(in_buf_used <= 0) + return; + + in_buffer[in_buf_used] = '\0'; + in_buf_used--; +} \ No newline at end of file diff --git a/src/client/clui/Client.hpp b/src/client/clui/Client.hpp new file mode 100644 index 0000000..37bc3e0 --- /dev/null +++ b/src/client/clui/Client.hpp @@ -0,0 +1,55 @@ +#ifndef WC_CLUI_CLIENT_H +#define WC_CLUI_CLIENT_H + +#include "../../const_vars.hpp" +#include "../ClientBase.hpp" + +class ChatRoom; + +class Client : public ClientBase { + char in_buffer[max_usermsg_len]; // for input + int in_buf_used; + + bool exit_flag; + + ChatRoom *room; +public: + Client(const char* ip, int port, ChatRoom *i_room) + : ClientBase(ip, port), in_buf_used(0), + exit_flag(false), room(i_room) {} + ~Client() {} + + virtual void HandleActions(); + virtual void AddMessage(const char *msg, int type); +private: + void AddCharToBuffer(char ch); + void RemoveCharFromBuffer(); +}; + + +/*class Client { + int fd; + char in_buffer[max_usermsg_len]; // for input + int in_buf_used; + + char out_buffer[max_msg_len]; // for message + int out_buf_used; + + bool exit_flag; + + Client(int i_fd) : fd(i_fd), in_buf_used(0), + out_buf_used(0), exit_flag(false) {} +public: + ~Client() { close(fd); } + + static Client *Start(const char* ip, int port); + void Run(ChatRoom *room); + void BreakLoop() { exit_flag = true; } + void HandleButton(ChatRoom *room); + + void AddCharToBuffer(char ch); + void RemoveCharFromBuffer(); + void SendMessage(); +};*/ + +#endif \ No newline at end of file diff --git a/src/client/clui/Makefile b/src/client/clui/Makefile index 071462b..b77c8f6 100644 --- a/src/client/clui/Makefile +++ b/src/client/clui/Makefile @@ -1,7 +1,7 @@ CPP = g++ CPPFLAGS = -Wall -g -lncurses -SOURCES = client.cpp clui.cpp user.cpp -OBJECTS = $(SOURCES:.cpp=.o) +SOURCES = main.cpp clui.cpp Client.cpp ../ClientBase.cpp +OBJECTS = main.o clui.o Client.o ClientBase.o EXECUTABLE = client .PHONY: all clean diff --git a/src/client/clui/client.cpp b/src/client/clui/client.cpp deleted file mode 100644 index 83f8ef0..0000000 --- a/src/client/clui/client.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include -#include -#include -#include - -#include "../config.hpp" -#include "user.hpp" - -int main(int argc, char *argv[]) -{ - initscr(); - noecho(); - - int rows, columns; - getmaxyx(stdscr, rows, columns); - if(rows != 24 || columns != 80) { - endwin(); - printf("Please use terminal with size 24x80\n"); - return 1; - } - - Client *user = Client::Start(SERVER_IP, SERVER_PORT); - if(!user) { - endwin(); - perror("server"); - return 1; - } - - ChatRoom *room = new ChatRoom(); - user->Run(room); - delete room; - - endwin(); - return 0; -} \ No newline at end of file diff --git a/src/client/clui/clui.cpp b/src/client/clui/clui.cpp index 78fd226..a7f908e 100644 --- a/src/client/clui/clui.cpp +++ b/src/client/clui/clui.cpp @@ -55,18 +55,19 @@ ChatRoom::~ChatRoom() if(input) delete input; - // #TODO: - /* if(first) ... delete message */ + while(first) { + message *tmp = first; + first = first->prev; + delete tmp; + } } -void ChatRoom::AddMessage(char *msg, int type) +void ChatRoom::AddMessage(const char *msg, int type) { message *recent_msg = new message; - int lines = 1; int len = strlen(msg); - if(len > CHAT_WIDTH-2 + CHAT_WIDTH-2) lines = 3; - else if(len > CHAT_WIDTH-2) lines = 2; + int lines = (len / oneline_len) + 1; strcpy(recent_msg->msg, msg); recent_msg->num_lines = lines; @@ -84,13 +85,13 @@ void ChatRoom::ChatRedraw() return; chat->Clear(false); - int available_lines = CHAT_HEIGHT - 2; + int available_lines = lines_in_chat; bool remove = false; message *tmp; message *last; for(message *m = first; m; m = m->prev) { - if(available_lines-1 >= m->num_lines) { + if(available_lines >= m->num_lines) { PrintMessage(available_lines, m); available_lines -= m->num_lines; last = m; @@ -119,25 +120,22 @@ void ChatRoom::PrintMessage(int line, message *m) { WINDOW *win = this->chat->GetWindow(); int need_print = m->num_lines; - int maxlen_oneline = CHAT_WIDTH-2; while(need_print != 0) { if(m->type == system_msg) wattron(win, A_ITALIC); else wattron(win, A_BOLD); - wmove(win, line-need_print+1, 1); - char *tmp = new char[maxlen_oneline]; - int str = maxlen_oneline * (m->num_lines - need_print); - memcpy(tmp, m->msg + str, maxlen_oneline); + char *tmp = new char[oneline_len]; + int str = oneline_len * (m->num_lines - need_print); + memcpy(tmp, m->msg + str, oneline_len); wprintw(win, tmp); - need_print--; - if(m->type == system_msg) wattroff(win, A_ITALIC); else wattroff(win, A_BOLD); delete[] tmp; + need_print--; } } diff --git a/src/client/clui/clui.hpp b/src/client/clui/clui.hpp index 0373f95..e337aa9 100644 --- a/src/client/clui/clui.hpp +++ b/src/client/clui/clui.hpp @@ -1,10 +1,10 @@ // CLUI - Command Line User Interface -#ifndef COMMANDLINEUI_H -#define COMMANDLINEUI_H +#ifndef WC_CLUI_H +#define WC_CLUI_H #include -#include "../const_vars.hpp" +#include "../../const_vars.hpp" class Interface_wc { WINDOW *w; @@ -41,7 +41,7 @@ public: ~ChatRoom(); // for chat: - void AddMessage(char *msg, int type); + void AddMessage(const char *msg, int type); // for players: //void AddPlayer() diff --git a/src/client/clui/main.cpp b/src/client/clui/main.cpp new file mode 100644 index 0000000..fd77708 --- /dev/null +++ b/src/client/clui/main.cpp @@ -0,0 +1,37 @@ +#include +#include +#include +#include + +#include "../../config.hpp" +#include "Client.hpp" +#include "clui.hpp" + +int main(int argc, char *argv[]) +{ + initscr(); + noecho(); + + int rows, columns; + getmaxyx(stdscr, rows, columns); + if(rows != 24 || columns != 80) { + endwin(); + printf("Please use terminal with size 24x80\n"); + return 1; + } + + ChatRoom *room = new ChatRoom(); + Client *user = new Client(SERVER_IP, SERVER_PORT, room); + if(user->ConstuctorError()) { + endwin(); + perror("server"); + return 1; + } + + while(user->Run()); + delete room; + delete user; + + endwin(); + return 0; +} \ No newline at end of file diff --git a/src/client/clui/user.cpp b/src/client/clui/user.cpp deleted file mode 100644 index d075751..0000000 --- a/src/client/clui/user.cpp +++ /dev/null @@ -1,153 +0,0 @@ -#include -#include -#include // for sockaddr_in -#include // for iten_aton -#include // for bind, connect -#include // for bind, connect -#include -#include -#include - -#include "user.hpp" - -const int key_enter = 10; -const int key_escape = 27; -const int key_backspace = 127; - -Client *Client::Start(const char* ip, int port) -{ - int client; - client = socket(AF_INET, SOCK_STREAM, 0); - if(client == -1) return 0; - - // remove "port sticking" aka socket in TIME_WAIT - int opt = 1; - setsockopt(client, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); - - /* call bind optional, the system chooses - the address automatically */ - - struct sockaddr_in server_adress; - server_adress.sin_family = AF_INET; - server_adress.sin_port = htons(port); - if(!inet_aton(ip, &(server_adress.sin_addr))) return 0; - - int res = connect(client, (struct sockaddr*) &server_adress, - sizeof(server_adress)); - if(res == -1) return 0; - - return new Client(client); -} - -void Client::Run(ChatRoom *room) -{ - unsigned int usecs = 0100000; - int flags = fcntl(fd, F_GETFL, 0); - fcntl(fd, F_SETFL, flags | O_NONBLOCK); - - int cls = false; - do { - this->HandleButton(room); - - int recive = read(fd, out_buffer+out_buf_used, - sizeof(out_buffer)-out_buf_used); - - if(recive < 0) { - if(errno != EINTR && errno != EAGAIN) - break; - } - else if(recive > 0) - out_buf_used += recive; - else { - if(!cls) { - strcpy(out_buffer, "Server closed the connection. Use ESC to exit."); - room->AddMessage(out_buffer, system_msg); - cls = true; - } - } - - if(out_buf_used > 0) { - /* warning: if we get a (message without '\n') > max_msg_len then - this code will not work */ - for(int i = 0; i < out_buf_used; i++) { - if(out_buffer[i] == '\n') { - out_buffer[i] = 0; - - // in first char have may spec-symbol, check it: - int spec_msg = usual_msg; - char *buf = out_buffer; - if(out_buffer[0] == system_char) { - spec_msg = system_msg; - buf += 1; - } - - room->AddMessage(buf, spec_msg); - memmove(out_buffer, out_buffer + i + 1, out_buf_used - i - 1); - out_buf_used -= i + 1; - break; - } - } - } - - usleep(usecs); - } while (!exit_flag); -} - -void Client::HandleButton(ChatRoom *room) -{ - int key = room->InputGetch(); - switch(key) - { - case key_escape: { - this->BreakLoop(); - break; - } - case ' '...'~': { // ascii table 32...126 - AddCharToBuffer(key); - room->AddCharToSendMsg(key); - break; - } - case '\n': { // send message - SendMessage(); - room->InputClear(); - room->SetInputCursor(1, 1); - break; - } - case key_backspace: { - RemoveCharFromBuffer(); - room->RemoveCharFromMsg(); - break; - } - default: break; - } -} - -void Client::AddCharToBuffer(char ch) -{ - if(in_buf_used >= max_usermsg_len-1) - return; - - in_buffer[in_buf_used] = ch; - in_buf_used++; -} - -void Client::RemoveCharFromBuffer() -{ - if(in_buf_used <= 0) - return; - - in_buffer[in_buf_used] = '\0'; - in_buf_used--; -} - -void Client::SendMessage() -{ - if(in_buf_used <= 0) - return; - - in_buffer[in_buf_used] = '\n'; - - write(fd, in_buffer, (in_buf_used+1)*sizeof(char)); - memset(in_buffer, 0, (in_buf_used+1)*sizeof(char)); - in_buf_used = 0; -} \ No newline at end of file diff --git a/src/client/clui/user.hpp b/src/client/clui/user.hpp deleted file mode 100644 index a203320..0000000 --- a/src/client/clui/user.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef USER_H -#define USER_H - -#include "clui.hpp" -#include "../const_vars.hpp" - -class Client { - int fd; - char in_buffer[max_usermsg_len]; // for input - int in_buf_used; - - char out_buffer[max_msg_len]; // for message - int out_buf_used; - - bool exit_flag; - - Client(int i_fd) : fd(i_fd), in_buf_used(0), - out_buf_used(0), exit_flag(false) {} -public: - ~Client() { close(fd); } - - static Client *Start(const char* ip, int port); - void Run(ChatRoom *room); - void BreakLoop() { exit_flag = true; } - void HandleButton(ChatRoom *room); - - void AddCharToBuffer(char ch); - void RemoveCharFromBuffer(); - void SendMessage(); -}; - -#endif \ No newline at end of file -- cgit v1.2.3-18-g5258