rpc.capnp (82501B)
1 # Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors 2 # Licensed under the MIT License: 3 # 4 # Permission is hereby granted, free of charge, to any person obtaining a copy 5 # of this software and associated documentation files (the "Software"), to deal 6 # in the Software without restriction, including without limitation the rights 7 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 # copies of the Software, and to permit persons to whom the Software is 9 # furnished to do so, subject to the following conditions: 10 # 11 # The above copyright notice and this permission notice shall be included in 12 # all copies or substantial portions of the Software. 13 # 14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 # THE SOFTWARE. 21 22 @0xb312981b2552a250; 23 # Recall that Cap'n Proto RPC allows messages to contain references to remote objects that 24 # implement interfaces. These references are called "capabilities", because they both designate 25 # the remote object to use and confer permission to use it. 26 # 27 # Recall also that Cap'n Proto RPC has the feature that when a method call itself returns a 28 # capability, the caller can begin calling methods on that capability _before the first call has 29 # returned_. The caller essentially sends a message saying "Hey server, as soon as you finish 30 # that previous call, do this with the result!". Cap'n Proto's RPC protocol makes this possible. 31 # 32 # The protocol is significantly more complicated than most RPC protocols. However, this is 33 # implementation complexity that underlies an easy-to-grasp higher-level model of object oriented 34 # programming. That is, just like TCP is a surprisingly complicated protocol that implements a 35 # conceptually-simple byte stream abstraction, Cap'n Proto is a surprisingly complicated protocol 36 # that implements a conceptually-simple object abstraction. 37 # 38 # Cap'n Proto RPC is based heavily on CapTP, the object-capability protocol used by the E 39 # programming language: 40 # http://www.erights.org/elib/distrib/captp/index.html 41 # 42 # Cap'n Proto RPC takes place between "vats". A vat hosts some set of objects and talks to other 43 # vats through direct bilateral connections. Typically, there is a 1:1 correspondence between vats 44 # and processes (in the unix sense of the word), although this is not strictly always true (one 45 # process could run multiple vats, or a distributed virtual vat might live across many processes). 46 # 47 # Cap'n Proto does not distinguish between "clients" and "servers" -- this is up to the application. 48 # Either end of any connection can potentially hold capabilities pointing to the other end, and 49 # can call methods on those capabilities. In the doc comments below, we use the words "sender" 50 # and "receiver". These refer to the sender and receiver of an instance of the struct or field 51 # being documented. Sometimes we refer to a "third-party" that is neither the sender nor the 52 # receiver. Documentation is generally written from the point of view of the sender. 53 # 54 # It is generally up to the vat network implementation to securely verify that connections are made 55 # to the intended vat as well as to encrypt transmitted data for privacy and integrity. See the 56 # `VatNetwork` example interface near the end of this file. 57 # 58 # When a new connection is formed, the only interesting things that can be done are to send a 59 # `Bootstrap` (level 0) or `Accept` (level 3) message. 60 # 61 # Unless otherwise specified, messages must be delivered to the receiving application in the same 62 # order in which they were initiated by the sending application. The goal is to support "E-Order", 63 # which states that two calls made on the same reference must be delivered in the order which they 64 # were made: 65 # http://erights.org/elib/concurrency/partial-order.html 66 # 67 # Since the full protocol is complicated, we define multiple levels of support that an 68 # implementation may target. For many applications, level 1 support will be sufficient. 69 # Comments in this file indicate which level requires the corresponding feature to be 70 # implemented. 71 # 72 # * **Level 0:** The implementation does not support object references. Only the bootstrap interface 73 # can be called. At this level, the implementation does not support object-oriented protocols and 74 # is similar in complexity to JSON-RPC or Protobuf services. This level should be considered only 75 # a temporary stepping-stone toward level 1 as the lack of object references drastically changes 76 # how protocols are designed. Applications _should not_ attempt to design their protocols around 77 # the limitations of level 0 implementations. 78 # 79 # * **Level 1:** The implementation supports simple bilateral interaction with object references 80 # and promise pipelining, but interactions between three or more parties are supported only via 81 # proxying of objects. E.g. if Alice (in Vat A) wants to send Bob (in Vat B) a capability 82 # pointing to Carol (in Vat C), Alice must create a proxy of Carol within Vat A and send Bob a 83 # reference to that; Bob cannot form a direct connection to Carol. Level 1 implementations do 84 # not support checking if two capabilities received from different vats actually point to the 85 # same object ("join"), although they should be able to do this check on capabilities received 86 # from the same vat. 87 # 88 # * **Level 2:** The implementation supports saving persistent capabilities -- i.e. capabilities 89 # that remain valid even after disconnect, and can be restored on a future connection. When a 90 # capability is saved, the requester receives a `SturdyRef`, which is a token that can be used 91 # to restore the capability later. 92 # 93 # * **Level 3:** The implementation supports three-way interactions. That is, if Alice (in Vat A) 94 # sends Bob (in Vat B) a capability pointing to Carol (in Vat C), then Vat B will automatically 95 # form a direct connection to Vat C rather than have requests be proxied through Vat A. 96 # 97 # * **Level 4:** The entire protocol is implemented, including joins (checking if two capabilities 98 # are equivalent). 99 # 100 # Note that an implementation must also support specific networks (transports), as described in 101 # the "Network-specific Parameters" section below. An implementation might have different levels 102 # depending on the network used. 103 # 104 # New implementations of Cap'n Proto should start out targeting the simplistic two-party network 105 # type as defined in `rpc-twoparty.capnp`. With this network type, level 3 is irrelevant and 106 # levels 2 and 4 are much easier than usual to implement. When such an implementation is paired 107 # with a container proxy, the contained app effectively gets to make full use of the proxy's 108 # network at level 4. And since Cap'n Proto IPC is extremely fast, it may never make sense to 109 # bother implementing any other vat network protocol -- just use the correct container type and get 110 # it for free. 111 112 using Cxx = import "/capnp/c++.capnp"; 113 $Cxx.namespace("capnp::rpc"); 114 115 # ======================================================================================== 116 # The Four Tables 117 # 118 # Cap'n Proto RPC connections are stateful (although an application built on Cap'n Proto could 119 # export a stateless interface). As in CapTP, for each open connection, a vat maintains four state 120 # tables: questions, answers, imports, and exports. See the diagram at: 121 # http://www.erights.org/elib/distrib/captp/4tables.html 122 # 123 # The question table corresponds to the other end's answer table, and the imports table corresponds 124 # to the other end's exports table. 125 # 126 # The entries in each table are identified by ID numbers (defined below as 32-bit integers). These 127 # numbers are always specific to the connection; a newly-established connection starts with no 128 # valid IDs. Since low-numbered IDs will pack better, it is suggested that IDs be assigned like 129 # Unix file descriptors -- prefer the lowest-number ID that is currently available. 130 # 131 # IDs in the questions/answers tables are chosen by the questioner and generally represent method 132 # calls that are in progress. 133 # 134 # IDs in the imports/exports tables are chosen by the exporter and generally represent objects on 135 # which methods may be called. Exports may be "settled", meaning the exported object is an actual 136 # object living in the exporter's vat, or they may be "promises", meaning the exported object is 137 # the as-yet-unknown result of an ongoing operation and will eventually be resolved to some other 138 # object once that operation completes. Calls made to a promise will be forwarded to the eventual 139 # target once it is known. The eventual replacement object does *not* get the same ID as the 140 # promise, as it may turn out to be an object that is already exported (so already has an ID) or 141 # may even live in a completely different vat (and so won't get an ID on the same export table 142 # at all). 143 # 144 # IDs can be reused over time. To make this safe, we carefully define the lifetime of IDs. Since 145 # messages using the ID could be traveling in both directions simultaneously, we must define the 146 # end of life of each ID _in each direction_. The ID is only safe to reuse once it has been 147 # released by both sides. 148 # 149 # When a Cap'n Proto connection is lost, everything on the four tables is lost. All questions are 150 # canceled and throw exceptions. All imports become broken (all future calls to them throw 151 # exceptions). All exports and answers are implicitly released. The only things not lost are 152 # persistent capabilities (`SturdyRef`s). The application must plan for this and should respond by 153 # establishing a new connection and restoring from these persistent capabilities. 154 155 using QuestionId = UInt32; 156 # **(level 0)** 157 # 158 # Identifies a question in the sender's question table (which corresponds to the receiver's answer 159 # table). The questioner (caller) chooses an ID when making a call. The ID remains valid in 160 # caller -> callee messages until a Finish message is sent, and remains valid in callee -> caller 161 # messages until a Return message is sent. 162 163 using AnswerId = QuestionId; 164 # **(level 0)** 165 # 166 # Identifies an answer in the sender's answer table (which corresponds to the receiver's question 167 # table). 168 # 169 # AnswerId is physically equivalent to QuestionId, since the question and answer tables correspond, 170 # but we define a separate type for documentation purposes: we always use the type representing 171 # the sender's point of view. 172 173 using ExportId = UInt32; 174 # **(level 1)** 175 # 176 # Identifies an exported capability or promise in the sender's export table (which corresponds 177 # to the receiver's import table). The exporter chooses an ID before sending a capability over the 178 # wire. If the capability is already in the table, the exporter should reuse the same ID. If the 179 # ID is a promise (as opposed to a settled capability), this must be indicated at the time the ID 180 # is introduced (e.g. by using `senderPromise` instead of `senderHosted` in `CapDescriptor`); in 181 # this case, the importer shall expect a later `Resolve` message that replaces the promise. 182 # 183 # ExportId/ImportIds are subject to reference counting. Whenever an `ExportId` is sent over the 184 # wire (from the exporter to the importer), the export's reference count is incremented (unless 185 # otherwise specified). The reference count is later decremented by a `Release` message. Since 186 # the `Release` message can specify an arbitrary number by which to reduce the reference count, the 187 # importer should usually batch reference decrements and only send a `Release` when it believes the 188 # reference count has hit zero. Of course, it is possible that a new reference to the export is 189 # in-flight at the time that the `Release` message is sent, so it is necessary for the exporter to 190 # keep track of the reference count on its end as well to avoid race conditions. 191 # 192 # When a connection is lost, all exports are implicitly released. It is not possible to restore 193 # a connection state after disconnect (although a transport layer could implement a concept of 194 # persistent connections if it is transparent to the RPC layer). 195 196 using ImportId = ExportId; 197 # **(level 1)** 198 # 199 # Identifies an imported capability or promise in the sender's import table (which corresponds to 200 # the receiver's export table). 201 # 202 # ImportId is physically equivalent to ExportId, since the export and import tables correspond, 203 # but we define a separate type for documentation purposes: we always use the type representing 204 # the sender's point of view. 205 # 206 # An `ImportId` remains valid in importer -> exporter messages until the importer has sent 207 # `Release` messages that (it believes) have reduced the reference count to zero. 208 209 # ======================================================================================== 210 # Messages 211 212 struct Message { 213 # An RPC connection is a bi-directional stream of Messages. 214 215 union { 216 unimplemented @0 :Message; 217 # The sender previously received this message from the peer but didn't understand it or doesn't 218 # yet implement the functionality that was requested. So, the sender is echoing the message 219 # back. In some cases, the receiver may be able to recover from this by pretending the sender 220 # had taken some appropriate "null" action. 221 # 222 # For example, say `resolve` is received by a level 0 implementation (because a previous call 223 # or return happened to contain a promise). The level 0 implementation will echo it back as 224 # `unimplemented`. The original sender can then simply release the cap to which the promise 225 # had resolved, thus avoiding a leak. 226 # 227 # For any message type that introduces a question, if the message comes back unimplemented, 228 # the original sender may simply treat it as if the question failed with an exception. 229 # 230 # In cases where there is no sensible way to react to an `unimplemented` message (without 231 # resource leaks or other serious problems), the connection may need to be aborted. This is 232 # a gray area; different implementations may take different approaches. 233 234 abort @1 :Exception; 235 # Sent when a connection is being aborted due to an unrecoverable error. This could be e.g. 236 # because the sender received an invalid or nonsensical message or because the sender had an 237 # internal error. The sender will shut down the outgoing half of the connection after `abort` 238 # and will completely close the connection shortly thereafter (it's up to the sender how much 239 # of a time buffer they want to offer for the client to receive the `abort` before the 240 # connection is reset). 241 242 # Level 0 features ----------------------------------------------- 243 244 bootstrap @8 :Bootstrap; # Request the peer's bootstrap interface. 245 call @2 :Call; # Begin a method call. 246 return @3 :Return; # Complete a method call. 247 finish @4 :Finish; # Release a returned answer / cancel a call. 248 249 # Level 1 features ----------------------------------------------- 250 251 resolve @5 :Resolve; # Resolve a previously-sent promise. 252 release @6 :Release; # Release a capability so that the remote object can be deallocated. 253 disembargo @13 :Disembargo; # Lift an embargo used to enforce E-order over promise resolution. 254 255 # Level 2 features ----------------------------------------------- 256 257 obsoleteSave @7 :AnyPointer; 258 # Obsolete request to save a capability, resulting in a SturdyRef. This has been replaced 259 # by the `Persistent` interface defined in `persistent.capnp`. This operation was never 260 # implemented. 261 262 obsoleteDelete @9 :AnyPointer; 263 # Obsolete way to delete a SturdyRef. This operation was never implemented. 264 265 # Level 3 features ----------------------------------------------- 266 267 provide @10 :Provide; # Provide a capability to a third party. 268 accept @11 :Accept; # Accept a capability provided by a third party. 269 270 # Level 4 features ----------------------------------------------- 271 272 join @12 :Join; # Directly connect to the common root of two or more proxied caps. 273 } 274 } 275 276 # Level 0 message types ---------------------------------------------- 277 278 struct Bootstrap { 279 # **(level 0)** 280 # 281 # Get the "bootstrap" interface exported by the remote vat. 282 # 283 # For level 0, 1, and 2 implementations, the "bootstrap" interface is simply the main interface 284 # exported by a vat. If the vat acts as a server fielding connections from clients, then the 285 # bootstrap interface defines the basic functionality available to a client when it connects. 286 # The exact interface definition obviously depends on the application. 287 # 288 # We call this a "bootstrap" because in an ideal Cap'n Proto world, bootstrap interfaces would 289 # never be used. In such a world, any time you connect to a new vat, you do so because you 290 # received an introduction from some other vat (see `ThirdPartyCapId`). Thus, the first message 291 # you send is `Accept`, and further communications derive from there. `Bootstrap` is not used. 292 # 293 # In such an ideal world, DNS itself would support Cap'n Proto -- performing a DNS lookup would 294 # actually return a new Cap'n Proto capability, thus introducing you to the target system via 295 # level 3 RPC. Applications would receive the capability to talk to DNS in the first place as 296 # an initial endowment or part of a Powerbox interaction. Therefore, an app can form arbitrary 297 # connections without ever using `Bootstrap`. 298 # 299 # Of course, in the real world, DNS is not Cap'n-Proto-based, and we don't want Cap'n Proto to 300 # require a whole new internet infrastructure to be useful. Therefore, we offer bootstrap 301 # interfaces as a way to get up and running without a level 3 introduction. Thus, bootstrap 302 # interfaces are used to "bootstrap" from other, non-Cap'n-Proto-based means of service discovery, 303 # such as legacy DNS. 304 # 305 # Note that a vat need not provide a bootstrap interface, and in fact many vats (especially those 306 # acting as clients) do not. In this case, the vat should either reply to `Bootstrap` with a 307 # `Return` indicating an exception, or should return a dummy capability with no methods. 308 309 questionId @0 :QuestionId; 310 # A new question ID identifying this request, which will eventually receive a Return message 311 # containing the restored capability. 312 313 deprecatedObjectId @1 :AnyPointer; 314 # ** DEPRECATED ** 315 # 316 # A Vat may export multiple bootstrap interfaces. In this case, `deprecatedObjectId` specifies 317 # which one to return. If this pointer is null, then the default bootstrap interface is returned. 318 # 319 # As of verison 0.5, use of this field is deprecated. If a service wants to export multiple 320 # bootstrap interfaces, it should instead define a single bootstrap interface that has methods 321 # that return each of the other interfaces. 322 # 323 # **History** 324 # 325 # In the first version of Cap'n Proto RPC (0.4.x) the `Bootstrap` message was called `Restore`. 326 # At the time, it was thought that this would eventually serve as the way to restore SturdyRefs 327 # (level 2). Meanwhile, an application could offer its "main" interface on a well-known 328 # (non-secret) SturdyRef. 329 # 330 # Since level 2 RPC was not implemented at the time, the `Restore` message was in practice only 331 # used to obtain the main interface. Since most applications had only one main interface that 332 # they wanted to restore, they tended to designate this with a null `objectId`. 333 # 334 # Unfortunately, the earliest version of the EZ RPC interfaces set a precedent of exporting 335 # multiple main interfaces by allowing them to be exported under string names. In this case, 336 # `objectId` was a Text value specifying the name. 337 # 338 # All of this proved problematic for several reasons: 339 # 340 # - The arrangement assumed that a client wishing to restore a SturdyRef would know exactly what 341 # machine to connect to and would be able to immediately restore a SturdyRef on connection. 342 # However, in practice, the ability to restore SturdyRefs is itself a capability that may 343 # require going through an authentication process to obtain. Thus, it makes more sense to 344 # define a "restorer service" as a full Cap'n Proto interface. If this restorer interface is 345 # offered as the vat's bootstrap interface, then this is equivalent to the old arrangement. 346 # 347 # - Overloading "Restore" for the purpose of obtaining well-known capabilities encouraged the 348 # practice of exporting singleton services with string names. If singleton services are desired, 349 # it is better to have one main interface that has methods that can be used to obtain each 350 # service, in order to get all the usual benefits of schemas and type checking. 351 # 352 # - Overloading "Restore" also had a security problem: Often, "main" or "well-known" 353 # capabilities exported by a vat are in fact not public: they are intended to be accessed only 354 # by clients who are capable of forming a connection to the vat. This can lead to trouble if 355 # the client itself has other clients and wishes to foward some `Restore` requests from those 356 # external clients -- it has to be very careful not to allow through `Restore` requests 357 # addressing the default capability. 358 # 359 # For example, consider the case of a sandboxed Sandstorm application and its supervisor. The 360 # application exports a default capability to its supervisor that provides access to 361 # functionality that only the supervisor is supposed to access. Meanwhile, though, applications 362 # may publish other capabilities that may be persistent, in which case the application needs 363 # to field `Restore` requests that could come from anywhere. These requests of course have to 364 # pass through the supervisor, as all communications with the outside world must. But, the 365 # supervisor has to be careful not to honor an external request addressing the application's 366 # default capability, since this capability is privileged. Unfortunately, the default 367 # capability cannot be given an unguessable name, because then the supervisor itself would not 368 # be able to address it! 369 # 370 # As of Cap'n Proto 0.5, `Restore` has been renamed to `Bootstrap` and is no longer planned for 371 # use in restoring SturdyRefs. 372 # 373 # Note that 0.4 also defined a message type called `Delete` that, like `Restore`, addressed a 374 # SturdyRef, but indicated that the client would not restore the ref again in the future. This 375 # operation was never implemented, so it was removed entirely. If a "delete" operation is desired, 376 # it should exist as a method on the same interface that handles restoring SturdyRefs. However, 377 # the utility of such an operation is questionable. You wouldn't be able to rely on it for 378 # garbage collection since a client could always disappear permanently without remembering to 379 # delete all its SturdyRefs, thus leaving them dangling forever. Therefore, it is advisable to 380 # design systems such that SturdyRefs never represent "owned" pointers. 381 # 382 # For example, say a SturdyRef points to an image file hosted on some server. That image file 383 # should also live inside a collection (a gallery, perhaps) hosted on the same server, owned by 384 # a user who can delete the image at any time. If the user deletes the image, the SturdyRef 385 # stops working. On the other hand, if the SturdyRef is discarded, this has no effect on the 386 # existence of the image in its collection. 387 } 388 389 struct Call { 390 # **(level 0)** 391 # 392 # Message type initiating a method call on a capability. 393 394 questionId @0 :QuestionId; 395 # A number, chosen by the caller, that identifies this call in future messages. This number 396 # must be different from all other calls originating from the same end of the connection (but 397 # may overlap with question IDs originating from the opposite end). A fine strategy is to use 398 # sequential question IDs, but the recipient should not assume this. 399 # 400 # A question ID can be reused once both: 401 # - A matching Return has been received from the callee. 402 # - A matching Finish has been sent from the caller. 403 404 target @1 :MessageTarget; 405 # The object that should receive this call. 406 407 interfaceId @2 :UInt64; 408 # The type ID of the interface being called. Each capability may implement multiple interfaces. 409 410 methodId @3 :UInt16; 411 # The ordinal number of the method to call within the requested interface. 412 413 allowThirdPartyTailCall @8 :Bool = false; 414 # Indicates whether or not the receiver is allowed to send a `Return` containing 415 # `acceptFromThirdParty`. Level 3 implementations should set this true. Otherwise, the callee 416 # will have to proxy the return in the case of a tail call to a third-party vat. 417 418 params @4 :Payload; 419 # The call parameters. `params.content` is a struct whose fields correspond to the parameters of 420 # the method. 421 422 sendResultsTo :union { 423 # Where should the return message be sent? 424 425 caller @5 :Void; 426 # Send the return message back to the caller (the usual). 427 428 yourself @6 :Void; 429 # **(level 1)** 430 # 431 # Don't actually return the results to the sender. Instead, hold on to them and await 432 # instructions from the sender regarding what to do with them. In particular, the sender 433 # may subsequently send a `Return` for some other call (which the receiver had previously made 434 # to the sender) with `takeFromOtherQuestion` set. The results from this call are then used 435 # as the results of the other call. 436 # 437 # When `yourself` is used, the receiver must still send a `Return` for the call, but sets the 438 # field `resultsSentElsewhere` in that `Return` rather than including the results. 439 # 440 # This feature can be used to implement tail calls in which a call from Vat A to Vat B ends up 441 # returning the result of a call from Vat B back to Vat A. 442 # 443 # In particular, the most common use case for this feature is when Vat A makes a call to a 444 # promise in Vat B, and then that promise ends up resolving to a capability back in Vat A. 445 # Vat B must forward all the queued calls on that promise back to Vat A, but can set `yourself` 446 # in the calls so that the results need not pass back through Vat B. 447 # 448 # For example: 449 # - Alice, in Vat A, calls foo() on Bob in Vat B. 450 # - Alice makes a pipelined call bar() on the promise returned by foo(). 451 # - Later on, Bob resolves the promise from foo() to point at Carol, who lives in Vat A (next 452 # to Alice). 453 # - Vat B dutifully forwards the bar() call to Carol. Let us call this forwarded call bar'(). 454 # Notice that bar() and bar'() are travelling in opposite directions on the same network 455 # link. 456 # - The `Call` for bar'() has `sendResultsTo` set to `yourself`. 457 # - Vat B sends a `Return` for bar() with `takeFromOtherQuestion` set in place of the results, 458 # with the value set to the question ID of bar'(). Vat B does not wait for bar'() to return, 459 # as doing so would introduce unnecessary round trip latency. 460 # - Vat A receives bar'() and delivers it to Carol. 461 # - When bar'() returns, Vat A sends a `Return` for bar'() to Vat B, with `resultsSentElsewhere` 462 # set in place of results. 463 # - Vat A sends a `Finish` for the bar() call to Vat B. 464 # - Vat B receives the `Finish` for bar() and sends a `Finish` for bar'(). 465 466 thirdParty @7 :RecipientId; 467 # **(level 3)** 468 # 469 # The call's result should be returned to a different vat. The receiver (the callee) expects 470 # to receive an `Accept` message from the indicated vat, and should return the call's result 471 # to it, rather than to the sender of the `Call`. 472 # 473 # This operates much like `yourself`, above, except that Carol is in a separate Vat C. `Call` 474 # messages are sent from Vat A -> Vat B and Vat B -> Vat C. A `Return` message is sent from 475 # Vat B -> Vat A that contains `acceptFromThirdParty` in place of results. When Vat A sends 476 # an `Accept` to Vat C, it receives back a `Return` containing the call's actual result. Vat C 477 # also sends a `Return` to Vat B with `resultsSentElsewhere`. 478 } 479 } 480 481 struct Return { 482 # **(level 0)** 483 # 484 # Message type sent from callee to caller indicating that the call has completed. 485 486 answerId @0 :AnswerId; 487 # Equal to the QuestionId of the corresponding `Call` message. 488 489 releaseParamCaps @1 :Bool = true; 490 # If true, all capabilities that were in the params should be considered released. The sender 491 # must not send separate `Release` messages for them. Level 0 implementations in particular 492 # should always set this true. This defaults true because if level 0 implementations forget to 493 # set it they'll never notice (just silently leak caps), but if level >=1 implementations forget 494 # to set it to false they'll quickly get errors. 495 # 496 # The receiver should act as if the sender had sent a release message with count=1 for each 497 # CapDescriptor in the original Call message. 498 499 union { 500 results @2 :Payload; 501 # The result. 502 # 503 # For regular method calls, `results.content` points to the result struct. 504 # 505 # For a `Return` in response to an `Accept` or `Bootstrap`, `results` contains a single 506 # capability (rather than a struct), and `results.content` is just a capability pointer with 507 # index 0. A `Finish` is still required in this case. 508 509 exception @3 :Exception; 510 # Indicates that the call failed and explains why. 511 512 canceled @4 :Void; 513 # Indicates that the call was canceled due to the caller sending a Finish message 514 # before the call had completed. 515 516 resultsSentElsewhere @5 :Void; 517 # This is set when returning from a `Call` that had `sendResultsTo` set to something other 518 # than `caller`. 519 # 520 # It doesn't matter too much when this is sent, as the receiver doesn't need to do anything 521 # with it, but the C++ implementation appears to wait for the call to finish before sending 522 # this. 523 524 takeFromOtherQuestion @6 :QuestionId; 525 # The sender has also sent (before this message) a `Call` with the given question ID and with 526 # `sendResultsTo.yourself` set, and the results of that other call should be used as the 527 # results here. `takeFromOtherQuestion` can only used once per question. 528 529 acceptFromThirdParty @7 :ThirdPartyCapId; 530 # **(level 3)** 531 # 532 # The caller should contact a third-party vat to pick up the results. An `Accept` message 533 # sent to the vat will return the result. This pairs with `Call.sendResultsTo.thirdParty`. 534 # It should only be used if the corresponding `Call` had `allowThirdPartyTailCall` set. 535 } 536 } 537 538 struct Finish { 539 # **(level 0)** 540 # 541 # Message type sent from the caller to the callee to indicate: 542 # 1) The questionId will no longer be used in any messages sent by the callee (no further 543 # pipelined requests). 544 # 2) If the call has not returned yet, the caller no longer cares about the result. If nothing 545 # else cares about the result either (e.g. there are no other outstanding calls pipelined on 546 # the result of this one) then the callee may wish to immediately cancel the operation and 547 # send back a Return message with "canceled" set. However, implementations are not required 548 # to support premature cancellation -- instead, the implementation may wait until the call 549 # actually completes and send a normal `Return` message. 550 # 551 # TODO(someday): Should we separate (1) and implicitly releasing result capabilities? It would be 552 # possible and useful to notify the server that it doesn't need to keep around the response to 553 # service pipeline requests even though the caller still wants to receive it / hasn't yet 554 # finished processing it. It could also be useful to notify the server that it need not marshal 555 # the results because the caller doesn't want them anyway, even if the caller is still sending 556 # pipelined calls, although this seems less useful (just saving some bytes on the wire). 557 558 questionId @0 :QuestionId; 559 # ID of the call whose result is to be released. 560 561 releaseResultCaps @1 :Bool = true; 562 # If true, all capabilities that were in the results should be considered released. The sender 563 # must not send separate `Release` messages for them. Level 0 implementations in particular 564 # should always set this true. This defaults true because if level 0 implementations forget to 565 # set it they'll never notice (just silently leak caps), but if level >=1 implementations forget 566 # set it false they'll quickly get errors. 567 } 568 569 # Level 1 message types ---------------------------------------------- 570 571 struct Resolve { 572 # **(level 1)** 573 # 574 # Message type sent to indicate that a previously-sent promise has now been resolved to some other 575 # object (possibly another promise) -- or broken, or canceled. 576 # 577 # Keep in mind that it's possible for a `Resolve` to be sent to a level 0 implementation that 578 # doesn't implement it. For example, a method call or return might contain a capability in the 579 # payload. Normally this is fine even if the receiver is level 0, because they will implicitly 580 # release all such capabilities on return / finish. But if the cap happens to be a promise, then 581 # a follow-up `Resolve` may be sent regardless of this release. The level 0 receiver will reply 582 # with an `unimplemented` message, and the sender (of the `Resolve`) can respond to this as if the 583 # receiver had immediately released any capability to which the promise resolved. 584 # 585 # When implementing promise resolution, it's important to understand how embargos work and the 586 # tricky case of the Tribble 4-way race condition. See the comments for the Disembargo message, 587 # below. 588 589 promiseId @0 :ExportId; 590 # The ID of the promise to be resolved. 591 # 592 # Unlike all other instances of `ExportId` sent from the exporter, the `Resolve` message does 593 # _not_ increase the reference count of `promiseId`. In fact, it is expected that the receiver 594 # will release the export soon after receiving `Resolve`, and the sender will not send this 595 # `ExportId` again until it has been released and recycled. 596 # 597 # When an export ID sent over the wire (e.g. in a `CapDescriptor`) is indicated to be a promise, 598 # this indicates that the sender will follow up at some point with a `Resolve` message. If the 599 # same `promiseId` is sent again before `Resolve`, still only one `Resolve` is sent. If the 600 # same ID is sent again later _after_ a `Resolve`, it can only be because the export's 601 # reference count hit zero in the meantime and the ID was re-assigned to a new export, therefore 602 # this later promise does _not_ correspond to the earlier `Resolve`. 603 # 604 # If a promise ID's reference count reaches zero before a `Resolve` is sent, the `Resolve` 605 # message may or may not still be sent (the `Resolve` may have already been in-flight when 606 # `Release` was sent, but if the `Release` is received before `Resolve` then there is no longer 607 # any reason to send a `Resolve`). Thus a `Resolve` may be received for a promise of which 608 # the receiver has no knowledge, because it already released it earlier. In this case, the 609 # receiver should simply release the capability to which the promise resolved. 610 611 union { 612 cap @1 :CapDescriptor; 613 # The object to which the promise resolved. 614 # 615 # The sender promises that from this point forth, until `promiseId` is released, it shall 616 # simply forward all messages to the capability designated by `cap`. This is true even if 617 # `cap` itself happens to designate another promise, and that other promise later resolves -- 618 # messages sent to `promiseId` shall still go to that other promise, not to its resolution. 619 # This is important in the case that the receiver of the `Resolve` ends up sending a 620 # `Disembargo` message towards `promiseId` in order to control message ordering -- that 621 # `Disembargo` really needs to reflect back to exactly the object designated by `cap` even 622 # if that object is itself a promise. 623 624 exception @2 :Exception; 625 # Indicates that the promise was broken. 626 } 627 } 628 629 struct Release { 630 # **(level 1)** 631 # 632 # Message type sent to indicate that the sender is done with the given capability and the receiver 633 # can free resources allocated to it. 634 635 id @0 :ImportId; 636 # What to release. 637 638 referenceCount @1 :UInt32; 639 # The amount by which to decrement the reference count. The export is only actually released 640 # when the reference count reaches zero. 641 } 642 643 struct Disembargo { 644 # **(level 1)** 645 # 646 # Message sent to indicate that an embargo on a recently-resolved promise may now be lifted. 647 # 648 # Embargos are used to enforce E-order in the presence of promise resolution. That is, if an 649 # application makes two calls foo() and bar() on the same capability reference, in that order, 650 # the calls should be delivered in the order in which they were made. But if foo() is called 651 # on a promise, and that promise happens to resolve before bar() is called, then the two calls 652 # may travel different paths over the network, and thus could arrive in the wrong order. In 653 # this case, the call to `bar()` must be embargoed, and a `Disembargo` message must be sent along 654 # the same path as `foo()` to ensure that the `Disembargo` arrives after `foo()`. Once the 655 # `Disembargo` arrives, `bar()` can then be delivered. 656 # 657 # There are two particular cases where embargos are important. Consider object Alice, in Vat A, 658 # who holds a promise P, pointing towards Vat B, that eventually resolves to Carol. The two 659 # cases are: 660 # - Carol lives in Vat A, i.e. next to Alice. In this case, Vat A needs to send a `Disembargo` 661 # message that echos through Vat B and back, to ensure that all pipelined calls on the promise 662 # have been delivered. 663 # - Carol lives in a different Vat C. When the promise resolves, a three-party handoff occurs 664 # (see `Provide` and `Accept`, which constitute level 3 of the protocol). In this case, we 665 # piggyback on the state that has already been set up to handle the handoff: the `Accept` 666 # message (from Vat A to Vat C) is embargoed, as are all pipelined messages sent to it, while 667 # a `Disembargo` message is sent from Vat A through Vat B to Vat C. See `Accept.embargo` for 668 # an example. 669 # 670 # Note that in the case where Carol actually lives in Vat B (i.e., the same vat that the promise 671 # already pointed at), no embargo is needed, because the pipelined calls are delivered over the 672 # same path as the later direct calls. 673 # 674 # Keep in mind that promise resolution happens both in the form of Resolve messages as well as 675 # Return messages (which resolve PromisedAnswers). Embargos apply in both cases. 676 # 677 # An alternative strategy for enforcing E-order over promise resolution could be for Vat A to 678 # implement the embargo internally. When Vat A is notified of promise resolution, it could 679 # send a dummy no-op call to promise P and wait for it to complete. Until that call completes, 680 # all calls to the capability are queued locally. This strategy works, but is pessimistic: 681 # in the three-party case, it requires an A -> B -> C -> B -> A round trip before calls can start 682 # being delivered directly to from Vat A to Vat C. The `Disembargo` message allows latency to be 683 # reduced. (In the two-party loopback case, the `Disembargo` message is just a more explicit way 684 # of accomplishing the same thing as a no-op call, but isn't any faster.) 685 # 686 # *The Tribble 4-way Race Condition* 687 # 688 # Any implementation of promise resolution and embargos must be aware of what we call the 689 # "Tribble 4-way race condition", after Dean Tribble, who explained the problem in a lively 690 # Friam meeting. 691 # 692 # Embargos are designed to work in the case where a two-hop path is being shortened to one hop. 693 # But sometimes there are more hops. Imagine that Alice has a reference to a remote promise P1 694 # that eventually resolves to _another_ remote promise P2 (in a third vat), which _at the same 695 # time_ happens to resolve to Bob (in a fourth vat). In this case, we're shortening from a 3-hop 696 # path (with four parties) to a 1-hop path (Alice -> Bob). 697 # 698 # Extending the embargo/disembargo protocol to be able to shorted multiple hops at once seems 699 # difficult. Instead, we make a rule that prevents this case from coming up: 700 # 701 # One a promise P has been resolved to a remote object reference R, then all further messages 702 # received addressed to P will be forwarded strictly to R. Even if it turns out later that R is 703 # itself a promise, and has resolved to some other object Q, messages sent to P will still be 704 # forwarded to R, not directly to Q (R will of course further forward the messages to Q). 705 # 706 # This rule does not cause a significant performance burden because once P has resolved to R, it 707 # is expected that people sending messages to P will shortly start sending them to R instead and 708 # drop P. P is at end-of-life anyway, so it doesn't matter if it ignores chances to further 709 # optimize its path. 710 711 target @0 :MessageTarget; 712 # What is to be disembargoed. 713 714 using EmbargoId = UInt32; 715 # Used in `senderLoopback` and `receiverLoopback`, below. 716 717 context :union { 718 senderLoopback @1 :EmbargoId; 719 # The sender is requesting a disembargo on a promise that is known to resolve back to a 720 # capability hosted by the sender. As soon as the receiver has echoed back all pipelined calls 721 # on this promise, it will deliver the Disembargo back to the sender with `receiverLoopback` 722 # set to the same value as `senderLoopback`. This value is chosen by the sender, and since 723 # it is also consumed be the sender, the sender can use whatever strategy it wants to make sure 724 # the value is unambiguous. 725 # 726 # The receiver must verify that the target capability actually resolves back to the sender's 727 # vat. Otherwise, the sender has committed a protocol error and should be disconnected. 728 729 receiverLoopback @2 :EmbargoId; 730 # The receiver previously sent a `senderLoopback` Disembargo towards a promise resolving to 731 # this capability, and that Disembargo is now being echoed back. 732 733 accept @3 :Void; 734 # **(level 3)** 735 # 736 # The sender is requesting a disembargo on a promise that is known to resolve to a third-party 737 # capability that the sender is currently in the process of accepting (using `Accept`). 738 # The receiver of this `Disembargo` has an outstanding `Provide` on said capability. The 739 # receiver should now send a `Disembargo` with `provide` set to the question ID of that 740 # `Provide` message. 741 # 742 # See `Accept.embargo` for an example. 743 744 provide @4 :QuestionId; 745 # **(level 3)** 746 # 747 # The sender is requesting a disembargo on a capability currently being provided to a third 748 # party. The question ID identifies the `Provide` message previously sent by the sender to 749 # this capability. On receipt, the receiver (the capability host) shall release the embargo 750 # on the `Accept` message that it has received from the third party. See `Accept.embargo` for 751 # an example. 752 } 753 } 754 755 # Level 2 message types ---------------------------------------------- 756 757 # See persistent.capnp. 758 759 # Level 3 message types ---------------------------------------------- 760 761 struct Provide { 762 # **(level 3)** 763 # 764 # Message type sent to indicate that the sender wishes to make a particular capability implemented 765 # by the receiver available to a third party for direct access (without the need for the third 766 # party to proxy through the sender). 767 # 768 # (In CapTP, `Provide` and `Accept` are methods of the global `NonceLocator` object exported by 769 # every vat. In Cap'n Proto, we bake this into the core protocol.) 770 771 questionId @0 :QuestionId; 772 # Question ID to be held open until the recipient has received the capability. A result will be 773 # returned once the third party has successfully received the capability. The sender must at some 774 # point send a `Finish` message as with any other call, and that message can be used to cancel the 775 # whole operation. 776 777 target @1 :MessageTarget; 778 # What is to be provided to the third party. 779 780 recipient @2 :RecipientId; 781 # Identity of the third party that is expected to pick up the capability. 782 } 783 784 struct Accept { 785 # **(level 3)** 786 # 787 # Message type sent to pick up a capability hosted by the receiving vat and provided by a third 788 # party. The third party previously designated the capability using `Provide`. 789 # 790 # This message is also used to pick up a redirected return -- see `Return.acceptFromThirdParty`. 791 792 questionId @0 :QuestionId; 793 # A new question ID identifying this accept message, which will eventually receive a Return 794 # message containing the provided capability (or the call result in the case of a redirected 795 # return). 796 797 provision @1 :ProvisionId; 798 # Identifies the provided object to be picked up. 799 800 embargo @2 :Bool; 801 # If true, this accept shall be temporarily embargoed. The resulting `Return` will not be sent, 802 # and any pipelined calls will not be delivered, until the embargo is released. The receiver 803 # (the capability host) will expect the provider (the vat that sent the `Provide` message) to 804 # eventually send a `Disembargo` message with the field `context.provide` set to the question ID 805 # of the original `Provide` message. At that point, the embargo is released and the queued 806 # messages are delivered. 807 # 808 # For example: 809 # - Alice, in Vat A, holds a promise P, which currently points toward Vat B. 810 # - Alice calls foo() on P. The `Call` message is sent to Vat B. 811 # - The promise P in Vat B ends up resolving to Carol, in Vat C. 812 # - Vat B sends a `Provide` message to Vat C, identifying Vat A as the recipient. 813 # - Vat B sends a `Resolve` message to Vat A, indicating that the promise has resolved to a 814 # `ThirdPartyCapId` identifying Carol in Vat C. 815 # - Vat A sends an `Accept` message to Vat C to pick up the capability. Since Vat A knows that 816 # it has an outstanding call to the promise, it sets `embargo` to `true` in the `Accept` 817 # message. 818 # - Vat A sends a `Disembargo` message to Vat B on promise P, with `context.accept` set. 819 # - Alice makes a call bar() to promise P, which is now pointing towards Vat C. Alice doesn't 820 # know anything about the mechanics of promise resolution happening under the hood, but she 821 # expects that bar() will be delivered after foo() because that is the order in which she 822 # initiated the calls. 823 # - Vat A sends the bar() call to Vat C, as a pipelined call on the result of the `Accept` (which 824 # hasn't returned yet, due to the embargo). Since calls to the newly-accepted capability 825 # are embargoed, Vat C does not deliver the call yet. 826 # - At some point, Vat B forwards the foo() call from the beginning of this example on to Vat C. 827 # - Vat B forwards the `Disembargo` from Vat A on to vat C. It sets `context.provide` to the 828 # question ID of the `Provide` message it had sent previously. 829 # - Vat C receives foo() before `Disembargo`, thus allowing it to correctly deliver foo() 830 # before delivering bar(). 831 # - Vat C receives `Disembargo` from Vat B. It can now send a `Return` for the `Accept` from 832 # Vat A, as well as deliver bar(). 833 } 834 835 # Level 4 message types ---------------------------------------------- 836 837 struct Join { 838 # **(level 4)** 839 # 840 # Message type sent to implement E.join(), which, given a number of capabilities that are 841 # expected to be equivalent, finds the underlying object upon which they all agree and forms a 842 # direct connection to it, skipping any proxies that may have been constructed by other vats 843 # while transmitting the capability. See: 844 # http://erights.org/elib/equality/index.html 845 # 846 # Note that this should only serve to bypass fully-transparent proxies -- proxies that were 847 # created merely for convenience, without any intention of hiding the underlying object. 848 # 849 # For example, say Bob holds two capabilities hosted by Alice and Carol, but he expects that both 850 # are simply proxies for a capability hosted elsewhere. He then issues a join request, which 851 # operates as follows: 852 # - Bob issues Join requests on both Alice and Carol. Each request contains a different piece 853 # of the JoinKey. 854 # - Alice is proxying a capability hosted by Dana, so forwards the request to Dana's cap. 855 # - Dana receives the first request and sees that the JoinKeyPart is one of two. She notes that 856 # she doesn't have the other part yet, so she records the request and responds with a 857 # JoinResult. 858 # - Alice relays the JoinAnswer back to Bob. 859 # - Carol is also proxying a capability from Dana, and so forwards her Join request to Dana as 860 # well. 861 # - Dana receives Carol's request and notes that she now has both parts of a JoinKey. She 862 # combines them in order to form information needed to form a secure connection to Bob. She 863 # also responds with another JoinResult. 864 # - Bob receives the responses from Alice and Carol. He uses the returned JoinResults to 865 # determine how to connect to Dana and attempts to form the connection. Since Bob and Dana now 866 # agree on a secret key that neither Alice nor Carol ever saw, this connection can be made 867 # securely even if Alice or Carol is conspiring against the other. (If Alice and Carol are 868 # conspiring _together_, they can obviously reproduce the key, but this doesn't matter because 869 # the whole point of the join is to verify that Alice and Carol agree on what capability they 870 # are proxying.) 871 # 872 # If the two capabilities aren't actually proxies of the same object, then the join requests 873 # will come back with conflicting `hostId`s and the join will fail before attempting to form any 874 # connection. 875 876 questionId @0 :QuestionId; 877 # Question ID used to respond to this Join. (Note that this ID only identifies one part of the 878 # request for one hop; each part has a different ID and relayed copies of the request have 879 # (probably) different IDs still.) 880 # 881 # The receiver will reply with a `Return` whose `results` is a JoinResult. This `JoinResult` 882 # is relayed from the joined object's host, possibly with transformation applied as needed 883 # by the network. 884 # 885 # Like any return, the result must be released using a `Finish`. However, this release 886 # should not occur until the joiner has either successfully connected to the joined object. 887 # Vats relaying a `Join` message similarly must not release the result they receive until the 888 # return they relayed back towards the joiner has itself been released. This allows the 889 # joined object's host to detect when the Join operation is canceled before completing -- if 890 # it receives a `Finish` for one of the join results before the joiner successfully 891 # connects. It can then free any resources it had allocated as part of the join. 892 893 target @1 :MessageTarget; 894 # The capability to join. 895 896 keyPart @2 :JoinKeyPart; 897 # A part of the join key. These combine to form the complete join key, which is used to establish 898 # a direct connection. 899 900 # TODO(before implementing): Change this so that multiple parts can be sent in a single Join 901 # message, so that if multiple join parts are going to cross the same connection they can be sent 902 # together, so that the receive can potentially optimize its handling of them. In the case where 903 # all parts are bundled together, should the recipient be expected to simply return a cap, so 904 # that the caller can immediately start pipelining to it? 905 } 906 907 # ======================================================================================== 908 # Common structures used in messages 909 910 struct MessageTarget { 911 # The target of a `Call` or other messages that target a capability. 912 913 union { 914 importedCap @0 :ImportId; 915 # This message is to a capability or promise previously imported by the caller (exported by 916 # the receiver). 917 918 promisedAnswer @1 :PromisedAnswer; 919 # This message is to a capability that is expected to be returned by another call that has not 920 # yet been completed. 921 # 922 # At level 0, this is supported only for addressing the result of a previous `Bootstrap`, so 923 # that initial startup doesn't require a round trip. 924 } 925 } 926 927 struct Payload { 928 # Represents some data structure that might contain capabilities. 929 930 content @0 :AnyPointer; 931 # Some Cap'n Proto data structure. Capability pointers embedded in this structure index into 932 # `capTable`. 933 934 capTable @1 :List(CapDescriptor); 935 # Descriptors corresponding to the cap pointers in `content`. 936 } 937 938 struct CapDescriptor { 939 # **(level 1)** 940 # 941 # When an application-defined type contains an interface pointer, that pointer contains an index 942 # into the message's capability table -- i.e. the `capTable` part of the `Payload`. Each 943 # capability in the table is represented as a `CapDescriptor`. The runtime API should not reveal 944 # the CapDescriptor directly to the application, but should instead wrap it in some kind of 945 # callable object with methods corresponding to the interface that the capability implements. 946 # 947 # Keep in mind that `ExportIds` in a `CapDescriptor` are subject to reference counting. See the 948 # description of `ExportId`. 949 # 950 # Note that it is currently not possible to include a broken capability in the CapDescriptor 951 # table. Instead, create a new export (`senderPromise`) for each broken capability and then 952 # immediately follow the payload-bearing Call or Return message with one Resolve message for each 953 # broken capability, resolving it to an exception. 954 955 union { 956 none @0 :Void; 957 # There is no capability here. This `CapDescriptor` should not appear in the payload content. 958 # A `none` CapDescriptor can be generated when an application inserts a capability into a 959 # message and then later changes its mind and removes it -- rewriting all of the other 960 # capability pointers may be hard, so instead a tombstone is left, similar to the way a removed 961 # struct or list instance is zeroed out of the message but the space is not reclaimed. 962 # Hopefully this is unusual. 963 964 senderHosted @1 :ExportId; 965 # The ID of a capability in the sender's export table (receiver's import table). It may be a 966 # newly allocated table entry, or an existing entry (increments the reference count). 967 968 senderPromise @2 :ExportId; 969 # A promise that the sender will resolve later. The sender will send exactly one Resolve 970 # message at a future point in time to replace this promise. Note that even if the same 971 # `senderPromise` is received multiple times, only one `Resolve` is sent to cover all of 972 # them. If `senderPromise` is released before the `Resolve` is sent, the sender (of this 973 # `CapDescriptor`) may choose not to send the `Resolve` at all. 974 975 receiverHosted @3 :ImportId; 976 # A capability (or promise) previously exported by the receiver (imported by the sender). 977 978 receiverAnswer @4 :PromisedAnswer; 979 # A capability expected to be returned in the results of a currently-outstanding call posed 980 # by the sender. 981 982 thirdPartyHosted @5 :ThirdPartyCapDescriptor; 983 # **(level 3)** 984 # 985 # A capability that lives in neither the sender's nor the receiver's vat. The sender needs 986 # to form a direct connection to a third party to pick up the capability. 987 # 988 # Level 1 and 2 implementations that receive a `thirdPartyHosted` may simply send calls to its 989 # `vine` instead. 990 } 991 992 attachedFd @6 :UInt8 = 0xff; 993 # If the RPC message in which this CapDescriptor was delivered also had file descriptors 994 # attached, and `fd` is a valid index into the list of attached file descriptors, then 995 # that file descriptor should be attached to this capability. If `attachedFd` is out-of-bounds 996 # for said list, then no FD is attached. 997 # 998 # For example, if the RPC message arrived over a Unix socket, then file descriptors may be 999 # attached by sending an SCM_RIGHTS ancillary message attached to the data bytes making up the 1000 # raw message. Receivers who wish to opt into FD passing should arrange to receive SCM_RIGHTS 1001 # whenever receiving an RPC message. Senders who wish to send FDs need not verify whether the 1002 # receiver knows how to receive them, because the operating system will automatically discard 1003 # ancillary messages like SCM_RIGHTS if the receiver doesn't ask to receive them, including 1004 # automatically closing any FDs. 1005 # 1006 # It is up to the application protocol to define what capabilities are expected to have file 1007 # descriptors attached, and what those FDs mean. But, for example, an application could use this 1008 # to open a file on disk and then transmit the open file descriptor to a sandboxed process that 1009 # does not otherwise have permission to access the filesystem directly. This is usually an 1010 # optimization: the sending process could instead provide an RPC interface supporting all the 1011 # operations needed (such as reading and writing a file), but by passing the file descriptor 1012 # directly, the recipient can often perform operations much more efficiently. Application 1013 # designers are encouraged to provide such RPC interfaces and automatically fall back to them 1014 # when FD passing is not available, so that the application can still work when the parties are 1015 # remote over a network. 1016 # 1017 # An attached FD is most often associated with a `senderHosted` descriptor. It could also make 1018 # sense in the case of `thirdPartyHosted`: in this case, the sender is forwarding the FD that 1019 # they received from the third party, so that the receiver can start using it without first 1020 # interacting with the third party. This is an optional optimization -- the middleman may choose 1021 # not to forward capabilities, in which case the receiver will need to complete the handshake 1022 # with the third party directly before receiving the FD. If an implementation receives a second 1023 # attached FD after having already received one previously (e.g. both in a `thirdPartyHosted` 1024 # CapDescriptor and then later again when receiving the final capability directly from the 1025 # third party), the implementation should discard the later FD and stick with the original. At 1026 # present, there is no known reason why other capability types (e.g. `receiverHosted`) would want 1027 # to carry an attached FD, but we reserve the right to define a meaning for this in the future. 1028 # 1029 # Each file descriptor attached to the message must be used in no more than one CapDescriptor, 1030 # so that the receiver does not need to use dup() or refcounting to handle the possibility of 1031 # multiple capabilities using the same descriptor. If multiple CapDescriptors do point to the 1032 # same FD index, then the receiver can arbitrarily choose which capability ends up having the 1033 # FD attached. 1034 # 1035 # To mitigate DoS attacks, RPC implementations should limit the number of FDs they are willing to 1036 # receive in a single message to a small value. If a message happens to contain more than that, 1037 # the list is truncated. Moreover, in some cases, FD passing needs to be blocked entirely for 1038 # security or implementation reasons, in which case the list may be truncated to zero. Hence, 1039 # `attachedFd` might point past the end of the list, which the implementation should treat as if 1040 # no FD was attached at all. 1041 # 1042 # The type of this field was chosen to be UInt8 because Linux supports sending only a maximum 1043 # of 253 file descriptors in an SCM_RIGHTS message anyway, and CapDescriptor had two bytes of 1044 # padding left -- so after adding this, there is still one byte for a future feature. 1045 # Conveniently, this also means we're able to use 0xff as the default value, which will always 1046 # be out-of-range (of course, the implementation should explicitly enforce that 255 descriptors 1047 # cannot be sent at once, rather than relying on Linux to do so). 1048 } 1049 1050 struct PromisedAnswer { 1051 # **(mostly level 1)** 1052 # 1053 # Specifies how to derive a promise from an unanswered question, by specifying the path of fields 1054 # to follow from the root of the eventual result struct to get to the desired capability. Used 1055 # to address method calls to a not-yet-returned capability or to pass such a capability as an 1056 # input to some other method call. 1057 # 1058 # Level 0 implementations must support `PromisedAnswer` only for the case where the answer is 1059 # to a `Bootstrap` message. In this case, `path` is always empty since `Bootstrap` always returns 1060 # a raw capability. 1061 1062 questionId @0 :QuestionId; 1063 # ID of the question (in the sender's question table / receiver's answer table) whose answer is 1064 # expected to contain the capability. 1065 1066 transform @1 :List(Op); 1067 # Operations / transformations to apply to the result in order to get the capability actually 1068 # being addressed. E.g. if the result is a struct and you want to call a method on a capability 1069 # pointed to by a field of the struct, you need a `getPointerField` op. 1070 1071 struct Op { 1072 union { 1073 noop @0 :Void; 1074 # Does nothing. This member is mostly defined so that we can make `Op` a union even 1075 # though (as of this writing) only one real operation is defined. 1076 1077 getPointerField @1 :UInt16; 1078 # Get a pointer field within a struct. The number is an index into the pointer section, NOT 1079 # a field ordinal, so that the receiver does not need to understand the schema. 1080 1081 # TODO(someday): We could add: 1082 # - For lists, the ability to address every member of the list, or a slice of the list, the 1083 # result of which would be another list. This is useful for implementing the equivalent of 1084 # a SQL table join (not to be confused with the `Join` message type). 1085 # - Maybe some ability to test a union. 1086 # - Probably not a good idea: the ability to specify an arbitrary script to run on the 1087 # result. We could define a little stack-based language where `Op` specifies one 1088 # "instruction" or transformation to apply. Although this is not a good idea 1089 # (over-engineered), any narrower additions to `Op` should be designed as if this 1090 # were the eventual goal. 1091 } 1092 } 1093 } 1094 1095 struct ThirdPartyCapDescriptor { 1096 # **(level 3)** 1097 # 1098 # Identifies a capability in a third-party vat that the sender wants the receiver to pick up. 1099 1100 id @0 :ThirdPartyCapId; 1101 # Identifies the third-party host and the specific capability to accept from it. 1102 1103 vineId @1 :ExportId; 1104 # A proxy for the third-party object exported by the sender. In CapTP terminology this is called 1105 # a "vine", because it is an indirect reference to the third-party object that snakes through the 1106 # sender vat. This serves two purposes: 1107 # 1108 # * Level 1 and 2 implementations that don't understand how to connect to a third party may 1109 # simply send calls to the vine. Such calls will be forwarded to the third-party by the 1110 # sender. 1111 # 1112 # * Level 3 implementations must release the vine only once they have successfully picked up the 1113 # object from the third party. This ensures that the capability is not released by the sender 1114 # prematurely. 1115 # 1116 # The sender will close the `Provide` request that it has sent to the third party as soon as 1117 # it receives either a `Call` or a `Release` message directed at the vine. 1118 } 1119 1120 struct Exception { 1121 # **(level 0)** 1122 # 1123 # Describes an arbitrary error that prevented an operation (e.g. a call) from completing. 1124 # 1125 # Cap'n Proto exceptions always indicate that something went wrong. In other words, in a fantasy 1126 # world where everything always works as expected, no exceptions would ever be thrown. Clients 1127 # should only ever catch exceptions as a means to implement fault-tolerance, where "fault" can 1128 # mean: 1129 # - Bugs. 1130 # - Invalid input. 1131 # - Configuration errors. 1132 # - Network problems. 1133 # - Insufficient resources. 1134 # - Version skew (unimplemented functionality). 1135 # - Other logistical problems. 1136 # 1137 # Exceptions should NOT be used to flag application-specific conditions that a client is expected 1138 # to handle in an application-specific way. Put another way, in the Cap'n Proto world, 1139 # "checked exceptions" (where an interface explicitly defines the exceptions it throws and 1140 # clients are forced by the type system to handle those exceptions) do NOT make sense. 1141 1142 reason @0 :Text; 1143 # Human-readable failure description. 1144 1145 type @3 :Type; 1146 # The type of the error. The purpose of this enum is not to describe the error itself, but 1147 # rather to describe how the client might want to respond to the error. 1148 1149 enum Type { 1150 failed @0; 1151 # A generic problem occurred, and it is believed that if the operation were repeated without 1152 # any change in the state of the world, the problem would occur again. 1153 # 1154 # A client might respond to this error by logging it for investigation by the developer and/or 1155 # displaying it to the user. 1156 1157 overloaded @1; 1158 # The request was rejected due to a temporary lack of resources. 1159 # 1160 # Examples include: 1161 # - There's not enough CPU time to keep up with incoming requests, so some are rejected. 1162 # - The server ran out of RAM or disk space during the request. 1163 # - The operation timed out (took significantly longer than it should have). 1164 # 1165 # A client might respond to this error by scheduling to retry the operation much later. The 1166 # client should NOT retry again immediately since this would likely exacerbate the problem. 1167 1168 disconnected @2; 1169 # The method failed because a connection to some necessary capability was lost. 1170 # 1171 # Examples include: 1172 # - The client introduced the server to a third-party capability, the connection to that third 1173 # party was subsequently lost, and then the client requested that the server use the dead 1174 # capability for something. 1175 # - The client previously requested that the server obtain a capability from some third party. 1176 # The server returned a capability to an object wrapping the third-party capability. Later, 1177 # the server's connection to the third party was lost. 1178 # - The capability has been revoked. Revocation does not necessarily mean that the client is 1179 # no longer authorized to use the capability; it is often used simply as a way to force the 1180 # client to repeat the setup process, perhaps to efficiently move them to a new back-end or 1181 # get them to recognize some other change that has occurred. 1182 # 1183 # A client should normally respond to this error by releasing all capabilities it is currently 1184 # holding related to the one it called and then re-creating them by restoring SturdyRefs and/or 1185 # repeating the method calls used to create them originally. In other words, disconnect and 1186 # start over. This should in turn cause the server to obtain a new copy of the capability that 1187 # it lost, thus making everything work. 1188 # 1189 # If the client receives another `disconnected` error in the process of rebuilding the 1190 # capability and retrying the call, it should treat this as an `overloaded` error: the network 1191 # is currently unreliable, possibly due to load or other temporary issues. 1192 1193 unimplemented @3; 1194 # The server doesn't implement the requested method. If there is some other method that the 1195 # client could call (perhaps an older and/or slower interface), it should try that instead. 1196 # Otherwise, this should be treated like `failed`. 1197 } 1198 1199 obsoleteIsCallersFault @1 :Bool; 1200 # OBSOLETE. Ignore. 1201 1202 obsoleteDurability @2 :UInt16; 1203 # OBSOLETE. See `type` instead. 1204 1205 trace @4 :Text; 1206 # Stack trace text from the remote server. The format is not specified. By default, 1207 # implementations do not provide stack traces; the application must explicitly enable them 1208 # when desired. 1209 } 1210 1211 # ======================================================================================== 1212 # Network-specific Parameters 1213 # 1214 # Some parts of the Cap'n Proto RPC protocol are not specified here because different vat networks 1215 # may wish to use different approaches to solving them. For example, on the public internet, you 1216 # may want to authenticate vats using public-key cryptography, but on a local intranet with trusted 1217 # infrastructure, you may be happy to authenticate based on network address only, or some other 1218 # lightweight mechanism. 1219 # 1220 # To accommodate this, we specify several "parameter" types. Each type is defined here as an 1221 # alias for `AnyPointer`, but a specific network will want to define a specific set of types to use. 1222 # All vats in a vat network must agree on these parameters in order to be able to communicate. 1223 # Inter-network communication can be accomplished through "gateways" that perform translation 1224 # between the primitives used on each network; these gateways may need to be deeply stateful, 1225 # depending on the translations they perform. 1226 # 1227 # For interaction over the global internet between parties with no other prior arrangement, a 1228 # particular set of bindings for these types is defined elsewhere. (TODO(someday): Specify where 1229 # these common definitions live.) 1230 # 1231 # Another common network type is the two-party network, in which one of the parties typically 1232 # interacts with the outside world entirely through the other party. In such a connection between 1233 # Alice and Bob, all objects that exist on Bob's other networks appear to Alice as if they were 1234 # hosted by Bob himself, and similarly all objects on Alice's network (if she even has one) appear 1235 # to Bob as if they were hosted by Alice. This network type is interesting because from the point 1236 # of view of a simple application that communicates with only one other party via the two-party 1237 # protocol, there are no three-party interactions at all, and joins are unusually simple to 1238 # implement, so implementing at level 4 is barely more complicated than implementing at level 1. 1239 # Moreover, if you pair an app implementing the two-party network with a container that implements 1240 # some other network, the app can then participate on the container's network just as if it 1241 # implemented that network directly. The types used by the two-party network are defined in 1242 # `rpc-twoparty.capnp`. 1243 # 1244 # The things that we need to parameterize are: 1245 # - How to store capabilities long-term without holding a connection open (mostly level 2). 1246 # - How to authenticate vats in three-party introductions (level 3). 1247 # - How to implement `Join` (level 4). 1248 # 1249 # Persistent references 1250 # --------------------- 1251 # 1252 # **(mostly level 2)** 1253 # 1254 # We want to allow some capabilities to be stored long-term, even if a connection is lost and later 1255 # recreated. ExportId is a short-term identifier that is specific to a connection, so it doesn't 1256 # help here. We need a way to specify long-term identifiers, as well as a strategy for 1257 # reconnecting to a referenced capability later. 1258 # 1259 # Three-party interactions 1260 # ------------------------ 1261 # 1262 # **(level 3)** 1263 # 1264 # In cases where more than two vats are interacting, we have situations where VatA holds a 1265 # capability hosted by VatB and wants to send that capability to VatC. This can be accomplished 1266 # by VatA proxying requests on the new capability, but doing so has two big problems: 1267 # - It's inefficient, requiring an extra network hop. 1268 # - If VatC receives another capability to the same object from VatD, it is difficult for VatC to 1269 # detect that the two capabilities are really the same and to implement the E "join" operation, 1270 # which is necessary for certain four-or-more-party interactions, such as the escrow pattern. 1271 # See: http://www.erights.org/elib/equality/grant-matcher/index.html 1272 # 1273 # Instead, we want a way for VatC to form a direct, authenticated connection to VatB. 1274 # 1275 # Join 1276 # ---- 1277 # 1278 # **(level 4)** 1279 # 1280 # The `Join` message type and corresponding operation arranges for a direct connection to be formed 1281 # between the joiner and the host of the joined object, and this connection must be authenticated. 1282 # Thus, the details are network-dependent. 1283 1284 using SturdyRef = AnyPointer; 1285 # **(level 2)** 1286 # 1287 # Identifies a persisted capability that can be restored in the future. How exactly a SturdyRef 1288 # is restored to a live object is specified along with the SturdyRef definition (i.e. not by 1289 # rpc.capnp). 1290 # 1291 # Generally a SturdyRef needs to specify three things: 1292 # - How to reach the vat that can restore the ref (e.g. a hostname or IP address). 1293 # - How to authenticate the vat after connecting (e.g. a public key fingerprint). 1294 # - The identity of a specific object hosted by the vat. Generally, this is an opaque pointer whose 1295 # format is defined by the specific vat -- the client has no need to inspect the object ID. 1296 # It is important that the object ID be unguessable if the object is not public (and objects 1297 # should almost never be public). 1298 # 1299 # The above are only suggestions. Some networks might work differently. For example, a private 1300 # network might employ a special restorer service whose sole purpose is to restore SturdyRefs. 1301 # In this case, the entire contents of SturdyRef might be opaque, because they are intended only 1302 # to be forwarded to the restorer service. 1303 1304 using ProvisionId = AnyPointer; 1305 # **(level 3)** 1306 # 1307 # The information that must be sent in an `Accept` message to identify the object being accepted. 1308 # 1309 # In a network where each vat has a public/private key pair, this could simply be the public key 1310 # fingerprint of the provider vat along with a nonce matching the one in the `RecipientId` used 1311 # in the `Provide` message sent from that provider. 1312 1313 using RecipientId = AnyPointer; 1314 # **(level 3)** 1315 # 1316 # The information that must be sent in a `Provide` message to identify the recipient of the 1317 # capability. 1318 # 1319 # In a network where each vat has a public/private key pair, this could simply be the public key 1320 # fingerprint of the recipient along with a nonce matching the one in the `ProvisionId`. 1321 # 1322 # As another example, when communicating between processes on the same machine over Unix sockets, 1323 # RecipientId could simply refer to a file descriptor attached to the message via SCM_RIGHTS. 1324 # This file descriptor would be one end of a newly-created socketpair, with the other end having 1325 # been sent to the capability's recipient in ThirdPartyCapId. 1326 1327 using ThirdPartyCapId = AnyPointer; 1328 # **(level 3)** 1329 # 1330 # The information needed to connect to a third party and accept a capability from it. 1331 # 1332 # In a network where each vat has a public/private key pair, this could be a combination of the 1333 # third party's public key fingerprint, hints on how to connect to the third party (e.g. an IP 1334 # address), and the nonce used in the corresponding `Provide` message's `RecipientId` as sent 1335 # to that third party (used to identify which capability to pick up). 1336 # 1337 # As another example, when communicating between processes on the same machine over Unix sockets, 1338 # ThirdPartyCapId could simply refer to a file descriptor attached to the message via SCM_RIGHTS. 1339 # This file descriptor would be one end of a newly-created socketpair, with the other end having 1340 # been sent to the process hosting the capability in RecipientId. 1341 1342 using JoinKeyPart = AnyPointer; 1343 # **(level 4)** 1344 # 1345 # A piece of a secret key. One piece is sent along each path that is expected to lead to the same 1346 # place. Once the pieces are combined, a direct connection may be formed between the sender and 1347 # the receiver, bypassing any men-in-the-middle along the paths. See the `Join` message type. 1348 # 1349 # The motivation for Joins is discussed under "Supporting Equality" in the "Unibus" protocol 1350 # sketch: http://www.erights.org/elib/distrib/captp/unibus.html 1351 # 1352 # In a network where each vat has a public/private key pair and each vat forms no more than one 1353 # connection to each other vat, Joins will rarely -- perhaps never -- be needed, as objects never 1354 # need to be transparently proxied and references to the same object sent over the same connection 1355 # have the same export ID. Thus, a successful join requires only checking that the two objects 1356 # come from the same connection and have the same ID, and then completes immediately. 1357 # 1358 # However, in networks where two vats may form more than one connection between each other, or 1359 # where proxying of objects occurs, joins are necessary. 1360 # 1361 # Typically, each JoinKeyPart would include a fixed-length data value such that all value parts 1362 # XOR'd together forms a shared secret that can be used to form an encrypted connection between 1363 # the joiner and the joined object's host. Each JoinKeyPart should also include an indication of 1364 # how many parts to expect and a hash of the shared secret (used to match up parts). 1365 1366 using JoinResult = AnyPointer; 1367 # **(level 4)** 1368 # 1369 # Information returned as the result to a `Join` message, needed by the joiner in order to form a 1370 # direct connection to a joined object. This might simply be the address of the joined object's 1371 # host vat, since the `JoinKey` has already been communicated so the two vats already have a shared 1372 # secret to use to authenticate each other. 1373 # 1374 # The `JoinResult` should also contain information that can be used to detect when the Join 1375 # requests ended up reaching different objects, so that this situation can be detected easily. 1376 # This could be a simple matter of including a sequence number -- if the joiner receives two 1377 # `JoinResult`s with sequence number 0, then they must have come from different objects and the 1378 # whole join is a failure. 1379 1380 # ======================================================================================== 1381 # Network interface sketch 1382 # 1383 # The interfaces below are meant to be pseudo-code to illustrate how the details of a particular 1384 # vat network might be abstracted away. They are written like Cap'n Proto interfaces, but in 1385 # practice you'd probably define these interfaces manually in the target programming language. A 1386 # Cap'n Proto RPC implementation should be able to use these interfaces without knowing the 1387 # definitions of the various network-specific parameters defined above. 1388 1389 # interface VatNetwork { 1390 # # Represents a vat network, with the ability to connect to particular vats and receive 1391 # # connections from vats. 1392 # # 1393 # # Note that methods returning a `Connection` may return a pre-existing `Connection`, and the 1394 # # caller is expected to find and share state with existing users of the connection. 1395 # 1396 # # Level 0 features ----------------------------------------------- 1397 # 1398 # connect(vatId :VatId) :Connection; 1399 # # Connect to the given vat. The transport should return a promise that does not 1400 # # resolve until authentication has completed, but allows messages to be pipelined in before 1401 # # that; the transport either queues these messages until authenticated, or sends them encrypted 1402 # # such that only the authentic vat would be able to decrypt them. The latter approach avoids a 1403 # # round trip for authentication. 1404 # 1405 # accept() :Connection; 1406 # # Wait for the next incoming connection and return it. Only connections formed by 1407 # # connect() are returned by this method. 1408 # 1409 # # Level 4 features ----------------------------------------------- 1410 # 1411 # newJoiner(count :UInt32) :NewJoinerResponse; 1412 # # Prepare a new Join operation, which will eventually lead to forming a new direct connection 1413 # # to the host of the joined capability. `count` is the number of capabilities to join. 1414 # 1415 # struct NewJoinerResponse { 1416 # joinKeyParts :List(JoinKeyPart); 1417 # # Key parts to send in Join messages to each capability. 1418 # 1419 # joiner :Joiner; 1420 # # Used to establish the final connection. 1421 # } 1422 # 1423 # interface Joiner { 1424 # addJoinResult(result :JoinResult) :Void; 1425 # # Add a JoinResult received in response to one of the `Join` messages. All `JoinResult`s 1426 # # returned from all paths must be added before trying to connect. 1427 # 1428 # connect() :ConnectionAndProvisionId; 1429 # # Try to form a connection to the joined capability's host, verifying that it has received 1430 # # all of the JoinKeyParts. Once the connection is formed, the caller should send an `Accept` 1431 # # message on it with the specified `ProvisionId` in order to receive the final capability. 1432 # } 1433 # 1434 # acceptConnectionFromJoiner(parts :List(JoinKeyPart), paths :List(VatPath)) 1435 # :ConnectionAndProvisionId; 1436 # # Called on a joined capability's host to receive the connection from the joiner, once all 1437 # # key parts have arrived. The caller should expect to receive an `Accept` message over the 1438 # # connection with the given ProvisionId. 1439 # } 1440 # 1441 # interface Connection { 1442 # # Level 0 features ----------------------------------------------- 1443 # 1444 # send(message :Message) :Void; 1445 # # Send the message. Returns successfully when the message (and all preceding messages) has 1446 # # been acknowledged by the recipient. 1447 # 1448 # receive() :Message; 1449 # # Receive the next message, and acknowledges receipt to the sender. Messages are received in 1450 # # the order in which they are sent. 1451 # 1452 # # Level 3 features ----------------------------------------------- 1453 # 1454 # introduceTo(recipient :Connection) :IntroductionInfo; 1455 # # Call before starting a three-way introduction, assuming a `Provide` message is to be sent on 1456 # # this connection and a `ThirdPartyCapId` is to be sent to `recipient`. 1457 # 1458 # struct IntroductionInfo { 1459 # sendToRecipient :ThirdPartyCapId; 1460 # sendToTarget :RecipientId; 1461 # } 1462 # 1463 # connectToIntroduced(capId :ThirdPartyCapId) :ConnectionAndProvisionId; 1464 # # Given a ThirdPartyCapId received over this connection, connect to the third party. The 1465 # # caller should then send an `Accept` message over the new connection. 1466 # 1467 # acceptIntroducedConnection(recipientId :RecipientId) :Connection; 1468 # # Given a RecipientId received in a `Provide` message on this `Connection`, wait for the 1469 # # recipient to connect, and return the connection formed. Usually, the first message received 1470 # # on the new connection will be an `Accept` message. 1471 # } 1472 # 1473 # struct ConnectionAndProvisionId { 1474 # # **(level 3)** 1475 # 1476 # connection :Connection; 1477 # # Connection on which to issue `Accept` message. 1478 # 1479 # provision :ProvisionId; 1480 # # `ProvisionId` to send in the `Accept` message. 1481 # }