예제 #1
0
 /// <summary> Add an additional answer to the record. Omit if there is no room.</summary>
 internal void AddAdditionalAnswer(DNSIncoming in_Renamed, DNSRecord rec)
 {
     if ((off < DNSConstants.MAX_MSG_TYPICAL - 200) && !rec.SuppressedBy(in_Renamed))
     {
         WriteRecord(rec, 0);
         numAdditionals++;
     }
 }
예제 #2
0
 /// <summary> True if this record would be supressed by an answer.
 /// This is the case if this record would not have a
 /// significantly longer TTL.
 /// </summary>
 internal virtual bool SuppressedBy(DNSRecord other)
 {
     if (SameAs(other) && (other.ttl > ttl / 2))
     {
         return(true);
     }
     return(false);
 }
예제 #3
0
 /// <summary> Add an answer if it is not suppressed.</summary>
 internal void AddAnswer(DNSIncoming in_Renamed, DNSRecord rec)
 {
     if (numAuthorities > 0 || numAdditionals > 0)
     {
         // TODO is this the right exception
         throw new Exception("Answers must be added before authorities and additionals");
     }
     if (!rec.SuppressedBy(in_Renamed))
     {
         AddAnswer(rec, 0);
     }
 }
예제 #4
0
파일: mDNS.cs 프로젝트: rajeshwarn/mDNS
        // Remind: Method updateRecord should receive a better name.
        /// <summary> Notify all listeners that a record was updated.</summary>
        internal virtual void UpdateRecord(long now, DNSRecord rec)
        {
            // We do not want to block the entire DNS while we are updating the record for each listener (service info)
            IList listenerList = null;

            lock (this)
            {
                listenerList = new ArrayList(listeners);
            }
            foreach (IDNSListener listener in listenerList)
            {
                listener.UpdateRecord(this, now, rec);
            }
            if (rec.type == DNSConstants.TYPE_PTR || rec.type == DNSConstants.TYPE_SRV)
            {
                IList serviceListenerList = null;
                lock (this)
                {
                    serviceListenerList = (IList)serviceListeners[rec.name.ToLower()];
                    // Iterate on a copy in case listeners will modify it
                    if (serviceListenerList != null)
                    {
                        serviceListenerList = new ArrayList(serviceListenerList);
                    }
                }
                if (serviceListenerList != null)
                {
                    bool   expired = rec.IsExpired(now);
                    string type    = rec.Name;
                    string name    = ((Pointer)rec).Alias;
                    // DNSRecord old = (DNSRecord)services.get(name.toLowerCase());
                    if (!expired)
                    {
                        // new record
                        ServiceEvent event_Renamed = new ServiceEvent(this, type, ToUnqualifiedName(type, name), null);
                        foreach (IServiceListener listener in serviceListenerList)
                        {
                            listener.ServiceAdded(this, event_Renamed);
                        }
                    }
                    else
                    {
                        // expire record
                        ServiceEvent event_Renamed = new ServiceEvent(this, type, ToUnqualifiedName(type, name), null);
                        foreach (IServiceListener listener in serviceListenerList)
                        {
                            listener.ServiceRemoved(this, event_Renamed);
                        }
                    }
                }
            }
        }
예제 #5
0
        // REMIND: Oops, this shouldn't be public!
        /// <summary> JmDNS callback to update a DNS record.</summary>
        public virtual void UpdateRecord(mDNS jmdns, long now, DNSRecord rec)
        {
            if ((rec != null) && !rec.IsExpired(now))
            {
                switch (rec.type)
                {
                case DNSConstants.TYPE_A:
                // IPv4
                case DNSConstants.TYPE_AAAA:                          // IPv6 FIXME [PJYF Oct 14 2004] This has not been tested
                    if (rec.name.Equals(server))
                    {
                        addr = ((Address)rec).IPAddress;
                    }
                    break;

                case DNSConstants.TYPE_SRV:
                    if (rec.name.Equals(QualifiedName))
                    {
                        Service srv = (Service)rec;
                        server   = srv.server;
                        port     = srv.port;
                        weight   = srv.weight;
                        priority = srv.priority;
                        addr     = null;
                        // changed to use getCache() instead - jeffs
                        // updateRecord(jmdns, now, (DNSRecord)jmdns.cache.get(server, TYPE_A, CLASS_IN));
                        UpdateRecord(jmdns, now, (DNSRecord)jmdns.Cache.get_Renamed(server, DNSConstants.TYPE_A, DNSConstants.CLASS_IN));
                    }
                    break;

                case DNSConstants.TYPE_TXT:
                    if (rec.name.Equals(QualifiedName))
                    {
                        Text txt = (Text)rec;
                        text = txt.text;
                    }
                    break;
                }
                // Future Design Pattern
                // This is done, to notify the wait loop in method
                // JmDNS.getServiceInfo(type, name, timeout);
                if (HasData && dns != null)
                {
                    dns.HandleServiceResolved(this);
                    dns = null;
                }
                lock (this)
                {
                    Monitor.PulseAll(this);
                }
            }
        }
