diff options
author | iphydf <iphydf@users.noreply.github.com> | 2018-01-15 00:31:06 +0000 |
---|---|---|
committer | iphydf <iphydf@users.noreply.github.com> | 2018-01-15 11:29:51 +0000 |
commit | cec5fea71bff1ba46be6bc126efb85c28a169f9e (patch) | |
tree | f87083521fa5f5328bb1342f691eefa49c60b396 /testing/hstox/driver.c | |
parent | 402664f58d3b076a3715ddf0fdb6bb49c70c57b4 (diff) |
Remove hstox test for now.
This isn't adding value. We're going to redo the whole rpc test framework
in the future, after a lot of refactoring that the hstox test currently
just stands in the way of.
Diffstat (limited to 'testing/hstox/driver.c')
-rw-r--r-- | testing/hstox/driver.c | 270 |
1 files changed, 0 insertions, 270 deletions
diff --git a/testing/hstox/driver.c b/testing/hstox/driver.c deleted file mode 100644 index 6d1b8e0e..00000000 --- a/testing/hstox/driver.c +++ /dev/null | |||
@@ -1,270 +0,0 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <errno.h> | ||
3 | #include <fcntl.h> | ||
4 | #include <netdb.h> | ||
5 | #include <signal.h> | ||
6 | #include <signal.h> | ||
7 | #include <stdarg.h> | ||
8 | #include <stdio.h> | ||
9 | #include <string.h> | ||
10 | #include <sys/stat.h> | ||
11 | #include <sys/socket.h> | ||
12 | #include <sys/types.h> | ||
13 | #include <netinet/in.h> | ||
14 | #include <unistd.h> | ||
15 | |||
16 | #include "driver.h" | ||
17 | #include "errors.h" | ||
18 | #include "methods.h" | ||
19 | #include "util.h" | ||
20 | |||
21 | #include <sodium.h> | ||
22 | |||
23 | static void __attribute__((__noreturn__)) handle_interrupt(int signum) | ||
24 | { | ||
25 | fprintf(stderr, "caught signal %d; exiting cleanly.\n", signum); | ||
26 | exit(0); | ||
27 | } | ||
28 | |||
29 | static int protocol_error(msgpack_packer *pk, char const *fmt, ...) | ||
30 | { | ||
31 | msgpack_pack_array(pk, 4); // 4 elements in the array | ||
32 | msgpack_pack_uint8(pk, 1); // 1. type = response | ||
33 | // 2. We don't know the msgid, because the packet we received is not a valid | ||
34 | // msgpack-rpc packet. | ||
35 | msgpack_pack_uint64(pk, 0); | ||
36 | |||
37 | // 3. Error message. | ||
38 | va_list ap; | ||
39 | va_start(ap, fmt); | ||
40 | int res = msgpack_pack_vstringf(pk, fmt, ap); | ||
41 | va_end(ap); | ||
42 | |||
43 | // 4. No success result. | ||
44 | msgpack_pack_array(pk, 0); | ||
45 | |||
46 | return res; | ||
47 | } | ||
48 | |||
49 | static bool type_check(msgpack_packer *pk, msgpack_object req, int index, | ||
50 | msgpack_object_type type) | ||
51 | { | ||
52 | if (req.via.array.ptr[index].type != type) { | ||
53 | protocol_error(pk, "element %d should be %s, but is %s", index, type_name(type), | ||
54 | type_name(req.via.array.ptr[index].type)); | ||
55 | return false; | ||
56 | } | ||
57 | |||
58 | return true; | ||
59 | } | ||
60 | |||
61 | static int close_ptr(int *fd) | ||
62 | { | ||
63 | if (fd && *fd >= 0) { | ||
64 | close(*fd); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | static int write_sample_input(msgpack_object req) | ||
69 | { | ||
70 | static unsigned int n; | ||
71 | |||
72 | char filename[256]; | ||
73 | msgpack_object_str name = req.via.array.ptr[2].via.str; | ||
74 | snprintf(filename, sizeof filename - name.size, "test-inputs/%04u-", n++); | ||
75 | |||
76 | assert(sizeof filename - strlen(filename) > name.size + 4); | ||
77 | memcpy(filename + strlen(filename) + name.size, ".mp", 4); | ||
78 | memcpy(filename + strlen(filename), name.ptr, name.size); | ||
79 | |||
80 | int fd __attribute__((__cleanup__(close_ptr))) = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); | ||
81 | |||
82 | if (fd < 0) | ||
83 | // If we can't open the sample file, we just don't write it. | ||
84 | { | ||
85 | return E_OK; | ||
86 | } | ||
87 | |||
88 | check_return(E_WRITE, ftruncate(fd, 0)); | ||
89 | |||
90 | msgpack_sbuffer sbuf __attribute__((__cleanup__(msgpack_sbuffer_destroy))) = {0}; | ||
91 | msgpack_sbuffer_init(&sbuf); | ||
92 | |||
93 | msgpack_packer pk; | ||
94 | msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); | ||
95 | |||
96 | msgpack_pack_object(&pk, req); | ||
97 | |||
98 | check_return(E_WRITE, write(fd, sbuf.data, sbuf.size)); | ||
99 | check_return(E_WRITE, close(fd)); | ||
100 | |||
101 | return E_OK; | ||
102 | } | ||
103 | |||
104 | static int handle_request(struct settings cfg, int write_fd, msgpack_object req) | ||
105 | { | ||
106 | if (cfg.trace) { | ||
107 | fprintf(stderr, "input: "); | ||
108 | msgpack_object_print(stderr, req); | ||
109 | fprintf(stderr, "\n"); | ||
110 | } | ||
111 | |||
112 | msgpack_sbuffer sbuf __attribute__((__cleanup__(msgpack_sbuffer_destroy))) = {0}; /* buffer */ | ||
113 | msgpack_sbuffer_init(&sbuf); /* initialize buffer */ | ||
114 | |||
115 | msgpack_packer pk; /* packer */ | ||
116 | msgpack_packer_init(&pk, &sbuf, msgpack_sbuffer_write); /* initialize packer */ | ||
117 | |||
118 | if (req.type != MSGPACK_OBJECT_ARRAY) { | ||
119 | protocol_error(&pk, "expected array, but got %s", type_name(req.type)); | ||
120 | } else if (req.via.array.size != 4) { | ||
121 | protocol_error(&pk, "array length should be 4, but is %d", req.via.array.size); | ||
122 | } else if (type_check(&pk, req, 0, MSGPACK_OBJECT_POSITIVE_INTEGER) && | ||
123 | type_check(&pk, req, 1, MSGPACK_OBJECT_POSITIVE_INTEGER) && | ||
124 | type_check(&pk, req, 2, MSGPACK_OBJECT_STR) && | ||
125 | type_check(&pk, req, 3, MSGPACK_OBJECT_ARRAY)) { | ||
126 | if (cfg.collect_samples) { | ||
127 | propagate(write_sample_input(req)); | ||
128 | } | ||
129 | |||
130 | uint64_t msgid = req.via.array.ptr[1].via.u64; | ||
131 | msgpack_object_str name = req.via.array.ptr[2].via.str; | ||
132 | msgpack_object_array args = req.via.array.ptr[3].via.array; | ||
133 | |||
134 | msgpack_pack_array(&pk, 4); // 4 elements in the array | ||
135 | msgpack_pack_uint8(&pk, 1); // 1. type = response | ||
136 | msgpack_pack_uint64(&pk, msgid); // 2. msgid | ||
137 | |||
138 | if (name.size == (sizeof "rpc.capabilities") - 1 && | ||
139 | memcmp(name.ptr, "rpc.capabilities", name.size) == 0) { | ||
140 | // 3. Error. | ||
141 | msgpack_pack_string(&pk, "capabilities negiotiation not implemented"); | ||
142 | // 4. No result. | ||
143 | msgpack_pack_nil(&pk); | ||
144 | } else { | ||
145 | // if error is null, this writes 3. no error, and 4. result | ||
146 | char const *error = | ||
147 | call_method(name, args, &pk); | ||
148 | |||
149 | if (error) { | ||
150 | if (cfg.debug) { | ||
151 | fprintf(stderr, "error '%s' in request: ", error); | ||
152 | msgpack_object_print(stderr, req); | ||
153 | fprintf(stderr, "\n"); | ||
154 | } | ||
155 | |||
156 | msgpack_pack_string(&pk, error); | ||
157 | msgpack_pack_array(&pk, 0); | ||
158 | } | ||
159 | } | ||
160 | } | ||
161 | |||
162 | check_return(E_WRITE, write(write_fd, sbuf.data, sbuf.size)); | ||
163 | |||
164 | if (cfg.trace) { | ||
165 | fprintf(stderr, "result: "); | ||
166 | msgpack_unpacked res __attribute__((__cleanup__(msgpack_unpacked_destroy))); | ||
167 | msgpack_unpacked_init(&res); | ||
168 | msgpack_unpack_next(&res, sbuf.data, sbuf.size, NULL); | ||
169 | msgpack_object_print(stderr, res.data); | ||
170 | fprintf(stderr, "\n"); | ||
171 | } | ||
172 | |||
173 | return E_OK; | ||
174 | } | ||
175 | |||
176 | int communicate(struct settings cfg, int read_fd, int write_fd) | ||
177 | { | ||
178 | msgpack_unpacker unp __attribute__((__cleanup__(msgpack_unpacker_destroy))); | ||
179 | msgpack_unpacker_init(&unp, 128); | ||
180 | |||
181 | while (true) { | ||
182 | char buf[64]; | ||
183 | int size = check_return(E_READ, read(read_fd, buf, sizeof buf)); | ||
184 | |||
185 | if (size == 0) { | ||
186 | break; | ||
187 | } | ||
188 | |||
189 | if (msgpack_unpacker_buffer_capacity(&unp) < size && | ||
190 | !msgpack_unpacker_reserve_buffer(&unp, size)) { | ||
191 | return E_NOMEM; | ||
192 | } | ||
193 | |||
194 | memcpy(msgpack_unpacker_buffer(&unp), buf, size); | ||
195 | msgpack_unpacker_buffer_consumed(&unp, size); | ||
196 | |||
197 | msgpack_unpacked req __attribute__((__cleanup__(msgpack_unpacked_destroy))) = {0}; | ||
198 | msgpack_unpacked_init(&req); | ||
199 | |||
200 | switch (msgpack_unpacker_next(&unp, &req)) { | ||
201 | case MSGPACK_UNPACK_SUCCESS: | ||
202 | propagate(handle_request(cfg, write_fd, req.data)); | ||
203 | break; | ||
204 | |||
205 | case MSGPACK_UNPACK_EXTRA_BYTES: | ||
206 | fprintf(stderr, "EXTRA_BYTES\n"); | ||
207 | break; | ||
208 | |||
209 | case MSGPACK_UNPACK_CONTINUE: | ||
210 | break; | ||
211 | |||
212 | case MSGPACK_UNPACK_PARSE_ERROR: | ||
213 | return E_PARSE; | ||
214 | |||
215 | case MSGPACK_UNPACK_NOMEM_ERROR: | ||
216 | return E_NOMEM; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | return E_OK; | ||
221 | } | ||
222 | |||
223 | static int closep(int *fd) | ||
224 | { | ||
225 | return close(*fd); | ||
226 | } | ||
227 | |||
228 | static int run_tests(struct settings cfg, int port) | ||
229 | { | ||
230 | int listen_fd __attribute__((__cleanup__(closep))) = 0; | ||
231 | listen_fd = check_return(E_SOCKET, socket(AF_INET, SOCK_STREAM, 0)); | ||
232 | check_return(E_SOCKET, setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &(int) { | ||
233 | 1 | ||
234 | }, sizeof(int))); | ||
235 | |||
236 | struct sockaddr_in servaddr = {0}; | ||
237 | servaddr.sin_family = AF_INET; | ||
238 | servaddr.sin_addr.s_addr = htons(INADDR_ANY); | ||
239 | servaddr.sin_port = htons(port); | ||
240 | |||
241 | check_return(E_BIND, bind(listen_fd, (struct sockaddr *)&servaddr, sizeof servaddr)); | ||
242 | check_return(E_LISTEN, listen(listen_fd, 10)); | ||
243 | |||
244 | while (true) { | ||
245 | int comm_fd __attribute__((__cleanup__(closep))) = 0; | ||
246 | comm_fd = check_return(E_ACCEPT, accept(listen_fd, NULL, NULL)); | ||
247 | propagate(communicate(cfg, comm_fd, comm_fd)); | ||
248 | } | ||
249 | |||
250 | return E_OK; | ||
251 | } | ||
252 | |||
253 | uint32_t network_main(struct settings cfg, uint16_t port, unsigned int timeout) | ||
254 | { | ||
255 | signal(SIGALRM, handle_interrupt); | ||
256 | signal(SIGINT, handle_interrupt); | ||
257 | check_return(E_SODIUM, sodium_init()); | ||
258 | |||
259 | // Kill the process after `timeout` seconds so we don't get lingering | ||
260 | // processes bound to the test port when something goes wrong with a test run. | ||
261 | alarm(timeout); | ||
262 | |||
263 | int result = run_tests(cfg, port); | ||
264 | |||
265 | if (result == E_OK) { | ||
266 | return E_OK; | ||
267 | } | ||
268 | |||
269 | return result | (errno << 8); | ||
270 | } | ||