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