diff --git a/hippolyzer/lib/client/inventory_manager.py b/hippolyzer/lib/client/inventory_manager.py index 6430180..8ecf1fb 100644 --- a/hippolyzer/lib/client/inventory_manager.py +++ b/hippolyzer/lib/client/inventory_manager.py @@ -16,6 +16,23 @@ class InventoryManager: def __init__(self, session: BaseClientSession): self._session = session self.model: InventoryModel = InventoryModel() + self._load_skeleton() + + def _load_skeleton(self): + assert not self.model.nodes + skel_cats: List[dict] = self._session.login_data.get('inventory-skeleton', []) + for skel_cat in skel_cats: + self.model.add(InventoryCategory( + name=skel_cat["name"], + cat_id=UUID(skel_cat["folder_id"]), + parent_id=UUID(skel_cat["parent_id"]), + # Don't use the version from the skeleton, this flags the inventory as needing + # completion from the inventory cache. This matches indra's behavior. + version=InventoryCategory.VERSION_NONE, + type="category", + pref_type="-1", + owner_id=self._session.agent_id, + )) def load_cache(self, path: Union[str, Path]): # Per indra, rough flow for loading inv on login is: @@ -34,7 +51,9 @@ class InventoryManager: skel_cats: List[dict] = self._session.login_data['inventory-skeleton'] # UUID -> version map for inventory skeleton skel_versions = {UUID(cat["folder_id"]): cat["version"] for cat in skel_cats} + LOG.info(f"Parsing inv cache at {path}") cached_categories, cached_items = self._parse_cache(path) + LOG.info(f"Done parsing inv cache at {path}") loaded_cat_ids: Set[UUID] = set() for cached_cat in cached_categories: @@ -71,6 +90,7 @@ class InventoryManager: with gzip.open(path, "rb") as f: # Line-delimited LLSD notation! for line in f.readlines(): + # TODO: Parsing of invcache is dominated by `parse_notation()`. It's stupidly inefficient. node_llsd = llsd.parse_notation(line) if first_line: # First line is the file header diff --git a/hippolyzer/lib/proxy/inventory_manager.py b/hippolyzer/lib/proxy/inventory_manager.py new file mode 100644 index 0000000..4a7f20c --- /dev/null +++ b/hippolyzer/lib/proxy/inventory_manager.py @@ -0,0 +1,12 @@ +from hippolyzer.lib.client.inventory_manager import InventoryManager +from hippolyzer.lib.client.state import BaseClientSession +from hippolyzer.lib.proxy.viewer_settings import iter_viewer_cache_dirs + + +class ProxyInventoryManager(InventoryManager): + def __init__(self, session: BaseClientSession): + super().__init__(session) + for cache_dir in iter_viewer_cache_dirs(): + inv_cache_path = cache_dir / (str(session.agent_id) + ".inv.llsd.gz") + if inv_cache_path.exists(): + self.load_cache(inv_cache_path) diff --git a/hippolyzer/lib/proxy/sessions.py b/hippolyzer/lib/proxy/sessions.py index 43db9b0..168f105 100644 --- a/hippolyzer/lib/proxy/sessions.py +++ b/hippolyzer/lib/proxy/sessions.py @@ -10,6 +10,7 @@ from typing import * from weakref import ref from hippolyzer.lib.base.datatypes import UUID +from hippolyzer.lib.base.helpers import proxify from hippolyzer.lib.base.message.message import Message from hippolyzer.lib.base.message.message_handler import MessageHandler from hippolyzer.lib.client.state import BaseClientSession @@ -18,6 +19,7 @@ from hippolyzer.lib.proxy.circuit import ProxiedCircuit from hippolyzer.lib.proxy.http_asset_repo import HTTPAssetRepo from hippolyzer.lib.proxy.http_proxy import HTTPFlowContext from hippolyzer.lib.proxy.caps import is_asset_server_cap_name, CapData, CapType +from hippolyzer.lib.proxy.inventory_manager import ProxyInventoryManager from hippolyzer.lib.proxy.namecache import ProxyNameCache from hippolyzer.lib.proxy.object_manager import ProxyWorldObjectManager from hippolyzer.lib.proxy.region import ProxiedRegion @@ -47,6 +49,7 @@ class Session(BaseClientSession): self.message_handler: MessageHandler[Message, str] = MessageHandler() self.http_message_handler: MessageHandler[HippoHTTPFlow, str] = MessageHandler() self.objects = ProxyWorldObjectManager(self, session_manager.settings, session_manager.name_cache) + self.inventory = ProxyInventoryManager(proxify(self)) # Base path of a newview type cache directory for this session self.cache_dir: Optional[str] = None self._main_region = None