/* * This file is open source software, licensed to you under the terms * of the Apache License, Version 2.0 (the "License"). See the NOTICE file * distributed with this work for additional information regarding copyright * ownership. You may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /* * Copyright 2015 Cloudius Systems */ #include #include "core/reactor.hh" #include "core/app-template.hh" #include "rpc/rpc.hh" struct serializer { template inline auto operator()(output_stream& out, T&& v, std::enable_if_t>::value, void*> = nullptr) { return out.write(reinterpret_cast(&v), sizeof(T)); } template inline auto operator()(output_stream& out, T&& v, std::enable_if_t>::value, void*> = nullptr) { return v.serialize(out); } inline auto operator()(output_stream& out, sstring& v) { auto l = std::make_unique(v.size()); auto f = operator()(out, *l); return f.then([v = std::forward(v), &out, l = std::move(l)] { return out.write(v.c_str(), v.size()); }); } template inline auto operator()(input_stream& in, T& v, std::enable_if_t::value, void*> = nullptr) { return in.read_exactly(sizeof(v)).then([&v] (temporary_buffer buf) mutable { if (buf.size() == 0) { throw rpc::closed_error(); } v = *reinterpret_cast(buf.get()); }); } template inline auto operator()(input_stream& in, T& v, std::enable_if_t::value, void*> = nullptr) { return v.deserialize(in); } inline auto operator()(input_stream& in, sstring& v) { return in.read_exactly(sizeof(size_t)).then([] (temporary_buffer buf) { if (buf.size() == 0) { throw rpc::closed_error(); } return make_ready_future(*reinterpret_cast(buf.get())); }).then([&in] (size_t l) { return in.read_exactly(l); }).then([&v] (temporary_buffer buf) mutable { if (buf.size() == 0) { throw rpc::closed_error(); } v = sstring(buf.get(), buf.size()); }); } }; namespace bpo = boost::program_options; int main(int ac, char** av) { app_template app; app.add_options() ("port", bpo::value()->default_value(10000), "RPC server port") ("server", bpo::value(), "Server address"); std::cout << "start "; rpc::protocol myrpc(serializer{}); static std::unique_ptr::server> server; static std::unique_ptr::client> client; static double x = 30.0; return app.run(ac, av, [&] { auto&& config = app.configuration(); uint16_t port = config["port"].as(); auto test1 = myrpc.register_handler(1, [x = 0](int i) mutable { print("test1 count %d got %d\n", ++x, i); }); auto test2 = myrpc.register_handler(2, [](int a, int b){ print("test2 got %d %d\n", a, b); return make_ready_future(a+b); }); auto test3 = myrpc.register_handler(3, [](double x){ print("test3 got %f\n", x); return std::make_unique(sin(x)); }); auto test4 = myrpc.register_handler(4, [](){ print("test4 throw!\n"); throw std::runtime_error("exception!"); }); auto test5 = myrpc.register_handler(5, [](){ print("test5 no wait\n"); return rpc::no_wait; }); auto test6 = myrpc.register_handler(6, [](const rpc::client_info& info, int x){ print("test6 client %s, %d\n", inet_ntoa(info.addr.as_posix_sockaddr_in().sin_addr), x); }); if (config.count("server")) { std::cout << "client" << std::endl; auto test7 = myrpc.make_client(7); client = std::make_unique::client>(myrpc, ipv4_addr{config["server"].as()}); auto f = make_ready_future<>(); for (auto i = 0; i < 100; i++) { print("iteration=%d\n", i); test1(*client, 5).then([] (){ print("test1 ended\n");}); test2(*client, 1, 2).then([] (int r) { print("test2 got %d\n", r); }); test3(*client, x).then([](double x) { print("sin=%f\n", x); }); test4(*client).then_wrapped([](future<> f) { try { f.get(); printf("test4 your should not see this!"); } catch (std::runtime_error& x){ print("test4 %s\n", x.what()); } }); test5(*client).then([] { print("test5 no wait ended\n"); }); test6(*client, 1).then([] { print("test6 ended\n"); }); f = test7(*client, 5, 6).then([] (long r) { print("test7 got %ld\n", r); }); } f.finally([] { engine().exit(0); }); } else { std::cout << "server on port " << port << std::endl; myrpc.register_handler(7, [](long a, long b) mutable { auto p = make_lw_shared>(); auto t = make_lw_shared>(); print("test7 got %ld %ld\n", a, b); auto f = p->get_future().then([a, b, t] { print("test7 calc res\n"); return a - b; }); t->set_callback([p = std::move(p)] () mutable { p->set_value(); }); using namespace std::chrono_literals; t->arm(1s); return f; }); server = std::make_unique::server>(myrpc, ipv4_addr{port}); } }); }