
    	^c                        d Z 	 	 	 	 	 	 	 	 	 dZdZdZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlmZ g dZd e            d<   d	Zd
ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!dZ"dZ#dZ$dZ%dZ&dZ'dZ(dZ)d Z*d!Z+dZ,dZ-dZ.dZ/dZ0d"Z1d#Z2d$Z3d%Z4d&Z5d'Z6d(Z7d)Z8d*Z9d+Z:d,Z;dZ<d-Z=d.Z>d Z?e%d/e&d0e'd1e(d2e)d3e*d4iZ@i e-d5e.d6e/d7e0d8e1d9e2d:e3d;e4d<e5d=e6d>e7d?e8d@e9dAe:dBe;dCe<dDe=dEe>dFe?d4iZAdG ZB G dH dIeC          ZD G dJ dKeC          ZE G dL dMeC          ZF G dN dOeC          ZG G dP dQeC          ZH G dR dSeC          ZI G dT dUeI          ZJ G dV dW          ZK G dX dYeK          ZL G dZ d[eK          ZM G d\ d]eM          ZN G d^ d_eM          ZO G d` daeM          ZP G db dceM          ZQ G dd deeM          ZR G df dg          ZS G dh di          ZT G dj dk          ZU G dl dme	jV                  ZW G dn do          ZX G dp dqe	jV                  ZY G dr dse	jV                  ZZ G dt du          Z[ G dv dw          Z\e]dxk    r0 e^dye            e\            Z_ e^dz           d{d|d}d~Z` e[dd eja        d          ddde`          Zb e^d           e_c                    eb            e^d            e^d            e^d ede_e                    dd                                e^d            e^d            e^d ede_e                    dd                                e^d            e^d           e_f                    eb            e^d           e_g                                 dS dS )a   Multicast DNS Service Discovery for Python, v0.12
    Copyright (C) 2003, Paul Scott-Murphy

    This module provides a framework for the use of DNS Service Discovery
    using IP multicast.  It has been tested against the JRendezvous
    implementation from <a href="http://strangeberry.com">StrangeBerry</a>,
    and against the mDNSResponder from Mac OS X 10.3.8.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, see
    <http://www.gnu.org/licenses/>.

s   Paul Scott-Murphys!   paul at scott dash murphy dot coms   0.12    N)pycompat)s   Zeroconfs   ServiceInfos   ServiceBrowser   _GLOBAL_DONE}            i  z224.0.0.251i  5   i  i  i#  i   i   i      @                            i              	   
                     !   s   ins   css   chs   hss   nones   any   as   nss   mds   mfs   cnames   soas   mbs   mgs   mrs   nulls   wkss   ptrs   hinfos   minfos   mxs   txts   quadas   srvc                  .    t          j                     dz  S )z#Current system time in milliseconds  )time     9/usr/lib/python3/dist-packages/hgext/zeroconf/Zeroconf.pycurrentTimeMillisr(      s    9;;r&   c                       e Zd ZdS )NonLocalNameExceptionN__name__
__module____qualname__r%   r&   r'   r*   r*              Dr&   r*   c                       e Zd ZdS )NonUniqueNameExceptionNr+   r%   r&   r'   r1   r1      r/   r&   r1   c                       e Zd ZdS )NamePartTooLongExceptionNr+   r%   r&   r'   r3   r3      r/   r&   r3   c                       e Zd ZdS )AbstractMethodExceptionNr+   r%   r&   r'   r5   r5      r/   r&   r5   c                       e Zd ZdS )BadTypeInNameExceptionNr+   r%   r&   r'   r7   r7      r/   r&   r7   c                       e Zd Zd ZdS )BadDomainNamec                 B    t                               | d|z             d S )Ns   at position %s)	Exception__init__)selfposs     r'   r<   zBadDomainName.__init__   s$    4!2S!899999r&   N)r,   r-   r.   r<   r%   r&   r'   r9   r9      s#        : : : : :r&   r9   c                       e Zd ZdS )BadDomainNameCircularNr+   r%   r&   r'   r@   r@      r/   r&   r@   c                   6    e Zd ZdZd Zd Zd Zd Zd Zd Z	dS )	DNSEntryzA DNS entryc                     |                                 | _        || _        || _        |t          z  | _        |t          z  dk    | _        d S )Nr   )lowerkeynametype_CLASS_MASKclazz_CLASS_UNIQUEuniquer=   rF   rG   rI   s       r'   r<   zDNSEntry.__init__   s@    ::<<		[(
},2r&   c                     t          |t                    r0| j        |j        k    o| j        |j        k    o| j        |j        k    S dS )z&Equality test on name, type, and classr   )
isinstancerB   rF   rG   rI   r=   others     r'   __eq__zDNSEntry.__eq__   sN    eX&& 		UZ' .I+.J%+-
 qr&   c                 .    |                      |           S zNon-equality testrQ   rO   s     r'   __ne__zDNSEntry.__ne__       ;;u%%%%r&   c                 H    	 t           |         S # t          $ r d|z  cY S w xY w)zClass accessor   ?(%s))_CLASSESKeyError)r=   rI   s     r'   getClazzzDNSEntry.getClazz  s=    	$E?" 	$ 	$ 	$e####	$    !!c                 H    	 t           |         S # t          $ r d|z  cY S w xY w)Type accessorrX   )_TYPESrZ   )r=   rG   s     r'   getTypezDNSEntry.getType	  s<    	#$< 	# 	# 	#d?"""	#r\   c                     d||                      | j                  |                     | j                  fz  }| j        r|dz  }n|dz  }|| j        z  }|	|d|z  z  }n|dz  }|S )1String representation with additional informations   %s[%s,%ss   -unique,   ,Ns   ,%s]   ])r`   rG   r[   rI   rK   rF   )r=   hdrrP   results       r'   toStringzDNSEntry.toString  s    LL##MM$*%% 
 

 ; 	k!FFdNF$)go%FFdNFr&   N)
