Exemple #1
0
        // NAT METHODS
        private static IceCandidate GatherNAActiveCandidate(IPAddress localIPAddress, IceCandidate baseCandidate)
        {
            // exactly the same procedure like GatherSRActiveCandidate()
            // derived from passive NAT assisted candidate

            IPEndPoint localEndpoint = new IPEndPoint(localIPAddress, 0);

            Socket activeConnectingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            // here is no bind, because active candidates don't have to be physically allocated here (allocation in connectivity checks)

            /*  RFC 6544 (ICE TCP), Section 3:
            In the case of active candidates, both IP
            address and port are present, but the port is meaningless (it is
            there only for making encoding of active candidates consistent with
            the other candidate types and is ignored by the peer).  As a
            consequence, active candidates do not need to be physically allocated
            at the time of address gathering.  Rather, the physical allocations,
            which occur as a consequence of a connection attempt, occur at the
            time of the connectivity checks.
             */

            // create candidate object
            IpAddressPort activeIpAddressPort = new IpAddressPort(AddressType.IPv4_Address, baseCandidate.addr_port.ipaddr, 0);         // port is meaningless
            IceCandidate activeCandidate = new IceCandidate(activeIpAddressPort, Overlay_Link.TLS_TCP_with_FH);
            activeCandidate.cand_type = CandType.tcp_nat;
            activeCandidate.rel_addr_port = new IpAddressPort(AddressType.IPv4_Address, localEndpoint.Address, 0);                      // port is meaningless
            activeCandidate.activeConnectingSocket = activeConnectingSocket;

            // TCP Type
            activeCandidate.tcpType = TcpType.Active;

            // TCP ICE extension
            IceExtension iceExtension = new IceExtension();
            iceExtension.name = Encoding.UTF8.GetBytes("tcptype");
            iceExtension.value = Encoding.UTF8.GetBytes("active");
            activeCandidate.extension_list.Add(iceExtension);

            return activeCandidate;
        }
Exemple #2
0
        private static IceCandidate GatherNAPassiveCandidate(IPAddress localIPAddress)
        {
            // local endpoint
            IPEndPoint localEndpoint = new IPEndPoint(localIPAddress, 0);

            // only one listening socket, because there is no need to use a STUN server. We get the IP and Port from the NAT using UPnP
            Socket passiveListeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            passiveListeningSocket.Bind(localEndpoint);

            // update localEndpoint with binded Port 
            localEndpoint = (IPEndPoint)passiveListeningSocket.LocalEndPoint;


            // check if UPnP is available
            UPnP upnp = new UPnP();
            bool foundUPnPDevice = false;

            try
            {
                foundUPnPDevice = upnp.Discover(localIPAddress);
            }
            catch (Exception e)
            {
                //Console.WriteLine(e.Message);
                return null;
            }


            // IPEndPoint for public mapping
            IPEndPoint publicMapping = null;

            // found UPnP internet gateway device?
            if (foundUPnPDevice)
            {
                // try to get public IP and to add a port mapping
                try
                {
                    string publicIP = upnp.GetExternalIP().ToString();

                    // we can use the local Port for the public NAT port mapping too
                    bool addedPortMapping = upnp.AddPortMapping((ushort)localEndpoint.Port, (ushort)localEndpoint.Port, ProtocolType.Tcp, "RELOAD ICE TCP Port mapping");

                    if (addedPortMapping && !string.IsNullOrEmpty(publicIP))
                    {
                        publicMapping = new IPEndPoint(IPAddress.Parse(publicIP), localEndpoint.Port);
                    }
                    else
                        return null;
                }

                catch (Exception e)
                {
                    //Console.WriteLine(e.Message);
                    return null;
                }
            }
            // no UPnP IGD found
            else
                return null;


            // got public mapping?
            if (publicMapping == null)
                return null;

            // save data in candidate object
            IpAddressPort passiveIpAddressPort = new IpAddressPort(AddressType.IPv4_Address, publicMapping.Address, (ushort)publicMapping.Port);
            IceCandidate passiveCandidate = new IceCandidate(passiveIpAddressPort, Overlay_Link.TLS_TCP_with_FH);
            passiveCandidate.cand_type = CandType.tcp_nat;
            passiveCandidate.rel_addr_port = new IpAddressPort(AddressType.IPv4_Address, localEndpoint.Address, (ushort)localEndpoint.Port);
            passiveCandidate.passiveListeningSocket = passiveListeningSocket;

            // TCP Type
            passiveCandidate.tcpType = TcpType.Passive;

            // TCP ICE extension
            IceExtension iceExtension = new IceExtension();
            iceExtension.name = Encoding.UTF8.GetBytes("tcptype");
            iceExtension.value = Encoding.UTF8.GetBytes("passive");
            passiveCandidate.extension_list.Add(iceExtension);


            return passiveCandidate;
        }
