capability.h (50290B)
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 #pragma once 23 24 #if CAPNP_LITE 25 #error "RPC APIs, including this header, are not available in lite mode." 26 #endif 27 28 #include <kj/async.h> 29 #include <kj/vector.h> 30 #include "raw-schema.h" 31 #include "any.h" 32 #include "pointer-helpers.h" 33 34 CAPNP_BEGIN_HEADER 35 36 namespace capnp { 37 38 template <typename Results> 39 class Response; 40 41 template <typename T> 42 class RemotePromise: public kj::Promise<Response<T>>, public T::Pipeline { 43 // A Promise which supports pipelined calls. T is typically a struct type. T must declare 44 // an inner "mix-in" type "Pipeline" which implements pipelining; RemotePromise simply 45 // multiply-inherits that type along with Promise<Response<T>>. T::Pipeline must be movable, 46 // but does not need to be copyable (i.e. just like Promise<T>). 47 // 48 // The promise is for an owned pointer so that the RPC system can allocate the MessageReader 49 // itself. 50 51 public: 52 inline RemotePromise(kj::Promise<Response<T>>&& promise, typename T::Pipeline&& pipeline) 53 : kj::Promise<Response<T>>(kj::mv(promise)), 54 T::Pipeline(kj::mv(pipeline)) {} 55 inline RemotePromise(decltype(nullptr)) 56 : kj::Promise<Response<T>>(nullptr), 57 T::Pipeline(nullptr) {} 58 KJ_DISALLOW_COPY(RemotePromise); 59 RemotePromise(RemotePromise&& other) = default; 60 RemotePromise& operator=(RemotePromise&& other) = default; 61 62 kj::Promise<Response<T>> dropPipeline() { 63 // Convenience method to convert this into a plain promise. 64 return kj::mv(*this); 65 } 66 67 static RemotePromise<T> reducePromise(kj::Promise<RemotePromise>&& promise); 68 // Hook for KJ so that Promise<RemotePromise<T>> automatically reduces to RemotePromise<T>. 69 }; 70 71 class LocalClient; 72 namespace _ { // private 73 extern const RawSchema NULL_INTERFACE_SCHEMA; // defined in schema.c++ 74 class CapabilityServerSetBase; 75 struct PipelineBuilderPair; 76 } // namespace _ (private) 77 78 struct Capability { 79 // A capability without type-safe methods. Typed capability clients wrap `Client` and typed 80 // capability servers subclass `Server` to dispatch to the regular, typed methods. 81 82 class Client; 83 class Server; 84 85 struct _capnpPrivate { 86 struct IsInterface; 87 static constexpr uint64_t typeId = 0x3; 88 static constexpr Kind kind = Kind::INTERFACE; 89 static constexpr _::RawSchema const* schema = &_::NULL_INTERFACE_SCHEMA; 90 91 static const _::RawBrandedSchema* brand() { 92 return &_::NULL_INTERFACE_SCHEMA.defaultBrand; 93 } 94 }; 95 }; 96 97 // ======================================================================================= 98 // Capability clients 99 100 class RequestHook; 101 class ResponseHook; 102 class PipelineHook; 103 class ClientHook; 104 105 template <typename Params, typename Results> 106 class Request: public Params::Builder { 107 // A call that hasn't been sent yet. This class extends a Builder for the call's "Params" 108 // structure with a method send() that actually sends it. 109 // 110 // Given a Cap'n Proto method `foo(a :A, b :B): C`, the generated client interface will have 111 // a method `Request<FooParams, C> fooRequest()` (as well as a convenience method 112 // `RemotePromise<C> foo(A::Reader a, B::Reader b)`). 113 114 public: 115 inline Request(typename Params::Builder builder, kj::Own<RequestHook>&& hook) 116 : Params::Builder(builder), hook(kj::mv(hook)) {} 117 inline Request(decltype(nullptr)): Params::Builder(nullptr) {} 118 119 RemotePromise<Results> send() KJ_WARN_UNUSED_RESULT; 120 // Send the call and return a promise for the results. 121 122 private: 123 kj::Own<RequestHook> hook; 124 125 friend class Capability::Client; 126 friend struct DynamicCapability; 127 template <typename, typename> 128 friend class CallContext; 129 friend class RequestHook; 130 }; 131 132 template <typename Params> 133 class StreamingRequest: public Params::Builder { 134 // Like `Request` but for streaming requests. 135 136 public: 137 inline StreamingRequest(typename Params::Builder builder, kj::Own<RequestHook>&& hook) 138 : Params::Builder(builder), hook(kj::mv(hook)) {} 139 inline StreamingRequest(decltype(nullptr)): Params::Builder(nullptr) {} 140 141 kj::Promise<void> send() KJ_WARN_UNUSED_RESULT; 142 143 private: 144 kj::Own<RequestHook> hook; 145 146 friend class Capability::Client; 147 friend struct DynamicCapability; 148 template <typename, typename> 149 friend class CallContext; 150 friend class RequestHook; 151 }; 152 153 template <typename Results> 154 class Response: public Results::Reader { 155 // A completed call. This class extends a Reader for the call's answer structure. The Response 156 // is move-only -- once it goes out-of-scope, the underlying message will be freed. 157 158 public: 159 inline Response(typename Results::Reader reader, kj::Own<ResponseHook>&& hook) 160 : Results::Reader(reader), hook(kj::mv(hook)) {} 161 162 private: 163 kj::Own<ResponseHook> hook; 164 165 template <typename, typename> 166 friend class Request; 167 friend class ResponseHook; 168 }; 169 170 class Capability::Client { 171 // Base type for capability clients. 172 173 public: 174 typedef Capability Reads; 175 typedef Capability Calls; 176 177 Client(decltype(nullptr)); 178 // If you need to declare a Client before you have anything to assign to it (perhaps because 179 // the assignment is going to occur in an if/else scope), you can start by initializing it to 180 // `nullptr`. The resulting client is not meant to be called and throws exceptions from all 181 // methods. 182 183 template <typename T, typename = kj::EnableIf<kj::canConvert<T*, Capability::Server*>()>> 184 Client(kj::Own<T>&& server); 185 // Make a client capability that wraps the given server capability. The server's methods will 186 // only be executed in the given EventLoop, regardless of what thread calls the client's methods. 187 188 template <typename T, typename = kj::EnableIf<kj::canConvert<T*, Client*>()>> 189 Client(kj::Promise<T>&& promise); 190 // Make a client from a promise for a future client. The resulting client queues calls until the 191 // promise resolves. 192 193 Client(kj::Exception&& exception); 194 // Make a broken client that throws the given exception from all calls. 195 196 Client(Client& other); 197 Client& operator=(Client& other); 198 // Copies by reference counting. Warning: This refcounting is not thread-safe. All copies of 199 // the client must remain in one thread. 200 201 Client(Client&&) = default; 202 Client& operator=(Client&&) = default; 203 // Move constructor avoids reference counting. 204 205 explicit Client(kj::Own<ClientHook>&& hook); 206 // For use by the RPC implementation: Wrap a ClientHook. 207 208 template <typename T> 209 typename T::Client castAs(); 210 // Reinterpret the capability as implementing the given interface. Note that no error will occur 211 // here if the capability does not actually implement this interface, but later method calls will 212 // fail. It's up to the application to decide how indicate that additional interfaces are 213 // supported. 214 // 215 // TODO(perf): GCC 4.8 / Clang 3.3: rvalue-qualified version for better performance. 216 217 template <typename T> 218 typename T::Client castAs(InterfaceSchema schema); 219 // Dynamic version. `T` must be `DynamicCapability`, and you must `#include <capnp/dynamic.h>`. 220 221 kj::Promise<void> whenResolved(); 222 // If the capability is actually only a promise, the returned promise resolves once the 223 // capability itself has resolved to its final destination (or propagates the exception if 224 // the capability promise is rejected). This is mainly useful for error-checking in the case 225 // where no calls are being made. There is no reason to wait for this before making calls; if 226 // the capability does not resolve, the call results will propagate the error. 227 228 Request<AnyPointer, AnyPointer> typelessRequest( 229 uint64_t interfaceId, uint16_t methodId, 230 kj::Maybe<MessageSize> sizeHint); 231 // Make a request without knowing the types of the params or results. You specify the type ID 232 // and method number manually. 233 234 kj::Promise<kj::Maybe<int>> getFd(); 235 // If the capability's server implemented Capability::Server::getFd() returning non-null, and all 236 // RPC links between the client and server support FD passing, returns a file descriptor pointing 237 // to the same underlying file description as the server did. Returns null if the server provided 238 // no FD or if FD passing was unavailable at some intervening link. 239 // 240 // This returns a Promise to handle the case of an unresolved promise capability, e.g. a 241 // pipelined capability. The promise resolves no later than when the capability settles, i.e. 242 // the same time `whenResolved()` would complete. 243 // 244 // The file descriptor will remain open at least as long as the Capability::Client remains alive. 245 // If you need it to last longer, you will need to `dup()` it. 246 247 // TODO(someday): method(s) for Join 248 249 protected: 250 Client() = default; 251 252 template <typename Params, typename Results> 253 Request<Params, Results> newCall(uint64_t interfaceId, uint16_t methodId, 254 kj::Maybe<MessageSize> sizeHint); 255 template <typename Params> 256 StreamingRequest<Params> newStreamingCall(uint64_t interfaceId, uint16_t methodId, 257 kj::Maybe<MessageSize> sizeHint); 258 259 private: 260 kj::Own<ClientHook> hook; 261 262 static kj::Own<ClientHook> makeLocalClient(kj::Own<Capability::Server>&& server); 263 264 template <typename, Kind> 265 friend struct _::PointerHelpers; 266 friend struct DynamicCapability; 267 friend class Orphanage; 268 friend struct DynamicStruct; 269 friend struct DynamicList; 270 template <typename, Kind> 271 friend struct List; 272 friend class _::CapabilityServerSetBase; 273 friend class ClientHook; 274 }; 275 276 // ======================================================================================= 277 // Capability servers 278 279 class CallContextHook; 280 281 template <typename Params, typename Results> 282 class CallContext: public kj::DisallowConstCopy { 283 // Wrapper around CallContextHook with a specific return type. 284 // 285 // Methods of this class may only be called from within the server's event loop, not from other 286 // threads. 287 // 288 // The CallContext becomes invalid as soon as the call reports completion. 289 290 public: 291 explicit CallContext(CallContextHook& hook); 292 293 typename Params::Reader getParams(); 294 // Get the params payload. 295 296 void releaseParams(); 297 // Release the params payload. getParams() will throw an exception after this is called. 298 // Releasing the params may allow the RPC system to free up buffer space to handle other 299 // requests. Long-running asynchronous methods should try to call this as early as is 300 // convenient. 301 302 typename Results::Builder getResults(kj::Maybe<MessageSize> sizeHint = nullptr); 303 typename Results::Builder initResults(kj::Maybe<MessageSize> sizeHint = nullptr); 304 void setResults(typename Results::Reader value); 305 void adoptResults(Orphan<Results>&& value); 306 Orphanage getResultsOrphanage(kj::Maybe<MessageSize> sizeHint = nullptr); 307 // Manipulate the results payload. The "Return" message (part of the RPC protocol) will 308 // typically be allocated the first time one of these is called. Some RPC systems may 309 // allocate these messages in a limited space (such as a shared memory segment), therefore the 310 // application should delay calling these as long as is convenient to do so (but don't delay 311 // if doing so would require extra copies later). 312 // 313 // `sizeHint` indicates a guess at the message size. This will usually be used to decide how 314 // much space to allocate for the first message segment (don't worry: only space that is actually 315 // used will be sent on the wire). If omitted, the system decides. The message root pointer 316 // should not be included in the size. So, if you are simply going to copy some existing message 317 // directly into the results, just call `.totalSize()` and pass that in. 318 319 void setPipeline(typename Results::Pipeline&& pipeline); 320 void setPipeline(typename Results::Pipeline& pipeline); 321 // Tells the system where the capabilities in the response will eventually resolve to. This 322 // allows requests that are promise-pipelined on this call's results to continue their journey 323 // to the final destination before this call itself has completed. 324 // 325 // This is particularly useful when forwarding RPC calls to other remote servers, but where a 326 // tail call can't be used. For example, imagine Alice calls `foo()` on Bob. In `foo()`'s 327 // implementation, Bob calls `bar()` on Charlie. `bar()` returns a capability to Bob, and then 328 // `foo()` returns the same capability on to Alice. Now imagine Alice is actually using promise 329 // pipelining in a chain like `foo().getCap().baz()`. The `baz()` call will travel to Bob as a 330 // pipelined call without waiting for `foo()` to return first. But once it gets to Bob, the 331 // message has to patiently wait until `foo()` has completed there, before it can then be 332 // forwarded on to Charlie. It would be better if immediately upon Bob calling `bar()` on 333 // Charlie, then Alice's call to `baz()` could be forwarded to Charlie as a pipelined call, 334 // without waiting for `bar()` to return. This would avoid a network round trip of latency 335 // between Bob and Charlie. 336 // 337 // To solve this problem, Bob takes the pipeline object from the `bar()` call, transforms it into 338 // an appropriate pipeline for a `foo()` call, and passes that to `setPipeline()`. This allows 339 // Alice's pipelined `baz()` call to flow through immediately. The code looks like: 340 // 341 // kj::Promise<void> foo(FooContext context) { 342 // auto barPromise = charlie.barRequest().send(); 343 // 344 // // Set up the final pipeline using pipelined capabilities from `barPromise`. 345 // capnp::PipelineBuilder<FooResults> pipeline; 346 // pipeline.setResultCap(barPromise.getSomeCap()); 347 // context.setPipeline(pipeline.build()); 348 // 349 // // Now actually wait for the results and process them. 350 // return barPromise 351 // .then([context](capnp::Response<BarResults> response) mutable { 352 // auto results = context.initResults(); 353 // 354 // // Make sure to set up the capabilities exactly as we did in the pipeline. 355 // results.setResultCap(response.getSomeCap()); 356 // 357 // // ... do other stuff with the real response ... 358 // }); 359 // } 360 // 361 // Of course, if `foo()` and `bar()` return exactly the same type, and Bob doesn't intend 362 // to do anything with `bar()`'s response except pass it through, then `tailCall()` is a better 363 // choice here. `setPipeline()` is useful when some transformation is needed on the response, 364 // or the middleman needs to inspect the response for some reason. 365 // 366 // Note: This method has an overload that takes an lvalue reference for convenience. This 367 // overload increments the refcount on the underlying PipelineHook -- it does not keep the 368 // reference. 369 370 template <typename SubParams> 371 kj::Promise<void> tailCall(Request<SubParams, Results>&& tailRequest); 372 // Resolve the call by making a tail call. `tailRequest` is a request that has been filled in 373 // but not yet sent. The context will send the call, then fill in the results with the result 374 // of the call. If tailCall() is used, {get,init,set,adopt}Results (above) *must not* be called. 375 // 376 // The RPC implementation may be able to optimize a tail call to another machine such that the 377 // results never actually pass through this machine. Even if no such optimization is possible, 378 // `tailCall()` may allow pipelined calls to be forwarded optimistically to the new call site. 379 // 380 // In general, this should be the last thing a method implementation calls, and the promise 381 // returned from `tailCall()` should then be returned by the method implementation. 382 383 void allowCancellation(); 384 // Indicate that it is OK for the RPC system to discard its Promise for this call's result if 385 // the caller cancels the call, thereby transitively canceling any asynchronous operations the 386 // call implementation was performing. This is not done by default because it could represent a 387 // security risk: applications must be carefully written to ensure that they do not end up in 388 // a bad state if an operation is canceled at an arbitrary point. However, for long-running 389 // method calls that hold significant resources, prompt cancellation is often useful. 390 // 391 // Keep in mind that asynchronous cancellation cannot occur while the method is synchronously 392 // executing on a local thread. The method must perform an asynchronous operation or call 393 // `EventLoop::current().evalLater()` to yield control. 394 // 395 // Note: You might think that we should offer `onCancel()` and/or `isCanceled()` methods that 396 // provide notification when the caller cancels the request without forcefully killing off the 397 // promise chain. Unfortunately, this composes poorly with promise forking: the canceled 398 // path may be just one branch of a fork of the result promise. The other branches still want 399 // the call to continue. Promise forking is used within the Cap'n Proto implementation -- in 400 // particular each pipelined call forks the result promise. So, if a caller made a pipelined 401 // call and then dropped the original object, the call should not be canceled, but it would be 402 // excessively complicated for the framework to avoid notififying of cancellation as long as 403 // pipelined calls still exist. 404 405 private: 406 CallContextHook* hook; 407 408 friend class Capability::Server; 409 friend struct DynamicCapability; 410 friend class CallContextHook; 411 }; 412 413 template <typename Params> 414 class StreamingCallContext: public kj::DisallowConstCopy { 415 // Like CallContext but for streaming calls. 416 417 public: 418 explicit StreamingCallContext(CallContextHook& hook); 419 420 typename Params::Reader getParams(); 421 void releaseParams(); 422 423 // Note: tailCall() is not supported because: 424 // - It would significantly complicate the implementation of streaming. 425 // - It wouldn't be particularly useful since streaming calls don't return anything, and they 426 // already compensate for latency. 427 428 void allowCancellation(); 429 430 private: 431 CallContextHook* hook; 432 433 friend class Capability::Server; 434 friend struct DynamicCapability; 435 friend class CallContextHook; 436 }; 437 438 class Capability::Server { 439 // Objects implementing a Cap'n Proto interface must subclass this. Typically, such objects 440 // will instead subclass a typed Server interface which will take care of implementing 441 // dispatchCall(). 442 443 public: 444 typedef Capability Serves; 445 446 struct DispatchCallResult { 447 kj::Promise<void> promise; 448 // Promise for completion of the call. 449 450 bool isStreaming; 451 // If true, this method was declared as `-> stream;`. No other calls should be permitted until 452 // this call finishes, and if this call throws an exception, all future calls will throw the 453 // same exception. 454 }; 455 456 virtual DispatchCallResult dispatchCall(uint64_t interfaceId, uint16_t methodId, 457 CallContext<AnyPointer, AnyPointer> context) = 0; 458 // Call the given method. `params` is the input struct, and should be released as soon as it 459 // is no longer needed. `context` may be used to allocate the output struct and deal with 460 // cancellation. 461 462 virtual kj::Maybe<int> getFd() { return nullptr; } 463 // If this capability is backed by a file descriptor that is safe to directly expose to clients, 464 // returns that FD. When FD passing has been enabled in the RPC layer, this FD may be sent to 465 // other processes along with the capability. 466 467 virtual kj::Maybe<kj::Promise<Capability::Client>> shortenPath(); 468 // If this returns non-null, then it is a promise which, when resolved, points to a new 469 // capability to which future calls can be sent. Use this in cases where an object implementation 470 // might discover a more-optimized path some time after it starts. 471 // 472 // Implementing this (and returning non-null) will cause the capability to be advertised as a 473 // promise at the RPC protocol level. Once the promise returned by shortenPath() resolves, the 474 // remote client will receive a `Resolve` message updating it to point at the new destination. 475 // 476 // `shortenPath()` can also be used as a hack to shut up the client. If shortenPath() returns 477 // a promise that resolves to an exception, then the client will be notified that the capability 478 // is now broken. Assuming the client is using a correct RPC implemnetation, this should cause 479 // all further calls initiated by the client to this capability to immediately fail client-side, 480 // sparing the server's bandwidth. 481 // 482 // The default implementation always returns nullptr. 483 484 // TODO(someday): Method which can optionally be overridden to implement Join when the object is 485 // a proxy. 486 487 protected: 488 inline Capability::Client thisCap(); 489 // Get a capability pointing to this object, much like the `this` keyword. 490 // 491 // The effect of this method is undefined if: 492 // - No capability client has been created pointing to this object. (This is always the case in 493 // the server's constructor.) 494 // - The capability client pointing at this object has been destroyed. (This is always the case 495 // in the server's destructor.) 496 // - Multiple capability clients have been created around the same server (possible if the server 497 // is refcounted, which is not recommended since the client itself provides refcounting). 498 499 template <typename Params, typename Results> 500 CallContext<Params, Results> internalGetTypedContext( 501 CallContext<AnyPointer, AnyPointer> typeless); 502 template <typename Params> 503 StreamingCallContext<Params> internalGetTypedStreamingContext( 504 CallContext<AnyPointer, AnyPointer> typeless); 505 DispatchCallResult internalUnimplemented(const char* actualInterfaceName, 506 uint64_t requestedTypeId); 507 DispatchCallResult internalUnimplemented(const char* interfaceName, 508 uint64_t typeId, uint16_t methodId); 509 kj::Promise<void> internalUnimplemented(const char* interfaceName, const char* methodName, 510 uint64_t typeId, uint16_t methodId); 511 512 private: 513 ClientHook* thisHook = nullptr; 514 friend class LocalClient; 515 }; 516 517 // ======================================================================================= 518 519 template <typename T> 520 class PipelineBuilder: public T::Builder { 521 // Convenience class to build a Pipeline object for use with CallContext::setPipeline(). 522 // 523 // Building a pipeline object is like building an RPC result message, except that you only need 524 // to fill in the capabilities, since the purpose is only to allow pipelined RPC requests to 525 // flow through. 526 // 527 // See the docs for `CallContext::setPipeline()` for an example. 528 529 public: 530 PipelineBuilder(uint firstSegmentWords = 64); 531 // Construct a builder, allocating the given number of words for the first segment of the backing 532 // message. Since `PipelineBuilder` is typically used with small RPC messages, the default size 533 // here is considerably smaller than with MallocMessageBuilder. 534 535 typename T::Pipeline build(); 536 // Constructs a `Pipeline` object backed by the current content of this builder. Calling this 537 // consumes the `PipelineBuilder`; no further methods can be invoked. 538 539 private: 540 kj::Own<PipelineHook> hook; 541 542 PipelineBuilder(_::PipelineBuilderPair pair); 543 }; 544 545 // ======================================================================================= 546 547 class ReaderCapabilityTable: private _::CapTableReader { 548 // Class which imbues Readers with the ability to read capabilities. 549 // 550 // In Cap'n Proto format, the encoding of a capability pointer is simply an integer index into 551 // an external table. Since these pointers fundamentally point outside the message, a 552 // MessageReader by default has no idea what they point at, and therefore reading capabilities 553 // from such a reader will throw exceptions. 554 // 555 // In order to be able to read capabilities, you must first attach a capability table, using 556 // this class. By "imbuing" a Reader, you get a new Reader which will interpret capability 557 // pointers by treating them as indexes into the ReaderCapabilityTable. 558 // 559 // Note that when using Cap'n Proto's RPC system, this is handled automatically. 560 561 public: 562 explicit ReaderCapabilityTable(kj::Array<kj::Maybe<kj::Own<ClientHook>>> table); 563 KJ_DISALLOW_COPY(ReaderCapabilityTable); 564 565 template <typename T> 566 T imbue(T reader); 567 // Return a reader equivalent to `reader` except that when reading capability-valued fields, 568 // the capabilities are looked up in this table. 569 570 private: 571 kj::Array<kj::Maybe<kj::Own<ClientHook>>> table; 572 573 kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override; 574 }; 575 576 class BuilderCapabilityTable: private _::CapTableBuilder { 577 // Class which imbues Builders with the ability to read and write capabilities. 578 // 579 // This is much like ReaderCapabilityTable, except for builders. The table starts out empty, 580 // but capabilities can be added to it over time. 581 582 public: 583 BuilderCapabilityTable(); 584 KJ_DISALLOW_COPY(BuilderCapabilityTable); 585 586 inline kj::ArrayPtr<kj::Maybe<kj::Own<ClientHook>>> getTable() { return table; } 587 588 template <typename T> 589 T imbue(T builder); 590 // Return a builder equivalent to `builder` except that when reading capability-valued fields, 591 // the capabilities are looked up in this table. 592 593 private: 594 kj::Vector<kj::Maybe<kj::Own<ClientHook>>> table; 595 596 kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override; 597 uint injectCap(kj::Own<ClientHook>&& cap) override; 598 void dropCap(uint index) override; 599 }; 600 601 // ======================================================================================= 602 603 namespace _ { // private 604 605 class CapabilityServerSetBase { 606 public: 607 Capability::Client addInternal(kj::Own<Capability::Server>&& server, void* ptr); 608 kj::Promise<void*> getLocalServerInternal(Capability::Client& client); 609 }; 610 611 } // namespace _ (private) 612 613 template <typename T> 614 class CapabilityServerSet: private _::CapabilityServerSetBase { 615 // Allows a server to recognize its own capabilities when passed back to it, and obtain the 616 // underlying Server objects associated with them. 617 // 618 // All objects in the set must have the same interface type T. The objects may implement various 619 // interfaces derived from T (and in fact T can be `capnp::Capability` to accept all objects), 620 // but note that if you compile with RTTI disabled then you will not be able to down-cast through 621 // virtual inheritance, and all inheritance between server interfaces is virtual. So, with RTTI 622 // disabled, you will likely need to set T to be the most-derived Cap'n Proto interface type, 623 // and you server class will need to be directly derived from that, so that you can use 624 // static_cast (or kj::downcast) to cast to it after calling getLocalServer(). (If you compile 625 // with RTTI, then you can freely dynamic_cast and ignore this issue!) 626 627 public: 628 CapabilityServerSet() = default; 629 KJ_DISALLOW_COPY(CapabilityServerSet); 630 631 typename T::Client add(kj::Own<typename T::Server>&& server); 632 // Create a new capability Client for the given Server and also add this server to the set. 633 634 kj::Promise<kj::Maybe<typename T::Server&>> getLocalServer(typename T::Client& client); 635 // Given a Client pointing to a server previously passed to add(), return the corresponding 636 // Server. This returns a promise because if the input client is itself a promise, this must 637 // wait for it to resolve. Keep in mind that the server will be deleted when all clients are 638 // gone, so the caller should make sure to keep the client alive (hence why this method only 639 // accepts an lvalue input). 640 }; 641 642 // ======================================================================================= 643 // Hook interfaces which must be implemented by the RPC system. Applications never call these 644 // directly; the RPC system implements them and the types defined earlier in this file wrap them. 645 646 class RequestHook { 647 // Hook interface implemented by RPC system representing a request being built. 648 649 public: 650 virtual RemotePromise<AnyPointer> send() = 0; 651 // Send the call and return a promise for the result. 652 653 virtual kj::Promise<void> sendStreaming() = 0; 654 // Send a streaming call. 655 656 virtual const void* getBrand() = 0; 657 // Returns a void* that identifies who made this request. This can be used by an RPC adapter to 658 // discover when tail call is going to be sent over its own connection and therefore can be 659 // optimized into a remote tail call. 660 661 template <typename T, typename U> 662 inline static kj::Own<RequestHook> from(Request<T, U>&& request) { 663 return kj::mv(request.hook); 664 } 665 }; 666 667 class ResponseHook { 668 // Hook interface implemented by RPC system representing a response. 669 // 670 // At present this class has no methods. It exists only for garbage collection -- when the 671 // ResponseHook is destroyed, the results can be freed. 672 673 public: 674 virtual ~ResponseHook() noexcept(false); 675 // Just here to make sure the type is dynamic. 676 677 template <typename T> 678 inline static kj::Own<ResponseHook> from(Response<T>&& response) { 679 return kj::mv(response.hook); 680 } 681 }; 682 683 // class PipelineHook is declared in any.h because it is needed there. 684 685 class ClientHook { 686 public: 687 ClientHook(); 688 689 virtual Request<AnyPointer, AnyPointer> newCall( 690 uint64_t interfaceId, uint16_t methodId, kj::Maybe<MessageSize> sizeHint) = 0; 691 // Start a new call, allowing the client to allocate request/response objects as it sees fit. 692 // This version is used when calls are made from application code in the local process. 693 694 struct VoidPromiseAndPipeline { 695 kj::Promise<void> promise; 696 kj::Own<PipelineHook> pipeline; 697 }; 698 699 virtual VoidPromiseAndPipeline call(uint64_t interfaceId, uint16_t methodId, 700 kj::Own<CallContextHook>&& context) = 0; 701 // Call the object, but the caller controls allocation of the request/response objects. If the 702 // callee insists on allocating these objects itself, it must make a copy. This version is used 703 // when calls come in over the network via an RPC system. Note that even if the returned 704 // `Promise<void>` is discarded, the call may continue executing if any pipelined calls are 705 // waiting for it. 706 // 707 // Since the caller of this method chooses the CallContext implementation, it is the caller's 708 // responsibility to ensure that the returned promise is not canceled unless allowed via 709 // the context's `allowCancellation()`. 710 // 711 // The call must not begin synchronously; the callee must arrange for the call to begin in a 712 // later turn of the event loop. Otherwise, application code may call back and affect the 713 // callee's state in an unexpected way. 714 715 virtual kj::Maybe<ClientHook&> getResolved() = 0; 716 // If this ClientHook is a promise that has already resolved, returns the inner, resolved version 717 // of the capability. The caller may permanently replace this client with the resolved one if 718 // desired. Returns null if the client isn't a promise or hasn't resolved yet -- use 719 // `whenMoreResolved()` to distinguish between them. 720 721 virtual kj::Maybe<kj::Promise<kj::Own<ClientHook>>> whenMoreResolved() = 0; 722 // If this client is a settled reference (not a promise), return nullptr. Otherwise, return a 723 // promise that eventually resolves to a new client that is closer to being the final, settled 724 // client (i.e. the value eventually returned by `getResolved()`). Calling this repeatedly 725 // should eventually produce a settled client. 726 727 kj::Promise<void> whenResolved(); 728 // Repeatedly calls whenMoreResolved() until it returns nullptr. 729 730 virtual kj::Own<ClientHook> addRef() = 0; 731 // Return a new reference to the same capability. 732 733 virtual const void* getBrand() = 0; 734 // Returns a void* that identifies who made this client. This can be used by an RPC adapter to 735 // discover when a capability it needs to marshal is one that it created in the first place, and 736 // therefore it can transfer the capability without proxying. 737 738 static const uint NULL_CAPABILITY_BRAND; 739 static const uint BROKEN_CAPABILITY_BRAND; 740 // Values are irrelevant; used for pointers. 741 742 inline bool isNull() { return getBrand() == &NULL_CAPABILITY_BRAND; } 743 // Returns true if the capability was created as a result of assigning a Client to null or by 744 // reading a null pointer out of a Cap'n Proto message. 745 746 inline bool isError() { return getBrand() == &BROKEN_CAPABILITY_BRAND; } 747 // Returns true if the capability was created by newBrokenCap(). 748 749 virtual kj::Maybe<int> getFd() = 0; 750 // Implements Capability::Client::getFd(). If this returns null but whenMoreResolved() returns 751 // non-null, then Capability::Client::getFd() waits for resolution and tries again. 752 753 static kj::Own<ClientHook> from(Capability::Client client) { return kj::mv(client.hook); } 754 }; 755 756 class CallContextHook { 757 // Hook interface implemented by RPC system to manage a call on the server side. See 758 // CallContext<T>. 759 760 public: 761 virtual AnyPointer::Reader getParams() = 0; 762 virtual void releaseParams() = 0; 763 virtual AnyPointer::Builder getResults(kj::Maybe<MessageSize> sizeHint) = 0; 764 virtual kj::Promise<void> tailCall(kj::Own<RequestHook>&& request) = 0; 765 virtual void allowCancellation() = 0; 766 767 virtual void setPipeline(kj::Own<PipelineHook>&& pipeline) = 0; 768 769 virtual kj::Promise<AnyPointer::Pipeline> onTailCall() = 0; 770 // If `tailCall()` is called, resolves to the PipelineHook from the tail call. An 771 // implementation of `ClientHook::call()` is allowed to call this at most once. 772 773 virtual ClientHook::VoidPromiseAndPipeline directTailCall(kj::Own<RequestHook>&& request) = 0; 774 // Call this when you would otherwise call onTailCall() immediately followed by tailCall(). 775 // Implementations of tailCall() should typically call directTailCall() and then fulfill the 776 // promise fulfiller for onTailCall() with the returned pipeline. 777 778 virtual kj::Own<CallContextHook> addRef() = 0; 779 780 template <typename Params, typename Results> 781 static CallContextHook& from(CallContext<Params, Results>& context) { return *context.hook; } 782 template <typename Params> 783 static CallContextHook& from(StreamingCallContext<Params>& context) { return *context.hook; } 784 }; 785 786 kj::Own<ClientHook> newLocalPromiseClient(kj::Promise<kj::Own<ClientHook>>&& promise); 787 // Returns a ClientHook that queues up calls until `promise` resolves, then forwards them to 788 // the new client. This hook's `getResolved()` and `whenMoreResolved()` methods will reflect the 789 // redirection to the eventual replacement client. 790 791 kj::Own<PipelineHook> newLocalPromisePipeline(kj::Promise<kj::Own<PipelineHook>>&& promise); 792 // Returns a PipelineHook that queues up calls until `promise` resolves, then forwards them to 793 // the new pipeline. 794 795 kj::Own<ClientHook> newBrokenCap(kj::StringPtr reason); 796 kj::Own<ClientHook> newBrokenCap(kj::Exception&& reason); 797 // Helper function that creates a capability which simply throws exceptions when called. 798 799 kj::Own<PipelineHook> newBrokenPipeline(kj::Exception&& reason); 800 // Helper function that creates a pipeline which simply throws exceptions when called. 801 802 Request<AnyPointer, AnyPointer> newBrokenRequest( 803 kj::Exception&& reason, kj::Maybe<MessageSize> sizeHint); 804 // Helper function that creates a Request object that simply throws exceptions when sent. 805 806 // ======================================================================================= 807 // Extend PointerHelpers for interfaces 808 809 namespace _ { // private 810 811 template <typename T> 812 struct PointerHelpers<T, Kind::INTERFACE> { 813 static inline typename T::Client get(PointerReader reader) { 814 return typename T::Client(reader.getCapability()); 815 } 816 static inline typename T::Client get(PointerBuilder builder) { 817 return typename T::Client(builder.getCapability()); 818 } 819 static inline void set(PointerBuilder builder, typename T::Client&& value) { 820 builder.setCapability(kj::mv(value.Capability::Client::hook)); 821 } 822 static inline void set(PointerBuilder builder, typename T::Client& value) { 823 builder.setCapability(value.Capability::Client::hook->addRef()); 824 } 825 static inline void adopt(PointerBuilder builder, Orphan<T>&& value) { 826 builder.adopt(kj::mv(value.builder)); 827 } 828 static inline Orphan<T> disown(PointerBuilder builder) { 829 return Orphan<T>(builder.disown()); 830 } 831 }; 832 833 } // namespace _ (private) 834 835 // ======================================================================================= 836 // Extend List for interfaces 837 838 template <typename T> 839 struct List<T, Kind::INTERFACE> { 840 List() = delete; 841 842 class Reader { 843 public: 844 typedef List<T> Reads; 845 846 Reader() = default; 847 inline explicit Reader(_::ListReader reader): reader(reader) {} 848 849 inline uint size() const { return unbound(reader.size() / ELEMENTS); } 850 inline typename T::Client operator[](uint index) const { 851 KJ_IREQUIRE(index < size()); 852 return typename T::Client(reader.getPointerElement( 853 bounded(index) * ELEMENTS).getCapability()); 854 } 855 856 typedef _::IndexingIterator<const Reader, typename T::Client> Iterator; 857 inline Iterator begin() const { return Iterator(this, 0); } 858 inline Iterator end() const { return Iterator(this, size()); } 859 860 inline MessageSize totalSize() const { 861 return reader.totalSize().asPublic(); 862 } 863 864 private: 865 _::ListReader reader; 866 template <typename U, Kind K> 867 friend struct _::PointerHelpers; 868 template <typename U, Kind K> 869 friend struct List; 870 friend class Orphanage; 871 template <typename U, Kind K> 872 friend struct ToDynamic_; 873 }; 874 875 class Builder { 876 public: 877 typedef List<T> Builds; 878 879 Builder() = delete; 880 inline Builder(decltype(nullptr)) {} 881 inline explicit Builder(_::ListBuilder builder): builder(builder) {} 882 883 inline operator Reader() const { return Reader(builder.asReader()); } 884 inline Reader asReader() const { return Reader(builder.asReader()); } 885 886 inline uint size() const { return unbound(builder.size() / ELEMENTS); } 887 inline typename T::Client operator[](uint index) { 888 KJ_IREQUIRE(index < size()); 889 return typename T::Client(builder.getPointerElement( 890 bounded(index) * ELEMENTS).getCapability()); 891 } 892 inline void set(uint index, typename T::Client value) { 893 KJ_IREQUIRE(index < size()); 894 builder.getPointerElement(bounded(index) * ELEMENTS).setCapability(kj::mv(value.hook)); 895 } 896 inline void adopt(uint index, Orphan<T>&& value) { 897 KJ_IREQUIRE(index < size()); 898 builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value)); 899 } 900 inline Orphan<T> disown(uint index) { 901 KJ_IREQUIRE(index < size()); 902 return Orphan<T>(builder.getPointerElement(bounded(index) * ELEMENTS).disown()); 903 } 904 905 typedef _::IndexingIterator<Builder, typename T::Client> Iterator; 906 inline Iterator begin() { return Iterator(this, 0); } 907 inline Iterator end() { return Iterator(this, size()); } 908 909 private: 910 _::ListBuilder builder; 911 friend class Orphanage; 912 template <typename U, Kind K> 913 friend struct ToDynamic_; 914 }; 915 916 private: 917 inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) { 918 return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS); 919 } 920 inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) { 921 return builder.getList(ElementSize::POINTER, defaultValue); 922 } 923 inline static _::ListReader getFromPointer( 924 const _::PointerReader& reader, const word* defaultValue) { 925 return reader.getList(ElementSize::POINTER, defaultValue); 926 } 927 928 template <typename U, Kind k> 929 friend struct List; 930 template <typename U, Kind K> 931 friend struct _::PointerHelpers; 932 }; 933 934 // ======================================================================================= 935 // Inline implementation details 936 937 template <typename T> 938 RemotePromise<T> RemotePromise<T>::reducePromise(kj::Promise<RemotePromise>&& promise) { 939 kj::Tuple<kj::Promise<Response<T>>, kj::Promise<kj::Own<PipelineHook>>> splitPromise = 940 promise.then([](RemotePromise&& inner) { 941 // `inner` is multiply-inherited, and we want to move away each superclass separately. 942 // Let's create two references to make clear what we're doing (though this is not strictly 943 // necessary). 944 kj::Promise<Response<T>>& innerPromise = inner; 945 typename T::Pipeline& innerPipeline = inner; 946 return kj::tuple(kj::mv(innerPromise), PipelineHook::from(kj::mv(innerPipeline))); 947 }).split(); 948 949 return RemotePromise(kj::mv(kj::get<0>(splitPromise)), 950 typename T::Pipeline(AnyPointer::Pipeline( 951 newLocalPromisePipeline(kj::mv(kj::get<1>(splitPromise)))))); 952 } 953 954 template <typename Params, typename Results> 955 RemotePromise<Results> Request<Params, Results>::send() { 956 auto typelessPromise = hook->send(); 957 hook = nullptr; // prevent reuse 958 959 // Convert the Promise to return the correct response type. 960 // Explicitly upcast to kj::Promise to make clear that calling .then() doesn't invalidate the 961 // Pipeline part of the RemotePromise. 962 auto typedPromise = kj::implicitCast<kj::Promise<Response<AnyPointer>>&>(typelessPromise) 963 .then([](Response<AnyPointer>&& response) -> Response<Results> { 964 return Response<Results>(response.getAs<Results>(), kj::mv(response.hook)); 965 }); 966 967 // Wrap the typeless pipeline in a typed wrapper. 968 typename Results::Pipeline typedPipeline( 969 kj::mv(kj::implicitCast<AnyPointer::Pipeline&>(typelessPromise))); 970 971 return RemotePromise<Results>(kj::mv(typedPromise), kj::mv(typedPipeline)); 972 } 973 974 template <typename Params> 975 kj::Promise<void> StreamingRequest<Params>::send() { 976 auto promise = hook->sendStreaming(); 977 hook = nullptr; // prevent reuse 978 return promise; 979 } 980 981 inline Capability::Client::Client(kj::Own<ClientHook>&& hook): hook(kj::mv(hook)) {} 982 template <typename T, typename> 983 inline Capability::Client::Client(kj::Own<T>&& server) 984 : hook(makeLocalClient(kj::mv(server))) {} 985 template <typename T, typename> 986 inline Capability::Client::Client(kj::Promise<T>&& promise) 987 : hook(newLocalPromiseClient(promise.then([](T&& t) { return kj::mv(t.hook); }))) {} 988 inline Capability::Client::Client(Client& other): hook(other.hook->addRef()) {} 989 inline Capability::Client& Capability::Client::operator=(Client& other) { 990 hook = other.hook->addRef(); 991 return *this; 992 } 993 template <typename T> 994 inline typename T::Client Capability::Client::castAs() { 995 return typename T::Client(hook->addRef()); 996 } 997 inline Request<AnyPointer, AnyPointer> Capability::Client::typelessRequest( 998 uint64_t interfaceId, uint16_t methodId, 999 kj::Maybe<MessageSize> sizeHint) { 1000 return newCall<AnyPointer, AnyPointer>(interfaceId, methodId, sizeHint); 1001 } 1002 template <typename Params, typename Results> 1003 inline Request<Params, Results> Capability::Client::newCall( 1004 uint64_t interfaceId, uint16_t methodId, kj::Maybe<MessageSize> sizeHint) { 1005 auto typeless = hook->newCall(interfaceId, methodId, sizeHint); 1006 return Request<Params, Results>(typeless.template getAs<Params>(), kj::mv(typeless.hook)); 1007 } 1008 template <typename Params> 1009 inline StreamingRequest<Params> Capability::Client::newStreamingCall( 1010 uint64_t interfaceId, uint16_t methodId, kj::Maybe<MessageSize> sizeHint) { 1011 auto typeless = hook->newCall(interfaceId, methodId, sizeHint); 1012 return StreamingRequest<Params>(typeless.template getAs<Params>(), kj::mv(typeless.hook)); 1013 } 1014 1015 template <typename Params, typename Results> 1016 inline CallContext<Params, Results>::CallContext(CallContextHook& hook): hook(&hook) {} 1017 template <typename Params> 1018 inline StreamingCallContext<Params>::StreamingCallContext(CallContextHook& hook): hook(&hook) {} 1019 template <typename Params, typename Results> 1020 inline typename Params::Reader CallContext<Params, Results>::getParams() { 1021 return hook->getParams().template getAs<Params>(); 1022 } 1023 template <typename Params> 1024 inline typename Params::Reader StreamingCallContext<Params>::getParams() { 1025 return hook->getParams().template getAs<Params>(); 1026 } 1027 template <typename Params, typename Results> 1028 inline void CallContext<Params, Results>::releaseParams() { 1029 hook->releaseParams(); 1030 } 1031 template <typename Params> 1032 inline void StreamingCallContext<Params>::releaseParams() { 1033 hook->releaseParams(); 1034 } 1035 template <typename Params, typename Results> 1036 inline typename Results::Builder CallContext<Params, Results>::getResults( 1037 kj::Maybe<MessageSize> sizeHint) { 1038 // `template` keyword needed due to: http://llvm.org/bugs/show_bug.cgi?id=17401 1039 return hook->getResults(sizeHint).template getAs<Results>(); 1040 } 1041 template <typename Params, typename Results> 1042 inline typename Results::Builder CallContext<Params, Results>::initResults( 1043 kj::Maybe<MessageSize> sizeHint) { 1044 // `template` keyword needed due to: http://llvm.org/bugs/show_bug.cgi?id=17401 1045 return hook->getResults(sizeHint).template initAs<Results>(); 1046 } 1047 template <typename Params, typename Results> 1048 inline void CallContext<Params, Results>::setResults(typename Results::Reader value) { 1049 hook->getResults(value.totalSize()).template setAs<Results>(value); 1050 } 1051 template <typename Params, typename Results> 1052 inline void CallContext<Params, Results>::adoptResults(Orphan<Results>&& value) { 1053 hook->getResults(nullptr).adopt(kj::mv(value)); 1054 } 1055 template <typename Params, typename Results> 1056 inline Orphanage CallContext<Params, Results>::getResultsOrphanage( 1057 kj::Maybe<MessageSize> sizeHint) { 1058 return Orphanage::getForMessageContaining(hook->getResults(sizeHint)); 1059 } 1060 template <typename Params, typename Results> 1061 void CallContext<Params, Results>::setPipeline(typename Results::Pipeline&& pipeline) { 1062 hook->setPipeline(PipelineHook::from(kj::mv(pipeline))); 1063 } 1064 template <typename Params, typename Results> 1065 void CallContext<Params, Results>::setPipeline(typename Results::Pipeline& pipeline) { 1066 hook->setPipeline(PipelineHook::from(pipeline).addRef()); 1067 } 1068 template <typename Params, typename Results> 1069 template <typename SubParams> 1070 inline kj::Promise<void> CallContext<Params, Results>::tailCall( 1071 Request<SubParams, Results>&& tailRequest) { 1072 return hook->tailCall(kj::mv(tailRequest.hook)); 1073 } 1074 template <typename Params, typename Results> 1075 inline void CallContext<Params, Results>::allowCancellation() { 1076 hook->allowCancellation(); 1077 } 1078 template <typename Params> 1079 inline void StreamingCallContext<Params>::allowCancellation() { 1080 hook->allowCancellation(); 1081 } 1082 1083 template <typename Params, typename Results> 1084 CallContext<Params, Results> Capability::Server::internalGetTypedContext( 1085 CallContext<AnyPointer, AnyPointer> typeless) { 1086 return CallContext<Params, Results>(*typeless.hook); 1087 } 1088 1089 template <typename Params> 1090 StreamingCallContext<Params> Capability::Server::internalGetTypedStreamingContext( 1091 CallContext<AnyPointer, AnyPointer> typeless) { 1092 return StreamingCallContext<Params>(*typeless.hook); 1093 } 1094 1095 Capability::Client Capability::Server::thisCap() { 1096 return Client(thisHook->addRef()); 1097 } 1098 1099 namespace _ { // private 1100 1101 struct PipelineBuilderPair { 1102 AnyPointer::Builder root; 1103 kj::Own<PipelineHook> hook; 1104 }; 1105 1106 PipelineBuilderPair newPipelineBuilder(uint firstSegmentWords); 1107 1108 } // namespace _ (private) 1109 1110 template <typename T> 1111 PipelineBuilder<T>::PipelineBuilder(uint firstSegmentWords) 1112 : PipelineBuilder(_::newPipelineBuilder(firstSegmentWords)) {} 1113 1114 template <typename T> 1115 PipelineBuilder<T>::PipelineBuilder(_::PipelineBuilderPair pair) 1116 : T::Builder(pair.root.initAs<T>()), 1117 hook(kj::mv(pair.hook)) {} 1118 1119 template <typename T> 1120 typename T::Pipeline PipelineBuilder<T>::build() { 1121 // Prevent subsequent accidental modification. A good compiler should be able to optimize this 1122 // assignment away assuming the PipelineBuilder is not accessed again after this point. 1123 static_cast<typename T::Builder&>(*this) = nullptr; 1124 1125 return typename T::Pipeline(AnyPointer::Pipeline(kj::mv(hook))); 1126 } 1127 1128 template <typename T> 1129 T ReaderCapabilityTable::imbue(T reader) { 1130 return T(_::PointerHelpers<FromReader<T>>::getInternalReader(reader).imbue(this)); 1131 } 1132 1133 template <typename T> 1134 T BuilderCapabilityTable::imbue(T builder) { 1135 return T(_::PointerHelpers<FromBuilder<T>>::getInternalBuilder(kj::mv(builder)).imbue(this)); 1136 } 1137 1138 template <typename T> 1139 typename T::Client CapabilityServerSet<T>::add(kj::Own<typename T::Server>&& server) { 1140 void* ptr = reinterpret_cast<void*>(server.get()); 1141 // Clang insists that `castAs` is a template-dependent member and therefore we need the 1142 // `template` keyword here, but AFAICT this is wrong: addImpl() is not a template. 1143 return addInternal(kj::mv(server), ptr).template castAs<T>(); 1144 } 1145 1146 template <typename T> 1147 kj::Promise<kj::Maybe<typename T::Server&>> CapabilityServerSet<T>::getLocalServer( 1148 typename T::Client& client) { 1149 return getLocalServerInternal(client) 1150 .then([](void* server) -> kj::Maybe<typename T::Server&> { 1151 if (server == nullptr) { 1152 return nullptr; 1153 } else { 1154 return *reinterpret_cast<typename T::Server*>(server); 1155 } 1156 }); 1157 } 1158 1159 template <typename T> 1160 struct Orphanage::GetInnerReader<T, Kind::INTERFACE> { 1161 static inline kj::Own<ClientHook> apply(typename T::Client t) { 1162 return ClientHook::from(kj::mv(t)); 1163 } 1164 }; 1165 1166 #define CAPNP_CAPABILITY_H_INCLUDED // for testing includes in unit test 1167 1168 } // namespace capnp 1169 1170 CAPNP_END_HEADER