r,   r-   r.   __doc__r<   rQ   rU   r[   r`   rg   r%   r&   r'   rB   rB      st        3 3 3  & & &$ $ $# # #    r&   rB   c                   $    e Zd ZdZd Zd Zd ZdS )DNSQuestionzA DNS question entryc                     t          |t                    r|                    d          }|                    d          st	          |          t
                              | |||           d S )Nasciis   .local.)rN   strencodeendswithr*   rB   r<   rL   s       r'   r<   zDNSQuestion.__init__&  sg    dC   	(;;w''D}}Z(( 	.'---$dE22222r&   c                     | j         |j         k    o/| j        |j        k    p| j        t          k    o| j        |j        k    S )z6Returns true if the question is answered by the record)rI   rG   	_TYPE_ANYrF   )r=   recs     r'   
answeredByzDNSQuestion.answeredBy-  sC     J#)# &ch&@$)y*@&	SX%	
r&   c                 :    t                               | dd          S )String representations   questionN)rB   rg   r=   s    r'   __repr__zDNSQuestion.__repr__5  s      {D999r&   N)r,   r-   r.   rh   r<   rs   rw   r%   r&   r'   rj   rj   #  sG        3 3 3
 
 
: : : : :r&   rj   c                   T    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd ZdS )	DNSRecordz.A DNS record - like a DNS entry, but has a TTLc                 t    t                               | |||           || _        t                      | _        d S N)rB   r<   ttlr(   created)r=   rF   rG   rI   r|   s        r'   r<   zDNSRecord.__init__=  s4    $dE222(**r&   c                 f    t          |t                    rt                              | |          S dS )zTests equality as per DNSRecordr   )rN   ry   rB   rQ   rO   s     r'   rQ   zDNSRecord.__eq__B  s-    eY'' 	0??4///qr&   c                 J    |j         D ]}|                     |          r dS dS )zdReturns true if any answer in a message can suffice for the
        information held in this record.r   r   )answerssuppressedByAnswer)r=   msgrecords      r'   suppressedByzDNSRecord.suppressedByH  s<     k 	 	F&&v.. qqqr&   c                 <    | |k    r|j         | j         dz  k    rdS dS )zwReturns true if another record has same name, type and class,
        and if its TTL is at least half of this record's.r   r   r   )r|   rO   s     r'   r   zDNSRecord.suppressedByAnswerP  s)     5==UY$(Q,771qr&   c                 ,    | j         || j        z  dz  z   S )zXReturns the time at which this record will have expired
        by a certain percentage.r   r}   r|   )r=   percents     r'   getExpirationTimezDNSRecord.getExpirationTimeW  s     |w1B677r&   c                 T    t          d|                     d          |z
  dz            S )z%Returns the remaining TTL in seconds.r   d   r#   )maxr   r=   nows     r'   getRemainingTTLzDNSRecord.getRemainingTTL\  s*    1t--c22S8D@AAAr&   c                 4    |                      d          |k    S )z(Returns true if this record has expired.r   r   r   s     r'   	isExpiredzDNSRecord.isExpired`  s    %%c**c11r&   c                 4    |                      d          |k    S )z9Returns true if this record is at least half way expired.2   r   r   s     r'   isStalezDNSRecord.isStaled  s    %%b))S00r&   c                 6    |j         | _         |j        | _        dS )zJSets this record's TTL and created time to that of
        another record.Nr   rO   s     r'   resetTTLzDNSRecord.resetTTLh  s     }9r&   c                     t           )zAbstract method)r5   r=   outs     r'   writezDNSRecord.writen  s    %%r&   c                     d| j         |                     t                                |fz  }t                              | d|          S )rb   s   %s/%s,%ss   record)r|   r   r(   rB   rg   )r=   rP   args      r'   rg   zDNSRecord.toStringr  sK    H  !2!4!455
 

   y#666r&   N)r,   r-   r.   rh   r<   rQ   r   r   r   r   r   r   r   r   rg   r%   r&   r'   ry   ry   :  s        88+ + +
      8 8 8
B B B2 2 21 1 1  & & &7 7 7 7 7r&   ry   c                   *    e Zd ZdZd Zd Zd Zd ZdS )
DNSAddresszA DNS address recordc                 P    t                               | ||||           || _        d S r{   )ry   r<   address)r=   rF   rG   rI   r|   r   s         r'   r<   zDNSAddress.__init__  s)    4tUC888r&   c                 `    |                     | j        t          | j                             dS z'Used in constructing an outgoing packetN)writeStringr   lenr   s     r'   r   zDNSAddress.write  s(    c$,&7&788888r&   c                 P    t          |t                    r| j        |j        k    S dS )zTests equality on addressr   )rN   r   r   rO   s     r'   rQ   zDNSAddress.__eq__  s(    eZ(( 	1<5=00qr&   c                 d    	 t          j        | j                  S # t          $ r
 | j        cY S w xY wru   )socket	inet_ntoar   r;   rv   s    r'   rw   zDNSAddress.__repr__  sC    	 #DL111 	  	  	 <	 s    //Nr,   r-   r.   rh   r<   r   rQ   rw   r%   r&   r'   r   r   |  sV          9 9 9           r&   r   c                   *    e Zd ZdZd Zd Zd Zd ZdS )DNSHinfozA DNS host information recordc                 ^    t                               | ||||           || _        || _        d S r{   )ry   r<   cpuos)r=   rF   rG   rI   r|   r   r   s          r'   r<   zDNSHinfo.__init__  s0    4tUC888r&   c                     |                     | j        t          | j                             |                     | j        t          | j                             dS r   )r   r   r   r   r   s     r'   r   zDNSHinfo.write  sD    #dh--000TW.....r&   c                 p    t          |t                    r | j        |j        k    o| j        |j        k    S dS )zTests equality on cpu and osr   )rN   r   r   r   rO   s     r'   rQ   zDNSHinfo.__eq__  s7    eX&& 	A8uy(@TW-@@qr&   c                 &    | j         dz   | j        z   S )ru       )r   r   rv   s    r'   rw   zDNSHinfo.__repr__  s    x$((r&   Nr   r%   r&   r'   r   r     sV        ''  
/ / /
  ) ) ) ) )r&   r   c                   *    e Zd ZdZd Zd Zd Zd ZdS )
DNSPointerzA DNS pointer recordc                 P    t                               | ||||           || _        d S r{   )ry   r<   alias)r=   rF   rG   rI   r|   r   s         r'   r<   zDNSPointer.__init__  s)    4tUC888


r&   c                 :    |                     | j                   dS r   )	writeNamer   r   s     r'   r   zDNSPointer.write  s    dj!!!!!r&   c                 P    t          |t                    r| j        |j        k    S dS )zTests equality on aliasr   )rN   r   r   rO   s     r'   rQ   zDNSPointer.__eq__  s(    eZ(( 	-:,,qr&   c                 6    |                      | j                  S r   )rg   r   rv   s    r'   rw   zDNSPointer.__repr__  s    }}TZ(((r&   Nr   r%   r&   r'   r   r     sV          " " "  ) ) ) ) )r&   r   c                   *    e Zd ZdZd Zd Zd Zd ZdS )DNSTextzA DNS text recordc                 P    t                               | ||||           || _        d S r{   )ry   r<   text)r=   rF   rG   rI   r|   r   s         r'   r<   zDNSText.__init__  s)    4tUC888			r&   c                 `    |                     | j        t          | j                             dS r   )r   r   r   r   s     r'   r   zDNSText.write  s&    	3ty>>22222r&   c                 P    t          |t                    r| j        |j        k    S dS )zTests equality on textr   )rN   r   r   rO   s     r'   rQ   zDNSText.__eq__  s(    eW%% 	+9
**qr&   c                     t          | j                  dk    r%|                     | j        dd         dz             S |                     | j                  S )ru   r   Nr      ...)r   r   rg   rv   s    r'   rw   zDNSText.__repr__  sJ    ty>>B==2A2!7888==+++r&   Nr   r%   r&   r'   r   r     sV          3 3 3  , , , , ,r&   r   c                   *    e Zd ZdZd Zd Zd Zd ZdS )
DNSServicezA DNS service recordc	                 z    t                               | ||||           || _        || _        || _        || _        d S r{   )ry   r<   priorityweightportserver)	r=   rF   rG   rI   r|   r   r   r   r   s	            r'   r<   zDNSService.__init__  s>    4tUC888 	r&   c                     |                     | j                   |                     | j                   |                     | j                   |                    | j                   dS r   )
writeShortr   r   r   r   r   r   s     r'   r   zDNSService.write  sX    t}%%%t{###ty!!!dk"""""r&   c                     t          |t                    r@| j        |j        k    o/| j        |j        k    o| j        |j        k    o| j        |j        k    S dS )z3Tests equality on priority, weight, port and serverr   )rN   r   r   r   r   r   rO   s     r'   rQ   zDNSService.__eq__  sa    eZ(( 	/ 0K5</0I+0 K5</	 qr&   c                 J    |                      d| j        | j        fz            S )ru   s   %s:%s)rg   r   r   rv   s    r'   rw   zDNSService.__repr__  s"    }}Xdi(@@AAAr&   Nr   r%   r&   r'   r   r     s[          # # #	 	 	B B B B Br&   r   c                   Z    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
 Zd Zd Zd ZdS )DNSIncomingz/Object representation of an incoming DNS packetc                     d| _         || _        g | _        g | _        d| _        d| _        d| _        d| _        |                                  | 	                                 | 
                                 dS )z/Constructor from string holding bytes of packetr   N)offsetdata	questionsr   numquestions
