| [62b2964] | 1 | "use strict";
|
|---|
| 2 | Object.defineProperty(exports, "__esModule", { value: true });
|
|---|
| 3 | exports.CloudflareSocket = void 0;
|
|---|
| 4 | const events_1 = require("events");
|
|---|
| 5 | /**
|
|---|
| 6 | * Wrapper around the Cloudflare built-in socket that can be used by the `Connection`.
|
|---|
| 7 | */
|
|---|
| 8 | class CloudflareSocket extends events_1.EventEmitter {
|
|---|
| 9 | constructor(ssl) {
|
|---|
| 10 | super();
|
|---|
| 11 | this.ssl = ssl;
|
|---|
| 12 | this.writable = false;
|
|---|
| 13 | this.destroyed = false;
|
|---|
| 14 | this._upgrading = false;
|
|---|
| 15 | this._upgraded = false;
|
|---|
| 16 | this._cfSocket = null;
|
|---|
| 17 | this._cfWriter = null;
|
|---|
| 18 | this._cfReader = null;
|
|---|
| 19 | }
|
|---|
| 20 | setNoDelay() {
|
|---|
| 21 | return this;
|
|---|
| 22 | }
|
|---|
| 23 | setKeepAlive() {
|
|---|
| 24 | return this;
|
|---|
| 25 | }
|
|---|
| 26 | ref() {
|
|---|
| 27 | return this;
|
|---|
| 28 | }
|
|---|
| 29 | unref() {
|
|---|
| 30 | return this;
|
|---|
| 31 | }
|
|---|
| 32 | async connect(port, host, connectListener) {
|
|---|
| 33 | try {
|
|---|
| 34 | log('connecting');
|
|---|
| 35 | if (connectListener)
|
|---|
| 36 | this.once('connect', connectListener);
|
|---|
| 37 | const options = this.ssl ? { secureTransport: 'starttls' } : {};
|
|---|
| 38 | const mod = await import('cloudflare:sockets');
|
|---|
| 39 | const connect = mod.connect;
|
|---|
| 40 | this._cfSocket = connect(`${host}:${port}`, options);
|
|---|
| 41 | this._cfWriter = this._cfSocket.writable.getWriter();
|
|---|
| 42 | this._addClosedHandler();
|
|---|
| 43 | this._cfReader = this._cfSocket.readable.getReader();
|
|---|
| 44 | if (this.ssl) {
|
|---|
| 45 | this._listenOnce().catch((e) => this.emit('error', e));
|
|---|
| 46 | }
|
|---|
| 47 | else {
|
|---|
| 48 | this._listen().catch((e) => this.emit('error', e));
|
|---|
| 49 | }
|
|---|
| 50 | await this._cfWriter.ready;
|
|---|
| 51 | log('socket ready');
|
|---|
| 52 | this.writable = true;
|
|---|
| 53 | this.emit('connect');
|
|---|
| 54 | return this;
|
|---|
| 55 | }
|
|---|
| 56 | catch (e) {
|
|---|
| 57 | this.emit('error', e);
|
|---|
| 58 | }
|
|---|
| 59 | }
|
|---|
| 60 | async _listen() {
|
|---|
| 61 | // eslint-disable-next-line no-constant-condition
|
|---|
| 62 | while (true) {
|
|---|
| 63 | log('awaiting receive from CF socket');
|
|---|
| 64 | const { done, value } = await this._cfReader.read();
|
|---|
| 65 | log('CF socket received:', done, value);
|
|---|
| 66 | if (done) {
|
|---|
| 67 | log('done');
|
|---|
| 68 | break;
|
|---|
| 69 | }
|
|---|
| 70 | this.emit('data', Buffer.from(value));
|
|---|
| 71 | }
|
|---|
| 72 | }
|
|---|
| 73 | async _listenOnce() {
|
|---|
| 74 | log('awaiting first receive from CF socket');
|
|---|
| 75 | const { done, value } = await this._cfReader.read();
|
|---|
| 76 | log('First CF socket received:', done, value);
|
|---|
| 77 | this.emit('data', Buffer.from(value));
|
|---|
| 78 | }
|
|---|
| 79 | write(data, encoding = 'utf8', callback = () => { }) {
|
|---|
| 80 | if (data.length === 0)
|
|---|
| 81 | return callback();
|
|---|
| 82 | if (typeof data === 'string')
|
|---|
| 83 | data = Buffer.from(data, encoding);
|
|---|
| 84 | log('sending data direct:', data);
|
|---|
| 85 | this._cfWriter.write(data).then(() => {
|
|---|
| 86 | log('data sent');
|
|---|
| 87 | callback();
|
|---|
| 88 | }, (err) => {
|
|---|
| 89 | log('send error', err);
|
|---|
| 90 | callback(err);
|
|---|
| 91 | });
|
|---|
| 92 | return true;
|
|---|
| 93 | }
|
|---|
| 94 | end(data = Buffer.alloc(0), encoding = 'utf8', callback = () => { }) {
|
|---|
| 95 | log('ending CF socket');
|
|---|
| 96 | this.write(data, encoding, (err) => {
|
|---|
| 97 | this._cfSocket.close();
|
|---|
| 98 | if (callback)
|
|---|
| 99 | callback(err);
|
|---|
| 100 | });
|
|---|
| 101 | return this;
|
|---|
| 102 | }
|
|---|
| 103 | destroy(reason) {
|
|---|
| 104 | log('destroying CF socket', reason);
|
|---|
| 105 | this.destroyed = true;
|
|---|
| 106 | return this.end();
|
|---|
| 107 | }
|
|---|
| 108 | startTls(options) {
|
|---|
| 109 | if (this._upgraded) {
|
|---|
| 110 | // Don't try to upgrade again.
|
|---|
| 111 | this.emit('error', 'Cannot call `startTls()` more than once on a socket');
|
|---|
| 112 | return;
|
|---|
| 113 | }
|
|---|
| 114 | this._cfWriter.releaseLock();
|
|---|
| 115 | this._cfReader.releaseLock();
|
|---|
| 116 | this._upgrading = true;
|
|---|
| 117 | this._cfSocket = this._cfSocket.startTls(options);
|
|---|
| 118 | this._cfWriter = this._cfSocket.writable.getWriter();
|
|---|
| 119 | this._cfReader = this._cfSocket.readable.getReader();
|
|---|
| 120 | this._addClosedHandler();
|
|---|
| 121 | this._listen().catch((e) => this.emit('error', e));
|
|---|
| 122 | }
|
|---|
| 123 | _addClosedHandler() {
|
|---|
| 124 | this._cfSocket.closed.then(() => {
|
|---|
| 125 | if (!this._upgrading) {
|
|---|
| 126 | log('CF socket closed');
|
|---|
| 127 | this._cfSocket = null;
|
|---|
| 128 | this.emit('close');
|
|---|
| 129 | }
|
|---|
| 130 | else {
|
|---|
| 131 | this._upgrading = false;
|
|---|
| 132 | this._upgraded = true;
|
|---|
| 133 | }
|
|---|
| 134 | }).catch((e) => this.emit('error', e));
|
|---|
| 135 | }
|
|---|
| 136 | }
|
|---|
| 137 | exports.CloudflareSocket = CloudflareSocket;
|
|---|
| 138 | const debug = false;
|
|---|
| 139 | function dump(data) {
|
|---|
| 140 | if (data instanceof Uint8Array || data instanceof ArrayBuffer) {
|
|---|
| 141 | // workaround https://github.com/microsoft/TypeScript/issues/63447
|
|---|
| 142 | const buf = data instanceof Uint8Array ? Buffer.from(data) : Buffer.from(data);
|
|---|
| 143 | const hex = buf.toString('hex');
|
|---|
| 144 | const str = new TextDecoder().decode(data);
|
|---|
| 145 | return `\n>>> STR: "${str.replace(/\n/g, '\\n')}"\n>>> HEX: ${hex}\n`;
|
|---|
| 146 | }
|
|---|
| 147 | else {
|
|---|
| 148 | return data;
|
|---|
| 149 | }
|
|---|
| 150 | }
|
|---|
| 151 | function log(...args) {
|
|---|
| 152 | debug && console.log(...args.map(dump));
|
|---|
| 153 | }
|
|---|
| 154 | //# sourceMappingURL=index.js.map |
|---|