summaryrefslogtreecommitdiff
path: root/src/vm.cc
diff options
context:
space:
mode:
authorYour Name <you@example.com>2024-03-28 16:18:36 -0400
committerYour Name <you@example.com>2024-03-28 16:18:36 -0400
commitc644379e79262a7478a7fb9ea8001f315fdb6eaf (patch)
treed71b15e396ebca28b76f0b5fd1971dd352877e4e /src/vm.cc
downloadnerdhack-master.tar.gz
nerdhack-master.tar.bz2
nerdhack-master.zip
Initial commitHEADmaster
Diffstat (limited to 'src/vm.cc')
-rw-r--r--src/vm.cc85
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
+ }
+}