numanswersnumauthoritiesnumadditionals
readHeaderreadQuestions
readOthers)r=   r   s     r'   r<   zDNSIncoming.__init__   su    	r&   c                 L   d}t          j        |          }t          j        || j        | j        | j        |z                      }| xj        |z  c_        |d         | _        |d         | _        |d         | _        |d         | _        |d         | _	        |d         | _
        dS )	zReads header portion of packets   !HHHHHHr   r   r   r   r   r   N)structcalcsizeunpackr   r   idflagsr   r   r   r   r=   formatlengthinfos       r'   r   zDNSIncoming.readHeader  s    ((}DIdkDK&,@@A
 
 	vq'!W
 Gq'"1g"1gr&   c                    d}t          j        |          }t          d| j                  D ]}|                                 }t          j        || j        | j        | j        |z                      }| xj        |z  c_        	 t          ||d         |d                   }| j	        
                    |           # t          $ r Y w xY wdS )z!Reads questions section of packets   !HHr   r   N)r   r   ranger   readNamer   r   r   rj   r   appendr*   )r=   r   r   irF   r   questions          r'   r   zDNSIncoming.readQuestions  s    ((q$+,, 	 	A==??D=	$+f0D"DE D KK6!KK&tT!Wd1g>>%%h////(   	 	s   7B::
CCc                     d}t          j        |          }t          j        || j        | j        | j        |z                      }| xj        |z  c_        |d         S )z Reads an integer from the packet   !Ir   r   r   r   r   r   r   s       r'   readIntzDNSIncoming.readInt0  \    ((}DIdkDK&,@@A
 
 	vAwr&   c                     t          | j        | j                           }| xj        dz  c_        |                     |          S )z(Reads a character string from the packetr   )ordr   r   
readString)r=   r   s     r'   readCharacterStringzDNSIncoming.readCharacterString:  s:    TYt{+,,qv&&&r&   c                     d|z  }t          j        |          }t          j        || j        | j        | j        |z                      }| xj        |z  c_        |d         S )z0Reads a string of a given length from the packets   !%dsr   r   )r=   r   r   r   r   s        r'   r   zDNSIncoming.readString@  s`    3((}DIdkDK&,@@A
 
 	vAwr&   c                     d}t          j        |          }t          j        || j        | j        | j        |z                      }| xj        |z  c_        |d         S )z'Reads an unsigned short from the packet   !Hr   r   r   s       r'   readUnsignedShortzDNSIncoming.readUnsignedShortJ  r   r&   c                    d}t          j        |          }| j        | j        z   | j        z   }t          d|          D ]}|                                 }t          j        || j        | j	        | j	        |z                      }| xj	        |z  c_	        d}|d         t          k    r:t          ||d         |d         |d         |                     d                    }n|d         t          k    s|d         t          k    r9t          ||d         |d         |d         |                                           }n|d         t           k    r@t#          ||d         |d         |d         |                     |d                             }n>|d         t$          k    rqt'          ||d         |d         |d         |                                 |                                 |                                 |                                           }n|d         t*          k    rKt-          ||d         |d         |d         |                                 |                                           }n`|d         t0          k    r9t          ||d         |d         |d         |                     d                    }n| xj	        |d         z  c_	        || j                            |           dS )	z@Reads answers, authorities and additionals section of the packets   !HHiHr   Nr   r   r   r   r   )r   r   r   r   r   r   r   r   r   r   _TYPE_Ar   r   _TYPE_CNAME	_TYPE_PTRr   	_TYPE_TXTr   	_TYPE_SRVr   r   _TYPE_HINFOr   r   
_TYPE_AAAAr   r   )r=   r   r   nr   domainr   rr   s           r'   r   zDNSIncoming.readOthersT  s   ((Od11D4GGq! 8	) 8	)A]]__F=	$+f0D"DE D KK6!KKCAw'!! DGT!Wd1gtq7I7I  aK''47i+?+? DGT!Wd1gt}}  aI%%DGT!Wd1gttAw7O7O  aI%% GGG**,,**,,**,,MMOO	 	 aK''GGG,,..,,..  aJ&& DGT!Wd1gtr7J7J  tAw&##C(((q8	) 8	)r&   c                 2    | j         t          z  t          k    S )zReturns true if this is a query)r   _FLAGS_QR_MASK_FLAGS_QR_QUERYrv   s    r'   isQueryzDNSIncoming.isQuery  s    
^+??r&   c                 2    | j         t          z  t          k    S )z"Returns true if this is a response)r   r  _FLAGS_QR_RESPONSErv   s    r'   
isResponsezDNSIncoming.isResponse  s    
^+0BBBr&   c                 L    | j         |||z                                d          S )z6Reads a UTF-8 string of a given length from the packetutf-8)r   decode)r=   r   r   s      r'   readUTFzDNSIncoming.readUTF  s&    y&3,./66w???r&   c                    d}| j         }d}|}	 t          | j        ||dz                      }|dz  }|dk    rn|dz  }|dk    r4d                    ||                     ||          dz   f          }||z  }n`|dk    rK|dk     r|dz   }|dz  d	z  t          | j        ||dz                      z  }||k    rt          |          |}nt          |          |dk    r|| _         n|| _         |S )
z#Reads a domain name from the packet Tr   r      .?   r   )r   r   r   joinr  r@   r9   )r=   rf   offnextfirstr   ts          r'   r   zDNSIncoming.readName  s*   k	)dicAg.//C1HCaxxd
ADyy&$,,sC*@*@3*F!GHHs
d!887Dd
q(C	#a-0H,I,II%<</444#C(((#	)& 199DKKDKr&   N)r,   r-   r.   rh   r<   r   r   r   r   r   r   r   r  r
  r  r   r%   r&   r'   r   r     s        99  & & &   "  ' ' '    =) =) =)~@ @ @C C C@ @ @    r&   r   c                   t    e Zd ZdZddZd Zd Zd Zd Zd Z	d	 Z
