From 1f58e1575963312a9ac1d57bbc5988e389ef4d92 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 24 Mar 2021 11:36:13 -0700 Subject: [PATCH] Add 'active' boolean to a domain to denote if the domain is heartbeating Include 'active', 'protocol', and 'version' is domain information in Place returned info Update number of domain reported users to be sum of logged in and anonymous avatars Reorder Place return tests so /api/v1/places does not return Places with no domains Update documentation on return of added fields for Places --- docs/API-Places.md | 3 +++ docs/API-Users.md | 2 +- src/Entities/DomainEntity.ts | 3 ++- src/Entities/DomainFields.ts | 9 +++++++++ src/Entities/Domains.ts | 1 + src/Entities/Places.ts | 16 ++++++++-------- src/route-tools/Util.ts | 5 ++++- src/routes/api/v1/domains/domainId.ts | 4 +++- src/routes/api/v1/places.ts | 4 ++-- 9 files changed, 33 insertions(+), 14 deletions(-) diff --git a/docs/API-Places.md b/docs/API-Places.md index b1909497..8b634412 100755 --- a/docs/API-Places.md +++ b/docs/API-Places.md @@ -105,6 +105,9 @@ This request return JSON formatted as: "sponsorAccountId": string, "network_address": string, "ice_server_address": string, + 'version': string, // version of domain-server + 'protocol_version': string, // protocol version for domain-server + 'active': boolean, // true if domain is heartbeating "time_of_last_heartbeat": ISOStringDate, "num_users": integer }, diff --git a/docs/API-Users.md b/docs/API-Users.md index 902712b1..79340c39 100755 --- a/docs/API-Users.md +++ b/docs/API-Users.md @@ -51,7 +51,7 @@ The response body is an "applicaton/json" structure that contains an array of us "node_id": stringSessionId, "root": { "domain": { - "id": + "id": string "network_address": stringHostname, "network_port": intPortNum, "ice_server_address": stringHostname, diff --git a/src/Entities/DomainEntity.ts b/src/Entities/DomainEntity.ts index 879b84e7..87e01ade 100755 --- a/src/Entities/DomainEntity.ts +++ b/src/Entities/DomainEntity.ts @@ -51,7 +51,8 @@ export class DomainEntity implements Entity { // admin stuff public iPAddrOfFirstContact: string; // IP address that registered this domain - public whenCreated: Date; // What the variable name says + public whenCreated: Date; // What the variable name says + public active: boolean; // domain is heartbeating public timeOfLastHeartbeat: Date; // time of last heartbeat public lastSenderKey: string; // a key identifying the sender diff --git a/src/Entities/DomainFields.ts b/src/Entities/DomainFields.ts index 652b8650..b98aa4e2 100644 --- a/src/Entities/DomainFields.ts +++ b/src/Entities/DomainFields.ts @@ -319,6 +319,15 @@ export const DomainFields: { [key: string]: FieldDefn } = { setter: noSetter, getter: dateStringGetter }, + 'active': { + entity_field: 'active', + request_field_name: 'active', + get_permissions: [ Perm.ALL ], + set_permissions: [ Perm.NONE ], + validate: isBooleanValidator, + setter: noSetter, + getter: simpleGetter + }, 'time_of_last_heartbeat': { entity_field: 'timeOfLastHeartbeat', request_field_name: 'time_of_last_heartbeat', diff --git a/src/Entities/Domains.ts b/src/Entities/Domains.ts index ced3566f..b0264ad3 100755 --- a/src/Entities/Domains.ts +++ b/src/Entities/Domains.ts @@ -52,6 +52,7 @@ export function initDomains(): void { Logger.info(`Domains: domain ${aDomain.name} not heartbeating. Zeroing users.`); aDomain.numUsers = 0; aDomain.anonUsers = 0; + aDomain.active = false; const updates: VKeyedCollection = { 'numUsers': 0, 'anonUsers': 0 diff --git a/src/Entities/Places.ts b/src/Entities/Places.ts index 1793b820..95c29262 100755 --- a/src/Entities/Places.ts +++ b/src/Entities/Places.ts @@ -174,19 +174,19 @@ export const Places = { // The address is of the form "optional-domain/x,y,z/x,y,z,w". // If the domain is missing, the domain-server's network address is added let addr = pPlace.path ?? '/0,0,0/0,0,0,1'; + + // If no domain/address specified in path, build addr using reported domain IP/port const pieces = addr.split('/'); - // kludge as there were a bunch of "undefined" domain/address names - if (pieces.length > 0 && pieces[0].length === 9 && pieces[0] === 'undefined') { - pieces[0] = ''; - }; if (pieces[0].length === 0) { const aDomain = await Domains.getDomainWithId(pPlace.domainId); if (IsNotNullOrEmpty(aDomain)) { - let domainAddr = aDomain.networkAddr; - if (IsNotNullOrEmpty(aDomain.networkPort)) { - domainAddr = aDomain.networkAddr + ":" + aDomain.networkPort; + if (IsNotNullOrEmpty(aDomain.networkAddr)) { + let domainAddr = aDomain.networkAddr; + if (IsNotNullOrEmpty(aDomain.networkPort)) { + domainAddr = aDomain.networkAddr + ":" + aDomain.networkPort; + }; + addr = domainAddr + addr; }; - addr = domainAddr + addr; }; }; return addr; diff --git a/src/route-tools/Util.ts b/src/route-tools/Util.ts index 49fcf4c9..224615a3 100755 --- a/src/route-tools/Util.ts +++ b/src/route-tools/Util.ts @@ -134,8 +134,11 @@ export async function buildDomainInfo(pDomain: DomainEntity): Promise { 'network_address': pDomain.networkAddr, 'network_port': pDomain.networkPort, 'ice_server_address': pDomain.iceServerAddr, + 'version': pDomain.version, + 'protocol_version': pDomain.protocol, + 'active': pDomain.active ?? false, 'time_of_last_heartbeat': pDomain.timeOfLastHeartbeat ? pDomain.timeOfLastHeartbeat.toISOString() : undefined, - 'num_users': pDomain.numUsers + 'num_users': pDomain.numUsers + pDomain.anonUsers }; } diff --git a/src/routes/api/v1/domains/domainId.ts b/src/routes/api/v1/domains/domainId.ts index 58fd58be..6f0b4fee 100755 --- a/src/routes/api/v1/domains/domainId.ts +++ b/src/routes/api/v1/domains/domainId.ts @@ -31,6 +31,7 @@ import { VKeyedCollection } from '@Tools/vTypes'; import { Logger } from '@Tools/Logging'; import Config from '@Base/config'; import { IsNullOrEmpty } from '@Tools/Misc'; +import { updateObjectFields } from '@Tools/Db'; // GET /api/v1/domains/:domainId // Return a small snippet if domain data for the domainId specified in the request @@ -90,7 +91,7 @@ const procPutDomains: RequestHandler = async (req: Request, resp: Response, next }; }; - /* FOLLOWING CODE DOES NOT WORK: the socker.remoteAddress is the IP addr + /* FOLLOWING CODE DOES NOT WORK: the socket.remoteAddress is the IP addr of the front end proxy server. Need to use 'x-forwarded-for:' header or whatever is the right source. Could also have the domain-server send the information more often. @@ -109,6 +110,7 @@ const procPutDomains: RequestHandler = async (req: Request, resp: Response, next // This 'POST" is used as the domain heartbeat. Remember it's alive. updated.timeOfLastHeartbeat = new Date(); + updated.active = true; Logger.debug('procPutDomains. updating=' + JSON.stringify(updated)); Domains.updateEntityFields(req.vDomain, updated); } diff --git a/src/routes/api/v1/places.ts b/src/routes/api/v1/places.ts index 05bf69de..6ec8061d 100755 --- a/src/routes/api/v1/places.ts +++ b/src/routes/api/v1/places.ts @@ -52,8 +52,8 @@ const procGetPlaces: RequestHandler = async (req: Request, resp: Response, next: const places: any[] = []; for await (const place of Places.enumerateAsync(placer, pager)) { const aDomain = await Domains.getDomainWithId(place.domainId); - if (await visibilitier.criteriaTestAsync(place, aDomain)) { - if (aDomain && IsNotNullOrEmpty(aDomain.networkAddr)) { + if (aDomain && IsNotNullOrEmpty(aDomain.networkAddr)) { + if (await visibilitier.criteriaTestAsync(place, aDomain)) { places.push(await buildPlaceInfo(place, aDomain)); }; };