#include "../include/Server.h" #include #include using namespace boost::asio; using ip::tcp; /*************** * con_handler * ***************/ con_handler::con_handler( basic_socket_acceptor::executor_type &io_service) : sock(io_service) {} con_handler::~con_handler() {} con_handler::pointer con_handler::create(basic_socket_acceptor::executor_type &io_service) { return pointer(new con_handler(io_service)); } tcp::socket &con_handler::socket() { return sock; } void con_handler::start() { sock.async_read_some(buffer(data, max_length), boost::bind(&con_handler::handle_read_version, shared_from_this(), placeholders::error, placeholders::bytes_transferred)); } void con_handler::handle_read(const boost::system::error_code &err, size_t bytes_transferred) { if (!err) { std::cout << this->data << std::endl; } else { std::cerr << "error: " << err.message() << std::endl; sock.close(); } } void con_handler::handle_read_version(const boost::system::error_code &err, size_t bytes_transferred) { if (!err) { // set up json stuff JSONCPP_STRING err; Json::Value root; Json::CharReaderBuilder builder; const std::unique_ptr reader(builder.newCharReader()); // parse data if (!reader->parse(this->data, this->data + bytes_transferred, &root, &err)) { std::cerr << "Json error: " << err << std::endl << "data: " << this->data; sock.close(); } // create answer Json::Value answer; Json::StreamWriterBuilder stringBuilder; answer["version"] = this->protocolVersion; // check version string if (root["version"].compare(this->protocolVersion) == 0) { answer["accept"] = true; const std::string answerString = Json::writeString(stringBuilder, answer); // send answer sock.async_write_some(buffer(answerString, max_length), boost::bind(&con_handler::handle_write, shared_from_this(), placeholders::error, placeholders::bytes_transferred)); // read next data sock.async_read_some(buffer(data, max_length), boost::bind(&con_handler::handle_read_login, shared_from_this(), placeholders::error, placeholders::bytes_transferred)); } else { answer["accept"] = false; const std::string answerString = Json::writeString(stringBuilder, answer); // send answer sock.async_write_some(buffer(answerString, max_length), boost::bind(&con_handler::handle_write, shared_from_this(), placeholders::error, placeholders::bytes_transferred)); // close connection sock.close(); } } else { std::cerr << "error: " << err.message() << std::endl; sock.close(); } } void con_handler::handle_read_login(const boost::system::error_code &err, size_t bytes_transferred) { if (!err) { // set up json stuff JSONCPP_STRING err; Json::Value root; Json::CharReaderBuilder builder; const std::unique_ptr reader(builder.newCharReader()); // parse data if (!reader->parse(this->data, this->data + bytes_transferred, &root, &err)) { std::cerr << "Json error: " << err << std::endl << "data: " << this->data; sock.close(); } Json::Value answer; Json::StreamWriterBuilder stringBuilder; // user credentials // TODO check user credentials!!! if (root["user"].compare("user") == 0 && root["pass"].compare("pass") == 0) { answer["accept"] = true; const std::string answerString = Json::writeString(stringBuilder, answer); // send answer sock.async_write_some(buffer(answerString, max_length), boost::bind(&con_handler::handle_write, shared_from_this(), placeholders::error, placeholders::bytes_transferred)); // read next data sock.async_read_some(buffer(data, max_length), boost::bind(&con_handler::handle_read_command, shared_from_this(), placeholders::error, placeholders::bytes_transferred)); } else { answer["accept"] = false; const std::string answerString = Json::writeString(stringBuilder, answer); // send answer sock.async_write_some(buffer(answerString, max_length), boost::bind(&con_handler::handle_write, shared_from_this(), placeholders::error, placeholders::bytes_transferred)); // close connection sock.close(); } } else { std::cerr << "error: " << err.message() << std::endl; sock.close(); } } void con_handler::handle_read_command(const boost::system::error_code &err, size_t bytes_transferred) { if (!err) { // set up json stuff JSONCPP_STRING err; Json::Value root; Json::CharReaderBuilder builder; const std::unique_ptr reader(builder.newCharReader()); // parse data if (!reader->parse(this->data, this->data + bytes_transferred, &root, &err)) { std::cerr << "Json error: " << err << std::endl << "data: " << this->data; sock.close(); } Json::Value answer; Json::StreamWriterBuilder stringBuilder; // check command if (root["command"].compare("status") == 0) { answer["command"] = "status"; // TODO answer a real status message answer["response"] = "This is a status message :)"; const std::string answerString = Json::writeString(stringBuilder, answer); // send answer sock.async_write_some(buffer(answerString, max_length), boost::bind(&con_handler::handle_write, shared_from_this(), placeholders::error, placeholders::bytes_transferred)); // read next data sock.async_read_some(buffer(data, max_length), boost::bind(&con_handler::handle_read_command, shared_from_this(), placeholders::error, placeholders::bytes_transferred)); } else if (root["command"].compare("list") == 0) { answer["command"] = "list"; // TODO look for real data Json::Value array; array.append("some"); array.append("important"); array.append("data"); answer["names"] = array; answer["remaining"] = 0; const std::string answerString = Json::writeString(stringBuilder, answer); // send answer sock.async_write_some(buffer(answerString, max_length), boost::bind(&con_handler::handle_write, shared_from_this(), placeholders::error, placeholders::bytes_transferred)); // read next data sock.async_read_some(buffer(data, max_length), boost::bind(&con_handler::handle_read_command, shared_from_this(), placeholders::error, placeholders::bytes_transferred)); } else if (root["command"].compare("put") == 0) { answer["command"] = "put"; // TODO establish real connection and receive file answer["accept"] = false; const std::string answerString = Json::writeString(stringBuilder, answer); // send answer sock.async_write_some(buffer(answerString, max_length), boost::bind(&con_handler::handle_write, shared_from_this(), placeholders::error, placeholders::bytes_transferred)); // read next data sock.async_read_some(buffer(data, max_length), boost::bind(&con_handler::handle_read_command, shared_from_this(), placeholders::error, placeholders::bytes_transferred)); } else if (root["command"].compare("get") == 0) { answer["command"] = "get"; // TODO establish real connection and send file answer["accept"] = false; const std::string answerString = Json::writeString(stringBuilder, answer); // send answer sock.async_write_some(buffer(answerString, max_length), boost::bind(&con_handler::handle_write, shared_from_this(), placeholders::error, placeholders::bytes_transferred)); // read next data sock.async_read_some(buffer(data, max_length), boost::bind(&con_handler::handle_read_command, shared_from_this(), placeholders::error, placeholders::bytes_transferred)); } else if (root["command"].compare("close") == 0) { answer["command"] = "close"; answer["response"] = "bye"; const std::string answerString = Json::writeString(stringBuilder, answer); // send answer sock.async_write_some(buffer(answerString, max_length), boost::bind(&con_handler::handle_write, shared_from_this(), placeholders::error, placeholders::bytes_transferred)); // close connection sock.close(); } else { // TODO handle error // close connection sock.close(); } } else { std::cerr << "error: " << err.message() << std::endl; sock.close(); } } void con_handler::handle_write(const boost::system::error_code &err, size_t bytes_transferred) { if (!err) { std::cout << "Hello World!" << std::endl; } else { std::cerr << "error: " << err.message() << std::endl; sock.close(); } } /********** * Server * **********/ void Server::start_accept() { auto executor = acceptor_.get_executor(); con_handler::pointer connection = con_handler::create(executor); 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(), 1234)) { start_accept(); } Server::~Server() {} void Server::handle_accept(con_handler::pointer connection, const boost::system::error_code &err) { if (!err) { connection->start(); } start_accept(); }