process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; const MODULE_NAME = 'TRANSPORT'; const http = require('http'); const url = require('url'); const request = require('request'); const config = require('komodo-sdk/config'); const logger = require('tektrans-logger'); const uniqid = require('uniqid'); let callback; const maxSendRetry = Number(config.max_send_retry) || 5; const sleepBeforeRetryMs = (Number(config.sleep_before_retry_secs) || 60) * 1000; function sleep(ms) { return new Promise((resolve) => { setTimeout(() => { resolve(null); }, ms); }); } function cleanResponseToPartner(_data) { const data = JSON.parse(JSON.stringify(_data)); delete data.origin; delete data.origin_report_ip; delete data.origin_report_port; delete data.reverse_url; delete data.misc; delete data.inquiry_only; // eslint-disable-next-line no-restricted-syntax for (const key in data) { // eslint-disable-next-line no-prototype-builtins if (data.hasOwnProperty(key)) { if (key.indexOf('[') >= 0) { delete data[key]; } } } return data; } function onRequestFromPartner(req, res) { const xid = uniqid(); const methodName = 'onRequestFromPartner'; const remoteAddress = req.connection.remoteAddress.replace(/^::ffff:/, ''); const qs = url.parse(req.url, true).query; logger.verbose('Got a request from partner', { xid, module_name: MODULE_NAME, method_name: methodName, remote_address: remoteAddress, url: req.url, qs, }); const partner = `${qs.terminal_name}@${remoteAddress}`; const { password, reverse_url: reverseUrl, product_name: productName, destination, request_id: requestId, } = qs; if ( !qs.terminal_name || !password || !reverseUrl || !productName || !destination || !requestId ) { logger.verbose('Invalid request from partner', { xid, hasTerminalName: !!qs.terminal_name, hasPassword: !!password, hasProductName: !!productName, hasDestination: !!destination, hasRequestId: !!requestId, }); res.end('INVALID REQUEST'); return; } const msg = [productName, destination, password, requestId].join('.'); callback.onIncomingMessage( { me: config.username, partner, msg: msg.trim(), reverse_url: reverseUrl, }, (err, _result) => { const result = cleanResponseToPartner(_result); logger.verbose('C2DEEE9D Forwarding CORE response to partner as direct response', { xid, result: _result, }); res.end(JSON.stringify(result)); }, ); } function createHttpServer() { const listenPort = config.center_port; http.createServer(onRequestFromPartner).listen(listenPort, () => { logger.info('Center HTTP server listen on tcp port', { listenPort }); }); } function init(cb) { if (!cb) { logger.warn('Callback is not defined'); // eslint-disable-next-line no-console console.trace(); process.exit(1); return; } callback = cb; createHttpServer(); } async function sleepAndResend(xid, partner, msg, params, retry) { if (retry > maxSendRetry) { logger.verbose('Retry exceeded', { xid, retry: retry || 0, params, }); return; } logger.verbose('Sleep before resend', { xid, sleepBeforeRetryMs }); await sleep(sleepBeforeRetryMs); // eslint-disable-next-line no-use-before-define send(partner, msg, params, retry + 1); } function send(partner, msg, params, retry) { const xid = uniqid(); if (retry) { logger.verbose('F39C9082: Resending', { xid, partner, msg, params, retry, }); } else { logger.verbose('Got response from CORE', { xid, partner, msg, params, retried: retry || 0, }); } if (!params || !params.reverse_url) { logger.verbose('Undefined reverse_url, not forwarding message to partner', { xid }); return; } if (params.reverse_url.indexOf('http') < 0) { logger.verbose('Invalid reverse_url, not forwarding message to partner', { xid }); return; } if (params.rc === '68') { logger.verbose('Ignoring RC 68 reverse report', { xid }); return; } const reqOptions = { url: params.reverse_url, qs: cleanResponseToPartner(params), }; logger.verbose('Sending reverse report to partner', { xid, request: reqOptions, }); request(reqOptions, (err, res, body) => { if (err) { logger.warn('Error sending reverse report to partner', { xid, request: reqOptions, err, }); sleepAndResend(xid, partner, msg, params, retry || 0); return; } /* if (res.statusCode != 200) { logger.warn('Partner not returning HTTP status code 200 on reverse report', { request: reqOptions, http_status: res.statusCode, }); _sleepAndResend(partner, msg, params, retry); return; } */ logger.verbose('Reverse report has been sent to partner', { xid, request: reqOptions, httpStatus: res && res.statusCode, responseBody: body, }); }); } exports.init = init; exports.send = send;