<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://osimdev.org/wiki/index.php?action=history&amp;feed=atom&amp;title=OpenSimulator_Internals%2FCode_Map%2FROBUST%2FGatekeeperService</id>
	<title>OpenSimulator Internals/Code Map/ROBUST/GatekeeperService - Revision history</title>
	<link rel="self" type="application/atom+xml" href="http://osimdev.org/wiki/index.php?action=history&amp;feed=atom&amp;title=OpenSimulator_Internals%2FCode_Map%2FROBUST%2FGatekeeperService"/>
	<link rel="alternate" type="text/html" href="http://osimdev.org/wiki/index.php?title=OpenSimulator_Internals/Code_Map/ROBUST/GatekeeperService&amp;action=history"/>
	<updated>2026-08-04T15:31:45Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>http://osimdev.org/wiki/index.php?title=OpenSimulator_Internals/Code_Map/ROBUST/GatekeeperService&amp;diff=66&amp;oldid=prev</id>
		<title>Jwbshaw: first</title>
		<link rel="alternate" type="text/html" href="http://osimdev.org/wiki/index.php?title=OpenSimulator_Internals/Code_Map/ROBUST/GatekeeperService&amp;diff=66&amp;oldid=prev"/>
		<updated>2026-07-07T12:06:09Z</updated>

		<summary type="html">&lt;p&gt;first&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;= OpenSimulator Internals/Code Map/ROBUST/GatekeeperService =&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
GatekeeperService is the HyperGrid entry point for a grid. It handles inbound teleport requests from foreign grids and local-grid login requests that go through the HG path. It authenticates the visiting agent, checks access policy, and launches the agent at the destination region.&lt;br /&gt;
&lt;br /&gt;
Source file:&lt;br /&gt;
&lt;br /&gt;
 OpenSim/Services/HypergridService/GatekeeperService.cs&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Constructor and Config Loading ===&lt;br /&gt;
&lt;br /&gt;
 GatekeeperService(IConfigSource config, ISimulationService simService)&lt;br /&gt;
&lt;br /&gt;
[GatekeeperService] section is required -- throws if absent.&lt;br /&gt;
&lt;br /&gt;
All static fields are initialized once (m_Initialized flag). Subsequent instantiations are no-ops.&lt;br /&gt;
&lt;br /&gt;
Services loaded from [GatekeeperService]:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Key !! Interface !! Required&lt;br /&gt;
|-&lt;br /&gt;
| GridService || IGridService || Yes -- throws if empty&lt;br /&gt;
|-&lt;br /&gt;
| PresenceService || IPresenceService || Yes -- throws if empty&lt;br /&gt;
|-&lt;br /&gt;
| SimulationService || ISimulationService || Yes -- throws if null after loading&lt;br /&gt;
|-&lt;br /&gt;
| UserAccountService || IUserAccountService || No&lt;br /&gt;
|-&lt;br /&gt;
| UserAgentService || IUserAgentService || No&lt;br /&gt;
|-&lt;br /&gt;
| GridUserService || IGridUserService || No&lt;br /&gt;
|-&lt;br /&gt;
| BansService || IBansService || No&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
simService argument takes precedence over SimulationService config key if non-null.&lt;br /&gt;
&lt;br /&gt;
Additional config:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Section !! Key !! Default !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| [GatekeeperService] || ScopeID || UUID.Zero || Grid scope filter&lt;br /&gt;
|-&lt;br /&gt;
| [GatekeeperService] || AllowTeleportsToAnyRegion || true || If false, all inbound TPs go to the default HG region&lt;br /&gt;
|-&lt;br /&gt;
| [Const]/[Startup]/[Hypergrid]/[GatekeeperService] || GatekeeperURI || (none) || External URL of this gatekeeper; also tries ExternalName&lt;br /&gt;
|-&lt;br /&gt;
| [Const]/[Startup]/[Hypergrid]/[GatekeeperService] || GatekeeperURIAlias || (none) || Comma-separated list of alternate hostnames accepted as this grid&lt;br /&gt;
|-&lt;br /&gt;
| [GatekeeperService] || ForeignAgentsAllowed || true || Whether visitors from other grids are permitted&lt;br /&gt;
|-&lt;br /&gt;
| [GatekeeperService] || AllowExcept || (none) || Comma-separated HomeURIs excluded from ForeignAgentsAllowed=true&lt;br /&gt;
|-&lt;br /&gt;
| [GatekeeperService] || DisallowExcept || (none) || Comma-separated HomeURIs excluded from ForeignAgentsAllowed=false&lt;br /&gt;
|-&lt;br /&gt;
| [AccessControl]/[GatekeeperService] || AllowedClients || (none) || Regex matched against viewer string&lt;br /&gt;
|-&lt;br /&gt;
| [AccessControl]/[GatekeeperService] || DeniedClients || (none) || Regex matched against viewer string&lt;br /&gt;
|-&lt;br /&gt;
| [AccessControl]/[GatekeeperService] || DeniedMacs || (none) || Case-insensitive substring match against MAC&lt;br /&gt;
|-&lt;br /&gt;
| [AccessControl]/[GatekeeperService] || DeniedID0s || (none) || Case-insensitive substring match against id0&lt;br /&gt;
|-&lt;br /&gt;
| [PresenceService] || AllowDuplicatePresences || false || If false, kick existing session on duplicate login&lt;br /&gt;
|-&lt;br /&gt;
| [Messaging] || MessageKey || (none) || Auth key for InstantMessage service&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
GatekeeperURI is resolved at startup via OSHHTPHost. Throws if the hostname cannot be resolved or is invalid.&lt;br /&gt;
&lt;br /&gt;
GatekeeperURIAlias entries are parsed but not resolved (IsValidHost only, not IsResolvedHost) -- allows aliases that may not be locally resolvable.&lt;br /&gt;
&lt;br /&gt;
AllowedClients and DeniedClients regex compilation failures are caught and logged; the regex is set to null (check skipped).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== LinkLocalRegion() ===&lt;br /&gt;
&lt;br /&gt;
 public bool LinkLocalRegion(string regionName, out UUID regionID, out ulong regionHandle,&lt;br /&gt;
     out string externalName, out string imageURL, out string reason, out int sizeX, out int sizeY)&lt;br /&gt;
