#include #include #include "session.h" #include "db/database_manager.h" #include "i_network_bridge.h" #include "lua_api.h" #include "lua_processor.h" #include "machine.h" #include "vfs.h" vfs_node* find_node_by_id(vfs_node* root, long long id) { if(root->id == id) { return root; } for(auto const& [name, child] : root->children) { vfs_node* found = find_node_by_id(child, id); if(found) { return found; } } return nullptr; } Session::Session(Machine* home_machine, DatabaseManager* db_manager, MachineManager* machine_manager, INetworkBridge* network_bridge) : _machine_manager(machine_manager), _db_manager(db_manager), _network_bridge(network_bridge), _home_machine(home_machine), _session_machine(home_machine) { if(home_machine) _current_dir = home_machine->vfs_root; } Session::~Session(void) { } vfs_node* Session::get_current_dir(void) { return _current_dir; } Machine* Session::get_home_machine(void) { return _home_machine; } Machine* Session::get_session_machine(void) { return _session_machine; } DatabaseManager* Session::get_db_manager(void) { return _db_manager; } MachineManager* Session::get_machine_manager(void) { return _machine_manager; } INetworkBridge* Session::get_network_bridge(void) { return _network_bridge; } void Session::set_current_dir(vfs_node* node) { _current_dir = node; } void Session::set_session_machine(Machine* machine) { _session_machine = machine; if(_session_machine) { _current_dir = _session_machine->vfs_root; } } std::string Session::process_command(const std::string& command) { /* * Creating the Lua processor on-demand to ensure it exists on the same * thread that will execute the script. */ LuaProcessor lua(*this); /* Trim trailing whitespace. */ std::string cmd = command; size_t end = cmd.find_last_not_of(" \t\n\r"); cmd = (end == std::string::npos) ? "" : cmd.substr(0, end+1); /* === Generic script executer. === */ /* Parse the command and it's arguments. */ std::stringstream ss(cmd); std::string command_name; ss >> command_name; std::vector args; std::string arg; while(ss >> arg) { args.push_back(arg); } /* Find the /bin directory in the current machine's VFS. */ vfs_node* bin_dir = find_node_by_path(_session_machine->vfs_root, "/bin"); if(bin_dir && bin_dir->type == DIR_NODE) { auto it = bin_dir->children.find(command_name); if(it != bin_dir->children.end()) { vfs_node* command_node = it->second; if(command_node->type == EXEC_NODE) { /* Execute the script. */ bool is_remote = (_session_machine != _home_machine); sol::object result = lua.execute(command_node->content, *this, args, is_remote); return result.is() ? result.as() : "[Script returned an unexpected type]"; } } } return "Unknown command: " + command_name + "\n"; } std::string Session::write_file(const std::string& path, const std::string& content) { return api::write_file(*this, path, content); } std::string Session::read_file(const std::string& path) { vfs_node* root = get_session_machine()->vfs_root; vfs_node* node = nullptr; if(path[0] == '/') { node = find_node_by_path(root, path); } else { /* Relative path. */ vfs_node* current_dir = get_current_dir(); if(current_dir->children.count(path)) { node = current_dir->children.at(path); } } if(node && (node->type == FILE_NODE || node->type == EXEC_NODE)) { return node->content; } return "Error: file not found."; }