Exemple #1
0
        private static void UpdateWhoIsOnlineFile()
        {
            try {
                var SB = new StringBuilder();
                SB.AppendLine("Node,RemoteIP,User,Status");
                lock (_ListLock) {
                    // Get status from each node
                    for (int Node = Config.Instance.FirstNode; Node <= Config.Instance.LastNode; Node++)
                    {
                        if (_ClientThreads[Node] == null)
                        {
                            SB.AppendLine($"{Node}\t\t\tWaiting for caller");
                        }
                        else
                        {
                            SB.AppendLine($"{Node}\t{_ClientThreads[Node].IPAddress}\t{_ClientThreads[Node].Alias}\t{_ClientThreads[Node].Status}");
                        }
                    }
                }

                string WhoIsOnlineFilename = StringUtils.PathCombine(ProcessUtils.StartupPath, "whoisonline.txt");
                FileUtils.FileWriteAllText(WhoIsOnlineFilename, SB.ToString());
            } catch (Exception ex) {
                RMLog.Exception(ex, "Unable to update whoisonline.txt");
            }
        }
Exemple #2
0
        public void Start()
        {
            RMLog.Handler += RMLog_Handler;

            RMLog.Info("fTelnetProxy Starting Up");

            Config.Default.Load();
            ParseEnvironmentVariables();
            ParseCommandLineArgs();

            if ((Config.Default.CertificateFilename != "") && File.Exists(Config.Default.CertificateFilename))
            {
                try {
                    Config.Default.Certificate = new X509Certificate2(Config.Default.CertificateFilename, Config.Default.CertificatePassword);
                } catch (Exception ex) {
                    RMLog.Exception(ex, "--Error loading cert file");
                }
            }

            try {
                RMLog.Info("Starting WebSocket proxy thread");
                _WebSocketServer = new WebSocketServerThread("0.0.0.0", Config.Default.ListenPort);
                _WebSocketServer.Start();
            } catch (Exception ex) {
                RMLog.Exception(ex, "Failed to start WebSocket proxy thread");
                Environment.Exit(1);
            }
        }
Exemple #3
0
        protected override void Execute()
        {
            while (!_Stop)
            {
                string IgnoredIPsFileName  = StringUtils.PathCombine(ProcessUtils.StartupPath, "config", "ignored-ips.txt");
                string CombinedFileName    = StringUtils.PathCombine(ProcessUtils.StartupPath, "config", "ignored-ips-combined.txt");
                string StatusCakeFileName  = StringUtils.PathCombine(ProcessUtils.StartupPath, "config", "ignored-ips-statuscake.txt");
                string UptimeRobotFileName = StringUtils.PathCombine(ProcessUtils.StartupPath, "config", "ignored-ips-uptimerobot.txt");

                // Get the list of servers from StatusCake
                try {
                    string IPs = WebUtils.HttpGet("https://www.statuscake.com/API/Locations/txt");
                    IPs = IPs.Replace("\r\n", "CRLF").Replace("\n", "\r\n").Replace("CRLF", "\r\n");
                    FileUtils.FileWriteAllText(StatusCakeFileName, IPs);
                } catch (Exception ex) {
                    RMLog.Exception(ex, "Unable to download https://www.statuscake.com/API/Locations/txt");
                }

                // Get the list of servers from UptimeRobot
                try {
                    string Locations = WebUtils.HttpGet("http://uptimerobot.com/locations");
                    var    Matches   = Regex.Matches(Locations, @"[<]li[>](\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})");

                    List <string> IPs = new List <string>();
                    foreach (Match M in Matches)
                    {
                        IPs.Add(M.Groups[1].Value);
                    }

                    FileUtils.FileWriteAllText(UptimeRobotFileName, string.Join("\r\n", IPs.ToArray()));
                } catch (Exception ex) {
                    RMLog.Exception(ex, "Unable to download https://www.statuscake.com/API/Locations/txt");
                }

                // Combine the lists
                try {
                    FileUtils.FileWriteAllText(CombinedFileName, "");
                    if (File.Exists(IgnoredIPsFileName))
                    {
                        FileUtils.FileAppendAllText(CombinedFileName, FileUtils.FileReadAllText(IgnoredIPsFileName));
                    }
                    if (File.Exists(StatusCakeFileName))
                    {
                        FileUtils.FileAppendAllText(CombinedFileName, FileUtils.FileReadAllText(StatusCakeFileName));
                    }
                    if (File.Exists(UptimeRobotFileName))
                    {
                        FileUtils.FileAppendAllText(CombinedFileName, FileUtils.FileReadAllText(UptimeRobotFileName));
                    }
                } catch (Exception ex) {
                    RMLog.Exception(ex, "Unable to combine Ignored IPs lists");
                }

                // Wait for one hour before updating again
                if (!_Stop && (_StopEvent != null))
                {
                    _StopEvent.WaitOne(3600000);
                }
            }
        }
