123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440 |
- #include "../include/Server.h"
- #include "../include/base64.h"
- #include <iostream>
- #include <jsoncpp/json/json.h>
- using namespace boost::asio;
- using ip::tcp;
- /***************
- * con_handler *
- ***************/
- con_handler::con_handler(
- basic_socket_acceptor<ip::tcp>::executor_type &io_service)
- : sock(io_service) {}
- con_handler::~con_handler() {}
- con_handler::pointer
- con_handler::create(basic_socket_acceptor<ip::tcp>::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<Json::CharReader> 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);
- // 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));
- // send answer
- sock.async_write_some(buffer(answerString, max_length),
- boost::bind(&con_handler::handle_write,
- 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<Json::CharReader> 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);
- // 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));
- // send answer
- sock.async_write_some(buffer(answerString, max_length),
- boost::bind(&con_handler::handle_write,
- 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<Json::CharReader> 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) {
- // 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));
- 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));
- } else if (root["command"].compare("list") == 0) {
- // 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));
- 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));
- } else if (root["command"].compare("put") == 0) {
- // 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));
- answer["command"] = "put";
- if (this->putFile.is_open() && root["cancel"].asBool() == true) {
- // cancel upload
- this->putFile.close();
- std::remove(this->putFileName.c_str());
- } else if (this->putFile.is_open()) {
- // upload chunks
- // decode base64 string
- const std::string data = base64::decode(root["data"].asString());
- this->putFile << data;
- // close file if put sends remaining = 0
- if (root["remaining"].asInt() == 0) {
- this->putFile.close();
- }
- } else {
- // start upload
- const std::string filename = root["file"].asString();
- if (filename.find("/") != std::string::npos) {
- // slashes in file names are illegal
- 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));
- } else {
- // build file path
- this->putFileName = this->fileDirectory;
- this->putFileName.append(filename);
- // open file and test if it already exists
- this->putFile.open(this->putFileName,
- std::ios::app | std::ios::binary);
- if (this->putFile.tellp() != std::ios::beg) {
- // file already exists
- this->putFile.close();
- 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));
- } else {
- // accept file
- 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));
- }
- }
- }
- } else if (root["command"].compare("get") == 0) {
- // 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));
- answer["command"] = "get";
- // a get request is already being progressed
- if (this->getFile.is_open()) {
- 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));
- } else {
- // open file
- const std::string filename = root["file"].asString();
- if (filename.find("/") != std::string::npos) {
- // slashes in file names are illegal
- 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));
- } else {
- std::string file = this->fileDirectory;
- file.append(filename);
- this->getFile = std::ifstream(file, std::ios::ate | std::ios::binary);
- if (this->getFile.is_open() == 0) {
- // file does not exist or cannot be opened
- 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));
- } else {
- // get size of file
- size_t size = this->getFile.tellg();
- this->getFile.seekg(std::ios::beg);
- char fileBuffer[9];
- while (size_t read = this->getFile.readsome(fileBuffer, 8)) {
- fileBuffer[read] = 0;
- size -= read;
- int remaining = size / 8 + (size % 8 == 0 ? 0 : 1);
- answer["remaining"] = remaining;
- answer["cancel"] = false;
- answer["data"] = base64::encode(fileBuffer);
- const std::string answerString =
- Json::writeString(stringBuilder, answer);
- sock.async_write_some(
- buffer(answerString, max_length),
- boost::bind(&con_handler::handle_write, shared_from_this(),
- placeholders::error,
- placeholders::bytes_transferred));
- }
- this->getFile.close();
- }
- }
- }
- } 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();
- }
|