예제 #6
0
        /// <summary> Add an authorative answer to the message.</summary>
        internal void  AddAuthorativeAnswer(DNSRecord rec)
        {
            if (numAdditionals > 0)
            {
                // TODO is this the right exception?
                throw new Exception("Authorative answers must be added before additional answers");
            }
            authorativeAnswers.Add(rec);
            WriteRecord(rec, 0);
            numAuthorities++;

            // VERIFY:
        }
예제 #7
0
파일: Text.cs 프로젝트: pisker/mDNS
		internal override bool SameValue(DNSRecord other)
		{
			Text txt = (Text) other;
			if (txt.text.Length != text.Length)
			{
				return false;
			}
			for (int i = text.Length; i-- > 0; )
			{
				if (txt.text[i] != text[i])
				{
					return false;
				}
			}
			return true;
		}
예제 #8
0
 /// <summary> Add an answer to the message.</summary>
 internal void AddAnswer(DNSRecord rec, long now)
 {
     if (numAuthorities > 0 || numAdditionals > 0)
     {
         // TODO is this the right exception?
         throw new Exception("Questions must be added before answers");
     }
     if (rec != null)
     {
         if ((now == 0) || !rec.IsExpired(now))
         {
             WriteRecord(rec, now);
             numAnswers++;
         }
     }
 }
예제 #9
0
파일: Text.cs 프로젝트: rajeshwarn/mDNS
        internal override bool SameValue(DNSRecord other)
        {
            Text txt = (Text)other;

            if (txt.text.Length != text.Length)
            {
                return(false);
            }
            for (int i = text.Length; i-- > 0;)
            {
                if (txt.text[i] != text[i])
                {
                    return(false);
                }
            }
            return(true);
        }
예제 #10
0
파일: Canceler.cs 프로젝트: rajeshwarn/mDNS
 public void Run(object state)
 {
     try
     {
         if (++count < 3)
         {
             logger.Debug("run() JmDNS canceling service");
             // announce the service
             DNSOutgoing out_Renamed = new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
             for (int i = 0; i < infos.Length; i++)
             {
                 ServiceInfo info = infos[i];
                 out_Renamed.AddAnswer(new Pointer(info.type, DNSConstants.TYPE_PTR, DNSConstants.CLASS_IN, ttl, info.QualifiedName), 0);
                 out_Renamed.AddAnswer(new Service(info.QualifiedName, DNSConstants.TYPE_SRV, DNSConstants.CLASS_IN, ttl, info.priority, info.weight, info.port, Enclosing_Instance.localHost.Name), 0);
                 out_Renamed.AddAnswer(new Text(info.QualifiedName, DNSConstants.TYPE_TXT, DNSConstants.CLASS_IN, ttl, info.text), 0);
                 DNSRecord answer = Enclosing_Instance.localHost.DNS4AddressRecord;
                 if (answer != null)
                 {
                     out_Renamed.AddAnswer(answer, 0);
                 }
                 answer = Enclosing_Instance.localHost.DNS6AddressRecord;
                 if (answer != null)
                 {
                     out_Renamed.AddAnswer(answer, 0);
                 }
             }
             Enclosing_Instance.Send(out_Renamed);
         }
         else
         {
             // After three successful announcements, we are finished.
             lock (lock_Renamed)
             {
                 Monitor.PulseAll(lock_Renamed);
             }
             // TODO: omit cancel?
             //cancel();
         }
     }
     catch (Exception e)
     {
         logger.Warn("run() exception ", e);
         Enclosing_Instance.Recover();
     }
 }
예제 #11
0
파일: mDNS.cs 프로젝트: rajeshwarn/mDNS
        /// <summary> Generate a possibly unique name for a service using the information we
        /// have in the cache.
        ///
        /// </summary>
        /// <returns> returns true, if the name of the service info had to be changed.
        /// </returns>
        private bool makeServiceNameUnique(ServiceInfo info)
        {
            string originalQualifiedName = info.QualifiedName;
            long   now = (DateTime.Now.Ticks - 621355968000000000) / 10000;

            bool collision;

            do
            {
                collision = false;

                // Check for collision in cache
                for (DNSCache.CacheNode j = cache.find(info.QualifiedName.ToLower()); j != null; j = j.Next)
                {
                    DNSRecord a = (DNSRecord)j.Value;
                    if ((a.type == DNSConstants.TYPE_SRV) && !a.IsExpired(now))
                    {
                        Service s = (Service)a;
                        if (s.port != info.port || !s.server.Equals(localHost.Name))
                        {
                            logger.Debug("makeServiceNameUnique() JmDNS.makeServiceNameUnique srv collision:" + a + " s.server=" + s.server + " " + localHost.Name + " equals:" + (s.server.Equals(localHost.Name)));
                            info.SetName(IncrementName(info.getName()));
                            collision = true;
                            break;
                        }
                    }
                }

                // Check for collision with other service infos published by JmDNS
                object selfService = services[info.QualifiedName.ToLower()];
                if (selfService != null && selfService != info)
                {
                    info.SetName(IncrementName(info.getName()));
                    collision = true;
                }
            }while (collision);

            return(!(originalQualifiedName.Equals(info.QualifiedName)));
        }