Exemple #3
0
        private static IceCandidate GatherSRPassiveCandidate(IPAddress localIPAddress)
        {
            // local endpoint
            IPEndPoint localEndpoint = new IPEndPoint(localIPAddress, 0);

            // listening socket
            Socket passiveListeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            passiveListeningSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            passiveListeningSocket.Bind(localEndpoint);

            // update localEndpoint with binded Port
            localEndpoint = (IPEndPoint)passiveListeningSocket.LocalEndPoint;

            // STUN socket
            Socket passiveSTUNSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            passiveSTUNSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            passiveSTUNSocket.Bind(localEndpoint);

            // get defined STUN servers
            List<IPEndPoint> definedSTUNServers = GetDefinedSTUNServers();

            // servers defined?
            if (definedSTUNServers.Count > 0)
            {
                // use first server
                IPEndPoint STUNEndPoint = definedSTUNServers[0];

                // try to connect
                try
                {
                    passiveSTUNSocket.Connect(STUNEndPoint);
                }

                catch (Exception e1)
                {
                    //Console.WriteLine(e1.Message);

                    // use second STUN server, if defined
                    if (definedSTUNServers.Count == 2)
                    {
                        STUNEndPoint = definedSTUNServers[1];

                        // try to connect
                        try
                        {
                            passiveSTUNSocket.Connect(STUNEndPoint);
                        }

                        catch (Exception e2)
                        {
                            //Console.WriteLine(e2.Message);

                            // could not establish a connection to a STUN server
                            return null;
                        }
                    }
                }

            }

            // no STUN servers defined
            else
                return null;


            // get public mapping
            IPEndPoint publicMapping = GetPublicMapping(passiveSTUNSocket);


            // save data in candidate object
            IpAddressPort passiveIpAddressPort = new IpAddressPort(AddressType.IPv4_Address, publicMapping.Address, (ushort)publicMapping.Port);
            IceCandidate passiveCandidate = new IceCandidate(passiveIpAddressPort, Overlay_Link.TLS_TCP_with_FH);
            passiveCandidate.cand_type = CandType.tcp_srflx;
            passiveCandidate.rel_addr_port = new IpAddressPort(AddressType.IPv4_Address, localEndpoint.Address, (ushort)localEndpoint.Port);
            passiveCandidate.passiveListeningSocket = passiveListeningSocket;
            passiveCandidate.passiveSTUNSocket = passiveSTUNSocket;

            // TCP Type
            passiveCandidate.tcpType = TcpType.Passive;

            // TCP ICE extension
            IceExtension iceExtension = new IceExtension();
            iceExtension.name = Encoding.UTF8.GetBytes("tcptype");
            iceExtension.value = Encoding.UTF8.GetBytes("passive");
            passiveCandidate.extension_list.Add(iceExtension);

            return passiveCandidate;
        }
