Events
Events are used to describe server-side generated events, most notably things that run on a timer. The server connects outwards if these events require it. This is mostly just an acknowledgement that not everything (though almost everything) is a “Request” model.
Requests
Requests cover anything that is initiated by an external agent connecting to the server and issuing commands.
The server has only one channel for receiving requests, which is an open TCP port connected to a HTTP listener, thus all requests come in as HTTP requests regardless of their origin or destination.
“Page” objects, which extend an “Interface” register URL masks with the HTTP Listener which then hands out the requests as appropriate.
The HTTPListener performs HTTP level initialisation, such as capturing the request and response codes, stashing the IP address and so on, before handing it off to the appropriate Interface that the Page extends, of which there are presently three
Interfaces
Interfaces provide the glue between the HTTP layer and the internals of each interface, specifically they are responsible for managing sessions (cookies, logging in, authentication) including extracting any necessary state data to do so (cookies for browsers, developer keys and headers for SL connections).
The interfaces extract as much information about the request/session and store it in a State object, which is then used throughout the rest of the workflow. The interfaces are specific in their workflows and paths, though there are some common core components used via Commands.
System Interface
The system interface is the endpoint used by scripts inside Second Life, it is optimised for use by LSL which has native JSON support. As such, this Interface uses and expects a TEXT/PLAIN HTTP POST content containing a JSON structure that conforms to its requirements.
The System Interface expects POST content and reads this, converting it into a JSONObject which is stored in the session state.
The developer key is extracted from the JSON and resolved (the request terminated if not found).
SecondLife specific headers are read into the State.
The shard is verified to be production.
The various owner, region and instance objects are assembled if possible.
A “runas” set of parameters is honoured which allows objects to run commands on behalf of someone else (e.g. the server object always uses this)
TODO - if the developer is a superadmin their content is always permitted, this is necessary to allow some object to create the instance in the first place (and thus the permit list). for all other developers, the developer key is checked against the “permit” list for the instance
The 'active character' for this avatar is looked up.
If the region is not recognised, the system jumps into a “pre-registration” handler that only supports console commands from the Server objects, supporting the “*listinstances” “*createinstance” and “*joininstance” commands. Complete/join must be successfully actioned to progress beyond pre-registration.
If everything checks out then the command is passed to the JSON format handler in the Commands subsystem
UserExceptions are passed back as ErrorResponse's and SystemExceptions logged and a generic error message returned.
User Interface
The user interface is the endpoint used by “free standing”, web browsers, it expects HTTP GET and text/plain POST requests, and responds with TEXT/HTML content, it allows login and provides the administration portal, most of its design is custom to the user interface, though it can make use of the Commands subsystem to get things done.
Web pages in the user interface are implemented by extending the Page class, which extends the User.Interface class, which extends the overall Interface class.
The User.Interface class directly provides little more than a fallback exception handler, and invokes renderHTML inside Page class
The page level rendering process lays out the general page structure, a title section, a left hand menu bar and a main page segment.
Authentication checks are performed at this point, and the request “intercepted” if not authorised.
If authorised, a “Form” object is created which lays out the basic HTML elements and allows the responses to be read back into the fields, “createForm()” should be overridden by the final class to create the basic layout of the page, and “processForm()” should be used to process the final form state (with data read from the POST request, if present). after processForm() is called the output is rendered into the page in the appropriate place (after which the side menu is constructed).
Authentication
Cookie authentication is a primary cross interface authentication mechanism, either using HTTP cookies, or a “?gphud=xxx” parameter in the URL (used to start HUD related operations or other places where single sign on is useful). If the cookie is specified via the URL it is copied into the Set-Cookie headers to avoid the URL exposure of the cookie.
Assuming the cookie is valid, user, avatar and character information is loaded and returned.
If this cookie does not succeed then a username+password prompt is issued, the values cryptographically hashed and checked against those in the database. If these fail, errors are returned.
If successful the user may pick an avatar if they have more than one connected, and then pick a character if said avatar has more than one, after which they are completed with authentication.
All sessions post-authentication should result in a logged in Avatar/Character at a minimum, the User portion is only present if a user authenticated directly, connections via SSO cookies may only authenticate an Avatar and not a User object.
HUD Interface
The HUD interface is the endpoint used by the “HUD's web panel”. Similar to the User Interface it expects a variety of GET/POST and responds with TEXT/HTML. The Interface is actually implemented reusing the User Interface as its base, however it omits various elements from the User Interface such as a login page, support for anything other than cookie based authentication, no side menu, etc etc and is more tightly coupled to the user's character login, often generating messages that return to the HUD via a HTTP POST originating at the server side.
The HUD interface directly extends the User Interface, overriding a few pieces of the implementation.
Notably it will not fall back to using a username/password login, it requires cookie authentication (by URL or HTTP Cookies).
It also removes the surrounding layout and only displays the page content, without header or side menu.
The default handler is a HTML call to Commands.
Commands
Somewhat agnostically there exist Commands and Responses, these are designed to be independant of the interface or request origin, and most interfaces provide some way to break down a request into a Command which is then internally handled and a Response generated, which is returned to the caller. There are various implementation specific details for each interface as discussed above.
Commands define their arguments using a rich variety of types, which are intended to allow the interface to make smart decisions - e.g. a “CHARACTER_NEARBY” type allows the HUD based interface to show a list of characters that are only near the avater in world, while CHARACTER_PLAYABLE produces a list of characters the avatar can access, and CHARACTER simply provides the ability to enter any character.