From 65e3aef3f9ecb243129846216b213c4ca4ca8af8 Mon Sep 17 00:00:00 2001 From: Casper Warden <216465704+casperwardensl@users.noreply.github.com> Date: Sat, 3 Nov 2018 14:39:20 +0000 Subject: [PATCH] - Fix buffers out of order issue with Transfer system - Remove debug - Add cap invocation rate limiter (need to work out which caps require this) - Fix initial login timing out after just one second --- lib/Bot.ts | 2 +- lib/classes/Caps.ts | 30 +++++++++++++++++++++++++- lib/classes/commands/AssetCommands.ts | 6 ++++-- lib/classes/commands/RegionCommands.ts | 7 +++++- 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/lib/Bot.ts b/lib/Bot.ts index ca210d3..b0b3e05 100644 --- a/lib/Bot.ts +++ b/lib/Bot.ts @@ -215,7 +215,7 @@ export class Bot Code: circuit.circuitCode }; - await circuit.waitForAck(circuit.sendMessage(msg, PacketFlags.Reliable), 1000); + await circuit.waitForAck(circuit.sendMessage(msg, PacketFlags.Reliable), 10000); const agentMovement: CompleteAgentMovementMessage = new CompleteAgentMovementMessage(); diff --git a/lib/classes/Caps.ts b/lib/classes/Caps.ts index e56f947..394eac3 100644 --- a/lib/classes/Caps.ts +++ b/lib/classes/Caps.ts @@ -11,6 +11,8 @@ import {HTTPAssets} from '..'; export class Caps { + static CAP_INVOCATION_INTERVAL_MS = 250; + private region: Region; private onGotSeedCap: Subject = new Subject(); private gotSeedCap = false; @@ -18,6 +20,7 @@ export class Caps private clientEvents: ClientEvents; private agent: Agent; private active = false; + private capRateLimitTimers: {[key: string]: number} = {}; eventQueueClient: EventQueueClient | null = null; constructor(agent: Agent, region: Region, seedURL: string, clientEvents: ClientEvents) @@ -300,14 +303,39 @@ export class Caps }); } + private waitForCapTimeout(cap: string): Promise + { + return new Promise((resolve, reject) => + { + const timeToWait = (this.capRateLimitTimers[cap] + Caps.CAP_INVOCATION_INTERVAL_MS) - (new Date().getTime()); + if (timeToWait > 0) + { + setTimeout(() => + { + resolve(); + }, timeToWait); + } + else + { + resolve(); + } + }); + } + capsRequestXML(capability: string, data: any, debug = false): Promise { if (debug) { console.log(data); } - return new Promise((resolve, reject) => + return new Promise(async (resolve, reject) => { + const t = new Date().getTime(); + if (this.capRateLimitTimers[capability] && (this.capRateLimitTimers[capability] + Caps.CAP_INVOCATION_INTERVAL_MS) > t) + { + await this.waitForCapTimeout(capability); + } + this.capRateLimitTimers[capability] = t; this.getCapability(capability).then((url) => { const xml = LLSD.LLSD.formatXML(data); diff --git a/lib/classes/commands/AssetCommands.ts b/lib/classes/commands/AssetCommands.ts index 2338e10..e654147 100644 --- a/lib/classes/commands/AssetCommands.ts +++ b/lib/classes/commands/AssetCommands.ts @@ -136,7 +136,6 @@ export class AssetCommands extends CommandsBase } case Message.TransferAbort: { - console.log('GOT TRANSFERABORT'); const messg = packet.message as TransferAbortMessage; if (!messg.TransferInfo.TransferID.equals(transferID)) { @@ -155,7 +154,10 @@ export class AssetCommands extends CommandsBase } if (gotSize >= expectedSize) { - const packetNumbers = Object.keys(packets).sort(); + const packetNumbers = Object.keys(packets).sort((a: string, b: string): number => + { + return parseInt(a, 10) - parseInt(b, 10); + }); const buffers = []; for (const pn of packetNumbers) { diff --git a/lib/classes/commands/RegionCommands.ts b/lib/classes/commands/RegionCommands.ts index 47a7ef4..40ef90d 100644 --- a/lib/classes/commands/RegionCommands.ts +++ b/lib/classes/commands/RegionCommands.ts @@ -399,7 +399,7 @@ export class RegionCommands extends CommandsBase if (objs[ky] !== undefined) { const o = objs[ky]; - if (o.FullID !== undefined && o.name !== undefined && o.Flags !== undefined && !(o.Flags & PrimFlags.InventoryEmpty) && (!o.inventory || o.inventory.length === 0)) + if ((o.resolveAttempts === undefined || o.resolveAttempts < 3) && o.FullID !== undefined && o.name !== undefined && o.Flags !== undefined && !(o.Flags & PrimFlags.InventoryEmpty) && (!o.inventory || o.inventory.length === 0)) { console.log(' ... Downloading task inventory for object ' + o.FullID.toString() + ' (' + o.name + '), done ' + count + ' of ' + objectSet.length); const req = new RequestTaskInventoryMessage(); @@ -670,6 +670,11 @@ export class RegionCommands extends CommandsBase } catch (error) { + if (o.resolveAttempts === undefined) + { + o.resolveAttempts = 0; + } + o.resolveAttempts++; if (o.FullID !== undefined) { console.error('Error downloading task inventory of ' + o.FullID.toString() + ':');