UNPKG

@cloudamqp/amqp-client

Version:

AMQP 0-9-1 client, both for browsers (WebSocket) and node (TCP Socket)

184 lines 8.21 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.AMQPClient = void 0; const amqp_base_client_js_1 = require("./amqp-base-client.js"); const amqp_error_js_1 = require("./amqp-error.js"); const amqp_view_js_1 = require("./amqp-view.js"); const buffer_1 = require("buffer"); const net = __importStar(require("net")); const tls = __importStar(require("tls")); class AMQPClient extends amqp_base_client_js_1.AMQPBaseClient { constructor(url, tlsOptions) { const u = new URL(url); const vhost = decodeURIComponent(u.pathname.slice(1)) || "/"; const username = decodeURIComponent(u.username) || "guest"; const password = decodeURIComponent(u.password) || "guest"; const name = u.searchParams.get("name") || ""; const frameMax = parseInt(u.searchParams.get("frameMax") || "8192"); const heartbeat = parseInt(u.searchParams.get("heartbeat") || "0"); const channelMax = parseInt(u.searchParams.get("channelMax") || "0"); const platform = `${process.release.name} ${process.version} ${process.platform} ${process.arch}`; super(vhost, username, password, name, platform, frameMax, heartbeat, channelMax); this.tls = u.protocol === "amqps:"; this.tlsOptions = tlsOptions; this.host = u.hostname || "localhost"; this.port = parseInt(u.port) || (this.tls ? 5671 : 5672); this.insecure = u.searchParams.get("insecure") !== null; this.framePos = 0; this.frameSize = 0; this.frameBuffer = buffer_1.Buffer.allocUnsafe(frameMax); Object.defineProperty(this, 'frameBuffer', { enumerable: false }); } connect() { let rejectConnection; const socket = this.connectSocket(); socket.on('connect', () => { socket.on('error', (err) => this.onerror(new amqp_error_js_1.AMQPError(err.message, this))); socket.on('end', () => { if (rejectConnection) { rejectConnection(new amqp_error_js_1.AMQPError('Connection ended', this)); } }); socket.on('close', (hadError) => { const clientClosed = this.closed; this.closed = true; if (!hadError && !clientClosed) this.onerror(new amqp_error_js_1.AMQPError('Socket closed', this)); }); }); Object.defineProperty(this, 'socket', { value: socket, writable: true, enumerable: false }); socket.setTimeout((this.heartbeat || 60) * 1000); if (this.heartbeat === 0) socket.setKeepAlive(true, 60); return new Promise((resolve, reject) => { rejectConnection = reject; socket.on('timeout', () => reject(new amqp_error_js_1.AMQPError("timeout", this))); socket.on('error', (err) => reject(new amqp_error_js_1.AMQPError(err.message, this))); const onConnect = (conn) => { socket.setTimeout(this.heartbeat * 1000); resolve(conn); }; this.connectPromise = [onConnect, reject]; }); } connectSocket() { const options = { host: this.host, port: this.port, servername: net.isIP(this.host) ? "" : this.host, rejectUnauthorized: !this.insecure, ...this.tlsOptions }; const sendStart = () => this.send(new Uint8Array([65, 77, 81, 80, 0, 0, 9, 1])); const conn = this.tls ? tls.connect(options, sendStart) : net.connect(options, sendStart); conn.on('data', this.onRead.bind(this)); return conn; } onRead(buf) { const bufLen = buf.length; let bufPos = 0; while (bufPos < bufLen) { if (this.frameSize === 0) { if (this.framePos !== 0) { const copied = buf.copy(this.frameBuffer, this.framePos, bufPos, bufPos + 7 - this.framePos); if (copied === 0) throw new amqp_error_js_1.AMQPError(`Copied 0 bytes framePos=${this.framePos} bufPos=${bufPos} bytesWritten=${bufLen}`, this); this.frameSize = this.frameBuffer.readInt32BE(bufPos + 3) + 8; this.framePos += copied; bufPos += copied; continue; } if (bufPos + 3 + 4 > bufLen) { const copied = buf.copy(this.frameBuffer, this.framePos, bufPos, bufLen); if (copied === 0) throw new amqp_error_js_1.AMQPError(`Copied 0 bytes framePos=${this.framePos} bufPos=${bufPos} bytesWritten=${bufLen}`, this); this.framePos += copied; break; } this.frameSize = buf.readInt32BE(bufPos + 3) + 8; if (bufLen - bufPos >= this.frameSize) { const view = new amqp_view_js_1.AMQPView(buf.buffer, buf.byteOffset + bufPos, this.frameSize); this.parseFrames(view); bufPos += this.frameSize; this.frameSize = 0; continue; } } const leftOfFrame = this.frameSize - this.framePos; const copyBytes = Math.min(leftOfFrame, bufLen - bufPos); const copied = buf.copy(this.frameBuffer, this.framePos, bufPos, bufPos + copyBytes); if (copied === 0) throw new amqp_error_js_1.AMQPError(`Copied 0 bytes, please report this bug, frameSize=${this.frameSize} framePos=${this.framePos} bufPos=${bufPos} copyBytes=${copyBytes} bytesWritten=${bufLen}`, this); this.framePos += copied; bufPos += copied; if (this.framePos === this.frameSize) { const view = new amqp_view_js_1.AMQPView(this.frameBuffer.buffer, 0, this.frameSize); this.parseFrames(view); this.frameSize = this.framePos = 0; } } return true; } send(bytes) { return new Promise((resolve, reject) => { if (!this.socket) return reject(new amqp_error_js_1.AMQPError("Socket not connected", this)); try { this.socket.write(bytes, undefined, (err) => err ? reject(err) : resolve()); } catch (err) { this.closeSocket(); reject(err); } }); } closeSocket() { this.closed = true; if (this.socket) { this.socket.end(); this.socket.destroy(); } this.socket = undefined; } } exports.AMQPClient = AMQPClient; //# sourceMappingURL=amqp-socket-client.js.map