Exemple #4
0
        public void Run()
        {
            try {
                // Clear the buffers and reset the screen
                _ClientThread.NodeInfo.Connection.ReadString();
                _ClientThread.ClrScr();

                // Create the node directory and drop files
                CreateNodeDirectory();

                // Determine how to run the door
                if (((_ClientThread.NodeInfo.Door.Platform == OSUtils.Platform.Linux) && OSUtils.IsUnix) || ((_ClientThread.NodeInfo.Door.Platform == OSUtils.Platform.Windows) && OSUtils.IsWindows))
                {
                    RunDoorNative(TranslateCLS(_ClientThread.NodeInfo.Door.Command), TranslateCLS(_ClientThread.NodeInfo.Door.Parameters));
                }
                else if ((_ClientThread.NodeInfo.Door.Platform == OSUtils.Platform.DOS) && OSUtils.IsWindows)
                {
                    if (ProcessUtils.Is64BitOperatingSystem)
                    {
                        if (Helpers.IsDOSBoxInstalled())
                        {
                            RunDoorDOSBox(TranslateCLS(_ClientThread.NodeInfo.Door.Command), TranslateCLS(_ClientThread.NodeInfo.Door.Parameters));
                        }
                        else
                        {
                            RMLog.Error("DOS doors are not supported on 64bit Windows (unless you install DOSBox 0.73)");
                        }
                    }
                    else
                    {
                        (new RunDoorSBBSEXEC(_ClientThread)).Run(TranslateCLS(_ClientThread.NodeInfo.Door.Command), TranslateCLS(_ClientThread.NodeInfo.Door.Parameters), _ClientThread.NodeInfo.Door.ForceQuitDelay);
                    }
                }
                else if ((_ClientThread.NodeInfo.Door.Platform == OSUtils.Platform.DOS) && OSUtils.IsUnix)
                {
                    if (Helpers.IsDOSEMUInstalled())
                    {
                        RunDoorDOSEMU(TranslateCLS(_ClientThread.NodeInfo.Door.Command), TranslateCLS(_ClientThread.NodeInfo.Door.Parameters));
                    }
                    else
                    {
                        RMLog.Error("DOS doors are not supported on Linux (unless you install DOSEMU)");
                    }
                }
                else
                {
                    RMLog.Error("Unsure how to run door on current platform");
                }
            } catch (Exception ex) {
                RMLog.Exception(ex, "Error while running door '" + _ClientThread.NodeInfo.Door.Name + "'");
            } finally {
                // Clean up
                try {
                    _ClientThread.ClrScr();
                    _ClientThread.NodeInfo.Connection.SetBlocking(true); // In case native door disabled blocking sockets
                    DeleteNodeDirectory();
                } catch { /* Ignore */ }
            }
        }
        protected override void Execute()
        {
            using (_Server = new WebSocketConnection()) {
                if (_Server.Listen(_Address, _Port))
                {
                    RaiseListeningEvent();

                    while (!_Stop)
                    {
                        try {
                            // Accept an incoming connection
                            if (_Server.CanAccept(1000)) // 1 second
                            {
                                Socket NewSocket = _Server.Accept();
                                if (NewSocket != null)
                                {
                                    lock (_ClientThreadsLock) {
                                        WebSocketClientThread ClientThread = new WebSocketClientThread(NewSocket, ++_ClientThreadCounter);
                                        ClientThread.FinishEvent += ClientThread_FinishEvent;
                                        _ClientThreads.Add(ClientThread);
                                        RMLog.Info(_ClientThreads.Count.ToString() + " active connections");
                                        ClientThread.Start();
                                    }
                                }
                            }
                        } catch (Exception ex) {
                            RMLog.Exception(ex, "Unable to accept new websocket connection");
                        }
                    }

                    // Stop client threads
                    int ClientThreadCount = 0;
                    lock (_ClientThreadsLock) {
                        foreach (var ClientThread in _ClientThreads)
                        {
                            if (ClientThread != null)
                            {
                                ClientThread.Stop();
                            }
                        }
                        ClientThreadCount = _ClientThreads.Count;
                    }

                    // Wait for client threads
                    while (ClientThreadCount > 0)
                    {
                        lock (_ClientThreadsLock) {
                            ClientThreadCount = _ClientThreads.Count;
                        }
                        Thread.Sleep(100);
                    }
                }
                else
                {
                    RMLog.Error("WebSocket Server Thread: Unable to listen on " + _Address + ":" + _Port);
                }
            }
        }
Exemple #6
0
        public static void StartThread()
        {
            RMLog.Info("Starting Ignored IPs Thread");

            try {
                // Create Ignored IPs Thread and Thread objects
                _IgnoredIPsThread = new IgnoredIPsThread();
                _IgnoredIPsThread.Start();
            } catch (Exception ex) {
                RMLog.Exception(ex, "Error in IgnoredIPsThread::StartThread()");
            }
        }
Exemple #7
0
 private void StopProcess()
 {
     try {
         // Terminate process if it hasn't closed yet
         if ((P != null) && !P.HasExited)
         {
             RMLog.Error("Door still running, performing a force quit");
             P.Kill();
         }
     } catch (Exception ex) {
         RMLog.Exception(ex, "Unable to perform force quit");
     }
 }
Exemple #8
0
        public void Start()
        {
            if (_Status == GameSrvStatus.Paused)
            {
                // If we're paused, call Pause() again to un-pause
                Pause();
            }
            else if (_Status == GameSrvStatus.Stopped)
            {
                // Clean up the files not needed by this platform
                Helpers.CleanUpFiles();

                // Check for 3rd party software
                Helpers.CheckFor3rdPartySoftware();

                // Load the Global settings
                Config.Instance.Init();

                // Start the node manager
                NodeManager.Start();

                // Start the server threads
                ServerThreadManager.StartThreads();

                // Start the ignored ips thread
                IgnoredIPsThread.StartThread();

                // Start the timed events thread
                TimedEventsThread.StartThread();

                // Drop root, if necessary
                try {
                    Helpers.DropRoot(Config.Instance.UnixUser);
                } catch (ArgumentOutOfRangeException aoorex) {
                    RMLog.Exception(aoorex, "Unable to drop from root to '" + Config.Instance.UnixUser + "'");

                    // Undo previous actions on error
                    TimedEventsThread.StopThread();
                    IgnoredIPsThread.StopThread();
                    ServerThreadManager.StopThreads();
                    NodeManager.Stop();

                    // If we get here, we failed to go online
                    UpdateStatus(GameSrvStatus.Stopped);
                    return;
                }

                // If we get here, we're online
                UpdateStatus(GameSrvStatus.Started);
            }
        }
        public static void StopThreads()
        {
            RMLog.Info("Stopping Server Threads");

            try {
                foreach (KeyValuePair <int, ServerThread> KV in _ServerThreads)
                {
                    KV.Value.Stop();
                }
                _ServerThreads.Clear();
            } catch (Exception ex) {
                RMLog.Exception(ex, "Error in ServerThreadManager::StopThreads()");
            }
        }
Exemple #10
0
        public static void StopThread()
        {
            RMLog.Info("Stopping Ignored IPs Thread");

            if (_IgnoredIPsThread != null)
            {
                try {
                    _IgnoredIPsThread.Stop();
                    _IgnoredIPsThread.Dispose();
                    _IgnoredIPsThread = null;
                } catch (Exception ex) {
                    RMLog.Exception(ex, "Error in IgnoredIPsThread::StopThread()");
                }
            }
        }
Exemple #11
0
        public static void StopThread()
        {
            RMLog.Info("Stopping Timed Events Thread");

            if (_TimedEventsThread != null)
            {
                try {
                    _TimedEventsThread.Stop();
                    _TimedEventsThread.Dispose();
                    _TimedEventsThread = null;
                } catch (Exception ex) {
                    RMLog.Exception(ex, "Error in TimedEventsThread::StartThread()");
                }
            }
        }
