RELOAD ice candidates packed into a class
Наследование: ICloneable
Пример #1
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;
        }
Пример #2
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;
        }
Пример #3
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;
        }
Пример #4
0
        private static byte[] ComputeFoundation(IceCandidate candidate)   // checked
        {
            /* 
               RFC 5245, ICE, Section 4.1.1.3
               Finally, the agent assigns each candidate a foundation.  The
               foundation is an identifier, scoped within a session.  Two candidates
               MUST have the same foundation ID when all of the following are true:

               o  they are of the same type (host, relayed, server reflexive, or
                  peer reflexive).

               o  their bases have the same IP address (the ports can be different).

               o  for reflexive and relayed candidates, the STUN or TURN servers
                  used to obtain them have the same IP address.

               o  they were obtained using the same transport protocol (TCP, UDP,
                  etc.).

               Similarly, two candidates MUST have different foundations if their
               types are different, their bases have different IP addresses, the
               STUN or TURN servers used to obtain them have different IP addresses,
               or their transport protocols are different.
            */

            // type and transport protocol are both included in cand_type enum
            // and the candidates are always gathered from same servers (defined in config)
            // so we can build a foundation string out of the cand_type and the IP Address of the base, if a base exists (no host candidate)

            string candType = candidate.cand_type.ToString();
            string baseIPAddress = "";

            // if candidate has base (no host candidate)
            if (candidate.rel_addr_port != null)
                baseIPAddress = candidate.rel_addr_port.ipaddr.ToString();

            string foundation = candType + baseIPAddress;

            return Encoding.ASCII.GetBytes(foundation);
        }
Пример #5
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;
        }
Пример #6
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;
        }
Пример #7
0
        public bool Equals(IceCandidate cand)
        {
            // If parameter is null return false:
            if ((object)cand == null)
            {
                return false;
            }

            // Return true if the fields match:
            return (addr_port.port == cand.addr_port.port) &&
                    (priority == cand.priority) &&
                    (cand_type == cand.cand_type) &&
                    (tcpType == cand.tcpType);
        }
Пример #8
0
        public static void CloseAllCandidateSockets(IceCandidate candidate)
        {
            if (candidate.activeConnectingSocket != null)
                candidate.activeConnectingSocket.Close();

            if (candidate.passiveAcceptedSocket != null)
                candidate.passiveAcceptedSocket.Close();

            if (candidate.passiveListeningSocket != null)
                candidate.passiveListeningSocket.Close();

            if (candidate.passiveSTUNSocket != null)
                candidate.passiveSTUNSocket.Close();

            if (candidate.soAcceptedSocket != null)
                candidate.soAcceptedSocket.Close();

            if (candidate.soConnectingSocket != null)
                candidate.soConnectingSocket.Close();

            if (candidate.soListeningSocket != null)
                candidate.soListeningSocket.Close();

            if (candidate.soSTUN1Socket != null)
                candidate.soSTUN1Socket.Close();

            if (candidate.soSTUN2Socket != null)
                candidate.soSTUN2Socket.Close();
        }
Пример #9
0
        //public static void PrintCandidate(IceCandidate iceCandidate)
        //{
        //    Console.WriteLine("{0}:{1}", iceCandidate.addr_port.ipaddr.ToString(), iceCandidate.addr_port.port);
        //}

        public static void PrintCandidate(IceCandidate iceCandidate)
        {
            Console.WriteLine("{0}:{1} ({2})", iceCandidate.addr_port.ipaddr.ToString(), iceCandidate.addr_port.port, iceCandidate.tcpType.ToString());

            if (iceCandidate.rel_addr_port != null)
            {
                Console.WriteLine("\tBase: " + iceCandidate.rel_addr_port.ipaddr.ToString() + ":" + iceCandidate.rel_addr_port.port);
            }
        }
Пример #10
0
        public CandidatePair(IceCandidate localCandidate, IceCandidate remoteCandidate)
        {
            this.localCandidate = localCandidate;
            this.remoteCandidate = remoteCandidate;

            this.valid = false;
            this.nominated = false;
            this.state = CandidatePairState.Frozen;

            this.pairPriority = 0;

            /* RFC 5245, ICE, Section 5.7.4
            Each candidate pair in the check list has a foundation and a state.
            The foundation is the combination of the foundations of the local and
            remote candidates in the pair.
            */
            if (localCandidate.foundation != null && remoteCandidate.foundation != null)
            {
                this.pairFoundation = new byte[localCandidate.foundation.Length + remoteCandidate.foundation.Length];
                // first copy local candidate foundation
                Array.Copy(localCandidate.foundation, 0, this.pairFoundation, 0, localCandidate.foundation.Length);
                // then copy remote candidate foundation
                Array.Copy(remoteCandidate.foundation, 0, this.pairFoundation, localCandidate.foundation.Length, remoteCandidate.foundation.Length);
            }
            else
                this.pairFoundation = null;
        }
