Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
capnproto
Commits
d07bf3b8
Commit
d07bf3b8
authored
Sep 29, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
More capabilities core API WIP.
parent
398dac0d
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
377 additions
and
26 deletions
+377
-26
arena.c++
c++/src/capnp/arena.c++
+60
-6
arena.h
c++/src/capnp/arena.h
+16
-5
capability-context.c++
c++/src/capnp/capability-context.c++
+64
-0
capability-context.h
c++/src/capnp/capability-context.h
+158
-0
capability.c++
c++/src/capnp/capability.c++
+5
-6
capability.h
c++/src/capnp/capability.h
+0
-0
layout.c++
c++/src/capnp/layout.c++
+16
-0
layout.h
c++/src/capnp/layout.h
+19
-4
object.h
c++/src/capnp/object.h
+34
-0
rpc.capnp
c++/src/capnp/rpc.capnp
+5
-5
No files found.
c++/src/capnp/arena.c++
View file @
d07bf3b8
...
@@ -24,10 +24,13 @@
...
@@ -24,10 +24,13 @@
#define CAPNP_PRIVATE
#define CAPNP_PRIVATE
#include "arena.h"
#include "arena.h"
#include "message.h"
#include "message.h"
#include "capability.h"
#include <kj/debug.h>
#include <kj/debug.h>
#include <vector>
#include <vector>
#include <string.h>
#include <string.h>
#include <stdio.h>
#include <stdio.h>
#include "capability.h"
#include "capability-context.h"
namespace
capnp
{
namespace
capnp
{
namespace
_
{
// private
namespace
_
{
// private
...
@@ -99,10 +102,42 @@ void BasicReaderArena::reportReadLimitReached() {
...
@@ -99,10 +102,42 @@ void BasicReaderArena::reportReadLimitReached() {
}
}
}
}
namespace
{
class
DummyClientHook
final
:
public
ClientHook
{
public
:
Request
<
ObjectPointer
,
TypelessAnswer
>
newCall
(
uint64_t
interfaceId
,
uint16_t
methodId
)
const
override
{
KJ_FAIL_REQUIRE
(
"Calling capability that was extracted from a message that had no "
"capability context."
);
}
kj
::
Promise
<
void
>
whenResolved
()
const
override
{
return
kj
::
READY_NOW
;
}
kj
::
Own
<
ClientHook
>
addRef
()
const
override
{
return
kj
::
heap
<
DummyClientHook
>
();
}
void
*
getBrand
()
const
override
{
return
nullptr
;
}
};
}
// namespace
kj
::
Own
<
ClientHook
>
BasicReaderArena
::
extractCap
(
const
_
::
StructReader
&
capDescriptor
)
{
KJ_FAIL_REQUIRE
(
"Message contained a capability but is not imbued with a capability context."
)
{
return
kj
::
heap
<
DummyClientHook
>
();
}
}
// =======================================================================================
// =======================================================================================
ImbuedReaderArena
::
ImbuedReaderArena
(
Arena
*
base
)
ImbuedReaderArena
::
ImbuedReaderArena
(
Arena
*
base
,
CapExtractorBase
*
capExtractor
)
:
base
(
base
),
segment0
(
nullptr
,
SegmentId
(
0
),
nullptr
,
nullptr
)
{}
:
base
(
base
),
capExtractor
(
capExtractor
),
segment0
(
nullptr
,
SegmentId
(
0
),
nullptr
,
nullptr
)
{}
ImbuedReaderArena
::~
ImbuedReaderArena
()
noexcept
(
false
)
{}
ImbuedReaderArena
::~
ImbuedReaderArena
()
noexcept
(
false
)
{}
SegmentReader
*
ImbuedReaderArena
::
imbue
(
SegmentReader
*
baseSegment
)
{
SegmentReader
*
ImbuedReaderArena
::
imbue
(
SegmentReader
*
baseSegment
)
{
...
@@ -139,8 +174,6 @@ SegmentReader* ImbuedReaderArena::imbue(SegmentReader* baseSegment) {
...
@@ -139,8 +174,6 @@ SegmentReader* ImbuedReaderArena::imbue(SegmentReader* baseSegment) {
return
result
;
return
result
;
}
}
// implements Arena ------------------------------------------------
SegmentReader
*
ImbuedReaderArena
::
tryGetSegment
(
SegmentId
id
)
{
SegmentReader
*
ImbuedReaderArena
::
tryGetSegment
(
SegmentId
id
)
{
return
imbue
(
base
->
tryGetSegment
(
id
));
return
imbue
(
base
->
tryGetSegment
(
id
));
}
}
...
@@ -149,6 +182,10 @@ void ImbuedReaderArena::reportReadLimitReached() {
...
@@ -149,6 +182,10 @@ void ImbuedReaderArena::reportReadLimitReached() {
return
base
->
reportReadLimitReached
();
return
base
->
reportReadLimitReached
();
}
}
kj
::
Own
<
ClientHook
>
ImbuedReaderArena
::
extractCap
(
const
_
::
StructReader
&
capDescriptor
)
{
return
capExtractor
->
extractCapInternal
(
capDescriptor
);
}
// =======================================================================================
// =======================================================================================
BasicBuilderArena
::
BasicBuilderArena
(
MessageBuilder
*
message
)
BasicBuilderArena
::
BasicBuilderArena
(
MessageBuilder
*
message
)
...
@@ -288,10 +325,19 @@ void BasicBuilderArena::reportReadLimitReached() {
...
@@ -288,10 +325,19 @@ void BasicBuilderArena::reportReadLimitReached() {
}
}
}
}
kj
::
Own
<
ClientHook
>
BasicBuilderArena
::
extractCap
(
const
_
::
StructReader
&
capDescriptor
)
{
KJ_FAIL_REQUIRE
(
"Message contains no capabilities."
);
}
void
BasicBuilderArena
::
injectCap
(
_
::
PointerBuilder
pointer
,
kj
::
Own
<
ClientHook
>&&
cap
)
{
KJ_FAIL_REQUIRE
(
"Cannot inject capability into a builder that has not been imbued with a "
"capability context."
);
}
// =======================================================================================
// =======================================================================================
ImbuedBuilderArena
::
ImbuedBuilderArena
(
BuilderArena
*
base
)
ImbuedBuilderArena
::
ImbuedBuilderArena
(
BuilderArena
*
base
,
CapInjectorBase
*
capInjector
)
:
base
(
base
),
segment0
(
nullptr
)
{}
:
base
(
base
),
capInjector
(
capInjector
),
segment0
(
nullptr
)
{}
ImbuedBuilderArena
::~
ImbuedBuilderArena
()
noexcept
(
false
)
{}
ImbuedBuilderArena
::~
ImbuedBuilderArena
()
noexcept
(
false
)
{}
SegmentBuilder
*
ImbuedBuilderArena
::
imbue
(
SegmentBuilder
*
baseSegment
)
{
SegmentBuilder
*
ImbuedBuilderArena
::
imbue
(
SegmentBuilder
*
baseSegment
)
{
...
@@ -334,6 +380,10 @@ void ImbuedBuilderArena::reportReadLimitReached() {
...
@@ -334,6 +380,10 @@ void ImbuedBuilderArena::reportReadLimitReached() {
base
->
reportReadLimitReached
();
base
->
reportReadLimitReached
();
}
}
kj
::
Own
<
ClientHook
>
ImbuedBuilderArena
::
extractCap
(
const
_
::
StructReader
&
capDescriptor
)
{
return
capInjector
->
getInjectedCapInternal
(
capDescriptor
);
}
SegmentBuilder
*
ImbuedBuilderArena
::
getSegment
(
SegmentId
id
)
{
SegmentBuilder
*
ImbuedBuilderArena
::
getSegment
(
SegmentId
id
)
{
return
imbue
(
base
->
getSegment
(
id
));
return
imbue
(
base
->
getSegment
(
id
));
}
}
...
@@ -344,5 +394,9 @@ BuilderArena::AllocateResult ImbuedBuilderArena::allocate(WordCount amount) {
...
@@ -344,5 +394,9 @@ BuilderArena::AllocateResult ImbuedBuilderArena::allocate(WordCount amount) {
return
result
;
return
result
;
}
}
void
ImbuedBuilderArena
::
injectCap
(
_
::
PointerBuilder
pointer
,
kj
::
Own
<
ClientHook
>&&
cap
)
{
return
capInjector
->
injectCapInternal
(
pointer
,
kj
::
mv
(
cap
));
}
}
// namespace _ (private)
}
// namespace _ (private)
}
// namespace capnp
}
// namespace capnp
c++/src/capnp/arena.h
View file @
d07bf3b8
...
@@ -34,10 +34,13 @@
...
@@ -34,10 +34,13 @@
#include <kj/mutex.h>
#include <kj/mutex.h>
#include "common.h"
#include "common.h"
#include "message.h"
#include "message.h"
#include "layout.h"
namespace
capnp
{
namespace
capnp
{
class
TypelessCapability
;
class
CapExtractorBase
;
class
CapInjectorBase
;
class
ClientHook
;
namespace
_
{
// private
namespace
_
{
// private
...
@@ -182,7 +185,7 @@ public:
...
@@ -182,7 +185,7 @@ public:
// the VALIDATE_INPUT() macro which may throw an exception; if it return normally, the caller
// the VALIDATE_INPUT() macro which may throw an exception; if it return normally, the caller
// will need to continue with default values.
// will need to continue with default values.
virtual
kj
::
Own
<
TypelessCapability
>
extractCap
(
const
_
::
StructReader
&
capDescriptor
)
;
virtual
kj
::
Own
<
ClientHook
>
extractCap
(
const
_
::
StructReader
&
capDescriptor
)
=
0
;
// Given a StructReader for a capability descriptor embedded in the message, return the
// Given a StructReader for a capability descriptor embedded in the message, return the
// corresponding capability.
// corresponding capability.
};
};
...
@@ -196,6 +199,7 @@ public:
...
@@ -196,6 +199,7 @@ public:
// implements Arena ------------------------------------------------
// implements Arena ------------------------------------------------
SegmentReader
*
tryGetSegment
(
SegmentId
id
)
override
;
SegmentReader
*
tryGetSegment
(
SegmentId
id
)
override
;
void
reportReadLimitReached
()
override
;
void
reportReadLimitReached
()
override
;
kj
::
Own
<
ClientHook
>
extractCap
(
const
_
::
StructReader
&
capDescriptor
);
private
:
private
:
MessageReader
*
message
;
MessageReader
*
message
;
...
@@ -210,7 +214,7 @@ private:
...
@@ -210,7 +214,7 @@ private:
class
ImbuedReaderArena
final
:
public
Arena
{
class
ImbuedReaderArena
final
:
public
Arena
{
public
:
public
:
ImbuedReaderArena
(
Arena
*
base
);
ImbuedReaderArena
(
Arena
*
base
,
CapExtractorBase
*
capExtractor
);
~
ImbuedReaderArena
()
noexcept
(
false
);
~
ImbuedReaderArena
()
noexcept
(
false
);
KJ_DISALLOW_COPY
(
ImbuedReaderArena
);
KJ_DISALLOW_COPY
(
ImbuedReaderArena
);
...
@@ -219,9 +223,11 @@ public:
...
@@ -219,9 +223,11 @@ public:
// implements Arena ------------------------------------------------
// implements Arena ------------------------------------------------
SegmentReader
*
tryGetSegment
(
SegmentId
id
)
override
;
SegmentReader
*
tryGetSegment
(
SegmentId
id
)
override
;
void
reportReadLimitReached
()
override
;
void
reportReadLimitReached
()
override
;
kj
::
Own
<
ClientHook
>
extractCap
(
const
_
::
StructReader
&
capDescriptor
);
private
:
private
:
Arena
*
base
;
Arena
*
base
;
CapExtractorBase
*
capExtractor
;
// Optimize for single-segment messages so that small messages are handled quickly.
// Optimize for single-segment messages so that small messages are handled quickly.
SegmentReader
segment0
;
SegmentReader
segment0
;
...
@@ -248,7 +254,7 @@ public:
...
@@ -248,7 +254,7 @@ public:
// the arena is guaranteed to succeed. Therefore callers should try to allocate from a specific
// the arena is guaranteed to succeed. Therefore callers should try to allocate from a specific
// segment first if there is one, then fall back to the arena.
// segment first if there is one, then fall back to the arena.
virtual
void
injectCap
(
_
::
PointerBuilder
pointer
,
kj
::
Own
<
TypelessCapability
>&&
cap
)
=
0
;
virtual
void
injectCap
(
_
::
PointerBuilder
pointer
,
kj
::
Own
<
ClientHook
>&&
cap
)
=
0
;
// Add the capability to the message and initialize the given pointer as an interface pointer
// Add the capability to the message and initialize the given pointer as an interface pointer
// pointing to this cap.
// pointing to this cap.
};
};
...
@@ -271,10 +277,12 @@ public:
...
@@ -271,10 +277,12 @@ public:
// implements Arena ------------------------------------------------
// implements Arena ------------------------------------------------
SegmentReader
*
tryGetSegment
(
SegmentId
id
)
override
;
SegmentReader
*
tryGetSegment
(
SegmentId
id
)
override
;
void
reportReadLimitReached
()
override
;
void
reportReadLimitReached
()
override
;
kj
::
Own
<
ClientHook
>
extractCap
(
const
_
::
StructReader
&
capDescriptor
);
// implements BuilderArena -----------------------------------------
// implements BuilderArena -----------------------------------------
SegmentBuilder
*
getSegment
(
SegmentId
id
)
override
;
SegmentBuilder
*
getSegment
(
SegmentId
id
)
override
;
AllocateResult
allocate
(
WordCount
amount
)
override
;
AllocateResult
allocate
(
WordCount
amount
)
override
;
void
injectCap
(
_
::
PointerBuilder
pointer
,
kj
::
Own
<
ClientHook
>&&
cap
);
private
:
private
:
MessageBuilder
*
message
;
MessageBuilder
*
message
;
...
@@ -294,7 +302,7 @@ class ImbuedBuilderArena final: public BuilderArena {
...
@@ -294,7 +302,7 @@ class ImbuedBuilderArena final: public BuilderArena {
// A BuilderArena imbued with the ability to inject capabilities.
// A BuilderArena imbued with the ability to inject capabilities.
public
:
public
:
ImbuedBuilderArena
(
BuilderArena
*
base
);
ImbuedBuilderArena
(
BuilderArena
*
base
,
CapInjectorBase
*
capInjector
);
~
ImbuedBuilderArena
()
noexcept
(
false
);
~
ImbuedBuilderArena
()
noexcept
(
false
);
KJ_DISALLOW_COPY
(
ImbuedBuilderArena
);
KJ_DISALLOW_COPY
(
ImbuedBuilderArena
);
...
@@ -304,13 +312,16 @@ public:
...
@@ -304,13 +312,16 @@ public:
// implements Arena ------------------------------------------------
// implements Arena ------------------------------------------------
SegmentReader
*
tryGetSegment
(
SegmentId
id
)
override
;
SegmentReader
*
tryGetSegment
(
SegmentId
id
)
override
;
void
reportReadLimitReached
()
override
;
void
reportReadLimitReached
()
override
;
kj
::
Own
<
ClientHook
>
extractCap
(
const
_
::
StructReader
&
capDescriptor
);
// implements BuilderArena -----------------------------------------
// implements BuilderArena -----------------------------------------
SegmentBuilder
*
getSegment
(
SegmentId
id
)
override
;
SegmentBuilder
*
getSegment
(
SegmentId
id
)
override
;
AllocateResult
allocate
(
WordCount
amount
)
override
;
AllocateResult
allocate
(
WordCount
amount
)
override
;
void
injectCap
(
_
::
PointerBuilder
pointer
,
kj
::
Own
<
ClientHook
>&&
cap
);
private
:
private
:
BuilderArena
*
base
;
BuilderArena
*
base
;
CapInjectorBase
*
capInjector
;
ImbuedSegmentBuilder
segment0
;
ImbuedSegmentBuilder
segment0
;
...
...
c++/src/capnp/capability-context.c++
0 → 100644
View file @
d07bf3b8
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define CAPNP_PRIVATE
#include "capability-context.h"
#include "arena.h"
#include <kj/debug.h>
namespace
capnp
{
CapReaderContext
::
CapReaderContext
(
CapExtractorBase
&
extractor
)
:
extractor
(
&
extractor
)
{}
CapReaderContext
::~
CapReaderContext
()
noexcept
(
false
)
{
if
(
extractor
==
nullptr
)
{
kj
::
dtor
(
arena
());
}
}
ObjectPointer
::
Reader
CapReaderContext
::
imbue
(
ObjectPointer
::
Reader
base
)
{
KJ_REQUIRE
(
extractor
!=
nullptr
,
"imbue() can only be called once."
);
KJ_IF_MAYBE
(
oldArena
,
base
.
reader
.
getArena
())
{
kj
::
ctor
(
arena
(),
oldArena
,
extractor
);
}
else
{
KJ_FAIL_REQUIRE
(
"Cannot imbue unchecked message."
);
}
extractor
=
nullptr
;
return
ObjectPointer
::
Reader
(
base
.
reader
.
imbue
(
arena
()));
}
CapBuilderContext
::
CapBuilderContext
(
CapInjectorBase
&
injector
)
:
injector
(
&
injector
)
{}
CapBuilderContext
::~
CapBuilderContext
()
noexcept
(
false
)
{
if
(
injector
==
nullptr
)
{
kj
::
dtor
(
arena
());
}
}
ObjectPointer
::
Builder
CapBuilderContext
::
imbue
(
ObjectPointer
::
Builder
base
)
{
KJ_REQUIRE
(
injector
!=
nullptr
,
"imbue() can only be called once."
);
kj
::
ctor
(
arena
(),
&
base
.
builder
.
getArena
(),
injector
);
injector
=
nullptr
;
return
ObjectPointer
::
Builder
(
base
.
builder
.
imbue
(
arena
()));
}
}
// namespace capnp
c++/src/capnp/capability-context.h
0 → 100644
View file @
d07bf3b8
// Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Classes for imbuing message readers/builders with a capability context.
//
// These classes are for use by RPC implementations. Application code need not know about them.
//
// Normally, MessageReader and MessageBuilder do not support interface pointers because they
// are not RPC-aware and so have no idea how to convert between a serialized CapabilityDescriptor
// and a live capability. To fix this, a reader/builder object needs to be "imbued" with a
// capability context. This creates a new reader/builder which points at the same object but has
// the ability to deal with interface fields. Use `CapReaderContext` and `CapBuilderContext` to
// accomplish this.
#ifndef CAPNP_CAPABILITY_CONTEXT_H_
#define CAPNP_CAPABILITY_CONTEXT_H_
#include "layout.h"
#include "object.h"
#include <kj/mutex.h>
namespace
capnp
{
class
ClientHook
;
namespace
_
{
// private
class
ImbuedReaderArena
;
class
ImbuedBuilderArena
;
}
// namespace _ (private)
class
CapExtractorBase
{
// Non-template base class for CapExtractor<T>.
private
:
virtual
kj
::
Own
<
ClientHook
>
extractCapInternal
(
const
_
::
StructReader
&
capDescriptor
)
=
0
;
friend
class
_
::
ImbuedReaderArena
;
};
class
CapInjectorBase
{
// Non-template base class for CapInjector<T>.
private
:
virtual
void
injectCapInternal
(
_
::
PointerBuilder
builder
,
kj
::
Own
<
ClientHook
>&&
cap
)
=
0
;
virtual
kj
::
Own
<
ClientHook
>
getInjectedCapInternal
(
const
_
::
StructReader
&
capDescriptor
)
=
0
;
friend
class
_
::
ImbuedBuilderArena
;
};
template
<
typename
CapDescriptor
>
class
CapExtractor
:
public
CapExtractorBase
{
// Callback used to read a capability from a message, implemented by the RPC system.
// `CapDescriptor` is the struct type which the RPC implementation uses to represent
// capabilities. (On the wire, an interface pointer actually points to a struct of this type.)
public
:
virtual
kj
::
Own
<
ClientHook
>
extractCap
(
typename
CapDescriptor
::
Reader
descriptor
)
=
0
;
// Given the descriptor read off the wire, construct a live capability.
private
:
kj
::
Own
<
ClientHook
>
extractCapInternal
(
const
_
::
StructReader
&
capDescriptor
)
override
final
{
return
extractCap
(
typename
CapDescriptor
::
Reader
(
capDescriptor
));
}
};
template
<
typename
CapDescriptor
>
class
CapInjector
:
public
CapInjectorBase
{
// Callback used to write a capability into a message, implemented by the RPC system.
// `CapDescriptor` is the struct type which the RPC implementation uses to represent
// capabilities. (On the wire, an interface pointer actually points to a struct of this type.)
public
:
virtual
void
injectCap
(
typename
CapDescriptor
::
Builder
descriptor
,
kj
::
Own
<
ClientHook
>&&
cap
)
=
0
;
// Fill in the given descriptor so that it describes the given capability.
virtual
kj
::
Own
<
ClientHook
>
getInjectedCap
(
typename
CapDescriptor
::
Reader
descriptor
)
=
0
;
// Read back a cap that was previously injected with `injectCap`. This should return a new
// reference.
private
:
void
injectCapInternal
(
_
::
PointerBuilder
builder
,
kj
::
Own
<
ClientHook
>&&
cap
)
override
final
{
injectCap
(
typename
CapDescriptor
::
Builder
(
builder
.
initCapDescriptor
(
_
::
structSize
<
CapDescriptor
>
())),
kj
::
mv
(
cap
));
}
kj
::
Own
<
ClientHook
>
getInjectedCapInternal
(
const
_
::
StructReader
&
capDescriptor
)
{
return
getInjectedCap
(
typename
CapDescriptor
::
Reader
(
capDescriptor
));
}
};
// -------------------------------------------------------------------
class
CapReaderContext
{
// Class which can "imbue" reader objects from some other message with a capability context,
// so that interface pointers found in the message can be extracted and called.
//
// `imbue()` can only be called once per context.
public
:
CapReaderContext
(
CapExtractorBase
&
extractor
);
~
CapReaderContext
()
noexcept
(
false
);
ObjectPointer
::
Reader
imbue
(
ObjectPointer
::
Reader
base
);
private
:
CapExtractorBase
*
extractor
;
// becomes null once arena is allocated
void
*
arenaSpace
[
12
+
sizeof
(
kj
::
MutexGuarded
<
void
*>
)
/
sizeof
(
void
*
)];
_
::
ImbuedReaderArena
&
arena
()
{
return
*
reinterpret_cast
<
_
::
ImbuedReaderArena
*>
(
arenaSpace
);
}
friend
class
_
::
ImbuedReaderArena
;
};
class
CapBuilderContext
{
// Class which can "imbue" reader objects from some other message with a capability context,
// so that interface pointers found in the message can be set to point at live capabilities.
//
// `imbue()` can only be called once per context.
public
:
CapBuilderContext
(
CapInjectorBase
&
injector
);
~
CapBuilderContext
()
noexcept
(
false
);
ObjectPointer
::
Builder
imbue
(
ObjectPointer
::
Builder
base
);
private
:
CapInjectorBase
*
injector
;
// becomes null once arena is allocated
void
*
arenaSpace
[
12
+
sizeof
(
kj
::
MutexGuarded
<
void
*>
)
/
sizeof
(
void
*
)];
_
::
ImbuedBuilderArena
&
arena
()
{
return
*
reinterpret_cast
<
_
::
ImbuedBuilderArena
*>
(
arenaSpace
);
}
friend
class
_
::
ImbuedBuilderArena
;
};
}
// namespace capnp
#endif // CAPNP_CAPABILITY_CONTEXT_H_
c++/src/capnp/capability.c++
View file @
d07bf3b8
...
@@ -24,19 +24,18 @@
...
@@ -24,19 +24,18 @@
#include "capability.h"
#include "capability.h"
namespace
capnp
{
namespace
capnp
{
namespace
_
{
// private
CallResult
::
Pipeline
CallResult
::
Pipeline
::
getPointerField
(
uint16_t
pointerIndex
)
const
{
TypelessAnswer
::
Pipeline
TypelessAnswer
::
Pipeline
::
getPointerField
(
auto
newOps
=
kj
::
heapArray
<
PipelineManager
::
Op
>
(
ops
.
size
()
+
1
);
uint16_t
pointerIndex
)
const
{
auto
newOps
=
kj
::
heapArray
<
PipelineOp
>
(
ops
.
size
()
+
1
);
for
(
auto
i
:
kj
::
indices
(
ops
))
{
for
(
auto
i
:
kj
::
indices
(
ops
))
{
newOps
[
i
]
=
ops
[
i
];
newOps
[
i
]
=
ops
[
i
];
}
}
auto
&
newOp
=
newOps
[
ops
.
size
()];
auto
&
newOp
=
newOps
[
ops
.
size
()];
newOp
.
type
=
Pipeline
Manager
::
Op
::
GET_POINTER_FIELD
;
newOp
.
type
=
PipelineOp
::
GET_POINTER_FIELD
;
newOp
.
pointerIndex
=
pointerIndex
;
newOp
.
pointerIndex
=
pointerIndex
;
return
Pipeline
(
call
->
addRef
(),
kj
::
mv
(
newOps
));
return
Pipeline
(
hook
->
addRef
(),
kj
::
mv
(
newOps
));
}
}
}
// namespace _ (private)
}
// namespace capnp
}
// namespace capnp
c++/src/capnp/capability.h
View file @
d07bf3b8
This diff is collapsed.
Click to expand it.
c++/src/capnp/layout.c++
View file @
d07bf3b8
...
@@ -2104,6 +2104,14 @@ PointerReader PointerBuilder::asReader() const {
...
@@ -2104,6 +2104,14 @@ PointerReader PointerBuilder::asReader() const {
return
PointerReader
(
segment
,
pointer
,
std
::
numeric_limits
<
int
>::
max
());
return
PointerReader
(
segment
,
pointer
,
std
::
numeric_limits
<
int
>::
max
());
}
}
BuilderArena
&
PointerBuilder
::
getArena
()
const
{
return
*
segment
->
getArena
();
}
PointerBuilder
PointerBuilder
::
imbue
(
ImbuedBuilderArena
&
newArena
)
const
{
return
PointerBuilder
(
newArena
.
imbue
(
segment
),
pointer
);
}
// =======================================================================================
// =======================================================================================
// PointerReader
// PointerReader
...
@@ -2139,6 +2147,14 @@ bool PointerReader::isNull() const {
...
@@ -2139,6 +2147,14 @@ bool PointerReader::isNull() const {
return
pointer
==
nullptr
||
pointer
->
isNull
();
return
pointer
==
nullptr
||
pointer
->
isNull
();
}
}
kj
::
Maybe
<
Arena
&>
PointerReader
::
getArena
()
const
{
return
segment
==
nullptr
?
nullptr
:
segment
->
getArena
();
}
PointerReader
PointerReader
::
imbue
(
ImbuedReaderArena
&
newArena
)
const
{
return
PointerReader
(
newArena
.
imbue
(
segment
),
pointer
,
nestingLimit
);
}
// =======================================================================================
// =======================================================================================
// StructBuilder
// StructBuilder
...
...
c++/src/capnp/layout.h
View file @
d07bf3b8
...
@@ -39,7 +39,7 @@
...
@@ -39,7 +39,7 @@
namespace
capnp
{
namespace
capnp
{
class
TypelessCapability
;
class
ClientHook
;
namespace
_
{
// private
namespace
_
{
// private
...
@@ -54,7 +54,10 @@ struct WirePointer;
...
@@ -54,7 +54,10 @@ struct WirePointer;
struct
WireHelpers
;
struct
WireHelpers
;
class
SegmentReader
;
class
SegmentReader
;
class
SegmentBuilder
;
class
SegmentBuilder
;
class
Arena
;
class
BuilderArena
;
class
BuilderArena
;
class
ImbuedReaderArena
;
class
ImbuedBuilderArena
;
// =============================================================================
// =============================================================================
...
@@ -284,7 +287,7 @@ public:
...
@@ -284,7 +287,7 @@ public:
ListBuilder
getList
(
FieldSize
elementSize
,
const
word
*
defaultValzue
);
ListBuilder
getList
(
FieldSize
elementSize
,
const
word
*
defaultValzue
);
ListBuilder
getStructList
(
StructSize
elementSize
,
const
word
*
defaultValue
);
ListBuilder
getStructList
(
StructSize
elementSize
,
const
word
*
defaultValue
);
template
<
typename
T
>
typename
T
::
Builder
getBlob
(
const
void
*
defaultValue
,
ByteCount
defaultSize
);
template
<
typename
T
>
typename
T
::
Builder
getBlob
(
const
void
*
defaultValue
,
ByteCount
defaultSize
);
kj
::
Own
<
TypelessCapability
>
getCapability
();
kj
::
Own
<
ClientHook
>
getCapability
();
// Get methods: Get the value. If it is null, initialize it to a copy of the default value.
// Get methods: Get the value. If it is null, initialize it to a copy of the default value.
// The default value is encoded as an "unchecked message" for structs, lists, and objects, or a
// The default value is encoded as an "unchecked message" for structs, lists, and objects, or a
// simple byte array for blobs.
// simple byte array for blobs.
...
@@ -300,7 +303,7 @@ public:
...
@@ -300,7 +303,7 @@ public:
void
setStruct
(
const
StructReader
&
value
);
void
setStruct
(
const
StructReader
&
value
);
void
setList
(
const
ListReader
&
value
);
void
setList
(
const
ListReader
&
value
);
template
<
typename
T
>
void
setBlob
(
typename
T
::
Reader
value
);
template
<
typename
T
>
void
setBlob
(
typename
T
::
Reader
value
);
void
setCapability
(
kj
::
Own
<
TypelessCapability
>&&
cap
);
void
setCapability
(
kj
::
Own
<
ClientHook
>&&
cap
);
// Set methods: Initialize the pointer to a newly-allocated copy of the given value, discarding
// Set methods: Initialize the pointer to a newly-allocated copy of the given value, discarding
// the existing object.
// the existing object.
...
@@ -321,6 +324,12 @@ public:
...
@@ -321,6 +324,12 @@ public:
PointerReader
asReader
()
const
;
PointerReader
asReader
()
const
;
BuilderArena
&
getArena
()
const
;
// Get the arena containing this pointer.
PointerBuilder
imbue
(
ImbuedBuilderArena
&
newArena
)
const
;
// Imbue the pointer with a capability context, returning the imbued pointer.
private
:
private
:
SegmentBuilder
*
segment
;
// Memory segment in which the pointer resides.
SegmentBuilder
*
segment
;
// Memory segment in which the pointer resides.
WirePointer
*
pointer
;
// Pointer to the pointer.
WirePointer
*
pointer
;
// Pointer to the pointer.
...
@@ -342,7 +351,7 @@ public:
...
@@ -342,7 +351,7 @@ public:
ListReader
getList
(
FieldSize
expectedElementSize
,
const
word
*
defaultValue
)
const
;
ListReader
getList
(
FieldSize
expectedElementSize
,
const
word
*
defaultValue
)
const
;
template
<
typename
T
>
template
<
typename
T
>
typename
T
::
Reader
getBlob
(
const
void
*
defaultValue
,
ByteCount
defaultSize
)
const
;
typename
T
::
Reader
getBlob
(
const
void
*
defaultValue
,
ByteCount
defaultSize
)
const
;
kj
::
Own
<
TypelessCapability
>
getCapability
();
kj
::
Own
<
ClientHook
>
getCapability
();
// Get methods: Get the value. If it is null, return the default value instead.
// Get methods: Get the value. If it is null, return the default value instead.
// The default value is encoded as an "unchecked message" for structs, lists, and objects, or a
// The default value is encoded as an "unchecked message" for structs, lists, and objects, or a
// simple byte array for blobs.
// simple byte array for blobs.
...
@@ -352,6 +361,12 @@ public:
...
@@ -352,6 +361,12 @@ public:
// word* can actually be passed to readUnchecked() to read the designated sub-object later. If
// word* can actually be passed to readUnchecked() to read the designated sub-object later. If
// this isn't an unchecked message, throws an exception.
// this isn't an unchecked message, throws an exception.
kj
::
Maybe
<
Arena
&>
getArena
()
const
;
// Get the arena containing this pointer.
PointerReader
imbue
(
ImbuedReaderArena
&
newArena
)
const
;
// Imbue the pointer with a capability context, returning the imbued pointer.
private
:
private
:
SegmentReader
*
segment
;
// Memory segment in which the pointer resides.
SegmentReader
*
segment
;
// Memory segment in which the pointer resides.
const
WirePointer
*
pointer
;
// Pointer to the pointer. null = treat as null pointer.
const
WirePointer
*
pointer
;
// Pointer to the pointer. null = treat as null pointer.
...
...
c++/src/capnp/object.h
View file @
d07bf3b8
...
@@ -63,6 +63,7 @@ struct ObjectPointer {
...
@@ -63,6 +63,7 @@ struct ObjectPointer {
_
::
PointerReader
reader
;
_
::
PointerReader
reader
;
friend
struct
ObjectPointer
;
friend
struct
ObjectPointer
;
friend
class
Orphanage
;
friend
class
Orphanage
;
friend
class
CapReaderContext
;
};
};
class
Builder
{
class
Builder
{
...
@@ -143,6 +144,7 @@ struct ObjectPointer {
...
@@ -143,6 +144,7 @@ struct ObjectPointer {
private
:
private
:
_
::
PointerBuilder
builder
;
_
::
PointerBuilder
builder
;
friend
class
CapBuilderContext
;
};
};
};
};
...
@@ -281,6 +283,38 @@ inline Orphan<T> Orphan<ObjectPointer>::releaseAs() {
...
@@ -281,6 +283,38 @@ inline Orphan<T> Orphan<ObjectPointer>::releaseAs() {
return
Orphan
<
T
>
(
kj
::
mv
(
builder
));
return
Orphan
<
T
>
(
kj
::
mv
(
builder
));
}
}
// Using ObjectPointer as the template type should work...
template
<>
inline
typename
ObjectPointer
::
Reader
ObjectPointer
::
Reader
::
getAs
<
ObjectPointer
>
()
{
return
*
this
;
}
template
<>
inline
typename
ObjectPointer
::
Builder
ObjectPointer
::
Builder
::
getAs
<
ObjectPointer
>
()
{
return
*
this
;
}
template
<>
inline
typename
ObjectPointer
::
Builder
ObjectPointer
::
Builder
::
initAs
<
ObjectPointer
>
()
{
clear
();
return
*
this
;
}
template
<>
inline
void
ObjectPointer
::
Builder
::
setAs
<
ObjectPointer
>
(
ObjectPointer
::
Reader
value
)
{
return
builder
.
copyFrom
(
value
.
reader
);
}
template
<>
inline
void
ObjectPointer
::
Builder
::
adopt
<
ObjectPointer
>
(
Orphan
<
ObjectPointer
>&&
orphan
)
{
builder
.
adopt
(
kj
::
mv
(
orphan
.
builder
));
}
template
<>
inline
Orphan
<
ObjectPointer
>
ObjectPointer
::
Builder
::
disownAs
<
ObjectPointer
>
()
{
return
Orphan
<
ObjectPointer
>
(
builder
.
disown
());
}
template
<>
inline
Orphan
<
ObjectPointer
>
Orphan
<
ObjectPointer
>::
releaseAs
()
{
return
kj
::
mv
(
*
this
);
}
}
// namespace capnp
}
// namespace capnp
#endif // CAPNP_OBJECT_H_
#endif // CAPNP_OBJECT_H_
c++/src/capnp/rpc.capnp
View file @
d07bf3b8
...
@@ -950,7 +950,7 @@ using JoinAnswer = Object;
...
@@ -950,7 +950,7 @@ using JoinAnswer = Object;
#
#
# # Level 4 features -----------------------------------------------
# # Level 4 features -----------------------------------------------
#
#
# newJoiner(count :UInt32)
:
NewJoinerResponse;
# newJoiner(count :UInt32)
:
NewJoinerResponse;
# # Prepare a new Join operation, which will eventually lead to forming a new direct connection
# # Prepare a new Join operation, which will eventually lead to forming a new direct connection
# # to the host of the joined capability. `count` is the number of capabilities to join.
# # to the host of the joined capability. `count` is the number of capabilities to join.
#
#
...
@@ -973,7 +973,7 @@ using JoinAnswer = Object;
...
@@ -973,7 +973,7 @@ using JoinAnswer = Object;
# # message on it with the specified `ProvisionId` in order to receive the final capability.
# # message on it with the specified `ProvisionId` in order to receive the final capability.
# }
# }
#
#
# acceptConnectionFromJoiner(parts
:
List(JoinKeyPart), paths :List(VatPath))
# acceptConnectionFromJoiner(parts
:
List(JoinKeyPart), paths :List(VatPath))
# :ConnectionAndProvisionId;
# :ConnectionAndProvisionId;
# # Called on a joined capability's host to receive the connection from the joiner, once all
# # Called on a joined capability's host to receive the connection from the joiner, once all
# # key parts have arrived. The caller should expect to receive an `Accept` message over the
# # key parts have arrived. The caller should expect to receive an `Accept` message over the
...
@@ -1002,17 +1002,17 @@ using JoinAnswer = Object;
...
@@ -1002,17 +1002,17 @@ using JoinAnswer = Object;
# sendToTarget :RecipientId;
# sendToTarget :RecipientId;
# }
# }
#
#
# connectToIntroduced(capId
:
ThirdPartyCapId) :ConnectionAndProvisionId;
# connectToIntroduced(capId
:
ThirdPartyCapId) :ConnectionAndProvisionId;
# # Given a ThirdPartyCapId received over this connection, connect to the third party. The
# # Given a ThirdPartyCapId received over this connection, connect to the third party. The
# # caller should then send an `Accept` message over the new connection.
# # caller should then send an `Accept` message over the new connection.
#
#
# acceptIntroducedConnection(recipientId
: RecipientId): Connection
# acceptIntroducedConnection(recipientId
:RecipientId) :Connection;
# # Given a RecipientId received in a `Provide` message on this `Connection`, wait for the
# # Given a RecipientId received in a `Provide` message on this `Connection`, wait for the
# # recipient to connect, and return the connection formed. Usually, the first message received
# # recipient to connect, and return the connection formed. Usually, the first message received
# # on the new connection will be an `Accept` message.
# # on the new connection will be an `Accept` message.
# }
# }
#
#
# st
ur
ct ConnectionAndProvisionId {
# st
ru
ct ConnectionAndProvisionId {
# # **(level 3)**
# # **(level 3)**
#
#
# connection :Connection;
# connection :Connection;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment