summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoursoir <chat@joursoir.net>2020-11-27 01:41:09 +0300
committerJoursoir <chat@joursoir.net>2020-11-27 01:41:09 +0300
commit5cbaa841d0bf07f75614205059324e5d2adbc5dd (patch)
tree15ead74ebce111bb1952a81e4ea5bbb818fbeca9
parent67cdd15d97b14dd92de28fdbdb2770187c94e338 (diff)
downloadwant-chat-5cbaa841d0bf07f75614205059324e5d2adbc5dd.tar.gz
want-chat-5cbaa841d0bf07f75614205059324e5d2adbc5dd.tar.bz2
want-chat-5cbaa841d0bf07f75614205059324e5d2adbc5dd.zip
server: add different messages, support commands('/') and spec-messages
-rw-r--r--src/const_vars.hpp7
-rw-r--r--src/server/chat.cpp91
-rw-r--r--src/server/chat.hpp18
-rw-r--r--src/server/rooms.cpp205
-rw-r--r--src/server/rooms.hpp12
5 files changed, 246 insertions, 87 deletions
diff --git a/src/const_vars.hpp b/src/const_vars.hpp
index 9c7b1c5..d41f800 100644
--- a/src/const_vars.hpp
+++ b/src/const_vars.hpp
@@ -13,4 +13,11 @@ 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: '#'
+
#endif \ No newline at end of file
diff --git a/src/server/chat.cpp b/src/server/chat.cpp
index a9ecda1..0d6eef8 100644
--- a/src/server/chat.cpp
+++ b/src/server/chat.cpp
@@ -8,7 +8,7 @@
#include "chat.hpp"
#include "rooms.hpp"
-static const int qlen_for_listen = 6;
+const int qlen_for_listen = 6;
void ChatSession::Send(const char *msg)
{
@@ -61,7 +61,6 @@ void ChatSession::ReadAndCheck()
int rc = read(GetFd(), buffer+buf_used, sizeof(buffer)-buf_used);
CONSOLE_LOG("readC return %d bytes\n", rc);
if(rc < 1) {
- the_master->LeaveMessage(this);
the_master->CloseSession(this);
return;
}
@@ -94,27 +93,39 @@ void ChatSession::CheckLines()
}
}
-void ChatSession::ChangeName(const char *n_name)
+const char *ChatSession::GetName()
+{
+ if(name[0])
+ return name;
+ return 0;
+}
+
+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, "Now your name is %s\n", name);
+ sprintf(msg, "#Your name: %s\n", name);
this->Send(msg);
delete[] msg;
}
+void ChatSession::SetRoom(ChatRoom *new_master)
+{
+ this->the_master = new_master;
+}
+
//////////////////////////////////////////////////////////////
Server::Server(EventSelector *sel, int fd)
: FdHandler(fd), the_selector(sel)
{
the_selector->Add(this);
- lobby = new ChatRoom(this, true);
+ lobby = new ChatRoom(this, std_id_lobby);
}
Server::~Server()
@@ -150,6 +161,14 @@ Server *Server::Start(EventSelector *sel, int port)
return new Server(sel, in_d);
}
+bool Server::RoomExist(int id) const
+{
+ if(!room[id])
+ return false;
+
+ return true;
+}
+
void Server::Handle(bool r, bool w)
{
if(!r)
@@ -164,6 +183,24 @@ 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()
@@ -178,19 +215,53 @@ int Server::AddRoom()
int id = -1;
for(int i = 0; i < room_len; i++) {
if(room[i] == 0) {
- id = 0;
- room[i] = new ChatRoom(this, false);
+ id = i;
+ room[i] = new ChatRoom(this, id);
+ break;
}
}
if(id == -1) {
ChatRoom **tmp = new ChatRoom*[room_len+1];
- for(int i = 0; i < room_len; i++) {
+ for(int i = 0; i < room_len; i++)
tmp[i] = room[i];
- }
- tmp[room_len] = new ChatRoom(this, false);
+
+ id = room_len;
+ tmp[room_len] = new ChatRoom(this, id);
room_len += 1;
+
+ delete[] room;
+ room = tmp;
}
return id;
+}
+
+bool Server::DeleteRoom(int id)
+{
+ if(!room[id])
+ return false;
+
+ delete room[id];
+ room[id] = 0;
+
+ return true;
+}
+
+void Server::GotoLobby(ChatRoom *cur_room, ChatSession *s)
+{
+ cur_room->RemoveSession(s);
+ lobby->AddSession(s);
+ s->SetRoom(lobby);
+}
+
+bool Server::ChangeSessionRoom(ChatRoom *cur_room, ChatSession *s, int id)
+{
+ if(id >= room_len || !room[id])
+ return false;
+
+ cur_room->RemoveSession(s);
+ room[id]->AddSession(s);
+ s->SetRoom(room[id]);
+ return true;
} \ No newline at end of file
diff --git a/src/server/chat.hpp b/src/server/chat.hpp
index ca22519..6abfc48 100644
--- a/src/server/chat.hpp
+++ b/src/server/chat.hpp
@@ -27,29 +27,35 @@ class ChatSession : FdHandler {
void ReadAndIgnore();
void ReadAndCheck();
void CheckLines();
+
+ void SetRoom(ChatRoom *new_master);
public:
- const char *GetName() const { return name; }
+ const char *GetName();
- void ChangeName(const char *n_name);
+ void SetName(const char *n_name);
void Send(const char *msg);
};
class Server : public FdHandler {
EventSelector *the_selector;
ChatRoom **room;
- ChatRoom *lobby;
-
int room_len;
+ ChatRoom *lobby;
+
Server(EventSelector *sel, int fd);
public:
~Server();
static Server *Start(EventSelector *sel, int port);
+ bool RoomExist(int id) const;
+
int AddRoom();
- // RemoveRoom();
- // void AddSessionToRoom(ChatSession *s, int id);
+ 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);
void CloseConnection(ChatSession *s)
{ the_selector->Remove(s); delete s; }
private:
diff --git a/src/server/rooms.cpp b/src/server/rooms.cpp
index 624eb88..1ffb89a 100644
--- a/src/server/rooms.cpp
+++ b/src/server/rooms.cpp
@@ -1,23 +1,44 @@
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include "rooms.hpp"
#include "chat.hpp"
// hash of commands:
-#define CMD_NAME 210647350421
-#define CMD_CREATE 229394553991880
-
-const int cmd_num = 2;
-const char *commands[cmd_num] = {
- "/name",
- "/create"
- // /rooms - print all public rooms
-};
+#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 **ParseCommand(const char *input, int &arrc);
+char **ParseToArg(const char *input, int &arrc);
unsigned long hash(const char *str);
+struct cmd_info {
+ char name[15];
+ 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 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)
+
+ // IDEA: /clear - clear screen
+};
+
ChatRoom::~ChatRoom()
{
while(first) {
@@ -37,31 +58,18 @@ void ChatRoom::SendAll(const char *msg, ChatSession *except)
p->s->Send(msg);
}
-void ChatRoom::LeaveMessage(ChatSession *except)
-{
- if(it_lobby)
- return;
-
- const char left_msg[] = " has left the chat";
- const char *name = except->GetName();
-
- int len = strlen(name);
- char *lmsg = new char[len + sizeof(left_msg) + 2];
- sprintf(lmsg, "%s%s\n", name, left_msg);
- this->SendAll(lmsg, except);
- delete[] lmsg;
-}
-
void ChatRoom::HandleMessage(ChatSession *ses, const char *str)
{
if(str[0] == '/') { // if user sent a command
int argc = 0;
- char **argv = 0;
- argv = ParseCommand(str, argc);
-
+ char **argv = ParseToArg(str, argc);
this->HandleCommand(ses, argc, argv);
+
+ for(int i = 0; i < argc; i++)
+ delete[] argv[i];
+ delete[] argv;
}
- else if(!it_lobby) {
+ else if(code != std_id_lobby) {
char *msg = new char[max_msg_len];
sprintf(msg, "%s: %s\n", ses->GetName(), str);
@@ -71,54 +79,83 @@ void ChatRoom::HandleMessage(ChatSession *ses, const char *str)
}
}
-void ChatRoom::HandleCommand(ChatSession *s, int cmd_counter,
- char **commands)
+void ChatRoom::HandleCommand(ChatSession *ses, int count,
+ char **argvar)
{
- unsigned long cmd = -1;
- cmd = hash(commands[0]);
+ unsigned long hash_cmd = -1;
+ hash_cmd = hash(argvar[0]);
- switch(cmd)
- {
- case CMD_NAME: {
- if(!it_lobby) {
- s->Send("You can use this command only in lobby\n");
- break;
- }
+ int what_command = -1;
+ for(int i = 0; i < cmd_count; i++) {
+ if(cmd[i].name_hash == hash_cmd) {
+ what_command = i;
+ break;
+ }
+ }
- if(cmd_counter == 1) {
- s->Send("Usage: /name your_good_name\n");
- break;
- }
+ if(what_command == -1)
+ return ses->Send("#Unknown command. Use: /help\n");
- int len = strlen(commands[1]);
- if(len > max_name_len || len < 3) {
- s->Send("Incorrect name. Name length from 3 to 18 chars\n");
- break;
- }
+ 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";
+
+ // scope of command:
+ if(cmd[what_command].lobby_cmd == USE_IN_ROOM && code == std_id_lobby)
+ return ses->Send(onlyroom_msg);
+ else if(cmd[what_command].lobby_cmd == USE_IN_LOBBY && code != std_id_lobby)
+ return ses->Send(onlylobby_msg);
+
+ // right usage:
+ if(cmd[what_command].min_argc > count-1)
+ return ses->Send(cmd[what_command].usage);
- s->ChangeName(commands[1]);
+ // 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: {
- if(!it_lobby) {
- s->Send("You can use this command only in lobby\n");
- break;
- }
- if(!s->GetName()) {
- s->Send("Before you can use this command, use /name\n");
- break;
- }
+ int id = the_server->AddRoom();
- //int id = the_s->AddRoom();
- //the_s->AddSessionToRoom(s, id);
+ 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);
+ ses->Send(cmsg);
+ delete[] cmsg;
+ the_server->ChangeSessionRoom(this, ses, id);
+ break;
+ }
+ case CMD_JOIN: {
+ int id = atoi(argvar[1]);
+ bool success = false;
+ if(id >= 0)
+ success = the_server->ChangeSessionRoom(this, ses, id);
+
+ if(!success)
+ ses->Send("#Room with that id didn't exist\n");
+
+ break;
+ }
+ case CMD_EXIT: {
+ the_server->GotoLobby(this, ses);
break;
}
+ case CMD_ROOMS: {
- default: {
- s->Send("Unknown command. Use: /help\n");
break;
}
+ default: break;
}
}
@@ -128,10 +165,40 @@ void ChatRoom::AddSession(ChatSession *ses)
p->next = first;
p->s = ses;
first = p;
+
+ if(code == std_id_lobby)
+ return;
+
+ const char welcome_msg[] = "Welcome to the room #";
+ const char entered_msg[] = " has entered the room";
+
+ const char *name = ses->GetName();
+
+ char *wmsg = new char[sizeof(welcome_msg) + 2];
+ sprintf(wmsg, "#%s%d\n", 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);
+ this->SendAll(emsg, ses);
+ delete[] emsg;
+
}
void ChatRoom::RemoveSession(ChatSession *ses)
{
+ if(code != std_id_lobby) {
+ const char left_msg[] = " has left the room";
+ const char *name = ses->GetName();
+
+ int len = strlen(name);
+ char *lmsg = new char[len + sizeof(left_msg) + 2];
+ sprintf(lmsg, "#%s%s\n", name, left_msg);
+ this->SendAll(lmsg, ses);
+ delete[] lmsg;
+ }
+
item **p;
for(p = &first; *p; p = &((*p)->next)) {
if( ((*p)->s) == ses ) {
@@ -139,6 +206,10 @@ void ChatRoom::RemoveSession(ChatSession *ses)
*p = tmp->next;
// not delete ChatSession!
delete tmp;
+
+ if(code != std_id_lobby && !first)
+ the_server->DeleteRoom(code);
+
return;
}
}
@@ -146,13 +217,14 @@ void ChatRoom::RemoveSession(ChatSession *ses)
void ChatRoom::CloseSession(ChatSession *ses)
{
+ Server *serv = the_server;
this->RemoveSession(ses);
- the_server->CloseConnection(ses);
+ serv->CloseConnection(ses);
}
//////////////////////////////////////////////////////////////
-char **ParseCommand(const char *input, int &arrc)
+char **ParseToArg(const char *input, int &arrc)
{
int max_argv = 5;
arrc = 0;
@@ -161,12 +233,13 @@ char **ParseCommand(const char *input, int &arrc)
int start = 0;
for(int i = 0; i < (int) strlen(input)+1; i++) {
if(input[i] == ' ' || input[i] == '\0' || input[i] == '\n') { // end
- if(start == -1)
+ if(start == std_id_lobby)
continue;
int size = i - start;
- arr[arrc] = new char[size];
+ arr[arrc] = new char[size+1];
memcpy(arr[arrc], input + start, sizeof(char) * size);
+ arr[arrc][size] = '\0';
start = -1;
arrc++;
diff --git a/src/server/rooms.hpp b/src/server/rooms.hpp
index 08fffff..9423be1 100644
--- a/src/server/rooms.hpp
+++ b/src/server/rooms.hpp
@@ -1,12 +1,15 @@
#ifndef ROOMREALIZATION_H
#define ROOMREALIZATION_H
+const int std_id_lobby = -1;
+
class Server;
class ChatSession;
class ChatRoom {
Server *the_server;
- const bool it_lobby;
+ const int code;
+ // code == -1 it's lobby
struct item {
ChatSession *s;
@@ -14,15 +17,14 @@ class ChatRoom {
};
item *first;
public:
- ChatRoom(Server *i_server, bool i_lobby)
- : the_server(i_server), it_lobby(i_lobby), first(0) {}
+ ChatRoom(Server *i_server, int id)
+ : the_server(i_server), code(id), first(0) {}
~ChatRoom();
void SendAll(const char *msg, ChatSession *except = 0);
- void LeaveMessage(ChatSession *except);
void HandleMessage(ChatSession *ses, const char *str);
- void HandleCommand(ChatSession *s, int cmd_counter,
+ void HandleCommand(ChatSession *ses, int cmd_counter,
char **commands);
void AddSession(ChatSession *ses);