in packages/database/src/realtime/BrowserPollConnection.ts [137:241]
open(onMessage: (msg: {}) => void, onDisconnect: (a?: boolean) => void) {
this.curSegmentNum = 0;
this.onDisconnect_ = onDisconnect;
this.myPacketOrderer = new PacketReceiver(onMessage);
this.isClosed_ = false;
this.connectTimeoutTimer_ = setTimeout(() => {
this.log_('Timed out trying to connect.');
// Make sure we clear the host cache
this.onClosed_();
this.connectTimeoutTimer_ = null;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
}, Math.floor(LP_CONNECT_TIMEOUT)) as any;
// Ensure we delay the creation of the iframe until the DOM is loaded.
executeWhenDOMReady(() => {
if (this.isClosed_) {
return;
}
//Set up a callback that gets triggered once a connection is set up.
this.scriptTagHolder = new FirebaseIFrameScriptHolder(
(...args) => {
const [command, arg1, arg2, arg3, arg4] = args;
this.incrementIncomingBytes_(args);
if (!this.scriptTagHolder) {
return; // we closed the connection.
}
if (this.connectTimeoutTimer_) {
clearTimeout(this.connectTimeoutTimer_);
this.connectTimeoutTimer_ = null;
}
this.everConnected_ = true;
if (command === FIREBASE_LONGPOLL_START_PARAM) {
this.id = arg1 as string;
this.password = arg2 as string;
} else if (command === FIREBASE_LONGPOLL_CLOSE_COMMAND) {
// Don't clear the host cache. We got a response from the server, so we know it's reachable
if (arg1) {
// We aren't expecting any more data (other than what the server's already in the process of sending us
// through our already open polls), so don't send any more.
this.scriptTagHolder.sendNewPolls = false;
// arg1 in this case is the last response number sent by the server. We should try to receive
// all of the responses up to this one before closing
this.myPacketOrderer.closeAfter(arg1 as number, () => {
this.onClosed_();
});
} else {
this.onClosed_();
}
} else {
throw new Error('Unrecognized command received: ' + command);
}
},
(...args) => {
const [pN, data] = args;
this.incrementIncomingBytes_(args);
this.myPacketOrderer.handleResponse(pN as number, data as unknown[]);
},
() => {
this.onClosed_();
},
this.urlFn
);
//Send the initial request to connect. The serial number is simply to keep the browser from pulling previous results
//from cache.
const urlParams: { [k: string]: string | number } = {};
urlParams[FIREBASE_LONGPOLL_START_PARAM] = 't';
urlParams[FIREBASE_LONGPOLL_SERIAL_PARAM] = Math.floor(
Math.random() * 100000000
);
if (this.scriptTagHolder.uniqueCallbackIdentifier) {
urlParams[FIREBASE_LONGPOLL_CALLBACK_ID_PARAM] =
this.scriptTagHolder.uniqueCallbackIdentifier;
}
urlParams[VERSION_PARAM] = PROTOCOL_VERSION;
if (this.transportSessionId) {
urlParams[TRANSPORT_SESSION_PARAM] = this.transportSessionId;
}
if (this.lastSessionId) {
urlParams[LAST_SESSION_PARAM] = this.lastSessionId;
}
if (this.applicationId) {
urlParams[APPLICATION_ID_PARAM] = this.applicationId;
}
if (this.appCheckToken) {
urlParams[APP_CHECK_TOKEN_PARAM] = this.appCheckToken;
}
if (
typeof location !== 'undefined' &&
location.hostname &&
FORGE_DOMAIN_RE.test(location.hostname)
) {
urlParams[REFERER_PARAM] = FORGE_REF;
}
const connectURL = this.urlFn(urlParams);
this.log_('Connecting via long-poll to ' + connectURL);
this.scriptTagHolder.addTag(connectURL, () => {
/* do nothing */
});
});
}