/* * 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 #include #include #include #include #include "tls_echo_server.hh" using namespace seastar; namespace bpo = boost::program_options; int main(int ac, char** av) { app_template app; app.add_options() ("port", bpo::value()->default_value(10000), "Remote port") ("address", bpo::value()->default_value("127.0.0.1"), "Remote address") ("trust,t", bpo::value(), "Trust store") ("msg,m", bpo::value(), "Message to send") ("bytes,b", bpo::value()->default_value(512), "Use random bytes of length as message") ("iterations,i", bpo::value()->default_value(1), "Repeat X times") ("read-response,r", bpo::value()->default_value(true)->implicit_value(true), "Read echoed message") ("verbose,v", bpo::value()->default_value(false)->implicit_value(true), "Verbose operation") ("check-name,c", bpo::value()->default_value(false)->implicit_value(true), "Check server name") ("server-name,s", bpo::value(), "Expected server name") ; return app.run_deprecated(ac, av, [&] { auto&& config = app.configuration(); uint16_t port = config["port"].as(); auto addr = config["address"].as(); auto n = config["bytes"].as(); auto i = config["iterations"].as(); auto do_read = config["read-response"].as(); auto verbose = config["verbose"].as(); auto check = config["check-name"].as(); std::cout << "Starting..." << std::endl; auto certs = ::make_shared(); auto f = make_ready_future(); if (config.count("trust")) { f = certs->set_x509_trust_file(config["trust"].as(), tls::x509_crt_format::PEM); } seastar::shared_ptr msg; if (config.count("msg")) { msg = seastar::make_shared(config["msg"].as()); } else { msg = seastar::make_shared(sstring(sstring::initialized_later(), n)); for (size_t i = 0; i < n; ++i) { (*msg)[i] = '0' + char(::rand() % 30); } } sstring server_name; if (config.count("server-name")) { server_name = config["server-name"].as(); } if (verbose) { std::cout << "Msg (" << msg->size() << "B):" << std::endl << *msg << std::endl; } return f.then([=]() { return net::dns::get_host_by_name(addr).then([=](net::hostent e) { ipv4_addr ia(e.addr_list.front(), port); sstring name; if (check) { name = server_name.empty() ? e.names.front() : server_name; } return tls::connect(certs, ia, name).then([=](::connected_socket s) { auto strms = ::make_lw_shared(std::move(s)); auto range = boost::irange(size_t(0), i); return do_for_each(range, [=](auto) { auto f = strms->out.write(*msg); if (!do_read) { return strms->out.close().then([f = std::move(f)]() mutable { return std::move(f); }); } return f.then([=]() { return strms->out.flush().then([=] { return strms->in.read_exactly(msg->size()).then([=](temporary_buffer buf) { sstring tmp(buf.begin(), buf.end()); if (tmp != *msg) { std::cerr << "Got garbled message!" << std::endl; if (verbose) { std::cout << "Got (" << tmp.size() << ") :" << std::endl << tmp << std::endl; } throw std::runtime_error("Got garbled message!"); } }); }); }); }).then([strms, do_read]{ return do_read ? strms->out.close() : make_ready_future<>(); }).finally([strms]{ return strms->in.close(); }); }); }).handle_exception([](auto ep) { std::cerr << "Error: " << ep << std::endl; }); }).finally([] { engine().exit(0); }); }); }