diff --git a/source/authentication/udaClientSSL.cpp b/source/authentication/udaClientSSL.cpp index 880d33b5..7bbf1de5 100755 --- a/source/authentication/udaClientSSL.cpp +++ b/source/authentication/udaClientSSL.cpp @@ -40,7 +40,7 @@ void putUdaClientSSLSocket(int s) g_sslSocket = s; } -void initUdaClientSSL() +static void init_ssl_library() { if (g_sslInit) { return; // Already initialised @@ -323,7 +323,7 @@ int configureUdaClientSSLContext(const HostData* host) return 0; } -int startUdaClientSSL() +int initUdaClientSSL() { // Has SSL/TLS authentication already been passed? if (g_sslOK) { @@ -356,16 +356,21 @@ int startUdaClientSSL() // Initialise - initUdaClientSSL(); + init_ssl_library(); if (!(g_ctx = createUdaClientSSLContext())) { UDA_THROW_ERROR(999, "Unable to create the SSL context!"); } - if (g_host == nullptr || configureUdaClientSSLContext(g_host) != 0) { + if (configureUdaClientSSLContext(g_host) != 0) { UDA_THROW_ERROR(999, "Unable to configure the SSL context!"); } + return 0; +} + +int startUdaClientSSL() +{ // Bind an SSL object with the socket g_ssl = SSL_new(g_ctx); diff --git a/source/authentication/udaClientSSL.h b/source/authentication/udaClientSSL.h index cc582ab4..52a88d6f 100755 --- a/source/authentication/udaClientSSL.h +++ b/source/authentication/udaClientSSL.h @@ -30,6 +30,7 @@ SSL *getUdaClientSSL(); void putUdaClientSSLSocket(int s); void closeUdaClientSSL(); void putUdaClientSSLProtocol(int specified); +int initUdaClientSSL(); int startUdaClientSSL(); int readUdaClientSSL(void* iohandle, char* buf, int count); int writeUdaClientSSL(void* iohandle, char* buf, int count); diff --git a/source/bin/uda_cli.cpp b/source/bin/uda_cli.cpp index 6705df3b..527dc621 100644 --- a/source/bin/uda_cli.cpp +++ b/source/bin/uda_cli.cpp @@ -374,24 +374,40 @@ void print_data(const uda::Data* data, int uda_type) } } +void conflicting_options(const boost::program_options::variables_map & vm, + const std::string & opt1, const std::string & opt2) +{ + if (vm.count(opt1) && !vm[opt1].defaulted() && vm.count(opt2) && !vm[opt2].defaulted()) + { + throw po::error(std::string("conflicting options '") + opt1 + "' and '" + opt2 + "'"); + } +} + int main(int argc, const char** argv) { po::options_description desc("Allowed options"); desc.add_options() - ("help", "produce help message") + ("help", po::bool_switch(), "produce help message") ("host,h", po::value()->default_value("localhost"), "server host name") ("port,p", po::value()->default_value(56565), "server port") - ("request", po::value()->required(), "request"); + ("request", po::value(), "request") + ("source", po::value()->default_value(""), "source") + ("ping", po::bool_switch(), "ping the server"); po::positional_options_description p; p.add("request", 1); po::variables_map vm; - po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm); try { + po::store(po::command_line_parser(argc, argv).options(desc).positional(p).run(), vm); po::notify(vm); + + conflicting_options(vm, "ping", "request"); + if (!vm["ping"].as() && vm.count("request") == 0) { + throw po::error("either 'ping' or 'request' must be provided"); + } } catch (po::error& err) { - if (vm.count("help")) { + if (vm["help"].as()) { std::cout << "Usage: " << argv[0] << " [options] request\n"; std::cout << desc << "\n"; return 1; @@ -403,7 +419,7 @@ int main(int argc, const char** argv) } }; - if (vm.count("help")) { + if (vm["help"].as()) { std::cout << "Usage: " << argv[0] << " [options] request\n"; std::cout << desc << "\n"; return 1; @@ -417,7 +433,12 @@ int main(int argc, const char** argv) uda::Client::setServerPort(static_cast(vm["port"].as())); } - std::string request = vm["request"].as(); + std::string request; + if (vm["ping"].as()) { + request = "HELP::ping()"; + } else { + request = vm["request"].as(); + } if (request == "-") { std::stringstream ss; @@ -429,9 +450,11 @@ int main(int argc, const char** argv) } std::cout << "request: " << request << "\n"; + std::string source = vm["source"].as(); + uda::Client client; try { - auto& res = client.get(request, ""); + auto& res = client.get(request, source); if (res.isTree()) { print_tree(res.tree(), ""); @@ -445,6 +468,8 @@ int main(int argc, const char** argv) print_data(res.data(), res.uda_type()); } + client.close(); + } catch (uda::UDAException& err) { std::cerr << "UDA error: " << err.what() << "\n"; return -1; diff --git a/source/client/udaClient.cpp b/source/client/udaClient.cpp index 4ce8d76a..370ce708 100755 --- a/source/client/udaClient.cpp +++ b/source/client/udaClient.cpp @@ -51,8 +51,8 @@ USERDEFINEDTYPELIST* g_user_defined_type_list = nullptr; // List of a LOGMALLOCLIST* g_log_malloc_list = nullptr; // List of all Heap Allocations for Data unsigned int g_last_malloc_index = 0; // Malloc Log search index last value unsigned int* g_last_malloc_index_value = &g_last_malloc_index;; // Preserve Malloc Log search index last value in GENERAL_STRUCT -XDR* g_client_input = nullptr; -XDR* g_client_output = nullptr; +XDR** g_client_input = nullptr; +XDR** g_client_output = nullptr; LOGSTRUCTLIST* g_log_struct_list = nullptr; #endif // FATCLIENT @@ -366,8 +366,8 @@ int idamClient(REQUEST_BLOCK* request_block, int* indices) static int malloc_source = UDA_MALLOC_SOURCE_NONE; #ifndef FATCLIENT - g_client_input = client_input; // needed for udaFreeAll - g_client_output = client_output; // needed for udaFreeAll + g_client_input = &client_input; // needed for udaFreeAll + g_client_output = &client_output; // needed for udaFreeAll #endif LOGSTRUCTLIST log_struct_list; @@ -517,6 +517,16 @@ int idamClient(REQUEST_BLOCK* request_block, int* indices) # endif time(&tv_server_start); // Start the Clock again: Age of Server + //------------------------------------------------------------------------- + // Connect to the server with SSL (X509) authentication + +# if defined(SSLAUTHENTICATION) && !defined(FATCLIENT) + // Create the SSL binding and context, and verify the server certificate + if ((err = initUdaClientSSL()) != 0) { + break; + } +# endif + //------------------------------------------------------------------------- // Create the XDR Record Streams std::tie(client_input, client_output) = clientCreateXDRStream(); @@ -1444,9 +1454,9 @@ void udaFreeAll() client_block.timeout = 0; // Surrogate CLOSEDOWN instruction client_block.clientFlags = client_block.clientFlags | CLIENTFLAG_CLOSEDOWN; // Direct CLOSEDOWN instruction protocol_id = UDA_PROTOCOL_CLIENT_BLOCK; - protocol2(g_client_output, protocol_id, XDR_SEND, nullptr, g_log_malloc_list, g_user_defined_type_list, &client_block, + protocol2(*g_client_output, protocol_id, XDR_SEND, nullptr, g_log_malloc_list, g_user_defined_type_list, &client_block, protocol_version, g_log_struct_list, *udaPrivateFlags(), UDA_MALLOC_SOURCE_NONE); - xdrrec_endofrecord(g_client_output, 1); + xdrrec_endofrecord(*g_client_output, 1); } #endif // <========================== End of Client Server Code Only @@ -1455,7 +1465,7 @@ void udaFreeAll() #ifndef FATCLIENT // Close the Socket, XDR Streams and All Files - closedown(ClosedownType::CLOSE_ALL, nullptr, g_client_input, g_client_output, &reopen_logs); + closedown(ClosedownType::CLOSE_ALL, nullptr, *g_client_input, *g_client_output, &reopen_logs); #else closedown(ClosedownType::CLOSE_ALL, nullptr, nullptr, nullptr, &reopen_logs); #endif diff --git a/source/wrappers/c++/client.cpp b/source/wrappers/c++/client.cpp index a21ea557..95fba912 100755 --- a/source/wrappers/c++/client.cpp +++ b/source/wrappers/c++/client.cpp @@ -86,6 +86,11 @@ void uda::Client::setProperty(Property prop, int value) } } +void uda::Client::close() +{ + udaFreeAll(); +} + int uda::Client::property(Property prop) { auto client_flags = udaClientFlags(); diff --git a/source/wrappers/c++/client.hpp b/source/wrappers/c++/client.hpp index dad4fff3..9a036d8c 100755 --- a/source/wrappers/c++/client.hpp +++ b/source/wrappers/c++/client.hpp @@ -181,6 +181,8 @@ class LIBRARY_API Client { void put(const std::string& instruction, const uda::Array& data); + void close(); + private: friend class ResultList;