예제 #12
0
        internal void WriteRecord(DNSRecord rec, long now)
        {
            int save = off;

            try
            {
                WriteName(rec.name);
                WriteShort(rec.type);
                WriteShort(rec.clazz | ((rec.unique && multicast)?DNSConstants.CLASS_UNIQUE:0));
                WriteInt((now == 0)?rec.ttl:rec.GetRemainingTTL(now));
                WriteShort(0);
                int start = off;
                rec.Write(this);
                int len = off - start;
                data[start - 2] = (sbyte)(len >> 8);
                data[start - 1] = (sbyte)(len & 0xFF);
            }
            catch (IOException e)
            {
                off = save;
                throw e;
            }
        }
예제 #13
0
파일: mDNS.cs 프로젝트: rajeshwarn/mDNS
        /// <summary> Add a listener for a question. The listener will receive updates
        /// of answers to the question as they arrive, or from the cache if they
        /// are already available.
        /// </summary>
        internal virtual void AddListener(IDNSListener listener, DNSQuestion question)
        {
            long now = (DateTime.Now.Ticks - 621355968000000000) / 10000;

            // add the new listener
            lock (this)
            {
                listeners.Add(listener);
            }

            // report existing matched records
            if (question != null)
            {
                for (DNSCache.CacheNode i = cache.find(question.name); i != null; i = i.Next)
                {
                    DNSRecord c = (DNSRecord)i.Value;
                    if (question.IsAnsweredBy(c) && !c.IsExpired(now))
                    {
                        listener.UpdateRecord(this, now, c);
                    }
                }
            }
        }
예제 #14
0
파일: DNSOutgoing.cs 프로젝트: pisker/mDNS
		/// <summary> Add an additional answer to the record. Omit if there is no room.</summary>
		internal void AddAdditionalAnswer(DNSIncoming in_Renamed, DNSRecord rec)
		{
			if ((off < DNSConstants.MAX_MSG_TYPICAL - 200) && !rec.SuppressedBy(in_Renamed))
			{
				WriteRecord(rec, 0);
				numAdditionals++;
			}
		}
예제 #15
0
파일: Service.cs 프로젝트: pisker/mDNS
		internal override bool SameValue(DNSRecord other)
		{
			Service s = (Service) other;
			return (priority == s.priority) && (weight == s.weight) && (port == s.port) && server.Equals(s.server);
		}
예제 #16
0
파일: DNSRecord.cs 프로젝트: pisker/mDNS
		/// <summary> True if this record would be supressed by an answer.
		/// This is the case if this record would not have a
		/// significantly longer TTL.
		/// </summary>
		internal virtual bool SuppressedBy(DNSRecord other)
		{
			if (SameAs(other) && (other.ttl > ttl / 2))
			{
				return true;
			}
			return false;
		}
예제 #17
0
 /// <summary> True if this record has the same value as some other record.</summary>
 internal abstract bool SameValue(DNSRecord other);
예제 #18
0
파일: Address.cs 프로젝트: rajeshwarn/mDNS
 internal virtual bool Same(DNSRecord other)
 {
     return((SameName(other)) && ((SameValue(other))));
 }
예제 #19
0
파일: Address.cs 프로젝트: rajeshwarn/mDNS
 internal virtual bool SameName(DNSRecord other)
 {
     return(name.ToUpper().Equals(((Address)other).name.ToUpper()));
 }
예제 #20
0
파일: DNSOutgoing.cs 프로젝트: pisker/mDNS
		internal void WriteRecord(DNSRecord rec, long now)
		{
			int save = off;
			try
			{
				WriteName(rec.name);
				WriteShort(rec.type);
				WriteShort(rec.clazz | ((rec.unique && multicast)?DNSConstants.CLASS_UNIQUE:0));
				WriteInt((now == 0)?rec.ttl:rec.GetRemainingTTL(now));
				WriteShort(0);
				int start = off;
				rec.Write(this);
				int len = off - start;
				data[start - 2] = (sbyte) (len >> 8);
				data[start - 1] = (sbyte) (len & 0xFF);
			}
			catch (IOException e)
			{
				off = save;
				throw e;
			}
		}
예제 #21
0
파일: Address.cs 프로젝트: pisker/mDNS
		internal override bool SameValue(DNSRecord other)
		{
			return addr.Equals(((Address) other).IPAddress);
		}
예제 #22
0
파일: DNSQuestion.cs 프로젝트: pisker/mDNS
		/// <summary> Check if this question is answered by a given DNS record.</summary>
		internal bool IsAnsweredBy(DNSRecord rec)
		{
			return (clazz == rec.clazz) && ((type == rec.type) || (type == DNSConstants.TYPE_ANY)) && name.Equals(rec.name);
		}
예제 #23
0
파일: DNSRecord.cs 프로젝트: pisker/mDNS
		/// <summary> True if this record has the same value as some other record.</summary>
		internal abstract bool SameValue(DNSRecord other);
예제 #24
0
파일: Service.cs 프로젝트: pisker/mDNS
        internal override bool SameValue(DNSRecord other)
        {
            Service s = (Service)other;

            return((priority == s.priority) && (weight == s.weight) && (port == s.port) && server.Equals(s.server));
        }
예제 #25
0
 internal override bool SameValue(DNSRecord other)
 {
     return(alias.Equals(((Pointer)other).alias));
 }
예제 #26
0
파일: Pointer.cs 프로젝트: pisker/mDNS
		internal override bool SameValue(DNSRecord other)
		{
			return alias.Equals(((Pointer) other).alias);
		}