Exemple #4
0
        private static IceCandidate GatherSRSOCandidate(IPAddress localIPAddress)
        {
            // local endpoint
            IPEndPoint localEndpoint = new IPEndPoint(localIPAddress, 0);

            // listening socket
            Socket soListeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            soListeningSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            soListeningSocket.Bind(localEndpoint);

            // update localEndpoint with binded Port
            localEndpoint = (IPEndPoint)soListeningSocket.LocalEndPoint;

            // connecting socket
            Socket soConnectingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            soConnectingSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            soConnectingSocket.Bind(localEndpoint);

            // STUN1 socket
            Socket soSTUN1Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            soSTUN1Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            soSTUN1Socket.Bind(localEndpoint);

            // STUN2 socket
            Socket soSTUN2Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            soSTUN2Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            soSTUN2Socket.Bind(localEndpoint);


            // public mapping
            IPEndPoint publicMapping = null;


            // get defined STUN servers
            List<IPEndPoint> definedSTUNServers = GetDefinedSTUNServers();

            // no defined STUN servers
            if (definedSTUNServers.Count == 0)
                return null;


            // only one STUN Server defined
            // so we can't predict the port mapping for two successive outgoing connections
            // what we can do here is to assume that the outgoing connections get the same port mapping
            else if (definedSTUNServers.Count == 1)
            {
                // try to connect
                try
                {
                    soSTUN1Socket.Connect(definedSTUNServers[0]);
                }

                catch (Exception e)
                {
                    //Console.WriteLine(e.Message);

                    // could not connect to STUN server
                    return null;
                }

                publicMapping = GetPublicMapping(soSTUN1Socket);

            }

            // two STUN servers defined
            // here we can predict the port mapping for two successive outgoing connections
            else if (definedSTUNServers.Count == 2)
            {
                // try to connect to first STUN server
                try
                {
                    // get first public mapping
                    soSTUN1Socket.Connect(definedSTUNServers[0]);
                    IPEndPoint mapping1 = GetPublicMapping(soSTUN1Socket);

                    // now try to connect to second STUN Server
                    try
                    {
                        soSTUN2Socket.Connect(definedSTUNServers[1]);
                        IPEndPoint mapping2 = GetPublicMapping(soSTUN2Socket);

                        // calculate difference between port mappings
                        int portDifference = mapping2.Port - mapping1.Port;

                        // IP will be the same, port will be adapted
                        publicMapping = new IPEndPoint(mapping2.Address, mapping2.Port + portDifference);
                    }

                    catch (Exception e)
                    {
                        //Console.WriteLine(e.Message);

                        // use first mapping and assume port mapping will be equal
                        publicMapping = mapping1;
                    }

                }
                catch (Exception e1)
                {
                    //Console.WriteLine(e1.Message);

                    // could not connect to first STUN server
                    // try second, but then we can't predict port mapping, only assume the port mapping will be equal for next outgoing connection
                    try
                    {
                        soSTUN2Socket.Connect(definedSTUNServers[1]);

                        publicMapping = GetPublicMapping(soSTUN2Socket);
                    }

                    catch (Exception e2)
                    {
                        //Console.WriteLine(e2.Message);

                        // could not connect to first and second STUN Server
                        return null;
                    }
                }

            }


            // got no public mapping
            if (publicMapping == null)
                return null;


            // save data in candidate object
            IpAddressPort soIpAddressPort = new IpAddressPort(AddressType.IPv4_Address, publicMapping.Address, (ushort)publicMapping.Port);
            IceCandidate soCandidate = new IceCandidate(soIpAddressPort, Overlay_Link.TLS_TCP_with_FH);
            soCandidate.cand_type = CandType.tcp_srflx;
            soCandidate.rel_addr_port = new IpAddressPort(AddressType.IPv4_Address, localEndpoint.Address, (ushort)localEndpoint.Port);
            soCandidate.soListeningSocket = soListeningSocket;
            soCandidate.soConnectingSocket = soConnectingSocket;
            soCandidate.soSTUN1Socket = soSTUN1Socket;
            soCandidate.soSTUN2Socket = soSTUN2Socket;

            // TCP Type
            soCandidate.tcpType = TcpType.SO;

            // TCP ICE extension
            IceExtension iceExtension = new IceExtension();
            iceExtension.name = Encoding.UTF8.GetBytes("tcptype");
            iceExtension.value = Encoding.UTF8.GetBytes("so");
            soCandidate.extension_list.Add(iceExtension);


            return soCandidate;
        }
