Add bootstrap RPC methods
This is the new way for initializing RPC connections. It replaces the deprecated restore functionality
This commit is contained in:
@@ -30,6 +30,7 @@ cdef extern from "capnp/helpers/rpcHelper.h":
|
||||
Capability.Client restoreHelper(RpcSystem&, MessageReader&)
|
||||
Capability.Client restoreHelper(RpcSystem&, AnyPointer.Reader&)
|
||||
Capability.Client restoreHelper(RpcSystem&, AnyPointer.Builder&)
|
||||
Capability.Client bootstrapHelper(RpcSystem&)
|
||||
RpcSystem makeRpcClientWithRestorer(TwoPartyVatNetwork&, PyRestorer&)
|
||||
PyPromise connectServer(TaskSet &, PyRestorer &, AsyncIoContext *, StringPtr)
|
||||
|
||||
|
||||
@@ -73,6 +73,13 @@ capnp::Capability::Client restoreHelper(capnp::RpcSystem<capnp::rpc::twoparty::S
|
||||
return client.restore(hostId, objectId);
|
||||
}
|
||||
|
||||
capnp::Capability::Client bootstrapHelper(capnp::RpcSystem<capnp::rpc::twoparty::SturdyRefHostId>& client) {
|
||||
capnp::MallocMessageBuilder hostIdMessage(8);
|
||||
auto hostId = hostIdMessage.initRoot<capnp::rpc::twoparty::SturdyRefHostId>();
|
||||
hostId.setSide(capnp::rpc::twoparty::Side::SERVER);
|
||||
return client.bootstrap(hostId);
|
||||
}
|
||||
|
||||
template <typename SturdyRefHostId, typename ProvisionId,
|
||||
typename RecipientId, typename ThirdPartyCapId, typename JoinAnswer>
|
||||
capnp::RpcSystem<SturdyRefHostId> makeRpcClientWithRestorer(
|
||||
|
||||
@@ -345,6 +345,7 @@ cdef extern from "capnp/rpc-twoparty.h" namespace " ::capnp":
|
||||
VoidPromise onDisconnect()
|
||||
VoidPromise onDrained()
|
||||
RpcSystem makeRpcServer(TwoPartyVatNetwork&, PyRestorer&)
|
||||
RpcSystem makeRpcServerBootstrap"makeRpcServer"(TwoPartyVatNetwork&, Capability.Client)
|
||||
RpcSystem makeRpcClient(TwoPartyVatNetwork&)
|
||||
|
||||
cdef extern from "capnp/dynamic.h" namespace " ::capnp":
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from capnp.includes cimport capnp_cpp as capnp
|
||||
from capnp.includes cimport schema_cpp
|
||||
from capnp.includes.capnp_cpp cimport Schema as C_Schema, StructSchema as C_StructSchema, InterfaceSchema as C_InterfaceSchema, EnumSchema as C_EnumSchema, ListSchema as C_ListSchema, DynamicStruct as C_DynamicStruct, DynamicValue as C_DynamicValue, Type as C_Type, DynamicList as C_DynamicList, SchemaParser as C_SchemaParser, ParsedSchema as C_ParsedSchema, VOID, ArrayPtr, StringPtr, String, StringTree, DynamicOrphan as C_DynamicOrphan, AnyPointer as C_DynamicObject, DynamicCapability as C_DynamicCapability, Request, Response, RemotePromise, PyPromise, VoidPromise, CallContext, PyRestorer, RpcSystem, makeRpcServer, makeRpcClient, Capability as C_Capability, TwoPartyVatNetwork as C_TwoPartyVatNetwork, Side, AsyncIoStream, Own, makeTwoPartyVatNetwork, PromiseFulfillerPair as C_PromiseFulfillerPair, copyPromiseFulfillerPair, newPromiseAndFulfiller, PyArray, DynamicStruct_Builder
|
||||
from capnp.includes.capnp_cpp cimport Schema as C_Schema, StructSchema as C_StructSchema, InterfaceSchema as C_InterfaceSchema, EnumSchema as C_EnumSchema, ListSchema as C_ListSchema, DynamicStruct as C_DynamicStruct, DynamicValue as C_DynamicValue, Type as C_Type, DynamicList as C_DynamicList, SchemaParser as C_SchemaParser, ParsedSchema as C_ParsedSchema, VOID, ArrayPtr, StringPtr, String, StringTree, DynamicOrphan as C_DynamicOrphan, AnyPointer as C_DynamicObject, DynamicCapability as C_DynamicCapability, Request, Response, RemotePromise, PyPromise, VoidPromise, CallContext, PyRestorer, RpcSystem, makeRpcServer, makeRpcServerBootstrap, makeRpcClient, Capability as C_Capability, TwoPartyVatNetwork as C_TwoPartyVatNetwork, Side, AsyncIoStream, Own, makeTwoPartyVatNetwork, PromiseFulfillerPair as C_PromiseFulfillerPair, copyPromiseFulfillerPair, newPromiseAndFulfiller, PyArray, DynamicStruct_Builder
|
||||
from capnp.includes.schema_cpp cimport Node as C_Node, EnumNode as C_EnumNode
|
||||
from capnp.includes.types cimport *
|
||||
from capnp.helpers.non_circular cimport reraise_kj_exception
|
||||
|
||||
@@ -2253,6 +2253,9 @@ cdef class TwoPartyClient:
|
||||
|
||||
return self.restore(ref)
|
||||
|
||||
cpdef bootstrap(self) except +reraise_kj_exception:
|
||||
return _CapabilityClient()._init(helpers.bootstrapHelper(deref(self.thisptr)), self)
|
||||
|
||||
cpdef on_disconnect(self) except +reraise_kj_exception:
|
||||
return _VoidPromise()._init(deref(self._network.thisptr).onDisconnect())
|
||||
|
||||
@@ -2263,12 +2266,18 @@ cdef class TwoPartyServer:
|
||||
cdef public _Restorer _restorer
|
||||
cdef public _AsyncIoStream _stream
|
||||
cdef object _port
|
||||
cdef public object port_promise
|
||||
cdef public object port_promise, _bootstrap
|
||||
cdef capnp.TaskSet * _task_set
|
||||
cdef capnp.ErrorHandler _error_handler
|
||||
|
||||
def __init__(self, socket, restorer, server_socket=None):
|
||||
self._restorer = _convert_restorer(restorer)
|
||||
def __init__(self, socket, restorer=None, server_socket=None, bootstrap=None):
|
||||
if not restorer and not bootstrap:
|
||||
raise KjException("You must provide either a bootstrap interface or a restorer (deperecated) to a server constructor.")
|
||||
|
||||
cdef _InterfaceSchema schema
|
||||
self._restorer = None
|
||||
self._bootstrap = None
|
||||
|
||||
if isinstance(socket, basestring):
|
||||
self._connect(socket)
|
||||
else:
|
||||
@@ -2277,11 +2286,19 @@ cdef class TwoPartyServer:
|
||||
self._server_socket = server_socket
|
||||
self._port = 0
|
||||
self._network = _TwoPartyVatNetwork()._init(self._stream, capnp.SERVER)
|
||||
|
||||
if bootstrap:
|
||||
self._bootstrap = bootstrap
|
||||
schema = bootstrap.schema
|
||||
self.thisptr = new RpcSystem(makeRpcServerBootstrap(deref(self._network.thisptr), helpers.server_to_client(schema.thisptr, <PyObject *>bootstrap)))
|
||||
elif restorer:
|
||||
self._restorer = _convert_restorer(restorer)
|
||||
self.thisptr = new RpcSystem(makeRpcServer(deref(self._network.thisptr), deref(self._restorer.thisptr)))
|
||||
|
||||
Py_INCREF(self._orig_stream)
|
||||
Py_INCREF(self._stream)
|
||||
Py_INCREF(self._restorer)
|
||||
Py_INCREF(self._bootstrap)
|
||||
Py_INCREF(self._network)
|
||||
self._disconnect_promise = self.on_disconnect().then(self._decref)
|
||||
|
||||
@@ -2292,6 +2309,7 @@ cdef class TwoPartyServer:
|
||||
self.port_promise = Promise()._init(helpers.connectServer(deref(self._task_set), deref(self._restorer.thisptr), loop.thisptr, temp_string))
|
||||
|
||||
def _decref(self):
|
||||
Py_DECREF(self._bootstrap)
|
||||
Py_DECREF(self._restorer)
|
||||
Py_DECREF(self._orig_stream)
|
||||
Py_DECREF(self._stream)
|
||||
@@ -2318,8 +2336,6 @@ cdef class TwoPartyServer:
|
||||
else:
|
||||
return self._port
|
||||
|
||||
# TODO: add restore functionality here?
|
||||
|
||||
cdef class _AsyncIoStream:
|
||||
cdef Own[AsyncIoStream] thisptr
|
||||
|
||||
|
||||
@@ -86,3 +86,17 @@ def test_ez_rpc():
|
||||
|
||||
with pytest.raises(capnp.KjException):
|
||||
response = remote.wait()
|
||||
|
||||
def test_simple_rpc_bootstrap():
|
||||
read, write = socket.socketpair(socket.AF_UNIX)
|
||||
|
||||
server = capnp.TwoPartyServer(write, bootstrap=Server(100))
|
||||
client = capnp.TwoPartyClient(read)
|
||||
|
||||
cap = client.bootstrap()
|
||||
cap = cap.cast_as(test_capability_capnp.TestInterface)
|
||||
|
||||
remote = cap.foo(i=5)
|
||||
response = remote.wait()
|
||||
|
||||
assert response.x == '125'
|
||||
|
||||
Reference in New Issue
Block a user