agent-enviroments/builder/libs/seastar/demos/tls_simple_client_demo.cc
2024-09-10 17:06:08 +03:00

134 lines
5.8 KiB
C++

/*
* 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 <cmath>
#include <seastar/core/shared_ptr.hh>
#include <seastar/core/reactor.hh>
#include <seastar/core/app-template.hh>
#include <seastar/core/sleep.hh>
#include <seastar/core/loop.hh>
#include <seastar/net/dns.hh>
#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<uint16_t>()->default_value(10000), "Remote port")
("address", bpo::value<std::string>()->default_value("127.0.0.1"), "Remote address")
("trust,t", bpo::value<std::string>(), "Trust store")
("msg,m", bpo::value<std::string>(), "Message to send")
("bytes,b", bpo::value<size_t>()->default_value(512), "Use random bytes of length as message")
("iterations,i", bpo::value<size_t>()->default_value(1), "Repeat X times")
("read-response,r", bpo::value<bool>()->default_value(true)->implicit_value(true), "Read echoed message")
("verbose,v", bpo::value<bool>()->default_value(false)->implicit_value(true), "Verbose operation")
("check-name,c", bpo::value<bool>()->default_value(false)->implicit_value(true), "Check server name")
("server-name,s", bpo::value<std::string>(), "Expected server name")
;
return app.run_deprecated(ac, av, [&] {
auto&& config = app.configuration();
uint16_t port = config["port"].as<uint16_t>();
auto addr = config["address"].as<std::string>();
auto n = config["bytes"].as<size_t>();
auto i = config["iterations"].as<size_t>();
auto do_read = config["read-response"].as<bool>();
auto verbose = config["verbose"].as<bool>();
auto check = config["check-name"].as<bool>();
std::cout << "Starting..." << std::endl;
auto certs = ::make_shared<tls::certificate_credentials>();
auto f = make_ready_future();
if (config.count("trust")) {
f = certs->set_x509_trust_file(config["trust"].as<std::string>(), tls::x509_crt_format::PEM);
}
seastar::shared_ptr<sstring> msg;
if (config.count("msg")) {
msg = seastar::make_shared<sstring>(config["msg"].as<std::string>());
} else {
msg = seastar::make_shared<sstring>(uninitialized_string(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<std::string>();
}
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);
tls::tls_options options;
if (check) {
options.server_name = server_name.empty() ? e.names.front() : server_name;
}
return tls::connect(certs, ia, options).then([=](::connected_socket s) {
auto strms = ::make_lw_shared<streams>(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<char> 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);
});
});
}