membrane.c++ (21505B)
1 // Copyright (c) 2015 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 #include "membrane.h" 23 #include <kj/debug.h> 24 25 namespace capnp { 26 27 namespace { 28 29 static const char DUMMY = 0; 30 static constexpr const void* MEMBRANE_BRAND = &DUMMY; 31 32 kj::Own<ClientHook> membrane(kj::Own<ClientHook> inner, MembranePolicy& policy, bool reverse); 33 34 class MembraneCapTableReader final: public _::CapTableReader { 35 public: 36 MembraneCapTableReader(MembranePolicy& policy, bool reverse) 37 : policy(policy), reverse(reverse) {} 38 39 AnyPointer::Reader imbue(AnyPointer::Reader reader) { 40 return AnyPointer::Reader(imbue( 41 _::PointerHelpers<AnyPointer>::getInternalReader(kj::mv(reader)))); 42 } 43 44 _::PointerReader imbue(_::PointerReader reader) { 45 KJ_REQUIRE(inner == nullptr, "can only call this once"); 46 inner = reader.getCapTable(); 47 return reader.imbue(this); 48 } 49 50 _::StructReader imbue(_::StructReader reader) { 51 KJ_REQUIRE(inner == nullptr, "can only call this once"); 52 inner = reader.getCapTable(); 53 return reader.imbue(this); 54 } 55 56 _::ListReader imbue(_::ListReader reader) { 57 KJ_REQUIRE(inner == nullptr, "can only call this once"); 58 inner = reader.getCapTable(); 59 return reader.imbue(this); 60 } 61 62 kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override { 63 // The underlying message is inside the membrane, and we're pulling a cap out of it. Therefore, 64 // we want to wrap the extracted capability in the membrane. 65 return inner->extractCap(index).map([this](kj::Own<ClientHook>&& cap) { 66 return membrane(kj::mv(cap), policy, reverse); 67 }); 68 } 69 70 private: 71 _::CapTableReader* inner = nullptr; 72 MembranePolicy& policy; 73 bool reverse; 74 }; 75 76 class MembraneCapTableBuilder final: public _::CapTableBuilder { 77 public: 78 MembraneCapTableBuilder(MembranePolicy& policy, bool reverse) 79 : policy(policy), reverse(reverse) {} 80 81 AnyPointer::Builder imbue(AnyPointer::Builder builder) { 82 KJ_REQUIRE(inner == nullptr, "can only call this once"); 83 auto pointerBuilder = _::PointerHelpers<AnyPointer>::getInternalBuilder(kj::mv(builder)); 84 inner = pointerBuilder.getCapTable(); 85 return AnyPointer::Builder(pointerBuilder.imbue(this)); 86 } 87 88 AnyPointer::Builder unimbue(AnyPointer::Builder builder) { 89 auto pointerBuilder = _::PointerHelpers<AnyPointer>::getInternalBuilder(kj::mv(builder)); 90 KJ_REQUIRE(pointerBuilder.getCapTable() == this); 91 return AnyPointer::Builder(pointerBuilder.imbue(inner)); 92 } 93 94 kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override { 95 // The underlying message is inside the membrane, and we're pulling a cap out of it. Therefore, 96 // we want to wrap the extracted capability in the membrane. 97 return inner->extractCap(index).map([this](kj::Own<ClientHook>&& cap) { 98 return membrane(kj::mv(cap), policy, reverse); 99 }); 100 } 101 102 uint injectCap(kj::Own<ClientHook>&& cap) override { 103 // The underlying message is inside the membrane, and we're inserting a cap from outside into 104 // it. Therefore we want to add a reverse membrane. 105 return inner->injectCap(membrane(kj::mv(cap), policy, !reverse)); 106 } 107 108 void dropCap(uint index) override { 109 inner->dropCap(index); 110 } 111 112 private: 113 _::CapTableBuilder* inner = nullptr; 114 MembranePolicy& policy; 115 bool reverse; 116 }; 117 118 class MembranePipelineHook final: public PipelineHook, public kj::Refcounted { 119 public: 120 MembranePipelineHook( 121 kj::Own<PipelineHook>&& inner, kj::Own<MembranePolicy>&& policy, bool reverse) 122 : inner(kj::mv(inner)), policy(kj::mv(policy)), reverse(reverse) {} 123 124 kj::Own<PipelineHook> addRef() override { 125 return kj::addRef(*this); 126 } 127 128 kj::Own<ClientHook> getPipelinedCap(kj::ArrayPtr<const PipelineOp> ops) override { 129 return membrane(inner->getPipelinedCap(ops), *policy, reverse); 130 } 131 132 kj::Own<ClientHook> getPipelinedCap(kj::Array<PipelineOp>&& ops) override { 133 return membrane(inner->getPipelinedCap(kj::mv(ops)), *policy, reverse); 134 } 135 136 private: 137 kj::Own<PipelineHook> inner; 138 kj::Own<MembranePolicy> policy; 139 bool reverse; 140 }; 141 142 class MembraneResponseHook final: public ResponseHook { 143 public: 144 MembraneResponseHook( 145 kj::Own<ResponseHook>&& inner, kj::Own<MembranePolicy>&& policy, bool reverse) 146 : inner(kj::mv(inner)), policy(kj::mv(policy)), capTable(*this->policy, reverse) {} 147 148 AnyPointer::Reader imbue(AnyPointer::Reader reader) { return capTable.imbue(reader); } 149 150 private: 151 kj::Own<ResponseHook> inner; 152 kj::Own<MembranePolicy> policy; 153 MembraneCapTableReader capTable; 154 }; 155 156 class MembraneRequestHook final: public RequestHook { 157 public: 158 MembraneRequestHook(kj::Own<RequestHook>&& inner, kj::Own<MembranePolicy>&& policy, bool reverse) 159 : inner(kj::mv(inner)), policy(kj::mv(policy)), 160 reverse(reverse), capTable(*this->policy, reverse) {} 161 162 static Request<AnyPointer, AnyPointer> wrap( 163 Request<AnyPointer, AnyPointer>&& inner, MembranePolicy& policy, bool reverse) { 164 AnyPointer::Builder builder = inner; 165 auto innerHook = RequestHook::from(kj::mv(inner)); 166 if (innerHook->getBrand() == MEMBRANE_BRAND) { 167 auto& otherMembrane = kj::downcast<MembraneRequestHook>(*innerHook); 168 if (otherMembrane.policy.get() == &policy && otherMembrane.reverse == !reverse) { 169 // Request that passed across the membrane one way is now passing back the other way. 170 // Unwrap it rather than double-wrap it. 171 builder = otherMembrane.capTable.unimbue(builder); 172 return { builder, kj::mv(otherMembrane.inner) }; 173 } 174 } 175 176 auto newHook = kj::heap<MembraneRequestHook>(kj::mv(innerHook), policy.addRef(), reverse); 177 builder = newHook->capTable.imbue(builder); 178 return { builder, kj::mv(newHook) }; 179 } 180 181 static kj::Own<RequestHook> wrap( 182 kj::Own<RequestHook>&& inner, MembranePolicy& policy, bool reverse) { 183 if (inner->getBrand() == MEMBRANE_BRAND) { 184 auto& otherMembrane = kj::downcast<MembraneRequestHook>(*inner); 185 if (otherMembrane.policy.get() == &policy && otherMembrane.reverse == !reverse) { 186 // Request that passed across the membrane one way is now passing back the other way. 187 // Unwrap it rather than double-wrap it. 188 return kj::mv(otherMembrane.inner); 189 } 190 } 191 192 return kj::heap<MembraneRequestHook>(kj::mv(inner), policy.addRef(), reverse); 193 } 194 195 RemotePromise<AnyPointer> send() override { 196 auto promise = inner->send(); 197 198 auto newPipeline = AnyPointer::Pipeline(kj::refcounted<MembranePipelineHook>( 199 PipelineHook::from(kj::mv(promise)), policy->addRef(), reverse)); 200 201 auto onRevoked = policy->onRevoked(); 202 203 bool reverse = this->reverse; // for capture 204 auto newPromise = promise.then(kj::mvCapture(policy, 205 [reverse](kj::Own<MembranePolicy>&& policy, Response<AnyPointer>&& response) { 206 AnyPointer::Reader reader = response; 207 auto newRespHook = kj::heap<MembraneResponseHook>( 208 ResponseHook::from(kj::mv(response)), policy->addRef(), reverse); 209 reader = newRespHook->imbue(reader); 210 return Response<AnyPointer>(reader, kj::mv(newRespHook)); 211 })); 212 213 KJ_IF_MAYBE(r, kj::mv(onRevoked)) { 214 newPromise = newPromise.exclusiveJoin(r->then([]() -> Response<AnyPointer> { 215 KJ_FAIL_REQUIRE("onRevoked() promise resolved; it should only reject"); 216 })); 217 } 218 219 return RemotePromise<AnyPointer>(kj::mv(newPromise), kj::mv(newPipeline)); 220 } 221 222 kj::Promise<void> sendStreaming() override { 223 auto promise = inner->sendStreaming(); 224 225 KJ_IF_MAYBE(r, policy->onRevoked()) { 226 promise = promise.exclusiveJoin(r->then([]() { 227 KJ_FAIL_REQUIRE("onRevoked() promise resolved; it should only reject"); 228 })); 229 } 230 231 return promise; 232 } 233 234 const void* getBrand() override { 235 return MEMBRANE_BRAND; 236 } 237 238 private: 239 kj::Own<RequestHook> inner; 240 kj::Own<MembranePolicy> policy; 241 bool reverse; 242 MembraneCapTableBuilder capTable; 243 }; 244 245 class MembraneCallContextHook final: public CallContextHook, public kj::Refcounted { 246 public: 247 MembraneCallContextHook(kj::Own<CallContextHook>&& inner, 248 kj::Own<MembranePolicy>&& policy, bool reverse) 249 : inner(kj::mv(inner)), policy(kj::mv(policy)), reverse(reverse), 250 paramsCapTable(*this->policy, reverse), 251 resultsCapTable(*this->policy, reverse) {} 252 253 AnyPointer::Reader getParams() override { 254 KJ_REQUIRE(!releasedParams); 255 KJ_IF_MAYBE(p, params) { 256 return *p; 257 } else { 258 auto result = paramsCapTable.imbue(inner->getParams()); 259 params = result; 260 return result; 261 } 262 } 263 264 void releaseParams() override { 265 // Note that releaseParams() is idempotent -- it can be called multiple times. 266 releasedParams = true; 267 inner->releaseParams(); 268 } 269 270 AnyPointer::Builder getResults(kj::Maybe<MessageSize> sizeHint) override { 271 KJ_IF_MAYBE(r, results) { 272 return *r; 273 } else { 274 auto result = resultsCapTable.imbue(inner->getResults(sizeHint)); 275 results = result; 276 return result; 277 } 278 } 279 280 void setPipeline(kj::Own<PipelineHook>&& pipeline) override { 281 inner->setPipeline(kj::refcounted<MembranePipelineHook>( 282 kj::mv(pipeline), policy->addRef(), !reverse)); 283 } 284 285 kj::Promise<void> tailCall(kj::Own<RequestHook>&& request) override { 286 return inner->tailCall(MembraneRequestHook::wrap(kj::mv(request), *policy, !reverse)); 287 } 288 289 void allowCancellation() override { 290 inner->allowCancellation(); 291 } 292 293 kj::Promise<AnyPointer::Pipeline> onTailCall() override { 294 return inner->onTailCall().then([this](AnyPointer::Pipeline&& innerPipeline) { 295 return AnyPointer::Pipeline(kj::refcounted<MembranePipelineHook>( 296 PipelineHook::from(kj::mv(innerPipeline)), policy->addRef(), reverse)); 297 }); 298 } 299 300 ClientHook::VoidPromiseAndPipeline directTailCall(kj::Own<RequestHook>&& request) override { 301 auto pair = inner->directTailCall( 302 MembraneRequestHook::wrap(kj::mv(request), *policy, !reverse)); 303 304 return { 305 kj::mv(pair.promise), 306 kj::refcounted<MembranePipelineHook>(kj::mv(pair.pipeline), policy->addRef(), reverse) 307 }; 308 } 309 310 kj::Own<CallContextHook> addRef() override { 311 return kj::addRef(*this); 312 } 313 314 private: 315 kj::Own<CallContextHook> inner; 316 kj::Own<MembranePolicy> policy; 317 bool reverse; 318 319 MembraneCapTableReader paramsCapTable; 320 kj::Maybe<AnyPointer::Reader> params; 321 bool releasedParams = false; 322 323 MembraneCapTableBuilder resultsCapTable; 324 kj::Maybe<AnyPointer::Builder> results; 325 }; 326 327 class MembraneHook final: public ClientHook, public kj::Refcounted { 328 public: 329 MembraneHook(kj::Own<ClientHook>&& inner, kj::Own<MembranePolicy>&& policyParam, bool reverse) 330 : inner(kj::mv(inner)), policy(kj::mv(policyParam)), reverse(reverse) { 331 KJ_IF_MAYBE(r, policy->onRevoked()) { 332 revocationTask = r->eagerlyEvaluate([this](kj::Exception&& exception) { 333 this->inner = newBrokenCap(kj::mv(exception)); 334 }); 335 } 336 } 337 338 static kj::Own<ClientHook> wrap(ClientHook& cap, MembranePolicy& policy, bool reverse) { 339 if (cap.getBrand() == MEMBRANE_BRAND) { 340 auto& otherMembrane = kj::downcast<MembraneHook>(cap); 341 auto& rootPolicy = policy.rootPolicy(); 342 if (&otherMembrane.policy->rootPolicy() == &rootPolicy && 343 otherMembrane.reverse == !reverse) { 344 // Capability that passed across the membrane one way is now passing back the other way. 345 // Unwrap it rather than double-wrap it. 346 Capability::Client unwrapped(otherMembrane.inner->addRef()); 347 return ClientHook::from( 348 reverse ? rootPolicy.importInternal(kj::mv(unwrapped), *otherMembrane.policy, policy) 349 : rootPolicy.exportExternal(kj::mv(unwrapped), *otherMembrane.policy, policy)); 350 } 351 } 352 353 return ClientHook::from( 354 reverse ? policy.importExternal(Capability::Client(cap.addRef())) 355 : policy.exportInternal(Capability::Client(cap.addRef()))); 356 } 357 358 static kj::Own<ClientHook> wrap(kj::Own<ClientHook> cap, MembranePolicy& policy, bool reverse) { 359 if (cap->getBrand() == MEMBRANE_BRAND) { 360 auto& otherMembrane = kj::downcast<MembraneHook>(*cap); 361 auto& rootPolicy = policy.rootPolicy(); 362 if (&otherMembrane.policy->rootPolicy() == &rootPolicy && 363 otherMembrane.reverse == !reverse) { 364 // Capability that passed across the membrane one way is now passing back the other way. 365 // Unwrap it rather than double-wrap it. 366 Capability::Client unwrapped(otherMembrane.inner->addRef()); 367 return ClientHook::from( 368 reverse ? rootPolicy.importInternal(kj::mv(unwrapped), *otherMembrane.policy, policy) 369 : rootPolicy.exportExternal(kj::mv(unwrapped), *otherMembrane.policy, policy)); 370 } 371 } 372 373 return ClientHook::from( 374 reverse ? policy.importExternal(Capability::Client(kj::mv(cap))) 375 : policy.exportInternal(Capability::Client(kj::mv(cap)))); 376 } 377 378 Request<AnyPointer, AnyPointer> newCall( 379 uint64_t interfaceId, uint16_t methodId, kj::Maybe<MessageSize> sizeHint) override { 380 KJ_IF_MAYBE(r, resolved) { 381 return r->get()->newCall(interfaceId, methodId, sizeHint); 382 } 383 384 auto redirect = reverse 385 ? policy->outboundCall(interfaceId, methodId, Capability::Client(inner->addRef())) 386 : policy->inboundCall(interfaceId, methodId, Capability::Client(inner->addRef())); 387 KJ_IF_MAYBE(r, redirect) { 388 if (policy->shouldResolveBeforeRedirecting()) { 389 // The policy says that *if* this capability points into the membrane, then we want to 390 // redirect the call. However, if this capability is a promise, then it could resolve to 391 // something outside the membrane later. We have to wait before we actually redirect, 392 // otherwise behavior will differ depending on whether the promise is resolved. 393 KJ_IF_MAYBE(p, whenMoreResolved()) { 394 return newLocalPromiseClient(p->attach(addRef())) 395 ->newCall(interfaceId, methodId, sizeHint); 396 } 397 } 398 399 return ClientHook::from(kj::mv(*r))->newCall(interfaceId, methodId, sizeHint); 400 } else { 401 // For pass-through calls, we don't worry about promises, because if the capability resolves 402 // to something outside the membrane, then the call will pass back out of the membrane too. 403 return MembraneRequestHook::wrap( 404 inner->newCall(interfaceId, methodId, sizeHint), *policy, reverse); 405 } 406 } 407 408 VoidPromiseAndPipeline call(uint64_t interfaceId, uint16_t methodId, 409 kj::Own<CallContextHook>&& context) override { 410 KJ_IF_MAYBE(r, resolved) { 411 return r->get()->call(interfaceId, methodId, kj::mv(context)); 412 } 413 414 auto redirect = reverse 415 ? policy->outboundCall(interfaceId, methodId, Capability::Client(inner->addRef())) 416 : policy->inboundCall(interfaceId, methodId, Capability::Client(inner->addRef())); 417 KJ_IF_MAYBE(r, redirect) { 418 if (policy->shouldResolveBeforeRedirecting()) { 419 // The policy says that *if* this capability points into the membrane, then we want to 420 // redirect the call. However, if this capability is a promise, then it could resolve to 421 // something outside the membrane later. We have to wait before we actually redirect, 422 // otherwise behavior will differ depending on whether the promise is resolved. 423 KJ_IF_MAYBE(p, whenMoreResolved()) { 424 return newLocalPromiseClient(p->attach(addRef())) 425 ->call(interfaceId, methodId, kj::mv(context)); 426 } 427 } 428 429 return ClientHook::from(kj::mv(*r))->call(interfaceId, methodId, kj::mv(context)); 430 } else { 431 // !reverse because calls to the CallContext go in the opposite direction. 432 auto result = inner->call(interfaceId, methodId, 433 kj::refcounted<MembraneCallContextHook>(kj::mv(context), policy->addRef(), !reverse)); 434 435 KJ_IF_MAYBE(r, policy->onRevoked()) { 436 result.promise = result.promise.exclusiveJoin(kj::mv(*r)); 437 } 438 439 return { 440 kj::mv(result.promise), 441 kj::refcounted<MembranePipelineHook>(kj::mv(result.pipeline), policy->addRef(), reverse) 442 }; 443 } 444 } 445 446 kj::Maybe<ClientHook&> getResolved() override { 447 KJ_IF_MAYBE(r, resolved) { 448 return **r; 449 } 450 451 KJ_IF_MAYBE(newInner, inner->getResolved()) { 452 kj::Own<ClientHook> newResolved = wrap(*newInner, *policy, reverse); 453 ClientHook& result = *newResolved; 454 resolved = kj::mv(newResolved); 455 return result; 456 } else { 457 return nullptr; 458 } 459 } 460 461 kj::Maybe<kj::Promise<kj::Own<ClientHook>>> whenMoreResolved() override { 462 KJ_IF_MAYBE(r, resolved) { 463 return kj::Promise<kj::Own<ClientHook>>(r->get()->addRef()); 464 } 465 466 KJ_IF_MAYBE(promise, inner->whenMoreResolved()) { 467 KJ_IF_MAYBE(r, policy->onRevoked()) { 468 *promise = promise->exclusiveJoin(r->then([]() -> kj::Own<ClientHook> { 469 KJ_FAIL_REQUIRE("onRevoked() promise resolved; it should only reject"); 470 })); 471 } 472 473 return promise->then([this](kj::Own<ClientHook>&& newInner) { 474 kj::Own<ClientHook> newResolved = wrap(*newInner, *policy, reverse); 475 if (resolved == nullptr) { 476 resolved = newResolved->addRef(); 477 } 478 return newResolved; 479 }); 480 } else { 481 return nullptr; 482 } 483 } 484 485 kj::Own<ClientHook> addRef() override { 486 return kj::addRef(*this); 487 } 488 489 const void* getBrand() override { 490 return MEMBRANE_BRAND; 491 } 492 493 kj::Maybe<int> getFd() override { 494 // We can't let FDs pass over membranes because we have no way to enforce the membrane policy 495 // on them. If the MembranePolicy wishes to explicitly permit certain FDs to pass, it can 496 // always do so by overriding the appropriate policy methods. 497 return nullptr; 498 } 499 500 private: 501 kj::Own<ClientHook> inner; 502 kj::Own<MembranePolicy> policy; 503 bool reverse; 504 kj::Maybe<kj::Own<ClientHook>> resolved; 505 kj::Promise<void> revocationTask = nullptr; 506 }; 507 508 kj::Own<ClientHook> membrane(kj::Own<ClientHook> inner, MembranePolicy& policy, bool reverse) { 509 return MembraneHook::wrap(kj::mv(inner), policy, reverse); 510 } 511 512 } // namespace 513 514 Capability::Client MembranePolicy::importExternal(Capability::Client external) { 515 return Capability::Client(kj::refcounted<MembraneHook>( 516 ClientHook::from(kj::mv(external)), addRef(), true)); 517 } 518 519 Capability::Client MembranePolicy::exportInternal(Capability::Client internal) { 520 return Capability::Client(kj::refcounted<MembraneHook>( 521 ClientHook::from(kj::mv(internal)), addRef(), false)); 522 } 523 524 Capability::Client MembranePolicy::importInternal( 525 Capability::Client internal, MembranePolicy& exportPolicy, MembranePolicy& importPolicy) { 526 return kj::mv(internal); 527 } 528 529 Capability::Client MembranePolicy::exportExternal( 530 Capability::Client external, MembranePolicy& importPolicy, MembranePolicy& exportPolicy) { 531 return kj::mv(external); 532 } 533 534 Capability::Client membrane(Capability::Client inner, kj::Own<MembranePolicy> policy) { 535 return Capability::Client(membrane( 536 ClientHook::from(kj::mv(inner)), *policy, false)); 537 } 538 539 Capability::Client reverseMembrane(Capability::Client inner, kj::Own<MembranePolicy> policy) { 540 return Capability::Client(membrane( 541 ClientHook::from(kj::mv(inner)), *policy, true)); 542 } 543 544 namespace _ { // private 545 546 _::OrphanBuilder copyOutOfMembrane(PointerReader from, Orphanage to, 547 kj::Own<MembranePolicy> policy, bool reverse) { 548 MembraneCapTableReader capTable(*policy, reverse); 549 return _::OrphanBuilder::copy( 550 OrphanageInternal::getArena(to), 551 OrphanageInternal::getCapTable(to), 552 capTable.imbue(from)); 553 } 554 555 _::OrphanBuilder copyOutOfMembrane(StructReader from, Orphanage to, 556 kj::Own<MembranePolicy> policy, bool reverse) { 557 MembraneCapTableReader capTable(*policy, reverse); 558 return _::OrphanBuilder::copy( 559 OrphanageInternal::getArena(to), 560 OrphanageInternal::getCapTable(to), 561 capTable.imbue(from)); 562 } 563 564 _::OrphanBuilder copyOutOfMembrane(ListReader from, Orphanage to, 565 kj::Own<MembranePolicy> policy, bool reverse) { 566 MembraneCapTableReader capTable(*policy, reverse); 567 return _::OrphanBuilder::copy( 568 OrphanageInternal::getArena(to), 569 OrphanageInternal::getCapTable(to), 570 capTable.imbue(from)); 571 } 572 573 } // namespace _ (private) 574 575 } // namespace capnp 576