summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoursoir <chat@joursoir.net>2020-12-02 12:46:42 +0000
committerJoursoir <chat@joursoir.net>2020-12-02 12:46:42 +0000
commitad0a2dc909fbb772d42ab6faf13bba74fbc2483d (patch)
tree22e71f968850b7862331040f035c1125fdb44880
parenta6b8d6e475700efcb7ae1f7cdb7afeb2027fd4b7 (diff)
downloadwant-chat-ad0a2dc909fbb772d42ab6faf13bba74fbc2483d.tar.gz
want-chat-ad0a2dc909fbb772d42ab6faf13bba74fbc2483d.tar.bz2
want-chat-ad0a2dc909fbb772d42ab6faf13bba74fbc2483d.zip
try to make the code is easier; start work with db
-rw-r--r--src/server/ChatRoom.cpp (renamed from src/server/rooms.cpp)153
-rw-r--r--src/server/ChatRoom.hpp (renamed from src/server/rooms.hpp)24
-rw-r--r--src/server/ChatServer.cpp155
-rw-r--r--src/server/ChatServer.hpp63
-rw-r--r--src/server/Makefile10
-rw-r--r--src/server/UserInfo.cpp23
-rw-r--r--src/server/UserInfo.hpp55
-rw-r--r--src/server/UserInfo_io.cpp101
-rw-r--r--src/server/chat.cpp264
-rw-r--r--src/server/chat.hpp84
-rw-r--r--src/server/main.cpp29
-rw-r--r--src/server/server.cpp22
12 files changed, 535 insertions, 448 deletions
diff --git a/src/server/rooms.cpp b/src/server/ChatRoom.cpp
index ba1ee1b..a78670c 100644
--- a/src/server/rooms.cpp
+++ b/src/server/ChatRoom.cpp
@@ -2,9 +2,11 @@
#include <string.h>
#include <stdlib.h>
-#include "rooms.hpp"
-#include "chat.hpp"
+#include "ChatRoom.hpp"
+#include "ChatServer.hpp"
+#include "UserInfo.hpp"
+#define DB_BUFFER_SIZE 128
#define USE_IN_ROOM 0
#define USE_IN_LOBBY 1
#define USE_ANYWHERE 2
@@ -22,13 +24,15 @@ struct cmd_info {
char usage[64];
};
+const int cmd_id_help = 0;
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 int cmd_count = 5;
const struct cmd_info cmd[cmd_count] = {
+ {cmd_id_help, "/help", hash("/help"), USE_ANYWHERE, 0, "Usage: /help"},
{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"},
@@ -37,7 +41,7 @@ const struct cmd_info cmd[cmd_count] = {
// IDEA: /clear - clear screen
};
-ChatRoom::ChatRoom(Server *i_server, int id, char *pass)
+ChatRoom::ChatRoom(ChatServer *i_server, int id, char *pass)
: the_server(i_server), code(id), first(0)
{
if(pass)
@@ -50,53 +54,75 @@ ChatRoom::~ChatRoom()
while(first) {
item *tmp = first;
first = first->next;
- the_server->CloseConnection(tmp->s);
+ the_server->CloseConnection(tmp->u);
delete tmp;
}
}
-void ChatRoom::SendAll(const char *msg, ChatSession *except,
+void ChatRoom::SendAll(const char *msg, UserInfo *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, spec_msg);
+ if(p->u != except)
+ p->u->Send(msg, spec_msg);
}
-void ChatRoom::HandleMessage(ChatSession *ses, const char *str)
+void ChatRoom::HandleMessage(UserInfo *u, const char *str)
{
- int status = ses->state;
+ int status = u->GetStatus();
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);
+ u->Send("Incorrect name. Name length from 3 to 18 chars");
+ CloseSession(u);
}
if(checkForbiddenSymbols(str)) {
- ses->Send("Incorrect name. You use forbidden symbols.");
- CloseSession(ses);
+ u->Send("Incorrect name. You use forbidden symbols.");
+ CloseSession(u);
}
- 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;
+
+ //if(userInServer(char *nickname))
+ // проверить если кто-то с данным именем..
+
+ u->SetName(str);
+
+ char *msg = new char[DB_BUFFER_SIZE];
+ sprintf(msg, "SELECT password FROM users WHERE name = '%s' LIMIT 1", str);
+ CONSOLE_LOG("%s\n", msg);
+ AnswerDB *ans = the_server->QuerySelect(msg);
+ if(ans) {
+ DB_ROW *row = ans->GetNextRow();
+
+ char *pass = 0;
+ if(row) {
+ pass = new char[max_player_lenpass];
+ strcpy(pass, (*row)[0]);
+
+ CONSOLE_LOG("account exist! \n");
+ }
+ }
+ else CONSOLE_LOG("account noexist :( \n");
+ delete[] msg;
+
+ u->Send("Welcome to WantChat!");
+ u->Send(" ");
+ u->Send("It is 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(" ");
+
+ u->SetStatus(no_wait);
}
return;
@@ -105,7 +131,7 @@ void ChatRoom::HandleMessage(ChatSession *ses, const char *str)
if(str[0] == '/') { // if user sent a command
int argc = 0;
char **argv = ParseToArg(str, argc);
- this->HandleCommand(ses, argc, argv);
+ this->HandleCommand(u, argc, argv);
for(int i = 0; i < argc; i++)
delete[] argv[i];
@@ -113,16 +139,16 @@ 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", ses->GetName(), str);
+ sprintf(msg, "%s: %s", u->GetName(), str);
this->SendAll(msg, 0, usual_msg);
delete[] msg;
}
- else ses->Send("In the lobby you can only write commands");
+ else u->Send("In the lobby you can only write commands");
}
-void ChatRoom::HandleCommand(ChatSession *ses, int count,
+void ChatRoom::HandleCommand(UserInfo *u, int count,
char **argvar)
{
unsigned long hash_cmd = -1;
@@ -137,27 +163,31 @@ void ChatRoom::HandleCommand(ChatSession *ses, int count,
}
if(what_command == -1)
- return ses->Send("Unknown command. Use: /help");
+ return u->Send("Unknown command. Use: /help");
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)
- return ses->Send(onlyroom_msg);
+ return u->Send(onlyroom_msg);
else if(cmd[what_command].lobby_cmd == USE_IN_LOBBY && code != std_id_lobby)
- return ses->Send(onlylobby_msg);
+ return u->Send(onlylobby_msg);
// right usage:
if(cmd[what_command].min_argc > count-1)
- return ses->Send(cmd[what_command].usage);
+ return u->Send(cmd[what_command].usage);
switch(cmd[what_command].id) {
+ case cmd_id_help: {
+ u->Send("Help info...");
+ break;
+ }
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");
+ return u->Send("Maximum length of pass equals 24");
pass = argvar[1];
}
int id = the_server->AddRoom(pass);
@@ -167,28 +197,29 @@ void ChatRoom::HandleCommand(ChatSession *ses, int count,
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);
+ u->Send(cmsg);
delete[] cmsg;
- the_server->ChangeSessionRoom(this, ses, id, pass);
+ the_server->ChangeSessionRoom(this, u, id, pass);
break;
}
case cmd_id_join: {
int id = atoi(argvar[1]);
char *pass = argvar[2]; // if count == 2, then argvar[2] = 0
- int h_status = the_server->ChangeSessionRoom(this, ses, id, pass);
+ int h_status = the_server->ChangeSessionRoom(this, u, id, pass);
if(h_status == enter_noexist)
- return ses->Send("Room with that ID didn't exist");
+ return u->Send("Room with that ID didn't exist");
else if(h_status == enter_private)
- return ses->Send("It is private room, join using password");
+ return u->Send("It is private room, join using password");
else if(h_status == enter_uncorrect_pass)
- return ses->Send("Oops, this password is not valid");
+ return u->Send("Oops, this password is not valid");
+ u->Send("You has left the room");
break;
}
case cmd_id_exit: {
- the_server->GotoLobby(this, ses);
+ the_server->GotoLobby(this, u);
break;
}
case cmd_id_rooms: {
@@ -206,11 +237,11 @@ const char *ChatRoom::GetSecretPass()
return 0;
}
-void ChatRoom::AddSession(ChatSession *ses)
+void ChatRoom::AddSession(UserInfo *u)
{
item *p = new item;
p->next = first;
- p->s = ses;
+ p->u = u;
first = p;
if(code == std_id_lobby)
@@ -219,39 +250,39 @@ void ChatRoom::AddSession(ChatSession *ses)
const char welcome_msg[] = "Welcome to the room #";
const char entered_msg[] = " has entered the room";
- const char *name = ses->GetName();
+ const char *name = u->GetName();
char *wmsg = new char[sizeof(welcome_msg) + 2];
sprintf(wmsg, "%s%d", welcome_msg, code);
- ses->Send(wmsg);
+ u->Send(wmsg);
delete[] wmsg;
char *emsg = new char[strlen(name) + sizeof(entered_msg)];
sprintf(emsg, "%s%s", name, entered_msg);
- this->SendAll(emsg, ses);
+ this->SendAll(emsg, u);
delete[] emsg;
}
-void ChatRoom::RemoveSession(ChatSession *ses)
+void ChatRoom::RemoveSession(UserInfo *u)
{
if(code != std_id_lobby) {
const char left_msg[] = " has left the room";
- const char *name = ses->GetName();
+ const char *name = u->GetName();
int len = strlen(name);
char *lmsg = new char[len + sizeof(left_msg) + 2];
sprintf(lmsg, "%s%s", name, left_msg);
- this->SendAll(lmsg, ses);
+ this->SendAll(lmsg, u);
delete[] lmsg;
}
item **p;
for(p = &first; *p; p = &((*p)->next)) {
- if( ((*p)->s) == ses ) {
+ if( ((*p)->u) == u ) {
item *tmp = *p;
*p = tmp->next;
- // not delete ChatSession!
+ // not delete UserInfo!
delete tmp;
if(code != std_id_lobby && !first)
@@ -262,11 +293,11 @@ void ChatRoom::RemoveSession(ChatSession *ses)
}
}
-void ChatRoom::CloseSession(ChatSession *ses)
+void ChatRoom::CloseSession(UserInfo *u)
{
- Server *serv = the_server;
- this->RemoveSession(ses);
- serv->CloseConnection(ses);
+ ChatServer *serv = the_server;
+ this->RemoveSession(u);
+ serv->CloseConnection(u);
}
//////////////////////////////////////////////////////////////
diff --git a/src/server/rooms.hpp b/src/server/ChatRoom.hpp
index 4d71d0b..a9e2492 100644
--- a/src/server/rooms.hpp
+++ b/src/server/ChatRoom.hpp
@@ -5,38 +5,38 @@
const int std_id_lobby = -1;
const int max_room_lenpass = 24;
+const int max_player_lenpass = 24;
-class Server;
-class ChatSession;
+class ChatServer;
+class UserInfo;
class ChatRoom {
- Server *the_server;
+ ChatServer *the_server;
const int code;
// if code == std_id_lobby then it's lobby
-
char secret_pass[max_room_lenpass];
struct item {
- ChatSession *s;
+ UserInfo *u;
item *next;
};
item *first;
public:
- ChatRoom(Server *i_server, int id, char *pass);
+ ChatRoom(ChatServer *i_server, int id, char *pass);
~ChatRoom();
- void SendAll(const char *msg, ChatSession *except = 0,
+ void SendAll(const char *msg, UserInfo *except = 0,
const int spec_msg = system_msg);
- void HandleMessage(ChatSession *ses, const char *str);
- void HandleCommand(ChatSession *ses, int cmd_counter,
+ void HandleMessage(UserInfo *u, const char *str);
+ void HandleCommand(UserInfo *u, int cmd_counter,
char **commands);
const char *GetSecretPass();
- void AddSession(ChatSession *ses);
- void RemoveSession(ChatSession *ses);
- void CloseSession(ChatSession *ses);
+ void AddSession(UserInfo *u);
+ void RemoveSession(UserInfo *u);
+ void CloseSession(UserInfo *u);
};
#endif \ No newline at end of file
diff --git a/src/server/ChatServer.cpp b/src/server/ChatServer.cpp
new file mode 100644
index 0000000..6256e55
--- /dev/null
+++ b/src/server/ChatServer.cpp
@@ -0,0 +1,155 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "ChatServer.hpp"
+#include "UserInfo.hpp"
+#include "ChatRoom.hpp"
+
+const int qlen_for_listen = 6;
+
+ChatServer::ChatServer(EventSelector *sel, DatabaseManager *db, int fd)
+ : FdHandler(fd), the_selector(sel), dbase(db)
+{
+ the_selector->Add(this);
+ lobby = new ChatRoom(this, std_id_lobby, 0);
+}
+
+ChatServer::~ChatServer()
+{
+ if(room)
+ delete[] room;
+
+ the_selector->Remove(this);
+}
+
+ChatServer *ChatServer::Start(EventSelector *sel, DatabaseManager *db, int port)
+{
+ int in_d = socket(AF_INET, SOCK_STREAM, 0);
+ if(in_d == -1)
+ return 0;
+
+ int opt = 1;
+ setsockopt(in_d, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+
+ struct sockaddr_in addr;
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_port = htons(port);
+
+ int res = bind(in_d, (struct sockaddr*) &addr, sizeof(addr));
+ if(res == -1)
+ return 0;
+
+ res = listen(in_d, qlen_for_listen);
+ if(res == -1)
+ return 0;
+
+ return new ChatServer(sel, db, in_d);
+}
+
+int ChatServer::AddRoom(char *password)
+{
+ if(!room) {
+ room_len = 16;
+ room = new ChatRoom*[room_len];
+ for(int i = 0; i < room_len; i++)
+ room[i] = 0;
+ }
+
+ int id = -1;
+ for(int i = 0; i < room_len; i++) {
+ if(room[i] == 0) {
+ id = i;
+ room[i] = new ChatRoom(this, id, password);
+ break;
+ }
+ }
+
+ if(id == -1) {
+ ChatRoom **tmp = new ChatRoom*[room_len+1];
+ for(int i = 0; i < room_len; i++)
+ tmp[i] = room[i];
+
+ id = room_len;
+ tmp[room_len] = new ChatRoom(this, id, password);
+ room_len += 1;
+
+ delete[] room;
+ room = tmp;
+ }
+
+ return id;
+}
+
+bool ChatServer::DeleteRoom(int id)
+{
+ if(!room[id])
+ return false;
+
+ delete room[id];
+ room[id] = 0;
+
+ return true;
+}
+
+bool ChatServer::RoomExist(int id) const
+{
+ if(!room[id])
+ return false;
+
+ return true;
+}
+
+void ChatServer::GotoLobby(ChatRoom *cur_room, UserInfo *u)
+{
+ cur_room->RemoveSession(u);
+ lobby->AddSession(u);
+ u->SetRoom(lobby);
+}
+
+handle_room_enter ChatServer::ChangeSessionRoom(ChatRoom *cur_room,
+ UserInfo *u, int id, char *pass)
+{
+ if(id < 0 || id >= room_len || !room[id])
+ return enter_noexist;
+
+ const char *secret_word = room[id]->GetSecretPass();
+ CONSOLE_LOG("right pass: %s; user enter 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(u);
+ room[id]->AddSession(u);
+ u->SetRoom(room[id]);
+ return enter_success;
+}
+
+void ChatServer::CloseConnection(UserInfo *u)
+{
+ the_selector->Remove(u);
+ delete u;
+}
+
+void ChatServer::Handle(bool r, bool w)
+{
+ if(!r)
+ return;
+
+ struct sockaddr_in addr;
+ socklen_t len = sizeof(addr);
+ int sd = accept(GetFd(), (struct sockaddr*) &addr, &len);
+ if(sd == -1)
+ return;
+
+ UserInfo *u = new UserInfo(lobby, sd);
+ lobby->AddSession(u);
+ the_selector->Add(u);
+} \ No newline at end of file
diff --git a/src/server/ChatServer.hpp b/src/server/ChatServer.hpp
new file mode 100644
index 0000000..e2ef154
--- /dev/null
+++ b/src/server/ChatServer.hpp
@@ -0,0 +1,63 @@
+#ifndef WC_CHATSERVER_H
+#define WC_CHATSERVER_H
+
+#include "sockets.hpp"
+#include "database.hpp"
+#include "../const_vars.hpp"
+
+#define CONSOLE_LOG(f_, ...) printf((f_), ##__VA_ARGS__)
+
+enum handle_room_enter {
+ enter_noexist,
+ enter_private,
+ enter_uncorrect_pass,
+ enter_success
+};
+
+class ChatRoom;
+class UserInfo;
+
+class ChatServer : public FdHandler {
+ EventSelector *the_selector;
+ DatabaseManager *dbase;
+
+ ChatRoom **room;
+ int room_len;
+ ChatRoom *lobby;
+
+ ChatServer(EventSelector *sel, DatabaseManager *db, int fd);
+public:
+ ~ChatServer();
+ static ChatServer *Start(EventSelector *sel,
+ DatabaseManager *db, int fd);
+
+ int AddRoom(char *password);
+ bool DeleteRoom(int id); // call only if room is empty
+ bool RoomExist(int id) const;
+
+ void GotoLobby(ChatRoom *cur_room, UserInfo *u);
+ handle_room_enter ChangeSessionRoom(ChatRoom *cur_room,
+ UserInfo *u, int id, char *pass);
+
+ void CloseConnection(UserInfo *u);
+
+ // work with database:
+ AnswerDB *QuerySelect(const char *sql)
+ { return dbase->QuerySelect(sql); }
+
+private:
+ virtual void Handle(bool r, bool w);
+};
+
+/*class StorageOfUsers {
+ struct item {
+ ChatSession *s;
+ item *next;
+ }
+ item *first;
+public:
+ AddSession(ChatSession *s);
+ RemoveSession(ChatSession *s);
+};*/
+
+#endif \ No newline at end of file
diff --git a/src/server/Makefile b/src/server/Makefile
index be312d7..03836e8 100644
--- a/src/server/Makefile
+++ b/src/server/Makefile
@@ -1,6 +1,6 @@
CPP = g++
-CPPFLAGS = -Wall -g
-SOURCES = server.cpp sockets.cpp chat.cpp rooms.cpp
+CPPFLAGS = -Wall -g $(shell mariadb_config --cflags --libs)
+SOURCES = main.cpp sockets.cpp ChatServer.cpp UserInfo.cpp UserInfo_io.cpp ChatRoom.cpp database.cpp
OBJECTS = $(SOURCES:.cpp=.o)
EXECUTABLE = server
@@ -9,10 +9,10 @@ EXECUTABLE = server
all: $(EXECUTABLE)
clean:
- rm -rf $(OBJECTS) $(EXECUTABLE)
+ @rm -rf $(OBJECTS) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
- $(CPP) $(CPPFLAGS) -o $(EXECUTABLE) $(OBJECTS)
+ @$(CPP) $(CPPFLAGS) -o $(EXECUTABLE) $(OBJECTS)
$(OBJECTS):
- $(CPP) -c $(CPPFLAGS) $(SOURCES) \ No newline at end of file
+ @$(CPP) -c $(CPPFLAGS) $(SOURCES) \ No newline at end of file
diff --git a/src/server/UserInfo.cpp b/src/server/UserInfo.cpp
new file mode 100644
index 0000000..e7c0334
--- /dev/null
+++ b/src/server/UserInfo.cpp
@@ -0,0 +1,23 @@
+#include "UserInfo.hpp"
+
+void UserInfo::SetRoom(ChatRoom *new_master)
+{
+ this->the_master = new_master;
+}
+
+const char *UserInfo::GetName() const
+{
+ if(name[0])
+ return name;
+ return 0;
+}
+
+void UserInfo::SetName(const char *n_name)
+{
+ strcpy(name, n_name);
+}
+
+void UserInfo::SetStatus(const enum_status e_s)
+{
+ state = e_s;
+}
diff --git a/src/server/UserInfo.hpp b/src/server/UserInfo.hpp
new file mode 100644
index 0000000..e033b0c
--- /dev/null
+++ b/src/server/UserInfo.hpp
@@ -0,0 +1,55 @@
+#ifndef WC_USER_H
+#define WC_USER_H
+
+#include <string.h>
+
+#include "sockets.hpp"
+#include "ChatRoom.hpp"
+#include "../const_vars.hpp"
+
+class ChatServer;
+
+enum enum_status {
+ wait_name, // expecting a username from player
+ wait_reg, // expecting registration
+ wait_log, // expecting login
+ no_wait
+};
+
+#define CONSOLE_LOG(f_, ...) printf((f_), ##__VA_ARGS__) // delete later
+
+class UserInfo : FdHandler {
+ friend class ChatServer;
+
+ char name[max_name_len];
+ char buffer[max_msg_len];
+ int buf_used;
+ bool ignoring;
+
+ enum_status state;
+ ChatRoom *the_master;
+
+ UserInfo(ChatRoom *i_master, int i_fd) : FdHandler(i_fd),
+ buf_used(0), ignoring(false), state(wait_name),
+ the_master(i_master) {}
+ ~UserInfo() {}
+
+ void SetRoom(ChatRoom *new_master);
+
+ // === realization in UserInfo_io.cpp ===
+ virtual void Handle(bool r, bool w); // w disabled, only read
+ void ReadAndIgnore();
+ void ReadAndCheck();
+ void CheckLines();
+public:
+ void Send(const char *msg, const int spec_msg = system_msg);
+ // === realization in UserInfo_io.cpp ===
+
+ const char *GetName() const;
+ void SetName(const char *n_name);
+
+ enum_status GetStatus() const { return state; }
+ void SetStatus(const enum_status e_s);
+};
+
+#endif \ No newline at end of file
diff --git a/src/server/UserInfo_io.cpp b/src/server/UserInfo_io.cpp
new file mode 100644
index 0000000..d4d308a
--- /dev/null
+++ b/src/server/UserInfo_io.cpp
@@ -0,0 +1,101 @@
+#include <stdio.h>
+
+#include "UserInfo.hpp"
+
+void UserInfo::Handle(bool r, bool w)
+{
+ if(!r)
+ return;
+
+ // this functions create for support any client, not one WantChat client:
+ if(buf_used >= (int)sizeof(buffer)) {
+ buf_used = 0;
+ ignoring = true;
+ }
+ if(ignoring) {
+ CONSOLE_LOG("Ignore the message, it's so big\n");
+ ReadAndIgnore();
+ }
+ else
+ ReadAndCheck();
+}
+
+void UserInfo::ReadAndIgnore()
+{
+ int rc = read(GetFd(), buffer, sizeof(buffer));
+ CONSOLE_LOG("readI return %d bytes\n", rc);
+ if(rc < 1) {
+ the_master->CloseSession(this);
+ return;
+ }
+
+ for(int i = 0; i < rc; i++)
+ if(buffer[i] == '\n')
+ { // stop ignoring!
+ CONSOLE_LOG("ReadAndIgnore: find \\n\n");
+ int rest = rc - i - 1;
+ if(rest > 0)
+ memmove(buffer, buffer + i + 1, rest);
+ buf_used = rest;
+ ignoring = 0;
+ CheckLines();
+ }
+}
+
+void UserInfo::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->CloseSession(this);
+ return;
+ }
+ buf_used += rc;
+ CheckLines();
+}
+
+void UserInfo::CheckLines()
+{
+ if(buf_used <= 0)
+ return;
+
+ for(int i = 0; i < buf_used; i++) {
+ if(buffer[i] == '\n') {
+ CONSOLE_LOG("[CheckLines] buffer[i] == \\n i = %d\n", i);
+ buffer[i] = 0;
+ if(i > 0 && buffer[i-1] == '\r')
+ buffer[i-1] = 0;
+
+ CONSOLE_LOG("printed: %s\n", buffer);
+ the_master->HandleMessage(this, buffer);
+
+ int rest = buf_used - i - 1;
+ memmove(buffer, buffer + i + 1, rest);
+ buf_used = rest;
+ CONSOLE_LOG("[CheckLines] new buf_used = %d\n", buf_used);
+ CheckLines();
+ return;
+ }
+ }
+}
+
+void UserInfo::Send(const char *msg, const int spec_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;
+}
+
diff --git a/src/server/chat.cpp b/src/server/chat.cpp
deleted file mode 100644
index 561a61d..0000000
--- a/src/server/chat.cpp
+++ /dev/null
@@ -1,264 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#include "chat.hpp"
-#include "rooms.hpp"
-
-const int qlen_for_listen = 6;
-
-void ChatSession::Send(const char *msg, const int spec_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)
-{
- if(!r)
- return;
-
- // this functions create for support any client, not one WantChat client:
- if(buf_used >= (int)sizeof(buffer)) {
- buf_used = 0;
- ignoring = true;
- }
- if(ignoring) {
- CONSOLE_LOG("Ignore the message, it's so big\n");
- ReadAndIgnore();
- }
- else
- ReadAndCheck();
-}
-
-void ChatSession::ReadAndIgnore()
-{
- int rc = read(GetFd(), buffer, sizeof(buffer));
- CONSOLE_LOG("readI return %d bytes\n", rc);
- if(rc < 1) {
- the_master->CloseSession(this);
- return;
- }
-
- for(int i = 0; i < rc; i++)
- if(buffer[i] == '\n')
- { // stop ignoring!
- CONSOLE_LOG("ReadAndIgnore: find \\n\n");
- int rest = rc - i - 1;
- if(rest > 0)
- memmove(buffer, buffer + i + 1, rest);
- buf_used = rest;
- ignoring = 0;
- CheckLines();
- }
-}
-
-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->CloseSession(this);
- return;
- }
- buf_used += rc;
- CheckLines();
-}
-
-void ChatSession::CheckLines()
-{
- if(buf_used <= 0)
- return;
-
- for(int i = 0; i < buf_used; i++) {
- if(buffer[i] == '\n') {
- CONSOLE_LOG("[CheckLines] buffer[i] == \\n i = %d\n", i);
- buffer[i] = 0;
- if(i > 0 && buffer[i-1] == '\r')
- buffer[i-1] = 0;
-
- CONSOLE_LOG("printed: %s\n", buffer);
- the_master->HandleMessage(this, buffer);
-
- int rest = buf_used - i - 1;
- memmove(buffer, buffer + i + 1, rest);
- buf_used = rest;
- CONSOLE_LOG("[CheckLines] new buf_used = %d\n", buf_used);
- CheckLines();
- return;
- }
- }
-}
-
-const char *ChatSession::GetName()
-{
- if(name[0])
- return name;
- return 0;
-}
-
-void ChatSession::SetName(const char *n_name)
-{
- strcpy(name, n_name);
-}
-
-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, std_id_lobby, 0);
-}
-
-Server::~Server()
-{
- if(room)
- delete[] room;
-
- the_selector->Remove(this);
-}
-
-Server *Server::Start(EventSelector *sel, int port)
-{
- int in_d = socket(AF_INET, SOCK_STREAM, 0);
- if(in_d == -1)
- return 0;
-
- int opt = 1;
- setsockopt(in_d, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
-
- struct sockaddr_in addr;
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- addr.sin_port = htons(port);
-
- int res = bind(in_d, (struct sockaddr*) &addr, sizeof(addr));
- if(res == -1)
- return 0;
-
- res = listen(in_d, qlen_for_listen);
- if(res == -1)
- return 0;
-
- 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)
- return;
-
- struct sockaddr_in addr;
- socklen_t len = sizeof(addr);
- int sd = accept(GetFd(), (struct sockaddr*) &addr, &len);
- if(sd == -1)
- return;
-
- ChatSession *s = new ChatSession(lobby, sd);
- lobby->AddSession(s);
- the_selector->Add(s);
-}
-
-int Server::AddRoom(char *password)
-{
- if(!room) {
- room_len = 16;
- room = new ChatRoom*[room_len];
- for(int i = 0; i < room_len; i++)
- room[i] = 0;
- }
-
- int id = -1;
- for(int i = 0; i < room_len; i++) {
- if(room[i] == 0) {
- id = i;
- room[i] = new ChatRoom(this, id, password);
- break;
- }
- }
-
- if(id == -1) {
- ChatRoom **tmp = new ChatRoom*[room_len+1];
- for(int i = 0; i < room_len; i++)
- tmp[i] = room[i];
-
- id = room_len;
- tmp[room_len] = new ChatRoom(this, id, password);
- 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);
-}
-
-handle_room_enter Server::ChangeSessionRoom(ChatRoom *cur_room,
- ChatSession *s, int id, char *pass)
-{
- 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 enter_success;
-} \ No newline at end of file
diff --git a/src/server/chat.hpp b/src/server/chat.hpp
deleted file mode 100644
index 4b6c8b1..0000000
--- a/src/server/chat.hpp
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef CHATREALIZATION_H
-#define CHATREALIZATION_H
-
-#include "sockets.hpp"
-#include "../const_vars.hpp"
-
-#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), state(wait_name),
- the_master(i_master) {}
- ~ChatSession() {}
-
- void SetRoom(ChatRoom *new_master);
-
- virtual void Handle(bool r, bool w);
- void ReadAndIgnore();
- void ReadAndCheck();
- void CheckLines();
-public:
- const char *GetName();
-
- void SetName(const char *n_name);
- void Send(const char *msg, const int spec_msg = system_msg);
-};
-
-class Server : public FdHandler {
- EventSelector *the_selector;
- ChatRoom **room;
- 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(char *password);
- bool DeleteRoom(int id); // call only if room is empty
-
- void GotoLobby(ChatRoom *cur_room, ChatSession *s);
- handle_room_enter ChangeSessionRoom(ChatRoom *cur_room,
- ChatSession *s, int id, char *pass);
- void CloseConnection(ChatSession *s)
- { the_selector->Remove(s); delete s; }
-private:
- virtual void Handle(bool r, bool w);
-};
-
-
-#endif \ No newline at end of file
diff --git a/src/server/main.cpp b/src/server/main.cpp
new file mode 100644
index 0000000..2d0fea8
--- /dev/null
+++ b/src/server/main.cpp
@@ -0,0 +1,29 @@
+#include <stdio.h>
+
+#include "ChatServer.hpp"
+#include "database.hpp"
+#include "../config.hpp"
+
+int main(int argc, char *argv[])
+{
+ /* Event-driven programming */
+ /*
+ 1) selection event
+ 2) event handling
+ */
+ DatabaseManager *db = DatabaseManager::Connect(DATABASE_HOST, DATABASE_USER,
+ DATABASE_PASSWD, DATABASE_DB, DATABASE_PORT);
+ if(!db) {
+ perror("database");
+ return 1;
+ }
+
+ EventSelector *selector = new EventSelector;
+ ChatServer *serv = ChatServer::Start(selector, db, SERVER_PORT);
+ if(!serv) {
+ perror("server");
+ return 1;
+ }
+ selector->Run();
+ return 0;
+} \ No newline at end of file
diff --git a/src/server/server.cpp b/src/server/server.cpp
deleted file mode 100644
index ab7c420..0000000
--- a/src/server/server.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <stdio.h>
-
-#include "chat.hpp"
-
-const int port = 3030;
-
-int main(int argc, char *argv[])
-{
- /* Event-driven programming */
- /*
- 1) selection event
- 2) event handling
- */
- EventSelector *selector = new EventSelector;
- Server *serv = Server::Start(selector, port);
- if(!serv) {
- perror("server");
- return 1;
- }
- selector->Run();
- return 0;
-} \ No newline at end of file