diff options
author | Your Name <you@example.com> | 2024-03-28 16:18:36 -0400 |
---|---|---|
committer | Your Name <you@example.com> | 2024-03-28 16:18:36 -0400 |
commit | c644379e79262a7478a7fb9ea8001f315fdb6eaf (patch) | |
tree | d71b15e396ebca28b76f0b5fd1971dd352877e4e /src/vm.cc | |
download | nerdhack-master.tar.gz nerdhack-master.tar.bz2 nerdhack-master.zip |
Diffstat (limited to 'src/vm.cc')
-rw-r--r-- | src/vm.cc | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/vm.cc b/src/vm.cc new file mode 100644 index 0000000..29fcc43 --- /dev/null +++ b/src/vm.cc @@ -0,0 +1,85 @@ +#include "vm.h" +#include <iostream> +#include <thread> + +namespace vm { + virConnectPtr conn = NULL; + + struct vmImpl { + virDomainPtr dom; + virStreamPtr stream; + std::thread receiver; + }; + + void initConn() { + if (conn == NULL) { + conn = virConnectOpen("qemu:///system"); + } + if (conn == NULL) { + std::cerr << "Failed to open connection to qemu:///system\n"; + } + } + + void clearAllVMs() { + initConn(); + virDomainPtr *domains; + int numDomains = virConnectListAllDomains(conn, &domains, 0); + for (int i = 0; i < numDomains; i++) { + virDomainDestroy(domains[i]); + virDomainFree(domains[i]); + } + free(domains); + } + + VM::VM() : data(new vmImpl()) { + initConn(); + data->stream = virStreamNew(conn, 0); + } + + VM::~VM() { + virStreamAbort(data->stream); + virStreamFree(data->stream); + } + + int VM::start(std::string config) { + data->dom = virDomainCreateXML(conn, config.c_str(), VIR_DOMAIN_START_AUTODESTROY); + if (!data->dom) { + std::cerr << "Domain creation failed\n"; + return 1; + } + return 0; + } + + void VM::stop() { + if (data->dom) { + virDomainFree(data->dom); + } + } + + void receiveTask(virStreamPtr stream, std::function<int(const char*,size_t)> receiver) { + + virStreamRecvAll(stream, + [](virStreamPtr stream, const char *data, size_t nbytes, void *opaque) { + auto *receiver = static_cast<std::function<int(const char*,size_t)>*>(opaque); + return (*receiver)(data, nbytes); + }, + &receiver); + } + + void sendTask(virStreamPtr stream, std::function<int(char*,size_t)> sender) { + virStreamSendAll(stream, + [](virStreamPtr stream, char *data, size_t nbytes, void *opaque) { + auto *sender = static_cast<std::function<int(char*,size_t)>*>(opaque); + return (*sender)(data, nbytes); + }, + &sender); + } + + void VM::connect(std::function<int(const char*,size_t)> receiver, std::function<int(char*,size_t)> sender) { + if (virDomainOpenConsole(data->dom, NULL, data->stream, 0)) { + std::cerr << "Failed to open console\n"; + } + data->receiver = std::thread(receiveTask, data->stream, receiver); + sendTask(data->stream, sender); // Blocking + } +} |