Skip to content

Commit cb21f05

Browse files
committed
server: Add JSON-RPC scaffolding code.
1 parent 27d3596 commit cb21f05

File tree

10 files changed

+961
-2
lines changed

10 files changed

+961
-2
lines changed

include/vast/server/io.hpp

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright (c) 2024-present, Trail of Bits, Inc.
2+
3+
#pragma once
4+
5+
#include <memory>
6+
#include <span>
7+
#include <stdexcept>
8+
#include <string>
9+
10+
#include <stdio.h>
11+
12+
#include <gap/core/crtp.hpp>
13+
14+
#include "vast/Util/Warnings.hpp"
15+
16+
namespace vast::server {
17+
class connection_closed : public std::runtime_error
18+
{
19+
public:
20+
connection_closed() : std::runtime_error("Connection closed") {}
21+
22+
connection_closed(const char *what) : std::runtime_error(what) {}
23+
};
24+
25+
struct io_adapter
26+
{
27+
virtual ~io_adapter() = default;
28+
29+
virtual void close() {}
30+
31+
virtual size_t read_some(std::span< char > dst) = 0;
32+
virtual size_t write_some(std::span< const char > dst) = 0;
33+
34+
// Upon completion, `dst` is filled with data.
35+
void read_all(std::span< char > dst) {
36+
while (!dst.empty()) {
37+
size_t nread = read_some(dst);
38+
dst = dst.subspan(nread);
39+
}
40+
}
41+
42+
// Upon completion, all of the data in `src` is written to the client..
43+
void write_all(std::span< const char > src) {
44+
while (!src.empty()) {
45+
size_t nwritten = write_some(src);
46+
src = src.subspan(nwritten);
47+
}
48+
}
49+
50+
char read() {
51+
char res[1];
52+
read_all(res);
53+
return res[0];
54+
}
55+
};
56+
57+
class file_adapter final : public io_adapter
58+
{
59+
FILE *ifd;
60+
FILE *ofd;
61+
62+
public:
63+
file_adapter(FILE *ifd = stdin, FILE *ofd = stdout) : ifd(ifd), ofd(ofd) {
64+
VAST_ASSERT(ifd != nullptr);
65+
VAST_ASSERT(ofd != nullptr);
66+
67+
setvbuf(ofd, NULL, _IONBF, 0);
68+
}
69+
70+
size_t read_some(std::span< char > dst) override {
71+
size_t nread = fread(dst.data(), 1, dst.size_bytes(), ifd);
72+
if (nread == 0 && (feof(ifd) || ferror(ifd))) {
73+
throw connection_closed{};
74+
}
75+
return nread;
76+
}
77+
78+
size_t write_some(std::span< const char > src) override {
79+
size_t nwritten = fwrite(src.data(), 1, src.size_bytes(), ofd);
80+
if (src.size() != 0 && nwritten == 0) {
81+
throw connection_closed{};
82+
}
83+
return nwritten;
84+
}
85+
};
86+
87+
class sock_adapter final : public io_adapter
88+
{
89+
public:
90+
struct impl;
91+
92+
size_t read_some(std::span< char > dst) override;
93+
size_t write_some(std::span< const char > src) override;
94+
~sock_adapter();
95+
void close() override;
96+
97+
static std::unique_ptr< sock_adapter > create_unix_socket(const std::string &path);
98+
99+
private:
100+
std::unique_ptr< struct impl > pimpl;
101+
sock_adapter(std::unique_ptr< impl > pimpl);
102+
};
103+
} // namespace vast::server

0 commit comments

Comments
 (0)