OpenSimulator Internals/Connector Architecture/Simulation Connector
OpenSimulator Internals/Connector Architecture/Simulation Connector
[edit]Overview
[edit]SimulationServiceConnector is the remote connector for ISimulationService. It handles inter-simulator communication: creating and updating agents during teleport and region crossing, and transferring objects between regions. Unlike the other connectors, it talks directly to region simulators, not to ROBUST.
Source file:
OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs
Initialisation
[edit]No config file reading. No service URI -- the destination URI comes from GridRegion.ServerURI on each call.
Two constructors:
- Default (no args)
- IConfigSource -- no-op, config argument unused
GetScene() and GetInnerService() always return null.
Transport
[edit]Unlike all other connectors, SimulationServiceConnector does not use SynchronousRestFormsRequester. It uses WebUtil methods with OSDMap (LLSD) payloads:
- WebUtil.PostToServiceCompressed() -- compressed POST, used for CreateAgent first attempt
- WebUtil.PostToService() -- uncompressed POST, used as fallback
- WebUtil.PutToServiceCompressed() / PutToService() -- PUT, used for UpdateAgent
- WebUtil.ServiceOSDRequest() -- used for QueryAccess (QUERYACCESS method), ReleaseAgent and CloseAgent (DELETE)
URL pattern: destination.ServerURI + "agent/" + agentID + "/"
AgentPath() and ObjectPath() are virtual -- subclasses can override the path segments.
Agent Methods
[edit]CreateAgent()
[edit]public bool CreateAgent(GridRegion source, GridRegion destination, AgentCircuitData aCircuit, uint flags, EntityTransferContext ctx, out string reason)
- Packs AgentCircuitData via aCircuit.PackAgentCircuitData(ctx)
- Adds context, source region info, destination region info, and teleport flags via PackData()
- Attempts compressed POST first (WebUtil.PostToServiceCompressed)
- On success: reads _Result map for actual success/reason
- On failure: falls back to uncompressed POST (WebUtil.PostToService) with warning that destination should be updated
- Returns false with reason on all failure paths
UpdateAgent(destination, AgentData, ctx)
[edit]Full agent data update (region crossing). Timeout 200 seconds.
UpdateAgent(destination, AgentPosition)
[edit]Position-only update. Called frequently during avatar movement.
Deduplication via m_updateAgentQueue dictionary keyed by URI:
- First thread for a URI becomes the worker; subsequent threads update the map and return
- Worker loops, sending the most recent position until no new update arrives
- On send failure: blacklists the destination URI for 120 seconds via _failedSims ExpiringCache
- Blacklisted destinations return false immediately without attempting contact
Private UpdateAgent(destination, IAgentData, ctx, timeout) handles the actual PUT:
- Uses PutToServiceCompressed
- If OutboundVersion >= 0.3: returns immediately on success
- If OutboundVersion < 0.2: falls back to uncompressed PutToService on failure
QueryAccess()
[edit]public bool QueryAccess(GridRegion destination, UUID agentID, string agentHomeURI, bool viaTeleport, Vector3 position, List<UUID> featuresAvailable, EntityTransferContext ctx, out string reason)
URL: destination.ServerURI + "agent/" + agentID + "/" + destination.RegionID + "/"
Sends simulation service version negotiation fields:
- simulation_service_supported_min/max
- simulation_service_accepted_min/max
- my_version (legacy field, set to minimum for safety)
- features (List of UUID capabilities)
- context
Response handling:
- Reads _Result map for success, reason, negotiated_inbound_version, negotiated_outbound_version
- Falls back to legacy "version" field (SIMULATION/N.N format) if negotiated fields absent
- Sets ctx.InboundVersion and ctx.OutboundVersion from response
- If MethodNotAllowed error received: logs it and returns true (legacy simulator compatibility)
- Sets ctx.WearablesCount based on OutboundVersion:
- < 0.5: LEGACY_VERSION_MAX_WEARABLES
- < 0.6: LEGACY_VERSION_MAX_WEARABLES + 1
- >= 0.6: -1 (send all)
- Clears featuresAvailable and repopulates from response
Comment in source notes the _Result success/failure is the authoritative one, not the sibling result node -- legacy issue from 0.7.3.1 era labelled "nte4.8 crap".
ReleaseAgent()
[edit]Sends DELETE to a provided URI (not constructed from destination). Always returns true regardless of result.
CloseAgent()
[edit]URL: destination.ServerURI + "agent/" + id + "/" + destination.RegionID + "/?auth=" + auth_code
Sends DELETE. Always returns true regardless of result.
Object Methods
[edit]CreateObject(destination, newPosition, sog, isLocalCall)
[edit]URL: destination.ServerURI + "object/" + sog.UUID + "/"
Packs scene object as XML2 via sog.ToXml2(), extra state via ExtraToXmlString() and GetStateSnapshot(). Sends uncompressed POST. Returns false if result is null or success is false.
CreateObject(destination, userID, itemID)
[edit]Not implemented. Always returns false with a TODO comment.
Notes
[edit]- This connector talks to region simulators, not ROBUST. The destination URI comes from GridRegion.ServerURI per call.
- The compressed/uncompressed fallback in CreateAgent() exists for backward compatibility with older simulators. A warning is logged when the fallback is needed.
- UpdateAgent position deduplication means only the most recent position is ever sent -- intermediate positions are silently dropped. This is intentional.
- The 200-second timeout on full AgentData UpdateAgent is notably long -- comment "yes, 200 seconds" is in the source.
- ReleaseAgent and CloseAgent always return true -- callers cannot detect failure from return value.
- CreateObject by userID+itemID is explicitly unimplemented with a "TODO, not that urgent" comment.