You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-desktop/js/modules/loki_p2p_api.js

129 lines
3.3 KiB
JavaScript

/* global setTimeout, clearTimeout */
const EventEmitter = require('events');
const offlinePingTime = 2 * 60 * 1000; // 2 minutes
class LokiP2pAPI extends EventEmitter {
constructor(ourKey) {
super();
this.contactP2pDetails = {};
this.ourKey = ourKey;
}
reset() {
Object.keys(this.contactP2pDetails).forEach(key => {
clearTimeout(this.contactP2pDetails[key].pingTimer);
delete this.contactP2pDetails[key];
});
}
updateContactP2pDetails(pubKey, address, port, isPing = false) {
// Stagger the timers so the friends don't ping each other at the same time
const timerDuration =
pubKey < this.ourKey
? 60 * 1000 // 1 minute
: 2 * 60 * 1000; // 2 minutes
if (!this.contactP2pDetails[pubKey]) {
// We didn't have this contact's details
this.contactP2pDetails[pubKey] = {
address,
port,
timerDuration,
pingTimer: null,
isOnline: false,
};
if (isPing) {
this.setContactOnline(pubKey);
return;
}
// Try ping
this.pingContact(pubKey);
return;
}
// We already had this contact's details
const baseDetails = { ...this.contactP2pDetails[pubKey] };
if (isPing) {
// Received a ping
// Update details in case they are new and mark online
this.contactP2pDetails[pubKey].address = address;
this.contactP2pDetails[pubKey].port = port;
this.setContactOnline(pubKey);
return;
}
// Received a storage broadcast message
if (
baseDetails.isOnline ||
baseDetails.address !== address ||
baseDetails.port !== port
) {
// Had the contact marked as online and details we had were the same
this.pingContact(pubKey);
return;
}
// Had the contact marked as offline or got new details
this.contactP2pDetails[pubKey].address = address;
this.contactP2pDetails[pubKey].port = port;
this.setContactOffline(pubKey);
this.pingContact(pubKey);
}
getContactP2pDetails(pubKey) {
return this.contactP2pDetails[pubKey] || null;
}
isContactOnline(pubKey) {
const contactDetails = this.contactP2pDetails[pubKey];
return !!(contactDetails && contactDetails.isOnline);
}
setContactOffline(pubKey) {
this.emit('offline', pubKey);
if (!this.contactP2pDetails[pubKey]) {
return;
}
clearTimeout(this.contactP2pDetails[pubKey].pingTimer);
this.contactP2pDetails[pubKey].pingTimer = setTimeout(
this.pingContact.bind(this),
offlinePingTime,
pubKey
);
this.contactP2pDetails[pubKey].isOnline = false;
}
setContactOnline(pubKey) {
if (!this.contactP2pDetails[pubKey]) {
return;
}
this.emit('online', pubKey);
clearTimeout(this.contactP2pDetails[pubKey].pingTimer);
this.contactP2pDetails[pubKey].isOnline = true;
this.contactP2pDetails[pubKey].pingTimer = setTimeout(
this.pingContact.bind(this),
this.contactP2pDetails[pubKey].timerDuration,
pubKey
);
}
isOnline(pubKey) {
return !!(
this.contactP2pDetails[pubKey] && this.contactP2pDetails[pubKey].isOnline
);
}
pingContact(pubKey) {
if (!this.contactP2pDetails[pubKey]) {
// Don't ping if we don't have their details
return;
}
this.emit('pingContact', pubKey);
}
}
module.exports = LokiP2pAPI;