Jump to content

OpenSimulator Internals/Code Map/ROBUST/LoginService

From Open Simulator Technical Help

OpenSimulator Internals/Code Map/ROBUST/LoginService

[edit]

Overview

[edit]

LLLoginService handles viewer login requests. It is the most complex ROBUST service -- it orchestrates authentication, inventory, presence, destination selection, and agent launch across multiple other services.

Source file:

OpenSim/Services/LLLoginService/LLLoginService.cs

Constructor and Config Loading

[edit]
LLLoginService(IConfigSource config, ISimulationService simService, ILibraryService libraryService)

[LoginService] section is required -- throws if absent.

Services loaded from [LoginService]:

Key Interface Required
UserAccountService IUserAccountService Yes -- throws if empty
AuthenticationService IAuthenticationService Yes -- throws if empty
GridUserService IGridUserService No
UserAgentService IUserAgentService No
InventoryService IInventoryService No
GridService IGridService No
PresenceService IPresenceService No
AvatarService IAvatarService No
FriendsService IFriendsService No
SimulationService ISimulationService No -- remote connector
LibraryService ILibraryService No
HGInventoryServicePlugin IInventoryService No -- HG suitcase only

AuthenticationService receives (config, IUserAccountService) as constructor args -- the only service that gets a second argument.

simService and libraryService may be passed directly as arguments (used by standalone mode); if null, the service loads them from config.

Additional config read:

Section Key Default Notes
[LoginService] WelcomeMessage "Welcome to OpenSim!" Overridden by MessageUrl if fetch succeeds
[LoginService] MessageUrl (none) URL to fetch welcome message from at startup
[LoginService] RequireInventory true Fail login if inventory unavailable
[LoginService] AllowRemoteSetLoginLevel false Allow SetLevel via HTTP
[LoginService] MinLoginLevel 0 Minimum UserLevel to permit login
[LoginService] GatekeeperURI (none) Also checked in [Startup] and [Hypergrid]
[LoginService] MapTileURL (none)
[LoginService] ProfileServerURL (none)
[LoginService] OpenIDServerURL (none)
[LoginService] SearchURL (none)
[LoginService] Currency (none)
[LoginService] ClassifiedFee (none)
[LoginService] DestinationGuide (none)
[LoginService] AvatarPicker (none)
[LoginService] AllowLoginFallbackToAnyRegion true Legacy: try any online region if no default/fallback found
[LoginService] DSTZone "America/Los_Angeles;Pacific Standard Time"
[AccessControl] or [LoginService] AllowedClients (none) Regex matched against viewer string
[AccessControl] or [LoginService] DeniedClients (none) Regex matched against viewer string
[AccessControl] or [LoginService] DeniedMacs (none) Substring-matched against MAC
[AccessControl] or [LoginService] DeniedID0s (none) Substring-matched against id0
[Groups] MaxAgentGroups Constants.MaxAgentGroups Max groups per avatar
[PresenceService] AllowDuplicatePresences false If false, kick existing session on duplicate login
[Messaging] MessageKey (none) Auth key for InstantMessage service

WelcomeMessage priority: MessageUrl fetch (if configured and succeeds) overrides WelcomeMessage. If MessageUrl is configured but fetch fails, falls back to WelcomeMessage. "\n" in the message is replaced with a real newline.

SRV_ keys in [LoginService] override service URLs in AgentCircuitData and update the UserAccount record in the database if the value has changed.

Console commands registered once (static Initialized flag):

  • login level <n> -- sets MinLoginLevel
  • login reset -- resets MinLoginLevel to config value
  • login text <text> -- sets welcome message

Login()

[edit]
public LoginResponse Login(string firstName, string lastName, string passwd, string startLocation,
    UUID scopeID, string clientVersion, string channel, string mac, string id0, IPEndPoint clientIP)

The main login path. Returns a LoginResponse (success) or LLFailedLoginResponse (failure). All failures are caught by a top-level try/catch that calls PresenceService.LogoutAgent() and returns LLFailedLoginResponse.InternalError.

Sequence:

  1. Client checks:
    • If AllowedClientsRegex is set: clientVersion (or channel + " " + clientVersion) must match -- else LoginBlockedProblem
    • If DeniedClientsRegex is set: must not match -- else LoginBlockedProblem
    • If DeniedMacs is set: MAC must not appear as substring -- else LoginBlockedProblem
    • If DeniedID0s is set: id0 must not appear as substring -- else LoginBlockedProblem
  2. Account lookup: GetUserAccount(scopeID, firstName, lastName) -- UserProblem if not found
  3. Level check: account.UserLevel < MinLoginLevel -- LoginBlockedProblem
  4. God account check: account.PrincipalID == Constants.servicesGodAgentID -- UserProblem (blocked)
  5. Scope check: if scopeID provided and account.ScopeID is nonzero and doesn't match -- UserProblem
  6. Authentication:
    • Strips "$1$" prefix from passwd if present, otherwise MD5-hashes it
    • Calls AuthenticationService.Authenticate() -- UserProblem if fails
  7. Duplicate presence check (if AllowDuplicatePresences = false):
    • If GridUserInfo shows user is online with a known last region: sends god-kill IM to that region, calls LoggedOut(), returns AlreadyLoggedInProblem
  8. Inventory:
    • If RequireInventory and InventoryService is null: InventoryProblem
    • Calls HGInventoryService.GetRootFolder() if configured (creates suitcase folder)
    • Calls InventoryService.GetInventorySkeleton() -- InventoryProblem if empty and RequireInventory
  9. Presence login: PresenceService.LoginAgent(principalID, session, secureSession) -- GridProblem if fails
  10. Home region lookup via GridService.GetRegionByUUID() using guinfo.HomeRegionID
  11. Destination selection: FindDestination() -- GridProblem if returns null; also logs out presence
  12. Avatar appearance: AvatarService.GetAppearance() if configured
  13. Agent launch: LaunchAgentAtGrid() -- logs out presence and returns failure reason if null
  14. GridUserService.LoggedIn() -- called only after successful agent launch
  15. Friends list: FriendsService.GetFriends()
  16. Active gestures: InventoryService.GetActiveGestures()
  17. Builds and returns LLLoginResponse

