![]() | International Virtual Observatory Alliance |
SAMP is a messaging protocol that enables astronomy software tools to interoperate and communicate.
IVOA members have recognised that building a monolithic tool that attempts to fulfil all the requirements of all users is impractical, and it is a better use of our limited resources to enable individual tools to work together better. One element of this is defining common file formats for the exchange of data between different applications. Another important component is a messaging system that enables the applications to share data and take advantage of each other's functionality. SAMP is intended to build on the success of a prior messaging protocol, PLASTIC, which has been in use since 2006 in over a dozen astronomy applications and has proven popular with users and developers. SAMP is an IVOA-endorsed standard that builds on this success. It is also intended to form a framework for more general messaging requirements.
This is an IVOA Working Draft for review by IVOA members and other interested parties. It is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to use IVOA Working Drafts as reference materials or to cite them as other than "work in progress".
1.1 History
1.2 Requirements and Scope
1.3 Types of Messaging
1.4 About this Document
2 Architectural Overview
2.1 Nomenclature
2.2 Messaging Topology
2.3 The Lifecycle of a Client
2.4 The Lifecycle of a Hub
2.5 Message Delivery Patterns
2.6 Extensible Vocabularies
2.7 Use of Profiles
3 Abstract APIs and Data Types
3.1 Hub Discovery Mechanism
3.2 Communicating with the Hub
3.3 SAMP Data Types
3.4 Scalar Type Encoding Conventions
3.5 Registering with the Hub
3.6 Application Metadata
3.7 MType Subscriptions
3.8 Message Encoding
3.9 Response Encoding
3.10 Sending and Receiving Messages
3.11 Operations a Hub Must Support
3.12 Operations a Callable Client Must Support
3.13 Error Processing
4 Standard Profile
4.1 Data Type Mappings
4.2 API Mappings
4.3 Lockfile and Hub Discovery
4.4 Examples
5 MTypes: Message Semantics and Vocabulary
5.1 The Form of an MType
5.2 The Description of an MType
5.3 MType Vocabulary: Extensibility and Process
5.4 Core MTypes
5.4.1 Hub Administrative Messages
5.4.2 Client Administrative Messages
A Changes between PLASTIC and SAMP
B SAMP/PLASTIC interoperability
SAMP is a direct descendent of the PLASTIC protocol, which in turn grew - in the VOTech [1] framework - from the interoperability work of the Aladin [2] and VisIVO [3] teams. We also note the contribution of the team behind the earlier XPA protocol [4]. For more information on PLASTIC's history and purpose see the IVOA Note PLASTIC - a protocol for desktop application interoperability [5] and the PLASTIC SourceForge site [6].
SAMP has similar aims to PLASTIC, but incorporates lessons learnt from two years of practical experience and ideas from partners who were not involved in PLASTIC's initial design.
Broadly speaking, SAMP is an abstract framework for loosely coupled asynchronous RPC-like and/or event-based communication with extensible message semantics using structured but weakly-typed data and based on a central service providing multi-directional publish/subscribe message brokering. These concepts are expanded on below. It attempts to make as few assumptions as possible about the transport layer or programming language with which it is used. It also defines a "Standard Profile" which specifies how to implement this framework using XML-RPC [7] as the transport layer. The result of combining this Standard Profile with the rest of the SAMP standard is deliberately similar in design to PLASTIC, and the intention is that existing PLASTIC applications can be modified to speak SAMP instead without great effort.
SAMP aims to be a simple and extensible protocol that is platform- and language-neutral. The emphasis is on a simple protocol with a very shallow learning curve in order to encourage as many application authors as possible to adopt it. SAMP is intended to do what you need most of the time. The SAMP authors believe that this is the best way to foster innovation and collaboration in astronomy applications.
It is important to note therefore that SAMP's scope is reasonably modest; it is not intended to be the perfect messaging solution for all situations. In particular SAMP itself has no support for transactions, guaranteed message delivery, message integrity or messaging beyond a single machine. However, by layering the SAMP architecture on top of suitable messaging infrastructures such capabilities could be provided. These possibilities are not discussed further in this document, but the intention is to provide an architecture which is sufficiently open to allow for such things in the future with little change to the basics.
SAMP is currently limited to inter-application desktop messaging with the idea that the basic framework presented here is extensible to meet future needs, and so it is beyond the scope of this document to outline the many types of messaging systems in use today (these are covered in detail in many other documents). While based on established messaging models, SAMP is in many ways a hybrid of several basic messaging concepts; the protocol is however flexible enough that later versions should be able to interact fairly easily with other messaging systems because of the shared messaging models.
The messaging concepts used within SAMP include:
This document contains the following main sections describing the SAMP protocol and how to use it. Section 2 covers the requirements, basic concepts and overall architecture of SAMP. Section 3 defines abstract (i.e. independent of language, platform and transport protocol) interfaces which clients and hubs must offer to participate in SAMP messaging, along with data types and encoding rules required to use them. Section 4 explains how the abstract API can be mapped to specific network operations to form an interoperable messaging system, and defines the "Standard Profile", based on XML-RPC, which gives a particular set of such mappings. Section 5 describes the use of the MType keys used to denote message semantics, and outlines an MType vocabulary.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
This section provides a high level view of the SAMP protocol.
In the text that follows these terms are used:
SAMP has a hub-based architecture (see Figure 1). The hub is a single service used to route all messages between clients. This makes application discovery more straightforward in that each client only needs to locate the hub, and the services provided by the hub are intended to simplify the actions of the client. A disadvantage of this architecture is that the hub may be a message bottleneck and the hub may be the single point of failure. The former means that SAMP may not be suitable for extremely high throughput requirements; the latter may be mitigated by an appropriate strategy for hub restart if failure is likely.
Note that the hub is defined as a service interface which may have any of a number of implementations. It may be an independent application running as a daemon, an adapter interface layered on top of an existing messaging infrastructure, or a service provided by an application which is itself one of the hub's clients.
A SAMP client goes through the following phases:
Phases 4-7 are all optional and may be repeated in any order.
By subscribing to the MTypes described in Section 5.4.1 a client may, if it wishes, keep track of the details of other clients' registrations, metadata and subscriptions.
A SAMP hub goes through the following phases:
Phases 3-8 are responses to events which may occur multiple times and in any order.
The MTypes broadcast by the hub to inform clients of changes in its state are given in Section 5.4.1.
Readers should note that, given this scheme, race conditions may occur. A client might for instance try to register with a hub which has just shut down, or attempt to send to a recipient which has already unregistered. Specific profiles MAY define best-practice rules in order to best manage these conditions, but in general clients should be aware that SAMP's lack of guaranteed message delivery and timing means that unexpected conditions are possible.
Messages can be sent according to three patterns, differing in whether and how a response is returned to the sender:
The Notification pattern is strictly one-way while in the Call/Response patterns the recipient returns a response to the sender.
If the sender expects to receive some useful data as a result of the receiver's processing, or if it wishes to find out whether and when the processing is completed, it should use one of the Call/Response variants. If on the other hand the sender has no interest in what the recipient does with the message once it has been sent, it may use the Notification pattern. Notification, since it involves no communication back from the recipient to the sender, uses fewer resources. Although typically "event"-type messages will be sent using Notify and "request-for-information"-type messages will be sent using Call/Response, the choice of which delivery pattern to use is entirely distinct from the content of the message, and is up to the sender; any message (MType) may be sent using any of the above patterns. Apart from the fact of returning or not returning a response, the recipient should process messages in exactly the same way regardless of which pattern is used.
From the receiver's point of view there are only two cases, Notification and Asynchronous Call/Response. However the hub provides a convenience method which simulates a synchronous call from the sender's point of view. The purpose of this is to simplify the use of the protocol in situations such as scripting environments which cannot easily handle asynchronicity. However, it is recommended to use the asynchronous pattern where possible due to its greater robustness.
At several places in this document structured information is conveyed by use of a controlled but extensible vocabulary. Some examples are the application metadata keys (Section 3.6), message encoding keys (Section 3.8) and Standard Profile lockfile tokens (Section 4.3).
Wherever this pattern is used, the following rules apply. This document defines certain well-known keys with defined meanings. These may be optional or required as documented, but if present MUST be used by clients and hubs in the way defined here. All such well-known keys start with the string "samp.".
Clients and hubs are however free to introduce and use non-well-known keys as they see fit. Any string may be used for such a non-standard key, with the restriction that it MUST NOT start with the string "samp.".
The general rule is that hubs and clients which encounter keys which they do not understand should ignore them, propagating them to downstream consumers if appropriate. As far as possible, where new keys are introduced they should be such that applications which ignore them will continue to behave in a sensible way.
Hubs and clients are therefore able to communicate information additional to that defined in the current version of this document without disruption to those which do not understand it. This extensibility may be of use to applications which have mutual private requirements outside the scope of this specification, or to enable experimentation with new features. If the SAMP community finds such experiments useful, future versions of this document may bring such functionality within the SAMP specification itself by defining new keys in the "samp." namespace. The ways in which these vocabularies are used means that such extensions should be possible with minimal upheaval to the existing specification and implementations.
The design of SAMP is based on the abstract interfaces defined in Section 3. On its own however, this does not include the detailed instructions required by application developers to achieve interoperability. To achieve that, application developers must know how to map the operations in the abstract SAMP interfaces to specific I/O (in most cases, network) operations. It is these I/O operations which actually form the communication between applications. The rules defining this mapping from interface to I/O operations are what constitute a SAMP "Profile" (the term "Implementation" was considered for this purpose, but rejected because it has too many overlapping meanings in this context).
There are two ways in which such a Profile can be specified as far as client application developers are concerned:
Although either is possible, SAMP is well-suited for approach (1) above given a suitable low-level transport library. This is the case since the operations are quite low-level, so client applications can easily perform them without requiring an independently developed SAMP library. This has the additional advantages that central effort does not have to be expended in producing language-specific libraries, and that the question of "unsupported" languages does not arise.
Section 4 describes a Profile along the lines of (1) above, based on XML-RPC, which can be used directly by client and hub developers, in conjunction with the abstract interface description in Section 3, to write interoperable applications. This is at present the only SAMP Profile which has been defined.
Although splitting the abstract interface and Profile descriptions in this way complicates the document a little, it separates the basic design principles from the details of how to apply them, and it opens the door for other Profiles serving other use cases in the future.
In order to keep track of which hub is running, a hub discovery mechanism, capable of storing information about how to determine the existence of and communicate with a running hub, is needed. This is a Profile-specific matter and a specific prescription will be described in 4.3.
The details of how a client communicates with the hub are Profile-specific. A specific prescription will be described in Section 4.
For all hub/client communication, including the actual content of messages, SAMP uses three conceptual data types:
These types can in principle be nested to any level, so that the elements of a list or the values of a map may themselves be strings, lists or maps.
There is no reserved representation for a null value, and it is illegal to send a null value in a SAMP context even if the underlying transport protocol permits this. However a zero-length string or an empty list or map may where appropriate be used to indicate an empty value.
Although SAMP imposes no maximum on the length of a string, particular transport protocols or implementation considerations may effectively do so; in general hub and client implementations are not expected to deal with data items of unlimited size. General purpose MTypes should therefore be specified so that bulk data is not sent within the message - in general it is preferred to define a message parameter as the URL or filename of a potentially large file rather than as the inline text of the file itself.
At the protocol level there is no provision for typing of scalars; unlike many Remote Procedure Call (RPC) protocols SAMP does not distinguish syntactically between strings, integers, floating point values, booleans etc. This minimizes the restrictions on what underlying transport protocols may be used, and avoids a number of problems associated with using typed values from untyped languages such as Python and Perl. The practical requirement to transmit these types is addressed however by the next section.
Although the protocol itself defines string as the only scalar type, some MTypes will wish to define parameters or return values which have non-string semantics, so conventions for encoding these as strings are in practice required. Such conventions only need to be understood by the sender and recipient of a given message and so can be established on a per-MType basis, but to avoid unnecessary duplication of effort this section defines some commonly-used type encoding conventions.
We define the following BNF productions:
<digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" <digits> ::= <digit> | <digits> <digit> <float-digits> ::= <digits> | <digits> "." | "." <digits> | <digits> "." <digits> <sign> ::= "+" | "-"
With reference to the above we define the following type encoding conventions:
The numeric types are based on the syntax of the C programming language, since this syntax forms the basis for typed data syntax in many other languages. There may be extensions to this list in future versions of this document.
Particular MType definitions may use these conventions or devise their own as required. Where the conventions in this list are used, message documentation should make it clear using a form of words along the lines "this parameter contains a SAMP int ".
A client registers with the hub to:
The registration information is in the form of a map containing data items which the client may wish to use during the SAMP session. The hub MUST fill in values for the following keys in the returned map:
These keys form part of an extensible vocabulary as explained in Section 2.6. In most cases a client will not require either of the above IDs for normal SAMP operation, but they are there for clients which do wish to know them. Particular Profiles may require additional entries in this map.
Immediately following registration, the client will typically perform some or all of the following optional operations:
A client may store metadata in the form of a map of key-value pairs in the hub for retrieval by other clients. Typical metadata might be the human-readable name of the application, a description and a URL for its icon, but other values are permitted. The following keys are defined for well-known metadata items:
All of the above are OPTIONAL, but samp.name is strongly RECOMMENDED. These keys form the basis of an extensible vocabulary as explained in Section 2.6.
As outlined above, an MType is a string which defines the semantics of a message. MTypes have a hierarchical form. Their syntax is given by the following BNF:
<mchar> ::= [0-9a-z] | "-" | "_" <atom> ::= <mchar> | <atom> <mchar> <mtype> ::= <atom> | <atom> "." <atom>
Examples might be "samp.hub.event.shutdown" or "file.load".
A client may subscribe to one or more MTypes to indicate which messages it is willing to receive. A client will only ever receive messages with MTypes to which it has subscribed. In order to do this it passes a subscriptions map to the hub. Each key of this map is an MType string to which the client wishes to subscribe, and the corresponding value is a map which may contain additional information about that subscription. Currently, no keys are defined for these per-MType maps, so typically they will be empty (have no entries). The use of a map here is to permit experimentation and perhaps future extension of the SAMP standard.
As a special case, simple wildcarding is permitted in subscriptions. The keys of the subscription map may actually be of the form <msub>, where
<msub> ::= "*" | <mtype> "." "*"
Thus a subscription key "file.event.*" means that a client wishes to receive any messages with MType which begin "file.event.". This does not include "file.event". A subscription key "*" subscribes to all MTypes. Note that the wildcard "*" character may only appear at the end of a subscription key, and that this indicates subscription to the entire subtree.
More discussion of MTypes, including their semantics, is given in Section 5.
A message is an abstract container for the information we wish to send to another application. The message itself is that data which should arrive at the receiving application. It may be transmitted along with some external items (e.g. sender, recipient and message identifiers) required to ensure proper delivery or handling.
The message can be encoded as a map with the following REQUIRED keys:
These keys form the basis of an extensible vocabulary as explained in Section 2.6.
A response is what may be returned from a recipient to a sender giving the result of processing a message (though in the case of the Notification delivery pattern, no such response is generated or returned). It may contain MType-specific return values, or error information, or both.
The response can be encoded as a map with the following keys:
These keys form the basis of an extensible vocabulary as explained in Section 2.6.
As outlined in Section 2.5, three messaging patterns are supported, differing according to whether and how the response is returned to the sender. For a given MType there may be a messaging pattern that is most typically used, but there is nothing in the protocol that ties a particular MType to a particular messaging pattern; any MType may legally be sent using any delivery pattern.
From the point of view of the sender, there are three ways in which a message may be sent, and from the point of view of the recipient there are two ways in which one may be received. These are described as follows.
Note that the two different cases from the receiver's point of view, Notification and Call/Response , differ only in whether a response is returned to the hub. In other respects the receiver should process the message in exactly the same way for both patterns.
Although it is REQUIRED by this standard that client applications provide a Response for every Call that they receive, there is no way that the hub can enforce this. Senders using the Synchronous or Asynchronous Call/Response patterns therefore should be aware that badly-behaved recipients might fail to respond, leading to calls going unanswered indefinitely. The timeout parameter in the Synchronous Call/Response pattern provides some protection from this eventuality; users of the Asynchronous Call/Response pattern may or may not wish to take their own steps.
This section describes the operations that a hub must support and the associated data that must be sent and received. The precise details of how these operations map onto method names and signatures is Profile-dependent. The mapping for the Standard Profile is given in Section 4.2.
All these operations with the exception of callAndWait() should complete, and where appropriate return a result, quickly.
This section lists the operations which the hub may call on a callable client. Note that callability is optional for clients; special (Profile-dependent) steps may be required for a client to inform the hub how it may be contacted, and thus become callable. Clients which are not callable may send messages using the Notify or Synchronous Call/Response patterns, but are unable to receive messages or to use Asynchronous Call/Response, since these operations rely on client callbacks from the hub.
The precise details of how these operations map onto method names and signatures is Profile-dependent. The mapping for the Standard Profile is given in Section 4.2.
All these operations should complete quickly.
Errors encountered by clients when processing Call/Response-pattern messages themselves (in response to a syntactically legal receiveCall() operation) should be signalled by returning appropriate content in the response map sent back in the matching reply() call, as described in Section 3.9.
In the case of bad calls of the operations defined in Sections 3.11 and 3.12, for instance syntactically invalid parameters, hubs and clients should use the usual error reporting mechanisms of the transport protocol in use.
Section 3 provides an abstract definition of the operations and data structures used for SAMP messaging. As explained in Section 2.7, in order to implement this architecture some concrete choices about how to instantiate these concepts are required.
This section gives the details of a SAMP Profile based on the XML-RPC specification [7]. Hub discovery is via a lockfile in the user's home directory.
XML-RPC is a simple general purpose Remote Procedure Call protocol based on sending XML documents using HTTP POST (it resembles a very lightweight version of SOAP). Since the mappings from SAMP concepts such as API calls and data types to their XML-RPC equivalents is very straightforward, it is easy for application authors to write compliant code without use of any SAMP-specific library code. An XML-RPC library, while not essential, will make coding much easier; such libraries are available for many languages.
The SAMP argument and return value data types described in Section 3.3 map straightforwardly onto XML-RPC data types as follows:
SAMP type | XML-RPC element | |
string | - | <string> |
list | - | <array> |
map | - | <struct> |
The <value> children of <array> and <struct> elements themselves contain children of type <string>, <array> or <struct>.
Note that other XML-RPC scalar types (<i4>, double etc) are not used; even where the semantic sense of a value matches one of those types it must be encoded as an XML-RPC <string>.
The operation names in the SAMP hub and client abstract APIs (Sections 3.11 and 3.12) very nearly have a one to one mapping with those in the Standard Profile XML-RPC APIs. The differences are as follows:
The private-key string referred to above serves two purposes. First it identifies the client in hub/client communications. Some such identifier is required, since XML-RPC calls have no other way of determining the sender's identity. Second, it prevents application spoofing, since the private key is never revealed to other applications, so that one application cannot pose as another in making calls to the hub.
The usual XML-RPC fault mechanism is used to respond to invalid calls as described in 3.13. The XML-RPC fault's <faultString> element should contain a user-directed message as appropriate and the <faultCode> value has no particular significance.
Hub discovery is performed by examining a lockfile in a well-known location. This has the consequence that in normal operation each user may run only one hub, and users do not share hubs. The name of the lockfile is ".samp" in the user's home directory. A "home directory" is a somewhat system-dependent concept: we define it as the value of the $HOME environment variable on Unix-like systems and as the value of the %USERPROFILE% environment variable on Microsoft Windows2.
The format of the file is given by the following BNF productions:
<file> ::= <lines> <lines> ::= <line> | <lines> <line> <line> ::= <line-content> <EOL> | <EOL> <line-content> ::= <comment> | <assignment> <comment> ::= "#" <any-string> <assignment> ::= <name> "=" <any-string> <name> ::= <token-string> <token-string> ::= <token-char> | <token-string> <token-char> <any-string> ::= <any-char> | <any-string> <any-char> <EOL> ::= "\r" | "\n" | "\r" "\n" <token-char> ::= [a-zA-Z0-9] | "-" | "_" | "." <any-char> ::= [\x20-\x7f]
The only parts which are significant to SAMP clients/hubs are (a) existence of the file and (b) <assignment> lines.
A legal lockfile MUST provide (in any order) unique assignments for the following tokens:
These keys form the basis of an extensible vocabulary as explained in Section 2.6. Other blank, comment or assignment lines may be included as desired.
The lockfile should normally be created with permissions which allow only its owner to read it. This provides a measure of security in that only processes with the same permissions as the hub process (hence presumably running under the same user ID) will be able to register with the hub, since only they will be able to provide the samp.secret required for registration. Thus under normal circumstances all participants in a SAMP conversation can be presumed owned by the same user, and therefore not malicious.3
An example lockfile might therefore look like this:
# SAMP lockfile written 2008-29-02T17:45:01 # Required keys: samp.secret=734144fdaab8400a1ec2 samp.hub.xmlrpc.url=http://andromeda.star.bris.ac.uk:8001/xmlrpc samp.profile.version=1.0 # Info stored by hub for some private reason: com.yoyodyne.hubid=c80995f1
The existence of the file MAY be taken (e.g. by a hub deciding whether to start or not) to indicate that a hub is running. However it is RECOMMENDED to attempt to contact the hub at the given XML-RPC URL (e.g. by calling ping()) to determine whether it is actually alive.
The hub discovery sequences are therefore as follows:
Hub implementations SHOULD make their best effort to perform the shutdown sequence above even if they terminate as a result of some error condition.
Note that manipulation of a file is not atomic, so that race conditions are possible. For instance a client or hub examining the lockfile may read it after it has been created but before it has been populated with the mandatory assignments, or two hubs may look for a lockfile simultaneously, not find one, and both decide that they should therefore start up, one presumably overwriting the other's lockfile. Hub and client implementations should be aware of such possibilities, but may not be able to guarantee to avoid them or their consequences. In general this is the sort of risk that SAMP and its Standard Profile are prepared to take - an eventuality which will occur sufficiently infrequently that it is not worth significant additional complexity to avoid. In the worst case a SAMP session may fail in some way, and will have to be restarted.
Here is an example in pseudo-code of how an application might locate and
register with a hub, and send a message requiring no response to other
registered clients.
# Read information from lockfile to locate and register with hub.
string hub-url = readFromLockfile("samp.hub.xmlprc.url");
string samp-secret = readFromLockfile("samp.secret");
# Establish XML-RPC connection with hub
# (uses some generic XML-RPC library)
xmlrpcServer hub = xmlrpcConnect(hub-url);
# Register with hub.
map reg-info = hub.xmlrpcCall("samp.hub.register", samp-secret);
string private-key = reg-info.getValue("samp.private-key");
# Store metadata in hub for use by other applications.
map metadata = ("samp.name" -> "dummy",
"samp.description.text" -> "Test Application",
"dummy.version" -> "0.1-3");
hub.xmlrpcCall("samp.hub.declareMetadata", private-key, metadata);
# Send a message requesting file load to all other
# registered clients, not wanting any response.
map loadParams = ("filename" -> "/tmp/foo.bar");
map loadMsg = ("samp.mtype" -> "file.load",
"samp.params" -> loadParams);
hub.xmlrpcCall("samp.hub.notifyAll", private-key, loadMsg);
# Unregister
hub.xmlrpcCall("samp.hub.unregister", private-key);
The first few XML-RPC documents sent over the wire for this exchange
would look something like the following.
The registration call from the client to the hub:
POST /xmlrpc HTTP/1.0
User-Agent: Java/1.5.0_10
Content-Type: text/xml
Content-Length: 189
<?xml version="1.0"?>
<methodCall>
<methodName>samp.hub.register</methodName>
<params>
<param><value><string>734144fdaab8400a1ec2</string></value></param>
</params>
</methodCall>
which leads to the response:
HTTP/1.1 200 OK
Connection: close
Content-Type: text/xml
Content-Length: 464
<?xml version="1.0"?>
<methodResponse>
<params><param><value><struct>
<member>
<name>samp.private-key</name>
<value><string>client-key:1a52fdf</string></value>
</member>
<member>
<name>samp.hub-id</name>
<value><string>client-id:0</string></value>
</member>
<member>
<name>samp.self-id</name>
<value><string>client-id:4</string></value>
</member>
</struct></value></param></params>
</methodResponse>
The client can then declare its metadata:
the response to this call has no useful content so can be ignored or discarded.
POST /xmlrpc HTTP/1.0
User-Agent: Java/1.5.0_10
Content-Type: text/xml
Content-Length: 600
<?xml version="1.0"?>
<methodCall>
<methodName>samp.hub.declareMetadata</methodName>
<params>
<param><value><string>app-id:1a52fdf-2</string></value></param>
<param><value><struct>
<member>
<name>samp.name</name>
<value><string>dummy</string></value>
</member>
<member>
<name>samp.description.text</name>
<value><string>Test application</string></value>
</member>
<member>
<name>dummy.version</name>
<value><string>0.1-3</string></value>
</member>
</struct></value></param>
</params>
</methodCall>
The message itself is sent from the client to the hub as follows:
POST /xmlrpc HTTP/1.0
User-Agent: Java/1.5.0_10
Content-Type: text/xml
Content-Length: 523
<?xml version="1.0"?>
<methodCall>
<methodName>samp.hub.notifyAll</methodName>
<params>
<param><value><string>app-id:1a52fdf-2</string></value></param>
<param><value><struct>
<member>
<name>samp.mtype</name>
<value>file.load</value>
</member>
<member>
<name>samp.params</name>
<value><struct>
<name>filename</name>
<value>/tmp/foo.bar</value>
</struct></value>
</member>
</struct></value></param>
</params>
</methodCall>
Again, there is no interesting response.
As stated earlier, a message contains an MType string that defines the semantic meaning of the message, for example a request for another application to load a table. The concept behind the MType is similar to that of a UCD in that a small vocabulary is sufficient to describe the expected range of concepts required by a messaging system within the current scope of the SAMP protocol. Developers are free to introduce new MTypes for use within applications without restriction; new MTypes intended to be used for Hub messaging or other administrative purposes within the messaging system should be discussed within the IVOA for approval as part of the SAMP standard.
MType syntax is formally defined in Section 3.7. Like a UCD, an MType is made up of atoms. These are not only meaningful to the developer, but form the central concept of the message. Because we wish to loosely couple the capabilities one application is searching for from the details of what another may provide, we don't create a rigorous definition of the behavior that an MType must provoke in a receiver. Instead, the MType defines a specific semantic message such as "display an image", it is up to the receiving application to determine how it chooses to do the display (e.g. a rendered greyscale image within an application or displaying the image in a web browser might both be valid for the recipient and faithful to the meaning of the message).
The ordering of the words in an MType should normally use the object of the message followed by the action to be performed (or the information about that object). For example, the use of "image.display" is preferred to "display.image" in order to keep the number of toplevel words (and thus message classes) like `image' small, but still allow for a wide variety of messages to be created that can perform many useful actions on an image. If no existing MType exists for the required purpose, developers can agree to the use of a new MType such as "image.display.extnum" if e.g. the ability to display a specific image extension number warrants a new MType.
In order that senders and recipients can agree on what is meant by a given message, the meaning of an MType must be clearly documented. This means that for a given MType the following information must be available:
For each of the named parameters, and each of the returned values, the following information must be provided:
Together, this is much the same information as should be given for documentation of a public interface method in a weakly-typed programming language.
The parameters and return values associated with each MType form extensible vocabularies as explained in Section 2.6, except that there is no reserved "samp." namespace.
Note that it is possible for the MType to have no returned values. This is actually quite common if the MType does not represent a request for data. It is not usually necessary to define a status-like return value (success or failure), since this information can be conveyed as the value of the samp.status entry in the call response as described in Section 3.9.
The set of MTypes forms an extensible vocabulary along the lines of Section 2.6. The relatively small number of MTypes in the "samp." namespace are defined in Section 5.4 of this document, but applications will need to use a wider range of MTypes to exchange useful information. Although clients are formally permitted to define and use any MTypes outside of the reserved "samp." namespace, for effective interoperability there must be public agreement between application authors on this unreserved vocabulary and its semantics. Since addition of new MTypes is expected to be ongoing, MTypes from this broader vocabulary will be documented in some kind of working list outside of this document to avoid the administrative overhead and delay associated with the IVOA Recommendation Track [8]. This working list may take the form of an IVOA Note.
Details of the procedure remain to be decided, but good practice for an application author who has the need to send or receive a message with particular semantics will be along the following lines:
This section defines those MTypes currently in the samp. hierarchy. These are the "administrative"-type MTypes which are core to the SAMP architecture or widely applicable to SAMP applications.
The following MTypes are for messages which SHOULD be broadcast by the hub in response to changes in hub state. By subscribing to these messages, clients are able to keep track of the current set of registered applications and of their metadata and subscriptions. In general, non-hub clients SHOULD NOT send these messages.
The following messages are generic messages defined for client use.
In order to facilitate the transition from PLASTIC to SAMP from an application developer's point of view, we summarize in this Appendix the main changes. In some cases the reasons for these are summarized as well.
PLASTIC | SAMP |
message | MType |
support a message | subscribe to an MType |
synchronous request | synchronous call/response |
asynchronous request | notification |
This section will detail how interoperability between SAMP-compatible and PLASTIC-compatible clients can be achieved, using hubs able to translate PLASTIC messages into SAMP MTypes.
One way a hub might implement this is to generate msg-id by concatenating the sender's client id and the msg-tag . When any response is received the hub can then unpack the accompanying msg-id to find out who the original sender was and what msg-tag it used. In this way the hub can determine how to pass each response back to its correct sender without needing to maintain internal state concerning messages in progress. Hub and client implementations may wish to exploit this freedom in assigning message IDs for other purposes as well, for instance to incorporate timestamps or checksums.
2Note to Java developers: contrary to what you might expect, the user.home system property on Windows does not give you the value of USERPROFILE. See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4787931.
3
Of course they may be owned by the same user and still be malicious,
but in this case SAMP represents no additional security risk.