Exemple #12
0
 private void FlushLog()
 {
     lock (_LogLock) {
         // Flush log to disk
         if (_Log.Count > 0)
         {
             try {
                 FileUtils.FileAppendAllText(StringUtils.PathCombine(ProcessUtils.StartupPath, "logs", "gamesrv.log"), string.Join(Environment.NewLine, _Log.ToArray()) + Environment.NewLine);
                 _Log.Clear();
             } catch (Exception ex) {
                 RMLog.Exception(ex, "Unable to update gamesrv.log");
             }
         }
     }
 }
 public void DisplayActiveConnections()
 {
     lock (_ClientThreadsLock) {
         foreach (var ClientThread in _ClientThreads)
         {
             if (ClientThread != null)
             {
                 try {
                     ClientThread.DisplayConnectionInformation();
                 } catch (Exception ex) {
                     RMLog.Exception(ex, "Error listing client thread details");
                 }
             }
         }
     }
 }
Exemple #14
0
        public static void Run(ClientThread clientThread)
        {
            if (clientThread == null)
            {
                throw new ArgumentNullException("clientThread");
            }

            // Loop through the options, and run the ones we allow here
            bool ExitFor = false;

            string[] Processes = LogOnProcess.GetProcesses();
            for (int i = 0; i < Processes.Length; i++)
            {
                try {
                    LogOnProcess LP = new LogOnProcess(Processes[i]);
                    if ((LP.Loaded) && (!clientThread.QuitThread()))
                    {
                        switch (LP.Action)
                        {
                        case Action.Disconnect:
                        case Action.DisplayFile:
                        case Action.DisplayFileMore:
                        case Action.DisplayFilePause:
                        case Action.MainMenu:
                        case Action.Pause:
                        case Action.RunDoor:
                            MenuOption MO = new MenuOption("", '\0')
                            {
                                Action         = LP.Action,
                                Name           = LP.Name,
                                Parameters     = LP.Parameters,
                                RequiredAccess = LP.RequiredAccess,
                            };
                            ExitFor = clientThread.HandleMenuOption(MO);
                            break;
                        }
                        if (ExitFor)
                        {
                            break;
                        }
                    }
                } catch (Exception ex) {
                    // If there's something wrong with the ini entry (Action is invalid for example), this will throw a System.ArgumentException error, so we just ignore that menu item
                    RMLog.Exception(ex, "Error during logon process '" + Processes[i] + "'");
                }
            }
        }
Exemple #15
0
 public static bool IsBannedIP(string ip)
 {
     try {
         string BannedIPsFileName = StringUtils.PathCombine(ProcessUtils.StartupPath, "config", "banned-ips.txt");
         if (File.Exists(BannedIPsFileName))
         {
             return(FileContainsIP(BannedIPsFileName, ip));
         }
         else
         {
             // No file means not banned
             return(false);
         }
     } catch (Exception ex) {
         RMLog.Exception(ex, "Unable to validate client IP against banned-ips.txt");
         return(false); // Give them the benefit of the doubt on error
     }
 }
Exemple #16
0
 public static bool IsRLoginIP(string ip)
 {
     try {
         string RLoginIPsFileName = StringUtils.PathCombine(ProcessUtils.StartupPath, "config", "rlogin-ips.txt");
         if (File.Exists(RLoginIPsFileName))
         {
             return(FileContainsIP(RLoginIPsFileName, ip));
         }
         else
         {
             // No file means any RLogin connection allowed
             return(true);
         }
     } catch (Exception ex) {
         RMLog.Exception(ex, "Unable to validate client IP against ignored-ips.txt");
         return(true); // Give them the benefit of the doubt on error
     }
 }
        public static void StartThreads()
        {
            if ((Config.Instance.RLoginServerPort > 0) || (Config.Instance.TelnetServerPort > 0))
            {
                RMLog.Info("Starting Server Threads");

                try {
                    _ServerThreads.Clear();

                    if (Config.Instance.RLoginServerPort > 0)
                    {
                        // Create Server Thread and add to collection
                        _ServerThreads.Add(Config.Instance.RLoginServerPort, new RLoginServerThread());
                    }

                    if (Config.Instance.TelnetServerPort > 0)
                    {
                        // Create Server Thread and add to collection
                        _ServerThreads.Add(Config.Instance.TelnetServerPort, new TelnetServerThread());
                    }

                    if (Config.Instance.WebSocketServerPort > 0)
                    {
                        // Create Server Thread and add to collection
                        _ServerThreads.Add(Config.Instance.WebSocketServerPort, new WebSocketServerThread());
                    }

                    // Now actually start the server threads
                    foreach (var KVP in _ServerThreads)
                    {
                        KVP.Value.Start();
                    }
                } catch (Exception ex) {
                    RMLog.Exception(ex, "Error in ServerThreadManager::StartThreads()");
                }
            }
            else
            {
                RMLog.Error("Must specify a port for RLogin and/or Telnet servers");
            }
        }
Exemple #18
0
 protected override void Execute()
 {
     while (!_Stop)
     {
         using (TcpConnection Connection = new TcpConnection()) {
             if (Connection.Listen(_LocalAddress, _LocalPort))
             {
                 while (!_Stop)
                 {
                     // Accept an incoming connection
                     if (Connection.CanAccept(1000)) // 1 second
                     {
                         try {
                             TcpConnection NewConnection = Connection.AcceptTCP();
                             if (NewConnection != null)
                             {
                                 // TODOX Add check for flash socket policy request by doing a peek with a 1 second timeout or something
                                 //       If peeked character is < then peek another character to see if it's the flash request string
                                 HandleNewConnection(NewConnection);
                             }
                         } catch (Exception ex) {
                             RMLog.Exception(ex, "Error in ServerThread::Execute()");
                         }
                     }
                 }
             }
             else
             {
                 RMLog.Error($"{_ConnectionType} Server Thread unable to listen on {_LocalAddress}:{_LocalPort}.  Retry in 15 seconds.");
                 for (int i = 1; i <= 15; i++)
                 {
                     Thread.Sleep(1000);
                     if (_Stop)
                     {
                         break;
                     }
                 }
             }
         }
     }
 }
