engine/src/Utils/Network/Server.cpp
2013-05-27 13:24:27 +00:00

241 lines
5.7 KiB
C++

#include "include/Utils/Utils.h"
#include "boost/random.hpp"
namespace SE
{
std::vector<std::string> TSimpleAutorizator::UserPasswords;
boost::mutex TSimpleAutorizator::UserPasswordsMutex;
std::string TSimpleAutorizator::GenerateRandomPassword()
{
boost::random::mt19937 RandomGenerator;
RandomGenerator.seed(static_cast<unsigned int>(std::time(0)));
static const int passwordLength = 18;
static const std::string symbols = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!()-=_+[]{};:,.?";
std::string result;
boost::random::uniform_int_distribution<> symbolRandom(0, symbols.size()-1);
for (size_t i = 0; i < passwordLength; i++)
{
result += symbols[symbolRandom(RandomGenerator)];
}
return result;
}
TSimpleAutorizator::TSimpleAutorizator(boost::asio::io_service& ioService, boost::asio::ip::tcp::socket& socket)
: IoService(ioService)
, Socket(socket)
{
}
void TSimpleAutorizator::StartListen()
{
boost::shared_ptr<TDataReader> dataReader(new TDataReader(Socket));
dataReader->DataReadSignalMap.AddSlot("Hello", boost::bind(&TSimpleAutorizator::HandleGetRegisterRequest, this, _1));
dataReader->DataReadSignalMap.AddSlot("HelloAgain", boost::bind(&TSimpleAutorizator::HandleGetLoginRequest, this, _1));
dataReader->ErrorSignal.connect(ErrorSignal);
dataReader->StartReadOnce();
}
void TSimpleAutorizator::HandleGetRegisterRequest(boost::property_tree::ptree pTree)
{
CreateNewUser();
}
void TSimpleAutorizator::HandleGetLoginRequest(boost::property_tree::ptree pTree)
{
std::string login = pTree.get<std::string>("Login");
std::string password = pTree.get<std::string>("Password");
int loginNum = boost::lexical_cast<int>(login);
bool loginIsValid = loginNum < UserPasswords.size();
if (!loginIsValid)
{
CreateNewUser();
return;
}
bool passwordIsValid = UserPasswords[loginNum] == password;
if (!passwordIsValid)
{
CreateNewUser();
return;
}
//Login and password are ok
boost::property_tree::ptree pt;
pt.put("OnHello.Login", login);
pt.put("OnHello.Password", password);
SendPropertyTree(IoService, Socket, pt);
AllowedSignal(login);
}
void TSimpleAutorizator::CreateNewUser()
{
std::string login = boost::lexical_cast<std::string>(UserPasswords.size());
std::string password = GenerateRandomPassword();
UserPasswordsMutex.lock();
UserPasswords.push_back(password);
UserPasswordsMutex.unlock();
boost::property_tree::ptree pt;
pt.put("OnHello.Login", login);
pt.put("OnHello.Password", password);
SendPropertyTree(IoService, Socket, pt);
AllowedSignal(login);
}
//================================
TConnectedUser::TConnectedUser(TServerSocket& server)
: Server(server)
, Socket(server.IoService)
, Autorizator(std::shared_ptr<TSimpleAutorizator>(new TSimpleAutorizator(server.IoService, Socket)))
{
}
TConnectedUser::~TConnectedUser()
{
}
void TConnectedUser::HandleAllowed(std::string login)
{
UserDataReader = boost::shared_ptr<TDataReader>(new TDataReader(Socket));
UserDataReader->ErrorSignal.connect(boost::bind(&TServerSocket::DeleteUser, &Server, shared_from_this()));
Login = login;
Server.OnUserAuthorizedSignal(shared_from_this());
UserDataReader->StartReadNonstop();
}
void TConnectedUser::SendPropertyTree(boost::property_tree::ptree pTree)
{
SE::SendPropertyTree(Server.IoService, Socket, pTree);
}
void TConnectedUser::DisconnectSlots()
{
UserDataReader->DataReadSignalMap.Clear();
UserDataReader->ErrorSignal.disconnect_all_slots();
std::shared_ptr<TSimpleAutorizator> authorizator = boost::get<std::shared_ptr<TSimpleAutorizator>>(Autorizator);
authorizator->ErrorSignal.disconnect_all_slots();
authorizator->AllowedSignal.disconnect_all_slots();
//authorizator->DeniedSignal.disconnect_all_slots();
}
TServerSocket::TServerSocket()
{
}
TServerSocket::~TServerSocket()
{
}
void TServerSocket::Open(int port)
{
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
Acceptor = std::shared_ptr<boost::asio::ip::tcp::acceptor>(new boost::asio::ip::tcp::acceptor(IoService, endpoint));
StartAccept();
ServiceThread = boost::thread(boost::bind(&TServerSocket::UpdateInThread, this));
}
void TServerSocket::Close()
{
}
void TServerSocket::UpdateInThread()
{
IoService.run();
IoService.reset();
}
void TServerSocket::JoinServiceThread()
{
ServiceThread.join();
}
void TServerSocket::StartAccept()
{
boost::shared_ptr<TConnectedUser> newUser(new TConnectedUser(*this));
Acceptor->async_accept(newUser->Socket, boost::bind(&TServerSocket::HandleAccept, this, newUser, boost::asio::placeholders::error));
}
void TServerSocket::HandleAccept(boost::shared_ptr<TConnectedUser> user, const boost::system::error_code& error)
{
if (!error)
{
UserArr.push_back(user);
std::shared_ptr<TSimpleAutorizator> authorizator = boost::get<std::shared_ptr<TSimpleAutorizator>>(user->Autorizator);
authorizator->AllowedSignal.connect(boost::bind(&TConnectedUser::HandleAllowed, user, _1));
authorizator->ErrorSignal.connect(boost::bind(&TServerSocket::DeleteUser, this, user));
boost::get<std::shared_ptr<TSimpleAutorizator>>(user->Autorizator)->StartListen();
}
StartAccept();
}
void TServerSocket::DeleteUser(boost::shared_ptr<TConnectedUser> user)
{
std::vector<boost::shared_ptr<TConnectedUser>>::iterator i = std::find(UserArr.begin(), UserArr.end(), user);
user->DisconnectSlots();
OnUserDisconnectedSignal(user);
UserArr.erase(i);
}
} //namspace SE