FindDestination()

[edit]
protected GridRegion FindDestination(...)

Resolves startLocation to a GridRegion. Returns null if no region can be found. Sets out parameters: gatekeeper, where ("home"/"last"/"url"/"safe"), position, lookAt, flags.

startLocation values:

"home":

  • Uses guinfo.HomeRegionID -- returns home region if found
  • Falls back to GridService.GetDefaultRegions()[0] (where = "safe")
  • Falls back to FindAlternativeRegion() (where = "safe")
  • Returns null if nothing found

"last":

  • Uses guinfo.LastRegionID -- returns last region if found, clamps position within region bounds
  • Falls back to default regions, then FindAlternativeRegion()

URI form (uri:RegionName&x&y&z):

  • Parsed by compiled Regex: ^uri:(?<region>[^&]+)&(?<x>\d+[.]?\d*)&(?<y>\d+[.]?\d*)&(?<z>\d+[.]?\d*)$
  • If region name contains '@': direct HG login -- explicitly rejected ("no longer supported"), returns null. The original implementation is present but commented out.
  • Otherwise: GridService.GetRegionByName(), falls back to defaults, then FindAlternativeRegion()

FindAlternativeRegion():

  • Tries GetFallbackRegions() near coordinate 1000,1000
  • If AllowLoginFallbackToAnyRegion: tries GetOnlineRegions() near 1000,1000 (up to 10)
  • Returns null if nothing found

LaunchAgentAtGrid()

[edit]
protected AgentCircuitData LaunchAgentAtGrid(...)

Builds AgentCircuitData via MakeAgent() and launches the agent at the destination region.

Two paths depending on whether UserAgentService is configured:

Without UserAgentService (non-HG or standalone):

  • Uses LocalSimulationService if available, else RemoteSimulationService
  • Calls LaunchAgentDirectly(): QueryAccess() then CreateAgent()
  • On failure: tries fallback regions from GridService.GetFallbackRegions()

With UserAgentService (HG-enabled):

  • Constructs gatekeeper GridRegion from m_GatekeeperURL if not already provided
  • Calls LaunchAgentIndirectly(): UserAgentService.LoginAgentToGrid()
  • On failure: tries fallback regions

Returns AgentCircuitData on success, null on failure.

MakeAgent() populates AgentCircuitData:

  • Generates random circuit code
  • Sets appearance (or empty AvatarAppearance if none)
  • Generates random CapsPath
  • Sets child = false (login agent is always root)
  • Calls SetServiceURLs()

SetServiceURLs():

  • Copies ServiceURLs from UserAccount record
  • Overrides with SRV_-prefixed keys from [LoginService] config
  • Appends GatekeeperURI if configured
  • Calls UserAccountService.StoreUserAccount() if any URLs were updated

SetLevel()

[edit]
public Hashtable SetLevel(string firstName, string lastName, string passwd, int level, IPEndPoint clientIP)

Remote login level control. Only active if AllowRemoteSetLoginLevel = true. Requires the caller to authenticate as a user with UserLevel >= 200. Sets m_MinLoginLevel to the requested level. Returns Hashtable with success = "false" on any failure, success = true on success.


SendAgentGodKillToRegion()

[edit]

Called during duplicate presence handling. Sends a god-kick InstantMessage (dialog = 250) from Constants.servicesGodAgentID to the agent's last known region via InstantMessageServiceConnector.SendInstantMessage(). Calls GridUserService.LoggedOut() after sending. Returns false if the region cannot be found or has no ServerURI.


Notes

[edit]
  • Direct HG login via URI (region@host:port form) is explicitly disabled. The original implementation is present as a large commented-out block with the note that it no longer works due to teleport flag changes and suitcase issues.
  • The god account (Constants.servicesGodAgentID) is explicitly blocked from logging in.
  • GridUserService.LoggedIn() is called only after LaunchAgentAtGrid() succeeds -- if agent launch fails, the GridUser record is not updated.
  • PresenceService.LoginAgent() is called before destination is confirmed. If FindDestination() or LaunchAgentAtGrid() fails, LogoutAgent() is called to clean up.
  • AllowedClients and DeniedClients regex compilation failures are caught and logged; the regex is set to null, meaning the check is skipped rather than blocking all logins.

See Also

[edit]