Exemple #19
0
        public static bool IsIgnoredIP(string ip)
        {
            try {
                if (Helpers.IsTempIgnoredIP(ip))
                {
                    return(true);
                }

                string IgnoredIPsFileName = StringUtils.PathCombine(ProcessUtils.StartupPath, "config", "ignored-ips-combined.txt");
                if (File.Exists(IgnoredIPsFileName))
                {
                    return(FileContainsIP(IgnoredIPsFileName, ip));
                }
                else
                {
                    // No file means not ignored
                    return(false);
                }
            } catch (Exception ex) {
                RMLog.Exception(ex, "Unable to validate client IP against ignored-ips.txt");
                return(false); // Give them the benefit of the doubt on error
            }
        }
        public void Start()
        {
            RMLog.Handler += RMLog_Handler;

            RMLog.Info("fTelnetProxy Starting Up");

            Config.Default.Load();
            ParseEnvironmentVariables();
            ParseCommandLineArgs();

            if (!string.IsNullOrWhiteSpace(Config.Default.CertificateFilename) && File.Exists(Config.Default.CertificateFilename))
            {
                try {
                    if (OSUtils.IsUnix)
                    {
                        Environment.SetEnvironmentVariable("MONO_TLS_PROVIDER", "btls");
                    }

                    // Try loading the certificate to ensure there are no problems
                    var testCert = Config.Default.Certificate;
                } catch (Exception ex) {
                    // Loading cert failed, so wipe the filename to ensure we don't try loading it again later
                    RMLog.Exception(ex, "--Error loading cert file");
                    Config.Default.CertificateFilename = null;
                }
            }

            try {
                RMLog.Info("Starting WebSocket proxy thread");
                _WebSocketServer = new WebSocketServerThread("0.0.0.0", Config.Default.ListenPort);
                _WebSocketServer.ListeningEvent += WebSocketServer_ListeningEvent;
                _WebSocketServer.Start();
            } catch (Exception ex) {
                RMLog.Exception(ex, "Failed to start WebSocket proxy thread");
                Environment.Exit(1);
            }
        }
