@stryke/capnp
Version:
A package to assist in running the Cap'n Proto compiler and creating Cap'n Proto serialization protocol schemas.
1,152 lines (1,151 loc) • 88 kB
text/typescript
import { Struct, ObjectSize, Orphan, Pointer, ListCtor, List } from 'capnp-es';
declare const _capnpFileId: bigint;
declare const Message_Which: {
/**
* The sender previously received this message from the peer but didn't understand it or doesn't
* yet implement the functionality that was requested. So, the sender is echoing the message
* back. In some cases, the receiver may be able to recover from this by pretending the sender
* had taken some appropriate "null" action.
*
* For example, say `resolve` is received by a level 0 implementation (because a previous call
* or return happened to contain a promise). The level 0 implementation will echo it back as
* `unimplemented`. The original sender can then simply release the cap to which the promise
* had resolved, thus avoiding a leak.
*
* For any message type that introduces a question, if the message comes back unimplemented,
* the original sender may simply treat it as if the question failed with an exception.
*
* In cases where there is no sensible way to react to an `unimplemented` message (without
* resource leaks or other serious problems), the connection may need to be aborted. This is
* a gray area; different implementations may take different approaches.
*
*/
readonly UNIMPLEMENTED: 0;
/**
* Sent when a connection is being aborted due to an unrecoverable error. This could be e.g.
* because the sender received an invalid or nonsensical message or because the sender had an
* internal error. The sender will shut down the outgoing half of the connection after `abort`
* and will completely close the connection shortly thereafter (it's up to the sender how much
* of a time buffer they want to offer for the client to receive the `abort` before the
* connection is reset).
*
*/
readonly ABORT: 1;
/**
* Request the peer's bootstrap interface.
*
*/
readonly BOOTSTRAP: 8;
/**
* Begin a method call.
*
*/
readonly CALL: 2;
/**
* Complete a method call.
*
*/
readonly RETURN: 3;
/**
* Release a returned answer / cancel a call.
*
*/
readonly FINISH: 4;
/**
* Resolve a previously-sent promise.
*
*/
readonly RESOLVE: 5;
/**
* Release a capability so that the remote object can be deallocated.
*
*/
readonly RELEASE: 6;
/**
* Lift an embargo used to enforce E-order over promise resolution.
*
*/
readonly DISEMBARGO: 13;
/**
* Obsolete request to save a capability, resulting in a SturdyRef. This has been replaced
* by the `Persistent` interface defined in `persistent.capnp`. This operation was never
* implemented.
*
*/
readonly OBSOLETE_SAVE: 7;
/**
* Obsolete way to delete a SturdyRef. This operation was never implemented.
*
*/
readonly OBSOLETE_DELETE: 9;
/**
* Provide a capability to a third party.
*
*/
readonly PROVIDE: 10;
/**
* Accept a capability provided by a third party.
*
*/
readonly ACCEPT: 11;
/**
* Directly connect to the common root of two or more proxied caps.
*
*/
readonly JOIN: 12;
};
type Message_Which = (typeof Message_Which)[keyof typeof Message_Which];
/**
* An RPC connection is a bi-directional stream of Messages.
*
*/
declare class Message extends Struct {
static readonly UNIMPLEMENTED: 0;
static readonly ABORT: 1;
static readonly BOOTSTRAP: 8;
static readonly CALL: 2;
static readonly RETURN: 3;
static readonly FINISH: 4;
static readonly RESOLVE: 5;
static readonly RELEASE: 6;
static readonly DISEMBARGO: 13;
static readonly OBSOLETE_SAVE: 7;
static readonly OBSOLETE_DELETE: 9;
static readonly PROVIDE: 10;
static readonly ACCEPT: 11;
static readonly JOIN: 12;
static readonly _capnp: {
displayName: string;
id: string;
size: ObjectSize;
};
_adoptUnimplemented(value: Orphan<Message>): void;
_disownUnimplemented(): Orphan<Message>;
/**
* The sender previously received this message from the peer but didn't understand it or doesn't
* yet implement the functionality that was requested. So, the sender is echoing the message
* back. In some cases, the receiver may be able to recover from this by pretending the sender
* had taken some appropriate "null" action.
*
* For example, say `resolve` is received by a level 0 implementation (because a previous call
* or return happened to contain a promise). The level 0 implementation will echo it back as
* `unimplemented`. The original sender can then simply release the cap to which the promise
* had resolved, thus avoiding a leak.
*
* For any message type that introduces a question, if the message comes back unimplemented,
* the original sender may simply treat it as if the question failed with an exception.
*
* In cases where there is no sensible way to react to an `unimplemented` message (without
* resource leaks or other serious problems), the connection may need to be aborted. This is
* a gray area; different implementations may take different approaches.
*
*/
get unimplemented(): Message;
_hasUnimplemented(): boolean;
_initUnimplemented(): Message;
get _isUnimplemented(): boolean;
set unimplemented(value: Message);
_adoptAbort(value: Orphan<Exception>): void;
_disownAbort(): Orphan<Exception>;
/**
* Sent when a connection is being aborted due to an unrecoverable error. This could be e.g.
* because the sender received an invalid or nonsensical message or because the sender had an
* internal error. The sender will shut down the outgoing half of the connection after `abort`
* and will completely close the connection shortly thereafter (it's up to the sender how much
* of a time buffer they want to offer for the client to receive the `abort` before the
* connection is reset).
*
*/
get abort(): Exception;
_hasAbort(): boolean;
_initAbort(): Exception;
get _isAbort(): boolean;
set abort(value: Exception);
_adoptBootstrap(value: Orphan<Bootstrap>): void;
_disownBootstrap(): Orphan<Bootstrap>;
/**
* Request the peer's bootstrap interface.
*
*/
get bootstrap(): Bootstrap;
_hasBootstrap(): boolean;
_initBootstrap(): Bootstrap;
get _isBootstrap(): boolean;
set bootstrap(value: Bootstrap);
_adoptCall(value: Orphan<Call>): void;
_disownCall(): Orphan<Call>;
/**
* Begin a method call.
*
*/
get call(): Call;
_hasCall(): boolean;
_initCall(): Call;
get _isCall(): boolean;
set call(value: Call);
_adoptReturn(value: Orphan<Return>): void;
_disownReturn(): Orphan<Return>;
/**
* Complete a method call.
*
*/
get return(): Return;
_hasReturn(): boolean;
_initReturn(): Return;
get _isReturn(): boolean;
set return(value: Return);
_adoptFinish(value: Orphan<Finish>): void;
_disownFinish(): Orphan<Finish>;
/**
* Release a returned answer / cancel a call.
*
*/
get finish(): Finish;
_hasFinish(): boolean;
_initFinish(): Finish;
get _isFinish(): boolean;
set finish(value: Finish);
_adoptResolve(value: Orphan<Resolve>): void;
_disownResolve(): Orphan<Resolve>;
/**
* Resolve a previously-sent promise.
*
*/
get resolve(): Resolve;
_hasResolve(): boolean;
_initResolve(): Resolve;
get _isResolve(): boolean;
set resolve(value: Resolve);
_adoptRelease(value: Orphan<Release>): void;
_disownRelease(): Orphan<Release>;
/**
* Release a capability so that the remote object can be deallocated.
*
*/
get release(): Release;
_hasRelease(): boolean;
_initRelease(): Release;
get _isRelease(): boolean;
set release(value: Release);
_adoptDisembargo(value: Orphan<Disembargo>): void;
_disownDisembargo(): Orphan<Disembargo>;
/**
* Lift an embargo used to enforce E-order over promise resolution.
*
*/
get disembargo(): Disembargo;
_hasDisembargo(): boolean;
_initDisembargo(): Disembargo;
get _isDisembargo(): boolean;
set disembargo(value: Disembargo);
_adoptObsoleteSave(value: Orphan<Pointer>): void;
_disownObsoleteSave(): Orphan<Pointer>;
/**
* Obsolete request to save a capability, resulting in a SturdyRef. This has been replaced
* by the `Persistent` interface defined in `persistent.capnp`. This operation was never
* implemented.
*
*/
get obsoleteSave(): Pointer;
_hasObsoleteSave(): boolean;
get _isObsoleteSave(): boolean;
set obsoleteSave(value: Pointer);
_adoptObsoleteDelete(value: Orphan<Pointer>): void;
_disownObsoleteDelete(): Orphan<Pointer>;
/**
* Obsolete way to delete a SturdyRef. This operation was never implemented.
*
*/
get obsoleteDelete(): Pointer;
_hasObsoleteDelete(): boolean;
get _isObsoleteDelete(): boolean;
set obsoleteDelete(value: Pointer);
_adoptProvide(value: Orphan<Provide>): void;
_disownProvide(): Orphan<Provide>;
/**
* Provide a capability to a third party.
*
*/
get provide(): Provide;
_hasProvide(): boolean;
_initProvide(): Provide;
get _isProvide(): boolean;
set provide(value: Provide);
_adoptAccept(value: Orphan<Accept>): void;
_disownAccept(): Orphan<Accept>;
/**
* Accept a capability provided by a third party.
*
*/
get accept(): Accept;
_hasAccept(): boolean;
_initAccept(): Accept;
get _isAccept(): boolean;
set accept(value: Accept);
_adoptJoin(value: Orphan<Join>): void;
_disownJoin(): Orphan<Join>;
/**
* Directly connect to the common root of two or more proxied caps.
*
*/
get join(): Join;
_hasJoin(): boolean;
_initJoin(): Join;
get _isJoin(): boolean;
set join(value: Join);
toString(): string;
which(): Message_Which;
}
/**
* **(level 0)**
*
* Get the "bootstrap" interface exported by the remote vat.
*
* For level 0, 1, and 2 implementations, the "bootstrap" interface is simply the main interface
* exported by a vat. If the vat acts as a server fielding connections from clients, then the
* bootstrap interface defines the basic functionality available to a client when it connects.
* The exact interface definition obviously depends on the application.
*
* We call this a "bootstrap" because in an ideal Cap'n Proto world, bootstrap interfaces would
* never be used. In such a world, any time you connect to a new vat, you do so because you
* received an introduction from some other vat (see `ThirdPartyCapId`). Thus, the first message
* you send is `Accept`, and further communications derive from there. `Bootstrap` is not used.
*
* In such an ideal world, DNS itself would support Cap'n Proto -- performing a DNS lookup would
* actually return a new Cap'n Proto capability, thus introducing you to the target system via
* level 3 RPC. Applications would receive the capability to talk to DNS in the first place as
* an initial endowment or part of a Powerbox interaction. Therefore, an app can form arbitrary
* connections without ever using `Bootstrap`.
*
* Of course, in the real world, DNS is not Cap'n-Proto-based, and we don't want Cap'n Proto to
* require a whole new internet infrastructure to be useful. Therefore, we offer bootstrap
* interfaces as a way to get up and running without a level 3 introduction. Thus, bootstrap
* interfaces are used to "bootstrap" from other, non-Cap'n-Proto-based means of service discovery,
* such as legacy DNS.
*
* Note that a vat need not provide a bootstrap interface, and in fact many vats (especially those
* acting as clients) do not. In this case, the vat should either reply to `Bootstrap` with a
* `Return` indicating an exception, or should return a dummy capability with no methods.
*
*/
declare class Bootstrap extends Struct {
static readonly _capnp: {
displayName: string;
id: string;
size: ObjectSize;
};
/**
* A new question ID identifying this request, which will eventually receive a Return message
* containing the restored capability.
*
*/
get questionId(): number;
set questionId(value: number);
_adoptDeprecatedObjectId(value: Orphan<Pointer>): void;
_disownDeprecatedObjectId(): Orphan<Pointer>;
/**
* ** DEPRECATED **
*
* A Vat may export multiple bootstrap interfaces. In this case, `deprecatedObjectId` specifies
* which one to return. If this pointer is null, then the default bootstrap interface is returned.
*
* As of version 0.5, use of this field is deprecated. If a service wants to export multiple
* bootstrap interfaces, it should instead define a single bootstrap interface that has methods
* that return each of the other interfaces.
*
* **History**
*
* In the first version of Cap'n Proto RPC (0.4.x) the `Bootstrap` message was called `Restore`.
* At the time, it was thought that this would eventually serve as the way to restore SturdyRefs
* (level 2). Meanwhile, an application could offer its "main" interface on a well-known
* (non-secret) SturdyRef.
*
* Since level 2 RPC was not implemented at the time, the `Restore` message was in practice only
* used to obtain the main interface. Since most applications had only one main interface that
* they wanted to restore, they tended to designate this with a null `objectId`.
*
* Unfortunately, the earliest version of the EZ RPC interfaces set a precedent of exporting
* multiple main interfaces by allowing them to be exported under string names. In this case,
* `objectId` was a Text value specifying the name.
*
* All of this proved problematic for several reasons:
*
* - The arrangement assumed that a client wishing to restore a SturdyRef would know exactly what
* machine to connect to and would be able to immediately restore a SturdyRef on connection.
* However, in practice, the ability to restore SturdyRefs is itself a capability that may
* require going through an authentication process to obtain. Thus, it makes more sense to
* define a "restorer service" as a full Cap'n Proto interface. If this restorer interface is
* offered as the vat's bootstrap interface, then this is equivalent to the old arrangement.
*
* - Overloading "Restore" for the purpose of obtaining well-known capabilities encouraged the
* practice of exporting singleton services with string names. If singleton services are desired,
* it is better to have one main interface that has methods that can be used to obtain each
* service, in order to get all the usual benefits of schemas and type checking.
*
* - Overloading "Restore" also had a security problem: Often, "main" or "well-known"
* capabilities exported by a vat are in fact not public: they are intended to be accessed only
* by clients who are capable of forming a connection to the vat. This can lead to trouble if
* the client itself has other clients and wishes to forward some `Restore` requests from those
* external clients -- it has to be very careful not to allow through `Restore` requests
* addressing the default capability.
*
* For example, consider the case of a sandboxed Sandstorm application and its supervisor. The
* application exports a default capability to its supervisor that provides access to
* functionality that only the supervisor is supposed to access. Meanwhile, though, applications
* may publish other capabilities that may be persistent, in which case the application needs
* to field `Restore` requests that could come from anywhere. These requests of course have to
* pass through the supervisor, as all communications with the outside world must. But, the
* supervisor has to be careful not to honor an external request addressing the application's
* default capability, since this capability is privileged. Unfortunately, the default
* capability cannot be given an unguessable name, because then the supervisor itself would not
* be able to address it!
*
* As of Cap'n Proto 0.5, `Restore` has been renamed to `Bootstrap` and is no longer planned for
* use in restoring SturdyRefs.
*
* Note that 0.4 also defined a message type called `Delete` that, like `Restore`, addressed a
* SturdyRef, but indicated that the client would not restore the ref again in the future. This
* operation was never implemented, so it was removed entirely. If a "delete" operation is desired,
* it should exist as a method on the same interface that handles restoring SturdyRefs. However,
* the utility of such an operation is questionable. You wouldn't be able to rely on it for
* garbage collection since a client could always disappear permanently without remembering to
* delete all its SturdyRefs, thus leaving them dangling forever. Therefore, it is advisable to
* design systems such that SturdyRefs never represent "owned" pointers.
*
* For example, say a SturdyRef points to an image file hosted on some server. That image file
* should also live inside a collection (a gallery, perhaps) hosted on the same server, owned by
* a user who can delete the image at any time. If the user deletes the image, the SturdyRef
* stops working. On the other hand, if the SturdyRef is discarded, this has no effect on the
* existence of the image in its collection.
*
*/
get deprecatedObjectId(): Pointer;
_hasDeprecatedObjectId(): boolean;
set deprecatedObjectId(value: Pointer);
toString(): string;
}
declare const Call_SendResultsTo_Which: {
/**
* Send the return message back to the caller (the usual).
*
*/
readonly CALLER: 0;
/**
* **(level 1)**
*
* Don't actually return the results to the sender. Instead, hold on to them and await
* instructions from the sender regarding what to do with them. In particular, the sender
* may subsequently send a `Return` for some other call (which the receiver had previously made
* to the sender) with `takeFromOtherQuestion` set. The results from this call are then used
* as the results of the other call.
*
* When `yourself` is used, the receiver must still send a `Return` for the call, but sets the
* field `resultsSentElsewhere` in that `Return` rather than including the results.
*
* This feature can be used to implement tail calls in which a call from Vat A to Vat B ends up
* returning the result of a call from Vat B back to Vat A.
*
* In particular, the most common use case for this feature is when Vat A makes a call to a
* promise in Vat B, and then that promise ends up resolving to a capability back in Vat A.
* Vat B must forward all the queued calls on that promise back to Vat A, but can set `yourself`
* in the calls so that the results need not pass back through Vat B.
*
* For example:
* - Alice, in Vat A, calls foo() on Bob in Vat B.
* - Alice makes a pipelined call bar() on the promise returned by foo().
* - Later on, Bob resolves the promise from foo() to point at Carol, who lives in Vat A (next
* to Alice).
* - Vat B dutifully forwards the bar() call to Carol. Let us call this forwarded call bar'().
* Notice that bar() and bar'() are travelling in opposite directions on the same network
* link.
* - The `Call` for bar'() has `sendResultsTo` set to `yourself`.
* - Vat B sends a `Return` for bar() with `takeFromOtherQuestion` set in place of the results,
* with the value set to the question ID of bar'(). Vat B does not wait for bar'() to return,
* as doing so would introduce unnecessary round trip latency.
* - Vat A receives bar'() and delivers it to Carol.
* - When bar'() returns, Vat A sends a `Return` for bar'() to Vat B, with `resultsSentElsewhere`
* set in place of results.
* - Vat A sends a `Finish` for the bar() call to Vat B.
* - Vat B receives the `Finish` for bar() and sends a `Finish` for bar'().
*
*/
readonly YOURSELF: 1;
/**
* **(level 3)**
*
* The call's result should be returned to a different vat. The receiver (the callee) expects
* to receive an `Accept` message from the indicated vat, and should return the call's result
* to it, rather than to the sender of the `Call`.
*
* This operates much like `yourself`, above, except that Carol is in a separate Vat C. `Call`
* messages are sent from Vat A -> Vat B and Vat B -> Vat C. A `Return` message is sent from
* Vat B -> Vat A that contains `acceptFromThirdParty` in place of results. When Vat A sends
* an `Accept` to Vat C, it receives back a `Return` containing the call's actual result. Vat C
* also sends a `Return` to Vat B with `resultsSentElsewhere`.
*
*/
readonly THIRD_PARTY: 2;
};
type Call_SendResultsTo_Which = (typeof Call_SendResultsTo_Which)[keyof typeof Call_SendResultsTo_Which];
/**
* Where should the return message be sent?
*
*/
declare class Call_SendResultsTo extends Struct {
static readonly CALLER: 0;
static readonly YOURSELF: 1;
static readonly THIRD_PARTY: 2;
static readonly _capnp: {
displayName: string;
id: string;
size: ObjectSize;
};
get _isCaller(): boolean;
set caller(_: true);
get _isYourself(): boolean;
set yourself(_: true);
_adoptThirdParty(value: Orphan<Pointer>): void;
_disownThirdParty(): Orphan<Pointer>;
/**
* **(level 3)**
*
* The call's result should be returned to a different vat. The receiver (the callee) expects
* to receive an `Accept` message from the indicated vat, and should return the call's result
* to it, rather than to the sender of the `Call`.
*
* This operates much like `yourself`, above, except that Carol is in a separate Vat C. `Call`
* messages are sent from Vat A -> Vat B and Vat B -> Vat C. A `Return` message is sent from
* Vat B -> Vat A that contains `acceptFromThirdParty` in place of results. When Vat A sends
* an `Accept` to Vat C, it receives back a `Return` containing the call's actual result. Vat C
* also sends a `Return` to Vat B with `resultsSentElsewhere`.
*
*/
get thirdParty(): Pointer;
_hasThirdParty(): boolean;
get _isThirdParty(): boolean;
set thirdParty(value: Pointer);
toString(): string;
which(): Call_SendResultsTo_Which;
}
/**
* **(level 0)**
*
* Message type initiating a method call on a capability.
*
*/
declare class Call extends Struct {
static readonly _capnp: {
displayName: string;
id: string;
size: ObjectSize;
defaultAllowThirdPartyTailCall: DataView<ArrayBufferLike>;
defaultNoPromisePipelining: DataView<ArrayBufferLike>;
defaultOnlyPromisePipeline: DataView<ArrayBufferLike>;
};
/**
* A number, chosen by the caller, that identifies this call in future messages. This number
* must be different from all other calls originating from the same end of the connection (but
* may overlap with question IDs originating from the opposite end). A fine strategy is to use
* sequential question IDs, but the recipient should not assume this.
*
* A question ID can be reused once both:
* - A matching Return has been received from the callee.
* - A matching Finish has been sent from the caller.
*
*/
get questionId(): number;
set questionId(value: number);
_adoptTarget(value: Orphan<MessageTarget>): void;
_disownTarget(): Orphan<MessageTarget>;
/**
* The object that should receive this call.
*
*/
get target(): MessageTarget;
_hasTarget(): boolean;
_initTarget(): MessageTarget;
set target(value: MessageTarget);
/**
* The type ID of the interface being called. Each capability may implement multiple interfaces.
*
*/
get interfaceId(): bigint;
set interfaceId(value: bigint);
/**
* The ordinal number of the method to call within the requested interface.
*
*/
get methodId(): number;
set methodId(value: number);
/**
* Indicates whether or not the receiver is allowed to send a `Return` containing
* `acceptFromThirdParty`. Level 3 implementations should set this true. Otherwise, the callee
* will have to proxy the return in the case of a tail call to a third-party vat.
*
*/
get allowThirdPartyTailCall(): boolean;
set allowThirdPartyTailCall(value: boolean);
/**
* If true, the sender promises that it won't make any promise-pipelined calls on the results of
* this call. If it breaks this promise, the receiver may throw an arbitrary error from such
* calls.
*
* The receiver may use this as an optimization, by skipping the bookkeeping needed for pipelining
* when no pipelined calls are expected. The sender typically sets this to false when the method's
* schema does not specify any return capabilities.
*
*/
get noPromisePipelining(): boolean;
set noPromisePipelining(value: boolean);
/**
* If true, the sender only plans to use this call to make pipelined calls. The receiver need not
* send a `Return` message (but is still allowed to do so).
*
* Since the sender does not know whether a `Return` will be sent, it must release all state
* related to the call when it sends `Finish`. However, in the case that the callee does not
* recognize this hint and chooses to send a `Return`, then technically the caller is not allowed
* to reuse the question ID until it receives said `Return`. This creates a conundrum: How does
* the caller decide when it's OK to reuse the ID? To sidestep the problem, the C++ implementation
* uses high-numbered IDs (with the high-order bit set) for such calls, and cycles through the
* IDs in order. If all 2^31 IDs in this space are used without ever seeing a `Return`, then the
* implementation assumes that the other end is in fact honoring the hint, and the ID counter is
* allowed to loop around. If a `Return` is ever seen when `onlyPromisePipeline` was set, then
* the implementation stops using this hint.
*
*/
get onlyPromisePipeline(): boolean;
set onlyPromisePipeline(value: boolean);
_adoptParams(value: Orphan<Payload>): void;
_disownParams(): Orphan<Payload>;
/**
* The call parameters. `params.content` is a struct whose fields correspond to the parameters of
* the method.
*
*/
get params(): Payload;
_hasParams(): boolean;
_initParams(): Payload;
set params(value: Payload);
/**
* Where should the return message be sent?
*
*/
get sendResultsTo(): Call_SendResultsTo;
_initSendResultsTo(): Call_SendResultsTo;
toString(): string;
}
declare const Return_Which: {
/**
* Equal to the QuestionId of the corresponding `Call` message.
*
*/
readonly RESULTS: 0;
/**
* If true, all capabilities that were in the params should be considered released. The sender
* must not send separate `Release` messages for them. Level 0 implementations in particular
* should always set this true. This defaults true because if level 0 implementations forget to
* set it they'll never notice (just silently leak caps), but if level >=1 implementations forget
* to set it to false they'll quickly get errors.
*
* The receiver should act as if the sender had sent a release message with count=1 for each
* CapDescriptor in the original Call message.
*
*/
readonly EXCEPTION: 1;
/**
* The result.
*
* For regular method calls, `results.content` points to the result struct.
*
* For a `Return` in response to an `Accept` or `Bootstrap`, `results` contains a single
* capability (rather than a struct), and `results.content` is just a capability pointer with
* index 0. A `Finish` is still required in this case.
*
*/
readonly CANCELED: 2;
/**
* Indicates that the call failed and explains why.
*
*/
readonly RESULTS_SENT_ELSEWHERE: 3;
/**
* Indicates that the call was canceled due to the caller sending a Finish message
* before the call had completed.
*
*/
readonly TAKE_FROM_OTHER_QUESTION: 4;
/**
* This is set when returning from a `Call` that had `sendResultsTo` set to something other
* than `caller`.
*
* It doesn't matter too much when this is sent, as the receiver doesn't need to do anything
* with it, but the C++ implementation appears to wait for the call to finish before sending
* this.
*
*/
readonly ACCEPT_FROM_THIRD_PARTY: 5;
};
type Return_Which = (typeof Return_Which)[keyof typeof Return_Which];
/**
* **(level 0)**
*
* Message type sent from callee to caller indicating that the call has completed.
*
*/
declare class Return extends Struct {
static readonly RESULTS: 0;
static readonly EXCEPTION: 1;
static readonly CANCELED: 2;
static readonly RESULTS_SENT_ELSEWHERE: 3;
static readonly TAKE_FROM_OTHER_QUESTION: 4;
static readonly ACCEPT_FROM_THIRD_PARTY: 5;
static readonly _capnp: {
displayName: string;
id: string;
size: ObjectSize;
defaultReleaseParamCaps: DataView<ArrayBufferLike>;
defaultNoFinishNeeded: DataView<ArrayBufferLike>;
};
/**
* Equal to the QuestionId of the corresponding `Call` message.
*
*/
get answerId(): number;
set answerId(value: number);
/**
* If true, all capabilities that were in the params should be considered released. The sender
* must not send separate `Release` messages for them. Level 0 implementations in particular
* should always set this true. This defaults true because if level 0 implementations forget to
* set it they'll never notice (just silently leak caps), but if level >=1 implementations forget
* to set it to false they'll quickly get errors.
*
* The receiver should act as if the sender had sent a release message with count=1 for each
* CapDescriptor in the original Call message.
*
*/
get releaseParamCaps(): boolean;
set releaseParamCaps(value: boolean);
/**
* If true, the sender does not need the receiver to send a `Finish` message; its answer table
* entry has already been cleaned up. This implies that the results do not contain any
* capabilities, since the `Finish` message would normally release those capabilities from
* promise pipelining responsibility. The caller may still send a `Finish` message if it wants,
* which will be silently ignored by the callee.
*
*/
get noFinishNeeded(): boolean;
set noFinishNeeded(value: boolean);
_adoptResults(value: Orphan<Payload>): void;
_disownResults(): Orphan<Payload>;
/**
* The result.
*
* For regular method calls, `results.content` points to the result struct.
*
* For a `Return` in response to an `Accept` or `Bootstrap`, `results` contains a single
* capability (rather than a struct), and `results.content` is just a capability pointer with
* index 0. A `Finish` is still required in this case.
*
*/
get results(): Payload;
_hasResults(): boolean;
_initResults(): Payload;
get _isResults(): boolean;
set results(value: Payload);
_adoptException(value: Orphan<Exception>): void;
_disownException(): Orphan<Exception>;
/**
* Indicates that the call failed and explains why.
*
*/
get exception(): Exception;
_hasException(): boolean;
_initException(): Exception;
get _isException(): boolean;
set exception(value: Exception);
get _isCanceled(): boolean;
set canceled(_: true);
get _isResultsSentElsewhere(): boolean;
set resultsSentElsewhere(_: true);
/**
* The sender has also sent (before this message) a `Call` with the given question ID and with
* `sendResultsTo.yourself` set, and the results of that other call should be used as the
* results here. `takeFromOtherQuestion` can only used once per question.
*
*/
get takeFromOtherQuestion(): number;
get _isTakeFromOtherQuestion(): boolean;
set takeFromOtherQuestion(value: number);
_adoptAcceptFromThirdParty(value: Orphan<Pointer>): void;
_disownAcceptFromThirdParty(): Orphan<Pointer>;
/**
* **(level 3)**
*
* The caller should contact a third-party vat to pick up the results. An `Accept` message
* sent to the vat will return the result. This pairs with `Call.sendResultsTo.thirdParty`.
* It should only be used if the corresponding `Call` had `allowThirdPartyTailCall` set.
*
*/
get acceptFromThirdParty(): Pointer;
_hasAcceptFromThirdParty(): boolean;
get _isAcceptFromThirdParty(): boolean;
set acceptFromThirdParty(value: Pointer);
toString(): string;
which(): Return_Which;
}
/**
* **(level 0)**
*
* Message type sent from the caller to the callee to indicate:
* 1) The questionId will no longer be used in any messages sent by the callee (no further
* pipelined requests).
* 2) If the call has not returned yet, the caller no longer cares about the result. If nothing
* else cares about the result either (e.g. there are no other outstanding calls pipelined on
* the result of this one) then the callee may wish to immediately cancel the operation and
* send back a Return message with "canceled" set. However, implementations are not required
* to support premature cancellation -- instead, the implementation may wait until the call
* actually completes and send a normal `Return` message.
*
* TODO(someday): Should we separate (1) and implicitly releasing result capabilities? It would be
* possible and useful to notify the server that it doesn't need to keep around the response to
* service pipeline requests even though the caller still wants to receive it / hasn't yet
* finished processing it. It could also be useful to notify the server that it need not marshal
* the results because the caller doesn't want them anyway, even if the caller is still sending
* pipelined calls, although this seems less useful (just saving some bytes on the wire).
*
*/
declare class Finish extends Struct {
static readonly _capnp: {
displayName: string;
id: string;
size: ObjectSize;
defaultReleaseResultCaps: DataView<ArrayBufferLike>;
defaultRequireEarlyCancellationWorkaround: DataView<ArrayBufferLike>;
};
/**
* ID of the call whose result is to be released.
*
*/
get questionId(): number;
set questionId(value: number);
/**
* If true, all capabilities that were in the results should be considered released. The sender
* must not send separate `Release` messages for them. Level 0 implementations in particular
* should always set this true. This defaults true because if level 0 implementations forget to
* set it they'll never notice (just silently leak caps), but if level >=1 implementations forget
* set it false they'll quickly get errors.
*
*/
get releaseResultCaps(): boolean;
set releaseResultCaps(value: boolean);
/**
* If true, if the RPC system receives this Finish message before the original call has even been
* delivered, it should defer cancellation util after delivery. In particular, this gives the
* destination object a chance to opt out of cancellation, e.g. as controlled by the
* `allowCancellation` annotation defined in `c++.capnp`.
*
* This is a work-around. Versions 1.0 and up of Cap'n Proto always set this to false. However,
* older versions of Cap'n Proto unintentionally exhibited this errant behavior by default, and
* as a result programs built with older versions could be inadvertently relying on their peers
* to implement the behavior. The purpose of this flag is to let newer versions know when the
* peer is an older version, so that it can attempt to work around the issue.
*
* See also comments in handleFinish() in rpc.c++ for more details.
*
*/
get requireEarlyCancellationWorkaround(): boolean;
set requireEarlyCancellationWorkaround(value: boolean);
toString(): string;
}
declare const Resolve_Which: {
/**
* The ID of the promise to be resolved.
*
* Unlike all other instances of `ExportId` sent from the exporter, the `Resolve` message does
* _not_ increase the reference count of `promiseId`. In fact, it is expected that the receiver
* will release the export soon after receiving `Resolve`, and the sender will not send this
* `ExportId` again until it has been released and recycled.
*
* When an export ID sent over the wire (e.g. in a `CapDescriptor`) is indicated to be a promise,
* this indicates that the sender will follow up at some point with a `Resolve` message. If the
* same `promiseId` is sent again before `Resolve`, still only one `Resolve` is sent. If the
* same ID is sent again later _after_ a `Resolve`, it can only be because the export's
* reference count hit zero in the meantime and the ID was re-assigned to a new export, therefore
* this later promise does _not_ correspond to the earlier `Resolve`.
*
* If a promise ID's reference count reaches zero before a `Resolve` is sent, the `Resolve`
* message may or may not still be sent (the `Resolve` may have already been in-flight when
* `Release` was sent, but if the `Release` is received before `Resolve` then there is no longer
* any reason to send a `Resolve`). Thus a `Resolve` may be received for a promise of which
* the receiver has no knowledge, because it already released it earlier. In this case, the
* receiver should simply release the capability to which the promise resolved.
*
*/
readonly CAP: 0;
/**
* The object to which the promise resolved.
*
* The sender promises that from this point forth, until `promiseId` is released, it shall
* simply forward all messages to the capability designated by `cap`. This is true even if
* `cap` itself happens to designate another promise, and that other promise later resolves --
* messages sent to `promiseId` shall still go to that other promise, not to its resolution.
* This is important in the case that the receiver of the `Resolve` ends up sending a
* `Disembargo` message towards `promiseId` in order to control message ordering -- that
* `Disembargo` really needs to reflect back to exactly the object designated by `cap` even
* if that object is itself a promise.
*
*/
readonly EXCEPTION: 1;
};
type Resolve_Which = (typeof Resolve_Which)[keyof typeof Resolve_Which];
/**
* **(level 1)**
*
* Message type sent to indicate that a previously-sent promise has now been resolved to some other
* object (possibly another promise) -- or broken, or canceled.
*
* Keep in mind that it's possible for a `Resolve` to be sent to a level 0 implementation that
* doesn't implement it. For example, a method call or return might contain a capability in the
* payload. Normally this is fine even if the receiver is level 0, because they will implicitly
* release all such capabilities on return / finish. But if the cap happens to be a promise, then
* a follow-up `Resolve` may be sent regardless of this release. The level 0 receiver will reply
* with an `unimplemented` message, and the sender (of the `Resolve`) can respond to this as if the
* receiver had immediately released any capability to which the promise resolved.
*
* When implementing promise resolution, it's important to understand how embargos work and the
* tricky case of the Tribble 4-way race condition. See the comments for the Disembargo message,
* below.
*
*/
declare class Resolve extends Struct {
static readonly CAP: 0;
static readonly EXCEPTION: 1;
static readonly _capnp: {
displayName: string;
id: string;
size: ObjectSize;
};
/**
* The ID of the promise to be resolved.
*
* Unlike all other instances of `ExportId` sent from the exporter, the `Resolve` message does
* _not_ increase the reference count of `promiseId`. In fact, it is expected that the receiver
* will release the export soon after receiving `Resolve`, and the sender will not send this
* `ExportId` again until it has been released and recycled.
*
* When an export ID sent over the wire (e.g. in a `CapDescriptor`) is indicated to be a promise,
* this indicates that the sender will follow up at some point with a `Resolve` message. If the
* same `promiseId` is sent again before `Resolve`, still only one `Resolve` is sent. If the
* same ID is sent again later _after_ a `Resolve`, it can only be because the export's
* reference count hit zero in the meantime and the ID was re-assigned to a new export, therefore
* this later promise does _not_ correspond to the earlier `Resolve`.
*
* If a promise ID's reference count reaches zero before a `Resolve` is sent, the `Resolve`
* message may or may not still be sent (the `Resolve` may have already been in-flight when
* `Release` was sent, but if the `Release` is received before `Resolve` then there is no longer
* any reason to send a `Resolve`). Thus a `Resolve` may be received for a promise of which
* the receiver has no knowledge, because it already released it earlier. In this case, the
* receiver should simply release the capability to which the promise resolved.
*
*/
get promiseId(): number;
set promiseId(value: number);
_adoptCap(value: Orphan<CapDescriptor>): void;
_disownCap(): Orphan<CapDescriptor>;
/**
* The object to which the promise resolved.
*
* The sender promises that from this point forth, until `promiseId` is released, it shall
* simply forward all messages to the capability designated by `cap`. This is true even if
* `cap` itself happens to designate another promise, and that other promise later resolves --
* messages sent to `promiseId` shall still go to that other promise, not to its resolution.
* This is important in the case that the receiver of the `Resolve` ends up sending a
* `Disembargo` message towards `promiseId` in order to control message ordering -- that
* `Disembargo` really needs to reflect back to exactly the object designated by `cap` even
* if that object is itself a promise.
*
*/
get cap(): CapDescriptor;
_hasCap(): boolean;
_initCap(): CapDescriptor;
get _isCap(): boolean;
set cap(value: CapDescriptor);
_adoptException(value: Orphan<Exception>): void;
_disownException(): Orphan<Exception>;
/**
* Indicates that the promise was broken.
*
*/
get exception(): Exception;
_hasException(): boolean;
_initException(): Exception;
get _isException(): boolean;
set exception(value: Exception);
toString(): string;
which(): Resolve_Which;
}
/**
* **(level 1)**
*
* Message type sent to indicate that the sender is done with the given capability and the receiver
* can free resources allocated to it.
*
*/
declare class Release extends Struct {
static readonly _capnp: {
displayName: string;
id: string;
size: ObjectSize;
};
/**
* What to release.
*
*/
get id(): number;
set id(value: number);
/**
* The amount by which to decrement the reference count. The export is only actually released
* when the reference count reaches zero.
*
*/
get referenceCount(): number;
set referenceCount(value: number);
toString(): string;
}
declare const Disembargo_Context_Which: {
/**
* The sender is requesting a disembargo on a promise that is known to resolve back to a
* capability hosted by the sender. As soon as the receiver has echoed back all pipelined calls
* on this promise, it will deliver the Disembargo back to the sender with `receiverLoopback`
* set to the same value as `senderLoopback`. This value is chosen by the sender, and since
* it is also consumed be the sender, the sender can use whatever strategy it wants to make sure
* the value is unambiguous.
*
* The receiver must verify that the target capability actually resolves back to the sender's
* vat. Otherwise, the sender has committed a protocol error and should be disconnected.
*
*/
readonly SENDER_LOOPBACK: 0;
/**
* The receiver previously sent a `senderLoopback` Disembargo towards a promise resolving to
* this capability, and that Disembargo is now being echoed back.
*
*/
readonly RECEIVER_LOOPBACK: 1;
/**
* **(level 3)**
*
* The sender is requesting a disembargo on a promise that is known to resolve to a third-party
* capability that the sender is currently in the process of accepting (using `Accept`).
* The receiver of this `Disembargo` has an outstanding `Provide` on said capability. The
* receiver should now send a `Disembargo` with `provide` set to the question ID of that
* `Provide` message.
*
* See `Accept.embargo` for an example.
*
*/
readonly ACCEPT: 2;
/**
* **(level 3)**
*
* The sender is requesting a disembargo on a capability currently being provided to a third
* party. The question ID identifies the `Provide` message previously sent by the sender to
* this capability. On receipt, the receiver (the capability host) shall release the embargo
* on the `Accept` message that it has received from the third party. See `Accept.embargo` for
* an example.
*
*/
readonly PROVIDE: 3;
};
type Disembargo_Context_Which = (typeof Disembargo_Context_Which)[keyof typeof Disembargo_Context_Which];
declare class Disembargo_Context extends Struct {
static readonly SENDER_LOOPBACK: 0;
static readonly RECEIVER_LOOPBACK: 1;
static readonly ACCEPT: 2;
static readonly PROVIDE: 3;
static readonly _capnp: {
displayName: string;
id: string;
size: ObjectSize;
};
/**
* The sender is requesting a disembargo on a promise that is known to resolve back to a
* capability hosted by the sender. As soon as the receiver has echoed back all pipelined calls
* on this promise, it will deliver the Disembargo back to the sender with `receiverLoopback`
* set to the same value as `senderLoopback`. This value is chosen by the sender, and since
* it is also consumed be the sender, the sender can use whatever strategy it wants to make sure
* the value is unambiguous.
*
* The receiver must verify that the target capability actually resolves back to the sender's
* vat. Otherwise, the sender has committed a protocol error and should be disconnected.
*
*/
get senderLoopback(): number;
get _isSenderLoopback(): boolean;
set senderLoopback(value: number);
/**
* The receiver previously sent a `senderLoopback` Disembargo towards a promise resolving to
* this capability, and that Disembargo is now being echoed back.
*
*/
get receiverLoopback(): number;
get _isReceiverLoopback(): boolean;
set receiverLoopback(value: number);
get _isAccept(): boolean;
set accept(_: true);
/**
* **(level 3)**
*
* The sender is requesting a disembargo on a capability currently being provided to a third
* party. The question ID identifies the `Provide` message previously sent by the sender to
* this capability. On receipt, the receiver (the capability host) shall release the embargo
* on the `Accept` message that it has received from the third party. See `Accept.embargo` for
* an example.
*
*/
get provide(): number;
get _isProvide(): boolean;
set provide(value: number);
toString(): string;
which(): Disembargo_Context_Which;
}
/**
* **(level 1)**
*
* Message sent to indicate that an embargo on a recently-resolved promise may now be lifted.
*
* Embargos are used to enforce E-order in the presence of promise resolution. That is, if an
* application makes two calls foo() and bar() on the same capability reference, in that order,
* the calls should be delivered in the order in which they were made. But if foo() is called
* on a promise, and that promise happens to resolve before bar() is called, then the two calls
* may travel different paths over the network, and thus could arrive in the wrong order. In
* this case, the call to `bar()` must be embargoed, and a `Disembargo` message must be sent along
* the same path as `foo()` to ensure that the `Disembargo` arrives after `foo()`. Once the
* `Disembargo` arrives, `bar()` can then be delivered.
*
* There are two particular cases where embargos are important. Consider object Alice, in Vat A,
* who holds a promise P, pointing towards Vat B, that eventually resolves to Carol. The two
* cases are:
* - Carol lives in Vat A, i.e. next to Alice. In this case, Vat A needs to send a `Disembargo`
* message that echos through Vat B and back, to ensure that all pipelined calls on the promise
* have been delivered.
* - Carol lives in a different Vat C. When the promise resolves, a three-party handoff occurs
* (see `Provide` and `Accept`, which constitute level 3 of the protocol). In this case, we
* piggyback on the state that has already been set up to handle the handoff: the `Accept`
* message (from Vat A to Vat C) is embargoed, as are all pipelined messages sent to it, while
* a `Disembargo` message is sent from Vat A through Vat B to Vat C. See `Accept.embargo` for
* an example.
*
* Note that in the case where Carol actually lives in Vat B (i.e., the same vat that the promise
* already pointed at), no embargo is needed, because the pipelined calls are delivered over the
* same path as the later direct calls.
*
* Keep in mind that promise resolution happens both in the form of Resolve messages as well as
* Return messages (which resolve PromisedAnswers). Embargos apply in both cases.
*
* An alternative strategy for enforcing E-order over promise resolution could be for Vat A to
* implement the embargo internally. When Vat A is notified of promise resolution, it could
* send a dummy no-op call to promise P and wait for it to complete. Until that call completes,
* all calls to the capability are queued locally. This strategy works, but is pessimistic:
* in the three-party case, it requires an A -> B -> C -> B -> A round trip before calls can start
* being delivered di