コード例 #1
0
ファイル: DhtDhcp.cs プロジェクト: tristion/brunet
        /**
         * <summary>This provides a mechanism for a node to get a lease by using the
         * Dht.  This uses Dht.Create which provides an atomic operation on the Dht,
         * where this node is the first to store a value at a specific key.  The idea
         * being that, this node being the first to store the IP, all nodes doing a
         * lookup for that IP Address would be directed to this node.</summary>
         * <remarks>Working with the Dht is a little tricky as transient errors could
         * be misrepresented as a failed Create.  It is that reason why there is a
         * Renew parameter. If that is set, the algorithm for obtaining an address
         * is slightly changed with more weight on reobtaining the RequestedAddr.
         * </remarks>
         * <param name="RequestedAddr">Optional parameter if the node would like to
         * request a specific address.</param>
         * <param name="Renew">Is the RequestedAddr a renewal?</param>
         * <param name="node_address">The Brunet.Address where the DhtIpopNode resides
         * </param>
         * <param name="para">Optional, position 0 should hold the hostname.</param>
         */
        public override byte[] RequestLease(byte[] RequestedAddr, bool Renew,
                                            string node_address, params object[] para)
        {
            int max_renew_attempts = 1;
            int renew_attempts     = max_renew_attempts;
            int attempts           = 2;

            if (Renew)
            {
                if (!ValidIP(RequestedAddr))
                {
                    throw new Exception("Invalid requested address: " +
                                        Utils.BytesToString(RequestedAddr, '.'));
                }
                MemBlock request_addr = MemBlock.Reference(RequestedAddr);
                renew_attempts = 2;
                attempts       = 1;
                if (request_addr.Equals(_current_ip) && DateTime.UtcNow < _current_quarter_lifetime)
                {
                    return(_current_ip);
                }
            }
            else if (RequestedAddr == null || !ValidIP(RequestedAddr))
            {
                RequestedAddr = MemBlock.Reference(RandomIPAddress());
            }

            byte[] hostname = null;
            if (para.Length > 0 && para[0] is string)
            {
                string shostname = para[0] as string;
                if (!shostname.Equals(string.Empty))
                {
                    hostname = Encoding.UTF8.GetBytes(Config.Namespace + "." + shostname + "." + Dns.DomainName);
                }
            }

            byte[] multicast_key = null;
            if (_multicast)
            {
                multicast_key = Encoding.UTF8.GetBytes(Config.Namespace + ".multicast.ipop");
            }

            byte[] node_addr = Encoding.UTF8.GetBytes(node_address);
            bool   res       = false;

            while (attempts-- > 0)
            {
                string str_addr = Utils.BytesToString(RequestedAddr, '.');
                ProtocolLog.WriteIf(IpopLog.DhcpLog, "Attempting to allocate IP Address:" + str_addr);

                byte[] dhcp_key = Encoding.UTF8.GetBytes("dhcp:" + Config.Namespace + ":" + str_addr);
                byte[] ip_addr  = Encoding.UTF8.GetBytes(str_addr);

                while (renew_attempts-- > 0)
                {
                    try {
                        res = _dht.Create(dhcp_key, node_addr, Config.LeaseTime);

                        if (hostname != null)
                        {
                            _dht.Put(hostname, ip_addr, Config.LeaseTime);
                        }

                        if (_multicast)
                        {
                            _dht.Put(multicast_key, node_addr, Config.LeaseTime);
                        }

//            _dht.Put(node_addr, dhcp_key, Config.LeaseTime);
                    }
                    catch (Exception e) {
                        ProtocolLog.WriteIf(IpopLog.DhcpLog, "Unable to allocate: " + e.Message);
                        res = false;
                    }
                }
                if (res)
                {
                    _current_ip = MemBlock.Reference(RequestedAddr);
                    _current_quarter_lifetime = DateTime.UtcNow.AddSeconds(Config.LeaseTime / 4.0);
                    break;
                }
                else
                {
                    // Failure!  Guess a new IP address
                    RequestedAddr  = RandomIPAddress();
                    renew_attempts = max_renew_attempts;
                }
            }

            if (!res)
            {
                throw new Exception("Unable to get an IP Address!");
            }

            return(RequestedAddr);
        }