comparison vamp-server/convert.cpp @ 116:d15cb1151d76

Add JSON support directly to the server. Had hoped to avoid this (using Capnp as canonical in the server and then converting externally as necessary) but it's just too useful for debugging purposes when bundled with client app
author Chris Cannam <c.cannam@qmul.ac.uk>
date Thu, 27 Oct 2016 11:39:41 +0100
parents 427c4c725085
children ff3fd8d1b2dc
comparison
equal deleted inserted replaced
115:5a716f08e4be 116:d15cb1151d76
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
1 2
2 #include "vamp-json/VampJson.h" 3 #include "vamp-json/VampJson.h"
3 #include "vamp-capnp/VampnProto.h" 4 #include "vamp-capnp/VampnProto.h"
4 #include "vamp-support/RequestOrResponse.h" 5 #include "vamp-support/RequestOrResponse.h"
5 #include "vamp-support/PreservingPluginHandleMapper.h" 6 #include "vamp-support/PreservingPluginHandleMapper.h"
16 17
17 void usage() 18 void usage()
18 { 19 {
19 string myname = "piper-convert"; 20 string myname = "piper-convert";
20 cerr << "\n" << myname << 21 cerr << "\n" << myname <<
21 ": Validate and convert Piper request and response messages\n\n" 22 ": Validate and convert Piper request and response messages\n\n"
22 " Usage: " << myname << " [-i <informat>] [-o <outformat>] request\n" 23 " Usage: " << myname << " [-i <informat>] [-o <outformat>] request\n"
23 " " << myname << " [-i <informat>] [-o <outformat>] response\n\n" 24 " " << myname << " [-i <informat>] [-o <outformat>] response\n\n"
24 " where\n" 25 " where\n"
25 " <informat>: the format to read from stdin\n" 26 " <informat>: the format to read from stdin\n"
26 " (\"json\" or \"capnp\", default is \"json\")\n" 27 " (\"json\" or \"capnp\", default is \"json\")\n"
27 " <outformat>: the format to convert to and write to stdout\n" 28 " <outformat>: the format to convert to and write to stdout\n"
28 " (\"json\", \"json-b64\" or \"capnp\", default is \"json\")\n" 29 " (\"json\", \"json-b64\" or \"capnp\", default is \"json\")\n"
29 " request|response: whether messages are Vamp request or response type\n\n" 30 " request|response: whether messages are Vamp request or response type\n\n"
30 "If <informat> and <outformat> differ, convert from <informat> to <outformat>.\n" 31 "If <informat> and <outformat> differ, convert from <informat> to <outformat>.\n"
31 "If <informat> and <outformat> are the same, just check validity of incoming\n" 32 "If <informat> and <outformat> are the same, just check validity of incoming\n"
32 "messages and pass them to output.\n\n" 33 "messages and pass them to output.\n\n"
33 "Specifying \"json-b64\" as output format forces base64 encoding for process and\n" 34 "Specifying \"json-b64\" as output format forces base64 encoding for process and\n"
34 "feature blocks, unlike the \"json\" output format which uses text encoding.\n" 35 "feature blocks, unlike the \"json\" output format which uses text encoding.\n"
35 "The \"json\" input format accepts either.\n\n"; 36 "The \"json\" input format accepts either.\n\n";
36 37
37 exit(2); 38 exit(2);
38 } 39 }
39 40
40 Json 41 Json
41 convertRequestJson(string input, string &err) 42 convertRequestJson(string input, string &err)
42 { 43 {
43 Json j = Json::parse(input, err); 44 Json j = Json::parse(input, err);
44 if (err != "") { 45 if (err != "") {
45 err = "invalid json: " + err; 46 err = "invalid json: " + err;
46 return {}; 47 return {};
47 } 48 }
48 if (!j.is_object()) { 49 if (!j.is_object()) {
49 err = "object expected at top level"; 50 err = "object expected at top level";
50 } else if (!j["method"].is_string()) { 51 } else if (!j["method"].is_string()) {
51 err = "string expected for method field"; 52 err = "string expected for method field";
52 } else if (!j["params"].is_null() && !j["params"].is_object()) { 53 } else if (!j["params"].is_null() && !j["params"].is_object()) {
53 err = "object expected for params field"; 54 err = "object expected for params field";
54 } 55 }
55 return j; 56 return j;
56 } 57 }
57 58
58 Json 59 Json
59 convertResponseJson(string input, string &err) 60 convertResponseJson(string input, string &err)
60 { 61 {
61 Json j = Json::parse(input, err); 62 Json j = Json::parse(input, err);
62 if (err != "") { 63 if (err != "") {
63 err = "invalid json: " + err; 64 err = "invalid json: " + err;
64 return {}; 65 return {};
65 } 66 }
66 if (!j.is_object()) { 67 if (!j.is_object()) {
67 err = "object expected at top level"; 68 err = "object expected at top level";
68 } else { 69 } else {
69 if (!j["result"].is_object()) { 70 if (!j["result"].is_object()) {
70 if (!j["error"].is_object()) { 71 if (!j["error"].is_object()) {
71 err = "expected either result or error object"; 72 err = "expected either result or error object";
72 } 73 }
152 RequestOrResponse rr; 153 RequestOrResponse rr;
153 rr.direction = RequestOrResponse::Request; 154 rr.direction = RequestOrResponse::Request;
154 155
155 string input; 156 string input;
156 if (!getline(cin, input)) { 157 if (!getline(cin, input)) {
157 // the EOF case, not actually an error 158 // the EOF case, not actually an error
158 rr.type = RRType::NotValid; 159 rr.type = RRType::NotValid;
159 return rr; 160 return rr;
160 } 161 }
161 162
162 Json j = convertRequestJson(input, err); 163 Json j = convertRequestJson(input, err);
163 if (err != "") return {}; 164 if (err != "") return {};
164 165
171 VampJson::BufferSerialisation::Array; 172 VampJson::BufferSerialisation::Array;
172 173
173 switch (rr.type) { 174 switch (rr.type) {
174 175
175 case RRType::List: 176 case RRType::List:
176 VampJson::toRpcRequest_List(j, err); // type check only 177 VampJson::toRpcRequest_List(j, err); // type check only
177 break; 178 break;
178 case RRType::Load: 179 case RRType::Load:
179 rr.loadRequest = VampJson::toRpcRequest_Load(j, err); 180 rr.loadRequest = VampJson::toRpcRequest_Load(j, err);
180 break; 181 break;
181 case RRType::Configure: 182 case RRType::Configure:
182 rr.configurationRequest = VampJson::toRpcRequest_Configure(j, mapper, err); 183 rr.configurationRequest = VampJson::toRpcRequest_Configure(j, mapper, err);
183 break; 184 break;
184 case RRType::Process: 185 case RRType::Process:
185 rr.processRequest = VampJson::toRpcRequest_Process(j, mapper, serialisation, err); 186 rr.processRequest = VampJson::toRpcRequest_Process(j, mapper, serialisation, err);
186 break; 187 break;
187 case RRType::Finish: 188 case RRType::Finish:
188 rr.finishRequest = VampJson::toRpcRequest_Finish(j, mapper, err); 189 rr.finishRequest = VampJson::toRpcRequest_Finish(j, mapper, err);
189 break; 190 break;
190 case RRType::NotValid: 191 case RRType::NotValid:
191 break; 192 break;
192 } 193 }
193 194
194 return rr; 195 return rr;
195 } 196 }
196 197
207 Json id = writeJsonId(rr.id); 208 Json id = writeJsonId(rr.id);
208 209
209 switch (rr.type) { 210 switch (rr.type) {
210 211
211 case RRType::List: 212 case RRType::List:
212 j = VampJson::fromRpcRequest_List(id); 213 j = VampJson::fromRpcRequest_List(id);
213 break; 214 break;
214 case RRType::Load: 215 case RRType::Load:
215 j = VampJson::fromRpcRequest_Load(rr.loadRequest, id); 216 j = VampJson::fromRpcRequest_Load(rr.loadRequest, id);
216 break; 217 break;
217 case RRType::Configure: 218 case RRType::Configure:
218 j = VampJson::fromRpcRequest_Configure(rr.configurationRequest, mapper, id); 219 j = VampJson::fromRpcRequest_Configure(rr.configurationRequest, mapper, id);
219 break; 220 break;
220 case RRType::Process: 221 case RRType::Process:
221 j = VampJson::fromRpcRequest_Process 222 j = VampJson::fromRpcRequest_Process
222 (rr.processRequest, mapper, serialisation, id); 223 (rr.processRequest, mapper, serialisation, id);
223 break; 224 break;
224 case RRType::Finish: 225 case RRType::Finish:
225 j = VampJson::fromRpcRequest_Finish(rr.finishRequest, mapper, id); 226 j = VampJson::fromRpcRequest_Finish(rr.finishRequest, mapper, id);
226 break; 227 break;
227 case RRType::NotValid: 228 case RRType::NotValid:
228 break; 229 break;
229 } 230 }
230 231
231 cout << j.dump() << endl; 232 cout << j.dump() << endl;
232 } 233 }
233 234
237 RequestOrResponse rr; 238 RequestOrResponse rr;
238 rr.direction = RequestOrResponse::Response; 239 rr.direction = RequestOrResponse::Response;
239 240
240 string input; 241 string input;
241 if (!getline(cin, input)) { 242 if (!getline(cin, input)) {
242 // the EOF case, not actually an error 243 // the EOF case, not actually an error
243 rr.type = RRType::NotValid; 244 rr.type = RRType::NotValid;
244 return rr; 245 return rr;
245 } 246 }
246 247
247 Json j = convertResponseJson(input, err); 248 Json j = convertResponseJson(input, err);
248 if (err != "") return {}; 249 if (err != "") return {};
249 250
259 rr.errorText = j["errorText"].string_value(); 260 rr.errorText = j["errorText"].string_value();
260 261
261 switch (rr.type) { 262 switch (rr.type) {
262 263
263 case RRType::List: 264 case RRType::List:
264 rr.listResponse = VampJson::toRpcResponse_List(j, err); 265 rr.listResponse = VampJson::toRpcResponse_List(j, err);
265 break; 266 break;
266 case RRType::Load: 267 case RRType::Load:
267 rr.loadResponse = VampJson::toRpcResponse_Load(j, mapper, err); 268 rr.loadResponse = VampJson::toRpcResponse_Load(j, mapper, err);
268 break; 269 break;
269 case RRType::Configure: 270 case RRType::Configure:
270 rr.configurationResponse = VampJson::toRpcResponse_Configure(j, mapper, err); 271 rr.configurationResponse = VampJson::toRpcResponse_Configure(j, mapper, err);
271 break; 272 break;
272 case RRType::Process: 273 case RRType::Process:
273 rr.processResponse = VampJson::toRpcResponse_Process(j, mapper, serialisation, err); 274 rr.processResponse = VampJson::toRpcResponse_Process(j, mapper, serialisation, err);
274 break; 275 break;
275 case RRType::Finish: 276 case RRType::Finish:
276 rr.finishResponse = VampJson::toRpcResponse_Finish(j, mapper, serialisation, err); 277 rr.finishResponse = VampJson::toRpcResponse_Finish(j, mapper, serialisation, err);
277 break; 278 break;
278 case RRType::NotValid: 279 case RRType::NotValid:
279 break; 280 break;
280 } 281 }
281 282
282 return rr; 283 return rr;
283 } 284 }
284 285
294 295
295 Json id = writeJsonId(rr.id); 296 Json id = writeJsonId(rr.id);
296 297
297 if (!rr.success) { 298 if (!rr.success) {
298 299
299 j = VampJson::fromError(rr.errorText, rr.type, id); 300 j = VampJson::fromError(rr.errorText, rr.type, id);
300 301
301 } else { 302 } else {
302 303
303 switch (rr.type) { 304 switch (rr.type) {
304 305
305 case RRType::List: 306 case RRType::List:
306 j = VampJson::fromRpcResponse_List(rr.listResponse, id); 307 j = VampJson::fromRpcResponse_List(rr.listResponse, id);
307 break; 308 break;
308 case RRType::Load: 309 case RRType::Load:
309 j = VampJson::fromRpcResponse_Load(rr.loadResponse, mapper, id); 310 j = VampJson::fromRpcResponse_Load(rr.loadResponse, mapper, id);
310 break; 311 break;
311 case RRType::Configure: 312 case RRType::Configure:
312 j = VampJson::fromRpcResponse_Configure(rr.configurationResponse, 313 j = VampJson::fromRpcResponse_Configure(rr.configurationResponse,
313 mapper, id); 314 mapper, id);
314 break; 315 break;
315 case RRType::Process: 316 case RRType::Process:
316 j = VampJson::fromRpcResponse_Process 317 j = VampJson::fromRpcResponse_Process
317 (rr.processResponse, mapper, serialisation, id); 318 (rr.processResponse, mapper, serialisation, id);
318 break; 319 break;
319 case RRType::Finish: 320 case RRType::Finish:
320 j = VampJson::fromRpcResponse_Finish 321 j = VampJson::fromRpcResponse_Finish
321 (rr.finishResponse, mapper, serialisation, id); 322 (rr.finishResponse, mapper, serialisation, id);
322 break; 323 break;
323 case RRType::NotValid: 324 case RRType::NotValid:
324 break; 325 break;
325 } 326 }
326 } 327 }
327 328
328 cout << j.dump() << endl; 329 cout << j.dump() << endl;
329 } 330 }
330 331
341 rr.id = readCapnpId(reader); 342 rr.id = readCapnpId(reader);
342 343
343 switch (rr.type) { 344 switch (rr.type) {
344 345
345 case RRType::List: 346 case RRType::List:
346 VampnProto::readRpcRequest_List(reader); // type check only 347 VampnProto::readRpcRequest_List(reader); // type check only
347 break; 348 break;
348 case RRType::Load: 349 case RRType::Load:
349 VampnProto::readRpcRequest_Load(rr.loadRequest, reader); 350 VampnProto::readRpcRequest_Load(rr.loadRequest, reader);
350 break; 351 break;
351 case RRType::Configure: 352 case RRType::Configure:
352 VampnProto::readRpcRequest_Configure(rr.configurationRequest, 353 VampnProto::readRpcRequest_Configure(rr.configurationRequest,
353 reader, mapper); 354 reader, mapper);
354 break; 355 break;
355 case RRType::Process: 356 case RRType::Process:
356 VampnProto::readRpcRequest_Process(rr.processRequest, reader, mapper); 357 VampnProto::readRpcRequest_Process(rr.processRequest, reader, mapper);
357 break; 358 break;
358 case RRType::Finish: 359 case RRType::Finish:
359 VampnProto::readRpcRequest_Finish(rr.finishRequest, reader, mapper); 360 VampnProto::readRpcRequest_Finish(rr.finishRequest, reader, mapper);
360 break; 361 break;
361 case RRType::NotValid: 362 case RRType::NotValid:
362 break; 363 break;
363 } 364 }
364 365
365 return rr; 366 return rr;
366 } 367 }
367 368
374 buildCapnpId(builder, rr.id); 375 buildCapnpId(builder, rr.id);
375 376
376 switch (rr.type) { 377 switch (rr.type) {
377 378
378 case RRType::List: 379 case RRType::List:
379 VampnProto::buildRpcRequest_List(builder); 380 VampnProto::buildRpcRequest_List(builder);
380 break; 381 break;
381 case RRType::Load: 382 case RRType::Load:
382 VampnProto::buildRpcRequest_Load(builder, rr.loadRequest); 383 VampnProto::buildRpcRequest_Load(builder, rr.loadRequest);
383 break; 384 break;
384 case RRType::Configure: 385 case RRType::Configure:
385 VampnProto::buildRpcRequest_Configure(builder, 386 VampnProto::buildRpcRequest_Configure(builder,
386 rr.configurationRequest, mapper); 387 rr.configurationRequest, mapper);
387 break; 388 break;
388 case RRType::Process: 389 case RRType::Process:
389 VampnProto::buildRpcRequest_Process(builder, rr.processRequest, mapper); 390 VampnProto::buildRpcRequest_Process(builder, rr.processRequest, mapper);
390 break; 391 break;
391 case RRType::Finish: 392 case RRType::Finish:
392 VampnProto::buildRpcRequest_Finish(builder, rr.finishRequest, mapper); 393 VampnProto::buildRpcRequest_Finish(builder, rr.finishRequest, mapper);
393 break; 394 break;
394 case RRType::NotValid: 395 case RRType::NotValid:
395 break; 396 break;
396 } 397 }
397 398
398 writeMessageToFd(1, message); 399 writeMessageToFd(1, message);
399 } 400 }
400 401
414 int errorCode = 0; 415 int errorCode = 0;
415 416
416 switch (rr.type) { 417 switch (rr.type) {
417 418
418 case RRType::List: 419 case RRType::List:
419 VampnProto::readRpcResponse_List(rr.listResponse, reader); 420 VampnProto::readRpcResponse_List(rr.listResponse, reader);
420 break; 421 break;
421 case RRType::Load: 422 case RRType::Load:
422 VampnProto::readRpcResponse_Load(rr.loadResponse, reader, mapper); 423 VampnProto::readRpcResponse_Load(rr.loadResponse, reader, mapper);
423 break; 424 break;
424 case RRType::Configure: 425 case RRType::Configure:
425 VampnProto::readRpcResponse_Configure(rr.configurationResponse, 426 VampnProto::readRpcResponse_Configure(rr.configurationResponse,
426 reader, mapper); 427 reader, mapper);
427 break; 428 break;
428 case RRType::Process: 429 case RRType::Process:
429 VampnProto::readRpcResponse_Process(rr.processResponse, reader, mapper); 430 VampnProto::readRpcResponse_Process(rr.processResponse, reader, mapper);
430 break; 431 break;
431 case RRType::Finish: 432 case RRType::Finish:
432 VampnProto::readRpcResponse_Finish(rr.finishResponse, reader, mapper); 433 VampnProto::readRpcResponse_Finish(rr.finishResponse, reader, mapper);
433 break; 434 break;
434 case RRType::NotValid: 435 case RRType::NotValid:
435 // error 436 // error
436 rr.success = false; 437 rr.success = false;
437 VampnProto::readRpcResponse_Error(errorCode, rr.errorText, reader); 438 VampnProto::readRpcResponse_Error(errorCode, rr.errorText, reader);
438 break; 439 break;
439 } 440 }
440 441
441 return rr; 442 return rr;
442 } 443 }
443 444
449 450
450 buildCapnpId(builder, rr.id); 451 buildCapnpId(builder, rr.id);
451 452
452 if (!rr.success) { 453 if (!rr.success) {
453 454
454 VampnProto::buildRpcResponse_Error(builder, rr.errorText, rr.type); 455 VampnProto::buildRpcResponse_Error(builder, rr.errorText, rr.type);
455 456
456 } else { 457 } else {
457 458
458 switch (rr.type) { 459 switch (rr.type) {
459 460
460 case RRType::List: 461 case RRType::List:
461 VampnProto::buildRpcResponse_List(builder, rr.listResponse); 462 VampnProto::buildRpcResponse_List(builder, rr.listResponse);
462 break; 463 break;
463 case RRType::Load: 464 case RRType::Load:
464 VampnProto::buildRpcResponse_Load(builder, rr.loadResponse, mapper); 465 VampnProto::buildRpcResponse_Load(builder, rr.loadResponse, mapper);
465 break; 466 break;
466 case RRType::Configure: 467 case RRType::Configure:
467 VampnProto::buildRpcResponse_Configure(builder, rr.configurationResponse, mapper); 468 VampnProto::buildRpcResponse_Configure(builder, rr.configurationResponse, mapper);
468 break; 469 break;
469 case RRType::Process: 470 case RRType::Process:
470 VampnProto::buildRpcResponse_Process(builder, rr.processResponse, mapper); 471 VampnProto::buildRpcResponse_Process(builder, rr.processResponse, mapper);
471 break; 472 break;
472 case RRType::Finish: 473 case RRType::Finish:
473 VampnProto::buildRpcResponse_Finish(builder, rr.finishResponse, mapper); 474 VampnProto::buildRpcResponse_Finish(builder, rr.finishResponse, mapper);
474 break; 475 break;
475 case RRType::NotValid: 476 case RRType::NotValid:
476 break; 477 break;
477 } 478 }
478 } 479 }
479 480
480 writeMessageToFd(1, message); 481 writeMessageToFd(1, message);
481 } 482 }
482 483
483 RequestOrResponse 484 RequestOrResponse
484 readInputJson(RequestOrResponse::Direction direction, string &err) 485 readInputJson(RequestOrResponse::Direction direction, string &err)
485 { 486 {
486 if (direction == RequestOrResponse::Request) { 487 if (direction == RequestOrResponse::Request) {
487 return readRequestJson(err); 488 return readRequestJson(err);
488 } else { 489 } else {
489 return readResponseJson(err); 490 return readResponseJson(err);
490 } 491 }
491 } 492 }
492 493
493 RequestOrResponse 494 RequestOrResponse
494 readInputCapnp(RequestOrResponse::Direction direction) 495 readInputCapnp(RequestOrResponse::Direction direction)
495 { 496 {
496 static kj::FdInputStream stream(0); // stdin 497 static kj::FdInputStream stream(0); // stdin
497 static kj::BufferedInputStreamWrapper buffered(stream); 498 static kj::BufferedInputStreamWrapper buffered(stream);
498 499
499 if (buffered.tryGetReadBuffer() == nullptr) { 500 if (buffered.tryGetReadBuffer() == nullptr) {
500 return {}; 501 return {};
501 } 502 }
502 503
503 if (direction == RequestOrResponse::Request) { 504 if (direction == RequestOrResponse::Request) {
504 return readRequestCapnp(buffered); 505 return readRequestCapnp(buffered);
505 } else { 506 } else {
506 return readResponseCapnp(buffered); 507 return readResponseCapnp(buffered);
507 } 508 }
508 } 509 }
509 510
510 RequestOrResponse 511 RequestOrResponse
511 readInput(string format, RequestOrResponse::Direction direction) 512 readInput(string format, RequestOrResponse::Direction direction)
512 { 513 {
513 if (format == "json") { 514 if (format == "json") {
514 string err; 515 string err;
515 auto result = readInputJson(direction, err); 516 auto result = readInputJson(direction, err);
516 if (err != "") throw runtime_error(err); 517 if (err != "") throw runtime_error(err);
517 else return result; 518 else return result;
518 } else if (format == "capnp") { 519 } else if (format == "capnp") {
519 return readInputCapnp(direction); 520 return readInputCapnp(direction);
520 } else { 521 } else {
521 throw runtime_error("unknown input format \"" + format + "\""); 522 throw runtime_error("unknown input format \"" + format + "\"");
522 } 523 }
523 } 524 }
524 525
525 void 526 void
526 writeOutput(string format, RequestOrResponse &rr) 527 writeOutput(string format, RequestOrResponse &rr)
527 { 528 {
528 if (format == "json") { 529 if (format == "json") {
529 if (rr.direction == RequestOrResponse::Request) { 530 if (rr.direction == RequestOrResponse::Request) {
530 writeRequestJson(rr, false); 531 writeRequestJson(rr, false);
531 } else { 532 } else {
532 writeResponseJson(rr, false); 533 writeResponseJson(rr, false);
533 } 534 }
534 } else if (format == "json-b64") { 535 } else if (format == "json-b64") {
535 if (rr.direction == RequestOrResponse::Request) { 536 if (rr.direction == RequestOrResponse::Request) {
536 writeRequestJson(rr, true); 537 writeRequestJson(rr, true);
537 } else { 538 } else {
538 writeResponseJson(rr, true); 539 writeResponseJson(rr, true);
539 } 540 }
540 } else if (format == "capnp") { 541 } else if (format == "capnp") {
541 if (rr.direction == RequestOrResponse::Request) { 542 if (rr.direction == RequestOrResponse::Request) {
542 writeRequestCapnp(rr); 543 writeRequestCapnp(rr);
543 } else { 544 } else {
544 writeResponseCapnp(rr); 545 writeResponseCapnp(rr);
545 } 546 }
546 } else { 547 } else {
547 throw runtime_error("unknown output format \"" + format + "\""); 548 throw runtime_error("unknown output format \"" + format + "\"");
548 } 549 }
549 } 550 }
550 551
551 int main(int argc, char **argv) 552 int main(int argc, char **argv)
552 { 553 {
553 if (argc < 2) { 554 if (argc < 2) {
554 usage(); 555 usage();
555 } 556 }
556 557
557 string informat = "json", outformat = "json"; 558 string informat = "json", outformat = "json";
558 RequestOrResponse::Direction direction = RequestOrResponse::Request; 559 RequestOrResponse::Direction direction = RequestOrResponse::Request;
559 bool haveDirection = false; 560 bool haveDirection = false;
560 561
561 for (int i = 1; i < argc; ++i) { 562 for (int i = 1; i < argc; ++i) {
562 563
563 string arg = argv[i]; 564 string arg = argv[i];
564 bool final = (i + 1 == argc); 565 bool final = (i + 1 == argc);
565 566
566 if (arg == "-i") { 567 if (arg == "-i") {
567 if (final) usage(); 568 if (final) usage();
568 else informat = argv[++i]; 569 else informat = argv[++i];
569 570
570 } else if (arg == "-o") { 571 } else if (arg == "-o") {
571 if (final) usage(); 572 if (final) usage();
572 else outformat = argv[++i]; 573 else outformat = argv[++i];
573 574
574 } else if (arg == "request") { 575 } else if (arg == "request") {
575 direction = RequestOrResponse::Request; 576 direction = RequestOrResponse::Request;
576 haveDirection = true; 577 haveDirection = true;
577 578
578 } else if (arg == "response") { 579 } else if (arg == "response") {
579 direction = RequestOrResponse::Response; 580 direction = RequestOrResponse::Response;
580 haveDirection = true; 581 haveDirection = true;
581 582
582 } else { 583 } else {
583 usage(); 584 usage();
584 } 585 }
585 } 586 }
586 587
587 if (informat == "" || outformat == "" || !haveDirection) { 588 if (informat == "" || outformat == "" || !haveDirection) {
588 usage(); 589 usage();
589 } 590 }
590 591
591 while (true) { 592 while (true) {
592 593
593 try { 594 try {
594 595
595 RequestOrResponse rr = readInput(informat, direction); 596 RequestOrResponse rr = readInput(informat, direction);
596 597
597 // NotValid without an exception indicates EOF: 598 // NotValid without an exception indicates EOF:
598 if (rr.type == RRType::NotValid) break; 599 if (rr.type == RRType::NotValid) break;
599 600
600 writeOutput(outformat, rr); 601 writeOutput(outformat, rr);
601 602
602 } catch (std::exception &e) { 603 } catch (std::exception &e) {
603 604
604 cerr << "Error: " << e.what() << endl; 605 cerr << "Error: " << e.what() << endl;
605 exit(1); 606 exit(1);
606 } 607 }
607 } 608 }
608 609
609 exit(0); 610 exit(0);
610 } 611 }
611 612