예제 #27
0
파일: DNSOutgoing.cs 프로젝트: pisker/mDNS
		/// <summary> Add an answer to the message.</summary>
		internal void AddAnswer(DNSRecord rec, long now)
		{
			if (numAuthorities > 0 || numAdditionals > 0)
			{
				// TODO is this the right exception?
				throw new Exception("Questions must be added before answers");
			}
			if (rec != null)
			{
				if ((now == 0) || !rec.IsExpired(now))
				{
					WriteRecord(rec, now);
					numAnswers++;
				}
			}
		}
예제 #28
0
파일: DNSOutgoing.cs 프로젝트: pisker/mDNS
		/// <summary> Add an authorative answer to the message.</summary>
		internal void  AddAuthorativeAnswer(DNSRecord rec)
		{
			if (numAdditionals > 0)
			{
				// TODO is this the right exception?
				throw new Exception("Authorative answers must be added before additional answers");
			}
			authorativeAnswers.Add(rec);
			WriteRecord(rec, 0);
			numAuthorities++;
			
			// VERIFY:
		}
예제 #29
0
파일: Address.cs 프로젝트: pisker/mDNS
		internal virtual bool Same(DNSRecord other)
		{
			return ((SameName(other)) && ((SameValue(other))));
		}
예제 #30
0
파일: DNSOutgoing.cs 프로젝트: pisker/mDNS
		/// <summary> Add an answer if it is not suppressed.</summary>
		internal void AddAnswer(DNSIncoming in_Renamed, DNSRecord rec)
		{
			if (numAuthorities > 0 || numAdditionals > 0)
			{
				// TODO is this the right exception
				throw new Exception("Answers must be added before authorities and additionals");
			}
			if (!rec.SuppressedBy(in_Renamed))
			{
				AddAnswer(rec, 0);
			}
		}
예제 #31
0
 /// <summary> True if this record is the same as some other record.</summary>
 internal virtual bool SameAs(DNSRecord other)
 {
     return(base.Equals(other) && SameValue((DNSRecord)other));
 }
예제 #32
0
파일: Address.cs 프로젝트: rajeshwarn/mDNS
 internal override bool SameValue(DNSRecord other)
 {
     return(addr.Equals(((Address)other).IPAddress));
 }
예제 #33
0
파일: mDNS.cs 프로젝트: rajeshwarn/mDNS
        /// <summary> Add an answer to a question. Deal with the case when the
        /// outgoing packet overflows
        /// </summary>
        internal virtual DNSOutgoing AddAnswer(DNSIncoming in_Renamed, IPAddress addr, int port, DNSOutgoing out_Renamed, DNSRecord rec)
        {
            if (out_Renamed == null)
            {
                out_Renamed = new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
            }
            try
            {
                out_Renamed.AddAnswer(in_Renamed, rec);
            }
            catch
            {
                out_Renamed.flags |= DNSConstants.FLAGS_TC;
                out_Renamed.id     = in_Renamed.id;
                out_Renamed.Finish();
                Send(out_Renamed);

                out_Renamed = new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
                out_Renamed.AddAnswer(in_Renamed, rec);
            }
            return(out_Renamed);
        }
예제 #34
0
파일: DNSRecord.cs 프로젝트: pisker/mDNS
		/// <summary> True if this record is the same as some other record.</summary>
		internal virtual bool SameAs(DNSRecord other)
		{
			return base.Equals(other) && SameValue((DNSRecord) other);
		}
