/*
Copyright © 2015 Gluzskiy Alexandr (sss)
This file is part of Unknown Download Manager (UDM).
UDM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
UDM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with UDM. If not, see .
*/
#include
#include
#include "server_session.h"
#include "../../protocol/udm.pb.h"
#include "utilities.h"
#include "socket_wraper.h"
#include "client.h"
extern std::map clients;
server_session::server_session(boost::asio::io_service &s, runtime_config_s &config, std::map &clients_, boost::asio::ssl::context *c) : io_service_(s), context_(c), runtime_config(config), clients(clients_)
{
if(runtime_config.config_file.get("server.enable_encryption", false))
{
socket_ = new socket_wraper(new boost::asio::ssl::stream(io_service_, *context_));
socket_->get_ssl_socket().async_handshake(boost::asio::ssl::stream_base::server, boost::bind(&server_session::handle_handshake, this, boost::asio::placeholders::error));
}
else
socket_ = new socket_wraper(new boost::asio::ip::tcp::socket(io_service_));
}
socket_wraper* server_session::socket()
{
return socket_;
}
void server_session::run()
{
recv_data_ = new char[4];
boost::asio::async_read(*socket_, boost::asio::buffer(recv_data_, 4), boost::bind(&server_session::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
void server_session::handle_handshake(const boost::system::error_code& error)
{
if (!error)
{
recv_data_ = new char[4];
boost::asio::async_read(*socket_, boost::asio::buffer(recv_data_, 4), boost::bind(&server_session::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
else
{
delete this;
}
}
void server_session::handle_read(const boost::system::error_code& error, size_t bytes_transferred)
{
if (!error)
{
std::string s;
// bool parsed = false;
unsigned size = ntohl(*(int32_t*)recv_data_);
delete [] recv_data_;
char *buf = new char[size];
boost::system::error_code ec;
boost::asio::read(*socket_, boost::asio::buffer(buf, size), ec);
if(ec)
{
}
//TODO: check for error
s.append(buf, size);
delete [] buf;
if(size != s.length())
{
delete this;
return;
}
//TODO:
client_msg msg;
if(msg.ParseFromString(s))
{
//parsed = true;
BOOST_LOG_TRIVIAL(trace)<<"received message:\n"<type())
{
case CLIENT_MSG_TYPE::CLIENT_AUTH_REQUEST:
{
server_msg m;
m.set_type(SERVER_MSG_TYPE::SERVER_AUTH_REPLY);
//TODO: check for already existing auth token
std::string server_password = runtime_config.config_file.get("server.password", "");
if(server_password.empty())
m.mutable_auth_reply()->set_status(true);
else
{
switch(msg->auth_info().hash_type())
{
case PASSWD_HASH_TYPE::HASH_NONE:
{
if(msg->auth_info().password() != server_password)
{
m.mutable_auth_reply()->set_status(false);
m.mutable_auth_reply()->set_error_description("wrong password");
}
else
m.mutable_auth_reply()->set_status(true);
}
break;
case PASSWD_HASH_TYPE::HASH_MD5:
{
//TODO:
}
break;
case PASSWD_HASH_TYPE::HASH_SHA2:
{
//TODO:
}
break;
case PASSWD_HASH_TYPE::HASH_SHA512:
{
unsigned char hash[64];
SHA512((unsigned char*)server_password.c_str(), server_password.length(), hash);
if(msg->auth_info().password() != std::string((const char*)hash))
{
m.mutable_auth_reply()->set_status(false);
m.mutable_auth_reply()->set_error_description("wrong password");
}
else
m.mutable_auth_reply()->set_status(true);
}
break;
default:
break;
}
}
if(m.auth_reply().status() == true)
{
client_auth_token = generate_auth_token();
m.mutable_auth_reply()->set_auth_token(client_auth_token);
auto i = clients.find(client_auth_token);
if(i == clients.end())
{
auto a = new client(client_auth_token);
clients[client_auth_token] = a;
client_ = a;
}
else
client_ = i->second;
//set auth token
}
send_message(&m);
}
break;
default:
break;
}
}
void server_session::send_message(server_msg *msg)
{
int size = 0;
std::shared_ptr ptr = pack_msg(msg, &size);
boost::asio::async_write(*socket_, boost::asio::buffer(*ptr, size), boost::bind(&server_session::handle_write, this, boost::asio::placeholders::error));
}
void server_session::handle_write(const boost::system::error_code& error)
{
if(!error)
{
//TODO:
}
else
{
//TODO: handle error
}
// recv_data_ = new char[4];
// boost::asio::async_read(socket_, boost::asio::buffer(recv_data_, 4), boost::bind(&server_session::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
server_session::~server_session()
{
//dtor
}