diff --git a/server/src/network_manager.cpp b/server/src/network_manager.cpp index 4a7b79f..418b232 100644 --- a/server/src/network_manager.cpp +++ b/server/src/network_manager.cpp @@ -18,15 +18,25 @@ NetworkManager::NetworkManager(const std::string& db_path) : _db_manager(std::make_unique(db_path)), _acceptor(_io_context), _machine_manager(_db_manager.get()) { - /* World setup. */ - _world_machines["8.8.8.8"] = _machine_manager.create_machine(1000, "dns.google", "npc"); - _world_machines["10.0.2.15"] = _machine_manager.create_machine(1001, "corp.internal", "npc"); - - /* Specific npc services. */ - _world_machines["8.8.8.8"]->services[80] = "HTTPD v2.4"; - _world_machines["10.0.2.15"]->services[21] = "FTPd v3.0"; _db_manager->init(); + _seed_npc_machines(); + + /* Load NPC machines from the database. */ + _db_manager->_db << "SELECT id, ip_address FROM machines WHERE owner_id IS NULL;" + >> [&](long long id, std::string ip_address) { + _world_machines[ip_address] = _machine_manager.load_machine(id, _db_manager.get()); + }; + + /* + * TODO: Services are not yet persistant. I'll add them in-mem for now. + */ + if(_world_machines.count("8.8.8.8")) { + _world_machines["8.8.8.8"]->services[80] = "HTTPD v2.4"; + } + if(_world_machines.count("10.0.2.15")) { + _world_machines["10.0.2.15"]->services[21] = "FTPd v3.0"; + } fprintf(stderr, "Created world with %zu networks\n", _world_machines.size()); } @@ -224,3 +234,58 @@ void NetworkManager::on_disconnect(std::shared_ptr connectio _players.erase(player_id); } + +void NetworkManager::_seed_npc_machines(void) { + int npc_count = 0; + _db_manager->_db << "SELECT count(*) FROM machines WHERE owner_id IS NULL;" >> npc_count; + + if(npc_count > 0) { + return; /* NPC already in db. */ + } + + fprintf(stderr, "First run: Seeding NPC machines into database...\n"); + + struct NpcDef { + std::string hostname; + std::string ip; + }; + + std::vector npc_defs = { + {"dns.google", "8.8.8.8"}, + {"corp.internal", "10.0.2.15"} + }; + + try { + for(const auto& def : npc_defs) { + _db_manager->_db << "INSERT INTO machines (hostname, ip_address) " + "VALUES(?, ?);" + << def.hostname << def.ip; + long long machine_id = _db_manager->_db.last_insert_rowid(); + + /* Create a basic VFS for the NPC machines. */ + _db_manager->_db << "INSERT INTO vfs_nodes (machine_id, parent_id, name, type) " + "VALUES (?, NULL, ?, 1);" + << machine_id << "/"; + long long root_id = _db_manager->_db.last_insert_rowid(); + + _db_manager->_db << "INSERT INTO vfs_nodes (machine_id, parent_id, name, type) " + "VALUES (?, ?, ?, 1);" + << machine_id << root_id << "etc"; + long long etc_id = _db_manager->_db.last_insert_rowid(); + + _db_manager->_db << "INSERT INTO vfs_nodes (machine_id, parent_id, name, type) " + "VALUES (?, ?, ?, 1);" + << machine_id << root_id << "bin"; + long long bin_id = _db_manager->_db.last_insert_rowid(); + + vfs_node* template_bin = _machine_manager.get_vfs_template()->children["bin"]; + for(auto const& [name, node] : template_bin->children) { + _db_manager->_db << "INSERT INTO vfs_nodes (machine_id, parent_id, name, type, content) " + "VALUES(?, ?, ?, ?, ?);" + << machine_id << bin_id << name << FILE_NODE << node->content; + } + } + } catch(const std::exception& e) { + fprintf(stderr, "Error seeding NPCs: %s. Database may be in an inconsistent state.\n", e.what()); + } +} diff --git a/server/src/network_manager.h b/server/src/network_manager.h index dcf2f90..a6e1005 100644 --- a/server/src/network_manager.h +++ b/server/src/network_manager.h @@ -28,6 +28,8 @@ private: const std::string& message); void on_disconnect(std::shared_ptr connection); + void _seed_npc_machines(void); + asio::io_context _io_context; std::thread _context_thread; asio::ip::tcp::acceptor _acceptor;