예제 #35
0
        /// <summary> Parse a message from a datagram packet.</summary>
        internal DNSIncoming(SupportClass.PacketSupport packet)
        {
            this.packet = packet;
            this.data   = SupportClass.ToSByteArray(packet.Data);
            this.len    = packet.Length;
            // TODO: will this always be 0 in .NET??
            this.off          = 0;
            this.questions    = ArrayList.ReadOnly(new ArrayList());
            this.answers      = ArrayList.ReadOnly(new ArrayList());
            this.receivedTime = (DateTime.Now.Ticks - 621355968000000000) / 10000;

            try
            {
                id             = ReadUnsignedShort();
                flags          = ReadUnsignedShort();
                numQuestions   = ReadUnsignedShort();
                numAnswers     = ReadUnsignedShort();
                numAuthorities = ReadUnsignedShort();
                numAdditionals = ReadUnsignedShort();

                // parse questions
                if (numQuestions > 0)
                {
                    questions = ArrayList.Synchronized(new ArrayList(numQuestions));
                    for (int i = 0; i < numQuestions; i++)
                    {
                        DNSQuestion question = new DNSQuestion(ReadName(), ReadUnsignedShort(), ReadUnsignedShort());
                        questions.Add(question);
                    }
                }

                // parse answers
                int n = numAnswers + numAuthorities + numAdditionals;
                if (n > 0)
                {
                    answers = ArrayList.Synchronized(new ArrayList(n));
                    for (int i = 0; i < n; i++)
                    {
                        string    domain = ReadName();
                        int       type   = ReadUnsignedShort();
                        int       clazz  = ReadUnsignedShort();
                        int       ttl    = ReadInt();
                        int       len    = ReadUnsignedShort();
                        int       end    = off + len;
                        DNSRecord rec    = null;

                        switch (type)
                        {
                        case DNSConstants.TYPE_A:
                        // IPv4
                        case DNSConstants.TYPE_AAAA:                                  // IPv6 FIXME [PJYF Oct 14 2004] This has not been tested
                            rec = new Address(domain, type, clazz, ttl, ReadBytes(off, len));
                            break;

                        case DNSConstants.TYPE_CNAME:
                        case DNSConstants.TYPE_PTR:
                            rec = new Pointer(domain, type, clazz, ttl, ReadName());
                            break;

                        case DNSConstants.TYPE_TXT:
                            rec = new Text(domain, type, clazz, ttl, ReadBytes(off, len));
                            break;

                        case DNSConstants.TYPE_SRV:
                            rec = new Service(domain, type, clazz, ttl, ReadUnsignedShort(), ReadUnsignedShort(), ReadUnsignedShort(), ReadName());
                            break;

                        case DNSConstants.TYPE_HINFO:
                            // Maybe we should do something with those
                            break;

                        default:
                            logger.Debug("DNSIncoming() unknown type:" + type);
                            break;
                        }

                        if (rec != null)
                        {
                            // Add a record, if we were able to create one.
                            answers.Add(rec);
                        }
                        else
                        {
                            // Addjust the numbers for the skipped record
                            if (answers.Count < numAnswers)
                            {
                                numAnswers--;
                            }
                            else if (answers.Count < numAnswers + numAuthorities)
                            {
                                numAuthorities--;
                            }
                            else if (answers.Count < numAnswers + numAuthorities + numAdditionals)
                            {
                                numAdditionals--;
                            }
                        }
                        off = end;
                    }
                }
            }
            catch (IOException e)
            {
                logger.Warn("DNSIncoming() dump " + Print(true) + "\n exception ", e);
                throw e;
            }
        }
예제 #36
0
파일: DNSRecord.cs 프로젝트: pisker/mDNS
		/// <summary> Reset the TTL of a record. This avoids having to
		/// update the entire record in the cache.
		/// </summary>
		internal virtual void ResetTTL(DNSRecord other)
		{
			created = other.created;
			ttl = other.ttl;
		}
예제 #37
0
파일: mDNS.cs 프로젝트: pisker/mDNS
		// Remind: Method updateRecord should receive a better name.
		/// <summary> Notify all listeners that a record was updated.</summary>
		internal virtual void UpdateRecord(long now, DNSRecord rec)
		{
			// We do not want to block the entire DNS while we are updating the record for each listener (service info)
			IList listenerList = null;
			lock (this)
			{
				listenerList = new ArrayList(listeners);
			}
			foreach (IDNSListener listener in listenerList)
			{
				listener.UpdateRecord(this, now, rec);
			}
			if (rec.type == DNSConstants.TYPE_PTR || rec.type == DNSConstants.TYPE_SRV)
			{
				IList serviceListenerList = null;
				lock (this)
				{
					serviceListenerList = (IList) serviceListeners[rec.name.ToLower()];
					// Iterate on a copy in case listeners will modify it
					if (serviceListenerList != null)
						serviceListenerList = new ArrayList(serviceListenerList);
				}
				if (serviceListenerList != null)
				{
					bool expired = rec.IsExpired(now);
					string type = rec.Name;
					string name = ((Pointer) rec).Alias;
					// DNSRecord old = (DNSRecord)services.get(name.toLowerCase());
					if (!expired)
					{
						// new record
						ServiceEvent event_Renamed = new ServiceEvent(this, type, ToUnqualifiedName(type, name), null);
						foreach (IServiceListener listener in serviceListenerList)
						{
							listener.ServiceAdded(this, event_Renamed);
						}
					}
					else
					{
						// expire record
						ServiceEvent event_Renamed = new ServiceEvent(this, type, ToUnqualifiedName(type, name), null);
						foreach (IServiceListener listener in serviceListenerList)
						{
							listener.ServiceRemoved(this, event_Renamed);
						}
					}
				}
			}
		}
예제 #38
0
파일: Address.cs 프로젝트: pisker/mDNS
		internal virtual bool SameName(DNSRecord other)
		{
			return name.ToUpper().Equals(((Address) other).name.ToUpper());
		}
예제 #39
0
파일: DNSRecord.cs 프로젝트: pisker/mDNS
		/// <summary> True if this record has the same type as some other record.</summary>
		internal virtual bool SameType(DNSRecord other)
		{
			return type == other.type;
		}
