UNPKG

mqlight-dev

Version:
292 lines (278 loc) 9.81 kB
/* %Z% %W% %I% %E% %U% */ /* * <copyright * notice="lm-source-program" * pids="5725-P60" * years="2013,2016" * crc="3568777996" > * Licensed Materials - Property of IBM * * 5725-P60 * * (C) Copyright IBM Corp. 2013, 2016 * * US Government Users Restricted Rights - Use, duplication or * disclosure restricted by GSA ADP Schedule Contract with * IBM Corp. * </copyright> */ /* jslint node: true */ /* jshint -W083,-W097 */ 'use strict'; var mqlight = require('mqlight-dev'); var nopt = require('nopt'); var uuid = require('uuid'); var fs = require('fs'); // parse the commandline arguments var types = { help: Boolean, service: String, 'keystore': String, 'keystore-passphrase': String, 'client-certificate': String, 'client-key': String, 'client-key-passphrase': String, 'trust-certificate': String, 'verify-name': Boolean, 'topic-pattern': String, id: String, 'destination-ttl': Number, 'share-name': String, file: String, delay: Number, 'verbose': Boolean }; var shorthands = { h: ['--help'], s: ['--service'], k: ['--keystore'], p: ['--keystore-passphrase'], c: ['--trust-certificate'], t: ['--topic-pattern'], i: ['--id'], n: ['--share-name'], f: ['--file'], d: ['--delay'] }; var parsed = nopt(types, shorthands, process.argv, 2); var remain = parsed.argv.remain; var showUsage = function() { var puts = console.log; puts('Usage: recv.js [options]'); puts(''); puts('Options:'); puts(' -h, --help show this help message and exit'); puts(' -s URL, --service=URL service to connect to, for example:\n' + ' amqp://user:password@host:5672 or\n' + ' amqps://host:5671 to use SSL/TLS\n' + ' (default: amqp://localhost)'); puts(' -k FILE, --keystore=FILE\n' + ' use key store contained in FILE (in PKCS#12' + ' format) to\n' + ' supply the client certificate, private key' + ' and trust\n' + ' certificates.\n' + ' The Connection must be secured with SSL/TLS' + ' (e.g. the\n' + " service URL must start with 'amqps://').\n" + ' Option is mutually exclusive with the' + ' client-key,\n' + ' client-certificate and trust-certifcate' + ' options'); puts(' -p PASSPHRASE, --keystore-passphrase=PASSPHRASE\n' + ' use PASSPHRASE to access the key store'); puts(' --client-certificate=FILE\n' + ' use the certificate contained in FILE (in' + ' PEM format) to\n' + ' supply the identity of the client. The' + ' connection must\n' + ' be secured with SSL/TLS'); puts(' --client-key=FILE use the private key contained in FILE (in' + ' PEM format)\n' + ' for encrypting the specified client' + ' certificate'); puts(' --client-key-passphrase=PASSPHRASE\n' + ' use PASSPHRASE to access the client private' + ' key'); puts(' -c FILE, --trust-certificate=FILE\n' + ' use the certificate contained in FILE (in' + ' PEM format) to\n' + ' validate the identity of the server. The' + ' connection must\n' + ' be secured with SSL/TLS'); puts(' --no-verify-name specify to not additionally check the' + " server's common\n" + ' name in the specified trust certificate' + ' matches the\n' + " actual server's DNS name"); puts(' -t TOPICPATTERN, --topic-pattern=TOPICPATTERN\n' + ' subscribe to receive messages matching' + ' TOPICPATTERN'); puts(' (default: public)'); puts(' -i ID, --id=ID the ID to use when connecting to MQ Light\n' + ' (default: recv_[0-9a-f]{7})'); puts(' --destination-ttl=NUM set destination time-to-live to NUM seconds'); puts(' -n NAME, --share-name NAME'); puts(' optionally, subscribe to a shared' + ' destination using\n' + ' NAME as the share name.'); puts(' -f FILE, --file=FILE write the payload of the next message' + ' received to\n' + ' FILE (overwriting previous file contents)' + ' then end.\n' + ' (default is to print messages to stdout)'); puts(' -d NUM, --delay=NUM delay for NUM seconds each time a message' + ' is received.'); puts(' --verbose print additional information about each' + ' message\n' + ' received.'); puts(''); }; if (parsed.help) { showUsage(); process.exit(0); } else if (remain.length > 0) { showUsage(); process.exit(1); } Object.getOwnPropertyNames(parsed).forEach(function(key) { if (key !== 'argv' && !types.hasOwnProperty(key)) { console.error('Error: Unsupported commandline option "%s"', key); console.error(); showUsage(); process.exit(1); } }); var service = parsed.service ? parsed.service : 'amqp://localhost'; var pattern = parsed['topic-pattern'] ? parsed['topic-pattern'] : 'public'; var id = parsed.id ? parsed.id : 'recv_' + uuid.v4().substring(0, 7); var share = parsed['share-name'] ? parsed['share-name'] : undefined; // connect client to server var opts = { service: service, id: id }; var checkService = false; if (parsed['keystore']) { /** the keystore to use for a TLS/SSL connection */ opts.sslKeystore = parsed['keystore']; checkService = true; } if (parsed['keystore-passphrase']) { /** the keystore-passphrase to use for a TLS/SSL connection */ opts.sslKeystorePassphrase = parsed['keystore-passphrase']; checkService = true; } if (parsed['client-certificate']) { /** the client-certificate to use for a TLS/SSL connection */ opts.sslClientCertificate = parsed['client-certificate']; checkService = true; } if (parsed['client-key']) { /** the client-key to use for a TLS/SSL connection */ opts.sslClientKey = parsed['client-key']; checkService = true; } if (parsed['client-key-passphrase']) { /** the client-key-passphrase to use for a TLS/SSL connection */ opts.sslClientKeyPassphrase = parsed['client-key-passphrase']; checkService = true; } if (parsed['trust-certificate']) { /** the trust-certificate to use for a TLS/SSL connection */ opts.sslTrustCertificate = parsed['trust-certificate']; checkService = true; } if (parsed['verify-name'] === false) { /** * Indicate not to additionally check the MQ Light server's * common name in the certificate matches the actual server's DNS name. */ opts.sslVerifyName = false; checkService = true; } if (checkService) { if (parsed.service) { if (service.indexOf('amqps', 0) !== 0) { console.error('*** error ***'); console.error("The service URL must start with 'amqps://' when using " + 'SSL/TLS options.'); console.error('Exiting.'); process.exit(1); } } else { /** if none specified, change the default service to be amqps:// */ opts.service = 'amqps://localhost'; } } var client = mqlight.createClient(opts); // create an event listener to handle any messages that arrive for us // and an event listener to handle any malformed messages var i = 0; var delayMs = 0; client.on('message', function(data, delivery) { ++i; if (parsed.verbose) console.log('# received message (%d)', i); if (parsed.file) { console.log('Writing message data to %s', parsed.file); fs.writeFileSync(parsed.file, data); delivery.message.confirmDelivery(); client.stop(function() { console.error('Exiting.'); process.exit(0); }); } else { console.log(data); if (parsed.verbose) console.log(delivery); if (delayMs > 0) { setTimeout(delivery.message.confirmDelivery, delayMs); } else { delivery.message.confirmDelivery(); } } }); client.on('malformed', function(data, delivery) { console.error('*** received malformed message (%d)', (++i)); if (data) { console.error(data); } console.error(delivery); }); // once started, receive messages for the supplied pattern client.on('started', function() { console.log('Connected to %s using client-id %s', client.service, client.id); var options = { qos: mqlight.QOS_AT_LEAST_ONCE, autoConfirm: false }; if (parsed['destination-ttl'] !== undefined) { options.ttl = Number(parsed['destination-ttl']) * 1000; } if (parsed.delay !== undefined) { delayMs = Number(parsed.delay) * 1000; if (delayMs > 0) options.credit = 1; } // now subscribe to pattern for messages client.subscribe(pattern, share, options, function(err, pattern) { if (err) { console.error('Problem with subscribe request: %s', err.toString()); setImmediate(function() { process.exit(1); }); } else { if (pattern) { if (share) { console.log('Subscribed to share: %s, pattern: %s', share, pattern); } else { console.log('Subscribed to pattern: %s', pattern); } } } }); }); client.on('error', function(error) { console.error('*** error ***'); if (error) { if (error.message) console.error('message: %s', error.toString()); else if (error.stack) console.error(error.stack); } console.error('Exiting.'); process.exit(1); });