123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- import { EventEmitter } from 'events';
- /**
- * Wrapper around the Cloudflare built-in socket that can be used by the `Connection`.
- */
- export class CloudflareSocket extends EventEmitter {
- constructor(ssl) {
- super();
- this.ssl = ssl;
- this.writable = false;
- this.destroyed = false;
- this._upgrading = false;
- this._upgraded = false;
- this._cfSocket = null;
- this._cfWriter = null;
- this._cfReader = null;
- }
- setNoDelay() {
- return this;
- }
- setKeepAlive() {
- return this;
- }
- ref() {
- return this;
- }
- unref() {
- return this;
- }
- async connect(port, host, connectListener) {
- try {
- log('connecting');
- if (connectListener)
- this.once('connect', connectListener);
- const options = this.ssl ? { secureTransport: 'starttls' } : {};
- const { connect } = await import('cloudflare:sockets');
- this._cfSocket = connect(`${host}:${port}`, options);
- this._cfWriter = this._cfSocket.writable.getWriter();
- this._addClosedHandler();
- this._cfReader = this._cfSocket.readable.getReader();
- if (this.ssl) {
- this._listenOnce().catch((e) => this.emit('error', e));
- }
- else {
- this._listen().catch((e) => this.emit('error', e));
- }
- await this._cfWriter.ready;
- log('socket ready');
- this.writable = true;
- this.emit('connect');
- return this;
- }
- catch (e) {
- this.emit('error', e);
- }
- }
- async _listen() {
- while (true) {
- log('awaiting receive from CF socket');
- const { done, value } = await this._cfReader.read();
- log('CF socket received:', done, value);
- if (done) {
- log('done');
- break;
- }
- this.emit('data', Buffer.from(value));
- }
- }
- async _listenOnce() {
- log('awaiting first receive from CF socket');
- const { done, value } = await this._cfReader.read();
- log('First CF socket received:', done, value);
- this.emit('data', Buffer.from(value));
- }
- write(data, encoding = 'utf8', callback = () => { }) {
- if (data.length === 0)
- return callback();
- if (typeof data === 'string')
- data = Buffer.from(data, encoding);
- log('sending data direct:', data);
- this._cfWriter.write(data).then(() => {
- log('data sent');
- callback();
- }, (err) => {
- log('send error', err);
- callback(err);
- });
- return true;
- }
- end(data = Buffer.alloc(0), encoding = 'utf8', callback = () => { }) {
- log('ending CF socket');
- this.write(data, encoding, (err) => {
- this._cfSocket.close();
- if (callback)
- callback(err);
- });
- return this;
- }
- destroy(reason) {
- log('destroying CF socket', reason);
- this.destroyed = true;
- return this.end();
- }
- startTls(options) {
- if (this._upgraded) {
- // Don't try to upgrade again.
- this.emit('error', 'Cannot call `startTls()` more than once on a socket');
- return;
- }
- this._cfWriter.releaseLock();
- this._cfReader.releaseLock();
- this._upgrading = true;
- this._cfSocket = this._cfSocket.startTls(options);
- this._cfWriter = this._cfSocket.writable.getWriter();
- this._cfReader = this._cfSocket.readable.getReader();
- this._addClosedHandler();
- this._listen().catch((e) => this.emit('error', e));
- }
- _addClosedHandler() {
- this._cfSocket.closed.then(() => {
- if (!this._upgrading) {
- log('CF socket closed');
- this._cfSocket = null;
- this.emit('close');
- }
- else {
- this._upgrading = false;
- this._upgraded = true;
- }
- }).catch((e) => this.emit('error', e));
- }
- }
- const debug = false;
- function dump(data) {
- if (data instanceof Uint8Array || data instanceof ArrayBuffer) {
- const hex = Buffer.from(data).toString('hex');
- const str = new TextDecoder().decode(data);
- return `\n>>> STR: "${str.replace(/\n/g, '\\n')}"\n>>> HEX: ${hex}\n`;
- }
- else {
- return data;
- }
- }
- function log(...args) {
- debug && console.log(...args.map(dump));
- }
- //# sourceMappingURL=index.js.map
|