c@23
|
1
|
c@23
|
2 #include "VampJson.h"
|
c@23
|
3 #include "VampnProto.h"
|
c@23
|
4
|
c@31
|
5 #include "bits/RequestOrResponse.h"
|
c@32
|
6 #include "bits/PreservingPluginHandleMapper.h"
|
c@31
|
7
|
c@23
|
8 #include <iostream>
|
c@23
|
9 #include <sstream>
|
c@23
|
10 #include <stdexcept>
|
c@23
|
11
|
c@23
|
12 using namespace std;
|
c@23
|
13 using namespace json11;
|
c@23
|
14 using namespace vampipe;
|
c@23
|
15
|
c@23
|
16 void usage()
|
c@23
|
17 {
|
c@23
|
18 string myname = "vampipe-convert";
|
c@23
|
19 cerr << "\n" << myname <<
|
c@24
|
20 ": Validate and convert Vamp request and response messages\n\n"
|
c@24
|
21 " Usage: " << myname << " [-i <informat>] [-o <outformat>] request\n"
|
c@24
|
22 " " << myname << " [-i <informat>] [-o <outformat>] response\n\n"
|
c@24
|
23 " where\n"
|
c@24
|
24 " <informat>: the format to read from stdin\n"
|
c@24
|
25 " (\"json\" or \"capnp\", default is \"json\")\n"
|
c@24
|
26 " <outformat>: the format to convert to and write to stdout\n"
|
c@44
|
27 " (\"json\", \"json-b64\" or \"capnp\", default is \"json\")\n"
|
c@44
|
28 " request|response: whether messages are Vamp request or response type\n\n"
|
c@24
|
29 "If <informat> and <outformat> differ, convert from <informat> to <outformat>.\n"
|
c@24
|
30 "If <informat> and <outformat> are the same, just check validity of incoming\n"
|
c@44
|
31 "messages and pass them to output.\n\n"
|
c@44
|
32 "Specifying \"json-b64\" as output format forces base64 encoding for process and\n"
|
c@44
|
33 "feature blocks, unlike the \"json\" output format which uses text encoding.\n"
|
c@44
|
34 "The \"json\" input format accepts either.\n\n";
|
c@24
|
35
|
c@23
|
36 exit(2);
|
c@23
|
37 }
|
c@23
|
38
|
c@24
|
39 Json
|
c@60
|
40 convertRequestJson(string input, string &err)
|
c@24
|
41 {
|
c@24
|
42 Json j = Json::parse(input, err);
|
c@24
|
43 if (err != "") {
|
c@60
|
44 err = "invalid json: " + err;
|
c@60
|
45 return {};
|
c@24
|
46 }
|
c@24
|
47 if (!j.is_object()) {
|
c@60
|
48 err = "object expected at top level";
|
c@67
|
49 } else if (!j["method"].is_string()) {
|
c@67
|
50 err = "string expected for method field";
|
c@67
|
51 } else if (!j["params"].is_null() && !j["params"].is_object()) {
|
c@67
|
52 err = "object expected for params field";
|
c@24
|
53 }
|
c@24
|
54 return j;
|
c@24
|
55 }
|
c@24
|
56
|
c@24
|
57 Json
|
c@60
|
58 convertResponseJson(string input, string &err)
|
c@24
|
59 {
|
c@24
|
60 Json j = Json::parse(input, err);
|
c@24
|
61 if (err != "") {
|
c@60
|
62 err = "invalid json: " + err;
|
c@60
|
63 return {};
|
c@24
|
64 }
|
c@24
|
65 if (!j.is_object()) {
|
c@60
|
66 err = "object expected at top level";
|
c@67
|
67 } else {
|
c@67
|
68 if (!j["result"].is_object()) {
|
c@67
|
69 if (!j["error"].is_object()) {
|
c@67
|
70 err = "expected either result or error object";
|
c@67
|
71 }
|
c@67
|
72 }
|
c@24
|
73 }
|
c@24
|
74 return j;
|
c@24
|
75 }
|
c@24
|
76
|
c@30
|
77 //!!! Lots of potential for refactoring the conversion classes based
|
c@30
|
78 //!!! on the common matter in the following eight functions...
|
c@30
|
79
|
c@32
|
80 PreservingPluginHandleMapper mapper;
|
c@32
|
81
|
c@23
|
82 RequestOrResponse
|
c@60
|
83 readRequestJson(string &err)
|
c@23
|
84 {
|
c@23
|
85 RequestOrResponse rr;
|
c@24
|
86 rr.direction = RequestOrResponse::Request;
|
c@24
|
87
|
c@24
|
88 string input;
|
c@24
|
89 if (!getline(cin, input)) {
|
c@60
|
90 // the EOF case, not actually an error
|
c@25
|
91 rr.type = RRType::NotValid;
|
c@24
|
92 return rr;
|
c@24
|
93 }
|
c@24
|
94
|
c@60
|
95 Json j = convertRequestJson(input, err);
|
c@60
|
96 if (err != "") return {};
|
c@27
|
97
|
c@60
|
98 rr.type = VampJson::getRequestResponseType(j, err);
|
c@60
|
99 if (err != "") return {};
|
c@60
|
100
|
c@66
|
101 VampJson::BufferSerialisation serialisation =
|
c@66
|
102 VampJson::BufferSerialisation::Array;
|
c@24
|
103
|
c@27
|
104 switch (rr.type) {
|
c@27
|
105
|
c@27
|
106 case RRType::List:
|
c@60
|
107 VampJson::toVampRequest_List(j, err); // type check only
|
c@27
|
108 break;
|
c@27
|
109 case RRType::Load:
|
c@60
|
110 rr.loadRequest = VampJson::toVampRequest_Load(j, err);
|
c@27
|
111 break;
|
c@27
|
112 case RRType::Configure:
|
c@60
|
113 rr.configurationRequest = VampJson::toVampRequest_Configure(j, mapper, err);
|
c@27
|
114 break;
|
c@27
|
115 case RRType::Process:
|
c@60
|
116 rr.processRequest = VampJson::toVampRequest_Process(j, mapper, serialisation, err);
|
c@27
|
117 break;
|
c@27
|
118 case RRType::Finish:
|
c@60
|
119 rr.finishRequest = VampJson::toVampRequest_Finish(j, mapper, err);
|
c@27
|
120 break;
|
c@27
|
121 case RRType::NotValid:
|
c@27
|
122 break;
|
c@24
|
123 }
|
c@24
|
124
|
c@24
|
125 return rr;
|
c@24
|
126 }
|
c@24
|
127
|
c@24
|
128 void
|
c@44
|
129 writeRequestJson(RequestOrResponse &rr, bool useBase64)
|
c@24
|
130 {
|
c@24
|
131 Json j;
|
c@24
|
132
|
c@54
|
133 VampJson::BufferSerialisation serialisation =
|
c@54
|
134 (useBase64 ?
|
c@54
|
135 VampJson::BufferSerialisation::Base64 :
|
c@66
|
136 VampJson::BufferSerialisation::Array);
|
c@54
|
137
|
c@27
|
138 switch (rr.type) {
|
c@27
|
139
|
c@27
|
140 case RRType::List:
|
c@24
|
141 j = VampJson::fromVampRequest_List();
|
c@27
|
142 break;
|
c@27
|
143 case RRType::Load:
|
c@24
|
144 j = VampJson::fromVampRequest_Load(rr.loadRequest);
|
c@27
|
145 break;
|
c@27
|
146 case RRType::Configure:
|
c@32
|
147 j = VampJson::fromVampRequest_Configure(rr.configurationRequest, mapper);
|
c@27
|
148 break;
|
c@27
|
149 case RRType::Process:
|
c@44
|
150 j = VampJson::fromVampRequest_Process
|
c@54
|
151 (rr.processRequest, mapper, serialisation);
|
c@27
|
152 break;
|
c@27
|
153 case RRType::Finish:
|
c@55
|
154 j = VampJson::fromVampRequest_Finish(rr.finishRequest, mapper);
|
c@27
|
155 break;
|
c@27
|
156 case RRType::NotValid:
|
c@27
|
157 break;
|
c@24
|
158 }
|
c@24
|
159
|
c@24
|
160 cout << j.dump() << endl;
|
c@24
|
161 }
|
c@24
|
162
|
c@24
|
163 RequestOrResponse
|
c@60
|
164 readResponseJson(string &err)
|
c@24
|
165 {
|
c@24
|
166 RequestOrResponse rr;
|
c@24
|
167 rr.direction = RequestOrResponse::Response;
|
c@24
|
168
|
c@23
|
169 string input;
|
c@23
|
170 if (!getline(cin, input)) {
|
c@60
|
171 // the EOF case, not actually an error
|
c@25
|
172 rr.type = RRType::NotValid;
|
c@23
|
173 return rr;
|
c@23
|
174 }
|
c@23
|
175
|
c@60
|
176 Json j = convertResponseJson(input, err);
|
c@60
|
177 if (err != "") return {};
|
c@27
|
178
|
c@60
|
179 rr.type = VampJson::getRequestResponseType(j, err);
|
c@60
|
180 if (err != "") return {};
|
c@60
|
181
|
c@66
|
182 VampJson::BufferSerialisation serialisation =
|
c@66
|
183 VampJson::BufferSerialisation::Array;
|
c@23
|
184
|
c@52
|
185 rr.success = j["success"].bool_value();
|
c@52
|
186 rr.errorText = j["errorText"].string_value();
|
c@52
|
187
|
c@27
|
188 switch (rr.type) {
|
c@27
|
189
|
c@27
|
190 case RRType::List:
|
c@60
|
191 rr.listResponse = VampJson::toVampResponse_List(j, err);
|
c@27
|
192 break;
|
c@27
|
193 case RRType::Load:
|
c@60
|
194 rr.loadResponse = VampJson::toVampResponse_Load(j, mapper, err);
|
c@27
|
195 break;
|
c@27
|
196 case RRType::Configure:
|
c@60
|
197 rr.configurationResponse = VampJson::toVampResponse_Configure(j, mapper, err);
|
c@27
|
198 break;
|
c@27
|
199 case RRType::Process:
|
c@60
|
200 rr.processResponse = VampJson::toVampResponse_Process(j, mapper, serialisation, err);
|
c@27
|
201 break;
|
c@27
|
202 case RRType::Finish:
|
c@60
|
203 rr.finishResponse = VampJson::toVampResponse_Finish(j, mapper, serialisation, err);
|
c@27
|
204 break;
|
c@27
|
205 case RRType::NotValid:
|
c@27
|
206 break;
|
c@23
|
207 }
|
c@23
|
208
|
c@23
|
209 return rr;
|
c@23
|
210 }
|
c@23
|
211
|
c@24
|
212 void
|
c@44
|
213 writeResponseJson(RequestOrResponse &rr, bool useBase64)
|
c@24
|
214 {
|
c@24
|
215 Json j;
|
c@24
|
216
|
c@53
|
217 VampJson::BufferSerialisation serialisation =
|
c@54
|
218 (useBase64 ?
|
c@53
|
219 VampJson::BufferSerialisation::Base64 :
|
c@66
|
220 VampJson::BufferSerialisation::Array);
|
c@53
|
221
|
c@52
|
222 if (!rr.success) {
|
c@27
|
223
|
c@52
|
224 j = VampJson::fromError(rr.errorText, rr.type);
|
c@52
|
225
|
c@52
|
226 } else {
|
c@52
|
227
|
c@52
|
228 switch (rr.type) {
|
c@52
|
229
|
c@52
|
230 case RRType::List:
|
c@59
|
231 j = VampJson::fromVampResponse_List(rr.listResponse);
|
c@52
|
232 break;
|
c@52
|
233 case RRType::Load:
|
c@52
|
234 j = VampJson::fromVampResponse_Load(rr.loadResponse, mapper);
|
c@52
|
235 break;
|
c@52
|
236 case RRType::Configure:
|
c@55
|
237 j = VampJson::fromVampResponse_Configure(rr.configurationResponse,
|
c@55
|
238 mapper);
|
c@52
|
239 break;
|
c@52
|
240 case RRType::Process:
|
c@52
|
241 j = VampJson::fromVampResponse_Process
|
c@53
|
242 (rr.processResponse, mapper, serialisation);
|
c@52
|
243 break;
|
c@52
|
244 case RRType::Finish:
|
c@52
|
245 j = VampJson::fromVampResponse_Finish
|
c@53
|
246 (rr.finishResponse, mapper, serialisation);
|
c@52
|
247 break;
|
c@52
|
248 case RRType::NotValid:
|
c@52
|
249 break;
|
c@52
|
250 }
|
c@24
|
251 }
|
c@52
|
252
|
c@27
|
253 cout << j.dump() << endl;
|
c@27
|
254 }
|
c@25
|
255
|
c@27
|
256 RequestOrResponse
|
c@33
|
257 readRequestCapnp(kj::BufferedInputStreamWrapper &buffered)
|
c@27
|
258 {
|
c@27
|
259 RequestOrResponse rr;
|
c@27
|
260 rr.direction = RequestOrResponse::Request;
|
c@27
|
261
|
c@33
|
262 ::capnp::InputStreamMessageReader message(buffered);
|
c@27
|
263 VampRequest::Reader reader = message.getRoot<VampRequest>();
|
c@27
|
264
|
c@27
|
265 rr.type = VampnProto::getRequestResponseType(reader);
|
c@27
|
266
|
c@27
|
267 switch (rr.type) {
|
c@27
|
268
|
c@27
|
269 case RRType::List:
|
c@27
|
270 VampnProto::readVampRequest_List(reader); // type check only
|
c@27
|
271 break;
|
c@27
|
272 case RRType::Load:
|
c@27
|
273 VampnProto::readVampRequest_Load(rr.loadRequest, reader);
|
c@27
|
274 break;
|
c@27
|
275 case RRType::Configure:
|
c@32
|
276 VampnProto::readVampRequest_Configure(rr.configurationRequest,
|
c@32
|
277 reader, mapper);
|
c@27
|
278 break;
|
c@27
|
279 case RRType::Process:
|
c@32
|
280 VampnProto::readVampRequest_Process(rr.processRequest, reader, mapper);
|
c@27
|
281 break;
|
c@27
|
282 case RRType::Finish:
|
c@55
|
283 VampnProto::readVampRequest_Finish(rr.finishRequest, reader, mapper);
|
c@27
|
284 break;
|
c@27
|
285 case RRType::NotValid:
|
c@27
|
286 break;
|
c@27
|
287 }
|
c@27
|
288
|
c@27
|
289 return rr;
|
c@27
|
290 }
|
c@27
|
291
|
c@29
|
292 void
|
c@29
|
293 writeRequestCapnp(RequestOrResponse &rr)
|
c@29
|
294 {
|
c@29
|
295 ::capnp::MallocMessageBuilder message;
|
c@29
|
296 VampRequest::Builder builder = message.initRoot<VampRequest>();
|
c@29
|
297
|
c@29
|
298 switch (rr.type) {
|
c@29
|
299
|
c@29
|
300 case RRType::List:
|
c@29
|
301 VampnProto::buildVampRequest_List(builder);
|
c@29
|
302 break;
|
c@29
|
303 case RRType::Load:
|
c@29
|
304 VampnProto::buildVampRequest_Load(builder, rr.loadRequest);
|
c@29
|
305 break;
|
c@29
|
306 case RRType::Configure:
|
c@29
|
307 VampnProto::buildVampRequest_Configure(builder,
|
c@32
|
308 rr.configurationRequest, mapper);
|
c@29
|
309 break;
|
c@29
|
310 case RRType::Process:
|
c@32
|
311 VampnProto::buildVampRequest_Process(builder, rr.processRequest, mapper);
|
c@29
|
312 break;
|
c@29
|
313 case RRType::Finish:
|
c@55
|
314 VampnProto::buildVampRequest_Finish(builder, rr.finishRequest, mapper);
|
c@29
|
315 break;
|
c@29
|
316 case RRType::NotValid:
|
c@29
|
317 break;
|
c@29
|
318 }
|
c@29
|
319
|
c@33
|
320 writeMessageToFd(1, message);
|
c@29
|
321 }
|
c@29
|
322
|
c@27
|
323 RequestOrResponse
|
c@33
|
324 readResponseCapnp(kj::BufferedInputStreamWrapper &buffered)
|
c@27
|
325 {
|
c@27
|
326 RequestOrResponse rr;
|
c@27
|
327 rr.direction = RequestOrResponse::Response;
|
c@27
|
328
|
c@33
|
329 ::capnp::InputStreamMessageReader message(buffered);
|
c@27
|
330 VampResponse::Reader reader = message.getRoot<VampResponse>();
|
c@27
|
331
|
c@27
|
332 rr.type = VampnProto::getRequestResponseType(reader);
|
c@52
|
333 rr.success = reader.getSuccess();
|
c@52
|
334 rr.errorText = reader.getErrorText();
|
c@27
|
335
|
c@27
|
336 switch (rr.type) {
|
c@27
|
337
|
c@27
|
338 case RRType::List:
|
c@27
|
339 VampnProto::readVampResponse_List(rr.listResponse, reader);
|
c@27
|
340 break;
|
c@27
|
341 case RRType::Load:
|
c@32
|
342 VampnProto::readVampResponse_Load(rr.loadResponse, reader, mapper);
|
c@27
|
343 break;
|
c@27
|
344 case RRType::Configure:
|
c@27
|
345 VampnProto::readVampResponse_Configure(rr.configurationResponse,
|
c@55
|
346 reader, mapper);
|
c@27
|
347 break;
|
c@27
|
348 case RRType::Process:
|
c@51
|
349 VampnProto::readVampResponse_Process(rr.processResponse, reader, mapper);
|
c@27
|
350 break;
|
c@27
|
351 case RRType::Finish:
|
c@51
|
352 VampnProto::readVampResponse_Finish(rr.finishResponse, reader, mapper);
|
c@27
|
353 break;
|
c@27
|
354 case RRType::NotValid:
|
c@27
|
355 break;
|
c@27
|
356 }
|
c@27
|
357
|
c@27
|
358 return rr;
|
c@24
|
359 }
|
c@24
|
360
|
c@29
|
361 void
|
c@29
|
362 writeResponseCapnp(RequestOrResponse &rr)
|
c@29
|
363 {
|
c@29
|
364 ::capnp::MallocMessageBuilder message;
|
c@29
|
365 VampResponse::Builder builder = message.initRoot<VampResponse>();
|
c@29
|
366
|
c@52
|
367 if (!rr.success) {
|
c@29
|
368
|
c@52
|
369 VampnProto::buildVampResponse_Error(builder, rr.errorText, rr.type);
|
c@52
|
370
|
c@52
|
371 } else {
|
c@52
|
372
|
c@52
|
373 switch (rr.type) {
|
c@52
|
374
|
c@52
|
375 case RRType::List:
|
c@56
|
376 VampnProto::buildVampResponse_List(builder, rr.listResponse);
|
c@52
|
377 break;
|
c@52
|
378 case RRType::Load:
|
c@52
|
379 VampnProto::buildVampResponse_Load(builder, rr.loadResponse, mapper);
|
c@52
|
380 break;
|
c@52
|
381 case RRType::Configure:
|
c@55
|
382 VampnProto::buildVampResponse_Configure(builder, rr.configurationResponse, mapper);
|
c@52
|
383 break;
|
c@52
|
384 case RRType::Process:
|
c@52
|
385 VampnProto::buildVampResponse_Process(builder, rr.processResponse, mapper);
|
c@52
|
386 break;
|
c@52
|
387 case RRType::Finish:
|
c@52
|
388 VampnProto::buildVampResponse_Finish(builder, rr.finishResponse, mapper);
|
c@52
|
389 break;
|
c@52
|
390 case RRType::NotValid:
|
c@52
|
391 break;
|
c@52
|
392 }
|
c@29
|
393 }
|
c@52
|
394
|
c@33
|
395 writeMessageToFd(1, message);
|
c@33
|
396 }
|
c@33
|
397
|
c@33
|
398 RequestOrResponse
|
c@60
|
399 readInputJson(RequestOrResponse::Direction direction, string &err)
|
c@33
|
400 {
|
c@33
|
401 if (direction == RequestOrResponse::Request) {
|
c@60
|
402 return readRequestJson(err);
|
c@33
|
403 } else {
|
c@60
|
404 return readResponseJson(err);
|
c@33
|
405 }
|
c@33
|
406 }
|
c@33
|
407
|
c@33
|
408 RequestOrResponse
|
c@33
|
409 readInputCapnp(RequestOrResponse::Direction direction)
|
c@33
|
410 {
|
c@33
|
411 static kj::FdInputStream stream(0); // stdin
|
c@33
|
412 static kj::BufferedInputStreamWrapper buffered(stream);
|
c@33
|
413
|
c@33
|
414 if (buffered.tryGetReadBuffer() == nullptr) {
|
c@33
|
415 return {};
|
c@33
|
416 }
|
c@33
|
417
|
c@33
|
418 if (direction == RequestOrResponse::Request) {
|
c@33
|
419 return readRequestCapnp(buffered);
|
c@33
|
420 } else {
|
c@33
|
421 return readResponseCapnp(buffered);
|
c@33
|
422 }
|
c@29
|
423 }
|
c@29
|
424
|
c@23
|
425 RequestOrResponse
|
c@24
|
426 readInput(string format, RequestOrResponse::Direction direction)
|
c@23
|
427 {
|
c@23
|
428 if (format == "json") {
|
c@60
|
429 string err;
|
c@60
|
430 auto result = readInputJson(direction, err);
|
c@60
|
431 if (err != "") throw runtime_error(err);
|
c@60
|
432 else return result;
|
c@27
|
433 } else if (format == "capnp") {
|
c@33
|
434 return readInputCapnp(direction);
|
c@23
|
435 } else {
|
c@27
|
436 throw runtime_error("unknown input format \"" + format + "\"");
|
c@23
|
437 }
|
c@23
|
438 }
|
c@23
|
439
|
c@23
|
440 void
|
c@24
|
441 writeOutput(string format, RequestOrResponse &rr)
|
c@23
|
442 {
|
c@24
|
443 if (format == "json") {
|
c@24
|
444 if (rr.direction == RequestOrResponse::Request) {
|
c@44
|
445 writeRequestJson(rr, false);
|
c@24
|
446 } else {
|
c@44
|
447 writeResponseJson(rr, false);
|
c@44
|
448 }
|
c@44
|
449 } else if (format == "json-b64") {
|
c@44
|
450 if (rr.direction == RequestOrResponse::Request) {
|
c@44
|
451 writeRequestJson(rr, true);
|
c@44
|
452 } else {
|
c@44
|
453 writeResponseJson(rr, true);
|
c@24
|
454 }
|
c@29
|
455 } else if (format == "capnp") {
|
c@29
|
456 if (rr.direction == RequestOrResponse::Request) {
|
c@29
|
457 writeRequestCapnp(rr);
|
c@29
|
458 } else {
|
c@29
|
459 writeResponseCapnp(rr);
|
c@29
|
460 }
|
c@24
|
461 } else {
|
c@27
|
462 throw runtime_error("unknown output format \"" + format + "\"");
|
c@24
|
463 }
|
c@23
|
464 }
|
c@23
|
465
|
c@23
|
466 int main(int argc, char **argv)
|
c@23
|
467 {
|
c@24
|
468 if (argc < 2) {
|
c@23
|
469 usage();
|
c@23
|
470 }
|
c@23
|
471
|
c@24
|
472 string informat = "json", outformat = "json";
|
c@27
|
473 RequestOrResponse::Direction direction = RequestOrResponse::Request;
|
c@24
|
474 bool haveDirection = false;
|
c@23
|
475
|
c@24
|
476 for (int i = 1; i < argc; ++i) {
|
c@23
|
477
|
c@23
|
478 string arg = argv[i];
|
c@24
|
479 bool final = (i + 1 == argc);
|
c@23
|
480
|
c@23
|
481 if (arg == "-i") {
|
c@27
|
482 if (final) usage();
|
c@23
|
483 else informat = argv[++i];
|
c@23
|
484
|
c@23
|
485 } else if (arg == "-o") {
|
c@27
|
486 if (final) usage();
|
c@23
|
487 else outformat = argv[++i];
|
c@23
|
488
|
c@24
|
489 } else if (arg == "request") {
|
c@24
|
490 direction = RequestOrResponse::Request;
|
c@24
|
491 haveDirection = true;
|
c@24
|
492
|
c@24
|
493 } else if (arg == "response") {
|
c@24
|
494 direction = RequestOrResponse::Response;
|
c@24
|
495 haveDirection = true;
|
c@24
|
496
|
c@23
|
497 } else {
|
c@23
|
498 usage();
|
c@23
|
499 }
|
c@23
|
500 }
|
c@23
|
501
|
c@24
|
502 if (informat == "" || outformat == "" || !haveDirection) {
|
c@23
|
503 usage();
|
c@23
|
504 }
|
c@23
|
505
|
c@23
|
506 while (true) {
|
c@23
|
507
|
c@23
|
508 try {
|
c@23
|
509
|
c@24
|
510 RequestOrResponse rr = readInput(informat, direction);
|
c@29
|
511
|
c@29
|
512 // NotValid without an exception indicates EOF:
|
c@25
|
513 if (rr.type == RRType::NotValid) break;
|
c@29
|
514
|
c@23
|
515 writeOutput(outformat, rr);
|
c@23
|
516
|
c@23
|
517 } catch (std::exception &e) {
|
c@52
|
518
|
c@23
|
519 cerr << "Error: " << e.what() << endl;
|
c@23
|
520 exit(1);
|
c@23
|
521 }
|
c@23
|
522 }
|
c@23
|
523
|
c@23
|
524 exit(0);
|
c@23
|
525 }
|
c@23
|
526
|
c@23
|
527
|