Exemple #5
0
        private static IceCandidate GatherHostSOCandidate(IPAddress localIPAddress)
        {
            // local endpoint
            IPEndPoint localEndpoint = new IPEndPoint(localIPAddress, 0);

            // listening socket
            Socket soListeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            soListeningSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            soListeningSocket.Bind(localEndpoint);

            // update localEndpoint with binded Port
            localEndpoint = (IPEndPoint)soListeningSocket.LocalEndPoint;

            // connecting socket
            Socket soConnectingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            soConnectingSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            soConnectingSocket.Bind(localEndpoint);

            // save data in candidate object
            IpAddressPort soIpAddressPort = new IpAddressPort(AddressType.IPv4_Address, localEndpoint.Address, (ushort)localEndpoint.Port);
            IceCandidate soCandidate = new IceCandidate(soIpAddressPort, Overlay_Link.TLS_TCP_with_FH);
            soCandidate.cand_type = CandType.tcp_host;
            soCandidate.soListeningSocket = soListeningSocket;
            soCandidate.soConnectingSocket = soConnectingSocket;

            // TCP Type
            soCandidate.tcpType = TcpType.SO;

            // TCP ICE extension
            IceExtension iceExtension = new IceExtension();
            iceExtension.name = Encoding.UTF8.GetBytes("tcptype");
            iceExtension.value = Encoding.UTF8.GetBytes("so");
            soCandidate.extension_list.Add(iceExtension);

            return soCandidate;
        }
Exemple #6
0
        private static IceCandidate GatherHostPassiveCandidate(IPAddress localIPAddress)
        {
            // local endpoint
            IPEndPoint localEndpoint = new IPEndPoint(localIPAddress, 0);


            Socket passiveListeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            passiveListeningSocket.Bind(localEndpoint);

            // update localEndpoint with binded Port
            localEndpoint = (IPEndPoint)passiveListeningSocket.LocalEndPoint;

            // save data in candidate object
            IpAddressPort passiveIpAddressPort = new IpAddressPort(AddressType.IPv4_Address, localEndpoint.Address, (ushort)localEndpoint.Port);
            IceCandidate passiveCandidate = new IceCandidate(passiveIpAddressPort, Overlay_Link.TLS_TCP_with_FH);
            passiveCandidate.cand_type = CandType.tcp_host;
            passiveCandidate.passiveListeningSocket = passiveListeningSocket;

            // TCP Type
            passiveCandidate.tcpType = TcpType.Passive;

            // TCP ICE extension
            IceExtension iceExtension = new IceExtension();
            iceExtension.name = Encoding.UTF8.GetBytes("tcptype");
            iceExtension.value = Encoding.UTF8.GetBytes("passive");
            passiveCandidate.extension_list.Add(iceExtension);

            return passiveCandidate;
        }
