Difference between revisions of "Plugin architecture"

From Second Life Wiki
Jump to navigation Jump to search
 
(52 intermediate revisions by 6 users not shown)
Line 1: Line 1:
'''Survey Of Client Plugins As Potential Models'''
As of this writing (February 12, 2007), there's not an official plugin architecture in the Second Life viewer.  However, there's been a lot of interest in developing one.  This page (and the pages it links to) are an attempt to capture a lot of the informal discussion that has occurred so far.


* Old Netscape Plugin


Wiki Link [http://en.wikipedia.org/wiki/NPAPI]
These are the three main issues to be addressed:


* New Mozilla Extensions
== Code loading ==
XUL Framework, challenging to build.
Dynamic loading of natively-compiled executable code can be accomplished with dlopen / dlsym in Linux and MacOSX and LoadLibrary on Win32.
Wiki Link [http://en.wikipedia.org/wiki/Extension_%28Mozilla%29]


* Browser Helper Object in IE
[[dlopen code example]]
Wiki Link [http://en.wikipedia.org/wiki/Browser_Helper_Object]


* Eclipse Plug In Model


Java callbacks and contracts.  [http://www.eclipse.org/articles/Article-Plug-in-architecture/plugin_architecture.html#2]
There are wrappers to allow this to be more cross platform:


== Required Changes ==
* Apache APR - Already in use in llimage/llimagej2c.cpp.  Not GPL compatible, but is compatible with the GPL+FLOSS exception license used in the Second Life viewer
Some changes in the code will be required to support plugins.
* libtltdl
* Glib GModules


* Complete GUI and other classes with functions that would be expected to exist, but don't because nothing needed them yet. For instance, add method overloads that should logically exist.
== Making the client into dynamic libs itself ==
* Allow multiple callbacks per message, as well as unregistering a previously registered one. Currently only one callback can be registered per message type.
* Verify that all the callbacks work in such a way that they wouldn't be confused by plugins. When a callback for a reply to a request runs it must make sure that the data to arrived is what was requested, and if not, ignore it.
* Add internal callbacks for events such as rendering a frame, receiving a chat message, etc.


[[Category:Feature Requests]]
Most interesting functions in the viewer could be broken out into dylibs / dlls so that plugins could link against them.  Code that we want to be able to call from a plugin needs to be in a DLL, and they can all be in the same DLL.  Code that is so rarely used we'd like to not load it unless we have to should go into a separate DLL.


== Calls from viewer to plugin (hooks) ==


In order to override or enhance existing functionality in the viewer, we need to be able to replace some code with our own.  One way to do this would be to install "hooks" into commonly-used functions.  In the example implementation code below, you can hook any function by adding 'PLUGIN_HOOK("function_name", data1, data2)' to the top of the function.


'''Plugin <--> LSL Communication Channels'''
When that macro is called, it looks to see if any hooks have been registered with a name that matches "function_name".  If so, it executes each one in turn.


Many compelling applications would benefit from a pipe between the plugin process and server side LSL scripts.    Anything which wants to communicate status or information which can only be gathered reliably via LSL rather than typical protocol messages the client receives would benefit from such a pipe. 
Each hook function can affect program execution in one of three ways:


A brief discussion on the alternatives for communication follows:
* Pass event through -- a function might decide to ignore this hook based on the contents of data1 and data2, or it might do something which doesn't disrupt the program flow (such as adding data to an internal list for later use, or displaying a dialog box).  In this case, it should just return TRUE.
* Modify params, pass event through -- as above, except the hook function can modify the contents of data1 and/or data2 before returning TRUE
* Swallow event: Sometimes, we want to completely override the function being hooked, for various reasons -- in this case, the plugin should return FALSE.


* Ideally, this pipe could be written differently from the current chat channels afforded by llSay or Instant Message, to avoid performance and size limitations.   However, an early implementation using available technologies would be preferable to one which may take significantly longer.
PLUGIN_HOOK executes each function in turn; if it function returns FALSE, it just issues a 'return' in the context of the hooked function. If all hooks return TRUE, control will eventually be passed to the hooked function.


* A chat channel implementation would require the ability for an avatar to have his client register a listener with the servers on channels other than channel 0.  The client would not display messages on channels other than 0, but would send them to any plugins which have been registered to listen on those channels.   
[[hook example code]]


* Another implementation, using instant messages, would be useful for the added privacy, however time lag between messages are significant and it would be desirable not to have these messages show up on the client itself so a flag would need to be added for plugin-only instant messages.
[[hooking sending IMs]]


* Other ideas, such as HTTP requests or Emails, for external plugin communication should be discarded quickly for the very reason that most systems now have significant firewalls and NAT'd connections which will deny such communication channels immediately.
== Calls from plugin to viewer (exposing an API) ==


Most plugins will want to call into the client and have it do things like display dialog boxes, send IMs, etc.  Unfortunately, there's no simple way to do this.


'''Security Model'''
One solution is to pick a number of useful functions, build a function pointer table, and allow plugins to ask for them by name.


An oft heard complaint about the Internet is the lack of security.  The ease with which hackers can install Trojan horses and develop sophisticated bot nets to do their willing is becoming a modern nightmare in technology today.
[[function pointer example code]]


One approach to fixing this problem, or at least, reverse it in its tracks is "Trusted Computing" ([http://en.wikipedia.org/wiki/Trusted_computing]).  While Second Life isn't pure Trusted Computing because you are installing software on your PC, it is a weak form in that scripts are executed on a central server rather than the local client.  This differentiates SL in very compelling ways for those who wish to surf safely.
== Required Changes ==
Some changes in the code will be required to support plugins.  


Some parts of SL do break this model, however they can be switched off with little degradation to your experience.   Buffer flow overruns occur in the code, but one would hope they could be stamped out over time more easily than arbitrary execution of code that can occur in modern Web Browsers, Operating Systems, and unfortunately, plugins in the Second Life client.
* Complete GUI and other classes with functions that would be expected to exist, but don't because nothing needed them yet. For instance, add method overloads that should logically exist.
* Allow multiple callbacks per message, as well as unregistering a previously registered one. Currently only one callback can be registered per message type.
* Verify that all the callbacks work in such a way that they wouldn't be confused by plugins. When a callback for a reply to a request runs it must make sure that the data to arrived is what was requested, and if not, ignore it.
* Add internal callbacks for events such as rendering a frame, receiving a chat message, etc.


However, all is not lost.  Plugins do not have to be the end of security in Second Life.  There are many approaches to solving this problem, but three main ones come to mind:  code signing, open source code, applet sandboxing.  Note that the first two assume simply linking against the current open sourced code base (IE: using the ll* apis), while the third would likely require a new language and API.  Code signing is my (Iron Perth) preferred method, so feel free to edit this and correct my bias.
=Other Information=
== Capabilities and Plugin Examples ==


* Code Signing.  Code Signing via SSL certificates or even Extended Validation SSL Certificates ([http://en.wikipedia.org/wiki/Extended_Validation_(High_Assurance)_SSL_Certificates]) would require a third party to issue a certificate which would indicate that the plug in has been verified as trusted.  This could go through several layers of verification, up to and including a code audit. 


However, given the micropayment and hyper innovation cycle that SL has successfully followed, a certificate which simply identifies the originator of the code (real life name, contact info, etc) would probably be most appropriate.  
The following is a discussion of what we'd like to be able to do with a plugin.  Note it is not a discussion of how plugins will be managed.


* Affecting rendering pipeline (eg, improving rendering of clouds)
* Transforming messages (eg:  adding encryption to IM messages)
* Improving the User Interface (eg: better building tools)
* Automated Agents, potentially headless (no GUI).
* Extend client to support new 3D object types and their behaviors (eg: rendering of objects with complex, non-primitive shapes or complex behaviors)
* Extend client to be a platform for other applications (eg: PDF viewer with scrollbars on the face of a prim)


* Open Source.  This approach would require all code to be clear text so that any exploits could be found by examining the code base.  It's unclear to me that this would work as the number of plugins became overwhelming in nature as people would simply stop examining the code of every plugin that they were given.  Rather, they'd go to a trusted source for plugins, which is what code signing basically is. 
== More Plugin Architecture Ideas ==


Also, this could reduce the incentive to innovate because of the lack of IP protection. 
# [[Plugin_architecture_RoadMap|Development Road Map]]
Note that some may argue that open source is the only approach because the client is released under GPL.  As the holders of the SL copyrights, hopefully Linden Lab will create an exception in the license so that we may link plugins against the code without having to GPL our own code base.
# Discussions
## [[Plugin_architecture_survey|Survey of Client Plugins as Potential Models]]
## [[Plugin_architecture_backwards|Backwards Compatibility]]
## [[Plugin_architecture_Security|Security Model Issues]]
## [[Plugin_architecture_Stability|Plugins affecting Client Stability]]
## [[Plugin_LSL_Communication|Plugins <--> LSL Communication Channels]]
## [[Plugin_closed_source|Closed Source versus Open Source]]


* Applet Sandboxing.  This is the JavaScript / Flash / Java Applet model where code is executed inside a VM inside the client.  In someways, this is a very compelling approach as it is usually not that challenging to secure the virtual machine.  It also allows for dynamic execution of code more easily.
# Alternatives
## [[Plugin_Embedded|Embedded Virtual Machine With Scripting Language]]
## [[Plugin_Separate_Process|Separate Process]]


However, it is also a significant engineering feat to build such a thing, it usually has limited capabilities, and often suffers from time and space constraints during execution.
[[Category:Feature Requests]]
 
 
'''Dynamic Updating Of Plugins'''
 
'''Dynamic Loading of Plugins'''
 
'''Cross Platform Issues'''
 
'''PlugIns effecting Client Stability'''

Latest revision as of 22:55, 6 April 2007

As of this writing (February 12, 2007), there's not an official plugin architecture in the Second Life viewer. However, there's been a lot of interest in developing one. This page (and the pages it links to) are an attempt to capture a lot of the informal discussion that has occurred so far.


These are the three main issues to be addressed:

Code loading

Dynamic loading of natively-compiled executable code can be accomplished with dlopen / dlsym in Linux and MacOSX and LoadLibrary on Win32.

dlopen code example


There are wrappers to allow this to be more cross platform:

  • Apache APR - Already in use in llimage/llimagej2c.cpp. Not GPL compatible, but is compatible with the GPL+FLOSS exception license used in the Second Life viewer
  • libtltdl
  • Glib GModules

Making the client into dynamic libs itself

Most interesting functions in the viewer could be broken out into dylibs / dlls so that plugins could link against them. Code that we want to be able to call from a plugin needs to be in a DLL, and they can all be in the same DLL. Code that is so rarely used we'd like to not load it unless we have to should go into a separate DLL.

Calls from viewer to plugin (hooks)

In order to override or enhance existing functionality in the viewer, we need to be able to replace some code with our own. One way to do this would be to install "hooks" into commonly-used functions. In the example implementation code below, you can hook any function by adding 'PLUGIN_HOOK("function_name", data1, data2)' to the top of the function.

When that macro is called, it looks to see if any hooks have been registered with a name that matches "function_name". If so, it executes each one in turn.

Each hook function can affect program execution in one of three ways:

  • Pass event through -- a function might decide to ignore this hook based on the contents of data1 and data2, or it might do something which doesn't disrupt the program flow (such as adding data to an internal list for later use, or displaying a dialog box). In this case, it should just return TRUE.
  • Modify params, pass event through -- as above, except the hook function can modify the contents of data1 and/or data2 before returning TRUE
  • Swallow event: Sometimes, we want to completely override the function being hooked, for various reasons -- in this case, the plugin should return FALSE.

PLUGIN_HOOK executes each function in turn; if it function returns FALSE, it just issues a 'return' in the context of the hooked function. If all hooks return TRUE, control will eventually be passed to the hooked function.

hook example code

hooking sending IMs

Calls from plugin to viewer (exposing an API)

Most plugins will want to call into the client and have it do things like display dialog boxes, send IMs, etc. Unfortunately, there's no simple way to do this.

One solution is to pick a number of useful functions, build a function pointer table, and allow plugins to ask for them by name.

function pointer example code

Required Changes

Some changes in the code will be required to support plugins.

  • Complete GUI and other classes with functions that would be expected to exist, but don't because nothing needed them yet. For instance, add method overloads that should logically exist.
  • Allow multiple callbacks per message, as well as unregistering a previously registered one. Currently only one callback can be registered per message type.
  • Verify that all the callbacks work in such a way that they wouldn't be confused by plugins. When a callback for a reply to a request runs it must make sure that the data to arrived is what was requested, and if not, ignore it.
  • Add internal callbacks for events such as rendering a frame, receiving a chat message, etc.

Other Information

Capabilities and Plugin Examples

The following is a discussion of what we'd like to be able to do with a plugin. Note it is not a discussion of how plugins will be managed.

  • Affecting rendering pipeline (eg, improving rendering of clouds)
  • Transforming messages (eg: adding encryption to IM messages)
  • Improving the User Interface (eg: better building tools)
  • Automated Agents, potentially headless (no GUI).
  • Extend client to support new 3D object types and their behaviors (eg: rendering of objects with complex, non-primitive shapes or complex behaviors)
  • Extend client to be a platform for other applications (eg: PDF viewer with scrollbars on the face of a prim)

More Plugin Architecture Ideas

  1. Development Road Map
  2. Discussions
    1. Survey of Client Plugins as Potential Models
    2. Backwards Compatibility
    3. Security Model Issues
    4. Plugins affecting Client Stability
    5. Plugins <--> LSL Communication Channels
    6. Closed Source versus Open Source
  1. Alternatives
    1. Embedded Virtual Machine With Scripting Language
    2. Separate Process