123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- #include "../include/Server.h"
- #include "../include/Config.h"
- #include "../include/base64.h"
- #include <iostream>
- using namespace boost::asio;
- using ip::tcp;
- /***************
- * con_handler *
- ***************/
- con_handler::con_handler(basic_socket_acceptor<ip::tcp>::executor_type &io_service, boost::asio::ssl::context &context)
- : sock(io_service), sslsock(sock, context), usessl(Config::getValue("SSLenabled") == "true"), buf(max_length), jsonCommander(fileManager) {
- // disable indentation for json
- this->jsonStringBuilder.settings_["indentation"] = "";
- // init reader to parse json
- Json::CharReaderBuilder builder;
- jsonReader = std::unique_ptr<Json::CharReader>(builder.newCharReader());
- }
- con_handler::~con_handler() {}
- con_handler::pointer con_handler::create(basic_socket_acceptor<ip::tcp>::executor_type &io_service, boost::asio::ssl::context &context) {
- return pointer(new con_handler(io_service, context));
- }
- tcp::socket &con_handler::socket() { return sock; }
- bool con_handler::handshake() {
- boost::system::error_code err;
- sslsock.handshake(boost::asio::ssl::stream_base::server, err);
- if (err) {
- std::cerr << "SSL handshake failed: " << err.message() << std::endl;
- close_sock();
- return false;
- }
- return true;
- }
- void con_handler::close_sock() { sock.close(); }
- void con_handler::start() {
- if (usessl) {
- if (handshake())
- read(&con_handler::handle_read_version);
- } else
- read(&con_handler::handle_read_version);
- }
- void con_handler::handle_read_version(const boost::system::error_code &err, size_t bytes_transferred) {
- if (!err) {
- // set up json stuff
- Json::Value root = parseMessage();
- JsonCommander::Response response = this->jsonCommander.testVersion(root);
- switch (response.action) {
- case JsonCommander::Action::send:
- read(&con_handler::handle_read_login);
- sendJson(response.json);
- break;
- case JsonCommander::Action::closeAndSend:
- sendJson(response.json);
- default:
- close_sock();
- }
- } else {
- std::cerr << __PRETTY_FUNCTION__ << " error: " << err.message() << std::endl;
- close_sock();
- }
- }
- void con_handler::handle_read_login(const boost::system::error_code &err, size_t bytes_transferred) {
- if (!err) {
- // set up json stuff
- Json::Value root = parseMessage();
- JsonCommander::Response response = this->jsonCommander.checkLogin(root);
- switch (response.action) {
- case JsonCommander::Action::send:
- read(&con_handler::handle_read_command);
- sendJson(response.json);
- break;
- case JsonCommander::Action::closeAndSend:
- sendJson(response.json);
- default:
- close_sock();
- }
- } else {
- std::cerr << __PRETTY_FUNCTION__ << " error: " << err.message() << std::endl;
- close_sock();
- }
- }
- void con_handler::handle_read_command(const boost::system::error_code &err, size_t bytes_transferred) {
- if (!err) {
- // set up json stuff
- Json::Value root = parseMessage();
- JsonCommander::Response response = this->jsonCommander.execute(root);
- switch (response.action) {
- case JsonCommander::Action::send:
- read(&con_handler::handle_read_command);
- sendJson(response.json);
- break;
- case JsonCommander::Action::closeAndSend:
- sendJson(response.json);
- default:
- close_sock();
- }
- } else {
- std::cerr << __PRETTY_FUNCTION__ << " error: " << err.message() << std::endl;
- close_sock();
- }
- }
- void con_handler::handle_write(const boost::system::error_code &err, size_t bytes_transferred) {
- if (err) {
- std::cerr << __PRETTY_FUNCTION__ << " error: " << err.message() << std::endl;
- close_sock();
- }
- }
- void con_handler::read(void (con_handler::*handler)(const boost::system::error_code &err, size_t bytes_transferred)) {
- if (usessl)
- async_read_until(sslsock, buf, '\n', bind(handler, shared_from_this(), placeholders::error, placeholders::bytes_transferred));
- else
- async_read_until(sock, buf, '\n', bind(handler, shared_from_this(), placeholders::error, placeholders::bytes_transferred));
- }
- void con_handler::sendJson(const Json::Value &json) {
- std::string jsonString = Json::writeString(jsonStringBuilder, json);
- jsonString.append("\n");
- if (usessl)
- sslsock.async_write_some(buffer(jsonString, max_length),
- boost::bind(&con_handler::handle_write, shared_from_this(), placeholders::error, placeholders::bytes_transferred));
- else
- sock.async_write_some(buffer(jsonString, max_length),
- boost::bind(&con_handler::handle_write, shared_from_this(), placeholders::error, placeholders::bytes_transferred));
- }
- Json::Value con_handler::parseMessage() {
- const char *data = buffer_cast<const char *>(buf.data());
- std::string dataStr(data, buf.size());
- const int lineEnd = dataStr.find('\n');
- JSONCPP_STRING err;
- Json::Value root;
- // parse data
- if (!this->jsonReader->parse(data, data + lineEnd, &root, &err)) {
- std::cerr << "Json error: " << err << std::endl << "data: " << data;
- close_sock();
- }
- buf.consume(lineEnd + 1);
- return root;
- }
- /**********
- * Server *
- **********/
- void Server::start_accept() {
- auto executor = acceptor_.get_executor();
- con_handler::pointer connection = con_handler::create(executor, context_);
- acceptor_.async_accept(connection->socket(), boost::bind(&Server::handle_accept, this, connection, placeholders::error));
- }
- Server::Server(io_service &io_service)
- : acceptor_(io_service, tcp::endpoint(tcp::v4(), std::stoi(Config::getValue("port")))), context_(boost::asio::ssl::context::sslv23) {
- if (Config::getValue("SSLenabled") == "true") {
- context_.set_options(boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::single_dh_use);
- context_.use_certificate_chain_file(Config::getValue("SSLcertificate"));
- context_.use_private_key_file(Config::getValue("SSLprivatekey"), boost::asio::ssl::context::pem);
- context_.use_tmp_dh_file(Config::getValue("SSLdhparams"));
- }
- start_accept();
- }
- Server::~Server() {}
- void Server::handle_accept(con_handler::pointer connection, const boost::system::error_code &err) {
- if (!err) {
- connection->start();
- }
- start_accept();
- }
|