Exemple #7
0
        // HOST METHODS
        private static IceCandidate GatherHostActiveCandidate(IPAddress localIPAddress)
        {
            IPEndPoint localEndpoint = new IPEndPoint(localIPAddress, 0);

            //Socket activeConnectingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //// here is no bind, because active candidates don't have to be physically allocated here (allocation in connectivity checks)
            //activeConnectingSocket.Bind(localEndpoint); // TEST

            /*  RFC 6544 (ICE TCP), Section 3:
            In the case of active candidates, both IP
            address and port are present, but the port is meaningless (it is
            there only for making encoding of active candidates consistent with
            the other candidate types and is ignored by the peer).  As a
            consequence, active candidates do not need to be physically allocated
            at the time of address gathering.  Rather, the physical allocations,
            which occur as a consequence of a connection attempt, occur at the
            time of the connectivity checks.
             */

            // save data in candidate object
            IpAddressPort activeIpAddressPort = new IpAddressPort(AddressType.IPv4_Address, localEndpoint.Address, (ushort)localEndpoint.Port);
            IceCandidate activeCandidate = new IceCandidate(activeIpAddressPort, Overlay_Link.TLS_TCP_with_FH);
            activeCandidate.cand_type = CandType.tcp_host;
            //activeCandidate.activeConnectingSocket = activeConnectingSocket; // TEST: in PerformCheck

            // TCP Type
            activeCandidate.tcpType = TcpType.Active;

            // TCP ICE extension
            IceExtension iceExtension = new IceExtension();
            iceExtension.name = Encoding.UTF8.GetBytes("tcptype");
            iceExtension.value = Encoding.UTF8.GetBytes("active");
            activeCandidate.extension_list.Add(iceExtension);

            return activeCandidate;
        }
Exemple #8
0
        public static IceCandidate CreateBootstrapCandidate(IPAddress localIPAddress, int port)
        {
            // save data in candidate object
            IpAddressPort bootstrapIpAddressPort = new IpAddressPort(AddressType.IPv4_Address, localIPAddress, (ushort)port);
            IceCandidate bootstrapCandidate = new IceCandidate(bootstrapIpAddressPort, Overlay_Link.TLS_TCP_with_FH);
            bootstrapCandidate.cand_type = CandType.tcp_bootstrap;

            // TCP Type
            bootstrapCandidate.tcpType = TcpType.Passive;

            // TCP ICE extension
            IceExtension iceExtension = new IceExtension();
            iceExtension.name = Encoding.UTF8.GetBytes("tcptype");
            iceExtension.value = Encoding.UTF8.GetBytes("passive");
            bootstrapCandidate.extension_list.Add(iceExtension);


            // set other preference and foundation
            bootstrapCandidate.otherPreference = 8191;
            bootstrapCandidate.foundation = ComputeFoundation(bootstrapCandidate);

            return bootstrapCandidate;
        }
