idnits 2.17.1 draft-oberstet-hybi-tavendo-wamp-00.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- == There are 14 instances of lines with non-RFC2606-compliant FQDNs in the document. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year -- The document date (September 27, 2015) is 3134 days in the past. Is this intentional? Checking references for intended status: Proposed Standard ---------------------------------------------------------------------------- (See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs) -- Looks like a reference, but probably isn't: '1' on line 2749 -- Looks like a reference, but probably isn't: '0' on line 1144 -- Looks like a reference, but probably isn't: '255' on line 1144 -- Looks like a reference, but probably isn't: '256' on line 1146 -- Looks like a reference, but probably isn't: '1023' on line 1146 -- Looks like a reference, but probably isn't: '33' on line 1587 -- Looks like a reference, but probably isn't: '713845233' on line 1587 -- Looks like a reference, but probably isn't: '5512315355' on line 1641 -- Looks like a reference, but probably isn't: '34' on line 1641 -- Looks like a reference, but probably isn't: '85346237' on line 1656 -- Looks like a reference, but probably isn't: '35' on line 1656 -- Looks like a reference, but probably isn't: '17' on line 1775 -- Looks like a reference, but probably isn't: '239714735' on line 1775 -- Looks like a reference, but probably isn't: '4429313566' on line 1775 -- Looks like a reference, but probably isn't: '65' on line 1942 -- Looks like a reference, but probably isn't: '25349185' on line 1942 -- Looks like a reference, but probably isn't: '2103333224' on line 1980 -- Looks like a reference, but probably isn't: '66' on line 1980 -- Looks like a reference, but probably isn't: '788923562' on line 1995 -- Looks like a reference, but probably isn't: '67' on line 1995 Summary: 0 errors (**), 0 flaws (~~), 2 warnings (==), 21 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 BiDirectional or Server-Initiated HTTP T. Oberstein 3 Internet-Draft Tavendo GmbH 4 Intended status: Standards Track September 27, 2015 5 Expires: March 30, 2016 7 Web Application Messaging Protocol - Basic Profile 8 draft-oberstet-hybi-tavendo-wamp-00 10 Abstract 12 This document defines the basic profile for the Web Application 13 Messaging Protocol (WAMP). WAMP is a routed protocol that provides 14 two messaging patterns: Publish & Subscribe and routed Remote 15 Procedure Calls. It is intended to connect application components in 16 distributed applications. WAMP uses WebSocket as its default 17 transport, but can be transmitted via any other protocol that allows 18 for ordered, reliable, bi-directional and message-based 19 communication. 21 Status of This Memo 23 This Internet-Draft is submitted in full conformance with the 24 provisions of BCP 78 and BCP 79. 26 Internet-Drafts are working documents of the Internet Engineering 27 Task Force (IETF). Note that other groups may also distribute 28 working documents as Internet-Drafts. The list of current Internet- 29 Drafts is at http://datatracker.ietf.org/drafts/current/. 31 Internet-Drafts are draft documents valid for a maximum of six months 32 and may be updated, replaced, or obsoleted by other documents at any 33 time. It is inappropriate to use Internet-Drafts as reference 34 material or to cite them other than as "work in progress." 36 This Internet-Draft will expire on March 30, 2016. 38 Copyright Notice 40 Copyright (c) 2015 IETF Trust and the persons identified as the 41 document authors. All rights reserved. 43 This document is subject to BCP 78 and the IETF Trust's Legal 44 Provisions Relating to IETF Documents 45 (http://trustee.ietf.org/license-info) in effect on the date of 46 publication of this document. Please review these documents 47 carefully, as they describe your rights and restrictions with respect 48 to this document. Code Components extracted from this document must 49 include Simplified BSD License text as described in Section 4.e of 50 the Trust Legal Provisions and are provided without warranty as 51 described in the Simplified BSD License. 53 Table of Contents 55 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4 56 1.1. Background . . . . . . . . . . . . . . . . . . . . . . . 4 57 1.2. Protocol Overview . . . . . . . . . . . . . . . . . . . . 5 58 1.3. Design Philosophy . . . . . . . . . . . . . . . . . . . . 5 59 1.3.1. Basic and Advanced Profile . . . . . . . . . . . . . 6 60 1.3.2. Application Code . . . . . . . . . . . . . . . . . . 6 61 1.3.3. Router Implementation Specifics . . . . . . . . . . . 7 62 1.4. Relationship to WebSocket . . . . . . . . . . . . . . . . 7 63 2. Conformance Requirements . . . . . . . . . . . . . . . . . . 7 64 2.1. Terminology and Other Conventions . . . . . . . . . . . . 7 65 3. Realms, Sessions and Transports . . . . . . . . . . . . . . . 8 66 4. Peers and Roles . . . . . . . . . . . . . . . . . . . . . . . 8 67 4.1. Symmetric Messaging . . . . . . . . . . . . . . . . . . . 8 68 4.2. Remote Procedure Call Roles . . . . . . . . . . . . . . . 9 69 4.3. Publish & Subscribe Roles . . . . . . . . . . . . . . . . 9 70 4.4. Peers with multiple Roles . . . . . . . . . . . . . . . . 10 71 5. Building Blocks . . . . . . . . . . . . . . . . . . . . . . . 10 72 5.1. Identifiers . . . . . . . . . . . . . . . . . . . . . . . 10 73 5.1.1. URIs . . . . . . . . . . . . . . . . . . . . . . . . 10 74 5.1.2. IDs . . . . . . . . . . . . . . . . . . . . . . . . . 13 75 5.2. Serializations . . . . . . . . . . . . . . . . . . . . . 15 76 5.2.1. JSON . . . . . . . . . . . . . . . . . . . . . . . . 15 77 5.2.2. MsgPack . . . . . . . . . . . . . . . . . . . . . . . 16 78 5.3. Transports . . . . . . . . . . . . . . . . . . . . . . . 16 79 5.3.1. WebSocket Transport . . . . . . . . . . . . . . . . . 16 80 5.3.2. Transport and Session Lifetime . . . . . . . . . . . 17 81 6. Messages . . . . . . . . . . . . . . . . . . . . . . . . . . 18 82 6.1. Extensibility . . . . . . . . . . . . . . . . . . . . . . 19 83 6.2. No Polymorphism . . . . . . . . . . . . . . . . . . . . . 19 84 6.3. Structure . . . . . . . . . . . . . . . . . . . . . . . . 20 85 6.4. Message Definitions . . . . . . . . . . . . . . . . . . . 20 86 6.4.1. Session Lifecycle . . . . . . . . . . . . . . . . . . 20 87 6.4.2. Publish & Subscribe . . . . . . . . . . . . . . . . . 21 88 6.4.3. Routed Remote Procedure Calls . . . . . . . . . . . . 23 89 6.5. Message Codes and Direction . . . . . . . . . . . . . . . 24 90 6.6. Extension Messages . . . . . . . . . . . . . . . . . . . 25 91 6.7. Empty Arguments and Keyword Arguments . . . . . . . . . . 25 92 7. Sessions . . . . . . . . . . . . . . . . . . . . . . . . . . 26 93 7.1. Session Establishment . . . . . . . . . . . . . . . . . . 26 94 7.1.1. HELLO . . . . . . . . . . . . . . . . . . . . . . . . 26 95 7.1.2. WELCOME . . . . . . . . . . . . . . . . . . . . . . . 28 96 7.1.3. ABORT . . . . . . . . . . . . . . . . . . . . . . . . 29 98 7.2. Session Closing . . . . . . . . . . . . . . . . . . . . . 30 99 7.2.1. Difference between ABORT and GOODBYE . . . . . . . . 31 100 7.3. Agent Identification . . . . . . . . . . . . . . . . . . 32 101 8. Publish and Subscribe . . . . . . . . . . . . . . . . . . . . 32 102 8.1. Subscribing and Unsubscribing . . . . . . . . . . . . . . 32 103 8.1.1. SUBSCRIBE . . . . . . . . . . . . . . . . . . . . . . 34 104 8.1.2. SUBSCRIBED . . . . . . . . . . . . . . . . . . . . . 34 105 8.1.3. Subscribe ERROR . . . . . . . . . . . . . . . . . . . 35 106 8.1.4. UNSUBSCRIBE . . . . . . . . . . . . . . . . . . . . . 35 107 8.1.5. UNSUBSCRIBED . . . . . . . . . . . . . . . . . . . . 36 108 8.1.6. Unsubscribe ERROR . . . . . . . . . . . . . . . . . . 36 109 8.2. Publishing and Events . . . . . . . . . . . . . . . . . . 37 110 8.2.1. PUBLISH . . . . . . . . . . . . . . . . . . . . . . . 37 111 8.2.2. PUBLISHED . . . . . . . . . . . . . . . . . . . . . . 38 112 8.2.3. Publish ERROR . . . . . . . . . . . . . . . . . . . . 39 113 8.2.4. EVENT . . . . . . . . . . . . . . . . . . . . . . . . 39 114 9. Remote Procedure Calls . . . . . . . . . . . . . . . . . . . 40 115 9.1. Registering and Unregistering . . . . . . . . . . . . . . 41 116 9.1.1. REGISTER . . . . . . . . . . . . . . . . . . . . . . 41 117 9.1.2. REGISTERED . . . . . . . . . . . . . . . . . . . . . 42 118 9.1.3. Register ERROR . . . . . . . . . . . . . . . . . . . 42 119 9.1.4. UNREGISTER . . . . . . . . . . . . . . . . . . . . . 43 120 9.1.5. UNREGISTERED . . . . . . . . . . . . . . . . . . . . 43 121 9.1.6. Unregister ERROR . . . . . . . . . . . . . . . . . . 43 122 9.2. Calling and Invocations . . . . . . . . . . . . . . . . . 44 123 9.2.1. CALL . . . . . . . . . . . . . . . . . . . . . . . . 45 124 9.2.2. INVOCATION . . . . . . . . . . . . . . . . . . . . . 46 125 9.2.3. YIELD . . . . . . . . . . . . . . . . . . . . . . . . 47 126 9.2.4. RESULT . . . . . . . . . . . . . . . . . . . . . . . 48 127 9.2.5. Invocation ERROR . . . . . . . . . . . . . . . . . . 49 128 9.2.6. Call ERROR . . . . . . . . . . . . . . . . . . . . . 50 129 9.3. Predefined URIs . . . . . . . . . . . . . . . . . . . . . 51 130 9.4. Interaction . . . . . . . . . . . . . . . . . . . . . . . 51 131 9.4.1. Session Close . . . . . . . . . . . . . . . . . . . . 52 132 9.5. Authorization . . . . . . . . . . . . . . . . . . . . . . 52 133 9.6. Ordering Guarantees . . . . . . . . . . . . . . . . . . . 53 134 9.6.1. Publish & Subscribe Ordering . . . . . . . . . . . . 53 135 9.6.2. Remote Procedure Call Ordering . . . . . . . . . . . 53 136 9.7. Security Model . . . . . . . . . . . . . . . . . . . . . 54 137 9.7.1. Transport Encryption and Integrity . . . . . . . . . 54 138 9.7.2. Router Authentication . . . . . . . . . . . . . . . . 54 139 9.7.3. Client Authentication . . . . . . . . . . . . . . . . 55 140 9.8. Binary conversion of JSON Strings . . . . . . . . . . . . 56 141 9.8.1. Python . . . . . . . . . . . . . . . . . . . . . . . 57 142 9.8.2. JavaScript . . . . . . . . . . . . . . . . . . . . . 57 143 10. Security Considerations . . . . . . . . . . . . . . . . . . . 58 144 11. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 59 145 12. Contributors . . . . . . . . . . . . . . . . . . . . . . . . 59 146 13. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 59 147 14. References . . . . . . . . . . . . . . . . . . . . . . . . . 59 148 14.1. Normative References . . . . . . . . . . . . . . . . . . 59 149 14.2. Informative References . . . . . . . . . . . . . . . . . 59 150 14.3. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 59 151 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 59 153 1. Introduction 155 1.1. Background 157 _This section is non-normative._ 159 The WebSocket protocol brought bi-directional real-time connections 160 to the browser. This defines an API at the message level, requiring 161 users who want to use WebSocket connections in their applications to 162 define any semantics on top of it. 164 The Web Application Messaging Protocl (WAMP) was initially defined as 165 WebSocket protocol at the technical level, and is intended to provide 166 application developers with the semantics they need to handle 167 messaging between components in distributed applications. 169 WAMP is a routed protocol, with all components connecting to a WAMP 170 router. 172 WAMP provides two messaging patterns: Publish & Subscribe and routed 173 Remote Procedure calls. 175 Publish & Subscribe is an established messaging pattern where 176 components inform the router that they want to receive information on 177 a topic (they suscribe to the topic). A component can then publish 178 to this topic, and the router distributes events to all subscribers. 180 With routed Remote Procedure calls, the decoupling of the Publish & 181 Subscribe pattern is applied to Remote Procedure Calls: a component 182 announces to the router that it provides a certain procedure, 183 identified by a procedure name. Other components can then call the 184 procedure, with the router invoking the procedure on the registering 185 component, receiving the result for this, and forwarding this to the 186 caller. 188 Routed Remote Procedure Calls transfer the decoupling of the Publish 189 & Subscribe pattern to Remote Procedure Calls. A caller is no longer 190 required to have knowledge of the Callee, it merely needs to know the 191 identifier for the procedure it wants to call. There is also no 192 longer a need for a direct connection between the caller and the 193 callee, since all traffic is routed. This enables calling procedures 194 in components which are not reachable externally, e.g. on a NATted 195 connection, but which can establish an outgoing connection to the 196 WAMP router. 198 Combining these two patterns into a single protocol allows a single 199 protocol to be used for the entire messaging requirements of an 200 application, reducing complexity in the technology stack and 201 networking overheads. 203 While WAMP was originally specified to run over WebSocket, it can run 204 over any transport which is message-based, ordered, reliable and bi- 205 directional. 207 1.2. Protocol Overview 209 _This section is non-normative._ 211 For each of the two messaging patterns, three roles are defined: 213 For PubSub, there are Subscribers and Publishers, which are connected 214 through a Broker. 216 For routed Remote Procedure Calls there are Callers and Callees, 217 which are connected through a Dealer. 219 WAMP Connections are established by Clients to a Router. Connections 220 can use any transport which is message-based, ordered, reliable and 221 bi-directional, with WebSocket as the default transport. 223 WAMP Sessions are established using a WAMP Connection. A WAMP 224 Session connects to a Realm on a Router. Routing occurs only between 225 WAMP Sessions connected to the same realm. 227 o extend me - 229 1.3. Design Philosophy 231 _This section is non-normative._ 233 WAMP was designed to be performant, safe and easy to implement. Its 234 entire design was drive by a implement, get feedback, adjust cycle. 236 A first version of the protocol was publicly released in March 2012. 237 The intention was to gain insight through implementation and use, and 238 integrate these into a second version of the protocol, where there 239 would be no regard for compatibility between the two versions. 240 Several interoperable, independent implementations were released, and 241 feedback from the implementers and users was collected. 243 The second version of the protocol, which this RFC covers, integrates 244 this feedback. Routed Remote Procedure Calls are one outcome of 245 this, where the first version of the protocol only allowed to call 246 functionality implemented in the router. A connected outcome was the 247 strict separation of routing and application functionality (see 248 below). 250 While WAMP was originally developed to use WebSocket as a transport, 251 and JSON for serialization, experience in the field showed that other 252 transports and serialization formats were better suited to some use 253 cases. As an example, with the use of WAMP in the Internet of Things 254 sphere, resource constraints play a much larger role than in the 255 browser, so any reduction in resource use of WAMP implementations 256 counts. This lead to the decoupling of WAMP from any particular 257 transport or serialization, and the establishment of minimum 258 requirements for each. 260 1.3.1. Basic and Advanced Profile 262 This specification is for a necessary basic set of features which 263 allow WAMP to function, and which is referred to as the WAMP Basic 264 Profile. 266 The specification of additional features is still ongoing. The 267 standardization of such features will be through a separate, future 268 document. 270 1.3.2. Application Code 272 WAMP is designed for application code to run inside _Clients_, i.e. 273 _Peers_ of the roles _Callee_, _Caller_, _Publisher_, and 274 _Subscriber_. 276 _Routers_, i.e. _Peers_ of the roles _Brokers_ and _Dealers_ are 277 responsible for *generic call and event routing* and do not run 278 application code. 280 This allows to transparently exchange _Broker_ and _Dealer_ 281 implementations without affecting the application and to distribute 282 and deploy application components flexibly. 284 Note that a *program* that implements e.g. the _Dealer_ role might 285 at the same time implement e.g. a built-in _Callee_. It is the 286 _Dealer_ and _Broker_ that are generic, not the program. 288 1.3.3. Router Implementation Specifics 290 This specification only deals with the protocol level for a basic 291 profile. Specific WAMP _Broker_ and _Dealer_ implementations might 292 differ in aspects such as: 294 o support for WAMP Advanced Profile 296 o router networks (clustering and federation) 298 o authentication and authorization schemes 300 o message persistence 302 o management and monitoring 304 The definition and documentation of implementation specific _Router_ 305 features like the above is outside the scope of this document. 307 1.4. Relationship to WebSocket 309 WAMP uses WebSocket as its default transport binding, and is a 310 registered WebSocket subprotocol. 312 2. Conformance Requirements 314 All diagrams, examples, and notes in this specification are non- 315 normative, as are all sections explicitly marked non-normative. 316 Everything else in this specification is normative. 318 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 319 "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this 320 document are to be interpreted as described in RFC 2119 [RFC2119]. 322 Requirements phrased in the imperative as part of algorithms (such as 323 "strip any leading space characters" or "return false and abort these 324 steps") are to be interpreted with the meaning of the key word 325 ("MUST", "SHOULD", "MAY", etc.) used in introducing the algorithm. 327 Conformance requirements phrased as algorithms or specific steps MAY 328 be implemented in any manner, so long as the end result is 329 equivalent. 331 2.1. Terminology and Other Conventions 333 Key terms such as named algorithms or definitions are indicated like 334 _this_. 336 3. Realms, Sessions and Transports 338 A _Realm_ is a WAMP routing and administrative domain, optionally 339 protected by authentication and authorization. -- extend -- 341 A _Session_ is a transient conversation between two _Peers_ attached 342 to a _Realm_ and running over a _Transport_. 344 A _Transport_ connects two WAMP _Peers_ and provides a channel over 345 which WAMP messages for a WAMP _Session_ can flow in both directions. 347 WAMP can run over any _transport_ which is message-based, 348 bidirectional, reliable and ordered. 350 The default transport for WAMP is WebSocket [RFC6455], where WAMP is 351 an officially registered [1] subprotocol. 353 4. Peers and Roles 355 A WAMP _Session_ connects two _Peers_, a _Client_ and a _Router_. 356 Each WAMP _Peer_ can implement one or more roles. 358 A _Client_ can implement any combination of the _Roles_: 360 o _Callee_ 362 o _Caller_ 364 o _Publisher_ 366 o _Subscriber_ 368 and a _Router_ can implement either or both of the _Roles_: 370 o _Dealer_ 372 o _Broker_ 374 This document describes WAMP as in client-to-router communication. 375 Direct client-to-client communication is not supported by WAMP. 376 Router-to-router communication MAY be defined by a specific router 377 implementation. 379 4.1. Symmetric Messaging 381 It is important to note that though the establishment of a 382 _Transport_ might have a inherent asymmetry (like a TCP client 383 establishing a WebSocket connection to a server), and _Clients_ 384 establish WAMP sessions by attaching to _Realms_ on _Routers_, WAMP 385 itself is designed to be fully symmetric for application components. 387 After the transport and a session have been established, any 388 application component may act as _Caller_, _Callee_, _Publisher_ and 389 _Subscriber_ at the same time. And _Routers_ provide the fabric on 390 top of which WAMP runs a symmetric application messaging service. 392 4.2. Remote Procedure Call Roles 394 The Remote Procedure Call messaging pattern involves peers of three 395 different roles: 397 o _Callee (Client)_ 399 o _Caller (Client)_ 401 o _Dealer (Router)_ 403 A _Caller_ issues calls to remote procedures by providing the 404 procedure URI and any arguments for the call. The _Callee_ will 405 execute the procedure using the supplied arguments to the call and 406 return the result of the call to the _Caller_. 408 _Callees_ register procedures they provide with _Dealers_. _Callers_ 409 initiate procedure calls first to _Dealers_. _Dealers_ route calls 410 incoming from _Callers_ to _Callees_ implementing the procedure 411 called, and route call results back from _Callees_ to _Callers_. 413 The _Caller_ and _Callee_ will usually run application code, while 414 the _Dealer_ works as a generic router for remote procedure calls 415 decoupling _Callers_ and _Callees_. 417 4.3. Publish & Subscribe Roles 419 The Publish & Subscribe messaging pattern involves peers of three 420 different roles: 422 o _Subscriber (Client)_ 424 o _Publisher (Client)_ 426 o _Broker (Router)_ 428 A _Publishers_ publishes events to topics by providing the topic URI 429 and any payload for the event. _Subscribers_ of the topic will 430 receive the event together with the event payload. 432 _Subscribers_ subscribe to topics they are interested in with 433 _Brokers_. _Publishers_ initiate publication first at _Brokers_. 434 _Brokers_ route events incoming from _Publishers_ to _Subscribers_ 435 that are subscribed to respective topics. 437 The _Publisher_ and _Subscriber_ will usually run application code, 438 while the _Broker_ works as a generic router for events decoupling 439 _Publishers_ from _Subscribers_. 441 4.4. Peers with multiple Roles 443 Note that _Peers_ might implement more than one role: e.g. a _Peer_ 444 might act as _Caller_, _Publisher_ and _Subscriber_ at the same time. 445 Another _Peer_ might act as both a _Broker_ and a _Dealer_. 447 5. Building Blocks 449 WAMP is defined with respect to the following building blocks 451 1. Identifiers 453 2. Serializations 455 3. Transports 457 For each building block, WAMP only assumes a defined set of 458 requirements, which allows to run WAMP variants with different 459 concrete bindings. 461 5.1. Identifiers 463 5.1.1. URIs 465 WAMP needs to identify the following _persistent_ resources: 467 1. Topics 469 2. Procedures 471 3. Errors 473 These are identified in WAMP using _Uniform Resource Identifiers_ 474 (URIs) [RFC3986] that MUST be Unicode strings. 476 When using JSON as WAMP serialization format, URIs (as other 477 strings) are transmitted in UTF-8 [RFC3629] encoding. 479 _Examples_ 480 o "com.myapp.mytopic1" 482 o "com.myapp.myprocedure1" 484 o "com.myapp.myerror1" 486 The URIs are understood to form a single, global, hierarchical 487 namespace for WAMP. 489 The namespace is unified for topics, procedures and errors - these 490 different resource types do NOT have separate namespaces. 492 To avoid resource naming conflicts, the package naming convention 493 from Java is used, where URIs SHOULD begin with (reversed) domain 494 names owned by the organization defining the URI. 496 5.1.1.1. Relaxed/Loose URIs 498 URI components (the parts between two "."s, the head part up to the 499 first ".", the tail part after the last ".") MUST NOT contain a ".", 500 "#" or whitespace characters and MUST NOT be empty (zero-length 501 strings). 503 The restriction not to allow "." in component strings is due to 504 the fact that "." is used to separate components, and WAMP 505 associates semantics with resource hierarchies, such as in 506 pattern-based subscriptions that may be part of an Advanced 507 Profile. The restriction not to allow empty (zero-length) strings 508 as components is due to the fact that this may be used to denote 509 wildcard components with pattern-based subscriptions and 510 registrations in an Advanced Profile. The character "#" is not 511 allowed since this is reserved for internal use by _Dealers_ and 512 _Brokers_. 514 As an example, the following regular expression could be used in 515 Python to check URIs according to above rules: 517 518 ## loose URI check disallowing empty URI components 519 pattern = re.compile(r"^([^\s\.#]+\.)*([^\s\.#]+)$") 520 522 When empty URI components are allowed (this may the case for specific 523 messages that are part of an Advanced Profile), this following 524 regular expression can be used (shown used in Python): 526 527 ## loose URI check allowing empty URI components 528 pattern = re.compile(r"^(([^\s\.#]+\.)|\.)*([^\s\.#]+)?$") 529 531 5.1.1.2. Strict URIs 533 While the above rules MUST be followed, following a stricter URI rule 534 is recommended: URI components SHOULD only contain letters, digits 535 and "_". 537 As an example, the following regular expression could be used in 538 Python to check URIs according to the above rules: 540 541 ## strict URI check disallowing empty URI components 542 pattern = re.compile(r"^([0-9a-z_]+\.)*([0-9a-z_]+)$") 543 545 When empty URI components are allowed (this may the case for specific 546 messages that are part of an Advanced Profile), the following regular 547 expression can be used (shown in Python): 549 550 ## strict URI check allowing empty URI components 551 pattern = re.compile(r"^(([0-9a-z_]+\.)|\.)*([0-9a-z_]+)?$") 552 554 Following the suggested regular expression will make URI 555 components valid identifiers in most languages (modulo URIs 556 starting with a digit and language keywords) and the use of lower- 557 case only will make those identifiers unique in languages that 558 have case-insensitive identifiers. Following this suggestion can 559 allow implementations to map topics, procedures and errors to the 560 language environment in a completely transparent way. 562 5.1.1.3. Reserved URIs 564 Further, application URIs MUST NOT use "wamp" as a first URI 565 component, since this is reserved for URIs predefined with the WAMP 566 protocol itself. 568 _Examples_ 570 o "wamp.error.not_authorized" 572 o "wamp.error.procedure_already_exists" 574 5.1.2. IDs 576 WAMP needs to identify the following ephemeral entities each in the 577 scope noted: 579 1. Sessions (_global scope_) 581 2. Publications (_global scope_) 583 3. Subscriptions (_router scope_) 585 4. Registrations (_router scope_) 587 5. Requests (_session scope_) 589 These are identified in WAMP using IDs that are integers between 590 (inclusive) *0* and *2^53* (9007199254740992): 592 o IDs in the _global scope_ MUST be drawn _randomly_ from a _uniform 593 distribution_ over the complete range [0, 2^53] 595 o IDs in the _router scope_ can be chosen freely by the specific 596 router implementation 598 o IDs in the _session scope_ SHOULD be incremented by 1 beginning 599 with 1 (for each direction - _Client-to-Router_ and _Router-to- 600 Client_) 602 The reason to choose the specific upper bound is that 2^53 is the 603 largest integer such that this integer and _all_ (positive) 604 smaller integers can be represented exactly in IEEE-754 doubles. 605 Some languages (e.g. JavaScript) use doubles as their sole number 606 type. Most languages do have signed and unsigned 64-bit integer 607 types that both can hold any value from the specified range. 609 The following is a complete list of usage of IDs in the three 610 categories for all WAMP messages. For a full definition of these see 611 Section 6. 613 5.1.2.1. Global Scope IDs 615 o "WELCOME.Session" 617 o "PUBLISHED.Publication" 619 o "EVENT.Publication" 621 5.1.2.2. Router Scope IDs 623 o "EVENT.Subscription" 625 o "SUBSCRIBED.Subscription" 627 o "REGISTERED.Registration" 629 o "UNSUBSCRIBE.Subscription" 631 o "UNREGISTER.Registration" 633 o "INVOCATION.Registration" 635 5.1.2.3. Session Scope IDs 637 o "ERROR.Request" 639 o "PUBLISH.Request" 641 o "PUBLISHED.Request" 643 o "SUBSCRIBE.Request" 645 o "SUBSCRIBED.Request" 647 o "UNSUBSCRIBE.Request" 649 o "UNSUBSCRIBED.Request" 651 o "CALL.Request" 653 o "CANCEL.Request" 655 o "RESULT.Request" 657 o "REGISTER.Request" 659 o "REGISTERED.Request" 661 o "UNREGISTER.Request" 663 o "UNREGISTERED.Request" 665 o "INVOCATION.Request" 667 o "INTERRUPT.Request" 668 o "YIELD.Request" 670 5.2. Serializations 672 WAMP is a message based protocol that requires serialization of 673 messages to octet sequences to be sent out on the wire. 675 A message _serialization_ format is assumed that (at least) provides 676 the following types: 678 o "integer" (non-negative) 680 o "string" (UTF-8 encoded Unicode) 682 o "bool" 684 o "list" 686 o "dict" (with string keys) 688 WAMP _itself_ only uses the above types, e.g. it does not use the 689 JSON data types "number" (non-integer) and "null". The 690 _application payloads_ transmitted by WAMP (e.g. in call arguments 691 or event payloads) may use other types a concrete serialization 692 format supports. 694 There is no required serialization or set of serializations for WAMP 695 implementations (but each implementation MUST, of course, implement 696 at least one serialization format). Routers SHOULD implement more 697 than one serialization format, enabling components using different 698 kinds of serializations to connect to each other. 700 WAMP defines two bindings for message _serialization_: 702 1. JSON 704 2. MsgPack 706 Other bindings for _serialization_ may be defined in future WAMP 707 versions. 709 5.2.1. JSON 711 With JSON serialization, each WAMP message is serialized according to 712 the JSON specification as described in RFC4627. 714 Further, binary data follows a convention for conversion to JSON 715 strings. For details see the Appendix. 717 5.2.2. MsgPack 719 With MsgPack serialization, each WAMP message is serialized according 720 to the MsgPack specification. 722 Version 5 or later of MsgPack MUST BE used, since this version is 723 able to differentiate between strings and binary values. 725 5.3. Transports 727 WAMP assumes a _transport_ with the following characteristics: 729 1. message-based 731 2. reliable 733 3. ordered 735 4. bidirectional (full-duplex) 737 There is no required transport or set of transports for WAMP 738 implementations (but each implementation MUST, of course, implement 739 at least one transport). Routers SHOULD implement more than one 740 transport, enabling components using different kinds of transports to 741 connect in an application. 743 5.3.1. WebSocket Transport 745 The default transport binding for WAMP is WebSocket. 747 As a default, WAMP messages are transmitted as WebSocket messages: 748 each WAMP message is transmitted as a separate WebSocket message (not 749 WebSocket frame). A *batched mode* where multiple WAMP messages are 750 transmitted via single WebSocket message may be defined as part of an 751 Advanced Profile. 753 The WAMP protocol MUST BE negotiated during the WebSocket opening 754 handshake between _Peers_ using the WebSocket subprotocol negotiation 755 mechanism. 757 WAMP uses the following WebSocket subprotocol identifiers for 758 unbatched modes: 760 o "wamp.2.json" 762 o "wamp.2.msgpack" 763 With "wamp.2.json", _all_ WebSocket messages MUST BE of type *text* 764 (UTF8 encoded payload) and use the JSON message serialization. 766 With "wamp.2.msgpack", _all_ WebSocket messages MUST BE of type 767 *binary* and use the MsgPack message serialization. 769 To avoid incompatibilities merely due to naming conflicts with 770 WebSocket subprotocol identifiers, implementers SHOULD register 771 identifiers for additional serialization formats with the official 772 WebSocket subprotocol registry. 774 5.3.2. Transport and Session Lifetime 776 WAMP implementations MAY choose to tie the lifetime of the underlying 777 transport connection for a WAMP connection to that of a WAMP session, 778 i.e. establish a new transport-layer connection as part of each new 779 session establishment. They MAY equally choose to allow re-use of a 780 transport connection, allowing subsequent WAMP sessions to be 781 established using the same transport connection. 783 The diagram below illustrates the full transport connection and 784 session lifecycle for an implementation which uses WebSocket over TCP 785 as the transport and allows the re-use of a transport connection. 787 ,------. ,------. 788 | Peer | | Peer | 789 `--+---' `--+---' 791 TCP established 792 |<----------------------------------------->| 793 | | 794 | TLS established | 795 |+<--------------------------------------->+| 796 |+ +| 797 |+ WebSocket established +| 798 |+|<------------------------------------->|+| 799 |+| |+| 800 |+| WAMP established |+| 801 |+|+<----------------------------------->+|+| 802 |+|+ +|+| 803 |+|+ +|+| 804 |+|+ WAMP closed +|+| 805 |+|+<----------------------------------->+|+| 806 |+| |+| 807 |+| |+| 808 |+| WAMP established |+| 809 |+|+<----------------------------------->+|+| 810 |+|+ +|+| 811 |+|+ +|+| 812 |+|+ WAMP closed +|+| 813 |+|+<----------------------------------->+|+| 814 |+| |+| 815 |+| WebSocket closed |+| 816 |+|<------------------------------------->|+| 817 |+ +| 818 |+ TLS closed +| 819 |+<--------------------------------------->+| 820 | | 821 | TCP closed | 822 |<----------------------------------------->| 824 ,--+---. ,--+---. 825 | Peer | | Peer | 826 `------' `------' 828 6. Messages 830 All WAMP messages are a "list" with a first element "MessageType" 831 followed by one or more message type specific elements: 833 [MessageType|integer, ... one or more message type specific 834 elements ...] 836 The notation "Element|type" denotes a message element named "Element" 837 of type "type", where "type" is one of 839 o "uri": a string URI as defined in Section 5.1.1 841 o "id": an integer ID as defined in Section 5.1.2 843 o "integer": a non-negative integer 845 o "string": a Unicode string, including the empty string 847 o "bool": a boolean value ("true" or "false") - integers MUST NOT be 848 used instead of boolean value 850 o "dict": a dictionary (map) where keys MUST be strings, keys MUST 851 be unique and serialization order is undefined (left to the 852 serializer being used) 854 o "list": a list (array) where items can be again any of this 855 enumeration 857 _Example_ 859 A "SUBSCRIBE" message has the following format 861 [SUBSCRIBE, Request|id, Options|dict, Topic|uri] 863 Here is an example message conforming to the above format 865 [32, 713845233, {}, "com.myapp.mytopic1"] 867 6.1. Extensibility 869 Some WAMP messages contain "Options|dict" or "Details|dict" elements. 870 This allows for future extensibility and implementations that only 871 provide subsets of functionality by ignoring unimplemented 872 attributes. Keys in "Options" and "Details" MUST be of type "string" 873 and MUST match the regular expression "[a-z][a-z0-9_]{2,}" for WAMP 874 _predefined_ keys. Implementations MAY use implementation-specific 875 keys that MUST match the regular expression "_[a-z0-9_]{3,}". 876 Attributes unknown to an implementation MUST be ignored. 878 6.2. No Polymorphism 880 For a given "MessageType" _and_ number of message elements the 881 expected types are uniquely defined. Hence there are no polymorphic 882 messages in WAMP. This leads to a message parsing and validation 883 control flow that is efficient, simple to implement and simple to 884 code for rigorous message format checking. 886 6.3. Structure 888 The _application_ payload (that is call arguments, call results, 889 event payload etc) is always at the end of the message element list. 890 The rationale is: _Brokers_ and _Dealers_ have no need to inspect 891 (parse) the application payload. Their business is call/event 892 routing. Having the application payload at the end of the list 893 allows _Brokers_ and _Dealers_ to skip parsing it altogether. This 894 can improve efficiency and performance. 896 6.4. Message Definitions 898 WAMP defines the following messages that are explained in detail in 899 the following sections. 901 The messages concerning the WAMP session itself are mandatory for all 902 _Peers_, i.e. a _Client_ MUST implement "HELLO", "ABORT" and 903 "GOODBYE", while a _Router_ MUST implement "WELCOME", "ABORT" and 904 "GOODBYE". 906 All other messages are mandatory _per role_, i.e. in an 907 implementation that only provides a _Client_ with the role of 908 _Publisher_ MUST additionally implement sending "PUBLISH" and 909 receiving "PUBLISHED" and "ERROR" messages. 911 6.4.1. Session Lifecycle 913 6.4.1.1. HELLO 915 Sent by a _Client_ to initiate opening of a WAMP session to a 916 _Router_ attaching to a _Realm_. 918 [HELLO, Realm|uri, Details|dict] 920 6.4.1.2. WELCOME 922 Sent by a _Router_ to accept a _Client_. The WAMP session is now 923 open. 925 [WELCOME, Session|id, Details|dict] 927 6.4.1.3. ABORT 929 Sent by a _Peer_ to abort the opening of a WAMP session. No response 930 is expected. 932 [ABORT, Details|dict, Reason|uri] 934 6.4.1.4. GOODBYE 936 Sent by a _Peer_ to close a previously opened WAMP session. Must be 937 echo'ed by the receiving _Peer_. 939 [GOODBYE, Details|dict, Reason|uri] 941 6.4.1.5. ERROR 943 Error reply sent by a _Peer_ as an error response to different kinds 944 of requests. 946 [ERROR, REQUEST.Type|int, REQUEST.Request|id, Details|dict, 947 Error|uri] 949 [ERROR, REQUEST.Type|int, REQUEST.Request|id, Details|dict, 950 Error|uri, Arguments|list] 952 [ERROR, REQUEST.Type|int, REQUEST.Request|id, Details|dict, 953 Error|uri, Arguments|list, ArgumentsKw|dict] 955 6.4.2. Publish & Subscribe 957 6.4.2.1. PUBLISH 959 Sent by a _Publisher_ to a _Broker_ to publish an event. 961 [PUBLISH, Request|id, Options|dict, Topic|uri] 963 [PUBLISH, Request|id, Options|dict, Topic|uri, 964 Arguments|list] 966 [PUBLISH, Request|id, Options|dict, Topic|uri, 967 Arguments|list, ArgumentsKw|dict] 969 6.4.2.2. PUBLISHED 971 Acknowledge sent by a _Broker_ to a _Publisher_ for acknowledged 972 publications. 974 [PUBLISHED, PUBLISH.Request|id, Publication|id] 976 6.4.2.3. SUBSCRIBE 978 Subscribe request sent by a _Subscriber_ to a _Broker_ to subscribe 979 to a topic. 981 [SUBSCRIBE, Request|id, Options|dict, Topic|uri] 983 6.4.2.4. SUBSCRIBED 985 Acknowledge sent by a _Broker_ to a _Subscriber_ to acknowledge a 986 subscription. 988 [SUBSCRIBED, SUBSCRIBE.Request|id, Subscription|id] 990 6.4.2.5. UNSUBSCRIBE 992 Unsubscribe request sent by a _Subscriber_ to a _Broker_ to 993 unsubscribe a subscription. 995 [UNSUBSCRIBE, Request|id, SUBSCRIBED.Subscription|id] 997 6.4.2.6. UNSUBSCRIBED 999 Acknowledge sent by a _Broker_ to a _Subscriber_ to acknowledge 1000 unsubscription. 1002 [UNSUBSCRIBED, UNSUBSCRIBE.Request|id] 1004 6.4.2.7. EVENT 1006 Event dispatched by _Broker_ to _Subscribers_ for subscriptions the 1007 event was matching. 1009 [EVENT, SUBSCRIBED.Subscription|id, PUBLISHED.Publication|id, 1010 Details|dict] 1012 [EVENT, SUBSCRIBED.Subscription|id, PUBLISHED.Publication|id, 1013 Details|dict, PUBLISH.Arguments|list] 1015 [EVENT, SUBSCRIBED.Subscription|id, PUBLISHED.Publication|id, 1016 Details|dict, PUBLISH.Arguments|list, 1017 PUBLISH.ArgumentsKw|dict] 1019 An event is dispatched to a _Subscriber_ for a given 1020 "Subscription|id" _only once_. On the other hand, a _Subscriber_ 1021 that holds subscriptions with different "Subscription|id"s that 1022 all match a given event will receive the event on each matching 1023 subscription. 1025 6.4.3. Routed Remote Procedure Calls 1027 6.4.3.1. CALL 1029 Call as originally issued by the _Caller_ to the _Dealer_. 1031 [CALL, Request|id, Options|dict, Procedure|uri] 1033 [CALL, Request|id, Options|dict, Procedure|uri, Arguments|list] 1035 [CALL, Request|id, Options|dict, Procedure|uri, Arguments|list, 1036 ArgumentsKw|dict] 1038 6.4.3.2. RESULT 1040 Result of a call as returned by _Dealer_ to _Caller_. 1042 [RESULT, CALL.Request|id, Details|dict] 1044 [RESULT, CALL.Request|id, Details|dict, YIELD.Arguments|list] 1046 [RESULT, CALL.Request|id, Details|dict, YIELD.Arguments|list, 1047 YIELD.ArgumentsKw|dict] 1049 6.4.3.3. REGISTER 1051 A _Callees_ request to register an endpoint at a _Dealer_. 1053 [REGISTER, Request|id, Options|dict, Procedure|uri] 1055 6.4.3.4. REGISTERED 1057 Acknowledge sent by a _Dealer_ to a _Callee_ for successful 1058 registration. 1060 [REGISTERED, REGISTER.Request|id, Registration|id] 1062 6.4.3.5. UNREGISTER 1064 A _Callees_ request to unregister a previously established 1065 registration. 1067 [UNREGISTER, Request|id, REGISTERED.Registration|id] 1069 6.4.3.6. UNREGISTERED 1071 Acknowledge sent by a _Dealer_ to a _Callee_ for successful 1072 unregistration. 1074 [UNREGISTERED, UNREGISTER.Request|id] 1076 6.4.3.7. INVOCATION 1078 Actual invocation of an endpoint sent by _Dealer_ to a _Callee_. 1080 [INVOCATION, Request|id, REGISTERED.Registration|id, 1081 Details|dict] 1083 [INVOCATION, Request|id, REGISTERED.Registration|id, 1084 Details|dict, C* Arguments|list] 1086 [INVOCATION, Request|id, REGISTERED.Registration|id, 1087 Details|dict, CALL.Arguments|list, CALL.ArgumentsKw|dict] 1089 6.4.3.8. YIELD 1091 Actual yield from an endpoint sent by a _Callee_ to _Dealer_. 1093 [YIELD, INVOCATION.Request|id, Options|dict] 1095 [YIELD, INVOCATION.Request|id, Options|dict, Arguments|list] 1097 [YIELD, INVOCATION.Request|id, Options|dict, Arguments|list, 1098 ArgumentsKw|dict] 1100 6.5. Message Codes and Direction 1102 The following table lists the message type code for *all 25 messages 1103 defined in the WAMP basic profile* and their direction between peer 1104 roles. 1106 Reserved codes may be used to identify additional message types in 1107 future standards documents. 1109 "Tx" indicates the message is sent by the respective role, and 1110 "Rx" indicates the message is received by the respective role. 1112 +-----+----------------+------+------+------+------+-------+--------+ 1113 | Cod | Message | Pub | Brk | Subs | Calr | Dealr | Callee | 1114 +-----+----------------+------+------+------+------+-------+--------+ 1115 | 1 | "HELLO" | Tx | Rx | Tx | Tx | Rx | Tx | 1116 | 2 | "WELCOME" | Rx | Tx | Rx | Rx | Tx | Rx | 1117 | 3 | "ABORT" | Rx | TxRx | Rx | Rx | TxRx | Rx | 1118 | 6 | "GOODBYE" | TxRx | TxRx | TxRx | TxRx | TxRx | TxRx | 1119 | | | | | | | | | 1120 | 8 | "ERROR" | Rx | Tx | Rx | Rx | TxRx | TxRx | 1121 | | | | | | | | | 1122 | 16 | "PUBLISH" | Tx | Rx | | | | | 1123 | 17 | "PUBLISHED" | Rx | Tx | | | | | 1124 | | | | | | | | | 1125 | 32 | "SUBSCRIBE" | | Rx | Tx | | | | 1126 | 33 | "SUBSCRIBED" | | Tx | Rx | | | | 1127 | 34 | "UNSUBSCRIBE" | | Rx | Tx | | | | 1128 | 35 | "UNSUBSCRIBED" | | Tx | Rx | | | | 1129 | 36 | "EVENT" | | Tx | Rx | | | | 1130 | | | | | | | | | 1131 | 48 | "CALL" | | | | Tx | Rx | | 1132 | 50 | "RESULT" | | | | Rx | Tx | | 1133 | | | | | | | | | 1134 | 64 | "REGISTER" | | | | | Rx | Tx | 1135 | 65 | "REGISTERED" | | | | | Tx | Rx | 1136 | 66 | "UNREGISTER" | | | | | Rx | Tx | 1137 | 67 | "UNREGISTERED" | | | | | Tx | Rx | 1138 | 68 | "INVOCATION" | | | | | Tx | Rx | 1139 | 70 | "YIELD" | | | | | Rx | Tx | 1140 +-----+----------------+------+------+------+------+-------+--------+ 1142 6.6. Extension Messages 1144 WAMP uses type codes from the core range [0, 255]. Implementations 1145 MAY define and use implementation specific messages with message type 1146 codes from the extension message range [256, 1023]. For example, a 1147 router MAY implement router-to-router communication by using 1148 extension messages. 1150 6.7. Empty Arguments and Keyword Arguments 1152 Implementations SHOULD avoid sending empty "Arguments" lists. 1154 E.g. a "CALL" message 1156 [CALL, Request|id, Options|dict, Procedure|uri, 1157 Arguments|list] 1159 where "Arguments == []" SHOULD be avoided, and instead 1161 [CALL, Request|id, Options|dict, Procedure|uri] 1163 SHOULD be sent. 1165 Implementations SHOULD avoid sending empty "ArgumentsKw" 1166 dictionaries. 1168 E.g. a "CALL" message 1170 [CALL, Request|id, Options|dict, Procedure|uri, 1171 Arguments|list, ArgumentsKw|dict] 1173 where "ArgumentsKw == {}" SHOULD be avoided, and instead 1175 [CALL, Request|id, Options|dict, Procedure|uri, 1176 Arguments|list] 1178 SHOULD be sent when "Arguments" is non-empty. 1180 7. Sessions 1182 The message flow between _Clients_ and _Routers_ for opening and 1183 closing WAMP sessions involves the following messages: 1185 1. "HELLO" 1187 2. "WELCOME" 1189 3. "ABORT" 1191 4. "GOODBYE" 1193 7.1. Session Establishment 1195 7.1.1. HELLO 1197 After the underlying transport has been established, the opening of a 1198 WAMP session is initiated by the _Client_ sending a "HELLO" message 1199 to the _Router_ 1201 [HELLO, Realm|uri, Details|dict] 1203 where 1205 o "Realm" is a string identifying the realm this session should 1206 attach to 1208 o "Details" is a dictionary that allows to provide additional 1209 opening information (see below). 1211 The "HELLO" message MUST be the very first message sent by the 1212 _Client_ after the transport has been established. 1214 In the WAMP Basic Profile without session authentication the _Router_ 1215 will reply with a "WELCOME" or "ABORT" message. 1217 ,------. ,------. 1218 |Client| |Router| 1219 `--+---' `--+---' 1220 | HELLO | 1221 | ----------------> 1222 | | 1223 | WELCOME | 1224 | <---------------- 1225 ,--+---. ,--+---. 1226 |Client| |Router| 1227 `------' `------' 1229 A WAMP session starts its lifetime when the _Router_ has sent a 1230 "WELCOME" message to the _Client_, and ends when the underlying 1231 transport closes or when the session is closed explicitly by either 1232 peer sending the "GOODBYE" message (see below). 1234 It is a protocol error to receive a second "HELLO" message during the 1235 lifetime of the session and the _Peer_ must fail the session if that 1236 happens. 1238 7.1.1.1. Client: Role and Feature Announcement 1240 WAMP uses _Role & Feature announcement_ instead of _protocol 1241 versioning_ to allow 1243 o implementations only supporting subsets of functionality 1245 o future extensibility 1247 A _Client_ must announce the *roles* it supports via 1248 "Hello.Details.roles|dict", with a key mapping to a 1249 "Hello.Details.roles.|dict" where "" can be: 1251 o "publisher" 1253 o "subscriber" 1255 o "caller" 1256 o "callee" 1258 A _Client_ can support any combination of the above roles but must 1259 support at least one role. 1261 The "|dict" is a dictionary describing *features* supported by 1262 the peer for that role. 1264 This is empty for WAMP Basic Profile implementations, but may be used 1265 by implementations implementing parts of a future WAMP Advanced 1266 Profile to list the specific set of features they support. 1268 _Example: A Client that implements the Publisher and Subscriber roles 1269 of the WAMP Basic Profile._ 1271 [1, "somerealm", { 1272 "roles": { 1273 "publisher": {}, 1274 "subscriber": {} 1275 } 1276 }] 1278 7.1.2. WELCOME 1280 A _Router_ completes the opening of a WAMP session by sending a 1281 "WELCOME" reply message to the _Client_. 1283 [WELCOME, Session|id, Details|dict] 1285 where 1287 o "Session" MUST be a randomly generated ID specific to the WAMP 1288 session. This applies for the lifetime of the session. 1290 o "Details" is a dictionary that allows to provide additional 1291 information regarding the open session (see below). 1293 In the WAMP Basic Profile without session authentication, a "WELCOME" 1294 message is the first message sent by the _Router_, directly in 1295 response to a "HELLO" message received from the _Client_. Extensions 1296 in an Advanced Profile may include intermediate steps and messages 1297 for authentication. 1299 Note. The behavior if a requested "Realm" does not presently 1300 exist is router-specific. A router may e.g. automatically create 1301 the realm, or deny the establishment of the session with a "ABORT" 1302 reply message. 1304 7.1.2.1. Router: Role and Feature Announcement 1306 Similar to a _Client_ announcing _Roles_ and _Features_ supported in 1307 the `"HELLO" message, a _Router_ announces its supported _Roles_ and 1308 _Features_ in the "WELCOME" message. 1310 A _Router_ MUST announce the *roles* it supports via 1311 "Welcome.Details.roles|dict", with a key mapping to a 1312 "Welcome.Details.roles.|dict" where "" can be: 1314 o "broker" 1316 o "dealer" 1318 A _Router_ must support at least one role, and MAY support both 1319 roles. 1321 The "|dict" is a dictionary describing *features* supported by 1322 the peer for that role. With WAMP Basic Profile implementations, 1323 this will be empty, but may be used by implementations implementing 1324 parts of a future WAMP Advanced Profile to list the specific set of 1325 features they support 1327 _Example: A Router implementing the Broker role of the WAMP Basic 1328 Profile._ 1330 [2, 9129137332, { 1331 "roles": { 1332 "broker": {} 1333 } 1334 }] 1336 7.1.3. ABORT 1338 Both the _Router_ and the _Client_ may abort the opening of a WAMP 1339 session by sending an "ABORT" message. 1341 [ABORT, Details|dict, Reason|uri] 1343 where 1345 o "Reason" MUST be an URI. 1347 o "Details" MUST be a dictionary that allows to provide additional, 1348 optional closing information (see below). 1350 No response to an "ABORT" message is expected. 1352 ,------. ,------. 1353 |Client| |Router| 1354 `--+---' `--+---' 1355 | HELLO | 1356 | ----------------> 1357 | | 1358 | ABORT | 1359 | <---------------- 1360 ,--+---. ,--+---. 1361 |Client| |Router| 1362 `------' `------' 1364 _Example_ 1366 [3, {"message": "The realm does not exist."}, 1367 "wamp.error.no_such_realm"] 1369 7.2. Session Closing 1371 A WAMP session starts its lifetime with the _Router_ sending a 1372 "WELCOME" message to the _Client_ and ends when the underlying 1373 transport disappears or when the WAMP session is closed explicitly by 1374 a "GOODBYE" message sent by one _Peer_ and a "GOODBYE" message sent 1375 from the other _Peer_ in response. 1377 [GOODBYE, Details|dict, Reason|uri] 1379 where 1381 o "Reason" MUST be an URI. 1383 o "Details" MUST be a dictionary that allows to provide additional, 1384 optional closing information (see below). 1386 ,------. ,------. 1387 |Client| |Router| 1388 `--+---' `--+---' 1389 | GOODBYE | 1390 | ----------------> 1391 | | 1392 | GOODBYE | 1393 | <---------------- 1394 ,--+---. ,--+---. 1395 |Client| |Router| 1396 `------' `------' 1397 ,------. ,------. 1398 |Client| |Router| 1399 `--+---' `--+---' 1400 | GOODBYE | 1401 | <---------------- 1402 | | 1403 | GOODBYE | 1404 | ----------------> 1405 ,--+---. ,--+---. 1406 |Client| |Router| 1407 `------' `------' 1409 _Example_. One _Peer_ initiates closing 1411 [6, {"message": "The host is shutting down now."}, 1412 "wamp.error.system_shutdown"] 1414 and the other peer replies 1416 [6, {}, "wamp.error.goodbye_and_out"] 1418 _Example_. One _Peer_ initiates closing 1420 [6, {}, "wamp.error.close_realm"] 1422 and the other peer replies 1424 [6, {}, "wamp.error.goodbye_and_out"] 1426 7.2.1. Difference between ABORT and GOODBYE 1428 The differences between "ABORT" and "GOODBYE" messages are: 1430 1. "ABORT" gets sent only _before_ a _Session_ is established, while 1431 "GOODBYE" is sent only _after_ a _Session_ is already 1432 established. 1434 2. "ABORT" is never replied to by a _Peer_, whereas "GOODBYE" must 1435 be replied to by the receiving _Peer_ 1437 Though "ABORT" and "GOODBYE" are structurally identical, using 1438 different message types serves to reduce overloaded meaning of 1439 messages and simplify message handling code. 1441 7.3. Agent Identification 1443 When a software agent operates in a network protocol, it often 1444 identifies itself, its application type, operating system, software 1445 vendor, or software revision, by submitting a characteristic 1446 identification string to its operating peer. 1448 Similar to what browsers do with the "User-Agent" HTTP header, both 1449 the "HELLO" and the "WELCOME" message MAY disclose the WAMP 1450 implementation in use to its peer: 1452 HELLO.Details.agent|string 1454 and 1456 WELCOME.Details.agent|string 1458 _Example: A Client "HELLO" message._ 1460 [1, "somerealm", { 1461 "agent": "AutobahnJS-0.9.14", 1462 "roles": { 1463 "subscriber": {}, 1464 "publisher": {} 1465 } 1466 }] 1468 _Example: A Router "WELCOME" message._ 1470 [2, 9129137332, { 1471 "agent": "Crossbar.io-0.10.11", 1472 "roles": { 1473 "broker": {} 1474 } 1475 }] 1477 8. Publish and Subscribe 1479 All of the following features for Publish & Subscribe are mandatory 1480 for WAMP Basic Profile implementations supporting the respective 1481 roles, i.e. _Publisher_, _Subscriber_ and _Dealer_. 1483 8.1. Subscribing and Unsubscribing 1485 The message flow between _Clients_ implementing the role of 1486 _Subscriber_ and _Routers_ implementing the role of _Broker_ for 1487 subscribing and unsubscribing involves the following messages: 1489 1. "SUBSCRIBE" 1491 2. "SUBSCRIBED" 1493 3. "UNSUBSCRIBE" 1495 4. "UNSUBSCRIBED" 1497 5. "ERROR" 1499 ,---------. ,------. ,----------. 1500 |Publisher| |Broker| |Subscriber| 1501 `----+----' `--+---' `----+-----' 1502 | | | 1503 | | | 1504 | | SUBSCRIBE | 1505 | | <--------------------- 1506 | | | 1507 | | SUBSCRIBED or ERROR | 1508 | | ---------------------> 1509 | | | 1510 | | | 1511 | | | 1512 | | | 1513 | | UNSUBSCRIBE | 1514 | | <--------------------- 1515 | | | 1516 | | UNSUBSCRIBED or ERROR| 1517 | | ---------------------> 1518 ,----+----. ,--+---. ,----+-----. 1519 |Publisher| |Broker| |Subscriber| 1520 `---------' `------' `----------' 1522 A _Subscriber_ may subscribe to zero, one or more topics, and a 1523 _Publisher_ publishes to topics without knowledge of subscribers. 1525 Upon subscribing to a topic via the "SUBSCRIBE" message, a 1526 _Subscriber_ will receive any future events published to the 1527 respective topic by _Publishers_, and will receive those events 1528 asynchronously. 1530 A subscription lasts for the duration of a session, unless a 1531 _Subscriber_ opts out from a previously established subscription via 1532 the "UNSUBSCRIBE" message. 1534 A _Subscriber_ may have more than one event handler attached to 1535 the same subscription. This can be implemented in different ways: 1536 a) a _Subscriber_ can recognize itself that it is already 1537 subscribed and just attach another handler to the subscription 1538 for incoming events, b) or it can send a new "SUBSCRIBE" message 1539 to broker (as it would be first) and upon receiving a 1540 "SUBSCRIBED.Subscription|id" it already knows about, attach the 1541 handler to the existing subscription 1543 8.1.1. SUBSCRIBE 1545 A _Subscriber_ communicates its interest in a topic to a _Broker_ by 1546 sending a "SUBSCRIBE" message: 1548 [SUBSCRIBE, Request|id, Options|dict, Topic|uri] 1550 where 1552 o "Request" MUST be a random, ephemeral ID chosen by the 1553 _Subscriber_ and used to correlate the _Broker's_ response with 1554 the request. 1556 o "Options" MUST be a dictionary that allows to provide additional 1557 subscription request details in a extensible way. This is 1558 described further below. 1560 o "Topic" is the topic the _Subscriber_ wants to subscribe to and 1561 MUST be an URI. 1563 _Example_ 1565 [32, 713845233, {}, "com.myapp.mytopic1"] 1567 A _Broker_, receiving a "SUBSCRIBE" message, can fullfill or reject 1568 the subscription, so it answers with "SUBSCRIBED" or "ERROR" 1569 messages. 1571 8.1.2. SUBSCRIBED 1573 If the _Broker_ is able to fulfill and allow the subscription, it 1574 answers by sending a "SUBSCRIBED" message to the _Subscriber_ 1576 [SUBSCRIBED, SUBSCRIBE.Request|id, Subscription|id] 1578 where 1580 o "SUBSCRIBE.Request" MUST be the ID from the original request. 1582 o "Subscription" MUST be an ID chosen by the _Broker_ for the 1583 subscription. 1585 _Example_ 1587 [33, 713845233, 5512315355] 1589 Note. The "Subscription" ID chosen by the broker need not be 1590 unique to the subscription of a single _Subscriber_, but may be 1591 assigned to the "Topic", or the combination of the "Topic" and 1592 some or all "Options", such as the topic pattern matching method 1593 to be used. Then this ID may be sent to all _Subscribers_ for the 1594 "Topic" or "Topic" / "Options" combination. This allows the 1595 _Broker_ to serialize an event to be delivered only once for all 1596 actual receivers of the event. 1598 In case of receiving a "SUBSCRIBE" message from the same 1599 _Subscriber_ and to already subscribed topic, _Broker_ should 1600 answer with "SUBSCRIBED" message, containing the existing 1601 "Subscription|id". 1603 8.1.3. Subscribe ERROR 1605 When the request for subscription cannot be fulfilled by the 1606 _Broker_, the _Broker_ sends back an "ERROR" message to the 1607 _Subscriber_ 1609 [ERROR, SUBSCRIBE, SUBSCRIBE.Request|id, Details|dict, 1610 Error|uri] 1612 where 1614 o "SUBSCRIBE.Request" MUST be the ID from the original request. 1616 o "Error" MUST be an URI that gives the error of why the request 1617 could not be fulfilled. 1619 _Example_ 1621 [8, 32, 713845233, {}, "wamp.error.not_authorized"] 1623 8.1.4. UNSUBSCRIBE 1625 When a _Subscriber_ is no longer interested in receiving events for a 1626 subscription it sends an "UNSUBSCRIBE" message 1628 [UNSUBSCRIBE, Request|id, SUBSCRIBED.Subscription|id] 1630 where 1631 o "Request" MUST be a random, ephemeral ID chosen by the 1632 _Subscriber_ and used to correlate the _Broker's_ response with 1633 the request. 1635 o "SUBSCRIBED.Subscription" MUST be the ID for the subscription to 1636 unsubscribe from, originally handed out by the _Broker_ to the 1637 _Subscriber_. 1639 _Example_ 1641 [34, 85346237, 5512315355] 1643 8.1.5. UNSUBSCRIBED 1645 Upon successful unsubscription, the _Broker_ sends an "UNSUBSCRIBED" 1646 message to the _Subscriber_ 1648 [UNSUBSCRIBED, UNSUBSCRIBE.Request|id] 1650 where 1652 o "UNSUBSCRIBE.Request" MUST be the ID from the original request. 1654 _Example_ 1656 [35, 85346237] 1658 8.1.6. Unsubscribe ERROR 1660 When the request fails, the _Broker_ sends an "ERROR" 1662 [ERROR, UNSUBSCRIBE, UNSUBSCRIBE.Request|id, Details|dict, 1663 Error|uri] 1665 where 1667 o "UNSUBSCRIBE.Request" MUST be the ID from the original request. 1669 o "Error" MUST be an URI that gives the error of why the request 1670 could not be fulfilled. 1672 _Example_ 1674 [8, 34, 85346237, {}, "wamp.error.no_such_subscription"] 1676 8.2. Publishing and Events 1678 The message flow between _Publishers_, a _Broker_ and _Subscribers_ 1679 for publishing to topics and dispatching events involves the 1680 following messages: 1682 1. "PUBLISH" 1684 2. "PUBLISHED" 1686 3. "EVENT" 1688 4. "ERROR" 1690 ,---------. ,------. ,----------. 1691 |Publisher| |Broker| |Subscriber| 1692 `----+----' `--+---' `----+-----' 1693 | PUBLISH | | 1694 |------------------> | 1695 | | | 1696 |PUBLISHED or ERROR| | 1697 |<------------------ | 1698 | | | 1699 | | EVENT | 1700 | | ------------------> 1701 ,----+----. ,--+---. ,----+-----. 1702 |Publisher| |Broker| |Subscriber| 1703 `---------' `------' `----------' 1705 8.2.1. PUBLISH 1707 When a _Publisher_ requests to publish an event to some topic, it 1708 sends a "PUBLISH" message to a _Broker_: 1710 [PUBLISH, Request|id, Options|dict, Topic|uri] 1712 or 1714 [PUBLISH, Request|id, Options|dict, Topic|uri, Arguments|list] 1716 or 1718 [PUBLISH, Request|id, Options|dict, Topic|uri, Arguments|list, 1719 ArgumentsKw|dict] 1721 where 1722 o "Request" is a random, ephemeral ID chosen by the _Publisher_ and 1723 used to correlate the _Broker's_ response with the request. 1725 o "Options" is a dictionary that allows to provide additional 1726 publication request details in an extensible way. This is 1727 described further below. 1729 o "Topic" is the topic published to. 1731 o "Arguments" is a list of application-level event payload elements. 1732 The list may be of zero length. 1734 o "ArgumentsKw" is an optional dictionary containing application- 1735 level event payload, provided as keyword arguments. The 1736 dictionary may be empty. 1738 If the _Broker_ is able to fulfill and allowing the publication, the 1739 _Broker_ will send the event to all current _Subscribers_ of the 1740 topic of the published event. 1742 By default, publications are unacknowledged, and the _Broker_ will 1743 not respond, whether the publication was successful indeed or not. 1744 This behavior can be changed with the option 1745 "PUBLISH.Options.acknowledge|bool" (see below). 1747 _Example_ 1749 [16, 239714735, {}, "com.myapp.mytopic1"] 1751 _Example_ 1753 [16, 239714735, {}, "com.myapp.mytopic1", ["Hello, world!"]] 1755 _Example_ 1757 [16, 239714735, {}, "com.myapp.mytopic1", [], {"color": "orange", 1758 "sizes": [23, 42, 7]}] 1760 8.2.2. PUBLISHED 1762 If the _Broker_ is able to fulfill and allowing the publication, and 1763 "PUBLISH.Options.acknowledge == true", the _Broker_ replies by 1764 sending a "PUBLISHED" message to the _Publisher_: 1766 [PUBLISHED, PUBLISH.Request|id, Publication|id] 1768 where 1769 o "PUBLISH.Request" is the ID from the original publication request. 1771 o "Publication" is a ID chosen by the Broker for the publication. 1773 _Example_ 1775 [17, 239714735, 4429313566] 1777 8.2.3. Publish ERROR 1779 When the request for publication cannot be fulfilled by the _Broker_, 1780 and "PUBLISH.Options.acknowledge == true", the _Broker_ sends back an 1781 "ERROR" message to the _Publisher_ 1783 [ERROR, PUBLISH, PUBLISH.Request|id, Details|dict, Error|uri] 1785 where 1787 o "PUBLISH.Request" is the ID from the original publication request. 1789 o "Error" is an URI that gives the error of why the request could 1790 not be fulfilled. 1792 _Example_ 1794 [8, 16, 239714735, {}, "wamp.error.not_authorized"] 1796 8.2.4. EVENT 1798 When a publication is successful and a _Broker_ dispatches the event, 1799 it determines a list of receivers for the event based on 1800 _Subscribers_ for the topic published to and, possibly, other 1801 information in the event. 1803 Note that the _Publisher_ of an event will never receive the 1804 published event even if the _Publisher_ is also a _Subscriber_ of the 1805 topic published to. 1807 WAMP Advanced Profile provides options for more detailed control 1808 over publication. 1810 When a _Subscriber_ is deemed to be a receiver, the _Broker_ sends 1811 the _Subscriber_ an "EVENT" message: 1813 [EVENT, SUBSCRIBED.Subscription|id, PUBLISHED.Publication|id, 1814 Details|dict] 1816 or 1818 [EVENT, SUBSCRIBED.Subscription|id, PUBLISHED.Publication|id, 1819 Details|dict, PUBLISH.Arguments|list] 1821 or 1823 [EVENT, SUBSCRIBED.Subscription|id, PUBLISHED.Publication|id, 1824 Details|dict, PUBLISH.Arguments|list, PUBLISH.ArgumentKw|dict] 1826 where 1828 o "SUBSCRIBED.Subscription" is the ID for the subscription under 1829 which the _Subscriber_ receives the event - the ID for the 1830 subscription originally handed out by the _Broker_ to the 1831 _Subscriber_. 1833 o "PUBLISHED.Publication" is the ID of the publication of the 1834 published event. 1836 o "Details" is a dictionary that allows the _Broker_ to provide 1837 additional event details in a extensible way. This is described 1838 further below. 1840 o "PUBLISH.Arguments" is the application-level event payload that 1841 was provided with the original publication request. 1843 o "PUBLISH.ArgumentKw" is the application-level event payload that 1844 was provided with the original publication request. 1846 _Example_ 1848 [36, 5512315355, 4429313566, {}] 1850 _Example_ 1852 [36, 5512315355, 4429313566, {}, ["Hello, world!"]] 1854 _Example_ 1856 [36, 5512315355, 4429313566, {}, [], {"color": "orange", 1857 "sizes": [23, 42, 7]}] 1859 9. Remote Procedure Calls 1861 All of the following features for Remote Procedure Calls are 1862 mandatory for WAMP Basic Profile implementations supporting the 1863 respective roles. 1865 9.1. Registering and Unregistering 1867 The message flow between _Callees_ and a _Dealer_ for registering and 1868 unregistering endpoints to be called over RPC involves the following 1869 messages: 1871 1. "REGISTER" 1873 2. "REGISTERED" 1875 3. "UNREGISTER" 1877 4. "UNREGISTERED" 1879 5. "ERROR" 1881 ,------. ,------. ,------. 1882 |Caller| |Dealer| |Callee| 1883 `--+---' `--+---' `--+---' 1884 | | | 1885 | | | 1886 | | REGISTER | 1887 | | <--------------------- 1888 | | | 1889 | | REGISTERED or ERROR | 1890 | | ---------------------> 1891 | | | 1892 | | | 1893 | | | 1894 | | | 1895 | | | 1896 | | UNREGISTER | 1897 | | <--------------------- 1898 | | | 1899 | | UNREGISTERED or ERROR| 1900 | | ---------------------> 1901 ,--+---. ,--+---. ,--+---. 1902 |Caller| |Dealer| |Callee| 1903 `------' `------' `------' 1905 9.1.1. REGISTER 1907 A _Callee_ announces the availability of an endpoint implementing a 1908 procedure with a _Dealer_ by sending a "REGISTER" message: 1910 [REGISTER, Request|id, Options|dict, Procedure|uri] 1912 where 1913 o "Request" is a random, ephemeral ID chosen by the _Callee_ and 1914 used to correlate the _Dealer's_ response with the request. 1916 o "Options" is a dictionary that allows to provide additional 1917 registration request details in a extensible way. This is 1918 described further below. 1920 o "Procedure"is the procedure the _Callee_ wants to register 1922 _Example_ 1924 [64, 25349185, {}, "com.myapp.myprocedure1"] 1926 9.1.2. REGISTERED 1928 If the _Dealer_ is able to fulfill and allowing the registration, it 1929 answers by sending a "REGISTERED" message to the "Callee": 1931 [REGISTERED, REGISTER.Request|id, Registration|id] 1933 where 1935 o "REGISTER.Request" is the ID from the original request. 1937 o "Registration" is an ID chosen by the _Dealer_ for the 1938 registration. 1940 _Example_ 1942 [65, 25349185, 2103333224] 1944 9.1.3. Register ERROR 1946 When the request for registration cannot be fulfilled by the 1947 _Dealer_, the _Dealer_ sends back an "ERROR" message to the _Callee_: 1949 [ERROR, REGISTER, REGISTER.Request|id, Details|dict, Error|uri] 1951 where 1953 o "REGISTER.Request" is the ID from the original request. 1955 o "Error" is an URI that gives the error of why the request could 1956 not be fulfilled. 1958 _Example_ 1960 [8, 64, 25349185, {}, "wamp.error.procedure_already_exists"] 1962 9.1.4. UNREGISTER 1964 When a _Callee_ is no longer willing to provide an implementation of 1965 the registered procedure, it sends an "UNREGISTER" message to the 1966 _Dealer_: 1968 [UNREGISTER, Request|id, REGISTERED.Registration|id] 1970 where 1972 o "Request" is a random, ephemeral ID chosen by the _Callee_ and 1973 used to correlate the _Dealer's_ response with the request. 1975 o "REGISTERED.Registration" is the ID for the registration to 1976 revoke, originally handed out by the _Dealer_ to the _Callee_. 1978 _Example_ 1980 [66, 788923562, 2103333224] 1982 9.1.5. UNREGISTERED 1984 Upon successful unregistration, the _Dealer_ sends an "UNREGISTERED" 1985 message to the _Callee_: 1987 [UNREGISTERED, UNREGISTER.Request|id] 1989 where 1991 o "UNREGISTER.Request" is the ID from the original request. 1993 _Example_ 1995 [67, 788923562] 1997 9.1.6. Unregister ERROR 1999 When the unregistration request fails, the _Dealer_ sends an "ERROR" 2000 message: 2002 [ERROR, UNREGISTER, UNREGISTER.Request|id, Details|dict, 2003 Error|uri] 2005 where 2007 o "UNREGISTER.Request" is the ID from the original request. 2009 o "Error" is an URI that gives the error of why the request could 2010 not be fulfilled. 2012 _Example_ 2014 [8, 66, 788923562, {}, "wamp.error.no_such_registration"] 2016 9.2. Calling and Invocations 2018 The message flow between _Callers_, a _Dealer_ and _Callees_ for 2019 calling procedures and invoking endpoints involves the following 2020 messages: 2022 1. "CALL" 2024 2. "RESULT" 2026 3. "INVOCATION" 2028 4. "YIELD" 2030 5. "ERROR" 2032 ,------. ,------. ,------. 2033 |Caller| |Dealer| |Callee| 2034 `--+---' `--+---' `--+---' 2035 | CALL | | 2036 | ----------------> | 2037 | | | 2038 | | INVOCATION | 2039 | | ----------------> 2040 | | | 2041 | | YIELD or ERROR | 2042 | | <---------------- 2043 | | | 2044 | RESULT or ERROR | | 2045 | <---------------- | 2046 ,--+---. ,--+---. ,--+---. 2047 |Caller| |Dealer| |Callee| 2048 `------' `------' `------' 2050 The execution of remote procedure calls is asynchronous, and there 2051 may be more than one call outstanding. A call is called outstanding 2052 (from the point of view of the _Caller_), when a (final) result or 2053 error has not yet been received by the _Caller_. 2055 9.2.1. CALL 2057 When a _Caller_ wishes to call a remote procedure, it sends a "CALL" 2058 message to a _Dealer_: 2060 [CALL, Request|id, Options|dict, Procedure|uri] 2062 or 2064 [CALL, Request|id, Options|dict, Procedure|uri, Arguments|list] 2066 or 2068 [CALL, Request|id, Options|dict, Procedure|uri, Arguments|list, 2069 ArgumentsKw|dict] 2071 where 2073 o "Request" is a random, ephemeral ID chosen by the _Caller_ and 2074 used to correlate the _Dealer's_ response with the request. 2076 o "Options" is a dictionary that allows to provide additional call 2077 request details in an extensible way. This is described further 2078 below. 2080 o "Procedure" is the URI of the procedure to be called. 2082 o "Arguments" is a list of positional call arguments (each of 2083 arbitrary type). The list may be of zero length. 2085 o "ArgumentsKw" is a dictionary of keyword call arguments (each of 2086 arbitrary type). The dictionary may be empty. 2088 _Example_ 2090 [48, 7814135, {}, "com.myapp.ping"] 2092 _Example_ 2094 [48, 7814135, {}, "com.myapp.echo", ["Hello, world!"]] 2096 _Example_ 2098 [48, 7814135, {}, "com.myapp.add2", [23, 7]] 2100 _Example_ 2102 [48, 7814135, {}, "com.myapp.user.new", ["johnny"], 2103 {"firstname": "John", "surname": "Doe"}] 2105 9.2.2. INVOCATION 2107 If the _Dealer_ is able to fulfill (mediate) the call and it allows 2108 the call, it sends a "INVOCATION" message to the respective _Callee_ 2109 implementing the procedure: 2111 [INVOCATION, Request|id, REGISTERED.Registration|id, 2112 Details|dict] 2114 or 2116 [INVOCATION, Request|id, REGISTERED.Registration|id, 2117 Details|dict, CALL.Arguments|list] 2119 or 2121 [INVOCATION, Request|id, REGISTERED.Registration|id, 2122 Details|dict, CALL.Arguments|list, CALL.ArgumentsKw|dict] 2124 where 2126 o "Request" is a random, ephemeral ID chosen by the _Dealer_ and 2127 used to correlate the _Callee's_ response with the request. 2129 o "REGISTERED.Registration" is the registration ID under which the 2130 procedure was registered at the _Dealer_. 2132 o "Details" is a dictionary that allows to provide additional 2133 invocation request details in an extensible way. This is 2134 described further below. 2136 o "CALL.Arguments" is the original list of positional call arguments 2137 as provided by the _Caller_. 2139 o "CALL.ArgumentsKw" is the original dictionary of keyword call 2140 arguments as provided by the _Caller_. 2142 _Example_ 2144 [68, 6131533, 9823526, {}] 2146 _Example_ 2148 [68, 6131533, 9823527, {}, ["Hello, world!"]] 2150 _Example_ 2152 [68, 6131533, 9823528, {}, [23, 7]] 2154 _Example_ 2156 [68, 6131533, 9823529, {}, ["johnny"], {"firstname": "John", 2157 "surname": "Doe"}] 2159 9.2.3. YIELD 2161 If the _Callee_ is able to successfully process and finish the 2162 execution of the call, it answers by sending a "YIELD" message to the 2163 _Dealer_: 2165 [YIELD, INVOCATION.Request|id, Options|dict] 2167 or 2169 [YIELD, INVOCATION.Request|id, Options|dict, Arguments|list] 2171 or 2173 [YIELD, INVOCATION.Request|id, Options|dict, Arguments|list, 2174 ArgumentsKw|dict] 2176 where 2178 o "INVOCATION.Request" is the ID from the original invocation 2179 request. 2181 o "Options"is a dictionary that allows to provide additional 2182 options. 2184 o "Arguments" is a list of positional result elements (each of 2185 arbitrary type). The list may be of zero length. 2187 o "ArgumentsKw" is a dictionary of keyword result elements (each of 2188 arbitrary type). The dictionary may be empty. 2190 _Example_ 2192 [70, 6131533, {}] 2194 _Example_ 2196 [70, 6131533, {}, ["Hello, world!"]] 2198 _Example_ 2200 [70, 6131533, {}, [30]] 2202 _Example_ 2204 [70, 6131533, {}, [], {"userid": 123, "karma": 10}] 2206 9.2.4. RESULT 2208 The _Dealer_ will then send a "RESULT" message to the original 2209 _Caller_: 2211 [RESULT, CALL.Request|id, Details|dict] 2213 or 2215 [RESULT, CALL.Request|id, Details|dict, YIELD.Arguments|list] 2217 or 2219 [RESULT, CALL.Request|id, Details|dict, YIELD.Arguments|list, 2220 YIELD.ArgumentsKw|dict] 2222 where 2224 o "CALL.Request" is the ID from the original call request. 2226 o "Details" is a dictionary of additional details. 2228 o "YIELD.Arguments" is the original list of positional result 2229 elements as returned by the _Callee_. 2231 o "YIELD.ArgumentsKw" is the original dictionary of keyword result 2232 elements as returned by the _Callee_. 2234 _Example_ 2236 [50, 7814135, {}] 2238 _Example_ 2240 [50, 7814135, {}, ["Hello, world!"]] 2242 _Example_ 2244 [50, 7814135, {}, [30]] 2246 _Example_ 2248 [50, 7814135, {}, [], {"userid": 123, "karma": 10}] 2250 9.2.5. Invocation ERROR 2252 If the _Callee_ is unable to process or finish the execution of the 2253 call, or the application code implementing the procedure raises an 2254 exception or otherwise runs into an error, the _Callee_ sends an 2255 "ERROR" message to the _Dealer_: 2257 [ERROR, INVOCATION, INVOCATION.Request|id, Details|dict, 2258 Error|uri] 2260 or 2262 [ERROR, INVOCATION, INVOCATION.Request|id, Details|dict, 2263 Error|uri, Arguments|list] 2265 or 2267 [ERROR, INVOCATION, INVOCATION.Request|id, Details|dict, 2268 Error|uri, Arguments|list, ArgumentsKw|dict] 2270 where 2272 o "INVOCATION.Request" is the ID from the original "INVOCATION" 2273 request previously sent by the _Dealer_ to the _Callee_. 2275 o "Details" is a dictionary with additional error details. 2277 o "Error" is an URI that identifies the error of why the request 2278 could not be fulfilled. 2280 o "Arguments" is a list containing arbitrary, application defined, 2281 positional error information. This will be forwarded by the 2282 _Dealer_ to the _Caller_ that initiated the call. 2284 o "ArgumentsKw" is a dictionary containing arbitrary, application 2285 defined, keyword-based error information. This will be forwarded 2286 by the _Dealer_ to the _Caller_ that initiated the call. 2288 _Example_ 2290 [8, 68, 6131533, {}, "com.myapp.error.object_write_protected", 2291 ["Object is write protected."], {"severity": 3}] 2293 9.2.6. Call ERROR 2295 The _Dealer_ will then send a "ERROR" message to the original 2296 _Caller_: 2298 [ERROR, CALL, CALL.Request|id, Details|dict, Error|uri] 2300 or 2302 [ERROR, CALL, CALL.Request|id, Details|dict, Error|uri, 2303 Arguments|list] 2305 or 2307 [ERROR, CALL, CALL.Request|id, Details|dict, Error|uri, 2308 Arguments|list, ArgumentsKw|dict] 2310 where 2312 o "CALL.Request" is the ID from the original "CALL" request sent by 2313 the _Caller_ to the _Dealer_. 2315 o "Details" is a dictionary with additional error details. 2317 o "Error" is an URI identifying the type of error as returned by the 2318 _Callee_ to the _Dealer_. 2320 o "Arguments" is a list containing the original error payload list 2321 as returned by the _Callee_ to the _Dealer_. 2323 o "ArgumentsKw" is a dictionary containing the original error 2324 payload dictionary as returned by the _Callee_ to the _Dealer_ 2326 _Example_ 2328 [8, 48, 7814135, {}, "com.myapp.error.object_write_protected", 2329 ["Object is write protected."], {"severity": 3}] 2331 If the original call already failed at the _Dealer_ *before* the call 2332 would have been forwarded to any _Callee_, the _Dealer_ will send an 2333 "ERROR" message to the _Caller_: 2335 [ERROR, CALL, CALL.Request|id, Details|dict, Error|uri] 2337 _Example_ 2339 [8, 48, 7814135, {}, "wamp.error.no_such_procedure"] 2341 9.3. Predefined URIs 2343 WAMP pre-defines the following error URIs as part of this Basic 2344 Profile, which cover the full set of error states. Additional error 2345 URIs may be defined as part of a future Advanced Profile to cover 2346 error states which may occur based on extensions of the protocol. 2348 o below has to be changed to state that for the given error state a 2349 party MUST send the specific error uri, e.g 2351 When a _Peer_ provides an incorrect URI for any URI-based attribute 2352 of a WAMP message (e.g. realm, topic), then the other _Peer_ has to 2353 respond with an "ERROR" message and give the following _Error URI_: 2355 wamp.error.invalid_uri 2357 9.4. Interaction 2359 _Peer_ provided an incorrect URI for any URI-based attribute of WAMP 2360 message, such as realm, topic or procedure 2362 wamp.error.invalid_uri 2364 A _Dealer_ could not perform a call, since no procedure is currently 2365 registered under the given URI. 2367 wamp.error.no_such_procedure 2369 A procedure could not be registered, since a procedure with the given 2370 URI is already registered. 2372 wamp.error.procedure_already_exists 2374 A _Dealer_ could not perform an unregister, since the given 2375 registration is not active. 2377 wamp.error.no_such_registration 2379 A _Broker_ could not perform an unsubscribe, since the given 2380 subscription is not active. 2382 wamp.error.no_such_subscription 2384 A call failed since the given argument types or values are not 2385 acceptable to the called procedure. In this case the _Callee_ may 2386 throw this error. Alternatively a _Router_ may throw this error if 2387 it performed _payload validation_ of a call, call result, call error 2388 or publish, and the payload did not conform to the requirements. 2390 wamp.error.invalid_argument 2392 9.4.1. Session Close 2394 The _Peer_ is shutting down completely - used as a "GOODBYE" (or 2395 "ABORT") reason. 2397 wamp.error.system_shutdown 2399 The _Peer_ want to leave the realm - used as a "GOODBYE" reason. 2401 wamp.error.close_realm 2403 A _Peer_ acknowledges ending of a session - used as a "GOODBYE" reply 2404 reason. 2406 wamp.error.goodbye_and_out 2408 9.5. Authorization 2410 A join, call, register, publish or subscribe failed, since the _Peer_ 2411 is not authorized to perform the operation. 2413 wamp.error.not_authorized 2415 A _Dealer_ or _Broker_ could not determine if the _Peer_ is 2416 authorized to perform a join, call, register, publish or subscribe, 2417 since the authorization operation _itself_ failed. E.g. a custom 2418 authorizer did run into an error. 2420 wamp.error.authorization_failed 2422 _Peer_ wanted to join a non-existing realm (and the _Router_ did not 2423 allow to auto-create the realm). 2425 wamp.error.no_such_realm 2427 A _Peer_ was to be authenticated under a Role that does not (or no 2428 longer) exists on the Router. For example, the _Peer_ was 2429 successfully authenticated, but the Role configured does not exists - 2430 hence there is some misconfiguration in the Router. 2432 wamp.error.no_such_role 2434 9.6. Ordering Guarantees 2436 All WAMP implementations, in particular _Routers_ MUST support the 2437 following ordering guarantees. 2439 A WAMP Advanced Profile may provide applications options to relax 2440 ordering guarantees, in particular with distributed calls. 2442 9.6.1. Publish & Subscribe Ordering 2444 Regarding *Publish & Subscribe*, the ordering guarantees are as 2445 follows: 2447 If _Subscriber A_ is subscribed to both *Topic 1* and *Topic 2*, and 2448 _Publisher B_ first publishes an *Event 1* to *Topic 1* and then an 2449 *Event 2* to *Topic 2*, then _Subscriber A_ will first receive *Event 2450 1* and then *Event 2*. This also holds if *Topic 1* and *Topic 2* are 2451 identical. 2453 In other words, WAMP guarantees ordering of events between any given 2454 _pair_ of _Publisher_ and _Subscriber_. 2456 Further, if _Subscriber A_ subscribes to *Topic 1*, the "SUBSCRIBED" 2457 message will be sent by the _Broker_ to _Subscriber A_ before any 2458 "EVENT" message for *Topic 1*. 2460 There is no guarantee regarding the order of return for multiple 2461 subsequent subscribe requests. A subscribe request might require the 2462 _Broker_ to do a time-consuming lookup in some database, whereas 2463 another subscribe request second might be permissible immediately. 2465 9.6.2. Remote Procedure Call Ordering 2467 Regarding *Remote Procedure Calls*, the ordering guarantees are as 2468 follows: 2470 If _Callee A_ has registered endpoints for both *Procedure 1* and 2471 *Procedure 2*, and _Caller B_ first issues a *Call 1* to *Procedure 2472 1* and then a *Call 2* to *Procedure 2*, and both calls are routed to 2473 _Callee A_, then _Callee A_ will first receive an invocation 2474 corresponding to *Call 1* and then *Call 2*. This also holds if 2475 *Procedure 1* and *Procedure 2* are identical. 2477 In other words, WAMP guarantees ordering of invocations between any 2478 given _pair_ of _Caller_ and _Callee_. 2480 There are no guarantees on the order of call results and errors in 2481 relation to _different_ calls, since the execution of calls upon 2482 different invocations of endpoints in _Callees_ are running 2483 independently. A first call might require an expensive, long-running 2484 computation, whereas a second, subsequent call might finish 2485 immediately. 2487 Further, if _Callee A_ registers for *Procedure 1*, the "REGISTERED" 2488 message will be sent by _Dealer_ to _Callee A_ before any 2489 "INVOCATION" message for *Procedure 1*. 2491 There is no guarantee regarding the order of return for multiple 2492 subsequent register requests. A register request might require the 2493 _Broker_ to do a time-consuming lookup in some database, whereas 2494 another register request second might be permissible immediately. 2496 9.7. Security Model 2498 The following discusses the security model for the WAMP basic 2499 profile. A WAMP Advanced Profile may extend this. 2501 9.7.1. Transport Encryption and Integrity 2503 WAMP transports may provide (optional) transport-level encryption and 2504 integrity verification. If so, encryption and integrity is point-to- 2505 point: between a _Client_ and the _Router_ it is connected to. 2507 Transport-level encryption and integrity is solely at the transport- 2508 level and transparent to WAMP. WAMP itself deliberately does not 2509 specify any kind of transport-level encryption. 2511 Implementations that offer TCP based transport such as WAMP-over- 2512 WebSocket or WAMP-over-RawSocket SHOULD implement Transport Layer 2513 Security (TLS). 2515 WAMP deployments are encouraged to stick to a TLS-only policy with 2516 the TLS code and setup being hardened. 2518 Further, when a _Client_ connects to a _Router_ over a local-only 2519 transport such as Unix domain sockets, the integrity of the data 2520 transmitted is implicit (the OS kernel is trusted), and the privacy 2521 of the data transmitted can be assured using file system permissions 2522 (no one can tap a Unix domain socket without appropriate permissions 2523 or being root). 2525 9.7.2. Router Authentication 2527 To authenticate _Routers_ to _Clients_, deployments MUST run TLS and 2528 _Clients_ MUST verify the _Router_ server certificate presented. 2530 WAMP itself does not provide mechanisms to authenticate a _Router_ 2531 (only a _Client_). 2533 The verification of the _Router_ server certificate can happen 2535 1. against a certificate trust database that comes with the 2536 _Clients_ operating system 2538 2. against an issuing certificate/key hard-wired into the _Client_ 2540 3. by using new mechanisms like DNS-based Authentication of Named 2541 Enitities (DNSSEC)/TLSA 2543 Further, when a _Client_ connects to a _Router_ over a local-only 2544 transport such as Unix domain sockets, the file system permissions 2545 can be used to create implicit trust. E.g. if only the OS user under 2546 which the _Router_ runs has the permission to create a Unix domain 2547 socket under a specific path, _Clients_ connecting to that path can 2548 trust in the router authenticity. 2550 9.7.3. Client Authentication 2552 Authentication of a _Client_ to a _Router_ at the WAMP level is not 2553 part of this basic profile. A WAMP Advanced Profile may specify such 2554 mechanisms. 2556 When running over TLS, a _Router_ may authenticate a _Client_ at the 2557 transport level by doing a _client certificate based authentication_. 2559 9.7.3.1. Routers are trusted 2561 _Routers_ are _trusted_ by _Clients_. 2563 In particular, _Routers_ can read (and modify) any application 2564 payload transmitted in events, calls, call results and call errors 2565 (the "Arguments" or "ArgumentsKw" message fields). 2567 Hence, _Routers_ do not provide confidentiality with respect to 2568 application payload, and also do not provide authenticity or 2569 integrity of application payloads that could be verified by a 2570 receiving _Client_. 2572 _Routers_ need to read the application payloads in cases of automatic 2573 conversion between different serialization formats. 2575 Further, _Routers_ are trusted to *actually perform* routing as 2576 specified. E.g. a _Client_ that publishes an event has to trust a 2577 _Router_ that the event is actually dispatched to all (eligible) 2578 _Subscribers_ by the _Router_. 2580 A rogue _Router_ might deny normal routing operation without a 2581 _Client_ taking notice. 2583 9.8. Binary conversion of JSON Strings 2585 Binary data follows a convention for conversion to JSON strings. 2587 A *byte array* is converted to a *JSON string* as follows: 2589 1. convert the byte array to a Base64 encoded (host language) string 2591 2. prepend the string with a "\0" character 2593 3. serialize the string to a JSON string 2595 _Example_ 2597 Consider the byte array (hex representation): 2599 10e3ff9053075c526f5fc06d4fe37cdb 2601 This will get converted to Base64 2603 EOP/kFMHXFJvX8BtT+N82w== 2605 prepended with "\0" 2607 \x00EOP/kFMHXFJvX8BtT+N82w== 2609 and serialized to a JSON string 2611 "\\u0000EOP/kFMHXFJvX8BtT+N82w==" 2613 A *JSON string* is unserialized to either a *string* or a *byte 2614 array* using the following procedure: 2616 1. Unserialize a JSON string to a host language (Unicode) string 2618 2. If the string starts with a "\0" character, interpret the rest 2619 (after the first character) as Base64 and decode to a byte array 2621 3. Otherwise, return the Unicode string 2623 Below are complete Python and JavaScript code examples for conversion 2624 between byte arrays and JSON strings. 2626 9.8.1. Python 2628 Here is a complete example in Python showing how byte arrays are 2629 converted to and from JSON: 2631 ```python 2632 2634 import os, base64, json, sys, binascii 2635 PY3 = sys.version_info >= (3,) 2636 if PY3: 2637 unicode = str 2639 data_in = os.urandom(16) 2640 print("In: {}".format(binascii.hexlify(data_in))) 2642 ## encoding 2643 encoded = json.dumps('\0' + base64.b64encode(data_in). 2644 decode('ascii')) 2646 print("JSON: {}".format(encoded)) 2648 ## decoding 2649 decoded = json.loads(encoded) 2650 if type(decoded) == unicode: 2651 if decoded[0] == '\0': 2652 data_out = base64.b64decode(decoded[1:]) 2653 else: 2654 data_out = decoded 2656 print("Out: {}".format(binascii.hexlify(data_out))) 2658 assert(data_out == data_in) 2660 2661 ``` 2663 9.8.2. JavaScript 2665 Here is a complete example in JavaScript showing how byte arrays are 2666 converted to and from JSON: 2668 ```javascript 2669 2671 var data_in = new Uint8Array(new ArrayBuffer(16)); 2673 // initialize test data 2674 for (var i = 0; i < data_in.length; ++i) { 2675 data_in[i] = i; 2676 } 2677 console.log(data_in); 2679 // convert byte array to raw string 2680 var raw_out = ''; 2681 for (var i = 0; i < data_in.length; ++i) { 2682 raw_out += String.fromCharCode(data_in[i]); 2683 } 2685 // base64 encode raw string, prepend with \0 and serialize to JSON 2686 var encoded = JSON.stringify("\0" + window.btoa(raw_out)); 2687 console.log(encoded); // "\u0000AAECAwQFBgcICQoLDA0ODw==" 2689 // unserialize from JSON 2690 var decoded = JSON.parse(encoded); 2692 var data_out; 2693 if (decoded.charCodeAt(0) === 0) { 2694 // strip first character and decode base64 to raw string 2695 var raw = window.atob(decoded.substring(1)); 2697 // convert raw string to byte array 2698 var data_out = new Uint8Array(new ArrayBuffer(raw.length)); 2699 for (var i = 0; i < raw.length; ++i) { 2700 data_out[i] = raw.charCodeAt(i); 2701 } 2702 } else { 2703 data_out = decoded; 2704 } 2706 console.log(data_out); 2708 2709 ``` 2711 10. Security Considerations 2713 -- write me -- 2715 11. IANA Considerations 2717 TBD 2719 12. Contributors 2721 13. Acknowledgements 2723 14. References 2725 14.1. Normative References 2727 [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO 2728 10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November 2729 2003, . 2731 [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform 2732 Resource Identifier (URI): Generic Syntax", STD 66, RFC 2733 3986, DOI 10.17487/RFC3986, January 2005, 2734 . 2736 [RFC6455] Fette, I. and A. Melnikov, "The WebSocket Protocol", RFC 2737 6455, DOI 10.17487/RFC6455, December 2011, 2738 . 2740 14.2. Informative References 2742 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 2743 Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/ 2744 RFC2119, March 1997, 2745 . 2747 14.3. URIs 2749 [1] http://www.iana.org/assignments/websocket/websocket.xml 2751 Author's Address 2753 Tobias G. Oberstein 2754 Tavendo GmbH 2756 Email: tobias.oberstein@tavendo.de