summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/client.cpp9
-rw-r--r--src/client/user.cpp37
-rw-r--r--src/client/user.hpp5
-rw-r--r--src/const_vars.hpp10
-rw-r--r--src/server/chat.cpp73
-rw-r--r--src/server/chat.hpp32
-rw-r--r--src/server/rooms.cpp188
-rw-r--r--src/server/rooms.hpp15
8 files changed, 241 insertions, 128 deletions
diff --git a/src/client/client.cpp b/src/client/client.cpp
index 7f092cc..8143b9e 100644
--- a/src/client/client.cpp
+++ b/src/client/client.cpp
@@ -10,6 +10,11 @@ static int port = 3030;
int main(int argc, char *argv[])
{
+ if(argc < 2) {
+ printf("Usage: client *name*\n");
+ return 1;
+ }
+
initscr();
//raw();
noecho();
@@ -22,10 +27,10 @@ int main(int argc, char *argv[])
return 1;
}
- Client *user = Client::Start(SERVER_IP, port);
+ Client *user = Client::Start(SERVER_IP, port, argv[1]);
if(!user) {
endwin();
- perror("client");
+ perror("server");
return 1;
}
diff --git a/src/client/user.cpp b/src/client/user.cpp
index 957665e..31cb5e5 100644
--- a/src/client/user.cpp
+++ b/src/client/user.cpp
@@ -10,7 +10,24 @@
#include "user.hpp"
-Client *Client::Start(const char* ip, int port)
+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);
@@ -32,7 +49,7 @@ Client *Client::Start(const char* ip, int port)
sizeof(server_adress));
if(res == -1) return 0;
- return new Client(client);
+ return new Client(client, username);
}
void Client::Run(ChatRoom *room)
@@ -41,6 +58,7 @@ void Client::Run(ChatRoom *room)
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+ int cls = false;
do {
this->HandleButton(room);
@@ -53,6 +71,13 @@ void Client::Run(ChatRoom *room)
}
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
@@ -62,14 +87,14 @@ void Client::Run(ChatRoom *room)
out_buffer[i] = 0;
// in first char have may spec-symbol, check it:
- int spec_symbol = usually_msg;
+ int spec_msg = usual_msg;
char *buf = out_buffer;
- if(out_buffer[0] == '#') {
- spec_symbol = system_msg;
+ if(out_buffer[0] == system_char) {
+ spec_msg = system_msg;
buf += 1;
}
- room->AddMessage(buf, spec_symbol);
+ room->AddMessage(buf, spec_msg);
memmove(out_buffer, out_buffer + i + 1, out_buf_used - i - 1);
out_buf_used -= i + 1;
break;
diff --git a/src/client/user.hpp b/src/client/user.hpp
index 8e2218a..1ae8427 100644
--- a/src/client/user.hpp
+++ b/src/client/user.hpp
@@ -14,12 +14,11 @@ class Client {
bool exit_flag;
- Client(int i_fd)
- : fd(i_fd), in_buf_used(0), out_buf_used(0) { }
+ Client(int i_fd, char *username);
public:
~Client() { close(fd); }
- static Client *Start(const char* ip, int port);
+ static Client *Start(const char* ip, int port, char *username);
void Run(ChatRoom *room);
void BreakLoop() { exit_flag = true; }
void HandleButton(ChatRoom *room);
diff --git a/src/const_vars.hpp b/src/const_vars.hpp
index d41f800..54ef70f 100644
--- a/src/const_vars.hpp
+++ b/src/const_vars.hpp
@@ -8,16 +8,14 @@
*/
const int max_name_len = 18;
+const int min_name_len = 3;
const int oneline_len = 57;
const int max_usermsg_len = oneline_len * 3 - max_name_len - 2; // ": " = 2
// 57 * 3 - 18 - 2 = 151
const int max_msg_len = oneline_len * 3; // 57*3 = 171
-const int key_enter = 10;
-const int key_escape = 27;
-const int key_backspace = 127;
-
-const int usually_msg = 0; // no first char
-const int system_msg = 1; // first char: '#'
+const int usual_msg = 0; // no first char
+const int system_msg = 1;
+const char system_char = '#';
#endif \ No newline at end of file
diff --git a/src/server/chat.cpp b/src/server/chat.cpp
index 0d6eef8..561a61d 100644
--- a/src/server/chat.cpp
+++ b/src/server/chat.cpp
@@ -10,10 +10,24 @@
const int qlen_for_listen = 6;
-void ChatSession::Send(const char *msg)
+void ChatSession::Send(const char *msg, const int spec_msg)
{
- CONSOLE_LOG("%s", msg);
- write(GetFd(), msg, strlen(msg));
+ int len = strlen(msg);
+ char *tmp_msg = new char[len+1+2]; // for spec_symb + \n
+
+ if(spec_msg == usual_msg)
+ sprintf(tmp_msg, "%s\n", msg);
+ else
+ {
+ char spec;
+ if(spec_msg == system_msg) spec = system_char;
+ sprintf(tmp_msg, "%c%s\n", spec, msg);
+ }
+
+ CONSOLE_LOG("%s", tmp_msg);
+ write(GetFd(), tmp_msg, strlen(tmp_msg));
+
+ delete[] tmp_msg;
}
void ChatSession::Handle(bool r, bool w)
@@ -102,16 +116,7 @@ const char *ChatSession::GetName()
void ChatSession::SetName(const char *n_name)
{
- for(int i = 0; i < max_name_len; i++)
- name[i] = 0;
-
strcpy(name, n_name);
- char *msg = new char[max_msg_len];
- sprintf(msg, "#Your name: %s\n", name);
-
- this->Send(msg);
-
- delete[] msg;
}
void ChatSession::SetRoom(ChatRoom *new_master)
@@ -125,7 +130,7 @@ Server::Server(EventSelector *sel, int fd)
: FdHandler(fd), the_selector(sel)
{
the_selector->Add(this);
- lobby = new ChatRoom(this, std_id_lobby);
+ lobby = new ChatRoom(this, std_id_lobby, 0);
}
Server::~Server()
@@ -183,27 +188,9 @@ void Server::Handle(bool r, bool w)
ChatSession *s = new ChatSession(lobby, sd);
lobby->AddSession(s);
the_selector->Add(s);
-
- // welcome messages:
- s->Send("#Welcome to WantChat!\n");
- s->Send(" \n");
- s->Send("#It is anonymous chat in retro-style 80s.\n");
- s->Send("#Use our chat-client for more immersed.\n");
- s->Send(" \n");
- s->Send("#This project is open source :)\n");
- s->Send("#Github: github.com/Joursoir/want-chat\n");
- s->Send(" \n");
- s->Send("#First, come up with a nickname using /name your_good_name\n");
- s->Send("#Thereafter you can join to room using /join room_id\n");
- s->Send("#You can find rooms using /rooms\n");
- s->Send(" \n");
- s->Send("#For more detailed info: /help. Good chatting!\n");
- s->Send(" \n");
-
-
}
-int Server::AddRoom()
+int Server::AddRoom(char *password)
{
if(!room) {
room_len = 16;
@@ -216,7 +203,7 @@ int Server::AddRoom()
for(int i = 0; i < room_len; i++) {
if(room[i] == 0) {
id = i;
- room[i] = new ChatRoom(this, id);
+ room[i] = new ChatRoom(this, id, password);
break;
}
}
@@ -227,7 +214,7 @@ int Server::AddRoom()
tmp[i] = room[i];
id = room_len;
- tmp[room_len] = new ChatRoom(this, id);
+ tmp[room_len] = new ChatRoom(this, id, password);
room_len += 1;
delete[] room;
@@ -255,13 +242,23 @@ void Server::GotoLobby(ChatRoom *cur_room, ChatSession *s)
s->SetRoom(lobby);
}
-bool Server::ChangeSessionRoom(ChatRoom *cur_room, ChatSession *s, int id)
+handle_room_enter Server::ChangeSessionRoom(ChatRoom *cur_room,
+ ChatSession *s, int id, char *pass)
{
- if(id >= room_len || !room[id])
- return false;
+ if(id < 0 || id >= room_len || !room[id])
+ return enter_noexist;
+
+ const char *secret_word = room[id]->GetSecretPass();
+ CONSOLE_LOG("s: %s; pass: %s\n", secret_word, pass);
+ if(secret_word != 0) {
+ if(!pass)
+ return enter_private;
+ if(strcmp(secret_word, pass) != 0)
+ return enter_uncorrect_pass;
+ }
cur_room->RemoveSession(s);
room[id]->AddSession(s);
s->SetRoom(room[id]);
- return true;
+ return enter_success;
} \ No newline at end of file
diff --git a/src/server/chat.hpp b/src/server/chat.hpp
index 6abfc48..4b6c8b1 100644
--- a/src/server/chat.hpp
+++ b/src/server/chat.hpp
@@ -6,34 +6,51 @@
#define CONSOLE_LOG(f_, ...) printf((f_), ##__VA_ARGS__)
+enum handle_room_enter {
+ enter_noexist,
+ enter_private,
+ enter_uncorrect_pass,
+ enter_success
+};
+
+enum enum_status {
+ wait_name, // expecting a username from player
+ wait_reg, // expecting registration
+ wait_log, // expecting login
+ no_wait
+};
+
class ChatRoom;
class Server;
class ChatSession : FdHandler {
friend class Server;
+ friend class ChatRoom;
char name[max_name_len];
char buffer[max_msg_len];
int buf_used;
bool ignoring;
+ enum_status state;
ChatRoom *the_master;
ChatSession(ChatRoom *i_master, int i_fd) : FdHandler(i_fd),
- buf_used(0), ignoring(false), the_master(i_master) {}
+ buf_used(0), ignoring(false), state(wait_name),
+ the_master(i_master) {}
~ChatSession() {}
+ void SetRoom(ChatRoom *new_master);
+
virtual void Handle(bool r, bool w);
- void ReadAndIgnore();
+ void ReadAndIgnore();
void ReadAndCheck();
void CheckLines();
-
- void SetRoom(ChatRoom *new_master);
public:
const char *GetName();
void SetName(const char *n_name);
- void Send(const char *msg);
+ void Send(const char *msg, const int spec_msg = system_msg);
};
class Server : public FdHandler {
@@ -51,11 +68,12 @@ public:
bool RoomExist(int id) const;
- int AddRoom();
+ int AddRoom(char *password);
bool DeleteRoom(int id); // call only if room is empty
void GotoLobby(ChatRoom *cur_room, ChatSession *s);
- bool ChangeSessionRoom(ChatRoom *cur_room, ChatSession *s, int id);
+ handle_room_enter ChangeSessionRoom(ChatRoom *cur_room,
+ ChatSession *s, int id, char *pass);
void CloseConnection(ChatSession *s)
{ the_selector->Remove(s); delete s; }
private:
diff --git a/src/server/rooms.cpp b/src/server/rooms.cpp
index 1ffb89a..ba1ee1b 100644
--- a/src/server/rooms.cpp
+++ b/src/server/rooms.cpp
@@ -5,40 +5,46 @@
#include "rooms.hpp"
#include "chat.hpp"
-// hash of commands:
-#define CMD_NAME 0
-#define CMD_CREATE 1
-#define CMD_JOIN 2
-#define CMD_EXIT 3
-#define CMD_ROOMS 4
-
#define USE_IN_ROOM 0
#define USE_IN_LOBBY 1
#define USE_ANYWHERE 2
-char **ParseToArg(const char *input, int &arrc);
-unsigned long hash(const char *str);
+static char **ParseToArg(const char *input, int &arrc);
+static unsigned long hash(const char *str);
+static bool checkForbiddenSymbols(const char *str);
struct cmd_info {
+ int id; // never -1 !!!
char name[15];
- unsigned long name_hash;
+ const unsigned long name_hash;
int lobby_cmd; // USE_IN_ROOM, USE_IN_LOBBY, USE_ANYWHERE
int min_argc;
char usage[64];
};
-const int cmd_count = 5;
+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_count = 4;
const struct cmd_info cmd[cmd_count] = {
- {"/name", hash("/name"), USE_IN_LOBBY, 1, "#Usage: /name *your_good_name*\n"},
- {"/create", hash("/create"), USE_IN_LOBBY, 0, "#Usage: /create [pass-key]\n"},
- {"/join", hash("/join"), USE_IN_LOBBY, 1, "#Usage: /join *id* [pass-key]\n"},
- {"/exit", hash("/exit"), USE_IN_ROOM, 0, "#Usage: /exit\n"},
- {"/rooms", hash("/rooms"), USE_IN_LOBBY, 0, "#Usage: /rooms\n"} // print all public rooms
- // if u add cmd, then add define too (see above)
+ {cmd_id_create, "/create", hash("/create"), USE_IN_LOBBY, 0, "Usage: /create [pass-key]"},
+ {cmd_id_join, "/join", hash("/join"), USE_IN_LOBBY, 1, "Usage: /join *id* [pass-key]"},
+ {cmd_id_exit, "/exit", hash("/exit"), USE_IN_ROOM, 0, "Usage: /exit"},
+ {cmd_id_rooms, "/rooms", hash("/rooms"), USE_IN_LOBBY, 0, "Usage: /rooms"} // print all public rooms
// IDEA: /clear - clear screen
};
+ChatRoom::ChatRoom(Server *i_server, int id, char *pass)
+ : the_server(i_server), code(id), first(0)
+{
+ if(pass)
+ strcpy(secret_pass, pass);
+ else secret_pass[0] = 0;
+}
+
ChatRoom::~ChatRoom()
{
while(first) {
@@ -49,17 +55,53 @@ ChatRoom::~ChatRoom()
}
}
-void ChatRoom::SendAll(const char *msg, ChatSession *except)
+void ChatRoom::SendAll(const char *msg, ChatSession *except,
+ const int spec_msg)
{
CONSOLE_LOG("Send message all: %s\n", msg);
item *p;
for(p = first; p; p = p->next)
if(p->s != except)
- p->s->Send(msg);
+ p->s->Send(msg, spec_msg);
}
void ChatRoom::HandleMessage(ChatSession *ses, const char *str)
{
+ int status = ses->state;
+ if(status != no_wait) {
+ if(status == wait_name) {
+ // handle name, if OK - will send hello msg
+ int len = strlen(str);
+ if(len > max_name_len || len < min_name_len) {
+ ses->Send("Incorrect name. Name length from 3 to 18 chars");
+ CloseSession(ses);
+ }
+ if(checkForbiddenSymbols(str)) {
+ ses->Send("Incorrect name. You use forbidden symbols.");
+ CloseSession(ses);
+ }
+ ses->SetName(str);
+
+ ses->Send("Welcome to WantChat!");
+ ses->Send(" ");
+ ses->Send("It is anonymous chat in retro-style 80s.");
+ ses->Send("Use our chat-client for more immersed.");
+ ses->Send(" ");
+ ses->Send("This project is open source :)");
+ ses->Send("Github: github.com/Joursoir/want-chat");
+ ses->Send(" ");
+ ses->Send("To join to room using /join room_id");
+ ses->Send("You can find rooms using /rooms");
+ ses->Send(" ");
+ ses->Send("For more detailed info: /help. Good chatting!");
+ ses->Send(" ");
+
+ ses->state = no_wait;
+ }
+
+ return;
+ }
+
if(str[0] == '/') { // if user sent a command
int argc = 0;
char **argv = ParseToArg(str, argc);
@@ -71,12 +113,13 @@ void ChatRoom::HandleMessage(ChatSession *ses, const char *str)
}
else if(code != std_id_lobby) {
char *msg = new char[max_msg_len];
- sprintf(msg, "%s: %s\n", ses->GetName(), str);
+ sprintf(msg, "%s: %s", ses->GetName(), str);
- this->SendAll(msg);
+ this->SendAll(msg, 0, usual_msg);
delete[] msg;
}
+ else ses->Send("In the lobby you can only write commands");
}
void ChatRoom::HandleCommand(ChatSession *ses, int count,
@@ -94,11 +137,10 @@ void ChatRoom::HandleCommand(ChatSession *ses, int count,
}
if(what_command == -1)
- return ses->Send("#Unknown command. Use: /help\n");
+ return ses->Send("Unknown command. Use: /help");
- const char onlyroom_msg[] = "#You can use this command only in rooms!\n";
- const char onlylobby_msg[] = "#You can use this command only in lobby!\n";
- const char initname_msg[] = "#First come up with name!\n";
+ const char onlyroom_msg[] = "You can use this command only in rooms!";
+ const char onlylobby_msg[] = "You can use this command only in lobby!";
// scope of command:
if(cmd[what_command].lobby_cmd == USE_IN_ROOM && code == std_id_lobby)
@@ -110,55 +152,60 @@ void ChatRoom::HandleCommand(ChatSession *ses, int count,
if(cmd[what_command].min_argc > count-1)
return ses->Send(cmd[what_command].usage);
- // name check:
- if((!ses->GetName()) && what_command != CMD_NAME)
- return ses->Send(initname_msg);
-
- switch(what_command) {
- case CMD_NAME: {
- int len = strlen(argvar[1]);
- if(len > max_name_len || len < 3)
- return ses->Send("#Incorrect name. Name length from 3 to 18 chars\n");
-
- ses->SetName(argvar[1]);
- break;
- }
- case CMD_CREATE: {
- int id = the_server->AddRoom();
-
- const char fcmsg[] = "#You create a room #";
- const char scmsg[] = " with password ";
- char *cmsg = new char[strlen(fcmsg)+strlen(scmsg)+4];
- sprintf(cmsg, "%s%d\n", fcmsg, id);
+ switch(cmd[what_command].id) {
+ case cmd_id_create: {
+ char *pass = 0;
+ if(count > 1) {
+ if(strlen(argvar[1]) > max_room_lenpass)
+ return ses->Send("Maximum length of pass equals 24");
+ pass = argvar[1];
+ }
+ int id = the_server->AddRoom(pass);
+
+ const char fcmsg[] = "You create a room #";
+ const char scmsg[] = " with password: ";
+ char *cmsg = new char[strlen(fcmsg)+3+strlen(scmsg)+max_room_lenpass];
+ if(pass) sprintf(cmsg, "%s%d%s%s", fcmsg, id, scmsg, pass);
+ else sprintf(cmsg, "%s%d", fcmsg, id);
ses->Send(cmsg);
delete[] cmsg;
- the_server->ChangeSessionRoom(this, ses, id);
+ the_server->ChangeSessionRoom(this, ses, id, pass);
break;
}
- case CMD_JOIN: {
+ case cmd_id_join: {
int id = atoi(argvar[1]);
- bool success = false;
- if(id >= 0)
- success = the_server->ChangeSessionRoom(this, ses, id);
+ char *pass = argvar[2]; // if count == 2, then argvar[2] = 0
- if(!success)
- ses->Send("#Room with that id didn't exist\n");
+ int h_status = the_server->ChangeSessionRoom(this, ses, id, pass);
+ if(h_status == enter_noexist)
+ return ses->Send("Room with that ID didn't exist");
+ else if(h_status == enter_private)
+ return ses->Send("It is private room, join using password");
+ else if(h_status == enter_uncorrect_pass)
+ return ses->Send("Oops, this password is not valid");
break;
}
- case CMD_EXIT: {
+ case cmd_id_exit: {
the_server->GotoLobby(this, ses);
break;
}
- case CMD_ROOMS: {
-
+ case cmd_id_rooms: {
+ // in development
break;
}
default: break;
}
}
+const char *ChatRoom::GetSecretPass()
+{
+ if(secret_pass[0] != 0)
+ return secret_pass;
+ return 0;
+}
+
void ChatRoom::AddSession(ChatSession *ses)
{
item *p = new item;
@@ -175,12 +222,12 @@ void ChatRoom::AddSession(ChatSession *ses)
const char *name = ses->GetName();
char *wmsg = new char[sizeof(welcome_msg) + 2];
- sprintf(wmsg, "#%s%d\n", welcome_msg, code);
+ sprintf(wmsg, "%s%d", welcome_msg, code);
ses->Send(wmsg);
delete[] wmsg;
- char *emsg = new char[strlen(name) + sizeof(entered_msg) + 2];
- sprintf(emsg, "#%s%s\n", name, entered_msg);
+ char *emsg = new char[strlen(name) + sizeof(entered_msg)];
+ sprintf(emsg, "%s%s", name, entered_msg);
this->SendAll(emsg, ses);
delete[] emsg;
@@ -194,7 +241,7 @@ void ChatRoom::RemoveSession(ChatSession *ses)
int len = strlen(name);
char *lmsg = new char[len + sizeof(left_msg) + 2];
- sprintf(lmsg, "#%s%s\n", name, left_msg);
+ sprintf(lmsg, "%s%s", name, left_msg);
this->SendAll(lmsg, ses);
delete[] lmsg;
}
@@ -224,11 +271,11 @@ void ChatRoom::CloseSession(ChatSession *ses)
//////////////////////////////////////////////////////////////
-char **ParseToArg(const char *input, int &arrc)
+static char **ParseToArg(const char *input, int &arrc)
{
int max_argv = 5;
arrc = 0;
- char **arr = new char*[max_argv];
+ char **arr = new char*[max_argv+1];
int start = 0;
for(int i = 0; i < (int) strlen(input)+1; i++) {
@@ -250,10 +297,11 @@ char **ParseToArg(const char *input, int &arrc)
start = i;
}
+ arr[arrc] = 0;
return arr;
}
-unsigned long hash(const char *str)
+static unsigned long hash(const char *str)
{
unsigned long hash = 5381;
char c;
@@ -262,4 +310,20 @@ unsigned long hash(const char *str)
hash = ((hash << 5) + hash) + c;
return hash;
+}
+
+static bool checkForbiddenSymbols(const char *str)
+{
+ char banned_symbols[] = {'!', '@', '#', '\'',
+ '\"', '\\', '/', '^', '&', '*', ';', ','};
+
+ int num = sizeof(banned_symbols)/sizeof(char);
+ for(int i = 0; i < (int)strlen(str); i++) {
+ for(int j = 0; j < num; j++) {
+ if(str[i] == banned_symbols[j])
+ return 1;
+ }
+ }
+
+ return 0;
} \ No newline at end of file
diff --git a/src/server/rooms.hpp b/src/server/rooms.hpp
index 9423be1..4d71d0b 100644
--- a/src/server/rooms.hpp
+++ b/src/server/rooms.hpp
@@ -1,7 +1,10 @@
#ifndef ROOMREALIZATION_H
#define ROOMREALIZATION_H
+#include "../const_vars.hpp"
+
const int std_id_lobby = -1;
+const int max_room_lenpass = 24;
class Server;
class ChatSession;
@@ -9,7 +12,9 @@ class ChatSession;
class ChatRoom {
Server *the_server;
const int code;
- // code == -1 it's lobby
+ // if code == std_id_lobby then it's lobby
+
+ char secret_pass[max_room_lenpass];
struct item {
ChatSession *s;
@@ -17,16 +22,18 @@ class ChatRoom {
};
item *first;
public:
- ChatRoom(Server *i_server, int id)
- : the_server(i_server), code(id), first(0) {}
+ ChatRoom(Server *i_server, int id, char *pass);
~ChatRoom();
- void SendAll(const char *msg, ChatSession *except = 0);
+ void SendAll(const char *msg, ChatSession *except = 0,
+ const int spec_msg = system_msg);
void HandleMessage(ChatSession *ses, const char *str);
void HandleCommand(ChatSession *ses, int cmd_counter,
char **commands);
+ const char *GetSecretPass();
+
void AddSession(ChatSession *ses);
void RemoveSession(ChatSession *ses);
void CloseSession(ChatSession *ses);