-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.cpp
124 lines (108 loc) · 3.93 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// SPDX-FileCopyrightText: 2022 Pepijn de Vos
//
// SPDX-License-Identifier: MPL-2.0
#include <string>
#include "api/Simulator.capnp.h"
#include <kj/debug.h>
#include <kj/filesystem.h>
#include <kj/exception.h>
#include <kj/async-io.h>
#include <capnp/message.h>
#include <capnp/rpc-twoparty.h>
#include "../simserver.h"
#include <boost/asio.hpp>
#include <boost/process.hpp>
#include <boost/dll.hpp>
#include <boost/process/handles.hpp>
#include <boost/process/extend.hpp>
class SimulatorImpl final : public Sim::Simulator<SimCommands>::Server
{
public:
SimulatorImpl(const kj::Directory &dir) : dir(dir) {}
kj::Promise<void> loadFiles(LoadFilesContext context) override
{
auto files = context.getParams().getFiles();
for (Sim::File::Reader f : files)
{
kj::Path path = kj::Path::parse(f.getName());
kj::Own<const kj::File> file = dir.openFile(path, kj::WriteMode::CREATE | kj::WriteMode::MODIFY | kj::WriteMode::CREATE_PARENT);
file->truncate(0);
file->write(0, f.getContents());
}
std::string name = files[0].getName();
auto res = context.getResults();
auto commands = kj::heap<SimCommandsImpl>(name);
res.setCommands(kj::mv(commands));
return kj::READY_NOW;
}
kj::Promise<void> loadPath(LoadPathContext context) override
{
auto file = context.getParams().getFile();
auto res = context.getResults();
auto commands = kj::heap<SimCommandsImpl>(file);
res.setCommands(kj::mv(commands));
return kj::READY_NOW;
}
const kj::Directory &dir;
};
using boost::this_process::native_handle_type;
int runchild(kj::LowLevelAsyncIoProvider::Fd fd) {
kj::AsyncIoContext ctx = kj::setupAsyncIo();
auto stream = ctx.lowLevelProvider->wrapSocketFd(fd);
auto network = capnp::TwoPartyVatNetwork(*stream, capnp::rpc::twoparty::Side::SERVER);
kj::Own<kj::Filesystem> fs = kj::newDiskFilesystem();
const kj::Directory &dir = fs->getCurrent();
auto rpc = capnp::makeRpcServer(network, kj::heap<SimulatorImpl>(dir));
network.onDisconnect().wait(ctx.waitScope);
std::cout << "Client disconnected" << std::endl;
return 0;
}
using namespace boost::asio;
using ip::tcp;
using namespace boost::process;
namespace ex = boost::process::extend;
struct do_inherit : boost::process::extend::handler
{
template<typename Char, typename Sequence>
void on_setup(ex::windows_executor<Char, Sequence> & exec)
{
std::cout << "windows setup" << std::endl;
exec.inherit_handles = 1;
}
template<typename Sequence>
void on_setup(ex::posix_executor<Sequence> & exec)
{
std::cout << "unix setup" << std::endl;
}
};
int main(int argc, char const *argv[])
{
std::string host = "::1";
int port = 5923;
if (argc == 2 && strcmp(argv[1], "--help")==0) {
std::cout << argv[0] << " [host] [port]" << std::endl;
return 0;
} else if (argc == 3 && strcmp(argv[1], "--child")==0) {
kj::LowLevelAsyncIoProvider::Fd fd = std::stoi(argv[2]);
return runchild(fd);
} else if (argc == 2) {
port = std::stoi(argv[1]);
} else if (argc == 3) {
host = argv[1];
port = std::stoi(argv[2]);
}
boost::filesystem::path p = boost::dll::program_location();
boost::asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(boost::asio::ip::address::from_string(host), port));
while (1)
{
std::cout << "waiting for clients on " << host << ":" << port << std::endl;
tcp::socket peersocket(io_service);
acceptor.accept(peersocket);
auto endpoint = peersocket.remote_endpoint();
std::cout << "Accepted new connection from a client" << endpoint.address() << ":" << endpoint.port() << std::endl;
std::string fd = std::to_string(peersocket.release());
boost::process::spawn(p, "--child", fd, do_inherit());
}
return 0;
}