예제 #40
0
파일: mDNS.cs 프로젝트: rajeshwarn/mDNS
        /// <summary> Handle an incoming response. Cache answers, and pass them on to
        /// the appropriate questions.
        /// </summary>
        internal void HandleResponse(DNSIncoming msg)
        {
            long now = (DateTime.Now.Ticks - 621355968000000000) / 10000;

            bool hostConflictDetected    = false;
            bool serviceConflictDetected = false;

            for (int recIdx = 0; recIdx < msg.answers.Count; recIdx++)
            {
                DNSRecord rec           = (DNSRecord)msg.answers[recIdx];
                bool      isInformative = false;
                bool      expired       = rec.IsExpired(now);

                // update the cache
                DNSRecord c = (DNSRecord)cache.get_Renamed(rec);
                if (c != null)
                {
                    if (expired)
                    {
                        isInformative = true;
                        cache.remove(c);
                    }
                    else
                    {
                        c.ResetTTL(rec);
                        rec = c;
                        msg.answers[recIdx] = c;                         // put back into collection
                    }
                }
                else
                {
                    if (!expired)
                    {
                        isInformative = true;
                        cache.add(rec);
                    }
                }
                switch (rec.type)
                {
                case DNSConstants.TYPE_PTR:
                    // handle _mdns._udp records
                    if (rec.Name.IndexOf("._mdns._udp.") >= 0)
                    {
                        if (!expired && rec.name.StartsWith("_services._mdns._udp."))
                        {
                            isInformative = true;
                            RegisterServiceType(((Pointer)rec).alias);
                        }
                        continue;
                    }
                    RegisterServiceType(rec.name);
                    break;
                }

                if ((rec.GetEntryType() == DNSConstants.TYPE_A) || (rec.GetEntryType() == DNSConstants.TYPE_AAAA))
                {
                    hostConflictDetected |= rec.HandleResponse(this);
                }
                else
                {
                    serviceConflictDetected |= rec.HandleResponse(this);
                }

                // notify the listeners
                if (isInformative)
                {
                    UpdateRecord(now, rec);
                }
            }

            if (hostConflictDetected || serviceConflictDetected)
            {
                new Prober(this).start();
            }
        }
예제 #41
0
        public void Run(object state)
        {
            DNSOutgoing out_Renamed = null;

            try
            {
                // send probes for JmDNS itself
                if (Enclosing_Instance.State == taskState)
                {
                    if (out_Renamed == null)
                    {
                        out_Renamed = new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
                    }
                    DNSRecord answer = Enclosing_Instance.localHost.DNS4AddressRecord;
                    if (answer != null)
                    {
                        out_Renamed.AddAnswer(answer, 0);
                    }
                    answer = Enclosing_Instance.localHost.DNS6AddressRecord;
                    if (answer != null)
                    {
                        out_Renamed.AddAnswer(answer, 0);
                    }
                    Enclosing_Instance.AdvanceState();
                }
                // send announces for services
                // Defensively copy the services into a local list,
                // to prevent race conditions with methods registerService
                // and unregisterService.
                IList list;
                lock (Enclosing_Instance)
                {
                    list = new ArrayList(Enclosing_Instance.services.Values);
                }
                foreach (ServiceInfo info in list)
                {
                    lock (info)
                    {
                        if (info.State == taskState && info.task == this)
                        {
                            info.AdvanceState();
                            logger.Debug("run() JmDNS announcing " + info.QualifiedName + " state " + info.State);
                            if (out_Renamed == null)
                            {
                                out_Renamed = new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
                            }
                            out_Renamed.AddAnswer(new Pointer(info.type, DNSConstants.TYPE_PTR, DNSConstants.CLASS_IN, DNSConstants.DNS_TTL, info.QualifiedName), 0);
                            out_Renamed.AddAnswer(new Service(info.QualifiedName, DNSConstants.TYPE_SRV, DNSConstants.CLASS_IN, DNSConstants.DNS_TTL, info.priority, info.weight, info.port, Enclosing_Instance.localHost.Name), 0);
                            out_Renamed.AddAnswer(new Text(info.QualifiedName, DNSConstants.TYPE_TXT, DNSConstants.CLASS_IN, DNSConstants.DNS_TTL, info.text), 0);
                        }
                    }
                }
                if (out_Renamed != null)
                {
                    logger.Debug("run() JmDNS announcing #" + taskState);
                    Enclosing_Instance.Send(out_Renamed);
                }
                else
                {
                    // If we have nothing to send, another timer taskState ahead
                    // of us has done the job for us. We can cancel.
                    cancel();
                }
            }
            catch (Exception e)
            {
                logger.Warn("run() exception ", e);
                Enclosing_Instance.Recover();
            }

            taskState = taskState.Advance();
            if (!taskState.Announcing)
            {
                cancel();

                new Renewer(enclosingInstance).start();
            }
        }
예제 #42
0
 /// <summary> Reset the TTL of a record. This avoids having to
 /// update the entire record in the cache.
 /// </summary>
 internal virtual void ResetTTL(DNSRecord other)
 {
     created = other.created;
     ttl     = other.ttl;
 }
예제 #43
0
파일: mDNS.cs 프로젝트: pisker/mDNS
		/// <summary> Add an answer to a question. Deal with the case when the
		/// outgoing packet overflows
		/// </summary>
		internal virtual DNSOutgoing AddAnswer(DNSIncoming in_Renamed, IPAddress addr, int port, DNSOutgoing out_Renamed, DNSRecord rec)
		{
			if (out_Renamed == null)
			{
				out_Renamed = new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
			}
			try
			{
				out_Renamed.AddAnswer(in_Renamed, rec);
			}
			catch
			{
				out_Renamed.flags |= DNSConstants.FLAGS_TC;
				out_Renamed.id = in_Renamed.id;
				out_Renamed.Finish();
				Send(out_Renamed);
				
				out_Renamed = new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA);
				out_Renamed.AddAnswer(in_Renamed, rec);
			}
			return out_Renamed;
		}
