/// <summary> /// Parses the passed command line arguments and returns the result /// in a CommandLineOptions object. /// </summary> /// <param name="args">Array of command line arguments</param> /// <param name="list">Array of command line arguments</param> /// <returns>Object containing the parsed command line</returns> public static CommandLineOptions Parse(string[] args, params string[] singleOptionList) { if (args == null) throw new ArgumentNullException("args"); CommandLineOptions cmdOptions = new CommandLineOptions(); int index = 0; if (index < args.Length) { string token = NextToken(args, ref index); while (!string.IsNullOrEmpty(token)) { if (IsArgument(token)) { string arg = token.TrimStart(OptionStartWithChars).TrimEnd(OptionEqualChar); string value = string.Empty; if (arg.Contains(OptionEqualChar)) { // arg was specified with an '=' sign, so we need // to split the string into the arg and value, but only // if there is no space between the '=' and the arg and value. string[] r = arg.Split(new char[] { OptionEqualChar }, 2); if (r.Length == 2) { arg = r[0]; value = r[1]; } } // single option do not need a following parameter bool isSingleOption = false; if (singleOptionList != null) { for (int i = 0; i < singleOptionList.Length; i++) { if (arg == singleOptionList[i]) { isSingleOption = true; break; } } } // find following parameter while (!isSingleOption && string.IsNullOrEmpty(value)) { index++; if (index < args.Length) { string next = NextToken(args, ref index); if (!string.IsNullOrEmpty(next)) { if (IsArgument(next)) { // push the token back onto the stack so // it gets picked up on next pass as an arg index--; value = MagicOptionValue; break; } else if (next != OptionEqualChar.ToString()) { // save the value (trimming any '=' from the start) value = next.TrimStart(OptionEqualChar); } } } else { index--; value = MagicOptionValue; break; } } // save the pair if (cmdOptions.Arguments.ContainsKey(arg)) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Option used in invalid context -- {0}", "option with the same argument.")); if (value == MagicOptionValue) { cmdOptions.Arguments.Add(arg, string.Empty); } else { cmdOptions.Arguments.Add(arg, value.TrimStart('\'').TrimEnd('\'')); } } else { // save stand-alone parameter if (cmdOptions.Parameters.Contains(token)) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Option used in invalid context -- {0}", "option with the same argument.")); cmdOptions.Parameters.Add(token.TrimStart('\'').TrimEnd('\'')); } index++; if (index < args.Length) { token = NextToken(args, ref index); } else { break; } } } return cmdOptions; }
private static TcpLikaCommandLineOptions ParseOptions(CommandLineOptions commandLineOptions) { if (commandLineOptions == null) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Option used in invalid context -- {0}", "must specify a <host:port>.")); var options = new TcpLikaCommandLineOptions(); if (commandLineOptions.Arguments.Any()) { foreach (var arg in commandLineOptions.Arguments.Keys) { var optionType = TcpLikaOptions.GetOptionType(arg); if (optionType == TcpLikaOptionType.None) throw new CommandLineException( string.Format(CultureInfo.CurrentCulture, "Option used in invalid context -- {0}", string.Format(CultureInfo.CurrentCulture, "cannot parse the command line argument : [{0}].", arg))); switch (optionType) { case TcpLikaOptionType.Threads: { options.IsSetThreads = true; int threads; if (!int.TryParse(commandLineOptions.Arguments[arg], out threads)) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid formats of threads option -- {0}.", commandLineOptions.Arguments[arg])); if (threads < 1) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid formats of threads option -- {0}.", commandLineOptions.Arguments[arg])); options.Threads = threads; } break; case TcpLikaOptionType.Nagle: { options.IsSetNagle = true; var nagle = commandLineOptions.Arguments[arg].ToString().ToUpperInvariant(); if (nagle != "ON" && nagle != "OFF") throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid formats of nagle option (ON|OFF) -- {0}.", commandLineOptions.Arguments[arg])); options.Nagle = nagle == "ON"; } break; case TcpLikaOptionType.ReceiveBufferSize: { options.IsSetReceiveBufferSize = true; int bufferSize; if (!int.TryParse(commandLineOptions.Arguments[arg], out bufferSize)) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid formats of receive buffer size option -- {0}.", commandLineOptions.Arguments[arg])); if (bufferSize < 1) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid formats of receive buffer size option -- {0}.", commandLineOptions.Arguments[arg])); options.ReceiveBufferSize = bufferSize; } break; case TcpLikaOptionType.SendBufferSize: { options.IsSetSendBufferSize = true; int bufferSize; if (!int.TryParse(commandLineOptions.Arguments[arg], out bufferSize)) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid formats of send buffer size option -- {0}.", commandLineOptions.Arguments[arg])); if (bufferSize < 1) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid formats of send buffer size option -- {0}.", commandLineOptions.Arguments[arg])); options.SendBufferSize = bufferSize; } break; case TcpLikaOptionType.Connections: { options.IsSetConnections = true; int connections; if (!int.TryParse(commandLineOptions.Arguments[arg], out connections)) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid formats of connections option -- {0}.", commandLineOptions.Arguments[arg])); if (connections < 1) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid formats of connections option -- {0}.", commandLineOptions.Arguments[arg])); options.Connections = connections; } break; case TcpLikaOptionType.ConnectionLifetime: { options.IsSetChannelLifetime = true; int milliseconds; if (!int.TryParse(commandLineOptions.Arguments[arg], out milliseconds)) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid formats of channel lifetime [milliseconds] option -- {0}.", commandLineOptions.Arguments[arg])); if (milliseconds < 1) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid formats of channel lifetime [milliseconds] option -- {0}.", commandLineOptions.Arguments[arg])); options.ChannelLifetime = TimeSpan.FromMilliseconds(milliseconds); } break; case TcpLikaOptionType.WebSocket: options.IsSetWebSocket = true; break; case TcpLikaOptionType.WebSocketPath: { options.IsSetWebSocketPath = true; options.WebSocketPath = commandLineOptions.Arguments[arg].Trim(); if (string.IsNullOrEmpty(options.WebSocketPath)) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid value of WebSocketPath option -- {0}.", commandLineOptions.Arguments[arg])); options.WebSocketPath = "/" + options.WebSocketPath.TrimStart('/'); } break; case TcpLikaOptionType.WebSocketProtocol: { options.IsSetWebSocketProtocol = true; options.WebSocketProtocol = commandLineOptions.Arguments[arg]; if (string.IsNullOrEmpty(options.WebSocketProtocol)) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid value of WebSocketProtocol option -- {0}.", commandLineOptions.Arguments[arg])); } break; case TcpLikaOptionType.Ssl: options.IsSetSsl = true; break; case TcpLikaOptionType.SslTargetHost: { options.IsSetSslTargetHost = true; options.SslTargetHost = commandLineOptions.Arguments[arg]; if (string.IsNullOrEmpty(options.SslTargetHost)) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid value of SslTargetHost option -- {0}.", commandLineOptions.Arguments[arg])); } break; case TcpLikaOptionType.SslClientCertificateFilePath: { options.IsSetSslClientCertificateFilePath = true; options.SslClientCertificateFilePath = commandLineOptions.Arguments[arg]; if (string.IsNullOrEmpty(options.SslClientCertificateFilePath)) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid value of SslClientCertificateFilePath option -- {0}.", commandLineOptions.Arguments[arg])); if (!File.Exists(options.SslClientCertificateFilePath)) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid value of SslClientCertificateFilePath option -- {0} does not exist.", commandLineOptions.Arguments[arg])); try { options.SslClientCertificates.Add(new X509Certificate2(options.SslClientCertificateFilePath)); } catch (CryptographicException ex) { throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid value of SslClientCertificateFilePath option -- {0}.", ex.Message), ex); } } break; case TcpLikaOptionType.SslBypassedErrors: options.IsSetSslPolicyErrorsBypassed = true; break; case TcpLikaOptionType.Help: options.IsSetHelp = true; break; case TcpLikaOptionType.Version: options.IsSetVersion = true; break; } } } if (commandLineOptions.Parameters.Any()) { try { foreach (var item in commandLineOptions.Parameters) { var splits = item.Split(':'); if (splits.Length < 2) throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "{0} is not well formatted as <host:port>.", item)); var host = IPAddress.Parse(splits[0]); var port = int.Parse(splits[1]); var endpoint = new IPEndPoint(host, port); options.RemoteEndPoints.Add(endpoint); } } catch (Exception ex) { throw new CommandLineException(string.Format(CultureInfo.CurrentCulture, "Invalid formats of endpoints -- {0}", ex.Message), ex); } } return options; }