Properly implemented the connection history logger
parent
1e2c20641b
commit
d2503aa4e6
|
@ -40,6 +40,7 @@ import {SelectedClientInfo} from "./SelectedClientInfo";
|
|||
import {SideBarManager} from "tc-shared/SideBarManager";
|
||||
import {ServerEventLog} from "tc-shared/connectionlog/ServerEventLog";
|
||||
import {PlaylistManager} from "tc-shared/music/PlaylistManager";
|
||||
import {connectionHistory} from "tc-shared/connectionlog/History";
|
||||
|
||||
export enum InputHardwareState {
|
||||
MISSING,
|
||||
|
@ -138,6 +139,7 @@ export class ConnectionHandler {
|
|||
|
||||
connection_state: ConnectionState = ConnectionState.UNCONNECTED;
|
||||
serverConnection: AbstractServerConnection;
|
||||
currentConnectId: number; /* Id used for the connection history */
|
||||
|
||||
fileManager: FileManager;
|
||||
|
||||
|
@ -263,7 +265,7 @@ export class ConnectionHandler {
|
|||
this.autoReconnectAttempt = parameters.auto_reconnect_attempt || false;
|
||||
this.handleDisconnect(DisconnectReason.REQUESTED);
|
||||
|
||||
let server_address: ServerAddress = {
|
||||
let resolvedAddress: ServerAddress = {
|
||||
host: "",
|
||||
port: -1
|
||||
};
|
||||
|
@ -271,22 +273,22 @@ export class ConnectionHandler {
|
|||
let _v6_end = addr.indexOf(']');
|
||||
let idx = addr.lastIndexOf(':');
|
||||
if(idx != -1 && idx > _v6_end) {
|
||||
server_address.port = parseInt(addr.substr(idx + 1));
|
||||
server_address.host = addr.substr(0, idx);
|
||||
resolvedAddress.port = parseInt(addr.substr(idx + 1));
|
||||
resolvedAddress.host = addr.substr(0, idx);
|
||||
} else {
|
||||
server_address.host = addr;
|
||||
server_address.port = 9987;
|
||||
resolvedAddress.host = addr;
|
||||
resolvedAddress.port = 9987;
|
||||
}
|
||||
}
|
||||
logInfo(LogCategory.CLIENT, tr("Start connection to %s:%d"), server_address.host, server_address.port);
|
||||
logInfo(LogCategory.CLIENT, tr("Start connection to %s:%d"), resolvedAddress.host, resolvedAddress.port);
|
||||
this.log.log("connection.begin", {
|
||||
address: {
|
||||
server_hostname: server_address.host,
|
||||
server_port: server_address.port
|
||||
server_hostname: resolvedAddress.host,
|
||||
server_port: resolvedAddress.port
|
||||
},
|
||||
client_nickname: parameters.nickname
|
||||
});
|
||||
this.channelTree.initialiseHead(addr, server_address);
|
||||
this.channelTree.initialiseHead(addr, resolvedAddress);
|
||||
|
||||
if(parameters.password && !parameters.password.hashed){
|
||||
try {
|
||||
|
@ -302,28 +304,28 @@ export class ConnectionHandler {
|
|||
}
|
||||
if(parameters.password) {
|
||||
connection_log.update_address_password({
|
||||
hostname: server_address.host,
|
||||
port: server_address.port
|
||||
hostname: resolvedAddress.host,
|
||||
port: resolvedAddress.port
|
||||
}, parameters.password.password);
|
||||
}
|
||||
|
||||
const original_address = {host: server_address.host, port: server_address.port};
|
||||
if(server_address.host === "localhost") {
|
||||
server_address.host = "127.0.0.1";
|
||||
} else if(dns.supported() && !server_address.host.match(Regex.IP_V4) && !server_address.host.match(Regex.IP_V6)) {
|
||||
const originalAddress = {host: resolvedAddress.host, port: resolvedAddress.port};
|
||||
if(resolvedAddress.host === "localhost") {
|
||||
resolvedAddress.host = "127.0.0.1";
|
||||
} else if(dns.supported() && !resolvedAddress.host.match(Regex.IP_V4) && !resolvedAddress.host.match(Regex.IP_V6)) {
|
||||
const id = ++this.connectAttemptId;
|
||||
this.log.log("connection.hostname.resolve", {});
|
||||
try {
|
||||
const resolved = await dns.resolve_address(server_address, { timeout: 5000 }) || {} as any;
|
||||
const resolved = await dns.resolve_address(resolvedAddress, { timeout: 5000 }) || {} as any;
|
||||
if(id != this.connectAttemptId)
|
||||
return; /* we're old */
|
||||
|
||||
server_address.host = typeof(resolved.target_ip) === "string" ? resolved.target_ip : server_address.host;
|
||||
server_address.port = typeof(resolved.target_port) === "number" ? resolved.target_port : server_address.port;
|
||||
resolvedAddress.host = typeof(resolved.target_ip) === "string" ? resolved.target_ip : resolvedAddress.host;
|
||||
resolvedAddress.port = typeof(resolved.target_port) === "number" ? resolved.target_port : resolvedAddress.port;
|
||||
this.log.log("connection.hostname.resolved", {
|
||||
address: {
|
||||
server_port: server_address.port,
|
||||
server_hostname: server_address.host
|
||||
server_port: resolvedAddress.port,
|
||||
server_hostname: resolvedAddress.host
|
||||
}
|
||||
});
|
||||
} catch(error) {
|
||||
|
@ -334,14 +336,22 @@ export class ConnectionHandler {
|
|||
}
|
||||
}
|
||||
|
||||
await this.serverConnection.connect(server_address, new HandshakeHandler(profile, parameters));
|
||||
if(user_action) {
|
||||
this.currentConnectId = await connectionHistory.logConnectionAttempt(originalAddress.host, originalAddress.port);
|
||||
} else {
|
||||
this.currentConnectId = -1;
|
||||
}
|
||||
|
||||
await this.serverConnection.connect(resolvedAddress, new HandshakeHandler(profile, parameters));
|
||||
setTimeout(() => {
|
||||
const connected = this.serverConnection.connected();
|
||||
if(user_action && connected) {
|
||||
connection_log.log_connect({
|
||||
hostname: original_address.host,
|
||||
port: original_address.port
|
||||
hostname: originalAddress.host,
|
||||
port: originalAddress.port
|
||||
});
|
||||
|
||||
/* TODO: Log successful connect/update the server unique id: attemptId */
|
||||
}
|
||||
}, 50);
|
||||
}
|
||||
|
@ -491,6 +501,7 @@ export class ConnectionHandler {
|
|||
private _certificate_modal: Modal;
|
||||
handleDisconnect(type: DisconnectReason, data: any = {}) {
|
||||
this.connectAttemptId++;
|
||||
this.currentConnectId = -1;
|
||||
|
||||
let auto_reconnect = false;
|
||||
switch (type) {
|
||||
|
|
|
@ -0,0 +1,435 @@
|
|||
import {LogCategory, logError, logWarn} from "tc-shared/log";
|
||||
import {tr} from "tc-shared/i18n/localize";
|
||||
import * as loader from "tc-loader";
|
||||
import {Stage} from "tc-loader";
|
||||
import {ConnectionHandler} from "tc-shared/ConnectionHandler";
|
||||
import {server_connections} from "tc-shared/ConnectionManager";
|
||||
import {ServerProperties} from "tc-shared/tree/Server";
|
||||
|
||||
const kUnknownServerUniqueId = "unknown";
|
||||
|
||||
export type ConnectionHistoryEntry = {
|
||||
id: number,
|
||||
timestamp: number,
|
||||
|
||||
targetHost: string,
|
||||
targetPort: number,
|
||||
|
||||
serverUniqueId: string | typeof kUnknownServerUniqueId
|
||||
};
|
||||
|
||||
export type ConnectionHistoryServerEntry = {
|
||||
firstConnectTimestamp: number,
|
||||
firstConnectId: number,
|
||||
|
||||
lastConnectTimestamp: number,
|
||||
lastConnectId: number,
|
||||
}
|
||||
|
||||
export type ConnectionHistoryServerInfo = {
|
||||
name: string,
|
||||
iconId: number,
|
||||
|
||||
/* These properties are only available upon server variable retrieval */
|
||||
clientsOnline: number | -1,
|
||||
clientsMax: number | -1,
|
||||
|
||||
passwordProtected: boolean
|
||||
}
|
||||
|
||||
export class ConnectionHistory {
|
||||
private database: IDBDatabase;
|
||||
|
||||
constructor() { }
|
||||
|
||||
async initializeDatabase() {
|
||||
const openRequest = indexedDB.open("connection-log", 1);
|
||||
openRequest.onupgradeneeded = event => {
|
||||
const database = openRequest.result;
|
||||
switch (event.oldVersion) {
|
||||
case 0:
|
||||
if(!database.objectStoreNames.contains("attempt-history")) {
|
||||
const store = database.createObjectStore("attempt-history", { keyPath: "id", autoIncrement: true });
|
||||
store.createIndex("timestamp", "timestamp", { unique: false });
|
||||
store.createIndex("targetHost", "targetHost", { unique: false });
|
||||
store.createIndex("targetPort", "targetPort", { unique: false });
|
||||
store.createIndex("serverUniqueId", "serverUniqueId", { unique: false });
|
||||
}
|
||||
|
||||
if(!database.objectStoreNames.contains("server-info")) {
|
||||
const store = database.createObjectStore("server-info", { keyPath: "uniqueId" });
|
||||
store.createIndex("firstConnectTimestamp", "firstConnectTimestamp", { unique: false });
|
||||
store.createIndex("firstConnectId", "firstConnectId", { unique: false });
|
||||
|
||||
store.createIndex("lastConnectTimestamp", "lastConnectTimestamp", { unique: false });
|
||||
store.createIndex("lastConnectId", "lastConnectId", { unique: false });
|
||||
|
||||
store.createIndex("name", "name", { unique: false });
|
||||
store.createIndex("iconId", "iconId", { unique: false });
|
||||
|
||||
store.createIndex("clientsOnline", "clientsOnline", { unique: false });
|
||||
store.createIndex("clientsMax", "clientsMax", { unique: false });
|
||||
|
||||
store.createIndex("passwordProtected", "passwordProtected", { unique: false });
|
||||
}
|
||||
|
||||
/* fall through wanted */
|
||||
case 1:
|
||||
break;
|
||||
|
||||
default:
|
||||
throw tra("connection log database has an invalid version: {}", event.oldVersion);
|
||||
}
|
||||
};
|
||||
|
||||
this.database = await new Promise<IDBDatabase>((resolve, reject) => {
|
||||
openRequest.onblocked = () => reject(tr("Failed to open the connection log database"));
|
||||
|
||||
openRequest.onerror = () => {
|
||||
logError(LogCategory.GENERAL, tr("Failed to open the client connection log database: %o"), openRequest.error);
|
||||
reject(openRequest.error.message);
|
||||
};
|
||||
|
||||
openRequest.onsuccess = () => resolve(openRequest.result);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new connection attempt.
|
||||
* @param targetHost
|
||||
* @param targetPort
|
||||
* @return Returns a unique connect attempt identifier id which could be later used to set the unique server id.
|
||||
*/
|
||||
async logConnectionAttempt(targetHost: string, targetPort: number) : Promise<number> {
|
||||
if(!this.database) {
|
||||
return;
|
||||
}
|
||||
|
||||
const transaction = this.database.transaction(["attempt-history"], "readwrite");
|
||||
const store = transaction.objectStore("attempt-history");
|
||||
|
||||
const id = await new Promise<IDBValidKey>((resolve, reject) => {
|
||||
const insert = store.put({
|
||||
timestamp: Date.now(),
|
||||
targetHost: targetHost,
|
||||
targetPort: targetPort,
|
||||
serverUniqueId: kUnknownServerUniqueId
|
||||
});
|
||||
|
||||
insert.onsuccess = () => resolve(insert.result);
|
||||
insert.onerror = () => reject(insert.error);
|
||||
});
|
||||
|
||||
if(typeof id !== "number") {
|
||||
logError(LogCategory.GENERAL, tr("Received invalid idb key type which isn't a number: %o"), id);
|
||||
throw tr("invalid idb key returned");
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
private async resolveDatabaseServerInfo(serverUniqueId: string) : Promise<IDBCursorWithValue | null> {
|
||||
const transaction = this.database.transaction(["server-info"], "readwrite");
|
||||
const store = transaction.objectStore("server-info");
|
||||
|
||||
return await new Promise<IDBCursorWithValue | null>((resolve, reject) => {
|
||||
const cursor = store.openCursor(serverUniqueId);
|
||||
cursor.onsuccess = () => resolve(cursor.result);
|
||||
cursor.onerror = () => reject(cursor.error);
|
||||
});
|
||||
}
|
||||
|
||||
private async updateDatabaseServerInfo(serverUniqueId: string, updateCallback: (databaseValue) => void) {
|
||||
let entry = await this.resolveDatabaseServerInfo(serverUniqueId);
|
||||
|
||||
if(entry) {
|
||||
const newValue = Object.assign({}, entry.value);
|
||||
updateCallback(newValue);
|
||||
await new Promise((resolve, reject) => {
|
||||
const update = entry.update(newValue);
|
||||
update.onsuccess = resolve;
|
||||
update.onerror = () => reject(update.error);
|
||||
});
|
||||
} else {
|
||||
const transaction = this.database.transaction(["server-info"], "readwrite");
|
||||
const store = transaction.objectStore("server-info");
|
||||
|
||||
const value = {
|
||||
uniqueId: serverUniqueId,
|
||||
|
||||
firstConnectTimestamp: 0,
|
||||
firstConnectId: -1,
|
||||
|
||||
lastConnectTimestamp: 0,
|
||||
lastConnectId: -1,
|
||||
|
||||
name: tr("unknown"),
|
||||
iconId: 0,
|
||||
|
||||
clientsOnline: -1,
|
||||
clientsMax: -1,
|
||||
|
||||
passwordProtected: false
|
||||
};
|
||||
|
||||
updateCallback(value);
|
||||
await new Promise((resolve, reject) => {
|
||||
const insert = store.put(value);
|
||||
insert.onsuccess = resolve;
|
||||
insert.onerror = () => reject(insert.error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the connection attempts target server id.
|
||||
* @param connectionAttemptId
|
||||
* @param serverUniqueId
|
||||
*/
|
||||
async updateConnectionServerUniqueId(connectionAttemptId: number, serverUniqueId: string) {
|
||||
if(!this.database) {
|
||||
return;
|
||||
}
|
||||
|
||||
const transaction = this.database.transaction(["attempt-history"], "readwrite");
|
||||
const store = transaction.objectStore("attempt-history");
|
||||
|
||||
let connectAttemptInfo;
|
||||
{
|
||||
const entry = await new Promise<IDBCursorWithValue | null>((resolve, reject) => {
|
||||
const cursor = store.openCursor(connectionAttemptId);
|
||||
cursor.onsuccess = () => resolve(cursor.result);
|
||||
cursor.onerror = () => reject(cursor.error);
|
||||
});
|
||||
|
||||
if(!entry) {
|
||||
throw tr("missing connection attempt");
|
||||
}
|
||||
|
||||
if(entry.value.serverUniqueId === serverUniqueId) {
|
||||
logWarn(LogCategory.GENERAL, tr("updateConnectionServerUniqueId(...) has been called twice"));
|
||||
return;
|
||||
} else if(entry.value.serverUniqueId !== kUnknownServerUniqueId) {
|
||||
throw tr("connection attempt has already a server unique id set");
|
||||
}
|
||||
|
||||
const newValue = connectAttemptInfo = Object.assign({}, entry.value);
|
||||
newValue.serverUniqueId = serverUniqueId;
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
const update = entry.update(newValue);
|
||||
update.onsuccess = resolve;
|
||||
update.onerror = () => reject(update.error);
|
||||
});
|
||||
}
|
||||
|
||||
await this.updateDatabaseServerInfo(serverUniqueId, databaseValue => {
|
||||
if(databaseValue.firstConnectTimestamp === 0) {
|
||||
databaseValue.firstConnectTimestamp = connectAttemptInfo.timestamp;
|
||||
databaseValue.firstConnectId = connectAttemptInfo.id;
|
||||
}
|
||||
|
||||
databaseValue.lastConnectTimestamp = connectAttemptInfo.timestamp;
|
||||
databaseValue.lastConnectId = connectAttemptInfo.id;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the server info of the given server.
|
||||
* @param serverUniqueId
|
||||
* @param info
|
||||
*/
|
||||
async updateServerInfo(serverUniqueId: string, info: ConnectionHistoryServerInfo) {
|
||||
if(!this.database) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
await this.updateDatabaseServerInfo(serverUniqueId, databaseValue => {
|
||||
databaseValue.name = info.name;
|
||||
databaseValue.iconId = info.iconId;
|
||||
|
||||
databaseValue.clientsOnline = info.clientsOnline;
|
||||
databaseValue.clientsMax = info.clientsMax;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the server info of a given server unique id
|
||||
* @param serverUniqueId
|
||||
*/
|
||||
async queryServerInfo(serverUniqueId: string) : Promise<(ConnectionHistoryServerInfo & ConnectionHistoryServerEntry) | undefined> {
|
||||
if(!this.database) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let entry = await this.resolveDatabaseServerInfo(serverUniqueId);
|
||||
if(!entry) {
|
||||
return;
|
||||
}
|
||||
|
||||
const value = entry.value;
|
||||
return {
|
||||
firstConnectId: value.firstConnectId,
|
||||
firstConnectTimestamp: value.firstConnectTimestamp,
|
||||
|
||||
lastConnectId: value.lastConnectId,
|
||||
lastConnectTimestamp: value.lastConnectTimestamp,
|
||||
|
||||
name: value.name,
|
||||
iconId: value.iconId,
|
||||
|
||||
clientsOnline: value.clientsOnline,
|
||||
clientsMax: value.clientsMax,
|
||||
|
||||
passwordProtected: value.passwordProtected
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the last connected addresses/servers.
|
||||
* @param maxUniqueServers
|
||||
*/
|
||||
async lastConnectedServers(maxUniqueServers: number) : Promise<ConnectionHistoryEntry[]> {
|
||||
if(!this.database) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const result: ConnectionHistoryEntry[] = [];
|
||||
|
||||
const transaction = this.database.transaction(["attempt-history"], "readwrite");
|
||||
const store = transaction.objectStore("attempt-history");
|
||||
|
||||
const cursor = store.index("timestamp").openCursor(undefined, "prev");
|
||||
while(result.length < maxUniqueServers) {
|
||||
const entry = await new Promise<IDBCursorWithValue | null>((resolve, reject) => {
|
||||
cursor.onsuccess = () => resolve(cursor.result);
|
||||
cursor.onerror = () => reject(cursor.error);
|
||||
});
|
||||
|
||||
if(!entry) {
|
||||
break;
|
||||
}
|
||||
|
||||
const parsedEntry = {
|
||||
id: entry.value.id,
|
||||
timestamp: entry.value.timestamp,
|
||||
|
||||
targetHost: entry.value.targetHost,
|
||||
targetPort: entry.value.targetPort,
|
||||
|
||||
serverUniqueId: entry.value.serverUniqueId,
|
||||
} as ConnectionHistoryEntry;
|
||||
entry.continue();
|
||||
|
||||
if(parsedEntry.serverUniqueId !== kUnknownServerUniqueId) {
|
||||
if(result.findIndex(entry => entry.serverUniqueId === parsedEntry.serverUniqueId) !== -1) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if(result.findIndex(entry => {
|
||||
return entry.targetHost === parsedEntry.targetHost && entry.targetPort === parsedEntry.targetPort;
|
||||
}) !== -1) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
result.push(parsedEntry);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
const kConnectServerInfoUpdatePropertyKeys: (keyof ServerProperties)[] = [
|
||||
"virtualserver_icon_id",
|
||||
"virtualserver_name",
|
||||
"virtualserver_flag_password",
|
||||
"virtualserver_maxclients",
|
||||
"virtualserver_clientsonline",
|
||||
"virtualserver_flag_password"
|
||||
];
|
||||
|
||||
class ConnectionHistoryUpdateListener {
|
||||
private readonly history: ConnectionHistory;
|
||||
|
||||
private listenerHandlerManager: (() => void)[];
|
||||
private listenerConnectionHandler: {[key: string]: (() => void)[]} = {};
|
||||
|
||||
constructor(history: ConnectionHistory) {
|
||||
this.history = history;
|
||||
this.listenerHandlerManager = [];
|
||||
|
||||
this.listenerHandlerManager.push(server_connections.events().on("notify_handler_created", event => {
|
||||
this.registerConnectionHandler(event.handler);
|
||||
}));
|
||||
|
||||
this.listenerHandlerManager.push(server_connections.events().on("notify_handler_deleted", event => {
|
||||
this.listenerConnectionHandler[event.handler.handlerId]?.forEach(callback => callback());
|
||||
delete this.listenerConnectionHandler[event.handler.handlerId];
|
||||
}));
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.listenerHandlerManager.forEach(callback => callback());
|
||||
|
||||
Object.values(this.listenerConnectionHandler).forEach(callbacks => callbacks.forEach(callback => callback()));
|
||||
this.listenerConnectionHandler = {};
|
||||
}
|
||||
|
||||
private registerConnectionHandler(handler: ConnectionHandler) {
|
||||
handler.channelTree.server.events.on("notify_properties_updated", event => {
|
||||
if("virtualserver_unique_identifier" in event.updated_properties) {
|
||||
if(handler.currentConnectId > 0) {
|
||||
this.history.updateConnectionServerUniqueId(handler.currentConnectId, event.server_properties.virtualserver_unique_identifier)
|
||||
.catch(error => {
|
||||
logError(LogCategory.GENERAL, tr("Failed to update connect server unique id: %o"), error);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for(const key of kConnectServerInfoUpdatePropertyKeys) {
|
||||
if(key in event.updated_properties) {
|
||||
this.history.updateServerInfo(event.server_properties.virtualserver_unique_identifier, {
|
||||
name: event.server_properties.virtualserver_name,
|
||||
iconId: event.server_properties.virtualserver_icon_id,
|
||||
|
||||
clientsMax: event.server_properties.virtualserver_maxclients,
|
||||
clientsOnline: event.server_properties.virtualserver_clientsonline,
|
||||
|
||||
passwordProtected: event.server_properties.virtualserver_flag_password
|
||||
}).catch(error => {
|
||||
logError(LogCategory.GENERAL, tr("Failed to update connect server info: %o"), error);
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export let connectionHistory: ConnectionHistory;
|
||||
let historyInfoListener: ConnectionHistoryUpdateListener;
|
||||
|
||||
loader.register_task(Stage.JAVASCRIPT_INITIALIZING, {
|
||||
priority: 0,
|
||||
name: "Chat history setup",
|
||||
function: async () => {
|
||||
if(!('indexedDB' in window)) {
|
||||
loader.critical_error(tr("Missing Indexed DB support"));
|
||||
throw tr("Missing Indexed DB support");
|
||||
}
|
||||
|
||||
connectionHistory = new ConnectionHistory();
|
||||
try {
|
||||
await connectionHistory.initializeDatabase();
|
||||
} catch (error) {
|
||||
logError(LogCategory.GENERAL, tr("Failed to initialize connection history database: %o"), error);
|
||||
logError(LogCategory.GENERAL, tr("Do not saving the connection attempts."));
|
||||
return;
|
||||
}
|
||||
|
||||
historyInfoListener = new ConnectionHistoryUpdateListener(connectionHistory);
|
||||
(window as any).connectionHistory = connectionHistory;
|
||||
}
|
||||
});
|
|
@ -206,8 +206,9 @@ async function doOpenDatabase(forceUpgrade: boolean) {
|
|||
|
||||
function doInitializeUser(uniqueId: string, database: IDBDatabase) {
|
||||
const storeId = clientUniqueId2StoreName(uniqueId);
|
||||
if(database.objectStoreNames.contains(storeId))
|
||||
if(database.objectStoreNames.contains(storeId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const store = database.createObjectStore(storeId, { keyPath: "databaseId", autoIncrement: true });
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ export interface ServerAddress {
|
|||
|
||||
export interface ServerEvents extends ChannelTreeEntryEvents {
|
||||
notify_properties_updated: {
|
||||
updated_properties: {[Key in keyof ServerProperties]: ServerProperties[Key]};
|
||||
updated_properties: Partial<ServerProperties>;
|
||||
server_properties: ServerProperties
|
||||
}
|
||||
}
|
||||
|
@ -267,24 +267,26 @@ export class ServerEntry extends ChannelTreeEntry<ServerEvents> {
|
|||
log.table(LogType.DEBUG, LogCategory.PERMISSIONS, "Server update properties", entries);
|
||||
}
|
||||
|
||||
let updatedProperties: Partial<ServerProperties> = {};
|
||||
let update_bookmarks = false;
|
||||
for(let variable of variables) {
|
||||
JSON.map_field_to(this.properties, variable.value, variable.key);
|
||||
if(!JSON.map_field_to(this.properties, variable.value, variable.key)) {
|
||||
/* The value has not been updated */
|
||||
continue;
|
||||
}
|
||||
|
||||
updatedProperties[variable.key] = variable.value;
|
||||
if(variable.key == "virtualserver_icon_id") {
|
||||
/* For more detail lookup client::updateVariables and client_icon_id!
|
||||
* ATTENTION: This is required!
|
||||
*/
|
||||
this.properties.virtualserver_icon_id = variable.value as any >>> 0;
|
||||
update_bookmarks = true;
|
||||
}
|
||||
}
|
||||
{
|
||||
let properties = {};
|
||||
for(const property of variables)
|
||||
properties[property.key] = this.properties[property.key];
|
||||
this.events.fire("notify_properties_updated", { updated_properties: properties as any, server_properties: this.properties });
|
||||
}
|
||||
|
||||
this.events.fire("notify_properties_updated", {
|
||||
updated_properties: updatedProperties,
|
||||
server_properties: this.properties
|
||||
});
|
||||
|
||||
if(update_bookmarks) {
|
||||
const bmarks = bookmarks.bookmarks_flat()
|
||||
.filter(e => e.server_properties.server_address === this.remote_address.host && e.server_properties.server_port == this.remote_address.port)
|
||||
|
|
|
@ -4,7 +4,6 @@ import {LogCategory} from "../../log";
|
|||
import * as loader from "tc-loader";
|
||||
import {createModal} from "../../ui/elements/Modal";
|
||||
import {ConnectionProfile, defaultConnectProfile, findConnectProfile, availableConnectProfiles} from "../../profiles/ConnectionProfile";
|
||||
import {KeyCode} from "../../PPTListener";
|
||||
import * as i18nc from "../../i18n/country";
|
||||
import {spawnSettingsModal} from "../../ui/modal/ModalSettings";
|
||||
import {server_connections} from "tc-shared/ConnectionManager";
|
||||
|
|
Loading…
Reference in New Issue