예제 #44
0
파일: ServiceInfo.cs 프로젝트: pisker/mDNS
		// REMIND: Oops, this shouldn't be public!
		/// <summary> JmDNS callback to update a DNS record.</summary>
		public virtual void UpdateRecord(mDNS jmdns, long now, DNSRecord rec)
		{
			if ((rec != null) && !rec.IsExpired(now))
			{
				switch (rec.type)
				{
					
					case DNSConstants.TYPE_A: 
					// IPv4
					case DNSConstants.TYPE_AAAA:  // IPv6 FIXME [PJYF Oct 14 2004] This has not been tested
						if (rec.name.Equals(server))
						{
							addr = ((Address) rec).IPAddress;
						}
						break;
					
					case DNSConstants.TYPE_SRV: 
						if (rec.name.Equals(QualifiedName))
						{
							Service srv = (Service) rec;
							server = srv.server;
							port = srv.port;
							weight = srv.weight;
							priority = srv.priority;
							addr = null;
							// changed to use getCache() instead - jeffs
							// updateRecord(jmdns, now, (DNSRecord)jmdns.cache.get(server, TYPE_A, CLASS_IN));
							UpdateRecord(jmdns, now, (DNSRecord) jmdns.Cache.get_Renamed(server, DNSConstants.TYPE_A, DNSConstants.CLASS_IN));
						}
						break;
					
					case DNSConstants.TYPE_TXT: 
						if (rec.name.Equals(QualifiedName))
						{
							Text txt = (Text) rec;
							text = txt.text;
						}
						break;
					}
				// Future Design Pattern
				// This is done, to notify the wait loop in method
				// JmDNS.getServiceInfo(type, name, timeout);
				if (HasData && dns != null)
				{
					dns.HandleServiceResolved(this);
					dns = null;
				}
				lock (this)
				{
					Monitor.PulseAll(this);
				}
			}
		}
예제 #45
0
 /// <summary> True if this record has the same type as some other record.</summary>
 internal virtual bool SameType(DNSRecord other)
 {
     return(type == other.type);
 }