Exemple #21
0
        public static bool IsBannedUser(string alias)
        {
            if (alias == null)
            {
                throw new ArgumentNullException("alias");
            }

            try {
                alias = alias.Trim().ToLower();
                if (string.IsNullOrEmpty(alias))
                {
                    return(false); // Don't ban for blank inputs
                }
                string BannedUsersFileName = StringUtils.PathCombine(ProcessUtils.StartupPath, "config", "banned-users.txt");
                if (File.Exists(BannedUsersFileName))
                {
                    string[] BannedUsers = FileUtils.FileReadAllLines(BannedUsersFileName);
                    foreach (string BannedUser in BannedUsers)
                    {
                        if (BannedUser.StartsWith(";"))
                        {
                            continue;
                        }

                        if (BannedUser.Trim().ToLower() == alias)
                        {
                            return(true);
                        }
                    }
                }
            } catch (Exception ex) {
                RMLog.Exception(ex, "Unable to validate alias against banned-users.txt");
            }

            // If we get here, it's an OK name
            return(false);
        }
        protected override void Execute()
        {
            try {
                // Handle non-proxy connections
                using (WebSocketConnection UserConnection = new WebSocketConnection(true, Config.Default.Certificate)) {
                    if (UserConnection.Open(_Socket))
                    {
                        _RemoteIP = UserConnection.GetRemoteIP();

                        RMLog.Debug("{" + _ConnectionId.ToString() + "} Opened connection from " + UserConnection.GetRemoteIP() + ":" + UserConnection.GetRemotePort());
                        if (UserConnection.Header["Path"] == "/ping")
                        {
                            // Handle ping requests (from proxy.ftelnet.ca most likely)
                            string Ping = UserConnection.ReadLn(1000);
                            if (UserConnection.ReadTimedOut)
                            {
                                RMLog.Debug("Answering a /ping (no time received) from " + UserConnection.GetRemoteIP() + ":" + UserConnection.GetRemotePort());
                            }
                            else
                            {
                                RMLog.Debug("Answering a /ping (" + Ping + ") from " + UserConnection.GetRemoteIP() + ":" + UserConnection.GetRemotePort());
                                UserConnection.Write(Ping);
                            }
                            return;
                        }
                    }
                    else
                    {
                        if (UserConnection.FlashPolicyFileRequest)
                        {
                            RMLog.Info("{" + _ConnectionId.ToString() + "} Answered flash policy file request from " + UserConnection.GetRemoteIP() + ":" + UserConnection.GetRemotePort().ToString());
                        }
                        else
                        {
                            RMLog.Debug("{" + _ConnectionId.ToString() + "} Invalid WebSocket connection from " + UserConnection.GetRemoteIP() + ":" + UserConnection.GetRemotePort().ToString());
                        }
                        return;
                    }

                    // If we get here it's a proxy connection, so handle it
                    RMLog.Info("{" + _ConnectionId.ToString() + "} Connection accepted from " + UserConnection.GetRemoteIP() + ":" + UserConnection.GetRemotePort());

                    string MessageText = string.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\r\n",
                                                       DateTime.Now.ToString(),
                                                       UserConnection.GetRemoteIP(),
                                                       UserConnection.GetRemotePort(),
                                                       UserConnection.Header["Path"],
                                                       UserConnection.Protocol,
                                                       UserConnection.SubProtocol);
                    FileUtils.FileAppendAllText(Path.Combine(ProcessUtils.StartupPath, "fTelnetProxy-Connections.log"), MessageText, Encoding.ASCII);

                    // Defaults for redirect location
                    _Hostname = Config.Default.TargetHostname;
                    _Port     = Config.Default.TargetPort;

                    // Check if user is requesting a custom target
                    if (UserConnection.Header["Path"] != "/")
                    {
                        bool CanRelay = false;

                        // Extract the requested host and port
                        string[] HostAndPort = UserConnection.Header["Path"].Split('/');
                        if ((HostAndPort.Length == 3) && (int.TryParse(HostAndPort[2], out _Port)))
                        {
                            _Hostname = HostAndPort[1];
                            if (Config.Default.TargetHostname.ToLower().Trim() == _Hostname.ToLower().Trim())
                            {
                                // User is requesting the target defined by the proxy admin, so check if it's to an allowed port
                                CanRelay = ((_Port > 0) && (_Port == Config.Default.TargetPort) || (_Port == Config.Default.RLoginPort));
                            }
                            else if (!string.IsNullOrEmpty(Config.Default.RelayFilename))
                            {
                                // proxy admin has relaying enabled, so check against the relay.cfg file
                                try {
                                    // Read relay file
                                    if (File.Exists(Config.Default.RelayFilename))
                                    {
                                        string[] AllowedHosts = File.ReadAllLines(Config.Default.RelayFilename);
                                        if (AllowedHosts.Length > 0)
                                        {
                                            // Check for a whitelisted port
                                            string[] AllowedPorts = AllowedHosts[0].Split(',');
                                            foreach (string AllowedPort in AllowedPorts)
                                            {
                                                if (AllowedPort == _Port.ToString())
                                                {
                                                    CanRelay = true;
                                                    break;
                                                }
                                            }

                                            // Not a whitelisted port, check for a whitelisted host
                                            if (!CanRelay)
                                            {
                                                string RequestedHostPort = _Hostname.ToLower() + ":" + _Port.ToString();
                                                foreach (string AllowedHost in AllowedHosts)
                                                {
                                                    if (AllowedHost.Trim().ToLower() == RequestedHostPort)
                                                    {
                                                        CanRelay = true;
                                                        break;
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            RMLog.Error("{" + _ConnectionId.ToString() + "} Relay file is empty: '" + Config.Default.RelayFilename + "'");
                                        }
                                    }
                                    else
                                    {
                                        RMLog.Error("{" + _ConnectionId.ToString() + "} Relay file does not exist: '" + Config.Default.RelayFilename + "'");
                                    }
                                } catch (Exception ex) {
                                    RMLog.Exception(ex, "{" + _ConnectionId.ToString() + "} Error reading relay file: '" + Config.Default.RelayFilename + "'");
                                }
                            }
                        }

                        if (!CanRelay)
                        {
                            RMLog.Info("{" + _ConnectionId.ToString() + "} Rejecting request for " + _Hostname + ":" + _Port.ToString());
                            UserConnection.WriteLn("Sorry, for security reasons this proxy won't connect to " + _Hostname + ":" + _Port.ToString());
                            UserConnection.WriteLn("unless you contact me via the contact form on www.fTelnet.ca.  Just let me");
                            UserConnection.WriteLn("know the hostname and port you're trying to connect to, and I'll add it to");
                            UserConnection.WriteLn("the whitelist for you.");
                            Thread.Sleep(2500);
                            return;
                        }
                    }

                    // Try to connect to the desired Host and Port
                    UserConnection.Write(Ansi.ClrScr() + "Connecting to " + _Hostname + ":" + _Port.ToString() + "...");
                    using (TcpConnection ServerConnection = new TcpConnection()) {
                        if (ServerConnection.Connect(_Hostname, _Port))
                        {
                            RMLog.Info("{" + _ConnectionId.ToString() + "} Connected to " + _Hostname + ":" + _Port.ToString());
                            UserConnection.WriteLn("connected!");

                            // Repeatedly move data around until a connection is closed (or a stop is requested)
                            bool DoSleep = true;
                            while (!_Stop && UserConnection.Connected && ServerConnection.Connected)
                            {
                                DoSleep = true;

                                if (UserConnection.CanRead())
                                {
                                    ServerConnection.WriteBytes(UserConnection.ReadBytes());
                                    _DateLastTX = DateTime.Now;
                                    DoSleep     = false;
                                }

                                if (ServerConnection.CanRead())
                                {
                                    UserConnection.WriteBytes(ServerConnection.ReadBytes(1024)); // 1k at a time to allow non-stop screens to be aborted by user input
                                    _DateLastRX = DateTime.Now;
                                    DoSleep     = false;
                                }

                                if (DoSleep)
                                {
                                    Thread.Sleep(1);
                                }

                                // Check if we should abort due to idle times
                                // TODOX Allow to be customized
                                if (SecondsSinceLastRX > 600)
                                {
                                    // 10 minutes of no server activity
                                    RMLog.Info("{" + _ConnectionId.ToString() + "} Disconnecting after 10 minutes of no activity from server");
                                    UserConnection.Write(Ansi.GotoXY(1, 1) + Ansi.CursorDown(255) + "\r\nDisconnecting after 10 minutes of no activity from server...");
                                    Thread.Sleep(2500);
                                    break;
                                }
                                else if (SecondsSinceLastTX > 600)
                                {
                                    // 10 minutes of no user activity
                                    RMLog.Info("{" + _ConnectionId.ToString() + "} Disconnecting after 10 minutes of no activity from user");
                                    UserConnection.Write(Ansi.GotoXY(1, 1) + Ansi.CursorDown(255) + "\r\nDisconnecting after 10 minutes of no activity from user...");
                                    Thread.Sleep(2500);
                                    break;
                                }
                                else if (SecondsSinceConnecting > 21600)
                                {
                                    // 6 hours since connecting
                                    RMLog.Info("{" + _ConnectionId.ToString() + "} Disconnecting after 6 hours");
                                    UserConnection.Write(Ansi.GotoXY(1, 1) + Ansi.CursorDown(255) + "\r\nDisconnecting after 6 hours...");
                                    Thread.Sleep(2500);
                                    break;
                                }
                            }

                            // Check why we exited the loop
                            if (_Stop)
                            {
                                RMLog.Info("{" + _ConnectionId.ToString() + "} Stop requested");
                                UserConnection.Write(Ansi.GotoXY(1, 1) + Ansi.CursorDown(255) + "\r\nProxy server shutting down...");
                                Thread.Sleep(2500);
                            }
                            else if (!UserConnection.Connected)
                            {
                                RMLog.Info("{" + _ConnectionId.ToString() + "} Client closed connection");
                            }
                            else if (!ServerConnection.Connected)
                            {
                                RMLog.Info("{" + _ConnectionId.ToString() + "} Server closed connection");
                                UserConnection.Write(Ansi.GotoXY(1, 1) + Ansi.CursorDown(255) + "\r\nServer closed connection...");
                                Thread.Sleep(2500);
                            }
                        }
                        else
                        {
                            RMLog.Info("{" + _ConnectionId.ToString() + "} Unable to connect to " + _Hostname + ":" + _Port.ToString());
                            UserConnection.WriteLn("unable to connect!");
                            Thread.Sleep(2500);
                        }
                    }

                    // Display info about the connection we're closing
                    DisplayConnectionInformation();
                }
            } catch (Exception ex) {
                RMLog.Exception(ex, "{" + _ConnectionId.ToString() + "} Exception in client thread");
            }
        }
Exemple #23
0
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static void Main(string[] args)
        {
            try {
                // Check for service mode or console mode
                if (Environment.UserInteractive || OSUtils.IsUnix)
                {
                    // Console mode, check for arguments
                    if (args.Length > 0)
                    {
                        try {
                            // Check entire parameter string for service install or uninstall request
                            string ParameterString = string.Concat(args).TrimStart('/').TrimStart('-');
                            switch (ParameterString)
                            {
                            case "install":
                                Console.WriteLine("Installing service...");
                                ManagedInstallerClass.InstallHelper(new string[] { Assembly.GetExecutingAssembly().Location });
                                Console.WriteLine("Service installed successfully!");
                                return;

                            case "uninstall":
                                Console.WriteLine("Uninstalling service...");
                                ManagedInstallerClass.InstallHelper(new string[] { "/u", Assembly.GetExecutingAssembly().Location });
                                Console.WriteLine("Service uninstalled successfully!");
                                return;
                            }
                        } catch (Exception ex) {
                            Console.WriteLine("Error handling service request: " + ex.Message);
                            return;
                        }
                    }

                    // If we get here, we're running as console app
                    using (var fTelnetProxy = new fTelnetProxy()) {
                        fTelnetProxy.Start();

                        Console.WriteLine("Press A for Active Connections or Q to Quit...");

                        while (true)
                        {
                            if (Console.KeyAvailable)
                            {
                                var Ch = Console.ReadKey(true).Key;
                                if (Ch == ConsoleKey.A)
                                {
                                    fTelnetProxy.DisplayActiveConnections();
                                }
                                else if (Ch == ConsoleKey.Q)
                                {
                                    break;
                                }
                                else
                                {
                                    Console.WriteLine(fTelnetProxy.ClientConnectionCount.ToString() + " active connections");
                                    Console.WriteLine("Press A for Active Connections or Q to Quit...");
                                }
                            }
                            else
                            {
                                Thread.Sleep(1000);
                            }
                        }

                        Console.WriteLine("Exiting...");

                        fTelnetProxy.Stop();
                    }
                }
                else
                {
                    // Service mode
                    using (var fTelnetProxyService = new Service()) {
                        ServiceBase.Run(fTelnetProxyService);
                    }
                }
            } catch (Exception ex) {
                RMLog.Exception(ex, "Unhandled exception in main program loop");
            }
        }
Exemple #24
0
        protected override void Execute()
        {
            try {
                // Handle non-proxy connections
                using (WebSocketConnection NewConnection = new WebSocketConnection(true, Config.Default.Certificate)) {
                    if (NewConnection.Open(_Socket))
                    {
                        RMLog.Debug("{" + _ConnectionId.ToString() + "} Opened connection from " + NewConnection.GetRemoteIP() + ":" + NewConnection.GetRemotePort());
                        if (NewConnection.Header["Path"] == "/ping")
                        {
                            // Handle ping requests (from proxy.ftelnet.ca most likely)
                            string Ping = NewConnection.ReadLn(1000);
                            if (NewConnection.ReadTimedOut)
                            {
                                RMLog.Debug("Answering a /ping (no time received) from " + NewConnection.GetRemoteIP() + ":" + NewConnection.GetRemotePort());
                            }
                            else
                            {
                                RMLog.Debug("Answering a /ping (" + Ping + ") from " + NewConnection.GetRemoteIP() + ":" + NewConnection.GetRemotePort());
                                NewConnection.Write(Ping);
                            }
                            return;
                        }
                    }
                    else
                    {
                        if (NewConnection.FlashPolicyFileRequest)
                        {
                            RMLog.Info("{" + _ConnectionId.ToString() + "} Answered flash policy file request from " + NewConnection.GetRemoteIP() + ":" + NewConnection.GetRemotePort().ToString());
                        }
                        else
                        {
                            RMLog.Debug("{" + _ConnectionId.ToString() + "} Invalid WebSocket connection from " + NewConnection.GetRemoteIP() + ":" + NewConnection.GetRemotePort().ToString());
                        }
                        return;
                    }

                    // If we get here it's a proxy connection, so handle it
                    RMLog.Info("{" + _ConnectionId.ToString() + "} Connection accepted from " + NewConnection.GetRemoteIP() + ":" + NewConnection.GetRemotePort());

                    string MessageText = string.Format("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\r\n",
                                                       DateTime.Now.ToString(),
                                                       NewConnection.GetRemoteIP(),
                                                       NewConnection.GetRemotePort(),
                                                       NewConnection.Header["Path"],
                                                       NewConnection.Protocol,
                                                       NewConnection.SubProtocol);
                    FileUtils.FileAppendAllText(Path.Combine(ProcessUtils.StartupPath, "fTelnetProxy-Connections.log"), MessageText, Encoding.ASCII);

                    // Defaults for redirect location
                    string Hostname = Config.Default.TargetHostname;
                    int    Port     = Config.Default.TargetPort;

                    // Check if user is requesting a custom target
                    if (NewConnection.Header["Path"] != "/")
                    {
                        bool CanRelay = false;

                        // Extract the requested host and port
                        string[] HostAndPort = NewConnection.Header["Path"].Split('/');
                        if ((HostAndPort.Length == 3) && (int.TryParse(HostAndPort[2], out Port)))
                        {
                            Hostname = HostAndPort[1];
                            if (Config.Default.TargetHostname.ToLower().Trim() == Hostname.ToLower().Trim())
                            {
                                // User is requesting the target defined by the proxy admin, so check if it's to an allowed port
                                CanRelay = ((Port > 0) && (Port == Config.Default.TargetPort) || (Port == Config.Default.RLoginPort));
                            }
                            else if (!string.IsNullOrEmpty(Config.Default.RelayFilename))
                            {
                                // proxy admin has relaying enabled, so check against the relay.cfg file
                                try {
                                    // Read relay file
                                    if (File.Exists(Config.Default.RelayFilename))
                                    {
                                        string[] AllowedHosts = File.ReadAllLines(Config.Default.RelayFilename);
                                        if (AllowedHosts.Length > 0)
                                        {
                                            // Check for a whitelisted port
                                            string[] AllowedPorts = AllowedHosts[0].Split(',');
                                            foreach (string AllowedPort in AllowedPorts)
                                            {
                                                if (AllowedPort == Port.ToString())
                                                {
                                                    CanRelay = true;
                                                    break;
                                                }
                                            }

                                            // Not a whitelisted port, check for a whitelisted host
                                            if (!CanRelay)
                                            {
                                                string RequestedHostPort = Hostname.ToLower() + ":" + Port.ToString();
                                                foreach (string AllowedHost in AllowedHosts)
                                                {
                                                    if (AllowedHost.Trim().ToLower() == RequestedHostPort)
                                                    {
                                                        CanRelay = true;
                                                        break;
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            RMLog.Error("{" + _ConnectionId.ToString() + "} Relay file is empty: '" + Config.Default.RelayFilename + "'");
                                        }
                                    }
                                    else
                                    {
                                        RMLog.Error("{" + _ConnectionId.ToString() + "} Relay file does not exist: '" + Config.Default.RelayFilename + "'");
                                    }
                                } catch (Exception ex) {
                                    RMLog.Exception(ex, "{" + _ConnectionId.ToString() + "} Error reading relay file: '" + Config.Default.RelayFilename + "'");
                                }
                            }
                        }

                        if (!CanRelay)
                        {
                            RMLog.Info("{" + _ConnectionId.ToString() + "} Rejecting request for " + Hostname + ":" + Port.ToString());
                            NewConnection.WriteLn("Sorry, for security reasons this proxy won't connect to " + Hostname + ":" + Port.ToString());
                            Thread.Sleep(2500);
                            return;
                        }
                    }

                    // Try to connect to the desired Host and Port
                    NewConnection.Write(Ansi.ClrScr() + "Connecting to " + Hostname + ":" + Port.ToString() + "...");
                    using (TcpConnection _TcpConnection = new TcpConnection()) {
                        if (_TcpConnection.Connect(Hostname, Port))
                        {
                            RMLog.Info("{" + _ConnectionId.ToString() + "} Connected to " + Hostname + ":" + Port.ToString());
                            NewConnection.WriteLn("connected!");

                            // Repeatedly move data around until a connection is closed (or a stop is requested)
                            bool DoSleep = true;
                            while (!_Stop && NewConnection.Connected && _TcpConnection.Connected)
                            {
                                DoSleep = true;

                                if (NewConnection.CanRead())
                                {
                                    _TcpConnection.WriteBytes(NewConnection.ReadBytes());
                                    DoSleep = false;
                                }

                                if (_TcpConnection.CanRead())
                                {
                                    NewConnection.WriteBytes(_TcpConnection.ReadBytes());
                                    DoSleep = false;
                                }

                                if (DoSleep)
                                {
                                    Thread.Sleep(1);
                                }
                            }

                            // Check why we exited the loop
                            if (_Stop)
                            {
                                RMLog.Info("{" + _ConnectionId.ToString() + "} Stop requested");
                                NewConnection.Write(Ansi.GotoXY(1, 1) + Ansi.CursorDown(255) + "\r\nProxy server shutting down...");
                                Thread.Sleep(2500);
                            }
                            else if (!NewConnection.Connected)
                            {
                                RMLog.Info("{" + _ConnectionId.ToString() + "} Client closed connection");
                            }
                            else if (!_TcpConnection.Connected)
                            {
                                RMLog.Info("{" + _ConnectionId.ToString() + "} Server closed connection");
                                NewConnection.Write(Ansi.GotoXY(1, 1) + Ansi.CursorDown(255) + "\r\nServer closed connection...");
                                Thread.Sleep(2500);
                            }
                        }
                        else
                        {
                            RMLog.Info("{" + _ConnectionId.ToString() + "} Unable to connect to " + Hostname + ":" + Port.ToString());
                            NewConnection.WriteLn("unable to connect!");
                            Thread.Sleep(2500);
                        }
                    }
                }
            } catch (Exception ex) {
                RMLog.Exception(ex, "{" + _ConnectionId.ToString() + "} Exception in client thread");
            }
        }
Exemple #25
0
        // TODOY Consolidate with ParseEnvironmentVariables
        private void ParseCommandLineArgs()
        {
            string[] Args = Environment.GetCommandLineArgs();
            if (Args.Length > 1)
            {
                RMLog.Info("Overriding with settings from command-line");

                for (int i = 1; i < Args.Length; i++)
                {
                    string Arg = Args[i].TrimStart('/').TrimStart('-');
                    switch (Arg)
                    {
                    case "c":
                    case "cert":
                        i += 1;

                        // If file doesn't exist, and it's relative, convert to absolute
                        if (!File.Exists(Args[i]) && !Path.IsPathRooted(Args[i]))
                        {
                            Args[i] = StringUtils.PathCombine(ProcessUtils.StartupPath, Args[i]);
                        }

                        if (File.Exists(Args[i]))
                        {
                            Config.Default.CertificateFilename = Args[i];
                            RMLog.Info("-Cert file......" + Config.Default.CertificateFilename);
                        }
                        else
                        {
                            RMLog.Error("-Cert file not found: '" + Args[i] + "'");
                        }
                        break;

                    case "?":
                    case "h":
                    case "help":
                        ShowHelp();
                        return;

                    case "l":
                    case "loglevel":
                        i += 1;
                        try {
                            RMLog.Level = (LogLevel)Enum.Parse(typeof(LogLevel), Args[i]);
                            RMLog.Info("-Log level......" + RMLog.Level.ToString());
                        } catch (Exception ex) {
                            RMLog.Exception(ex, "-Invalid log level: '" + Args[i] + "'");
                        }
                        break;

                    case "p":
                    case "port":
                        i += 1;
                        try {
                            Config.Default.ListenPort = Convert.ToInt16(Args[i]);
                            RMLog.Info("-Listen port...." + Config.Default.ListenPort.ToString());
                        } catch (Exception ex) {
                            RMLog.Exception(ex, "-Invalid port: '" + Args[i] + "'");
                        }
                        break;

                    case "pw":
                    case "password":
                        i += 1;
                        Config.Default.CertificatePassword = Args[i];
                        RMLog.Info("-Cert password..yes (hidden)");
                        break;

                    case "r":
                    case "relay":
                        i += 1;

                        // If file doesn't exist, and it's relative, convert to absolute
                        if (!File.Exists(Args[i]) && !Path.IsPathRooted(Args[i]))
                        {
                            Args[i] = StringUtils.PathCombine(ProcessUtils.StartupPath, Args[i]);
                        }

                        if (File.Exists(Args[i]))
                        {
                            Config.Default.RelayFilename = Args[i];
                            RMLog.Info("-Relay file....." + Config.Default.RelayFilename);
                        }
                        else
                        {
                            Config.Default.RelayFilename = "";
                            RMLog.Error("-Relay file not found: '" + Args[i] + "'");
                        }
                        break;

                    case "rp":
                    case "rlogin-port":
                        i += 1;
                        try {
                            Config.Default.RLoginPort = Convert.ToInt16(Args[i]);
                            if (Config.Default.RLoginPort > 0)
                            {
                                // TODOX If -rp is specified before -t, then this will display the wrong hostname
                                RMLog.Info("-RLogin target.." + Config.Default.TargetHostname + ":" + Config.Default.RLoginPort.ToString());
                            }
                            else
                            {
                                RMLog.Info("-RLogin target..DISABLED");
                            }
                        } catch (Exception ex) {
                            RMLog.Exception(ex, "-Invalid port: '" + Args[i] + "'");
                        }
                        break;

                    case "t":
                    case "target":
                        i += 1;
                        string TargetHostname = Config.Default.TargetHostname;
                        int    TargetPort     = Config.Default.TargetPort;
                        WebUtils.ParseHostPort(Args[i], ref TargetHostname, ref TargetPort);
                        Config.Default.TargetHostname = TargetHostname;
                        Config.Default.TargetPort     = TargetPort;
                        if (Config.Default.TargetPort > 0)
                        {
                            RMLog.Info("-Telnet target.." + Config.Default.TargetHostname + ":" + Config.Default.TargetPort.ToString());
                        }
                        else
                        {
                            RMLog.Info("-Telnet target..DISABLED");
                        }
                        break;

                    default:
                        RMLog.Error("-Unknown parameter: '" + Args[i] + "'");
                        break;
                    }
                }
            }
        }
Exemple #26
0
        // TODOY Consolidate with ParseCommandLine
        private void ParseEnvironmentVariables()
        {
            var EnvironmentVariables = Environment.GetEnvironmentVariables().Cast <DictionaryEntry>().Where(x => x.Key.ToString().ToLower().StartsWith("ftelnet_")).ToArray();

            if (EnvironmentVariables.Length > 0)
            {
                RMLog.Info("Overriding with settings from environment variables");

                for (int i = 0; i < EnvironmentVariables.Length; i++)
                {
                    string Arg   = EnvironmentVariables[i].Key.ToString().Substring(8).ToLower().Replace('_', '-'); // Substring off the leading ftelnet_ and replace _ with -
                    string Value = EnvironmentVariables[i].Value.ToString();

                    switch (Arg)
                    {
                    case "c":
                    case "cert":
                        // If file doesn't exist, and it's relative, convert to absolute
                        if (!File.Exists(Value) && !Path.IsPathRooted(Value))
                        {
                            Value = StringUtils.PathCombine(ProcessUtils.StartupPath, Value);
                        }

                        if (File.Exists(Value))
                        {
                            Config.Default.CertificateFilename = Value;
                            RMLog.Info("-Cert file......" + Config.Default.CertificateFilename);
                        }
                        else
                        {
                            RMLog.Error("-Cert file not found: '" + Value + "'");
                        }
                        break;

                    case "l":
                    case "loglevel":
                        try {
                            RMLog.Level = (LogLevel)Enum.Parse(typeof(LogLevel), Value);
                            RMLog.Info("-Log level......" + RMLog.Level.ToString());
                        } catch (Exception ex) {
                            RMLog.Exception(ex, "-Invalid log level: '" + Value + "'");
                        }
                        break;

                    case "p":
                    case "port":
                        try {
                            Config.Default.ListenPort = Convert.ToInt16(Value);
                            RMLog.Info("-Listen port...." + Config.Default.ListenPort.ToString());
                        } catch (Exception ex) {
                            RMLog.Exception(ex, "-Invalid port: '" + Value + "'");
                        }
                        break;

                    case "pw":
                    case "password":
                        Config.Default.CertificatePassword = Value;
                        RMLog.Info("-Cert password..yes (hidden)");
                        break;

                    case "r":
                    case "relay":
                        // If file doesn't exist, and it's relative, convert to absolute
                        if (!File.Exists(Value) && !Path.IsPathRooted(Value))
                        {
                            Value = StringUtils.PathCombine(ProcessUtils.StartupPath, Value);
                        }

                        if (File.Exists(Value))
                        {
                            Config.Default.RelayFilename = Value;
                            RMLog.Info("-Relay file....." + Config.Default.RelayFilename);
                        }
                        else
                        {
                            Config.Default.RelayFilename = "";
                            RMLog.Error("-Relay file not found: '" + Value + "'");
                        }
                        break;

                    case "rp":
                    case "rlogin-port":
                        try {
                            Config.Default.RLoginPort = Convert.ToInt16(Value);
                            if (Config.Default.RLoginPort > 0)
                            {
                                // TODOX If -rp is specified before -t, then this will display the wrong hostname
                                RMLog.Info("-RLogin target.." + Config.Default.TargetHostname + ":" + Config.Default.RLoginPort.ToString());
                            }
                            else
                            {
                                RMLog.Info("-RLogin target..DISABLED");
                            }
                        } catch (Exception ex) {
                            RMLog.Exception(ex, "-Invalid port: '" + Value + "'");
                        }
                        break;

                    case "t":
                    case "target":
                        string TargetHostname = Config.Default.TargetHostname;
                        int    TargetPort     = Config.Default.TargetPort;
                        WebUtils.ParseHostPort(Value, ref TargetHostname, ref TargetPort);
                        Config.Default.TargetHostname = TargetHostname;
                        Config.Default.TargetPort     = TargetPort;
                        if (Config.Default.TargetPort > 0)
                        {
                            RMLog.Info("-Telnet target.." + Config.Default.TargetHostname + ":" + Config.Default.TargetPort.ToString());
                        }
                        else
                        {
                            RMLog.Info("-Telnet target..DISABLED");
                        }
                        break;

                    default:
                        RMLog.Error("-Unknown parameter: '" + Arg + "'");
                        break;
                    }
                }
            }
        }