&lt;br /&gt;
Called by a foreign grid that wants to link to a region on this grid.&lt;br /&gt;
&lt;br /&gt;
If AllowTeleportsToAnyRegion = false or regionName is empty:&lt;br /&gt;
* Returns the first result from GridService.GetDefaultHypergridRegions()&lt;br /&gt;
* Caches it as m_DefaultGatewayRegion&lt;br /&gt;
* Returns false with an error reason if no default HG regions exist&lt;br /&gt;
&lt;br /&gt;
Otherwise:&lt;br /&gt;
* Calls GridService.GetLocalRegionByName() -- returns false if not found&lt;br /&gt;
&lt;br /&gt;
On success: populates regionID, regionHandle, sizeX, sizeY, externalName (gatekeeperURL + region name), imageURL (region ServerURI + index.php?method=regionImage{uuid}).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== GetHyperlinkRegion() ===&lt;br /&gt;
&lt;br /&gt;
 public GridRegion GetHyperlinkRegion(UUID regionID, UUID agentID, string agentHomeURI, out string message)&lt;br /&gt;
&lt;br /&gt;
Returns the GridRegion descriptor for a given regionID. Called by foreign grids after LinkLocalRegion to get the full region record.&lt;br /&gt;
&lt;br /&gt;
If AllowTeleportsToAnyRegion = false: returns m_DefaultGatewayRegion regardless of regionID.&lt;br /&gt;
&lt;br /&gt;
Otherwise: calls GridService.GetRegionByUUID(). Returns null with message if not found.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== LoginAgent() ===&lt;br /&gt;
&lt;br /&gt;
 public bool LoginAgent(GridRegion source, AgentCircuitData aCircuit, GridRegion destination, out string reason)&lt;br /&gt;
