/// <summary> /// Main entry point /// </summary> static void Main(string[] args) { var prog = new Program(); try { for (var index = 0; index < args.Length; index++) { int tmp; var opt = args[index]; if (string.IsNullOrEmpty(args[index])) { continue; } if (opt[0] == '-' || opt[0] == '/') { if (opt.Length == 1) { throw new ArgumentException($"Unknown option {opt}."); } var optc = opt[1]; if (optc == '-' && opt[0] != '/') { // Parse -- long option var optl = opt.Substring(2); switch (optl) { case "help": case "source": case "close": case "wait": case "local": optc = optl[0]; break; case "version": case "relay": case "websocket": optc = char.ToUpperInvariant(optl[0]); break; case "proxy": optc = 'x'; break; default: throw new ArgumentException($"Unknown option {opt}."); } } switch (optc) { case 'd': prog.NoStdIn = true; break; case 'c': prog.CloseOnEof = true; break; case 'R': prog.UseRelay = true; break; case 'W': prog.UseWS = true; break; case '?': case 'h': PrintHelp(); return; case 'x': case 's': index++; SocketAddress proxy; if (index >= args.Length || !SocketAddress.TryParse(args[index], out proxy)) { throw new ArgumentException($"Bad value for {opt}."); } prog.Proxy = proxy; break; case 'w': index++; if (index >= args.Length || !int.TryParse(args[index], out tmp)) { throw new ArgumentException($"Bad value for {opt}."); } prog.Timeout = tmp * 1000; break; case 'l': index++; if (index >= args.Length || !int.TryParse(args[index], out tmp)) { throw new ArgumentException($"Bad value for {opt}."); } prog.LocalPort = (ushort)tmp; break; default: throw new ArgumentException($"Unknown option {opt}."); } continue; } if (string.IsNullOrEmpty(prog.Host)) { prog.Host = opt; } else { var ports = opt.Split('-'); if (!int.TryParse(ports[0], out tmp)) { throw new ArgumentException($"Invalid port value {opt}."); } prog.Ports.Add(tmp); if (ports.Length == 2) { if (!int.TryParse(ports[1], out var hi) || hi > ushort.MaxValue) { throw new ArgumentException($"Invalid upper bound for port range: {opt}."); } while (++tmp <= hi) { prog.Ports.Add(tmp); } } else if (ports.Length > 2) { throw new ArgumentException($"Invalid port range: {opt}."); } } } prog.Validate(); } catch (ArgumentException e) { Console.Error.WriteLine($"Error: {e.Message}"); PrintHelp(); return; } // Register console cancellation var cts = new CancellationTokenSource(); Console.CancelKeyPress += (o, e) => { Console.Error.WriteLine(); Console.Error.WriteLine("Ctrl+C => Cancellation requested..."); cts.Cancel(); e.Cancel = true; // Wait for cts to kill readers and exit - do not exit immediately. }; prog.RunAsync(cts.Token).Wait(); }