Exemple #9
0
        public override RELOAD_MessageBody FromReader(ReloadMessage rm, BinaryReader reader, long reload_msg_size)
        {

            /* try to read the packet as a AttachReqAns packet */
            try
            {
                byte length;

                RELOAD_MsgCode = (RELOAD_MessageCode)(UInt16)IPAddress.NetworkToHostOrder(reader.ReadInt16());
                UInt32 message_len = (UInt32)(IPAddress.HostToNetworkOrder((int)reader.ReadInt32()));

                /* The username fragment (from ICE), we set it to zero length in NO-ICE */
                length = reader.ReadByte();
                if (length != 0)
                    ufrag = reader.ReadBytes(length);
                reload_msg_size -= (length + 1);

                /* The The ICE password, we set it to zero length in NO-ICE */
                length = reader.ReadByte();
                if (length != 0)
                    password = reader.ReadBytes(length);
                reload_msg_size -= (length + 1);

                /* An active/passive/actpass attribute from RFC 4145 [RFC4145]. */
                length = reader.ReadByte();
                if (length != 0)
                    role = reader.ReadBytes(length);
                reload_msg_size -= (length + 1);

                long ice_length = (UInt16)IPAddress.NetworkToHostOrder(reader.ReadInt16());

                reload_msg_size -= (ice_length + 2);

                while (ice_length > 1) //size of bool which follows
                {
                    AddressType type = (AddressType)reader.ReadByte();
                    --ice_length;
                    IPAddress ip;

                    length = reader.ReadByte();
                    --ice_length;

                    switch (type)
                    {
                        case AddressType.IPv4_Address:
                            if (length != 6)
                                return null;
                            ip = new IPAddress(reader.ReadBytes(4));
                            ice_length -= length;
                            break;
                        case AddressType.IPv6_Address:
                            if (length != 18)
                                return null;
                            ip = new IPAddress(reader.ReadBytes(16));
                            ice_length -= length;
                            break;
                        default:
                            throw new System.Exception(String.Format("Invalid address type {0} in AttachReqAns!", type));
                    }

                    UInt16 port = (ushort)IPAddress.NetworkToHostOrder(reader.ReadInt16());
                    ice_length -= 2;
                    Overlay_Link overlay_link = (Overlay_Link)reader.ReadByte();
                    --ice_length;
                    IceCandidate candidate = new IceCandidate(new IpAddressPort(type, ip, port), overlay_link);

                    int fond_length = reader.ReadByte();
                    candidate.foundation = reader.ReadBytes(fond_length);
                    ice_length -= (fond_length - 1);

                    candidate.priority = (UInt32)IPAddress.NetworkToHostOrder(reader.ReadInt32());
                    ice_length -= 4;
                    candidate.cand_type = (CandType)reader.ReadByte();
                    --ice_length;

                    switch (candidate.cand_type)
                    {
                        case CandType.tcp_host:
                            /* do nothing */
                            break;
                        case CandType.tcp_prflx:
                        case CandType.tcp_nat:      // new
                        case CandType.tcp_relay:
                        case CandType.tcp_srflx:
                            type = (AddressType)reader.ReadByte();
                            byte rel_length = reader.ReadByte();
                            //--ice_length;
                            ice_length -= 2;    // markus

                            switch (type)
                            {
                                case AddressType.IPv4_Address:
                                    if (rel_length != 6)
                                        return null;
                                    ip = new IPAddress(reader.ReadBytes(4));
                                    ice_length -= rel_length;
                                    break;
                                case AddressType.IPv6_Address:
                                    if (rel_length != 18)
                                        return null;
                                    ip = new IPAddress(reader.ReadBytes(16));
                                    ice_length -= rel_length;
                                    break;
                                default:
                                    throw new System.Exception(String.Format("Invalid rel address type {0} in AttachReqAns!", type));
                            }

                            port = (ushort)IPAddress.NetworkToHostOrder(reader.ReadInt16());
                            ice_length -= 2;

                            candidate.rel_addr_port = new IpAddressPort(type, ip, port);
                            break;
                    }

                    /*
                    // now read ice extension length
                    long ice_extension_size = (UInt16)IPAddress.NetworkToHostOrder(reader.ReadInt16());
                    if (ice_extension_size != 0)
                    {
                        //skip ice extension length
                        reader.ReadBytes((int)ice_extension_size);
                    }
                    ice_length -= (ice_extension_size + 2);
                    */


                    #region markus
                    // all new attributes for TCP ICE

                    // type preference
                    candidate.typePreference = (UInt32)IPAddress.NetworkToHostOrder(reader.ReadInt32());
                    ice_length -= 4;

                    // local preference
                    candidate.localPreference = (UInt32)IPAddress.NetworkToHostOrder(reader.ReadInt32());
                    ice_length -= 4;

                    // direction preference
                    candidate.directionPreference = (UInt32)IPAddress.NetworkToHostOrder(reader.ReadInt32());
                    ice_length -= 4;

                    // other preference
                    candidate.otherPreference = (UInt32)IPAddress.NetworkToHostOrder(reader.ReadInt32());
                    ice_length -= 4;

                    // tcp type
                    candidate.tcpType = (TcpType)reader.ReadByte();
                    --ice_length;

                    // ice extension
                    IceExtension iceExtension = new IceExtension();
                    iceExtension.name = Encoding.UTF8.GetBytes("tcptype");
                    iceExtension.value = Encoding.UTF8.GetBytes(candidate.tcpType.ToString());
                    candidate.extension_list.Add(iceExtension);

                    #endregion


                    ice_candidates.Add(candidate);
                }

                fSendUpdate = (bool)(reader.ReadByte() == 0 ? false : true);
                --reload_msg_size;
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return this;
        }