Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <algorithm>
- #include <fstream>
- #include <thread>
- #include <vector>
- #include <string>
- #include <mutex>
- #include <sstream>
- #include <ctime>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <string.h>
- #include <stdlib.h>
- #include <openssl/sha.h>
- #include <pqxx/pqxx>
- using namespace pqxx;
- connection database("dbname = the_hole user = postgres password = the_hole hostaddr = 127.0.0.1 port = 5432");
- nontransaction executioner(database);
- #define MAX_CONNECTIONS 128
- using namespace std;
- /*message base started*/
- char welcome[]="Welcome to Kronbash ltd overpowered and oversecured chat-server\n\
- TTTTT H H EEEEE H H OOO L EEEEE\n\
- T H H E H H OO OO L E \n\
- T HHHHH EEEEE HHHHH O O L EEEEE\n\
- T H H E H H OO OO L E \n\
- T H H EEEEE H H OOO LLLLL EEEEE\n\
- To call help send /HELP\n\
- ";
- char help_str[]="\
- /CREATE <username> <nickname> <password> -- register account\n\
- /USER <username> -- start identifying and set account name\n\
- /PASS <password> -- continue identifying and set account password\n\
- /DROP -- delete your account\n\
- /MSG <user> <prwmesg>-- send private message\n\
- /RESTORE <public/private> -- show you your private/all public messages\n\
- /INFO <user>-- show info about user\n\
- /QUIT -- exit from server\n\
- /LIST -- show nicknames on server\n\
- ";
- char help_admin_str[]="\
- /SETPASS <nickname> <password> -- change password anyone you want.\n";
- /*message base ended*/
- vector<string> split_str_by_space(string& str) {
- vector<string> parameters;
- string buffer;
- stringstream ss(str);
- while (ss >> buffer)
- parameters.push_back(buffer);
- return parameters;
- }
- struct user{
- string nickname;
- int socket;
- bool is_operator;
- string username;
- bool is_identified;
- char sha1_pass[SHA_DIGEST_LENGTH];
- };
- mutex users_base_lock;
- vector<user>users_base;
- mutex clients_lock;
- vector<int>clients;
- void disconnect(int Socket,string nickname){
- clients_lock.lock();
- shutdown(Socket,SHUT_RDWR);
- close(Socket);
- for(unsigned int i=0;i<clients.size();i++){
- if(clients[i]==Socket){
- clients.erase(clients.begin()+i);
- break;
- }
- }
- clients_lock.unlock();
- if(nickname==""){
- nickname="nobody";
- }
- cout << "SYSTEM: No." << Socket << "(" << nickname << ")" <<" disconnected\n";
- }
- int get_user_id(string name){
- for(unsigned int i=0;i<users_base.size();i++){
- if(name==users_base[i].nickname){
- return i;
- }
- }
- return -1;
- }
- mutex message_base_lock;
- struct message{
- int id; //номер записи во внутренней бд
- string message;
- };
- vector<message>message_base;
- mutex pmessage_base_lock;
- struct pmessage{
- string sender;
- string recipient;
- string message;
- };
- vector<pmessage>pmessage_base;
- bool stop_server=false;
- void message_sender(){
- char message[256];
- while(1){
- while(message_base.size()>0){
- memset(message,0,256);
- message_base_lock.lock();
- strcpy(message,message_base[0].message.c_str());
- message_base.erase(message_base.begin());
- message_base_lock.unlock();
- for(unsigned int i=0;i<clients.size();i++){
- if(clients[i]!=message_base[0].id){
- send(clients[i],message,strlen(message),MSG_NOSIGNAL);
- }
- }
- }
- while(pmessage_base.size()>0){
- pmessage_base_lock.lock();
- string pmessage=pmessage_base[0].message;
- string recipient=pmessage_base[0].recipient;
- pmessage_base.erase(pmessage_base.begin());
- pmessage_base_lock.unlock();
- for(unsigned int i=0;i<users_base.size();i++){
- if(users_base[i].nickname==recipient && users_base[i].is_identified){
- send(users_base[i].socket,pmessage.c_str(),strlen(pmessage.c_str()),MSG_NOSIGNAL);
- }
- }
- }
- if(stop_server)
- break;
- usleep(1000000);
- }
- }
- mutex pmessage_file;
- mutex message_file;
- mutex users_file;
- void connected(int Socket)
- {
- user temp_user;
- memset(&temp_user,0,sizeof(temp_user));
- char buf[256];
- string command;
- vector<string>args;
- while(1){
- if(stop_server){
- send(Socket,"Server stopped. See you later!\n",strlen("Server stopped. See you later!\n"),MSG_NOSIGNAL);
- break;
- }
- command="";
- args.clear();
- memset(buf,0,256);
- int RecvSize = recv(Socket,buf,256,MSG_NOSIGNAL);
- if((RecvSize==0)&&(errno!=EAGAIN)){
- break;
- }else if(RecvSize>0){
- command=(string)buf;
- args=split_str_by_space(command);
- if(args.size()==0){
- continue;
- }
- if(args[0]=="/LIST"){
- for(int i=0;i<users_base.size();i++){
- send(Socket,users_base[i].nickname.c_str(),strlen(users_base[i].nickname.c_str()),MSG_NOSIGNAL);
- send(Socket,"\n",1,MSG_NOSIGNAL);
- }
- }
- else if(args[0]=="/USER"){
- if(args.size()<2){
- send(Socket,"Error: wrong input format.\n",strlen("Error: wrong input format.\n"),MSG_NOSIGNAL);
- continue;
- }
- bool user_found=false;
- for(int i=0;i<users_base.size();i++){
- if(users_base[i].username==args[1]){
- if(users_base[i].is_identified){
- send(Socket,"Error: This user already entered.\n",strlen("Error: This user already entered.\n"),MSG_NOSIGNAL);
- continue;
- }
- send(Socket,"Success: Username found. Enter password for identifying(/PASS <pass>).\n",strlen("Success: Username found. Enter password for identifying(/PASS <pass>).\n"),MSG_NOSIGNAL);
- temp_user.username=users_base[i].username;
- user_found=true;
- break;
- }
- }
- if(!user_found){
- send(Socket,"Error: username not found.\n",strlen("Error: username not found.\n"),MSG_NOSIGNAL);
- }
- }
- else if(args[0]=="/PASS"){
- if(args.size()<2){
- send(Socket,"Error: wrong input format.\n",strlen("Error: wrong input format.\n"),MSG_NOSIGNAL);
- continue;
- }
- if(temp_user.username!=""){
- for(int i=0;i<users_base.size();i++){
- if(users_base[i].username==temp_user.username){
- unsigned char temp[SHA_DIGEST_LENGTH];
- unsigned char* str=(unsigned char*)args[1].c_str();
- SHA1((const unsigned char*)str,strlen((const char*)str),temp);
- if(strncmp(users_base[i].sha1_pass,(const char*)temp,20)==0){
- send(Socket,"Success: Correct password. You identifyied in system.\n",strlen("Success: Correct password. You identifyied in system.\n"),MSG_NOSIGNAL);
- temp_user.is_identified=true;
- temp_user.socket=Socket;
- users_base[i].socket=Socket;
- temp_user.nickname=users_base[i].nickname;
- users_base[i].is_identified=true;
- temp_user.is_operator=users_base[i].is_operator;
- }else{
- send(Socket,"Error: wrong password.\n",strlen("Error: wrong password.\n"),MSG_NOSIGNAL);
- }
- break;
- }
- }
- }else{
- send(Socket,"Error:you didn't set username.Try to set it before inputting password.\n",strlen("Error:you didn't set username.Try to set it before inputting password.\n"),MSG_NOSIGNAL);
- }
- }
- else if(args[0]=="/CREATE"){
- if(args.size()<4){
- send(Socket,"Error:wrong input format.\n",strlen("Error:wrong input format.\n"),MSG_NOSIGNAL);
- continue;
- }
- bool user_found=false;
- for(unsigned int i=0;i<users_base.size();i++){
- if(args[1]==users_base[i].username || args[2]==users_base[i].nickname){
- send(Socket,"Error: This username or nickname already registred. Try another name.\n",strlen("Error: This username or nickname already registred. Try another name.\n"),MSG_NOSIGNAL);
- user_found=true;
- break;
- }
- }
- if(user_found){
- continue;
- }
- temp_user.is_operator=false;
- temp_user.socket=0;
- temp_user.is_identified=0;
- temp_user.nickname=args[2];
- temp_user.username=args[1];
- unsigned char* str=(unsigned char*)args[3].c_str();
- SHA1((const unsigned char*)str,strlen((const char*)str),(unsigned char*)temp_user.sha1_pass);
- temp_user.socket=Socket;
- cout << "SYSTEM: user " << temp_user.nickname << " created.\n";
- users_base_lock.lock();
- users_base.push_back(temp_user);
- users_base_lock.unlock();
- users_file.lock();
- string isop="false";
- if(temp_user.is_operator)
- isop="true";
- executioner.exec("INSERT INTO users_base (nickname,is_operator,username,sha1_pass) VALUES ('"+temp_user.nickname+"','"+isop+"','"+temp_user.username+"','somesha1')");
- /*
- ofstream ufout;
- ufout.open("users",ios_base::app);
- ufout << temp_user.username << ' ' << temp_user.nickname << ' ' << "JUNK_NOT_PASSWORD";
- if(temp_user.is_operator)
- ufout << " 1\n";
- else
- ufout << " 0\n";
- ufout.close();
- */
- users_file.unlock();
- send(Socket,"Success: User successfully created.\n",strlen("Success: User successfully created.\n"),MSG_NOSIGNAL);
- }
- else if(args[0]=="/INFO"){
- if(args.size()<2){
- send(Socket,"Error: wrong input format.\n",strlen("Error: wrong input format.\n"),MSG_NOSIGNAL);
- continue;
- }
- int i=get_user_id(args[1]);
- if(i==-1){
- send(Socket,"Error: User not found\n",strlen("Error: User not found\n"),MSG_NOSIGNAL);
- continue;
- }
- send(Socket,"Username:",strlen("Username:"),MSG_NOSIGNAL);
- send(Socket,users_base[i].username.c_str(),strlen(users_base[i].username.c_str()),MSG_NOSIGNAL);
- send(Socket,"\nNickname:",strlen("\nNickname:"),MSG_NOSIGNAL);
- send(Socket,users_base[i].nickname.c_str(),strlen(users_base[i].nickname.c_str()),MSG_NOSIGNAL);
- send(Socket,"\n",strlen("\n"),MSG_NOSIGNAL);
- }
- else if(args[0]=="/QUIT"){
- break;
- }
- else if(args[0]=="/HELP"){
- send(Socket,help_str,strlen(help_str),MSG_NOSIGNAL);
- if(temp_user.is_operator){
- send(Socket,help_admin_str,strlen(help_admin_str),MSG_NOSIGNAL);
- }
- }
- else if(temp_user.is_identified){
- if(args[0]=="/MSG"){
- if (args.size() < 3){
- send(Socket,"Error:wrong input format\n",strlen("Error:wrong input format\n"),MSG_NOSIGNAL);
- continue;
- }
- pmessage temp_pmessage;
- temp_pmessage.recipient=args[1];
- temp_pmessage.sender=temp_user.nickname;
- temp_pmessage.message="From "+temp_user.nickname+" to "+temp_pmessage.recipient+":";
- for(int i=2;i<args.size();i++){
- temp_pmessage.message+=" "+args[i];
- }
- temp_pmessage.message+="\n";
- pmessage_file.lock();
- ofstream pmfout;
- pmfout.open("private_messages",ios_base::app);
- pmfout << temp_pmessage.message;
- pmfout.close();
- executioner.exec("INSERT INTO pmessage_base (recipient,sender,message) VALUES ('"+args[1]+"','"+temp_user.nickname+"','"+temp_pmessage.message+"')");
- pmessage_file.unlock();
- pmessage_base_lock.lock();
- pmessage_base.push_back(temp_pmessage);
- pmessage_base_lock.unlock();
- send(Socket,"Success: private message sended.\n",strlen("Success: private message sended.\n"),MSG_NOSIGNAL);
- }
- else if(args[0]=="/RESTORE"){
- if (args.size() < 2){
- send(Socket,"Error:wrong input format\n",strlen("Error:wrong input format\n"),MSG_NOSIGNAL);
- continue;
- }
- if (args[1]=="private"){
- pmessage_file.lock();
- result data(executioner.exec("SELECT * FROM pmessage_base WHERE recipient = '"+temp_user.nickname+"' OR sender = '"+temp_user.nickname+"')"));
- for (result::const_iterator c = data.begin(); c != data.end(); ++c) {
- string message=c[0].as<string>()+"\n";
- send(Socket,message.c_str(),strlen(message.c_str()),MSG_NOSIGNAL);
- }
- pmessage_file.unlock();
- }else if(args[1]=="public"){
- message_file.lock();
- result data(executioner.exec("SELECT message FROM message_base"));
- for (result::const_iterator c = data.begin(); c != data.end(); ++c) {
- string message=c[0].as<string>()+"\n";
- send(Socket,message.c_str(),strlen(message.c_str()),MSG_NOSIGNAL);
- }
- message_file.unlock();
- }else{
- send(Socket,"Error:only private\\public chat bases avaliable!",strlen("Error:only private\\public chat bases avaliable!"),MSG_NOSIGNAL);
- }
- }
- else if(args[0]=="/DROP"){
- if (temp_user.username=="admin"){
- send(Socket,"nope\n",strlen("nope\n"),MSG_NOSIGNAL);
- continue;
- }
- for(int i=0;i<users_base.size();i++){
- if(users_base[i].username==temp_user.username){
- users_base.erase(users_base.begin()+i);
- send(Socket,"Success: User deleted.\n",strlen("Success: User deleted.\n"),MSG_NOSIGNAL);
- executioner.exec("DELETE FROM users_base WHERE username = '"+temp_user.username+"';");
- cout << "SYSTEM: User " << temp_user.username << " dropped and disconnected.\n";
- break;
- }
- }
- break;
- }
- else if(temp_user.is_operator && args[0]=="/SETPASS"){
- if(args.size()<3){
- send(Socket,"Error: wrong input format.\n",strlen("Error: wrong input format.\n"),MSG_NOSIGNAL);
- continue;
- }
- int i=get_user_id(args[1]);
- if(i==-1){
- send(Socket,"Error: User not found\n",strlen("Error: User not found\n"),MSG_NOSIGNAL);
- continue;
- }
- users_base_lock.lock();
- unsigned char* str=(unsigned char*)args[2].c_str();
- SHA1((const unsigned char*)str,strlen((const char*)str),(unsigned char*)users_base[i].sha1_pass);
- users_base_lock.unlock();
- ///Change pass in base!!!
- send(Socket,"Success: User password successfully changed.\n",strlen("Success: User password successfully changed.\n"),MSG_NOSIGNAL);
- }
- else{
- message temp_message;
- temp_message.id=Socket;
- temp_message.message=(string)temp_user.nickname+":"+command;
- message_file.lock();
- executioner.exec("INSERT INTO message_base (sender,message) VALUES ('"+temp_user.nickname+"','"+temp_message.message+"')");
- message_file.unlock();
- message_base_lock.lock();
- message_base.push_back(temp_message);
- message_base_lock.unlock();
- }
- }
- else{
- send(Socket,"Error: unknown command or you're not identified.Try /HELP for help.\n",strlen("Error: unknown command or you're not identified.Try /HELP for help.\n"),MSG_NOSIGNAL);
- }
- cout << "Username: " << temp_user.username << endl << '\t';
- for(auto x: args){
- cout <<x << ' ';
- }
- cout << endl;
- }
- }
- disconnect(Socket,temp_user.nickname);
- return;
- }
- void connection_maker(int MasterSocket){
- while(1){
- if(stop_server)
- break;
- int SlaveSocket=accept(MasterSocket,0,0);
- cout << "SYSTEM: No." << SlaveSocket << " connected.\n";
- send(SlaveSocket,welcome,strlen(welcome),MSG_NOSIGNAL);
- thread connection(connected, SlaveSocket);
- clients_lock.lock();
- clients.push_back(SlaveSocket);
- clients_lock.unlock();
- connection.detach();
- }
- }
- int main(int argc,char** argv)
- {
- unsigned short int port=5002;
- string password="pass";
- bool db_restored=false;
- bool db_recreated=true;
- for(int i=1;i<argc;i++){
- if((string)argv[i]=="--help"){
- cout << "Usage: " << argv[0] << " [PARAMETERS]" << endl;
- cout << "Parameters:" << endl;
- cout << "--password [password] - set password of admin's account on the server(1024-65000)" << endl;
- cout << "--recreate-database - removes old files of server, like public and private message bases,users account bases" << endl;
- cout << "--port [PORT] - set unique port of server(default is 5002)" << endl;
- return 0;
- }
- else if((string)argv[i]=="--recreate-database"){
- executioner.exec("DELETE FROM users_base *");
- executioner.exec("DELETE FROM message_base *");
- executioner.exec("DELETE FROM pmessage_base *");
- }
- else if((string)argv[i]=="--password"){
- if(argc>i+1){
- try{
- password=argv[++i];
- }
- catch(exception &e){
- cout << e.what() << "Something wrong happend. Aborted...\n";
- return 9997;
- }
- }
- }
- else if((string)argv[i]=="--port"){
- if(argc>i+1){
- try{
- port=atoi(argv[++i]);
- if(port<1024 || port>65000){
- cout << "Wrong value of port, 1024-65000 must be. Aborted...\n";
- return 9997;
- }
- }
- catch(exception &e){
- cout << e.what() << "Something wrong happend. Aborted...\n";
- return 9997;
- }
- }
- }
- }
- cout << "Call this program with --help flag to see help" << endl;
- user admin;
- admin.is_operator=true;
- admin.socket=0;
- admin.username="admin";
- admin.nickname="admin";
- SHA1((const unsigned char*)password.c_str(), strlen(password.c_str()), (unsigned char*)admin.sha1_pass);
- admin.is_identified=false;
- users_base.push_back(admin);
- if(!database.is_open()){
- cout << "Cant open database. Aborted...";
- }
- cout << "SYSTEM: Database connected.\n";
- result data( executioner.exec("SELECT * FROM users_base;"));
- for (result::const_iterator c = data.begin(); c != data.end(); ++c) {
- user temp_user;
- temp_user.nickname=c[0].as<string>();
- temp_user.is_operator=c[1].as<bool>();
- temp_user.username=c[2].as<string>();
- strncpy(temp_user.sha1_pass,(const char*)(c[2].as<string>().c_str()),20);
- users_base.push_back(temp_user);
- db_restored=true;
- }
- if(!db_restored){
- cout << "SYSTEM: Old users restored.\n";
- db_recreated=false;
- }else{
- cout << "SYSTEM: Warning, \'users_base\' database not found! New file will be created.\n";
- }
- int MasterSocket = socket(AF_INET,SOCK_STREAM,0);
- if(MasterSocket<0){
- cout << "SYSTEM: Error on socket creating.\n";
- return 9999;
- }
- struct sockaddr_in SockAddr;
- SockAddr.sin_family=AF_INET;
- SockAddr.sin_port=htons(port);
- SockAddr.sin_addr.s_addr=htonl(INADDR_ANY);
- if(bind(MasterSocket, (struct sockaddr*)(&SockAddr),sizeof(SockAddr))<0){
- cout << "SYSTEM: Error on binding. Wait a minute please.\n";
- return 9998;
- }
- listen(MasterSocket,MAX_CONNECTIONS);
- cout << "SYSTEM: Server started.\n";
- thread messenger(message_sender);
- cout << "SYSTEM: Messenger started.\n";
- cout << "Port:" << port << endl;
- cout << "Admin password:" << password << endl;
- cout << "Database restored:" << db_restored << endl;
- cout << "Database recreated:" << db_recreated << endl;
- thread connector(connection_maker,MasterSocket);
- connector.detach();
- cout << "SYSTEM: Connection maker started.\n";
- string command="";
- while(1){
- getline(cin,command);
- if(command=="stop"){
- cout << "Server will be stopped.\n";
- stop_server=true;
- break;
- }
- else if(command=="settings"){
- cout << "Port:" << port << endl;
- cout << "Admin password:" << password << endl;
- cout << "Clients connected:" << clients.size() << endl;
- }
- else{
- cout << "Unknown command: " << command << endl;
- cout << "Avaliable commands:" << endl;
- cout << "\tstop - stop server" << endl;
- cout << "\tsettings - show server settings" << endl;
- }
- }
- messenger.join();
- cout << "SYSTEM: Messenger stopped.\n";
- database.disconnect();
- cout << "SYSTEM: Database disconnected.\n";
- while(clients.size()>0)
- usleep(1000000);
- close(MasterSocket);
- cout << "SYSTEM: Server stopped.\n";
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement