public void Parse(INeighborRegistry registry, CancellationToken token)
        {
            if (_router?.Session == null || registry == null || !_router.Session.IsConnected())
            {
                throw new ArgumentException("Unable to parse STATIC routes, invalid parameters.");
            }
            try
            {
                _OperationStatusLabel = "Querying static routes...";
                string routes = _router.Session.ExecCommand("show route protocol static");
                token.ThrowIfCancellationRequested();
                MatchCollection knownNetworks = Regex.Matches(routes, @"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b\/\d{1,2}", RegexOptions.Compiled);
                if (knownNetworks.Count > 0)
                {
                    _OperationStatusLabel = "Processing static routes...";
                    // insert actual routes
                    for (int i = 0; i < knownNetworks.Count; i++)
                    {
                        string          thisNetwork           = knownNetworks[i].Value;
                        int             routeBlockStart       = knownNetworks[i].Index;
                        int             routeBlockEnd         = i == knownNetworks.Count - 1 ? routes.Length : knownNetworks[i + 1].Index;
                        string          thisRouteBlock        = routes.Substring(routeBlockStart, routeBlockEnd - routeBlockStart);
                        bool            isBestRoute           = thisRouteBlock.IndexOf("*[") > 0;
                        MatchCollection protocolBlocksHeaders = Regex.Matches(thisRouteBlock, @"\[(.*?)\]", RegexOptions.Compiled);
                        for (int j = 0; j < protocolBlocksHeaders.Count; j++)
                        {
                            try
                            {
                                string thisProtocolBlockHeader = protocolBlocksHeaders[j].Value;
                                int    protocolBlockStart      = protocolBlocksHeaders[j].Index;
                                int    protocolBlockEnd        = j == protocolBlocksHeaders.Count - 1 ? thisRouteBlock.Length : protocolBlocksHeaders[j + 1].Index;
                                string thisProtocolBlock       = thisRouteBlock.Substring(protocolBlockStart, protocolBlockEnd - protocolBlockStart);
                                string thisProtocolName        = Regex.Match(thisProtocolBlockHeader, @"[a-zA-Z]+", RegexOptions.Compiled)?.Value;
                                string nextHopAddress          = Regex.Match(thisProtocolBlock, @"(?<=to )[\d\.]{0,99}", RegexOptions.Compiled)?.Value;
                                string nextHopViaInterfaceName = Regex.Match(thisProtocolBlock, @"(?<=via ).*", RegexOptions.Compiled)?.Value?.Trim('\r');

                                _OperationStatusLabel = string.Format("Querying router interface {0}...", nextHopViaInterfaceName);
                                RouterInterface ri = _router.GetInterfaceByName(nextHopViaInterfaceName);
                                _OperationStatusLabel = string.Format("Registering STATIC neighbor {0}...", nextHopAddress);
                                registry.RegisterSTATICNeighbor(_router, thisNetwork, nextHopAddress, ri.Address, ri);
                            }
                            catch (Exception Ex)
                            {
                                DebugEx.WriteLine("Jumos_STATICParser error : " + Ex.Message);
                            }
                        }
                    }
                }
                _OperationStatusLabel = "JunOS STATIC route parser completed.";
            }
            catch (Exception Ex)
            {
                _OperationStatusLabel = "JunOS STATIC route parser failed with error : " + Ex.Message;
            }
        }
        public void Parse(INeighborRegistry registry, CancellationToken token)
        {
            if (_router?.Session == null || !_router.Session.IsConnected())
            {
                throw new ArgumentException("Unable to parse OSPF. Either thisRouter or Session parameter is invalid");
            }
            try
            {
                _OperationStatusLabel = "Querying OSPF neighbors...";
                string TextToParse = _router.Session.ExecCommand("show ip ospf neighbor");
                _OperationStatusLabel = "Querying OSPF interfaces...";
                string ospfInterfaces = _router.Session.ExecCommand("show ip ospf interface brief");
                _OperationStatusLabel = "Processing OSPF data...";
                token.ThrowIfCancellationRequested();
                string[] ospf_lines          = TextToParse.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                string   neighborRouterID    = "";
                string   neighborState       = "";
                string   remoteNeighboringIP = "";
                string   description         = "";

                foreach (string line in ospf_lines.Select(l => l.Trim()))
                {
                    neighborRouterID    = "";
                    neighborState       = "";
                    remoteNeighboringIP = "";
                    description         = "";
                    DebugEx.WriteLine(String.Format("CISCO_IOS_OSPF_PARSER : parsing OSPF neighbor row [ {0} ]", line), DebugLevel.Full);
                    token.ThrowIfCancellationRequested();
                    try
                    {
                        string[] words = line.SplitBySpace();
                        if (words.Length < 4)
                        {
                            continue;
                        }
                        // Words should look like:
                        // Neighbor ID,Pri,State,Dead Time,Address,Interface
                        // 172.20.0.255,128,FULL/BDR,00:00:34,172.20.0.14,TenGigabitEthernet0/1/0
                        var MatchedIPs = Regex.Matches(line, @"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}");
                        // we expect two ip addresses in the line, first is the Neighbor router ID, second is Neighboring IP address
                        if (MatchedIPs.Count == 2 && System.Net.IPAddress.TryParse(MatchedIPs[0].Value, out IPAddress nID) && System.Net.IPAddress.TryParse(MatchedIPs[1].Value, out IPAddress nIP))
                        {
                            // This is a new peer, initialize variables
                            string ifName = words[words.Length - 1];                             // last work is the interface name
                            _OperationStatusLabel = string.Format("Querying router interface {0}...", ifName);
                            RouterInterface ri = _router.GetInterfaceByName(ifName);
                            if (ri != null)
                            {
                                // add OSPF Area info to RouterInterface
                                if (ospfInterfaces != "")
                                {
                                    string ospfIntfLine = ospfInterfaces.SplitByLine().FirstOrDefault(l => l.Trim().StartsWith(ri.Name));
                                    if (!string.IsNullOrEmpty(ospfIntfLine))
                                    {
                                        string[] w = ospfIntfLine.SplitBySpace();
                                        //Interface    PID   Area            IP Address/Mask    Cost  State Nbrs F/C
                                        //Te0/1/0      100   172.20.0.0      172.20.0.1/28      1     DR    1/1
                                        ri.OSPFArea = w[2];
                                    }
                                }
                                neighborRouterID      = nID.ToString();
                                remoteNeighboringIP   = nIP.ToString();
                                neighborState         = words[2];
                                description           = "";
                                _OperationStatusLabel = string.Format("Registering OSPF neighbor {0}...", neighborRouterID);
                                registry.RegisterNeighbor(_router, RoutingProtocol.OSPF, neighborRouterID, "", description, remoteNeighboringIP, ri, neighborState);
                            }
                        }
                    }
                    catch (OperationCanceledException)
                    {
                        throw;
                    }
                    catch (Exception Ex)
                    {
                        string msg = String.Format("Cisco IOS OSPF Protocol Parser : Error while parsing ospf output line [{0}]. Error is : {1}", line, Ex.InnerExceptionsMessage());
                        DebugEx.WriteLine(msg);
                        _OperationStatusLabel = msg;
                    }
                }
                _OperationStatusLabel = "Cisco IOS OSPF Protocol Parser completed.";
            }
            catch (Exception Ex)
            {
                _OperationStatusLabel = "Cisco IOS OSPF Protocol Parser failed with error : " + Ex.Message;
            }
        }
        public void Parse(INeighborRegistry registry, CancellationToken token)
        {
            if (_router?.Session == null || !_router.Session.IsConnected())
            {
                throw new ArgumentException("Unable to parse OSPF. Either thisRouter or Session parameter is invalid");
            }
            try
            {
                _OperationStatusLabel = "Querying OSPF neighbors...";
                string TextToParse = _router.Session.ExecCommand("show ospf neighbor");
                _OperationStatusLabel = "Querying OSPF interfaces...";
                string ospfInterfaces = _router.Session.ExecCommand("show ospf interface");
                _OperationStatusLabel = "Processing OSPF data...";
                token.ThrowIfCancellationRequested();
                string[] ospf_lines          = TextToParse.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                string   neighborRouterID    = "";
                string   neighborState       = "";
                string   remoteNeighboringIP = "";
                string   description         = "";

                foreach (string line in ospf_lines.Select(l => l.Trim()))
                {
                    neighborRouterID    = "";
                    neighborState       = "";
                    remoteNeighboringIP = "";
                    description         = "";
                    DebugEx.WriteLine(String.Format("JUNOS_OSPF_PARSER : parsing OSPF neighbor row [ {0} ]", line), DebugLevel.Full);
                    token.ThrowIfCancellationRequested();
                    try
                    {
                        string[] words = line.SplitBySpace();
                        if (words.Length < 4)
                        {
                            continue;                                           // this line is something else
                        }
                        // Words should be:
                        // Address,Interface,State,ID,Pri,Dead
                        // 10.0.0.241,ae0.0,Full,10.0.0.254,128,34
                        neighborState = words[2];
                        IPAddress nIP;
                        IPAddress nID;
                        if (System.Net.IPAddress.TryParse(words[0], out nIP) && System.Net.IPAddress.TryParse(words[3], out nID))
                        {
                            // This is a new peer, initialize variables
                            _OperationStatusLabel = string.Format("Querying router interface {0}...", words[1]);
                            RouterInterface ri = _router.GetInterfaceByName(words[1]);
                            if (ri != null)
                            {
                                // add OSPF Area info to RouterInterface
                                if (ospfInterfaces != "")
                                {
                                    string ospfIntfLine = ospfInterfaces.SplitByLine().FirstOrDefault(l => l.Trim().StartsWith(ri.Name));
                                    if (!string.IsNullOrEmpty(ospfIntfLine))
                                    {
                                        string[] w = ospfIntfLine.SplitBySpace();
                                        // words array header  : Interface,State,Area,DR ID,BDR ID,Nbrs
                                        // words should be like: lo0.0,DRother,0.0.0.0,0.0.0.0,0.0.0.0,0
                                        ri.OSPFArea = w[2];
                                    }
                                }
                                neighborRouterID      = nID.ToString();
                                remoteNeighboringIP   = nIP.ToString();
                                description           = "";
                                _OperationStatusLabel = string.Format("Registering OSPF neighbor {0}...", neighborRouterID);
                                registry.RegisterNeighbor(_router, RoutingProtocol.OSPF, neighborRouterID, "", description, remoteNeighboringIP, ri, neighborState);
                            }
                        }
                    }
                    catch (OperationCanceledException)
                    {
                        throw;
                    }
                    catch (Exception Ex)
                    {
                        string msg = String.Format("OSPFarser : Error while parsing ospf output line [{0}]. Error is : {1}", line, Ex.InnerExceptionsMessage());
                        DebugEx.WriteLine(msg);
                        _OperationStatusLabel = msg;
                    }
                }
                _OperationStatusLabel = "JunOS OSPF route parser completed.";
            }
            catch (Exception Ex)
            {
                _OperationStatusLabel = "JunOS OSPF parser failed with error : " + Ex.Message;
            }
        }
        public void RegisterNHRP(INeighborRegistry registry)
        {
            try
            {
                string   vrrpSummary      = _session.ExecCommand("show vrrp summary");
                string[] vrrpSummaryLines = vrrpSummary.SplitByLine();
                //
                // Sample input for parsing
                //
                //Interface State       Group VR state VR Mode Type   Address
                //irb.2100  up          210   master Active    lcl    10.37.24.2
                //																						 vip    10.37.24.1
                //irb.2200  up          220   master Active    lcl    10.37.26.2
                //																						 vip    10.37.26.1


                string          VIPAddress  = "";
                string          GroupID     = "";
                string          PeerAddress = "";
                bool            isActive    = false;
                RouterInterface ri          = null;
                foreach (string thisLine in vrrpSummaryLines)
                {
                    if (thisLine.IndentLevel() == 0)
                    {
                        // interface definition is changing
                        if (GroupID != "" && VIPAddress != "")
                        {
                            registry.RegisterNHRPPeer(this, ri, NHRPProtocol.VRRP, isActive, VIPAddress, GroupID, PeerAddress);
                            VIPAddress  = "";
                            GroupID     = "";
                            PeerAddress = "";
                            ri          = null;
                        }
                        //
                        string[] words  = thisLine.SplitBySpace();
                        string   ifName = words[0];
                        isActive = thisLine.ToLowerInvariant().Contains("master");
                        ri       = GetInterfaceByName(ifName);
                        GroupID  = words[2];
                        continue;
                    }
                    if (ri != null)
                    {
                        string[] words = thisLine.SplitBySpace();
                        if (words.Length == 2)
                        {
                            switch (words[0])
                            {
                            case "lcl": break;

                            case "mas": PeerAddress = words[1]; break;

                            case "vip": VIPAddress = words[1]; break;
                            }
                        }
                    }
                }
                // register the last one
                if (ri != null && VIPAddress != "" && GroupID != "")
                {
                    registry.RegisterNHRPPeer(this, ri, NHRPProtocol.VRRP, isActive, VIPAddress, GroupID, PeerAddress);
                }
            }
            catch (Exception Ex)
            {
                string msg = string.Format("CiscoIOSRouter says : error processing NHRP interfaces : {0}", Ex.Message);
                DebugEx.WriteLine(msg);
            }
        }
        public void Parse(INeighborRegistry registry, CancellationToken token)
        {
            if (_router?.Session == null || !_router.Session.IsConnected())
            {
                throw new ArgumentException("Unable to parse BGP. Either thisRouter or Session parameter is invalid");
            }
            else
            {
                try
                {
                    _OperationStatusLabel = "Querying bgp neighbors...";
                    string bgpNeighbors = _router.Session.ExecCommand("show bgp neighbor");
                    token.ThrowIfCancellationRequested();
                    string[] bgp_lines           = bgpNeighbors.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                    string   peerRouterID        = "";
                    string   localNeighboringIP  = "";
                    string   remoteNeighboringIP = "";
                    string   remoteAS            = "";
                    string   description         = "";
                    string   neighborState       = "";
                    bool     sessionEstablished  = true;
                    bool     skipRestOfLines     = false;
                    string   localInterfaceName  = "";
                    BGPType  _bgpType            = BGPType.undetermined;


                    foreach (string line in bgp_lines.Select(l => l.Trim()))
                    {
                        DebugEx.WriteLine(String.Format("BGPParser : parsing BGP neighbor row [ {0} ]", line), DebugLevel.Full);
                        token.ThrowIfCancellationRequested();
                        try
                        {
                            #region Get description
                            if (line.StartsWith("Description:"))
                            {
                                string[] words = line.Split(":".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                                description = words[1];
                                continue;
                            }
                            #endregion

                            #region Check for Peer line
                            if (line.StartsWith("Peer:"))
                            {
                                // This is a new peer, initialize variables
                                peerRouterID        = "";
                                localNeighboringIP  = "";
                                remoteNeighboringIP = "";
                                remoteAS            = "";
                                description         = "";
                                neighborState       = "";
                                sessionEstablished  = true;
                                skipRestOfLines     = false;
                                localInterfaceName  = "";
                                // Get local address
                                Match m = Regex.Match(line, @"(?<=Local: )[\d.]{0,99}", RegexOptions.Compiled);
                                if (m.Success)
                                {
                                    localNeighboringIP = m.Value;
                                }
                                // Get peer address
                                m = Regex.Match(line, @"(?<=Peer: )[\d.]{0,99}", RegexOptions.Compiled);
                                if (m.Success)
                                {
                                    remoteNeighboringIP = m.Value;
                                }
                                // Get AS Numbers
                                var ASes = Regex.Matches(line, @"(?<=AS )[\d.]{0,99}", RegexOptions.Compiled);
                                if (ASes.Count != 2)
                                {
                                    throw new InvalidOperationException("Cannot parse BGP output : unable to retrieve local and remote AS numbers.");
                                }
                                remoteAS = ASes[0].Value;
                                _OperationStatusLabel = string.Format("Processing neighbor {0} for AS {1}...", remoteNeighboringIP, remoteAS);
                                continue;
                            }
                            #endregion

                            if (skipRestOfLines)
                            {
                                continue;
                            }

                            #region Check for state
                            if (line.StartsWith("Type:") && line.Contains("State:"))
                            {
                                Match m = Regex.Match(line, @"(?<=State: )\w+", RegexOptions.Compiled);
                                if (m.Success)
                                {
                                    neighborState = m.Value;
                                }
                                sessionEstablished = neighborState.ToLowerInvariant() == "established";
                                m = Regex.Match(line, @"(?<=Type: )\w+", RegexOptions.Compiled);
                                if (m.Success)
                                {
                                    _bgpType = m.Value.ToLowerInvariant() == "internal" ? BGPType.iBGP : BGPType.eBGP;
                                }
                            }
                            #endregion

                            if (sessionEstablished)
                            {
                                #region Parse Remote router ID
                                if (line.StartsWith("Peer ID:"))
                                {
                                    // Get remote router ID
                                    Match m = Regex.Match(line, @"(?<=Peer ID: )[\d.]{0,99}", RegexOptions.Compiled);
                                    if (!m.Success)
                                    {
                                        throw new InvalidOperationException("Cannot parse BGP output : unable to retrieve peer router ID.");
                                    }
                                    peerRouterID = m.Value;
                                    DebugEx.WriteLine(String.Format("JunOSBGPParser : found a neighbor {0}AS{1} <-> {2}AS{3}", _router.RouterID(RoutingProtocol.BGP), _router.BGPAutonomousSystem, peerRouterID, remoteAS), DebugLevel.Informational);
                                    continue;
                                }
                                #endregion

                                #region Get local interface
                                if (localInterfaceName == "")
                                {
                                    switch (_bgpType)
                                    {
                                    case BGPType.eBGP:
                                    {
                                        if (line.StartsWith("Local Interface:"))
                                        {
                                            string[] words = line.Split(":".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                                            localInterfaceName = words[1];
                                            continue;
                                        }
                                        break;
                                    }

                                    case BGPType.iBGP:
                                    {
                                        // since JunOS does not show Local Interface for iBGP, we need to query it, if we know the local ip
                                        if (localNeighboringIP != "")
                                        {
                                            localInterfaceName = _router.GetInterfaceNameByIPAddress(localNeighboringIP);
                                        }
                                        break;
                                    }
                                    }
                                }
                                #endregion
                            }

                            if (sessionEstablished && (localInterfaceName == "" || peerRouterID == "" || remoteAS == "" || localNeighboringIP == "" || remoteNeighboringIP == ""))
                            {
                                continue;
                            }

                            // when the BGP session is not established we can't know the neighbor router ID, so name it after peering ip which should be unique anyway
                            // We also won't know the localInterface at this point, so we need to query it by ip address
                            if (!sessionEstablished)
                            {
                                peerRouterID = remoteNeighboringIP;
                                if (localNeighboringIP != "")
                                {
                                    localInterfaceName = _router.GetInterfaceNameByIPAddress(localNeighboringIP);
                                }
                            }
                            // search database for peer router, select it or add new neighbor
                            _OperationStatusLabel = string.Format("Querying router interface {0}...", localInterfaceName);
                            RouterInterface ri = _router.GetInterfaceByName(localInterfaceName);
                            _OperationStatusLabel = string.Format("Registering BGP neighbor {0}...", peerRouterID);
                            registry.RegisterNeighbor(_router, RoutingProtocol.BGP, peerRouterID, remoteAS, description, remoteNeighboringIP, ri, neighborState);
                            // now all is done for this peer, skip lines until next peer is found
                            skipRestOfLines = true;
                        }
                        catch (OperationCanceledException)
                        {
                            throw;
                        }
                        catch (InvalidOperationException)
                        {
                            throw;
                        }
                        catch (Exception Ex)
                        {
                            string msg = String.Format("JunOSBGPParser : Error while parsing bgp output line [{0}]. Error is : {1}", line, Ex.InnerExceptionsMessage());
                            DebugEx.WriteLine(msg);
                            _OperationStatusLabel = msg;
                        }
                    }

                    _OperationStatusLabel = "JunOS BGP route parser completed.";
                }
                catch (Exception Ex)
                {
                    _OperationStatusLabel = "JunoS BGP parser failed with error : " + Ex.Message;
                }
            }
        }