# < Summary

Information

Class: | Renci.SshNet.NetConf.NetConfSession
Assembly: | Renci.SshNet
File(s): | \home\appveyor\projects\ssh-net\src\Renci.SshNet\Netconf\NetConfSession.cs

Line coverage
0%

Covered lines: | 0
Uncovered lines: | 128
Coverable lines: | 128
Total lines: | 205
Line coverage: | 0%

Branch coverage
0%

Covered branches: | 0
Total branches: | 28
Branch coverage: | 0%

Method coverage

Feature is only available for sponsors

Upgrade to PRO version

# Metrics

Method | Branch coverage | Cyclomatic complexity | Line coverage
--- | --- | --- | ---
.ctor(...) | 100% | 1 | 0%
get_ServerCapabilities() | 100% | 1 | 0%
get_ClientCapabilities() | 100% | 1 | 0%
SendReceiveRpc(...) | 0% | 8 | 0%
OnChannelOpen() | 100% | 1 | 0%
OnDataReceived(...) | 0% | 12 | 0%
Dispose(...) | 0% | 6 | 0%

# File(s)

## \home\appveyor\projects\ssh-net\src\Renci.SshNet\Netconf\NetConfSession.cs

| # | Line |  | Line coverage
--- | --- | --- | --- | ---
|  | `1` |  | `using System;`
|  | `2` |  | `using System.Globalization;`
|  | `3` |  | `using System.Text;`
|  | `4` |  | `using System.Text.RegularExpressions;`
|  | `5` |  | `using System.Threading;`
|  | `6` |  | `using System.Xml;`
|  | `7` |  | ``
|  | `8` |  | `using Renci.SshNet.Common;`
|  | `9` |  | ``
|  | `10` |  | `namespace Renci.SshNet.NetConf`
|  | `11` |  | `{`
|  | `12` |  | `internal sealed class NetConfSession : SubsystemSession, INetConfSession`
|  | `13` |  | `{`
|  | `14` |  | `private const string Prompt = "]]>]]>";`
|  | `15` |  | ``
| 0 | `16` |  | `private readonly StringBuilder _data = new StringBuilder();`
|  | `17` |  | `private bool _usingFramingProtocol;`
| 0 | `18` |  | `private EventWaitHandle _serverCapabilitiesConfirmed = new AutoResetEvent(initialState: false);`
| 0 | `19` |  | `private EventWaitHandle _rpcReplyReceived = new AutoResetEvent(initialState: false);`
| 0 | `20` |  | `private StringBuilder _rpcReply = new StringBuilder();`
|  | `21` |  | `private int _messageId;`
|  | `22` |  | ``
|  | `23` |  | `/// <summary>`
|  | `24` |  | `/// Gets NetConf server capabilities.`
|  | `25` |  | `/// </summary>`
| 0 | `26` |  | `public XmlDocument ServerCapabilities { get; private set; }`
|  | `27` |  | ``
|  | `28` |  | `/// <summary>`
|  | `29` |  | `/// Gets NetConf client capabilities.`
|  | `30` |  | `/// </summary>`
| 0 | `31` |  | `public XmlDocument ClientCapabilities { get; private set; }`
|  | `32` |  | ``
|  | `33` |  | `/// <summary>`
|  | `34` |  | `/// Initializes a new instance of the <see cref="NetConfSession"/> class.`
|  | `35` |  | `/// </summary>`
|  | `36` |  | `/// <param name="session">The session.</param>`
|  | `37` |  | `/// <param name="operationTimeout">The number of milliseconds to wait for an operation to complete, or -1 to wai`
|  | `38` |  | `public NetConfSession(ISession session, int operationTimeout)`
| 0 | `39` |  | `: base(session, "netconf", operationTimeout)`
| 0 | `40` |  | `{`
| 0 | `41` |  | `ClientCapabilities = new XmlDocument();`
| 0 | `42` |  | `ClientCapabilities.LoadXml("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +`
| 0 | `43` |  | `"<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">" +`
| 0 | `44` |  | `"<capabilities>" +`
| 0 | `45` |  | `"<capability>" +`
| 0 | `46` |  | `"urn:ietf:params:netconf:base:1.0" +`
| 0 | `47` |  | `"</capability>" +`
| 0 | `48` |  | `"</capabilities>" +`
| 0 | `49` |  | `"</hello>");`
| 0 | `50` |  | `}`
|  | `51` |  | ``
|  | `52` |  | `public XmlDocument SendReceiveRpc(XmlDocument rpc, bool automaticMessageIdHandling)`
| 0 | `53` |  | `{`
| 0 | `54` |  | `_ = _data.Clear();`
|  | `55` |  | ``
| 0 | `56` |  | `XmlNamespaceManager nsMgr = null;`
| 0 | `57` |  | `if (automaticMessageIdHandling)`
| 0 | `58` |  | `{`
| 0 | `59` |  | `_messageId++;`
| 0 | `60` |  | `nsMgr = new XmlNamespaceManager(rpc.NameTable);`
| 0 | `61` |  | `nsMgr.AddNamespace("nc", "urn:ietf:params:xml:ns:netconf:base:1.0");`
| 0 | `62` |  | `rpc.SelectSingleNode("/nc:rpc/@message-id", nsMgr).Value = _messageId.ToString(CultureInfo.InvariantCult`
| 0 | `63` |  | `}`
|  | `64` |  | ``
| 0 | `65` |  | `_rpcReply = new StringBuilder();`
| 0 | `66` |  | `_ = _rpcReplyReceived.Reset();`
| 0 | `67` |  | `var reply = new XmlDocument();`
| 0 | `68` |  | `if (_usingFramingProtocol)`
| 0 | `69` |  | `{`
| 0 | `70` |  | `var command = new StringBuilder(rpc.InnerXml.Length + 10);`
| 0 | `71` |  | `_ = command.AppendFormat(CultureInfo.InvariantCulture, "\n#{0}\n", rpc.InnerXml.Length);`
| 0 | `72` |  | `_ = command.Append(rpc.InnerXml);`
| 0 | `73` |  | `_ = command.Append("\n##\n");`
| 0 | `74` |  | `SendData(Encoding.UTF8.GetBytes(command.ToString()));`
|  | `75` |  | ``
| 0 | `76` |  | `WaitOnHandle(_rpcReplyReceived, OperationTimeout);`
| 0 | `77` |  | `reply.LoadXml(_rpcReply.ToString());`
| 0 | `78` |  | `}`
|  | `79` |  | `else`
| 0 | `80` |  | `{`
| 0 | `81` |  | `SendData(Encoding.UTF8.GetBytes(rpc.InnerXml + Prompt));`
| 0 | `82` |  | `WaitOnHandle(_rpcReplyReceived, OperationTimeout);`
| 0 | `83` |  | `reply.LoadXml(_rpcReply.ToString());`
| 0 | `84` |  | `}`
|  | `85` |  | ``
| 0 | `86` |  | `if (automaticMessageIdHandling)`
| 0 | `87` |  | `{`
| 0 | `88` |  | `var replyId = rpc.SelectSingleNode("/nc:rpc/@message-id", nsMgr).Value;`
| 0 | `89` |  | `if (replyId != _messageId.ToString(CultureInfo.InvariantCulture))`
| 0 | `90` |  | `{`
| 0 | `91` |  | `throw new NetConfServerException("The rpc message id does not match the rpc-reply message id.");`
|  | `92` |  | `}`
| 0 | `93` |  | `}`
|  | `94` |  | ``
| 0 | `95` |  | `return reply;`
| 0 | `96` |  | `}`
|  | `97` |  | ``
|  | `98` |  | `protected override void OnChannelOpen()`
| 0 | `99` |  | `{`
| 0 | `100` |  | `_ = _data.Clear();`
|  | `101` |  | ``
| 0 | `102` |  | `var message = string.Concat(ClientCapabilities.InnerXml, Prompt);`
|  | `103` |  | ``
| 0 | `104` |  | `SendData(Encoding.UTF8.GetBytes(message));`
|  | `105` |  | ``
| 0 | `106` |  | `WaitOnHandle(_serverCapabilitiesConfirmed, OperationTimeout);`
| 0 | `107` |  | `}`
|  | `108` |  | ``
|  | `109` |  | `protected override void OnDataReceived(byte[] data)`
| 0 | `110` |  | `{`
| 0 | `111` |  | `var chunk = Encoding.UTF8.GetString(data);`
|  | `112` |  | ``
| 0 | `113` |  | `if (ServerCapabilities is null)`
| 0 | `114` |  | `{`
| 0 | `115` |  | `_ = _data.Append(chunk);`
|  | `116` |  | ``
| 0 | `117` |  | `if (!chunk.Contains(Prompt))`
| 0 | `118` |  | `{`
| 0 | `119` |  | `return;`
|  | `120` |  | `}`
|  | `121` |  | ``
|  | `122` |  | `try`
| 0 | `123` |  | `{`
| 0 | `124` |  | `chunk = _data.ToString();`
| 0 | `125` |  | `_ = _data.Clear();`
|  | `126` |  | ``
| 0 | `127` |  | `ServerCapabilities = new XmlDocument();`
| 0 | `128` |  | `ServerCapabilities.LoadXml(chunk.Replace(Prompt, string.Empty));`
| 0 | `129` |  | `}`
| 0 | `130` |  | `catch (XmlException e)`
| 0 | `131` |  | `{`
| 0 | `132` |  | `throw new NetConfServerException("Server capabilities received are not well formed XML", e);`
|  | `133` |  | `}`
|  | `134` |  | ``
| 0 | `135` |  | `var nsMgr = new XmlNamespaceManager(ServerCapabilities.NameTable);`
| 0 | `136` |  | `nsMgr.AddNamespace("nc", "urn:ietf:params:xml:ns:netconf:base:1.0");`
|  | `137` |  | ``
| 0 | `138` |  | `_usingFramingProtocol = ServerCapabilities.SelectSingleNode("/nc:hello/nc:capabilities/nc:capability[tex`
|  | `139` |  | ``
| 0 | `140` |  | `_ = _serverCapabilitiesConfirmed.Set();`
| 0 | `141` |  | `}`
| 0 | `142` |  | `else if (_usingFramingProtocol)`
| 0 | `143` |  | `{`
| 0 | `144` |  | `var position = 0;`
|  | `145` |  | ``
|  | `146` |  | `for (; ; )`
| 0 | `147` |  | `{`
| 0 | `148` |  | `var match = Regex.Match(chunk.Substring(position), @"\n#(?<length>\d+)\n");`
| 0 | `149` |  | `if (!match.Success)`
| 0 | `150` |  | `{`
| 0 | `151` |  | `break;`
|  | `152` |  | `}`
|  | `153` |  | ``
| 0 | `154` |  | `var fractionLength = Convert.ToInt32(match.Groups["length"].Value, CultureInfo.InvariantCulture);`
| 0 | `155` |  | `_ = _rpcReply.Append(chunk, position + match.Index + match.Length, fractionLength);`
| 0 | `156` |  | `position += match.Index + match.Length + fractionLength;`
| 0 | `157` |  | `}`
|  | `158` |  | ``
|  | `159` |  | `#if NET7_0_OR_GREATER`
| 0 | `160` |  | `if (Regex.IsMatch(chunk.AsSpan(position), @"\n##\n"))`
|  | `161` |  | `#else`
| 0 | `162` |  | `if (Regex.IsMatch(chunk.Substring(position), @"\n##\n"))`
|  | `163` |  | `#endif // NET7_0_OR_GREATER`
| 0 | `164` |  | `{`
| 0 | `165` |  | `_ = _rpcReplyReceived.Set();`
| 0 | `166` |  | `}`
| 0 | `167` |  | `}`
|  | `168` |  | `else`
| 0 | `169` |  | `{`
| 0 | `170` |  | `_ = _data.Append(chunk);`
|  | `171` |  | ``
| 0 | `172` |  | `if (!chunk.Contains(Prompt))`
| 0 | `173` |  | `{`
| 0 | `174` |  | `return;`
|  | `175` |  | `}`
|  | `176` |  | ``
| 0 | `177` |  | `chunk = _data.ToString();`
| 0 | `178` |  | `_ = _data.Clear();`
|  | `179` |  | ``
| 0 | `180` |  | `_ = _rpcReply.Append(chunk.Replace(Prompt, string.Empty));`
| 0 | `181` |  | `_ = _rpcReplyReceived.Set();`
| 0 | `182` |  | `}`
| 0 | `183` |  | `}`
|  | `184` |  | ``
|  | `185` |  | `protected override void Dispose(bool disposing)`
| 0 | `186` |  | `{`
| 0 | `187` |  | `base.Dispose(disposing);`
|  | `188` |  | ``
| 0 | `189` |  | `if (disposing)`
| 0 | `190` |  | `{`
| 0 | `191` |  | `if (_serverCapabilitiesConfirmed != null)`
| 0 | `192` |  | `{`
| 0 | `193` |  | `_serverCapabilitiesConfirmed.Dispose();`
| 0 | `194` |  | `_serverCapabilitiesConfirmed = null;`
| 0 | `195` |  | `}`
|  | `196` |  | ``
| 0 | `197` |  | `if (_rpcReplyReceived != null)`
| 0 | `198` |  | `{`
| 0 | `199` |  | `_rpcReplyReceived.Dispose();`
| 0 | `200` |  | `_rpcReplyReceived = null;`
| 0 | `201` |  | `}`
| 0 | `202` |  | `}`
| 0 | `203` |  | `}`
|  | `204` |  | `}`
|  | `205` |  | `}`

# Methods/Properties

.ctor(Renci.SshNet.ISession,System.Int32)
get_ServerCapabilities()
get_ClientCapabilities()
SendReceiveRpc(System.Xml.XmlDocument,System.Boolean)
OnChannelOpen()
OnDataReceived(System.Byte[])
Dispose(System.Boolean)