UNPKG

@jonaskello-forks/amqp-client

Version:

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

107 lines 4.78 kB
import { AMQPBaseClient } from './amqp-base-client.js'; import { AMQPError } from './amqp-error.js'; import { AMQPView } from './amqp-view.js'; import { Buffer } from 'buffer'; import * as net from 'net'; import * as tls from 'tls'; export class AMQPClient extends AMQPBaseClient { constructor(url) { const u = new URL(url); const vhost = decodeURIComponent(u.pathname.slice(1)) || "/"; const username = u.username || "guest"; const password = u.password || "guest"; const name = u.searchParams.get("name") || ""; const frameMax = parseInt(u.searchParams.get("frameMax") || "4096"); const heartbeat = parseInt(u.searchParams.get("heartbeat") || "0"); const platform = `${process.release.name} ${process.version} ${process.platform} ${process.arch}`; super(vhost, username, password, name, platform, frameMax, heartbeat); this.tls = u.protocol === "amqps:"; this.host = u.hostname || "localhost"; this.port = parseInt(u.port) || (this.tls ? 5671 : 5672); this.insecure = u.searchParams.get("insecure") !== undefined; this.framePos = 0; this.frameSize = 0; this.frameBuffer = Buffer.allocUnsafe(frameMax); } connect() { const socket = this.connectSocket(); Object.defineProperty(this, 'socket', { value: socket, enumerable: false }); return new Promise((resolve, reject) => { socket.on('error', (err) => reject(new AMQPError(err.message, this))); this.connectPromise = [resolve, reject]; }); } connectSocket() { const options = { host: this.host, port: this.port, servername: this.host, rejectUnauthorized: !this.insecure }; 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 `Copied 0 bytes framePos=${this.framePos} bufPos=${bufPos} bytesWritten=${bufLen}`; 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 `Copied 0 bytes framePos=${this.framePos} bufPos=${bufPos} bytesWritten=${bufLen}`; this.framePos += copied; break; } this.frameSize = buf.readInt32BE(bufPos + 3) + 8; if (bufLen - bufPos >= this.frameSize) { const view = new 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 `Copied 0 bytes, please report this bug, frameSize=${this.frameSize} framePos=${this.framePos} bufPos=${bufPos} copyBytes=${copyBytes} bytesWritten=${bufLen}`; this.framePos += copied; bufPos += copied; if (this.framePos === this.frameSize) { const view = new 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) this.socket.write(bytes, undefined, (err) => err ? reject(err) : resolve()); else reject(new AMQPError("Socket not connected", this)); }); } closeSocket() { if (this.socket) this.socket.end(); } } //# sourceMappingURL=amqp-socket-client.js.map