d
 Zd Zd Zd Zd Zd Zd Zd Zd ZdS )DNSOutgoingz+Object representation of an outgoing packetr   c                     d| _         d| _        || _        || _        i | _        g | _        d| _        g | _        g | _        g | _	        g | _
        d S )Nr   r   )finishedr   	multicastr   namesr   sizer   r   authoritiesadditionals)r=   r   r  s      r'   r<   zDNSOutgoing.__init__  sW    "

		r&   c                 :    | j                             |           dS )zAdds a questionN)r   r   r=   r   s     r'   addQuestionzDNSOutgoing.addQuestion  s    f%%%%%r&   c                 `    |                     |          s|                     |d           dS dS )zAdds an answerr   N)r   addAnswerAtTime)r=   inpr   s      r'   	addAnswerzDNSOutgoing.addAnswer  s>    ""3'' 	,  +++++	, 	,r&   c                     |9|dk    s|                     |          s | j                            ||f           dS dS dS )z6Adds an answer if if does not expire by a certain timeNr   )r   r   r   )r=   r   r   s      r'   r'  zDNSOutgoing.addAnswerAtTime  sP    axxv//44x##VSM22222 xr&   c                 :    | j                             |           dS )zAdds an authoritative answerN)r!  r   r$  s     r'   addAuthoritativeAnswerz"DNSOutgoing.addAuthoritativeAnswer      '''''r&   c                 :    | j                             |           dS )zAdds an additional answerN)r"  r   r$  s     r'   addAdditionalAnswerzDNSOutgoing.addAdditionalAnswer  r-  r&   c                     d}| j                             t          j        |t	          |                               | xj        dz  c_        dS )z"Writes a single byte to the packet   !cr   N)r   r   r   packchrr   r=   valuer   s      r'   	writeBytezDNSOutgoing.writeByte  B    	VSZZ88999		Q				r&   c                     d}| j                             |t          j        ||                     | xj        dz  c_        dS )z=Inserts an unsigned short in a certain position in the packetr   r   N)r   insertr   r2  r   )r=   indexr5  r   s       r'   insertShortzDNSOutgoing.insertShort  s>    	FE : :;;;		Q				r&   c                     d}| j                             t          j        ||                     | xj        dz  c_        dS )z&Writes an unsigned short to the packetr   r   N)r   r   r   r2  r   r4  s      r'   r   zDNSOutgoing.writeShort  s<    	VU33444		Q				r&   c                     d}| j                             t          j        |t	          |                               | xj        dz  c_        dS )z(Writes an unsigned integer to the packetr   r   N)r   r   r   r2  intr   r4  s      r'   writeIntzDNSOutgoing.writeInt  r7  r&   c                     dt          |          z   dz   }| j                            t          j        ||                     | xj        |z  c_        dS )zWrites a string to the packet!sN)rm   r   r   r   r2  r   )r=   r5  r   r   s       r'   r   zDNSOutgoing.writeString  sM    s6{{"S(	VU33444		V				r&   c                     |                     d          }t          |          }|dk    rt          |                     |           |                     ||           dS )z5Writes a UTF-8 string of a given length to the packetr  r   N)rn   r   r3   r6  r   )r=   rB  utfstrr   s       r'   writeUTFzDNSOutgoing.writeUTF  s[    '""VB;;**v(((((r&   c                 x   	 | j         |         }nz# t          $ rm | j        | j         |<   |                    d          }|d         dk    r
|dd         }|D ]}|                     |           |                     d           Y dS w xY w|                     |dz	  dz             |                     |           dS )z"Writes a domain name to the packet   .r  r&   Nr   r   r  )r  rZ   r   splitrE  r6  )r=   rF   r:  partsparts        r'   r   zDNSOutgoing.writeName  s    	 Jt$EE 	 	 	
  $yDJtJJt$$ERyCcrc
 $ $d####NN1FF	  	
d*+++us    A3BBc                     |                      |j                   |                     |j                   |                     |j                   dS )zWrites a question to the packetN)r   rF   r   rG   rI   )r=   r   s     r'   writeQuestionzDNSOutgoing.writeQuestion*  sD    x}%%%&&&'''''r&   c                    |                      |j                   |                     |j                   |j        r*| j        r#|                     |j        t          z             n|                     |j                   |dk    r|                     |j	                   n(|                     |
                    |                     t          | j                  }| xj        dz  c_        |                    |            | xj        dz  c_        t          d                    | j        |d                             }|                     ||           dS )zPWrites a record (answer, authoritative answer, additional) to
        the packetr   r   r&   N)r   rF   r   rG   rK   r  rI   rJ   r?  r|   r   r   r   r   r   r  r;  )r=   r   r   r:  r   s        r'   writeRecordzDNSOutgoing.writeRecord0  s.    	v{###$$$= 	*T^ 	*OOFL=89999OOFL)))!88MM&*%%%%MM&0055666DI 			Q		T		Q		SXXdi/0011'''''r&   c                 @   | j         s}d| _         | j        D ]}|                     |           | j        D ]\  }}|                     ||           | j        D ]}|                     |d           | j        D ]}|                     |d           |                     dt          | j                             |                     dt          | j                             |                     dt          | j                             |                     dt          | j                             |                     d| j	                   | j
        r|                     dd           n|                     d| j                   d                    | j                  S )zReturns a string containing the packet's bytes

        No further parts should be added to the packet once this
        is done.r   r   r&   )r  r   rL  r   rN  r!  r"  r;  r   r   r  r   r  r   )r=   r   answertime_	authority
additionals         r'   packetzDNSOutgoing.packetG  s   
 } 	-DM N - -""8,,,,!% 0 0  ////!- / /	  A....". 0 0
  Q////QD$4 5 5666QD$4 5 5666QDL 1 1222QDN 3 3444Q
