annotate osx/include/capnp/ez-rpc.h @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents 0994c39f1e94
children
rev   line source
cannam@62 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
cannam@62 2 // Licensed under the MIT License:
cannam@62 3 //
cannam@62 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
cannam@62 5 // of this software and associated documentation files (the "Software"), to deal
cannam@62 6 // in the Software without restriction, including without limitation the rights
cannam@62 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
cannam@62 8 // copies of the Software, and to permit persons to whom the Software is
cannam@62 9 // furnished to do so, subject to the following conditions:
cannam@62 10 //
cannam@62 11 // The above copyright notice and this permission notice shall be included in
cannam@62 12 // all copies or substantial portions of the Software.
cannam@62 13 //
cannam@62 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
cannam@62 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
cannam@62 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
cannam@62 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
cannam@62 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
cannam@62 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
cannam@62 20 // THE SOFTWARE.
cannam@62 21
cannam@62 22 #ifndef CAPNP_EZ_RPC_H_
cannam@62 23 #define CAPNP_EZ_RPC_H_
cannam@62 24
cannam@62 25 #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
cannam@62 26 #pragma GCC system_header
cannam@62 27 #endif
cannam@62 28
cannam@62 29 #include "rpc.h"
cannam@62 30 #include "message.h"
cannam@62 31
cannam@62 32 struct sockaddr;
cannam@62 33
cannam@62 34 namespace kj { class AsyncIoProvider; class LowLevelAsyncIoProvider; }
cannam@62 35
cannam@62 36 namespace capnp {
cannam@62 37
cannam@62 38 class EzRpcContext;
cannam@62 39
cannam@62 40 class EzRpcClient {
cannam@62 41 // Super-simple interface for setting up a Cap'n Proto RPC client. Example:
cannam@62 42 //
cannam@62 43 // # Cap'n Proto schema
cannam@62 44 // interface Adder {
cannam@62 45 // add @0 (left :Int32, right :Int32) -> (value :Int32);
cannam@62 46 // }
cannam@62 47 //
cannam@62 48 // // C++ client
cannam@62 49 // int main() {
cannam@62 50 // capnp::EzRpcClient client("localhost:3456");
cannam@62 51 // Adder::Client adder = client.getMain<Adder>();
cannam@62 52 // auto request = adder.addRequest();
cannam@62 53 // request.setLeft(12);
cannam@62 54 // request.setRight(34);
cannam@62 55 // auto response = request.send().wait(client.getWaitScope());
cannam@62 56 // assert(response.getValue() == 46);
cannam@62 57 // return 0;
cannam@62 58 // }
cannam@62 59 //
cannam@62 60 // // C++ server
cannam@62 61 // class AdderImpl final: public Adder::Server {
cannam@62 62 // public:
cannam@62 63 // kj::Promise<void> add(AddContext context) override {
cannam@62 64 // auto params = context.getParams();
cannam@62 65 // context.getResults().setValue(params.getLeft() + params.getRight());
cannam@62 66 // return kj::READY_NOW;
cannam@62 67 // }
cannam@62 68 // };
cannam@62 69 //
cannam@62 70 // int main() {
cannam@62 71 // capnp::EzRpcServer server(kj::heap<AdderImpl>(), "*:3456");
cannam@62 72 // kj::NEVER_DONE.wait(server.getWaitScope());
cannam@62 73 // }
cannam@62 74 //
cannam@62 75 // This interface is easy, but it hides a lot of useful features available from the lower-level
cannam@62 76 // classes:
cannam@62 77 // - The server can only export a small set of public, singleton capabilities under well-known
cannam@62 78 // string names. This is fine for transient services where no state needs to be kept between
cannam@62 79 // connections, but hides the power of Cap'n Proto when it comes to long-lived resources.
cannam@62 80 // - EzRpcClient/EzRpcServer automatically set up a `kj::EventLoop` and make it current for the
cannam@62 81 // thread. Only one `kj::EventLoop` can exist per thread, so you cannot use these interfaces
cannam@62 82 // if you wish to set up your own event loop. (However, you can safely create multiple
cannam@62 83 // EzRpcClient / EzRpcServer objects in a single thread; they will make sure to make no more
cannam@62 84 // than one EventLoop.)
cannam@62 85 // - These classes only support simple two-party connections, not multilateral VatNetworks.
cannam@62 86 // - These classes only support communication over a raw, unencrypted socket. If you want to
cannam@62 87 // build on an abstract stream (perhaps one which supports encryption), you must use the
cannam@62 88 // lower-level interfaces.
cannam@62 89 //
cannam@62 90 // Some of these restrictions will probably be lifted in future versions, but some things will
cannam@62 91 // always require using the low-level interfaces directly. If you are interested in working
cannam@62 92 // at a lower level, start by looking at these interfaces:
cannam@62 93 // - `kj::setupAsyncIo()` in `kj/async-io.h`.
cannam@62 94 // - `RpcSystem` in `capnp/rpc.h`.
cannam@62 95 // - `TwoPartyVatNetwork` in `capnp/rpc-twoparty.h`.
cannam@62 96
cannam@62 97 public:
cannam@62 98 explicit EzRpcClient(kj::StringPtr serverAddress, uint defaultPort = 0,
cannam@62 99 ReaderOptions readerOpts = ReaderOptions());
cannam@62 100 // Construct a new EzRpcClient and connect to the given address. The connection is formed in
cannam@62 101 // the background -- if it fails, calls to capabilities returned by importCap() will fail with an
cannam@62 102 // appropriate exception.
cannam@62 103 //
cannam@62 104 // `defaultPort` is the IP port number to use if `serverAddress` does not include it explicitly.
cannam@62 105 // If unspecified, the port is required in `serverAddress`.
cannam@62 106 //
cannam@62 107 // The address is parsed by `kj::Network` in `kj/async-io.h`. See that interface for more info
cannam@62 108 // on the address format, but basically it's what you'd expect.
cannam@62 109 //
cannam@62 110 // `readerOpts` is the ReaderOptions structure used to read each incoming message on the
cannam@62 111 // connection. Setting this may be necessary if you need to receive very large individual
cannam@62 112 // messages or messages. However, it is recommended that you instead think about how to change
cannam@62 113 // your protocol to send large data blobs in multiple small chunks -- this is much better for
cannam@62 114 // both security and performance. See `ReaderOptions` in `message.h` for more details.
cannam@62 115
cannam@62 116 EzRpcClient(const struct sockaddr* serverAddress, uint addrSize,
cannam@62 117 ReaderOptions readerOpts = ReaderOptions());
cannam@62 118 // Like the above constructor, but connects to an already-resolved socket address. Any address
cannam@62 119 // format supported by `kj::Network` in `kj/async-io.h` is accepted.
cannam@62 120
cannam@62 121 explicit EzRpcClient(int socketFd, ReaderOptions readerOpts = ReaderOptions());
cannam@62 122 // Create a client on top of an already-connected socket.
cannam@62 123 // `readerOpts` acts as in the first constructor.
cannam@62 124
cannam@62 125 ~EzRpcClient() noexcept(false);
cannam@62 126
cannam@62 127 template <typename Type>
cannam@62 128 typename Type::Client getMain();
cannam@62 129 Capability::Client getMain();
cannam@62 130 // Get the server's main (aka "bootstrap") interface.
cannam@62 131
cannam@62 132 template <typename Type>
cannam@62 133 typename Type::Client importCap(kj::StringPtr name)
cannam@62 134 KJ_DEPRECATED("Change your server to export a main interface, then use getMain() instead.");
cannam@62 135 Capability::Client importCap(kj::StringPtr name)
cannam@62 136 KJ_DEPRECATED("Change your server to export a main interface, then use getMain() instead.");
cannam@62 137 // ** DEPRECATED **
cannam@62 138 //
cannam@62 139 // Ask the sever for the capability with the given name. You may specify a type to automatically
cannam@62 140 // down-cast to that type. It is up to you to specify the correct expected type.
cannam@62 141 //
cannam@62 142 // Named interfaces are deprecated. The new preferred usage pattern is for the server to export
cannam@62 143 // a "main" interface which itself has methods for getting any other interfaces.
cannam@62 144
cannam@62 145 kj::WaitScope& getWaitScope();
cannam@62 146 // Get the `WaitScope` for the client's `EventLoop`, which allows you to synchronously wait on
cannam@62 147 // promises.
cannam@62 148
cannam@62 149 kj::AsyncIoProvider& getIoProvider();
cannam@62 150 // Get the underlying AsyncIoProvider set up by the RPC system. This is useful if you want
cannam@62 151 // to do some non-RPC I/O in asynchronous fashion.
cannam@62 152
cannam@62 153 kj::LowLevelAsyncIoProvider& getLowLevelIoProvider();
cannam@62 154 // Get the underlying LowLevelAsyncIoProvider set up by the RPC system. This is useful if you
cannam@62 155 // want to do some non-RPC I/O in asynchronous fashion.
cannam@62 156
cannam@62 157 private:
cannam@62 158 struct Impl;
cannam@62 159 kj::Own<Impl> impl;
cannam@62 160 };
cannam@62 161
cannam@62 162 class EzRpcServer {
cannam@62 163 // The server counterpart to `EzRpcClient`. See `EzRpcClient` for an example.
cannam@62 164
cannam@62 165 public:
cannam@62 166 explicit EzRpcServer(Capability::Client mainInterface, kj::StringPtr bindAddress,
cannam@62 167 uint defaultPort = 0, ReaderOptions readerOpts = ReaderOptions());
cannam@62 168 // Construct a new `EzRpcServer` that binds to the given address. An address of "*" means to
cannam@62 169 // bind to all local addresses.
cannam@62 170 //
cannam@62 171 // `defaultPort` is the IP port number to use if `serverAddress` does not include it explicitly.
cannam@62 172 // If unspecified, a port is chosen automatically, and you must call getPort() to find out what
cannam@62 173 // it is.
cannam@62 174 //
cannam@62 175 // The address is parsed by `kj::Network` in `kj/async-io.h`. See that interface for more info
cannam@62 176 // on the address format, but basically it's what you'd expect.
cannam@62 177 //
cannam@62 178 // The server might not begin listening immediately, especially if `bindAddress` needs to be
cannam@62 179 // resolved. If you need to wait until the server is definitely up, wait on the promise returned
cannam@62 180 // by `getPort()`.
cannam@62 181 //
cannam@62 182 // `readerOpts` is the ReaderOptions structure used to read each incoming message on the
cannam@62 183 // connection. Setting this may be necessary if you need to receive very large individual
cannam@62 184 // messages or messages. However, it is recommended that you instead think about how to change
cannam@62 185 // your protocol to send large data blobs in multiple small chunks -- this is much better for
cannam@62 186 // both security and performance. See `ReaderOptions` in `message.h` for more details.
cannam@62 187
cannam@62 188 EzRpcServer(Capability::Client mainInterface, struct sockaddr* bindAddress, uint addrSize,
cannam@62 189 ReaderOptions readerOpts = ReaderOptions());
cannam@62 190 // Like the above constructor, but binds to an already-resolved socket address. Any address
cannam@62 191 // format supported by `kj::Network` in `kj/async-io.h` is accepted.
cannam@62 192
cannam@62 193 EzRpcServer(Capability::Client mainInterface, int socketFd, uint port,
cannam@62 194 ReaderOptions readerOpts = ReaderOptions());
cannam@62 195 // Create a server on top of an already-listening socket (i.e. one on which accept() may be
cannam@62 196 // called). `port` is returned by `getPort()` -- it serves no other purpose.
cannam@62 197 // `readerOpts` acts as in the other two above constructors.
cannam@62 198
cannam@62 199 explicit EzRpcServer(kj::StringPtr bindAddress, uint defaultPort = 0,
cannam@62 200 ReaderOptions readerOpts = ReaderOptions())
cannam@62 201 KJ_DEPRECATED("Please specify a main interface for your server.");
cannam@62 202 EzRpcServer(struct sockaddr* bindAddress, uint addrSize,
cannam@62 203 ReaderOptions readerOpts = ReaderOptions())
cannam@62 204 KJ_DEPRECATED("Please specify a main interface for your server.");
cannam@62 205 EzRpcServer(int socketFd, uint port, ReaderOptions readerOpts = ReaderOptions())
cannam@62 206 KJ_DEPRECATED("Please specify a main interface for your server.");
cannam@62 207
cannam@62 208 ~EzRpcServer() noexcept(false);
cannam@62 209
cannam@62 210 void exportCap(kj::StringPtr name, Capability::Client cap);
cannam@62 211 // Export a capability publicly under the given name, so that clients can import it.
cannam@62 212 //
cannam@62 213 // Keep in mind that you can implicitly convert `kj::Own<MyType::Server>&&` to
cannam@62 214 // `Capability::Client`, so it's typical to pass something like
cannam@62 215 // `kj::heap<MyImplementation>(<constructor params>)` as the second parameter.
cannam@62 216
cannam@62 217 kj::Promise<uint> getPort();
cannam@62 218 // Get the IP port number on which this server is listening. This promise won't resolve until
cannam@62 219 // the server is actually listening. If the address was not an IP address (e.g. it was a Unix
cannam@62 220 // domain socket) then getPort() resolves to zero.
cannam@62 221
cannam@62 222 kj::WaitScope& getWaitScope();
cannam@62 223 // Get the `WaitScope` for the client's `EventLoop`, which allows you to synchronously wait on
cannam@62 224 // promises.
cannam@62 225
cannam@62 226 kj::AsyncIoProvider& getIoProvider();
cannam@62 227 // Get the underlying AsyncIoProvider set up by the RPC system. This is useful if you want
cannam@62 228 // to do some non-RPC I/O in asynchronous fashion.
cannam@62 229
cannam@62 230 kj::LowLevelAsyncIoProvider& getLowLevelIoProvider();
cannam@62 231 // Get the underlying LowLevelAsyncIoProvider set up by the RPC system. This is useful if you
cannam@62 232 // want to do some non-RPC I/O in asynchronous fashion.
cannam@62 233
cannam@62 234 private:
cannam@62 235 struct Impl;
cannam@62 236 kj::Own<Impl> impl;
cannam@62 237 };
cannam@62 238
cannam@62 239 // =======================================================================================
cannam@62 240 // inline implementation details
cannam@62 241
cannam@62 242 template <typename Type>
cannam@62 243 inline typename Type::Client EzRpcClient::getMain() {
cannam@62 244 return getMain().castAs<Type>();
cannam@62 245 }
cannam@62 246
cannam@62 247 template <typename Type>
cannam@62 248 inline typename Type::Client EzRpcClient::importCap(kj::StringPtr name) {
cannam@62 249 return importCap(name).castAs<Type>();
cannam@62 250 }
cannam@62 251
cannam@62 252 } // namespace capnp
cannam@62 253
cannam@62 254 #endif // CAPNP_EZ_RPC_H_