예제 #46
0
        public void Run(object state)
        {
            lock (Enclosing_Instance.IOLock)
            {
                if (Enclosing_Instance.PlannedAnswer == in_Renamed)
                {
                    Enclosing_Instance.PlannedAnswer = null;
                }

                // We use these sets to prevent duplicate records
                // FIXME - This should be moved into DNSOutgoing
                // TODO: check these for compatibility
                SupportClass.HashSetSupport questions = new SupportClass.HashSetSupport();
                SupportClass.HashSetSupport answers   = new SupportClass.HashSetSupport();


                if (Enclosing_Instance.State == DNSState.ANNOUNCED)
                {
                    try
                    {
                        long now            = (DateTime.Now.Ticks - 621355968000000000) / 10000;
                        long expirationTime = now + 1;                         //=now+DNSConstants.KNOWN_ANSWER_TTL;
                        bool isUnicast      = (port != DNSConstants.MDNS_PORT);


                        // Answer questions
                        foreach (DNSEntry entry in in_Renamed.questions)
                        {
                            if (entry is DNSQuestion)
                            {
                                DNSQuestion q = (DNSQuestion)entry;

                                // for unicast responses the question must be included
                                if (isUnicast)
                                {
                                    //out.addQuestion(q);
                                    questions.Add(q);
                                }

                                int type = q.type;
                                if (type == DNSConstants.TYPE_ANY || type == DNSConstants.TYPE_SRV)
                                {
                                    // I ama not sure of why there is a special case here [PJYF Oct 15 2004]
                                    if (Enclosing_Instance.localHost.Name.ToUpper().Equals(q.Name.ToUpper()))
                                    {
                                        // type = DNSConstants.TYPE_A;
                                        DNSRecord answer = Enclosing_Instance.localHost.DNS4AddressRecord;
                                        if (answer != null)
                                        {
                                            answers.Add(answer);
                                        }
                                        answer = Enclosing_Instance.localHost.DNS6AddressRecord;
                                        if (answer != null)
                                        {
                                            answers.Add(answer);
                                        }
                                        type = DNSConstants.TYPE_IGNORE;
                                    }
                                    else if (Enclosing_Instance.serviceTypes.Contains(q.Name.ToLower()))
                                    {
                                        type = DNSConstants.TYPE_PTR;
                                    }
                                }

                                switch (type)
                                {
                                case DNSConstants.TYPE_A:
                                {
                                    // Answer a query for a domain name
                                    //out = addAnswer( in, addr, port, out, host );
                                    DNSRecord answer = Enclosing_Instance.localHost.DNS4AddressRecord;
                                    if (answer != null)
                                    {
                                        answers.Add(answer);
                                    }
                                    break;
                                }

                                case DNSConstants.TYPE_AAAA:
                                {
                                    // Answer a query for a domain name
                                    DNSRecord answer = Enclosing_Instance.localHost.DNS6AddressRecord;
                                    if (answer != null)
                                    {
                                        answers.Add(answer);
                                    }
                                    break;
                                }

                                case DNSConstants.TYPE_PTR:
                                {
                                    // Answer a query for services of a given type

                                    // find matching services
                                    foreach (ServiceInfo info in Enclosing_Instance.services.Values)
                                    {
                                        if (info.State == DNSState.ANNOUNCED)
                                        {
                                            if (q.name.ToUpper().Equals(info.type.ToUpper()))
                                            {
                                                DNSRecord answer = Enclosing_Instance.localHost.DNS4AddressRecord;
                                                if (answer != null)
                                                {
                                                    answers.Add(answer);
                                                }
                                                answer = Enclosing_Instance.localHost.DNS6AddressRecord;
                                                if (answer != null)
                                                {
                                                    answers.Add(answer);
                                                }
                                                answers.Add(new Pointer(info.type, DNSConstants.TYPE_PTR, DNSConstants.CLASS_IN, DNSConstants.DNS_TTL, info.QualifiedName));
                                                answers.Add(new Service(info.QualifiedName, DNSConstants.TYPE_SRV, DNSConstants.CLASS_IN | DNSConstants.CLASS_UNIQUE, DNSConstants.DNS_TTL, info.priority, info.weight, info.port, Enclosing_Instance.localHost.Name));
                                                answers.Add(new Text(info.QualifiedName, DNSConstants.TYPE_TXT, DNSConstants.CLASS_IN | DNSConstants.CLASS_UNIQUE, DNSConstants.DNS_TTL, info.text));
                                            }
                                        }
                                    }
                                    if (q.name.ToUpper().Equals("_services._mdns._udp.local.".ToUpper()))
                                    {
                                        foreach (String s in Enclosing_Instance.serviceTypes.Values)
                                        {
                                            answers.Add(new Pointer("_services._mdns._udp.local.", DNSConstants.TYPE_PTR, DNSConstants.CLASS_IN, DNSConstants.DNS_TTL, s));
                                        }
                                    }
                                    break;
                                }

                                case DNSConstants.TYPE_SRV:
                                case DNSConstants.TYPE_ANY:
                                case DNSConstants.TYPE_TXT:
                                {
                                    ServiceInfo info = (ServiceInfo)Enclosing_Instance.services[q.name.ToLower()];
                                    if (info != null && info.State == DNSState.ANNOUNCED)
                                    {
                                        DNSRecord answer = Enclosing_Instance.localHost.DNS4AddressRecord;
                                        if (answer != null)
                                        {
                                            answers.Add(answer);
                                        }
                                        answer = Enclosing_Instance.localHost.DNS6AddressRecord;
                                        if (answer != null)
                                        {
                                            answers.Add(answer);
                                        }
                                        answers.Add(new Pointer(info.type, DNSConstants.TYPE_PTR, DNSConstants.CLASS_IN, DNSConstants.DNS_TTL, info.QualifiedName));
                                        answers.Add(new Service(info.QualifiedName, DNSConstants.TYPE_SRV, DNSConstants.CLASS_IN | DNSConstants.CLASS_UNIQUE, DNSConstants.DNS_TTL, info.priority, info.weight, info.port, Enclosing_Instance.localHost.Name));
                                        answers.Add(new Text(info.QualifiedName, DNSConstants.TYPE_TXT, DNSConstants.CLASS_IN | DNSConstants.CLASS_UNIQUE, DNSConstants.DNS_TTL, info.text));
                                    }
                                    break;
                                }

                                default:
                                {
                                    //Console.WriteLine("JmDNSResponder.unhandled query:"+q);
                                    break;
                                }
                                }
                            }
                        }


                        // remove known answers, if the ttl is at least half of
                        // the correct value. (See Draft Cheshire chapter 7.1.).
                        foreach (DNSRecord knownAnswer in in_Renamed.answers)
                        {
                            bool tempBoolean;
                            tempBoolean = answers.Contains(knownAnswer);
                            answers.Remove(knownAnswer);
                            if (knownAnswer.ttl > DNSConstants.DNS_TTL / 2 && tempBoolean)
                            {
                                logger.Debug("JmDNS Responder Known Answer Removed");
                            }
                        }


                        // responde if we have answers
                        if (answers.Count != 0)
                        {
                            logger.Debug("run() JmDNS responding");
                            DNSOutgoing out_Renamed = null;
                            if (isUnicast)
                            {
                                out_Renamed = new DNSOutgoing(DNSConstants.FLAGS_QR_RESPONSE | DNSConstants.FLAGS_AA, false);
                            }

                            foreach (DNSQuestion question in questions)
                            {
                                out_Renamed.AddQuestion(question);
                            }
                            foreach (DNSRecord answer in answers)
                            {
                                out_Renamed = Enclosing_Instance.AddAnswer(in_Renamed, addr, port, out_Renamed, answer);
                            }
                            Enclosing_Instance.Send(out_Renamed);
                        }
                        // TODO: do we need this?
                        //cancel();
                    }
                    catch (Exception e)
                    {
                        logger.Warn("run() exception ", e);
                        Enclosing_Instance.Close();
                    }
                }
            }
        }
예제 #47
0
 /// <summary> Check if this question is answered by a given DNS record.</summary>
 internal bool IsAnsweredBy(DNSRecord rec)
 {
     return((clazz == rec.clazz) && ((type == rec.type) || (type == DNSConstants.TYPE_ANY)) && name.Equals(rec.name));
 }