145 lines
3.6 KiB
JavaScript
145 lines
3.6 KiB
JavaScript
import { decodePacket } from "engine.io-parser";
|
|
import { Emitter } from "@socket.io/component-emitter";
|
|
import { installTimerFunctions } from "./util.js";
|
|
import debugModule from "debug"; // debug()
|
|
import { encode } from "./contrib/parseqs.js";
|
|
const debug = debugModule("engine.io-client:transport"); // debug()
|
|
export class TransportError extends Error {
|
|
constructor(reason, description, context) {
|
|
super(reason);
|
|
this.description = description;
|
|
this.context = context;
|
|
this.type = "TransportError";
|
|
}
|
|
}
|
|
export class Transport extends Emitter {
|
|
/**
|
|
* Transport abstract constructor.
|
|
*
|
|
* @param {Object} opts - options
|
|
* @protected
|
|
*/
|
|
constructor(opts) {
|
|
super();
|
|
this.writable = false;
|
|
installTimerFunctions(this, opts);
|
|
this.opts = opts;
|
|
this.query = opts.query;
|
|
this.socket = opts.socket;
|
|
}
|
|
/**
|
|
* Emits an error.
|
|
*
|
|
* @param {String} reason
|
|
* @param description
|
|
* @param context - the error context
|
|
* @return {Transport} for chaining
|
|
* @protected
|
|
*/
|
|
onError(reason, description, context) {
|
|
super.emitReserved("error", new TransportError(reason, description, context));
|
|
return this;
|
|
}
|
|
/**
|
|
* Opens the transport.
|
|
*/
|
|
open() {
|
|
this.readyState = "opening";
|
|
this.doOpen();
|
|
return this;
|
|
}
|
|
/**
|
|
* Closes the transport.
|
|
*/
|
|
close() {
|
|
if (this.readyState === "opening" || this.readyState === "open") {
|
|
this.doClose();
|
|
this.onClose();
|
|
}
|
|
return this;
|
|
}
|
|
/**
|
|
* Sends multiple packets.
|
|
*
|
|
* @param {Array} packets
|
|
*/
|
|
send(packets) {
|
|
if (this.readyState === "open") {
|
|
this.write(packets);
|
|
}
|
|
else {
|
|
// this might happen if the transport was silently closed in the beforeunload event handler
|
|
debug("transport is not open, discarding packets");
|
|
}
|
|
}
|
|
/**
|
|
* Called upon open
|
|
*
|
|
* @protected
|
|
*/
|
|
onOpen() {
|
|
this.readyState = "open";
|
|
this.writable = true;
|
|
super.emitReserved("open");
|
|
}
|
|
/**
|
|
* Called with data.
|
|
*
|
|
* @param {String} data
|
|
* @protected
|
|
*/
|
|
onData(data) {
|
|
const packet = decodePacket(data, this.socket.binaryType);
|
|
this.onPacket(packet);
|
|
}
|
|
/**
|
|
* Called with a decoded packet.
|
|
*
|
|
* @protected
|
|
*/
|
|
onPacket(packet) {
|
|
super.emitReserved("packet", packet);
|
|
}
|
|
/**
|
|
* Called upon close.
|
|
*
|
|
* @protected
|
|
*/
|
|
onClose(details) {
|
|
this.readyState = "closed";
|
|
super.emitReserved("close", details);
|
|
}
|
|
/**
|
|
* Pauses the transport, in order not to lose packets during an upgrade.
|
|
*
|
|
* @param onPause
|
|
*/
|
|
pause(onPause) { }
|
|
createUri(schema, query = {}) {
|
|
return (schema +
|
|
"://" +
|
|
this._hostname() +
|
|
this._port() +
|
|
this.opts.path +
|
|
this._query(query));
|
|
}
|
|
_hostname() {
|
|
const hostname = this.opts.hostname;
|
|
return hostname.indexOf(":") === -1 ? hostname : "[" + hostname + "]";
|
|
}
|
|
_port() {
|
|
if (this.opts.port &&
|
|
((this.opts.secure && Number(this.opts.port !== 443)) ||
|
|
(!this.opts.secure && Number(this.opts.port) !== 80))) {
|
|
return ":" + this.opts.port;
|
|
}
|
|
else {
|
|
return "";
|
|
}
|
|
}
|
|
_query(query) {
|
|
const encodedQuery = encode(query);
|
|
return encodedQuery.length ? "?" + encodedQuery : "";
|
|
}
|
|
}
|