&lt;br /&gt;
Main inbound HG agent entry point. Returns false with a reason string on any failure.&lt;br /&gt;
&lt;br /&gt;
Sequence:&lt;br /&gt;
&lt;br /&gt;
# Client checks (same pattern as LLLoginService):&lt;br /&gt;
#* AllowedClientsRegex -- viewer string must match if set&lt;br /&gt;
#* DeniedClientsRegex -- viewer string must not match if set&lt;br /&gt;
#* DeniedMacs -- MAC must not appear as case-insensitive substring&lt;br /&gt;
#* DeniedID0s -- id0 must not appear as case-insensitive substring&lt;br /&gt;
# Authentication via Authenticate():&lt;br /&gt;
#* Verifies ServiceSessionID was issued for this grid (CheckAddress)&lt;br /&gt;
#* Verifies agent IP address is present&lt;br /&gt;
#* Calls UserAgentService.VerifyAgent() -- uses local service if HomeURI matches this grid, else instantiates a remote UserAgentServiceConnector&lt;br /&gt;
#* Returns false (&amp;quot;Unable to verify identity&amp;quot;) on failure&lt;br /&gt;
# Impersonation check (if UserAccountService configured):&lt;br /&gt;
#* Looks up aCircuit.AgentID in local UserAccounts&lt;br /&gt;
#* If found AND UserAgentService configured: calls IsAgentComingHome() -- if false, agent UUID collides with a local account but is not actually that user; refuses with &amp;quot;Unauthorized&amp;quot;&lt;br /&gt;
# Foreign agent policy (if account is null, i.e. visitor):&lt;br /&gt;
#* Starts with m_ForeignAgentsAllowed&lt;br /&gt;
#* If allowed AND HomeURI is in AllowExcept list: set allowed = false&lt;br /&gt;
#* If not allowed AND HomeURI is in DisallowExcept list: set allowed = true&lt;br /&gt;
#* Returns false (&amp;quot;Destination does not allow visitors from your world&amp;quot;) if not allowed&lt;br /&gt;
# Ban check via BansService.IsBanned(uui, IPAddress, Id0, authURL) if configured&lt;br /&gt;
# God account check: aCircuit.AgentID == Constants.servicesGodAgentID -- refuses with &amp;quot;Invalid account ID&amp;quot;&lt;br /&gt;
# Duplicate presence check (if GridUserService configured and AllowDuplicatePresences = false):&lt;br /&gt;
#* Gets GridUserInfo for the UUI&lt;br /&gt;
#* If online with known last region: calls SendAgentGodKillToRegion(), returns false&lt;br /&gt;
# Presence handling:&lt;br /&gt;
#* Calls PresenceService.GetAgent(sessionID)&lt;br /&gt;
#* If found: isFirstLogin = true (presence was placed by LLLoginService -- this is a local user logging into HG)&lt;br /&gt;
#* If not found: calls PresenceService.LoginAgent() -- fails if this also fails&lt;br /&gt;
# Destination verification: GridService.GetRegionByUUID() -- returns false if not found&lt;br /&gt;
# Name adjustment:&lt;br /&gt;
#* Local user: name taken from UserAccount record&lt;br /&gt;
#* Foreign user without &amp;quot;@&amp;quot; suffix: firstname becomes &amp;quot;firstname.lastname&amp;quot;, lastname becomes &amp;quot;@authority-of-HomeURI&amp;quot;&lt;br /&gt;
# Agent launch:&lt;br /&gt;
#* SimulationService.QueryAccess() -- returns false on rejection&lt;br /&gt;
#* SimulationService.CreateAgent() with ViaLogin (first login) or ViaHGLogin (HG transfer) flag, OR&amp;#039;d with existing teleport flags&lt;br /&gt;
#* On success: if not first login and GridUserService configured and account is null (foreign visitor), calls GridUserService.LoggedIn() with a composite UUI string: agentID + &amp;quot;;&amp;quot; + HomeURI + &amp;quot;;&amp;quot; + firstname + &amp;quot; &amp;quot; + lastname&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Authenticate() ===&lt;br /&gt;
&lt;br /&gt;
 protected bool Authenticate(AgentCircuitData aCircuit)&lt;br /&gt;
&lt;br /&gt;
Two-step check:&lt;br /&gt;
&lt;br /&gt;
CheckAddress(ServiceSessionID):&lt;br /&gt;
* Splits ServiceSessionID on &amp;quot;;&amp;quot;&lt;br /&gt;
* Parses first part as a grid URL&lt;br /&gt;
* Checks it against m_gatekeeperHost and m_gateKeeperAlias&lt;br /&gt;
* Returns false if it doesn&amp;#039;t match -- this grid did not issue the token&lt;br /&gt;
&lt;br /&gt;
VerifyAgent:&lt;br /&gt;
* If HomeURI resolves to this grid: uses local m_UserAgentService.VerifyAgent()&lt;br /&gt;
* Otherwise: instantiates a UserAgentServiceConnector for the foreign HomeURI and calls VerifyAgent() remotely&lt;br /&gt;
* Connection failures are caught and return false&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== SendAgentGodKillToRegion() ===&lt;br /&gt;
&lt;br /&gt;
Same pattern as LLLoginService. Sends a god-kick InstantMessage (dialog = 250) from Constants.servicesGodAgentID to the agent&amp;#039;s last known region. Calls GridUserService.LoggedOut() after sending. Returns false if the region cannot be found or has no ServerURI.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
=== Notes ===&lt;br /&gt;
&lt;br /&gt;
* All service references are static -- shared across all instances. The m_Initialized flag means only the first construction does any work.&lt;br /&gt;
* Foreign visitors get a composite UUI (agentID;HomeURI;name) logged to GridUser, not just a plain UUID.&lt;br /&gt;
* Direct HG login via URI with &amp;quot;@&amp;quot; in region name is not handled here -- that path was removed from LLLoginService and is not present in GatekeeperService.&lt;br /&gt;
* The AllowExcept/DisallowExcept lists provide per-grid overrides of the ForeignAgentsAllowed policy. Matching is exact string comparison on the HomeURI (trailing slash normalized).&lt;br /&gt;
* isFirstLogin logic is inverted from the variable name: the variable is set to true when the presence already exists (placed by the login service), meaning this is a local-grid user going HG outbound for the first time, not a returning foreign visitor.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[OpenSimulator Internals/Code Map/ROBUST]]&lt;br /&gt;
* [[OpenSimulator Internals/Code Map/ROBUST/LoginService]]&lt;br /&gt;
* [[OpenSimulator Internals/Code Map/ROBUST/PresenceService]]&lt;br /&gt;
* [[OpenSimulator Internals/Connector Architecture]]&lt;/div&gt;</summary>
		<author><name>Jwbshaw</name></author>
	</entry>
</feed>