Пример #11
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;
        }
Пример #12
0
        public override RELOAD_MessageBody FromReader(ReloadMessage rm, BinaryReader reader, long reload_msg_size)
        {

            /* try to read the packet as a AppAttachReqAns 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 = 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 = 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 = reload_msg_size - (length + 1);

                while (reload_msg_size > 0)
                {
                    AddressType type = (AddressType)reader.ReadByte();
                    IPAddress ip;

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


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

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

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

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

                    reload_msg_size = reload_msg_size - 8;

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

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

                            port = (ushort)IPAddress.NetworkToHostOrder(reader.ReadInt16());

                            candidate.rel_addr_port = new IpAddressPort(type, ip, port);
                            break;
                    }
                    ice_candidates.Add(candidate);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return this;
        }
Пример #13
0
        public List<IceCandidate> IPAddressToIceCandidate(IPAddress ip, int portNum)
        {
            List<IceCandidate> ice_candidates = new List<IceCandidate>();

            if (ip == null)
                return null;

            /* exclude IPv6 addresses for now                              */
            if (ip.AddressFamily == AddressFamily.InterNetworkV6)
                return null;

            /* Setup an TCP candidate first                                 */
            IceCandidate candidate = new IceCandidate(new IpAddressPort(ip.AddressFamily == AddressFamily.InterNetworkV6 ? AddressType.IPv6_Address : AddressType.IPv4_Address, ip, (UInt16)portNum), Overlay_Link.TLS_TCP_FH_NO_ICE);

            /* when sending an AppAttachReqAns, form one candidate with a
               priority value of (2^24)*(126)+(2^8)*(65535)+(2^0)*(256-1) that
               specifies the UDP port being listened to and another one with the
               TCP port.                                                    */

            ice_candidates.Add(candidate);

            /* same on UDP with same port number                            */
            IceCandidate candidate2 = new IceCandidate(new IpAddressPort(ip.AddressFamily == AddressFamily.InterNetworkV6 ? AddressType.IPv6_Address : AddressType.IPv4_Address, ip, (UInt16)portNum), Overlay_Link.DLTS_UDP_SR_NO_ICE);

            ice_candidates.Add(candidate2);

            return ice_candidates;
        }
Пример #14
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;
        }
Пример #15
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;
        }
Пример #16
0
        private static uint DetermineDirectionPreference(IceCandidate iceCandidate)
        {
            // RFC 6544, Section 4.2:
            /*
            The direction-pref MUST be between 0 and 7 (both inclusive), with 7
            being the most preferred.  It is RECOMMENDED that the host, UDP-tunneled, 
            and relayed TCP candidates have the direction-pref assigned as follows: 
            6 for active, 4 for passive, and 2 for S-O.  For the NAT-assisted and 
            server reflexive candidates, the RECOMMENDED values are: 6 for S-O, 
            4 for active, and 2 for passive.
             */

            // check for TCP extension
            if (iceCandidate.extension_list != null && iceCandidate.extension_list.Count == 1)
            {
                // Host, UDP-tunneled oder Relayed candidate
                if (iceCandidate.cand_type == CandType.tcp_host || iceCandidate.cand_type == CandType.tcp_udptunneled || iceCandidate.cand_type == CandType.tcp_relay)
                {
                    switch (Encoding.UTF8.GetString(iceCandidate.extension_list[0].value))
                    {
                        case "active":
                            return 6;
                        case "passive":
                            return 4;
                        case "so":
                            return 2;
                    }
                }

                // NAT-assisted oder Server Reflexive candidate
                else if (iceCandidate.cand_type == CandType.tcp_nat || iceCandidate.cand_type == CandType.tcp_srflx)
                {
                    switch (Encoding.UTF8.GetString(iceCandidate.extension_list[0].value))
                    {
                        case "active":
                            return 4;
                        case "passive":
                            return 2;
                        case "so":
                            return 6;
                    }
                }

                // no supported candidate
                else
                    return 0;
            }


            // no TCP extension specified
            return 0;

        }
