diff --git a/capnp/lib/capnp.pyx b/capnp/lib/capnp.pyx index 84f357c..709cfe3 100644 --- a/capnp/lib/capnp.pyx +++ b/capnp/lib/capnp.pyx @@ -1814,13 +1814,16 @@ cdef class TwoPartyServer: try: self.on_disconnect().wait() (clientsocket, address) = self._server_socket.accept() + self._orig_stream = clientsocket self._stream = _FdAsyncIoStream(clientsocket.fileno()) self._network = _TwoPartyVatNetwork()._init(deref(self._stream.thisptr), capnp.SERVER) 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._network) # TODO:MEMORY: attach this to onDrained, also figure out what's leaking except KeyboardInterrupt: break - # TODO: add restore functionality here? cdef class _FdAsyncIoStream: diff --git a/docs/index.rst b/docs/index.rst index 10c1dec..80ecfdf 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,6 +1,6 @@ .. capnp documentation master file -Welcome to capnp's documentation! +Welcome to pycapnp's documentation! ================================= This is a python wrapping of the C++ implementation of the `Cap'n Proto `_ library. Here is a short description, quoted from its docs: diff --git a/docs/install.rst b/docs/install.rst index c4720d5..0a93527 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -28,7 +28,7 @@ On some systems you will have to install Python's headers before doing any of th sudo apt-get install python-dev -You can control what compiler is used with the environment variable CC, ie. `CC=gcc-4.8 pip install pycapnp`. You only need to run the setuptools line if you have a setuptools older than v0.8.0, and the cython line if you have a version older than v0.19.1. +You can control what compiler is used with the environment variable CC, ie. `CC=gcc-4.8 pip install pycapnp`, and flags with CCFLAGS. You only need to run the setuptools line if you have a setuptools older than v0.8.0, and the cython line if you have a version older than v0.19.1. From Source --------------------- @@ -43,8 +43,6 @@ or:: cd pycapnp python setup.py install -If you don't use pip, you will need to manually install Cython, and a setuptools with a version >= .8. - Development ------------------- diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 7cd9f8a..76c6e9d 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -303,29 +303,21 @@ The examples below will be using `calculator.capnp `_ if you don't know what this means:: + calculator = client.ez_restore('calculator').cast_as(calculator_capnp.Calculator) There's two things worth noting here. First, we used the simpler `ez_restore` function. For servers that use a struct type as their Restorer, you will have to do the following instead:: @@ -383,35 +375,18 @@ You can also chain promises with `then` and the same pipelining will occur:: Server ~~~~~~~~~~~~~~ -Making a socket -################# - -Again, any socket-like object will work, but here's how to do it with the :py:mod:`socket` module:: - - host = '' # this will bind to all interfaces - port = 60000 - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - - # Optionally set TCP_NODELAY on socket to disable Nagle's algorithm - s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - - s.bind((host, port)) - s.listen(1) # service only 1 client at a time - -Then, you will have to accept connections one at a time:: - - (sock, address) = s.accept() - Starting a Server ################## Once you have a socket, it's quite simple to start a server:: - server = capnp.TwoPartyServer(sock, restore) + server = capnp.TwoPartyServer('*:60000', restore) server.run_forever() -See the `Restore`_ section +See the `Restore`_ section for an explanation of what the `restore` object needs to looks like. + +.. note:: You can also pass a socket with a `fileno()` method to TwoPartyServer. In that case, `run_forever` will not work, and you will have to use `on_disconnect.wait()`. Implementing a Server ####################### diff --git a/examples/calculator_client.py b/examples/calculator_client.py index bc8adca..b1e04e1 100755 --- a/examples/calculator_client.py +++ b/examples/calculator_client.py @@ -32,8 +32,8 @@ at the given address and does some RPCs') return parser.parse_args() -def main(sock): - client = capnp.TwoPartyClient(sock) +def main(host): + client = capnp.TwoPartyClient(host) # Pass "calculator" to ez_restore (there's also a `restore` function that # takes a struct or AnyPointer as an argument), and then cast the returned @@ -282,11 +282,4 @@ def main(sock): print("PASS") if __name__ == '__main__': - host, port = parse_args().host.split(':') - - sock = socket.create_connection((host, port)) - - # Set TCP_NODELAY on socket to disable Nagle's algorithm. This is not - # neccessary, but it speeds things up. - sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - main(sock) + main(parse_args().host) diff --git a/examples/calculator_server.py b/examples/calculator_server.py index 248e701..ffd9867 100755 --- a/examples/calculator_server.py +++ b/examples/calculator_server.py @@ -138,35 +138,8 @@ def restore(ref): def main(): address = parse_args().address - if ':' in address: - address, port = address.split(':') - port = int(port) - else: - port = random.randint(60000, 61000) - - if address == '*': - address = '' - - print("Listening on port: {}".format(port)) - - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - - # Set TCP_NODELAY on socket to disable Nagle's algorithm. This is not - # neccessary, but it speeds things up. - s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - - s.bind((address, port)) - s.listen(1) # service only 1 client at a time - - while True: - try: - (clientsocket, address) = s.accept() - server = capnp.TwoPartyServer(clientsocket, restore) - - server.run_forever() - print("client disconnected") - except KeyboardInterrupt: - break + server = capnp.TwoPartyServer(address, restore) + server.run_forever() if __name__ == '__main__': main()