+++~ -  A&&&&  DG,,,xx	"""r&   N)r   )r,   r-   r.   rh   r<   r%  r)  r'  r,  r/  r6  r;  r   r?  r   rE  r   rL  rN  rT  r%   r&   r'   r  r    s       55   & & &, , ,
3 3 3( ( (( ( (          ) ) )  4( ( (( ( (.# # # # #r&   r  c                   <    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
d	S )
DNSCachezA cache of DNS entriesc                     i | _         d S r{   )cacherv   s    r'   r<   zDNSCache.__init__f  s    


r&   c                     	 | j         |j                 }n!# t          $ r g x}| j         |j        <   Y nw xY w|                    |           dS )zAdds an entryN)rX  rE   rZ   r   r=   entrylists      r'   addzDNSCache.addi  sc    	.:ei(DD 	. 	. 	.+--D4:ei(((	.Es    33c                 x    	 | j         |j                 }|                    |           dS # t          $ r Y dS w xY w)zRemoves an entryN)rX  rE   removerZ   rZ  s      r'   r_  zDNSCache.removeq  sO    	:ei(DKK 	 	 	DD	s   '+ 
99c                     	 | j         |j                 }||                    |                   S # t          t          f$ r Y dS w xY w)zNGets an entry by key.  Will return None if there is no
        matching entry.N)rX  rE   r:  rZ   
ValueErrorrZ  s      r'   getzDNSCache.gety  sS    	:ei(D

5))***% 	 	 	44	s   ,/ AAc                 N    t          |||          }|                     |          S )zRGets an entry by details.  Will return None if there is
        no matching entry.)rB   rb  )r=   rF   rG   rI   r[  s        r'   getByDetailszDNSCache.getByDetails  s%     tU++xxr&   c                 B    	 | j         |         S # t          $ r g cY S w xY w)z5Returns a list of entries whose key matches the name.)rX  rZ   )r=   rF   s     r'   entriesWithNamezDNSCache.entriesWithName  s8    	:d## 	 	 	III	s    c                     	 t          t          j                            | j                                                            S # t          $ r g cY S w xY w)zReturns a list of all entries)r\  	itertoolschainfrom_iterablerX  valuesr;   rv   s    r'   entrieszDNSCache.entries  sW    		55dj6G6G6I6IJJKKK 	 	 	III	s   AA AAN)r,   r-   r.   rh   r<   r]  r_  rb  rd  rf  rl  r%   r&   r'   rV  rV  c  s                          r&   rV  c                   6    e Zd ZdZd Zd Zd Zd Zd Zd Z	dS )	Engineac  An engine wraps read access to sockets, allowing objects that
    need to receive data from sockets to be called back when the
    sockets are ready.

    A reader needs a handle_read() method, which is called when the socket
    it is interested in is ready for reading.

    Writers are not implemented here, because we only send short
    packets.
    c                     t           j                            |            || _        i | _        d| _        t          j                    | _        |                                  d S )Nr   )		threadingThreadr<   zeroconfreaderstimeout	Condition	conditionstartr=   rr  s     r'   r<   zEngine.__init__  sO    !!$''' ",..

r&   c                 l   t                      d         s|                                 }t          |          dk    rR| j                                         | j                            | j                   | j                                         n	 t          j        |g g | j                  \  }}}|D ]Y}	 | j	        |         
                                 ## t          $ r* t                      d         st          j                     Y Vw xY wn# t          $ r Y nw xY wt                      d         d S d S )Nr   r   )globals
getReadersr   rv  acquirewaitrt  releaseselectrs  handle_readr;   	traceback	print_exc)r=   rsrrwrersocks         r'   runz
Engine.run  sS   ))O, 	""B2ww!|| &&(((##DL111&&((((	!'r2r4<!H!HJBB " 6 66 L.::<<<<( 6 6 6#*99_#= 6 ) 3 5 5 566 !   D% ))O, 	 	 	 	 	s6   $D 5CD 1D	D D		D 
DDc                     | j                                          | j                                        }| j                                          |S r{   )rv  r|  rs  keysr~  r=   rf   s     r'   r{  zEngine.getReaders  sB       ""$$   r&   c                     | j                                          || j        |<   | j                                          | j                                          d S r{   rv  r|  rs  notifyr~  )r=   readerr   s      r'   	addReaderzEngine.addReader  sP       %V     r&   c                     | j                                          | j        |= | j                                          | j                                          d S r{   r  )r=   r   s     r'   	delReaderzEngine.delReader  sN       L      r&   c                     | j                                          | j                                          | j                                          d S r{   )rv  r|  r  r~  rv   s    r'   r  zEngine.notify  sD            r&   N)
r,   r-   r.   rh   r<   r  r{  r  r  r  r%   r&   r'   rn  rn    sx        	 	    ,  ! ! !! ! !! ! ! ! !r&   rn  c                       e Zd ZdZd Zd ZdS )Listenera4  A Listener is used by this module to listen on the multicast
    group to which DNS messages are sent, allowing the implementation
    to cache information as it arrives.

    It requires registration with an Engine object in order to have
    the read() method called when a socket is available for reading.c                 h    || _         | j         j                            | | j         j                   d S r{   )rr  enginer  r   rx  s     r'   r<   zListener.__init__  s/     &&tT]-ABBBBBr&   c                 X   | j         j        }	 |                    t                    \  }\  }}n3# t          j        $ r!}|j        t
          j        k    rY d }~d S  d }~ww xY w|| _        t          |          }|	                                r|t          k    r(| j                             |t          t                     d S |t          k    rD| j                             |||           | j                             |t          t                     d S d S | j                             |           d S r{   )rr  r   recvfrom_MAX_MSG_ABSOLUTEerrorerrnoEBADFr   r   r  
_MDNS_PORThandleQuery
_MDNS_ADDR	_DNS_PORThandleResponse)r=   r  r   addrr   er   s          r'   r  zListener.handle_read  s.   }#	!%/@!A!AD,4| 	 	 	w%+%%	 	$;;== 	. z!!))#z:FFFFF ""))#tT:::))#z:FFFFF #" M((-----s    / AAAAN)r,   r-   r.   rh   r<   r  r%   r&   r'   r  r    sA        H HC C C. . . . .r&   r  c                       e Zd ZdZd Zd ZdS )ReaperzNA Reaper is used by this module to remove cache entries that
    have expired.c                 z    t           j                            |            || _        |                                  d S r{   )rp  rq  r<   rr  rw  rx  s     r'   r<   zReaper.__init__  s1    !!$''' 

r&   c                 b   	 | j                             d           t                      d         rd S t                      }| j         j                                        D ]Q}|                    |          r:| j                             ||           | j         j                            |           R)NTi'  r   )	rr  r}  rz  r(   rX  rl  r   updateRecordr_  )r=   r   r   s      r'   r  z
Reaper.run	  s    	7My)))yy) #%%C--5577 7 7##C(( 7M..sF;;;M'..v666	7r&   N)r,   r-   r.   rh   r<   r  r%   r&   r'   r  r     s<           
	7 	7 	7 	7 	7r&   r  c                   *    e Zd ZdZd Zd Zd Zd ZdS )ServiceBrowserzUsed to browse for a service of a specific type.

    The listener object will have its addService() and
    removeService() methods called when this browser
    discovers changes in the services availability.c                 p   t           j                            |            || _        || _        || _        i | _        t                      | _        t          | _
        g | _        d| _        | j                            | t          | j        t          t                                |                                  dS )z%Creates a browser for a specific typer   N)rp  rq  r<   rr  rG   listenerservicesr(   nexttime_BROWSER_TIMEdelayr\  doneaddListenerrj   r   	_CLASS_INrw  )r=   rr  rG   r  s       r'   r<   zServiceBrowser.__init__  s    !!$''' 	 )++"
		!!+diI>>	
 	
 	
 	

r&   c                 v    j         t          k    r!j         j         k    r                    |          }	  j        j                                                 }|s|                               nA j        j                                        =  fd} j        	                    |           dS nS# t          $ rF |sA j        j                                        <    fd} j        	                    |           Y nw xY w                    d          }| j        k     r| _        dS dS dS dS )zCallback invoked by Zeroconf when new information arrives.

        Updates information required by browser in the Zeroconf cache.c                 P    j                             | j        j                  S r{   )r  removeServicerG   r   xr   r=   s    r'   <lambda>z-ServiceBrowser.updateRecord.<locals>.<lambda>:  s$    )D)D49fl* * r&   Nc                 P    j                             | j        j                  S r{   )r  
addServicerG   r   r  s    r'   r  z-ServiceBrowser.updateRecord.<locals>.<lambda>B  s$    )A)A49fl* * r&   K   )rG   r   rF   r   r  r   rD   r   r\  r   r;   r   r  )r=   rr  r   r   expired	oldrecordcallbackexpiress   `  `    r'   r  zServiceBrowser.updateRecord.  s~    ;)##ty(@(@&&s++G/ M&,*<*<*>*>?	 &&v....fl&8&8&:&:;         H I$$X...F /  / / / /:@DM&,"4"4"6"67         H I$$X.../ ..r22G&& '/ $#(@(@, '&s   A;B9 9AD	D	c                 F    d| _         | j                                         d S )Nr   )r  rr  	notifyAllrv   s    r'   cancelzServiceBrowser.cancelK  s#    	!!!!!r&   c                 N   	 d }t                      }t          | j                  dk    r-| j        |k    r"| j                            | j        |z
             t                      d         s| j        rd S t                      }| j        |k    rt          t                    }|
                    t          | j        t          t                               | j                                        D ]-}|                    |          s|                    ||           .| j                            |           || j        z   | _        t+          d| j        dz            | _        t          | j                  dk    r| j                            d          }| || j                   )NTr   r   i N  r   )r(   r   r\  r  rr  r}  rz  r  r  r  r%  rj   rG   r   r  r  rk  r   r'  sendr  minpop)r=   eventr   r   r   s        r'   r  zServiceBrowser.runO  s   	%E#%%C49~~""t}s':':""4=3#6777yy) TY #%%C}##!/22DIy) L LMMM"m2244 9 9F!++C00 9++FC888""3''' #dj 0 DJN;;
49~~!!	a(( dm$$$/	%r&   N)r,   r-   r.   rh   r<   r  r  r  r%   r&   r'   r  r    sZ        7 7  $( ( (:" " "% % % % %r&   r  c                       e Zd ZdZ	 	 	 	 	 	 ddZd Zd Zd Zd Zd	 Z	d
 Z
d Zd Zd Zd Zd Zd Zd Zd Zd Zd ZdS )ServiceInfozService informationNr   c	                     |                     |          st          || _        || _        || _        || _        || _        || _        |r|| _        n|| _        | 	                    |           dS )a  Create a service description.

        type: fully qualified service type name
        name: fully qualified service name
        address: IP address as unsigned short, network byte order
        port: port that the service runs on
        weight: weight of the service
        priority: priority of the service
        properties: dictionary of properties (or a string holding the bytes for
                    the text field)
        server: fully qualified name for service host (defaults to name)N)
ro   r7   rG   rF   r   r   r   r   r   setProperties)	r=   rG   rF   r   r   r   r   
propertiesr   s	            r'   r<   zServiceInfo.__init__m  sz    . }}T"" 	)((			  	 DKKDK:&&&&&r&   c                    t          |t                    r|| _        g }d}|D ]p}||         }|d}n7t          |t                    r|}nt          |t                    r|rd}nd}nd}|                    d                    ||f                     q|D ]L}d                    |t          j        dt          j
        t          |                              |f          }M|| _        dS || _        dS )z7Sets properties and text of this info from a dictionaryr&   N   true   false   =r1  )rN   dictr  rm   r>  r   r  r   r2  r   bytechrr   r   )r=   r  r\  rf   rE   r5  suffixitems           r'   r  zServiceInfo.setProperties  s   j$'' 	#(DODF! 6 6"3= FFs++ !"FFs++ ! *!(!) FDIIsFm445555  E8+;CII+F+FGG  DIII"DIIIr&   c                    || _         	 i }t          |          }d}g }||k     rEt          ||                   }|dz  }|                    ||||z                       ||z  }||k     E|D ]h}|                    d          }|dk    r|}	d}
n*|d|         }	||dz   d         }
|
dk    rd}
n
|
dk    s|
sd}
|	r|                    |	          |
||	<   i|| _        dS # t          $ r t          j	                     d| _        Y dS w xY w)z+Sets properties and text given a text fieldr   r   r  r  Nr  r  )
r   r   r   r   findrb  r  r;   r  r  )r=   r   rf   endr:  strsr   rB  eindexrE   r5  s              r'   setTextzServiceInfo.setText  s^   	 	#Fd))CED#++T%[))
D!78999	 #++  ( (R<<CEEGVG*CfqjllOE'' !(**%* !  (6::c??2"'F3K$DOOO 	# 	# 	#!!!"DOOOO	#s   CC $DDc                     | j         S )r^   )rG   rv   s    r'   r`   zServiceInfo.getType  
    yr&   c                     | j         [| j                            d| j         z             r9| j        dt          | j                  t          | j                   z
  dz
           S | j        S )zName accessorNrG  r   )rG   rF   ro   r   rv   s    r'   getNamezServiceInfo.getName  s[    9 TY%7%7ty8H%I%I 9Bs49~~DI>BBCCyr&   c                     | j         S )zAddress accessor)r   rv   s    r'   
getAddresszServiceInfo.getAddress  s
    |r&   c                     | j         S )zPort accessor)r   rv   s    r'   getPortzServiceInfo.getPort  r  r&   c                     | j         S )zPriority accessor)r   rv   s    r'   getPriorityzServiceInfo.getPriority  s
    }r&   c                     | j         S )zWeight accessor)r   rv   s    r'   	getWeightzServiceInfo.getWeight  
    {r&   c                     | j         S )zProperties accessor)r  rv   s    r'   getPropertieszServiceInfo.getProperties  s
    r&   c                     | j         S )zText accessor)r   rv   s    r'   getTextzServiceInfo.getText  r  r&   c                     | j         S )zServer accessor)r   rv   s    r'   	getServerzServiceInfo.getServer  r  r&   c           	      D   ||                     |          s|j        t          k    r |j        | j        k    r|j        | _        dS dS |j        t          k    r|j        | j        k    rr|j        | _        |j        | _        |j        | _        |j	        | _	        | 
                    |||j                            | j        t          t                               dS dS |j        t          k    r0|j        | j        k    r"|                     |j                   dS dS dS dS dS )z-Updates service information from a DNS recordN)r   rG   r   rF   r   r   r   r   r   r   r  rX  rd  r  r   r  r   )r=   rr  r   r   s       r'   r  zServiceInfo.updateRecord  s.   f&6&6s&;&;{g%%;$+--#)>DLLL .-	));$)++"(-DK &DI"(-DK$*ODM%%  33 K)      ,+ 	));$)++LL-----+ & *)++r&   c                 @   t                      }t          }||z   }||z   }	 |                    | t          | j        t
          t                               | j        | j        | j	        ||k    r	 |
                    |            dS ||k    rt          t                    }|                    t          | j        t          t                               |                    |j                            | j        t          t                    |           |                    t          | j        t$          t                               |                    |j                            | j        t$          t                    |           | j        r|                    t          | j        t&          t                               |                    |j                            | j        t&          t                    |           |                    |           ||z   }|dz  }|                    t-          ||          |z
             t                      }| j        | j        | j	        d}|
                    |            n# |
                    |            w xY w|S )zReturns true if the service could be discovered on the
        network, and updates this object with details discovered.
        Nr   r   r   )r(   _LISTENER_TIMEr  rj   rF   rq   r  r   r   r   removeListenerr  r  r%  r   r'  rX  rd  r   r   r  r}  r  )	r=   rr  rt  r   r  r  lastr   rf   s	            r'   requestzServiceInfo.request  s     !!U{W}/	*  k$)Y	BB   #t|';ty?P3;;N ##D)))))M 3;;%o66COO#DIy)DD   '' 33 Iy)  	   OO#DIy)DD   '' 33 Iy)  	   {.'WiHH   ++$N77 $Wi   	   MM#&&&;D!AIEc$oo3444'))O #t|';ty?PP F##D))))H##D))))s   AJ 	G%J Jc                 P    t          |t                    r|j        | j        k    S dS )zTests equality of service namer   )rN   r  rF   rO   s     r'   rQ   zServiceInfo.__eq__Q  s(    e[)) 	+:**qr&   c                 .    |                      |           S rS   rT   rO   s     r'   rU   zServiceInfo.__ne__W  rV   r&   c                    d| j         t          j        |                                           | j        fz  }| j        |dz  }n8t          | j                  dk     r|| j        z  }n|| j        dd         dz   z  }|dz  }|S )ru   s   service[%s,%s:%s,Ns   None      r   rd   )rF   r   r   r  r   r   r   r  s     r'   rw   zServiceInfo.__repr__[  s    %IT__..//I)
 

 9gFF49~~""$)#$)CRC.611$r&   )NNr   r   NN)r,   r-   r.   rh   r<   r  r  r`   r  r  r  r  r  r  r  r  r  r  rQ   rU   rw   r%   r&   r'   r  r  j  s6        #' #' #' #'J# # #@## ## ##J                  . . .29 9 9v  & & &    r&   r  c                       e Zd ZdZddZd Zd Zd Zd Zdd	Z	d
 Z
d ZefdZd Zd Zd Zd Zd Zd Zd Zd ZeefdZd ZdS )ZeroconfzImplementation of Zeroconf Multicast DNS Service Discovery

    Supports registration, unregistration, queries and browsing.
    Nc                    dt                      d<   |+t          j        t          j                              | _        n|| _        dt
          f| _        t          j        t          j        t          j                  | _        	 | j        	                    t          j
        t          j        d           | j        	                    t          j
        t          j        d           n# t          $ r Y nw xY w| j        	                    t          j        t          j        d           | j        	                    t          j        t          j        d           	 | j                            | j                   n# t          $ r Y nw xY w| j        	                    t          j        t          j        t          j        t(                    t          j        d          z              g | _        g | _        i | _        i | _        t3                      | _        t7          j                    | _        t=          |           | _        tA          |           | _!        tE          |           | _#        dS )	zxCreates an instance of the Zeroconf class, establishing
        multicast communications, listening and reaping threads.r   r   Nr&   r         0.0.0.0)$rz  r   gethostbynamegethostnameintfr  groupAF_INET
SOCK_DGRAM
setsockopt
SOL_SOCKETSO_REUSEADDRSO_REUSEPORTr;   SOL_IPIP_MULTICAST_TTLIP_MULTICAST_LOOPbindIP_ADD_MEMBERSHIP	inet_atonr  	listenersbrowsersr  servicetypesrV  rX  rp  ru  rv  rn  r  r  r  r  reaper)r=   bindaddresss     r'   r<   zZeroconf.__init__s  s    &'		/",V-?-A-ABBDII#DI:&
mFNF4EFF	K""6#4f6I1MMMK""6#4f6I1MMMM 
	 
	 
	 D
	 	v}f.EwOOOv}f.FPPP	KTZ(((( 	 	 	 D	 	M$Z((6+;I+F+FF	
 	
 	
 ZZ
",..Tll Tlls%   A C$ $
C10C1E5 5
FFc                 6    | j                             d          S )N	   127.0.0.1r  
startswithrv   s    r'   
isLoopbackzZeroconf.isLoopback  s    y##L111r&   c                 6    | j                             d          S )Ns   169.254.r  rv   s    r'   isLinklocalzZeroconf.isLinklocal  s    y##K000r&   c                     | j                                          | j                             |dz             | j                                          dS )zRCalling thread waits for a given number of milliseconds or
        until notified.r#   N)rv  r|  r}  r~  )r=   rt  s     r'   r}  zZeroconf.wait  sL     	   GdN+++     r&   c                     | j                                          | j                                          | j                                          dS )zNotifies all waiting threadsN)rv  r|  
notify_allr~  rv   s    r'   r  zZeroconf.notifyAll  sD       !!###     r&     c                 V    t          ||          }|                    | |          r|S dS )zReturns network's service information for a particular
        name and type, or None if no service matches by the timeout,
        which defaults to 3 seconds.N)r  r  )r=   rG   rF   rt  r   s        r'   getServiceInfozZeroconf.getServiceInfo  s3     4&&<<g&& 	Ktr&   c                     |                      |           | j                            t          | ||                     dS )zAdds a listener for a particular service type.  This object
        will then have its updateRecord method called when information
        arrives for that type.N)removeServiceListenerr  r   r  )r=   rG   r  s      r'   addServiceListenerzZeroconf.addServiceListener  s@     	""8,,,^D$AABBBBBr&   c                 Z    | j         D ]"}|j        |k    r|                                 ~#dS )z<Removes a listener from the set that is currently listening.N)r  r  r  )r=   r  browsers      r'   r$  zZeroconf.removeServiceListener  s?    } 	 	G8++   	 	r&   c                 
   |                      |           || j        |j                                        <   |j        | j        v r| j        |j        xx         dz  cc<   nd| j        |j        <   t                      }|}d}|dk     r{||k     r'|                     ||z
             t                      }4t          t          t          z            }|                    t          |j        t          t          ||j                  d           |                    t          |j        t           t          ||j        |j        |j        |j                  d           |                    t+          |j        t,          t          ||j                  d           |j        r;|                    t3          |j        t4          t          ||j                  d           |                     |           |dz  }|t8          z  }|dk     ydS dS )a  Registers service information to the network with a default TTL
        of 60 seconds.  Zeroconf will then respond to requests for
        information for that service.  The name of the service may be
        changed if needed to make it unique on the network.r   r   r   N)checkServicer  rF   rD   rG   r  r(   r}  r  r	  	_FLAGS_AAr'  r   r   r  r   r   r   r   r   r   r   r   r   r   r   r   r  _REGISTER_TIME)r=   r   r|   r   r  r   r   s          r'   registerServicezZeroconf.registerService  s    
 	$+/dioo''(9)))di(((A-((((+,Ddi(!!!eeX~~		(S.)))'))09<==C49iCKKQ   IMKIK	 	    	9idiHH!   | ##Widl  	   IIcNNNFA&HE !eeeeeer&   c                    	 | j         |j                                        = | j        |j                 dk    r| j        |j        xx         dz  cc<   n| j        |j        = n# t
          $ r Y nw xY wt                      }|}d}|dk     r{||k     r'|                     ||z
             t                      }4t          t          t          z            }|                    t          |j        t          t          d|j                  d           |                    t          |j        t           t          d|j        |j        |j        |j                  d           |                    t)          |j        t*          t          d|j                  d           |j        r;|                    t1          |j        t4          t          d|j                  d           |                     |           |dz  }|t8          z  }|dk     ydS dS )zUnregister a service.r   r   r   N)r  rF   rD   r  rG   rZ   r(   r}  r  r	  r*  r'  r   r   r  r   r   r   r   r   r   r   r   r   r   r   r   r  _UNREGISTER_TIME)r=   r   r   r  r   r   s         r'   unregisterServicezZeroconf.unregisterService  s   	dioo//0 +a//!$),,,1,,,,%di0 	 	 	D	!!!eeX~~		(S.)))'))09<==C49iAtyII1   IMKII	 	    	9iDIFF   | ##WiDL  	   IIcNNNFA((HE !eeeeees   AA   
A-,A-c                    t          | j                  dk    rt                      }|}d}|dk     r||k     r'|                     ||z
             t                      }4t	          t
          t          z            }| j                                        D ]}|                    t          |j
        t          t          d|j                  d           |                    t          |j        t          t          d|j        |j        |j        |j                  d           |                    t)          |j        t*          t          d|j                  d           |j        r;|                    t1          |j        t2          t          d|j                  d           
|                     |           |dz  }|t6          z  }|dk     dS dS dS )z#Unregister all registered services.r   r   r   N)r   r  r(   r}  r  r	  r*  rk  r'  r   rG   r   r  rF   r   r   r   r   r   r   r   r   r   r   r   r   r  r.  )r=   r   r  r   r   r   s         r'   unregisterAllServiceszZeroconf.unregisterAllServices3  s   t}!!#%%CHAa%%>>IIhn---+--C!"4y"@AA M0022  D''" Iy)Q	  	   ''" I%% M K I K	 	    ''	9iDINN   | ++& $WiDL  	   		#Q,,O a%%%%	 "! %r&   c           	         t                      }|}d}|dk     r| j                            |j                  D ]}|j        t          k    r|                    |          so|j        |j        k    r_|j                            d          dk     r:d|j        |j	        |j
        |j        fz  |_        |                     |            dS t          ||k     r'|                     ||z
             t                      }t          t          t           z            }|| _        |                    t'          |j        t          t(                               |                    t-          |j        t          t(          t.          |j                             |                     |           |dz  }|t2          z  }|dk     dS dS )znChecks the network for a unique service name, modifying the
        ServiceInfo passed in if it is not unique.r   r   rG  s   %s.[%s:%d].%sNr   )r(   rX  rf  rG   r   r   r   rF   r  r   r   r)  r1   r}  r  r  r*  debugr%  rj   r  r,  r   _DNS_TTLr  _CHECK_TIME)r=   r   r   r  r   r   r   s          r'   r)  zZeroconf.checkServiceb  s     !!!ee*44TY?? 1 1K9,,",,S11 -	11y~~d++a//$4 I L I I	8 %	 ))$///00X~~		(S.)))'))o	9::CDJOOK	9iHHIII&&49iHdiPP   IIcNNNFA#H; !eeeeeer&   c                 H   t                      }| j                            |           |c| j                            |j                  D ]C}|                    |          r,|                    |          s|                    | ||           D| 	                                 dS )zAdds a listener for a given question.  The listener will have
        its updateRecord method called when information is available to
        answer the question.N)
r(   r  r   rX  rf  rF   rs   r   r  r  )r=   r  r   r   r   s        r'   r  zZeroconf.addListener  s      !!h'''*44X]CC = =&&v.. =v7G7G7L7L =))$V<<<r&   c                     	 | j                             |           |                                  dS # t          $ r Y dS w xY w)zRemoves a listener.N)r  r_  r  r;   )r=   r  s     r'   r  zZeroconf.removeListener  sU    	N!!(+++NN 	 	 	DD	s   .2 
A A c                 p    | j         D ]}|                    | ||           |                                  dS )zNUsed to notify listeners of new information that has updated
        a record.N)r  r  r  )r=   r   rr   r  s       r'   r  zZeroconf.updateRecord  sF      	2 	2H!!$S1111r&   c                    t                      }|j        D ]}|                    |          }|| j                                        v rQ|r| j                            |           nN| j                            |          }||                    |           |}n| j                            |           | 	                    ||           dS )zlDeal with incoming response packets.  All answers
        are held in the cache, and listeners are notified.N)
r(   r   r   rX  rl  r_  rb  r   r]  r  )r=   r   r   r   r  r[  s         r'   r  zZeroconf.handleResponse  s      !!k 	+ 	+F&&s++G++---- 'J%%f---- JNN622E(v...!&
v&&&c6****	+ 	+r&   c                    d}|t           k    r<t          t          t          z  d          }|j        D ]}|                    |           |j        D ]s}|j        t          k    r|j        dk    rp| j	        
                                D ]V}|t          t          t          z            }|                    |t          dt          t          t          |                     W| j                                        D ]p}|j        |j        k    r^|t          t          t          z            }|                    |t          |j        t          t          t          |j                             q	 |t          t          t          z            }|j        t"          k    s|j        t$          k    r| j                                        D ]l}|j        |j                                        k    rH|                    |t+          |j        t"          t          t,          z  t          |j                             m| j                            |j                                        d          }|s|j        t2          k    s|j        t$          k    rZ|                    |t5          |j        t2          t          t,          z  t          |j        |j        |j        |j                             |j        t<          k    s|j        t$          k    rH|                    |t?          |j        t<          t          t,          z  t          |j                              |j        t2          k    rG|!                    t+          |j        t"          t          t,          z  t          |j                             Q# tD          $ r tG          j$                     Y qw xY w|,|j%        r'|j&        |_&        | '                    |||           dS dS dS )zKDeal with incoming query packets.  Provides a response if
        possible.Nr   s   _services._dns-sd._udp.local.)(r  r  r	  r*  r   r%  rG   r   rF   r  r  r)  r   r  r4  r  rk  r   rq   r   rD   r   rJ   r   rb  r   r   r   r   r   r   r   r   r/  r;   r  r  r   r   r  )r=   r   r  r   r   r   stypeservices           r'   r  zZeroconf.handleQuery  s     :09<a@@CM * *)))) Z	* Z	*H}	))=$DDD!%!2!7!7!9!9  ;"-.@9.L"M"MC& @ ) ) ( % 	 	 	 	  $}3355  G}44;"-.@9.L"M"MC& ' ) ) ( ' 	 	 		;*{)*<y*HII  }//8=I3M3M'+}';';'='= " "G&~1D1D1F1FFF #$'$.(0(/(1M(A(0(/%& %&	!" 	!" 	!" #m//0C0C0E0EtLLG" ! }	11X]i5O5O& ( ) )M 9 ( ' 0 ' ' '	 	    }	11X]i5O5O# ( ) )M 9 ( ' 	 	 	  }	11//& ' ' )M 9 ( '    ! * * *')))))* ?s{?VCFIIc4&&&&& ???s   -C8N"'D9N""OOc                     	 | j                             |                                d||f           dS # t          $ r Y dS w xY w)zSends an outgoing packet.r   N)r   sendtorT  r;   )r=   r   r  r   s       r'   r  zZeroconf.send!  sU    	Kszz||Qt===== 	 	 	DD	s   04 
AAc                    t                      d         dk    rdt                      d<   |                                  | j                                         |                                  | j                            t
          j        t
          j        t          j	        t                    t          j	        d          z              | j                                         dS dS )z^Ends the background threads, and prevent this instance from
        servicing further queries.r   r   r   r   N)rz  r  r  r  r1  r   r  r  IP_DROP_MEMBERSHIPr  r  closerv   s    r'   rA  zZeroconf.close+  s     99_%**)*GIIo&NNK   &&(((K"") ,,v/?	/J/JJ  
 K +*r&   r{   )r   )r,   r-   r.   rh   r<   r  r  r}  r  r"  r%  r$  r4  r,  r/  r1  r)  r  r  r  r  r  r  r  r  rA  r%   r&   r'   r  r  m  sg        
1# 1# 1# 1#f2 2 21 1 1! ! !! ! !   C C C   )1 0' 0' 0' 0'd/) /) /)b-- -- --^#$ #$ #$J
 
 
    + + +&j' j' j'X (j             r&   r  __main__s3   Multicast DNS Service Discovery for Python, versions'   1. Testing registration of a service...s   0.10s
   test values   another value)s   versionr!      bs   _http._tcp.local.s!   My Service Name._http._tcp.local.r  i  s      Registering service...s      Registration done.s*   2. Testing query of service information...s      Getting ZOE service:s   ZOE._http._tcp.local.s      Query done.s"   3. Testing query of own service...s      Getting self:s/   4. Testing unregister of service information...s      Unregister done.)hrh   
__author__	__email____version__r  rh  r  r   r   rp  r$   r  	mercurialr   __all__rz  r.  r5  r+  r  r  r  r  r  r4  _MAX_MSG_TYPICALr  r  r  r	  r*  	_FLAGS_TC	_FLAGS_RD	_FLAGS_RA_FLAGS_Z	_FLAGS_AD	_FLAGS_CDr  	_CLASS_CS	_CLASS_CH	_CLASS_HS_CLASS_NONE
_CLASS_ANYrH   rJ   r   _TYPE_NS_TYPE_MD_TYPE_MFr   	_TYPE_SOA_TYPE_MB_TYPE_MG_TYPE_MR
_TYPE_NULL	_TYPE_WKSr   r   _TYPE_MINFO_TYPE_MXr   r  r   rq   rY   r_   r(   r;   r*   r1   r3   r5   r7   r9   r@   rB   rj   ry   r   r   r   r   r   r   r  rV  rq  rn  r  r  r  r  r  r,   printrdescr  r   r,  rm   r"  r/  rA  r%   r&   r'   <module>rc     s   0IO	J; .#
@4C
 "
0	                       
:
:
: 		/    

	   										

	
			
		
 uuuu
T
e
 e
 e	

 
 v
 e
 e
 e
 
 v
 v
 
 
 e
  v!
" #
$ vv'
 
2  	 	 	 	 	I 	 	 		 	 	 	 	Y 	 	 		 	 	 	 	y 	 	 		 	 	 	 	i 	 	 		 	 	 	 	Y 	 	 	: : : : :I : : :
	 	 	 	 	M 	 	 	6 6 6 6 6 6 6 6r: : : : :( : : :.?7 ?7 ?7 ?7 ?7 ?7 ?7 ?7D               2) ) ) ) )y ) ) )0) ) ) ) ) ) ) ),, , , , ,i , , ,2B B B B B B B BBA A A A A A A AH_# _# _# _# _# _# _# _#D1 1 1 1 1 1 1 1h?! ?! ?! ?! ?!Y ?! ?! ?!D$. $. $. $. $. $. $. $.N7 7 7 7 7Y 7 7 7*R% R% R% R% R%Y% R% R% R%j@ @ @ @ @ @ @ @FK  K  K  K  K  K  K  K b z	E
@+NNN

A	E
4555}<LMMD;,&&		 D 
E
&'''d	E
"###	E
7888	E"A13KLLMM   
E
	E
/000	E$&J 	
 	
   
E
	E
<===	E
 !!!GGIIIIII r&   