From e99a03a838ddcf9eecadc10a7f71837afac3b99c Mon Sep 17 00:00:00 2001 From: Joursoir Date: Sun, 6 Dec 2020 19:47:25 +0000 Subject: some changes in reg/auth; client: remove name in arguments --- src/client/Makefile | 18 ----- src/client/client.cpp | 43 ---------- src/client/clui.cpp | 187 -------------------------------------------- src/client/clui.hpp | 61 --------------- src/client/user.cpp | 166 --------------------------------------- src/client/user.hpp | 31 -------- src/client_clui/Makefile | 18 +++++ src/client_clui/client.cpp | 35 +++++++++ src/client_clui/clui.cpp | 187 ++++++++++++++++++++++++++++++++++++++++++++ src/client_clui/clui.hpp | 61 +++++++++++++++ src/client_clui/user.cpp | 153 ++++++++++++++++++++++++++++++++++++ src/client_clui/user.hpp | 32 ++++++++ src/server/ChatRoom.cpp | 144 ++++++++++++++++++++-------------- src/server/ChatRoom.hpp | 1 + src/server/ChatRoom_cmd.cpp | 54 +------------ src/server/ChatServer.cpp | 4 +- 16 files changed, 579 insertions(+), 616 deletions(-) delete mode 100644 src/client/Makefile delete mode 100644 src/client/client.cpp delete mode 100644 src/client/clui.cpp delete mode 100644 src/client/clui.hpp delete mode 100644 src/client/user.cpp delete mode 100644 src/client/user.hpp create mode 100644 src/client_clui/Makefile create mode 100644 src/client_clui/client.cpp create mode 100644 src/client_clui/clui.cpp create mode 100644 src/client_clui/clui.hpp create mode 100644 src/client_clui/user.cpp create mode 100644 src/client_clui/user.hpp diff --git a/src/client/Makefile b/src/client/Makefile deleted file mode 100644 index 071462b..0000000 --- a/src/client/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -CPP = g++ -CPPFLAGS = -Wall -g -lncurses -SOURCES = client.cpp clui.cpp user.cpp -OBJECTS = $(SOURCES:.cpp=.o) -EXECUTABLE = client - -.PHONY: all clean - -all: $(EXECUTABLE) - -clean: - rm -rf $(OBJECTS) $(EXECUTABLE) - -$(EXECUTABLE): $(OBJECTS) - $(CPP) $(CPPFLAGS) -o $(EXECUTABLE) $(OBJECTS) - -$(OBJECTS): - $(CPP) -c $(CPPFLAGS) $(SOURCES) \ No newline at end of file diff --git a/src/client/client.cpp b/src/client/client.cpp deleted file mode 100644 index 8143b9e..0000000 --- a/src/client/client.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include -#include - -#include "user.hpp" - -#define SERVER_IP "127.0.0.1" -static int port = 3030; - -int main(int argc, char *argv[]) -{ - if(argc < 2) { - printf("Usage: client *name*\n"); - return 1; - } - - initscr(); - //raw(); - 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, port, argv[1]); - 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.cpp b/src/client/clui.cpp deleted file mode 100644 index 78fd226..0000000 --- a/src/client/clui.cpp +++ /dev/null @@ -1,187 +0,0 @@ -#include -#include - -#include "clui.hpp" - -#define CHAT_HEIGHT 20 -#define CHAT_WIDTH 59 -#define PLAYERS_WIDTH 20 -#define PLAYERS_HEIGHT 20 -#define INPUT_HEIGHT 4 -#define INPUT_WIDTH 80 - -Interface_wc::Interface_wc(int num_y, int num_x, int by, - int bx, char ch) : ny(num_y), nx(num_x), beg_y(by), - beg_x(bx), ch_line(ch) -{ - w = newwin(ny, nx, beg_y, beg_x); - box(w, ch_line, ch_line); - this->Update(); -} - -void Interface_wc::Hide() -{ - this->Clear(true); - this->Update(); - this->Delete(); -} - -void Interface_wc::Clear(bool full) -{ - werase(this->GetWindow()); - if(!full) - box(this->GetWindow(), ch_line, ch_line); -} - -//////////////////////////////////////////////////////////////////////// - -ChatRoom::ChatRoom() : first(0) -{ - chat = new Interface_wc(CHAT_HEIGHT, CHAT_WIDTH, 0, 0, 0); - players = new Interface_wc(PLAYERS_HEIGHT, PLAYERS_WIDTH, 0, 60, 0); - input = new Interface_wc(INPUT_HEIGHT, INPUT_WIDTH, 20, 0, 0); - nodelay(input->GetWindow(), true); - keypad(input->GetWindow(), true); - i_nx = 1; - i_ny = 1; -} - -ChatRoom::~ChatRoom() -{ - if(chat) - delete chat; - if(players) - delete players; - if(input) - delete input; - - // #TODO: - /* if(first) ... delete message */ -} - -void ChatRoom::AddMessage(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; - - strcpy(recent_msg->msg, msg); - recent_msg->num_lines = lines; - recent_msg->type = type; - - recent_msg->prev = first; - first = recent_msg; - - ChatRedraw(); -} - -void ChatRoom::ChatRedraw() -{ - if(!first) - return; - - chat->Clear(false); - int available_lines = CHAT_HEIGHT - 2; - bool remove = false; - message *tmp; - - message *last; - for(message *m = first; m; m = m->prev) { - if(available_lines-1 >= m->num_lines) { - PrintMessage(available_lines, m); - available_lines -= m->num_lines; - last = m; - } - else { - tmp = m; - remove = true; - break; - } - } - - if(remove) { - last->prev = 0; - while(tmp) { - message *m = tmp; - tmp = tmp->prev; - delete m; - } - } - - SetInputCursor(i_ny, i_nx); - chat->Update(); -} - -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); - - wprintw(win, tmp); - need_print--; - - if(m->type == system_msg) wattroff(win, A_ITALIC); - else wattroff(win, A_BOLD); - - delete[] tmp; - } -} - -bool ChatRoom::AddCharToSendMsg(char ch) -{ - if(i_ny == 2 && i_nx == max_usermsg_len/2-1) - return 0; - - mvwaddch(input->GetWindow(), i_ny, i_nx, ch); - i_nx++; - if(i_nx >= max_usermsg_len/2-1) { - if(i_ny == 1) { - i_ny++; - i_nx = 1; - } - else if(i_ny == 2) - i_nx--; - wmove(input->GetWindow(), i_ny, i_nx); - } - - input->Update(); - return 1; -} - -bool ChatRoom::RemoveCharFromMsg() -{ - if(i_ny == 1 && i_nx == 1) - return 0; - - i_nx--; - if(i_nx < 1) { - i_ny--; - i_nx = max_usermsg_len/2-1; - } - mvwaddch(input->GetWindow(), i_ny, i_nx, ' '); - wmove(input->GetWindow(), i_ny, i_nx); - - input->Update(); - return 1; -} - -void ChatRoom::SetInputCursor(int y, int x) -{ - input->SetCursor(y, x); - i_ny = y; - i_nx = x; -} \ No newline at end of file diff --git a/src/client/clui.hpp b/src/client/clui.hpp deleted file mode 100644 index 0373f95..0000000 --- a/src/client/clui.hpp +++ /dev/null @@ -1,61 +0,0 @@ -// CLUI - Command Line User Interface - -#ifndef COMMANDLINEUI_H -#define COMMANDLINEUI_H - -#include -#include "../const_vars.hpp" - -class Interface_wc { - WINDOW *w; - int ny, nx; - int beg_y, beg_x; - int ch_line; -public: - Interface_wc(int num_y, int num_x, int by, int bx, char ch); - - WINDOW *GetWindow() { return w; } - void SetCursor(int y, int x) { wmove(w, y, x); } - void Clear(bool full); - void Update() { wrefresh(w); } - void Delete() { delwin(w); } - - void Hide(); -}; - -class ChatRoom { - Interface_wc *chat; - Interface_wc *players; - Interface_wc *input; - int i_nx, i_ny; - - struct message { - char msg[max_msg_len]; - int num_lines; // number of lines - int type; - message *prev; - }; - message *first; -public: - ChatRoom(); - ~ChatRoom(); - - // for chat: - void AddMessage(char *msg, int type); - - // for players: - //void AddPlayer() - - // for input: - int InputGetch() { return wgetch(input->GetWindow()); } - bool AddCharToSendMsg(char ch); - bool RemoveCharFromMsg(); - void InputClear() { input->Clear(false); } - void SetInputCursor(int y, int x); -private: - // for chat: - void ChatRedraw(); - void PrintMessage(int line, message *m); -}; - -#endif \ No newline at end of file diff --git a/src/client/user.cpp b/src/client/user.cpp deleted file mode 100644 index 31cb5e5..0000000 --- a/src/client/user.cpp +++ /dev/null @@ -1,166 +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(int i_fd, char *username) : fd(i_fd), in_buf_used(0), - out_buf_used(0) -{ - int len = strlen(username); - char *name = new char[len+2]; - sprintf(name, "%s\n", username); - - write(i_fd, name, strlen(name)); - delete[] name; -} - -Client *Client::Start(const char* ip, int port, char *username) -{ - 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, username); -} - -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/user.hpp b/src/client/user.hpp deleted file mode 100644 index 1ae8427..0000000 --- a/src/client/user.hpp +++ /dev/null @@ -1,31 +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, char *username); -public: - ~Client() { close(fd); } - - static Client *Start(const char* ip, int port, char *username); - 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 new file mode 100644 index 0000000..071462b --- /dev/null +++ b/src/client_clui/Makefile @@ -0,0 +1,18 @@ +CPP = g++ +CPPFLAGS = -Wall -g -lncurses +SOURCES = client.cpp clui.cpp user.cpp +OBJECTS = $(SOURCES:.cpp=.o) +EXECUTABLE = client + +.PHONY: all clean + +all: $(EXECUTABLE) + +clean: + rm -rf $(OBJECTS) $(EXECUTABLE) + +$(EXECUTABLE): $(OBJECTS) + $(CPP) $(CPPFLAGS) -o $(EXECUTABLE) $(OBJECTS) + +$(OBJECTS): + $(CPP) -c $(CPPFLAGS) $(SOURCES) \ No newline at end of file diff --git a/src/client_clui/client.cpp b/src/client_clui/client.cpp new file mode 100644 index 0000000..83f8ef0 --- /dev/null +++ b/src/client_clui/client.cpp @@ -0,0 +1,35 @@ +#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 new file mode 100644 index 0000000..78fd226 --- /dev/null +++ b/src/client_clui/clui.cpp @@ -0,0 +1,187 @@ +#include +#include + +#include "clui.hpp" + +#define CHAT_HEIGHT 20 +#define CHAT_WIDTH 59 +#define PLAYERS_WIDTH 20 +#define PLAYERS_HEIGHT 20 +#define INPUT_HEIGHT 4 +#define INPUT_WIDTH 80 + +Interface_wc::Interface_wc(int num_y, int num_x, int by, + int bx, char ch) : ny(num_y), nx(num_x), beg_y(by), + beg_x(bx), ch_line(ch) +{ + w = newwin(ny, nx, beg_y, beg_x); + box(w, ch_line, ch_line); + this->Update(); +} + +void Interface_wc::Hide() +{ + this->Clear(true); + this->Update(); + this->Delete(); +} + +void Interface_wc::Clear(bool full) +{ + werase(this->GetWindow()); + if(!full) + box(this->GetWindow(), ch_line, ch_line); +} + +//////////////////////////////////////////////////////////////////////// + +ChatRoom::ChatRoom() : first(0) +{ + chat = new Interface_wc(CHAT_HEIGHT, CHAT_WIDTH, 0, 0, 0); + players = new Interface_wc(PLAYERS_HEIGHT, PLAYERS_WIDTH, 0, 60, 0); + input = new Interface_wc(INPUT_HEIGHT, INPUT_WIDTH, 20, 0, 0); + nodelay(input->GetWindow(), true); + keypad(input->GetWindow(), true); + i_nx = 1; + i_ny = 1; +} + +ChatRoom::~ChatRoom() +{ + if(chat) + delete chat; + if(players) + delete players; + if(input) + delete input; + + // #TODO: + /* if(first) ... delete message */ +} + +void ChatRoom::AddMessage(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; + + strcpy(recent_msg->msg, msg); + recent_msg->num_lines = lines; + recent_msg->type = type; + + recent_msg->prev = first; + first = recent_msg; + + ChatRedraw(); +} + +void ChatRoom::ChatRedraw() +{ + if(!first) + return; + + chat->Clear(false); + int available_lines = CHAT_HEIGHT - 2; + bool remove = false; + message *tmp; + + message *last; + for(message *m = first; m; m = m->prev) { + if(available_lines-1 >= m->num_lines) { + PrintMessage(available_lines, m); + available_lines -= m->num_lines; + last = m; + } + else { + tmp = m; + remove = true; + break; + } + } + + if(remove) { + last->prev = 0; + while(tmp) { + message *m = tmp; + tmp = tmp->prev; + delete m; + } + } + + SetInputCursor(i_ny, i_nx); + chat->Update(); +} + +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); + + wprintw(win, tmp); + need_print--; + + if(m->type == system_msg) wattroff(win, A_ITALIC); + else wattroff(win, A_BOLD); + + delete[] tmp; + } +} + +bool ChatRoom::AddCharToSendMsg(char ch) +{ + if(i_ny == 2 && i_nx == max_usermsg_len/2-1) + return 0; + + mvwaddch(input->GetWindow(), i_ny, i_nx, ch); + i_nx++; + if(i_nx >= max_usermsg_len/2-1) { + if(i_ny == 1) { + i_ny++; + i_nx = 1; + } + else if(i_ny == 2) + i_nx--; + wmove(input->GetWindow(), i_ny, i_nx); + } + + input->Update(); + return 1; +} + +bool ChatRoom::RemoveCharFromMsg() +{ + if(i_ny == 1 && i_nx == 1) + return 0; + + i_nx--; + if(i_nx < 1) { + i_ny--; + i_nx = max_usermsg_len/2-1; + } + mvwaddch(input->GetWindow(), i_ny, i_nx, ' '); + wmove(input->GetWindow(), i_ny, i_nx); + + input->Update(); + return 1; +} + +void ChatRoom::SetInputCursor(int y, int x) +{ + input->SetCursor(y, x); + i_ny = y; + i_nx = x; +} \ No newline at end of file diff --git a/src/client_clui/clui.hpp b/src/client_clui/clui.hpp new file mode 100644 index 0000000..0373f95 --- /dev/null +++ b/src/client_clui/clui.hpp @@ -0,0 +1,61 @@ +// CLUI - Command Line User Interface + +#ifndef COMMANDLINEUI_H +#define COMMANDLINEUI_H + +#include +#include "../const_vars.hpp" + +class Interface_wc { + WINDOW *w; + int ny, nx; + int beg_y, beg_x; + int ch_line; +public: + Interface_wc(int num_y, int num_x, int by, int bx, char ch); + + WINDOW *GetWindow() { return w; } + void SetCursor(int y, int x) { wmove(w, y, x); } + void Clear(bool full); + void Update() { wrefresh(w); } + void Delete() { delwin(w); } + + void Hide(); +}; + +class ChatRoom { + Interface_wc *chat; + Interface_wc *players; + Interface_wc *input; + int i_nx, i_ny; + + struct message { + char msg[max_msg_len]; + int num_lines; // number of lines + int type; + message *prev; + }; + message *first; +public: + ChatRoom(); + ~ChatRoom(); + + // for chat: + void AddMessage(char *msg, int type); + + // for players: + //void AddPlayer() + + // for input: + int InputGetch() { return wgetch(input->GetWindow()); } + bool AddCharToSendMsg(char ch); + bool RemoveCharFromMsg(); + void InputClear() { input->Clear(false); } + void SetInputCursor(int y, int x); +private: + // for chat: + void ChatRedraw(); + void PrintMessage(int line, message *m); +}; + +#endif \ No newline at end of file diff --git a/src/client_clui/user.cpp b/src/client_clui/user.cpp new file mode 100644 index 0000000..d075751 --- /dev/null +++ b/src/client_clui/user.cpp @@ -0,0 +1,153 @@ +#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 new file mode 100644 index 0000000..a203320 --- /dev/null +++ b/src/client_clui/user.hpp @@ -0,0 +1,32 @@ +#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 diff --git a/src/server/ChatRoom.cpp b/src/server/ChatRoom.cpp index 50c364c..9d99251 100644 --- a/src/server/ChatRoom.cpp +++ b/src/server/ChatRoom.cpp @@ -25,58 +25,8 @@ ChatRoom::~ChatRoom() void ChatRoom::HandleMessage(UserInfo *u, const char *str) { - int status = u->GetStatus(); - if(status == wait_name) { - if(!CheckEnterNickname(u, str)) { - CloseSession(u); - return; - } - u->SetName(str); - - // query to server - char *msg = new char[DB_BUFFER_SIZE]; - sprintf(msg, "SELECT password FROM users WHERE name = '%s' LIMIT 1", str); - AnswerDB *ans = the_server->QuerySelect(msg); - if(ans) { - DB_ROW *row = ans->GetNextRow(); - - sprintf(msg, "Welcome to WantChat, %s!", u->GetName()); - u->Send(msg); - u->Send(" "); - u->Send("Welcome to anonymous chat in retro-style 80s."); - u->Send("Use our chat-client for more immersed."); - u->Send(" "); - u->Send("This project is open source :)"); - u->Send("Github: github.com/Joursoir/want-chat"); - u->Send(" "); - u->Send("To join to room using /join room_id"); - u->Send("You can find rooms using /rooms"); - u->Send(" "); - u->Send("For more detailed info: /help. Good chatting!"); - u->Send(" "); - - if(row) { - u->SetPassword((*row)[0]); - u->SetStatus(wait_login); - - u->Send("Please, log in using /login"); - } - else { - u->SetStatus(wait_reg); - u->Send("Please, create account using /reg"); - } - } - else { - // handling error - CloseSession(u); - return; - } - // query to server - - delete[] msg; - delete ans; - return; - } + if(u->GetStatus() != no_wait) + return Identification(u, str); if(str[0] == '/') { // if user sent a command int argc = 0; @@ -95,11 +45,7 @@ void ChatRoom::HandleMessage(UserInfo *u, const char *str) delete[] msg; } - else { - if(status == wait_reg) u->Send(first_reg); - else if(status == wait_login) u->Send(first_login); - else u->Send("In the lobby you can write only commands"); - } + else u->Send("In the lobby you can write only commands"); } const char *ChatRoom::GetSecretPass() @@ -157,6 +103,90 @@ void ChatRoom::CloseSession(UserInfo *u) serv->CloseConnection(u); } +void ChatRoom::Identification(UserInfo *u, const char *str) +{ + int status = u->GetStatus(); + if(status == wait_name) { + if(!CheckEnterNickname(u, str)) { + CloseSession(u); + return; + } + u->SetName(str); + + // query to server + char *msg = new char[DB_BUFFER_SIZE]; + sprintf(msg, "SELECT password FROM users WHERE name = '%s' LIMIT 1", str); + AnswerDB *ans = the_server->QuerySelect(msg); + if(ans) { + DB_ROW *row = ans->GetNextRow(); + + if(row) { + u->SetPassword((*row)[0]); + u->SetStatus(wait_login); + + sprintf(msg, "Hello, %s! Please, type your password:", u->GetName()); + u->Send(msg); + } + else { + u->SetStatus(wait_reg); + sprintf(msg, "First time here, %s? Please, come up and write password:", u->GetName()); + u->Send(msg); + } + } + else { + // handling error + CloseSession(u); + return; + } + // query to server + + delete[] msg; + delete ans; + } + else if(status == wait_reg) { + if(!CheckEnterPassword(u, str)) + return; + + // query to server (add to database) + char *msg = new char[DB_BUFFER_SIZE]; + sprintf(msg, "INSERT INTO users (name, password) VALUES ('%s', '%s')", u->GetName(), str); + if(the_server->QueryInsert(msg) != 0) { + perror("mariadb insert"); + } + // query to server + + sprintf(msg, "Congratulations, %s! You have registered successfully.", u->GetName()); + u->Send(msg); + delete[] msg; + + u->SetStatus(no_wait); + } + else if(status == wait_login) { + const char *right_pass = u->GetPassword(); + + if(strcmp(str, right_pass) != 0) + return u->Send("Password are not right, try again."); + + u->Send("Yeh, right password! Glad you came back to WhatChat."); + u->SetStatus(no_wait); + } + + if(u->GetStatus() == no_wait) { + u->Send(" "); + u->Send("Welcome to anonymous chat in retro-style 80s."); + u->Send("Use our chat-client for more immersed."); + u->Send(" "); + u->Send("This project is open source :)"); + u->Send("Github: github.com/Joursoir/want-chat"); + u->Send(" "); + u->Send("To join to room using /join room_id"); + u->Send("You can find rooms using /rooms"); + u->Send(" "); + u->Send("For more detailed info: /help. Good chatting!"); + u->Send(" "); + } +} + bool ChatRoom::CheckEnterNickname(UserInfo *u, const char *name) { int len = strlen(name); diff --git a/src/server/ChatRoom.hpp b/src/server/ChatRoom.hpp index 183dcc1..fa56fb2 100644 --- a/src/server/ChatRoom.hpp +++ b/src/server/ChatRoom.hpp @@ -39,6 +39,7 @@ private: static char **ParseToArg(const char *input, int &arrc); // in _cmd static bool CheckForbiddenSymbols(const char *str); // in _cmd + void Identification(UserInfo *u, const char *str); bool CheckEnterNickname(UserInfo *u, const char *name); bool CheckEnterPassword(UserInfo *u, const char *pass); diff --git a/src/server/ChatRoom_cmd.cpp b/src/server/ChatRoom_cmd.cpp index d37ad5e..8b1f6e9 100644 --- a/src/server/ChatRoom_cmd.cpp +++ b/src/server/ChatRoom_cmd.cpp @@ -23,18 +23,14 @@ const int cmd_id_create = 1; const int cmd_id_join = 2; const int cmd_id_exit = 3; const int cmd_id_rooms = 4; -const int cmd_id_reg = 5; -const int cmd_id_login = 6; -const int cmd_count = 7; +const int cmd_count = 5; const struct cmd_info cmd[cmd_count] = { {cmd_id_help, "/help", ChatRoom::Hash("/help"), USE_ANYWHERE, 0, "Usage: /help"}, {cmd_id_create, "/create", ChatRoom::Hash("/create"), USE_IN_LOBBY, 0, "Usage: /create [pass-key]"}, {cmd_id_join, "/join", ChatRoom::Hash("/join"), USE_IN_LOBBY, 1, "Usage: /join *id* [pass-key]"}, {cmd_id_exit, "/exit", ChatRoom::Hash("/exit"), USE_IN_ROOM, 0, "Usage: /exit"}, - {cmd_id_rooms, "/rooms", ChatRoom::Hash("/rooms"), USE_IN_LOBBY, 0, "Usage: /rooms"}, // print all public rooms - {cmd_id_reg, "/reg", ChatRoom::Hash("/reg"), USE_IN_LOBBY, 2, "Usage: /reg *pass* *pass*"}, - {cmd_id_login, "/login", ChatRoom::Hash("/login"), USE_IN_LOBBY, 1, "Usage: /login *pass*"} + {cmd_id_rooms, "/rooms", ChatRoom::Hash("/rooms"), USE_IN_LOBBY, 0, "Usage: /rooms"} // print all public rooms // IDEA: /clear - clear screen }; @@ -56,12 +52,6 @@ void ChatRoom::HandleCommand(UserInfo *u, int count, if(what_command == -1) return u->Send("Unknown command. Use: /help"); - enum_status status = u->GetStatus(); - if(status == wait_reg && what_command != cmd_id_reg) - return u->Send(first_reg); - if(status == wait_login && what_command != cmd_id_login) - return u->Send(first_login); - // scope of command: if(cmd[what_command].lobby_cmd == USE_IN_ROOM && code == std_id_lobby) return u->Send("You can use this command only in rooms!"); @@ -127,46 +117,6 @@ void ChatRoom::HandleCommand(UserInfo *u, int count, // in development break; } - - case cmd_id_reg: { - char *pass_one = argvar[1]; - char *pass_two = argvar[2]; - - if(!CheckEnterPassword(u, pass_one)) - return; - if(strcmp(pass_one, pass_two) != 0) - return u->Send("Passwords are not match, try again"); - - // query to server (add to database) - char *msg = new char[DB_BUFFER_SIZE]; - sprintf(msg, "INSERT INTO users (name, password) VALUES ('%s', '%s')", u->GetName(), pass_one); - if(the_server->QueryInsert(msg) != 0) { - perror("mariadb insert"); - } - // query to server - - sprintf(msg, "Congratulations, %s. You registered in WhatChat.", u->GetName()); - u->Send(msg); - delete[] msg; - u->SetStatus(no_wait); - break; - } - case cmd_id_login: { - CONSOLE_LOG("[!] pass\n"); - char *enter_pass = argvar[1]; - const char *right_pass = u->GetPassword(); - - if(strcmp(enter_pass, right_pass) != 0) - return u->Send("Password are not right, try again"); - - int msg_len = strlen("Hello, ! Glad you came back to WhatChat."); - char *msg = new char[msg_len + max_name_len]; - sprintf(msg, "Hello, %s! Glad you came back to WhatChat.", u->GetName()); - u->Send(msg); - delete[] msg; - u->SetStatus(no_wait); - break; - } default: break; } } diff --git a/src/server/ChatServer.cpp b/src/server/ChatServer.cpp index 2d700e9..7b6a9ea 100644 --- a/src/server/ChatServer.cpp +++ b/src/server/ChatServer.cpp @@ -12,7 +12,7 @@ const int qlen_for_listen = 6; ChatServer::ChatServer(EventSelector *sel, DatabaseManager *db, int fd) - : FdHandler(fd), the_selector(sel), dbase(db) + : FdHandler(fd), the_selector(sel), dbase(db), room(0) { the_selector->Add(this); lobby = new ChatRoom(this, std_id_lobby, 0); @@ -163,6 +163,8 @@ void ChatServer::Handle(bool r, bool w) talkers->AddUser(u); lobby->AddSession(u); the_selector->Add(u); + + u->Send("Welcome to WantChat! What is your name?"); } /////////////////////////////////////////////////////////////// -- cgit v1.2.3-18-g5258