Пример #17
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;
        }
Пример #18
0
        private static IceCandidate CalculatePriority(IceCandidate iceCandidate)
        {
            // set type preference
            switch (iceCandidate.cand_type)
            {
                case CandType.tcp_host:
                    iceCandidate.typePreference = (uint)TypePreference.Host;
                    break;

                case CandType.tcp_nat:
                    iceCandidate.typePreference = (uint)TypePreference.NATAssisted;
                    break;

                case CandType.tcp_prflx:
                    iceCandidate.typePreference = (uint)TypePreference.PeerReflexive;
                    break;

                case CandType.tcp_relay:
                    iceCandidate.typePreference = (uint)TypePreference.Relay;
                    break;

                case CandType.tcp_srflx:
                    iceCandidate.typePreference = (uint)TypePreference.ServerReflexive;
                    break;

                case CandType.tcp_udptunneled:
                    iceCandidate.typePreference = (uint)TypePreference.UDPTunneled;
                    break;

                // no supported candidate type
                default:
                    return null;

            }

            // RFC 6940 (RELOAD), Section 6.5.1.1:
            // Each ICE candidate is represented as an IceCandidate structure, which is a direct translation of the information from the ICE string
            // structures, with the exception of the component ID. Since there is only one component, it is always 1, and thus left out of the structure.
            // component ID : RELOAD specific => always 1

            // RFC 6544, Section 4.2:
            // local preference = (2^13) * direction-pref + other-pref
            iceCandidate.directionPreference = DetermineDirectionPreference(iceCandidate);

            // other-pref is set in GatherCandidates()
            // decremented for each IP Address (or device)
            // see RFC 6544, Section 4.2:
            /*
            If any two candidates have the same type-preference and direction-
            pref, they MUST have a unique other-pref.  With this specification,
            this usually only happens with multi-homed hosts, in which case
            other-pref is the preference for the particular IP address from which
            the candidate was obtained.  When there is only a single IP address,
            this value SHOULD be set to the maximum allowed value (8191).
             */

            // calculate localPreference
            iceCandidate.localPreference = ((uint)PowerOf2(13)) * iceCandidate.directionPreference + iceCandidate.otherPreference;


            // calculate priority
            // RFC 5245, Section 4.1.2.1, formula:
            // priority = (2^24)*(type preference) + (2^8)*(local preference) + (2^0)*(256 - component ID)
            iceCandidate.priority = ((uint)PowerOf2(24)) * (iceCandidate.typePreference) + ((uint)PowerOf2(8)) * (iceCandidate.localPreference) + 255;


            return iceCandidate;
        }
