46 if (value == L"true") return true; |
47 if (value == L"true") return true; |
47 else if (value == L"false") return false; |
48 else if (value == L"false") return false; |
48 else throw relpipe::cli::RelpipeCLIException(L"Unable to parse boolean value: " + value + L" (expecting true or false)", relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); |
49 else throw relpipe::cli::RelpipeCLIException(L"Unable to parse boolean value: " + value + L" (expecting true or false)", relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); |
49 } |
50 } |
50 |
51 |
51 void setIfMissing(std::vector<Configuration::SocketOption>& options, const std::string& name, const std::string& value) { |
52 void setIfMissing(std::vector<Configuration::SocketOption>& options, const std::string& name, const std::string& value, bool includeEmptyValues = true) { |
52 auto n = convertor.from_bytes(name); |
53 auto n = convertor.from_bytes(name); |
53 auto v = convertor.from_bytes(value); |
54 auto v = convertor.from_bytes(value); |
54 for (auto o : options) if (o.name == n) return; |
55 for (auto o : options) if (o.name == n) return; |
55 options.push_back({n, v}); |
56 if (value.size() || includeEmptyValues) options.push_back({n, v}); |
56 } |
57 } |
57 |
58 |
58 public: |
59 public: |
59 |
60 |
60 static const relpipe::common::type::StringX OPTION_RELATION; |
61 static const relpipe::common::type::StringX OPTION_RELATION; |
61 static const relpipe::common::type::StringX OPTION_CONNECTION_STRING; |
62 static const relpipe::common::type::StringX OPTION_CONNECTION_STRING; |
62 static const relpipe::common::type::StringX OPTION_CONNECTION_OPTION; |
63 static const relpipe::common::type::StringX OPTION_CONNECTION_OPTION; |
63 |
64 |
64 Configuration parse(const std::vector<relpipe::common::type::StringX>& arguments) { |
65 Configuration parse(const std::vector<relpipe::common::type::StringX>& arguments) { |
65 Configuration c; |
66 Configuration c; |
|
67 relpipe::common::type::StringX connectionString; |
66 |
68 |
67 for (int i = 0; i < arguments.size();) { |
69 for (int i = 0; i < arguments.size();) { |
68 relpipe::common::type::StringX option = readNext(arguments, i); |
70 relpipe::common::type::StringX option = readNext(arguments, i); |
69 |
71 |
70 if (option == OPTION_RELATION) { |
72 if (option == OPTION_RELATION) { |
71 c.relation = readNext(arguments, i); |
73 c.relation = readNext(arguments, i); |
72 } else if (option == OPTION_CONNECTION_STRING) { |
74 } else if (option == OPTION_CONNECTION_STRING) { |
73 auto connectionString = readNext(arguments, i); |
75 connectionString = readNext(arguments, i); |
74 // FIXME: parse connection string and convert it to options |
|
75 } else if (option == OPTION_CONNECTION_OPTION) { |
76 } else if (option == OPTION_CONNECTION_OPTION) { |
76 auto name = readNext(arguments, i); |
77 auto name = readNext(arguments, i); |
77 auto value = readNext(arguments, i); |
78 auto value = readNext(arguments, i); |
78 c.options.push_back({name, value}); |
79 c.options.push_back({name, value}); |
79 } else throw relpipe::cli::RelpipeCLIException(L"Unsupported CLI option: " + option, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); |
80 } else throw relpipe::cli::RelpipeCLIException(L"Unsupported CLI option: " + option, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); |
80 } |
81 } |
81 |
82 |
82 using namespace options; |
83 using namespace options; |
|
84 |
|
85 // Parse the connection string and convert it to options: |
|
86 if (connectionString.size()) { |
|
87 std::string connectionStringBytes = convertor.to_bytes(connectionString); |
|
88 std::regex pattern("(tcp|udp|sctp)://([^:]+):([0-9]+)|(uds)://(.*)"); |
|
89 std::smatch match; |
|
90 if (std::regex_match(connectionStringBytes, match, pattern)) { |
|
91 setIfMissing(c.options, OPTION_PROTOCOL, match[1], false); |
|
92 setIfMissing(c.options, OPTION_PROTOCOL, match[4], false); |
|
93 setIfMissing(c.options, OPTION_HOST, match[2], false); |
|
94 setIfMissing(c.options, OPTION_PORT, match[3], false); |
|
95 setIfMissing(c.options, OPTION_PATH, match[5], false); |
|
96 if (match[1] == PROTOCOL_TCP) setIfMissing(c.options, OPTION_MODE, MODE_STREAM); |
|
97 } else { |
|
98 throw relpipe::cli::RelpipeCLIException(L"Invalid connection string: " + connectionString, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS); |
|
99 } |
|
100 } |
|
101 |
|
102 // Set defaults when values are missing: |
83 setIfMissing(c.options, OPTION_PROTOCOL, PROTOCOL_UDP); |
103 setIfMissing(c.options, OPTION_PROTOCOL, PROTOCOL_UDP); |
84 setIfMissing(c.options, OPTION_ROLE, ROLE_CLIENT); |
104 setIfMissing(c.options, OPTION_ROLE, ROLE_CLIENT); |
85 setIfMissing(c.options, OPTION_MODE, MODE_DATAGRAM); |
105 setIfMissing(c.options, OPTION_MODE, MODE_DATAGRAM); |
86 setIfMissing(c.options, OPTION_HOST, "127.0.0.1"); |
106 setIfMissing(c.options, OPTION_HOST, "127.0.0.1"); |
87 setIfMissing(c.options, OPTION_PORT, "64000"); |
107 setIfMissing(c.options, OPTION_PORT, "64000"); |