Пример #19
0
        public IEnumerator<ITask> PreJoinProdecure(List<BootstrapServer> BootstrapServerList)
        {
            bool attached = false;
            ulong bsTransId = 0;

            if (m_topology.LocalNode.Id == null)
                yield break;

            ReloadMessage reloadSendMsg;
            ReloadMessage reloadRcvMsg = null;

            /* This is the begin of populating the neighbor table
               convert local node to resource id + 1 and sent an attach to it
             */
            Destination dest = new Destination(new ResourceId(
              m_topology.LocalNode.Id + (byte)1));
            Destination last_destination = null;
            Node NextHopNode = null;
            int succSize = m_ReloadConfig.IamClient ? 1 : ReloadGlobals.SUCCESSOR_CACHE_SIZE;
            for (int i = 0; i < succSize; i++)
            {
                //if (last_destination != null && last_destination == dest)
                if (last_destination != null && last_destination.Equals(dest))    // markus: we have to use Equals method
                    break;
                if (m_ReloadConfig.IamClient)
                    reloadSendMsg = create_attach_req(dest, false);
                else
                    reloadSendMsg = create_attach_req(dest, true);

                //we do not know the bootstrap peer's node id so far so we leave that parameter empty Node(null)

                ReloadDialog reloadDialog = null;
                int RetransmissionTime = ReloadGlobals.RetransmissionTime + ReloadGlobals.MaxTimeToSendPacket;

                /* Modification for Clients out of draft, TLS stack will take some time
                 * to initialize, add another 10s waiting */
                if (m_ReloadConfig.IamClient && i == 0)
                    RetransmissionTime += 10000;

                int iRetrans = ReloadGlobals.MaxRetransmissions;

                int iCycleBootstrap = 0;

                while (iRetrans >= 0 &&
                  m_ReloadConfig.State < ReloadConfig.RELOAD_State.Shutdown)
                {
                    /* This is the first bootstrap contacting sequence if NextHopNode 
                     * is still zero, in any other case 
                     * use an attach to the node where we got the last answer from 
                     */
                    if (NextHopNode == null)
                    {
                        /* we could use a foreach loop, but CCR would multitask it, but we
                         * want serialize that here
                        */
                        if (iCycleBootstrap >= BootstrapServerList.Count())
                            iCycleBootstrap = 0;

                        BootstrapServer bss = BootstrapServerList[iCycleBootstrap++];

                        if (attached == true)
                            break;

                        //TKTODO Rejoin of bootstrap server not solved 
                        List<IceCandidate> ics = new List<IceCandidate>();
                        IceCandidate ice = new IceCandidate(new IpAddressPort(
                          AddressType.IPv4_Address, ReloadGlobals.IPAddressFromHost(
                          m_ReloadConfig, bss.Host), (UInt16)bss.Port),
                          Overlay_Link.TLS_TCP_FH_NO_ICE);

                        // markus: change cand_type to bootstrap
                        ice.cand_type = CandType.tcp_bootstrap;

                        ics.Add(ice);

                        NextHopNode = new Node(reloadRcvMsg == null ?
                          null : reloadRcvMsg.OriginatorID, ics);
                    }

                    try
                    {
                        /* use a new ReloadDialog instance for every usage, Monitor requires it                         */
                        reloadDialog = new ReloadDialog(m_ReloadConfig, m_flm, NextHopNode);

                        if (iCycleBootstrap > 0)
                        {
                            // save transaction id from request to bootstrap
                            if (NextHopNode.IceCandidates[0].addr_port.ipaddr.ToString() == BootstrapServerList[iCycleBootstrap - 1].Host &&
                                NextHopNode.IceCandidates[0].addr_port.port == BootstrapServerList[iCycleBootstrap - 1].Port)
                                bsTransId = reloadSendMsg.TransactionID;
                        }
                   
                        m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD,
                          String.Format("{0} ==> {1} Dest={2} TransId={3:x16}",
                          RELOAD_MessageCode.Attach_Request.ToString().PadRight(16, ' '),
                          NextHopNode, dest.ToString(), reloadSendMsg.TransactionID));

                        Arbiter.Activate(m_DispatcherQueue,
                          new IterativeTask<ReloadMessage, ReloadMessageFilter, int>(
                          reloadSendMsg, new ReloadMessageFilter(reloadSendMsg.TransactionID),
                          RetransmissionTime, reloadDialog.Execute));
                    }
                    catch (Exception ex)
                    {
                        m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR,
                          "PreJoinProcedure: " + ex.Message);
                    }

                    yield return Arbiter.Receive(false, reloadDialog.Done, done => { });

                    if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null)
                    {
                        if (reloadDialog.ReceivedMessage.TransactionID == bsTransId)
                        {

                            if (reloadDialog.ReceivedMessage.forwarding_header.via_list.Count == 1)
                            {
                                BootstrapServer bsServer = BootstrapServerList[iCycleBootstrap - 1];
                                bsServer.NodeId = reloadDialog.ReceivedMessage.forwarding_header.via_list[0].destination_data.node_id;
                                BootstrapServerList.RemoveAt(iCycleBootstrap - 1);
                                BootstrapServerList.Insert(iCycleBootstrap - 1, bsServer);
                                m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("Bootstrap ID: {0}", reloadDialog.ReceivedMessage.forwarding_header.via_list[0].destination_data.node_id));
                                //Console.WriteLine("Bootstrap ID: {0}", reloadDialog.ReceivedMessage.forwarding_header.via_list[0].destination_data.node_id);
                            }
                            else if (reloadDialog.ReceivedMessage.forwarding_header.via_list.Count == 2)
                            {
                                BootstrapServer bsServer = BootstrapServerList[iCycleBootstrap - 1];
                                bsServer.NodeId = reloadDialog.ReceivedMessage.forwarding_header.via_list[1].destination_data.node_id;
                                BootstrapServerList.RemoveAt(iCycleBootstrap - 1);
                                BootstrapServerList.Insert(iCycleBootstrap - 1, bsServer);
                                m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("Bootstrap ID: {0}", reloadDialog.ReceivedMessage.forwarding_header.via_list[1].destination_data.node_id));
                                //Console.WriteLine("Bootstrap ID: {0}", reloadDialog.ReceivedMessage.forwarding_header.via_list[1].destination_data.node_id);
                            }

                            bsTransId = 0;
                        }

                        break;
                    }




                    /* still bootstrapping, allow cycling trough different bootstraps by
                     * resetting NextHopNode
                     */
                    if (i == 0)
                        NextHopNode = null;

                    /* If a response has not been received when the timer fires, the request
                       is retransmitted with the same transaction identifier. 
                    */
                    --iRetrans;
                    if (iRetrans >= 0)
                    {
                        m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("Retrans {0} Attach  {1} TransId={2:x16}", iRetrans, NextHopNode, reloadSendMsg.TransactionID));
                        m_statistics.IncRetransmission();
                    }
                    else
                    {
                        m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("Failed! Attach {0} TransId={1:x16}", NextHopNode, reloadSendMsg.TransactionID));
                        m_statistics.IncTransmissionError();
                        if (ReloadGlobals.AutoExe)
                        {
                            m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "PreJoin: Exit because initial Attach Faild!");
                            m_machine.SendCommand("Exit");
                        }
                    }
                }
                try
                {
                    if (reloadDialog != null && !reloadDialog.Error && reloadDialog.ReceivedMessage != null)
                    {
                        //the SourceNodeID delivered from reloadDialog comes from connection table and is the last hop of the message
                        reloadRcvMsg = reloadDialog.ReceivedMessage;
                        RELOAD_MessageCode msgCode = reloadRcvMsg.reload_message_body.RELOAD_MsgCode;
                        if (reloadRcvMsg != null)
                        {
                            if (msgCode == RELOAD_MessageCode.Attach_Answer)
                            {
                                m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD,
                                  String.Format("{0} <== {1} last={2} TransId={3:x16}",
                                  msgCode.ToString().PadRight(16, ' '), reloadRcvMsg.OriginatorID,
                                  reloadRcvMsg.LastHopNodeId, reloadRcvMsg.TransactionID));

                                AttachReqAns answ = (AttachReqAns)reloadRcvMsg.reload_message_body;

                                if (answ != null)
                                {
                                    m_ReloadConfig.State = ReloadConfig.RELOAD_State.PreJoin;
                                    m_machine.StateUpdates(ReloadConfig.RELOAD_State.PreJoin);

                                    /*  An Attach in and of itself does not result in updating the routing
                                     *  table of either node.
                                     *  Note: We use the routing table here only for storing ice candidates 
                                     *  for later use, we will not update successor or predecessor list
                                     */
                                    NextHopNode = new Node(reloadRcvMsg.OriginatorID, answ.ice_candidates);
                                    /*  An Attach in and of itself does not result in updating the routing
                                     *  table of either node.
                                     *  Note: We use the routing table here only for storing ice candidates 
                                     *  for later use, we will not update successor or predecessor list
                                     */
                                    m_topology.routing_table.AddNode(NextHopNode);
                                    m_topology.routing_table.SetNodeState(NextHopNode.Id,
                                      NodeState.attached);

                                    if (CheckAndSetAdmittingPeer(NextHopNode) &&
                                      NextHopNode.Id != reloadRcvMsg.LastHopNodeId)
                                        // Send ping to establish a physical connection
                                        Arbiter.Activate(m_DispatcherQueue,
                                          new IterativeTask<Destination, PingOption>(new Destination(
                                          NextHopNode.Id), PingOption.direct, SendPing));

                                    if (m_ReloadConfig.IamClient)
                                    {
                                        m_ReloadConfig.LastJoinedTime = DateTime2.Now;
                                        TimeSpan joiningTime = m_ReloadConfig.LastJoinedTime - m_ReloadConfig.StartJoinMobile;
                                        m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_MEASURE,
                                          "Join:" + joiningTime.TotalSeconds.ToString());
                                    }

                                    attached = true;
                                }
                            }
                            else if (msgCode == RELOAD_MessageCode.Error)
                            {
                                if (dest.type == DestinationType.node)
                                {
                                    ErrorResponse error = (ErrorResponse)reloadRcvMsg.reload_message_body;

                                    if (error != null)
                                    {
                                        m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR,
                                          String.Format("Prejoin: Got Error {0} from {1} deleting {2}",
                                            error.ErrorMsg,
                                            reloadRcvMsg.OriginatorID,
                                            dest.destination_data.node_id));

                                        m_topology.routing_table.Leave(dest.destination_data.node_id);
                                    }
                                }
                            }
                        }
                        else
                        {
                            m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "PreJoinProcedure: reloadRcvMsg == null!!");
                        }

                        last_destination = dest;
                        dest = new Destination(new ResourceId(reloadRcvMsg.OriginatorID) + (byte)1);
                    }
                    else
                        break;
                }
                catch (Exception ex)
                {
                    m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "PreJoinProcedure: " + ex.Message);
                }
            } // End Successor Search

            // FingerTable enrichment
            if (!m_ReloadConfig.IamClient)
            {
                List<FTEntry> fingers = m_topology.routing_table.AttachFingers();
                Port<bool> attachNextPort = null;
                Boolean attachNext = true;
                /* JP SHOULD send Attach requests to initiate connections to each of
                 * the peers in the neighbor table as well as to the desired finger
                 * table entries.
                 */
                foreach (FTEntry finger in fingers)
                {
                    attachNextPort = new Port<bool>();
                    Arbiter.Activate(m_DispatcherQueue,
                      new IterativeTask<FTEntry, Port<bool>>(
                      finger, attachNextPort, AttachFinger));
                    /* Wait for finger attach */
                    yield return Arbiter.Receive(false, attachNextPort, next =>
                    {
                        attachNext = next;
                    });
                    if (!attachNext)
                        break;

                }
            }
            /* see base -18 p.106
            /* 4.  JP MUST enter all the peers it has contacted into its routing
            /*     table.
             */
            m_topology.routing_table.Conn2Route();

            /* Once JP has a reasonable set of connections it is ready to take its 
             * place in the DHT.  It does this by sending a Join to AP.
             */
            if (m_ReloadConfig.AdmittingPeer != null)
                if (!m_ReloadConfig.IamClient)
                {
                    m_ReloadConfig.State = ReloadConfig.RELOAD_State.Joining;
                    m_machine.StateUpdates(ReloadConfig.RELOAD_State.Joining);

                    m_topology.routing_table.SetWaitForJoinAnsw(
                      m_ReloadConfig.AdmittingPeer.Id, true);

                    reloadSendMsg = create_join_req(
                      new Destination(m_ReloadConfig.AdmittingPeer.Id));
                    ReloadDialog reloadDialog = null;

                    int RetransmissionTime = ReloadGlobals.RetransmissionTime + ReloadGlobals.MaxTimeToSendPacket;
                    int iRetrans = ReloadGlobals.MaxRetransmissions;

                    while (iRetrans >= 0 && m_ReloadConfig.State < ReloadConfig.RELOAD_State.Shutdown)
                    {
                        reloadDialog = new ReloadDialog(m_ReloadConfig, m_flm, m_ReloadConfig.AdmittingPeer);

                        m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("{0} ==> {1} TransId={2:x16}", RELOAD_MessageCode.Join_Request.ToString().PadRight(16, ' '), m_ReloadConfig.AdmittingPeer, reloadSendMsg.TransactionID));

                        Arbiter.Activate(m_DispatcherQueue, new IterativeTask<ReloadMessage, ReloadMessageFilter, int>(reloadSendMsg, new ReloadMessageFilter(reloadSendMsg.TransactionID), RetransmissionTime, reloadDialog.Execute));
                        yield return Arbiter.Receive(false, reloadDialog.Done, done => { });

                        if (!reloadDialog.Error && reloadDialog.ReceivedMessage != null)
                            break;

                        /* If a response has not been received when the timer fires, the request
                           is retransmitted with the same transaction identifier. 
                        */
                        --iRetrans;
                        if (iRetrans >= 0)
                        {
                            m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING, String.Format("Retrans {0} Join  {1} TransId={2:x16}", iRetrans, m_ReloadConfig.AdmittingPeer, reloadSendMsg.TransactionID));
                            m_statistics.IncRetransmission();
                        }
                        else
                        {
                            m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, String.Format("Failed! Join {0} TransId={1:x16}", m_ReloadConfig.AdmittingPeer, reloadSendMsg.TransactionID));
                            m_statistics.IncTransmissionError();
                        }
                    }

                    try
                    {
                        if (!reloadDialog.Error)
                        {
                            reloadRcvMsg = reloadDialog.ReceivedMessage;
                            RELOAD_MessageCode msgCode = reloadRcvMsg.reload_message_body.RELOAD_MsgCode;
                            if (reloadRcvMsg != null)
                            {
                                if (msgCode == RELOAD_MessageCode.Join_Answer)
                                {
                                    m_topology.routing_table.SetWaitForJoinAnsw(reloadRcvMsg.OriginatorID, false);

                                    m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD,
                                      String.Format("{0} <== {1} TransId={2:x16}",
                                      msgCode.ToString().PadRight(16, ' '), reloadRcvMsg.OriginatorID,
                                      reloadRcvMsg.TransactionID));

                                    NodeState nodestate = m_topology.routing_table.GetNodeState(reloadRcvMsg.OriginatorID);

                                    if (nodestate == NodeState.updates_received)
                                    {
                                        /* we previously received an update from admitting peer (maybe 
                                         * race condition), now joining is complete in any other case 
                                         * wait for updates to come from this node */
                                        m_ReloadConfig.State = ReloadConfig.RELOAD_State.Joined;
                                        m_machine.StateUpdates(ReloadConfig.RELOAD_State.Joined);
                                        m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_RELOAD, String.Format("Joining completed"));
                                        m_ReloadConfig.LastJoinedTime = DateTime.Now;
                                        TimeSpan joiningTime = m_ReloadConfig.LastJoinedTime - m_ReloadConfig.StartJoining;
                                        m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_MEASURE, String.Format("Join:{0}", joiningTime.TotalSeconds.ToString()));

                                        m_topology.routing_table.SendUpdateToAllNeighbors();
                                    }
                                    else
                                    {
                                        m_ReloadConfig.LastJoinedTime = DateTime.Now;
                                        TimeSpan joiningTime = m_ReloadConfig.LastJoinedTime - m_ReloadConfig.StartTime;
                                        m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_MEASURE, String.Format("Join:{0}", joiningTime.TotalSeconds.ToString()));

                                        m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_WARNING,
                                          String.Format("Prejoin: nodestate != update_recv at Node {0}", m_machine.ReloadConfig.ListenPort));
                                    }
                                    //m_topology.routing_table.SendUpdatesToAllFingers();
                                }
                            }
                            else
                            {
                                m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "PreJoinProcedure: reloadRcvMsg == null!!");
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_ERROR, "PreJoinProcedure: " + ex.Message);
                    }
                }
                else
                {
                    if (m_ReloadConfig.SipUri == "")
                        m_ReloadConfig.SipUri = String.Format("{0}@{1}", ReloadGlobals.HostName,
                            m_ReloadConfig.OverlayName);

                    if (m_ReloadConfig.SipUri != null && m_ReloadConfig.SipUri != "")
                    {
                        // explictite SIP registration as minimal config for RELOAD clients

                        IUsage sipRegistration = m_machine.UsageManager.CreateUsage(Usage_Code_Point.SIP_REGISTRATION,
                                                                         2,
                                                                         m_ReloadConfig.SipUri);
                        sipRegistration.ResourceName = m_ReloadConfig.SipUri;
                        List<StoreKindData> clientRegistrationList = new List<StoreKindData>();
                        StoreKindData sipKindData = new StoreKindData(sipRegistration.KindId,
                                                                      0, new StoredData(sipRegistration.Encapsulate(true)));
                        clientRegistrationList.Add(sipKindData);
                        Arbiter.Activate(m_DispatcherQueue, new IterativeTask<string, List<StoreKindData>>(m_ReloadConfig.SipUri, clientRegistrationList, Store));
                    }
                }
            else
            {
                m_ReloadConfig.Logger(ReloadGlobals.TRACEFLAGS.T_MEASURE,
                  String.Format("PreJoinPredure => Node {0} has no admitting peer = {1}!",
                  m_machine.ReloadConfig.ListenPort, m_ReloadConfig.AdmittingPeer));
                if (ReloadGlobals.AutoExe)
                {
                    m_machine.SendCommand("Exit");
                }
            }
        } // End PreJoin        
Пример #20
0
        public bool EqualsInAddressPort(IceCandidate iceCandidate)
        {
            // check if IP Address and Port are equal
            if (this.addr_port.ipaddr.Equals(iceCandidate.addr_port.ipaddr) &&
                this.addr_port.port == iceCandidate.addr_port.port &&
                this.addr_port.type == iceCandidate.addr_port.type)
            {
                return true;
            }

            else
                return false;
        }