
    6h                    f   S SK Jr            SrSrSrS SKrS SKrS SKrS SKrS SK	r	S SK
r
S SKrS SKrS SKJr  / SQrS \" 5       S'   S	rS
rSrSrSrSrSrSrSrSrSrSrS rSrSrSr Sr!Sr"Sr#Sr$Sr%Sr&Sr'Sr(Sr)Sr*S r+S!r,Sr-Sr.Sr/Sr0Sr1S"r2S#r3S$r4S%r5S&r6S'r7S(r8S)r9S*r:S+r;S,r<Sr=S-r>S.r?S r@\&S/\'S0\(S1\)S2\*S3\+S40rA0 \.S5_\/S6_\0S7_\1S8_\2S9_\3S:_\4S;_\5S<_\6S=_\7S>_\8S?_\9S@_\:SA_\;SB_\<SC_\=SD_\>SE_\?SF\@S40ErBSG rC " SH SI\D5      rE " SJ SK\D5      rF " SL SM\D5      rG " SN SO\D5      rH " SP SQ\D5      rI " SR SS\D5      rJ " ST SU\J5      rK\R                  rM\R                  (       a  \R                  rM " SV SW5      rP " SX SY\P5      rQ " SZ S[\P5      rR " S\ S]\R5      rS " S^ S_\R5      rT " S` Sa\R5      rU " Sb Sc\R5      rV " Sd Se\R5      rW " Sf Sg5      rX " Sh Si5      rY " Sj Sk5      rZ " Sl Sm\
R                  5      r\ " Sn So5      r] " Sp Sq\
R                  5      r^ " Sr Ss\
R                  5      r_ " St Su5      r` " Sv Sw5      ra\bSx:X  a  \c" Sy\5        \a" 5       rd\c" Sz5        S{S|S}S~.re\`" SS\R                  " S5      SS S \e5      rg\c" S5        \dR                  \g5        \c" S5        \c" S5        \c" S\i" \dR                  SS5      5      5        \c" S5        \c" S5        \c" S\i" \dR                  SS5      5      5        \c" S5        \c" S5        \dR                  \g5        \c" S5        \dR                  5         gg)    )annotationss   Paul Scott-Murphys!   paul at scott dash murphy dot coms   0.12N)pycompat)ZeroconfServiceInfo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                 2    [         R                   " 5       S-  $ )z#Current system time in milliseconds  )time     9/usr/lib/python3/dist-packages/hgext/zeroconf/Zeroconf.pycurrentTimeMillisr,      s    99;r*   c                      \ rS rSrSrg)NonLocalNameException   r)   N__name__
__module____qualname____firstlineno____static_attributes__r)   r*   r+   r.   r.          r*   r.   c                      \ rS rSrSrg)NonUniqueNameException   r)   Nr0   r)   r*   r+   r8   r8      r6   r*   r8   c                      \ rS rSrSrg)NamePartTooLongException   r)   Nr0   r)   r*   r+   r;   r;      r6   r*   r;   c                      \ rS rSrSrg)AbstractMethodException   r)   Nr0   r)   r*   r+   r>   r>      r6   r*   r>   c                      \ rS rSrSrg)BadTypeInNameException   r)   Nr0   r)   r*   r+   rA   rA      r6   r*   rA   c                      \ rS rSrS rSrg)BadDomainName   c                6    [         R                  U SU-  5        g )Ns   at position %s)	Exception__init__)selfposs     r+   rH   BadDomainName.__init__   s    4!2S!89r*   r)   N)r1   r2   r3   r4   rH   r5   r)   r*   r+   rD   rD      s    :r*   rD   c                      \ rS rSrSrg)BadDomainNameCircular   r)   Nr0   r)   r*   r+   rM   rM      r6   r*   rM   c                  <    \ rS rSrSrS rS rS rS rS r	S r
S	rg
)DNSEntry   zA DNS entryc                    UR                  5       U l        Xl        X l        U[        -  U l        U[        -  S:g  U l        g )Nr   )lowerkeynametype_CLASS_MASKclazz_CLASS_UNIQUEuniquerI   rU   rV   rX   s       r+   rH   DNSEntry.__init__   s6    ::<		[(
},2r*   c                    [        U[        5      (       aY  U R                  UR                  :H  =(       a9    U R                  UR                  :H  =(       a    U R                  UR                  :H  $ g)z&Equality test on name, type, and classr   )
isinstancerP   rU   rV   rX   rI   others     r+   __eq__DNSEntry.__eq__   sS    eX&&		UZZ' .II+.JJ%++-
 r*   c                .    U R                  U5      (       + $ zNon-equality testra   r_   s     r+   __ne__DNSEntry.__ne__
      ;;u%%%r*   c                @     [         U   $ ! [         a    SU-  s $ f = f)zClass accessor   ?(%s))_CLASSESKeyError)rI   rX   s     r+   getClazzDNSEntry.getClazz  s+    	$E?" 	$e##	$    c                @     [         U   $ ! [         a    SU-  s $ f = f)Type accessorrj   )_TYPESrl   )rI   rV   s     r+   getTypeDNSEntry.getType  s*    	#$< 	#d?"	#ro   c                    SUU R                  U R                  5      U R                  U R                  5      4-  nU R                  (       a  US-  nOUS-  nX0R
                  -  nUb
  USU-  -  nU$ US-  nU$ )1String representation with additional informations   %s[%s,%ss   -unique,   ,s   ,%s]   ])rs   rV   rm   rX   rZ   rU   )rI   hdrr`   results       r+   toStringDNSEntry.toString  s    LL#MM$**% 
 

 ;;k!FdNF))go%F  dNFr*   )rX   rT   rU   rV   rZ   N)r1   r2   r3   r4   __doc__rH   ra   rf   rm   rs   r{   r5   r)   r*   r+   rP   rP      s#    3&$#r*   rP   c                  *    \ rS rSrSrS rS rS rSrg)DNSQuestioni/  zA DNS question entryc                    [        U[        5      (       a  UR                  S5      nUR                  S5      (       d  [	        U5      e[
        R                  XX#5        g )Nasciis   .local.)r^   strencodeendswithr.   rP   rH   r[   s       r+   rH   DNSQuestion.__init__2  sG    dC  ;;w'D}}Z(('--$d2r*   c                    U R                   UR                   :H  =(       aS    U R                  UR                  :H  =(       d    U R                  [        :H  =(       a    U R                  UR                  :H  $ )z6Returns true if the question is answered by the record)rX   rV   	_TYPE_ANYrU   )rI   recs     r+   
answeredByDNSQuestion.answeredBy9  sQ     JJ#))# &chh&@$))y*@&		SXX%	
r*   c                0    [         R                  U SS5      $ )String representations   questionN)rP   r{   rI   s    r+   __repr__DNSQuestion.__repr__A  s      {D99r*   r)   N)	r1   r2   r3   r4   r}   rH   r   r   r5   r)   r*   r+   r   r   /  s    3
:r*   r   c                  Z    \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rS rS rSrg)	DNSRecordiF  z.A DNS record - like a DNS entry, but has a TTLc                Z    [         R                  XX#5        X@l        [        5       U l        g N)rP   rH   ttlr,   created)rI   rU   rV   rX   r   s        r+   rH   DNSRecord.__init__I  s!    $d2(*r*   c                X    [        U[        5      (       a  [        R                  X5      $ g)zTests equality as per DNSRecordr   )r^   r   rP   ra   r_   s     r+   ra   DNSRecord.__eq__N  s!    eY''??4//r*   c                Z    UR                    H  nU R                  U5      (       d  M    g   g)z\Returns true if any answer in a message can suffice for the
information held in this record.r   r   )answerssuppressedByAnswer)rI   msgrecords      r+   suppressedByDNSRecord.suppressedByT  s+     kkF&&v.. " r*   c                J    X:X  a  UR                   U R                   S-  :  a  gg)zoReturns 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   r_   s     r+   r   DNSRecord.suppressedByAnswer\  s"     =UYY$((Q,7r*   c                >    U R                   XR                  -  S-  -   $ )zPReturns the time at which this record will have expired
by a certain percentage.r   r   r   )rI   percents     r+   getExpirationTimeDNSRecord.getExpirationTimec  s     ||w1B677r*   c                D    [        SU R                  S5      U-
  S-  5      $ )z%Returns the remaining TTL in seconds.r   d   r'   )maxr   rI   nows     r+   getRemainingTTLDNSRecord.getRemainingTTLh  s$    1t--c2S8D@AAr*   c                *    U R                  S5      U:*  $ )z(Returns true if this record has expired.r   r   r   s     r+   	isExpiredDNSRecord.isExpiredl  s    %%c*c11r*   c                *    U R                  S5      U:*  $ )z9Returns true if this record is at least half way expired.2   r   r   s     r+   isStaleDNSRecord.isStalep  s    %%b)S00r*   c                H    UR                   U l         UR                  U l        g)zBSets this record's TTL and created time to that of
another record.Nr   r_   s     r+   resetTTLDNSRecord.resetTTLt  s     }}99r*   c                    [         e)zAbstract method)r>   rI   outs     r+   writeDNSRecord.writez  s    %%r*   c                    SU R                   U R                  [        5       5      U4-  n[        R	                  U SU5      $ )rv   s   %s/%s,%ss   record)r   r   r,   rP   r{   )rI   ry   r`   args       r+   r{   DNSRecord.toString~  sD    HH  !2!45
 

   y#66r*   r   N)r1   r2   r3   r4   r}   rH   ra   r   r   r   r   r   r   r   r   r{   r5   r)   r*   r+   r   r   F  s=    8+
8
B21&7r*   r   c                  0    \ rS rSrSrS rS rS rS rSr	g)	
DNSAddressi  zA DNS address recordc                >    [         R                  XX#U5        XPl        g r   )r   rH   address)rI   rU   rV   rX   r   r   s         r+   rH   DNSAddress.__init__  s    4tC8r*   c                b    UR                  U R                  [        U R                  5      5        gz'Used in constructing an outgoing packetN)writeStringr   lenr   s     r+   r   DNSAddress.write  s    c$,,&78r*   c                `    [        U[        5      (       a  U R                  UR                  :H  $ g)zTests equality on addressr   )r^   r   r   r_   s     r+   ra   DNSAddress.__eq__  s%    eZ((<<5==00r*   c                |     [         R                  " U R                  5      $ ! [         a    U R                  s $ f = f)r   )socket	inet_ntoar   rG   r   s    r+   r   DNSAddress.__repr__  s5    	 ##DLL11 	 <<	 s   " ;;r   N
r1   r2   r3   r4   r}   rH   r   ra   r   r5   r)   r*   r+   r   r     s    9 r*   r   c                  0    \ rS rSrSrS rS rS rS rSr	g)	DNSHinfoi  zA DNS host information recordc                J    [         R                  XX#U5        XPl        X`l        g r   )r   rH   cpuos)rI   rU   rV   rX   r   r   r   s          r+   rH   DNSHinfo.__init__  s    4tC8r*   c                    UR                  U R                  [        U R                  5      5        UR                  U R                  [        U R                  5      5        gr   )r   r   r   r   r   s     r+   r   DNSHinfo.write  s6    #dhh-0TWW.r*   c                    [        U[        5      (       a9  U R                  UR                  :H  =(       a    U R                  UR                  :H  $ g)zTests equality on cpu and osr   )r^   r   r   r   r_   s     r+   ra   DNSHinfo.__eq__  s7    eX&&88uyy(@TWW-@@r*   c                :    U R                   S-   U R                  -   $ )r       r   r   r   s    r+   r   DNSHinfo.__repr__  s    xx$((r*   r   Nr   r)   r*   r+   r   r     s    '
/
)r*   r   c                  0    \ rS rSrSrS rS rS rS rSr	g)	
DNSPointeri  zA DNS pointer recordc                >    [         R                  XX#U5        XPl        g r   )r   rH   alias)rI   rU   rV   rX   r   r   s         r+   rH   DNSPointer.__init__  s    4tC8
r*   c                :    UR                  U R                  5        gr   )	writeNamer   r   s     r+   r   DNSPointer.write  s    djj!r*   c                `    [        U[        5      (       a  U R                  UR                  :H  $ g)zTests equality on aliasr   )r^   r   r   r_   s     r+   ra   DNSPointer.__eq__  s%    eZ((::,,r*   c                :    U R                  SU R                  5      $ )r   r*   )r{   r   r   s    r+   r   DNSPointer.__repr__  s    }}S$**--r*   )r   Nr   r)   r*   r+   r   r     s    ".r*   r   c                  0    \ rS rSrSrS rS rS rS rSr	g)	DNSTexti  zA DNS text recordc                >    [         R                  XX#U5        XPl        g r   )r   rH   text)rI   rU   rV   rX   r   r   s         r+   rH   DNSText.__init__  s    4tC8	r*   c                b    UR                  U R                  [        U R                  5      5        gr   )r   r   r   r   s     r+   r   DNSText.write  s    		3tyy>2r*   c                `    [        U[        5      (       a  U R                  UR                  :H  $ g)zTests equality on textr   )r^   r   r   r_   s     r+   ra   DNSText.__eq__  s%    eW%%99

**r*   c                    [        U R                  5      S:  a"  U R                  SU R                  SS S-   5      $ U R                  SU R                  5      $ )r   r   r*   Nr      ...)r   r   r{   r   s    r+   r   DNSText.__repr__  sG    tyy>B==diimf&<====dii00r*   r   Nr   r)   r*   r+   r   r     s    31r*   r   c                  0    \ rS rSrSrS rS rS rS rSr	g)	
DNSServicei  zA DNS service recordc	                b    [         R                  XX#U5        XPl        X`l        Xpl        Xl        g r   )r   rH   priorityweightportserver)	rI   rU   rV   rX   r   r   r   r   r   s	            r+   rH   DNSService.__init__  s(    4tC8 	r*   c                    UR                  U R                  5        UR                  U R                  5        UR                  U R                  5        UR	                  U R
                  5        gr   )
writeShortr   r   r   r   r   r   s     r+   r   DNSService.write  sB    t}}%t{{#tyy!dkk"r*   c                    [        U[        5      (       ay  U R                  UR                  :H  =(       aY    U R                  UR                  :H  =(       a9    U R                  UR                  :H  =(       a    U R
                  UR
                  :H  $ g)z3Tests equality on priority, weight, port and serverr   )r^   r   r   r   r   r   r_   s     r+   ra   DNSService.__eq__  sj    eZ((/ 0KK5<</0II+0 KK5<</	 r*   c                X    U R                  SSU R                  U R                  4-  5      $ )r   r*   s   %s:%s)r{   r   r   r   s    r+   r   DNSService.__repr__  s%    }}S(dkk499-E"EFFr*   )r   r   r   r   Nr   r)   r*   r+   r   r     s    #	Gr*   r   c                  `    \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rS rS rS rSrg)DNSIncomingi	  z/Object representation of an incoming DNS packetc                    SU l         Xl        / U l        / U l        SU l        SU l        SU l        SU l        U R                  5         U R                  5         U R                  5         g)z/Constructor from string holding bytes of packetr   N)offsetdata	questionsr   numquestions
numanswersnumauthoritiesnumadditionals
readHeaderreadQuestions
readOthers)rI   r  s     r+   rH   DNSIncoming.__init__  s[    	r*   c                J   Sn[         R                  " U5      n[         R                  " XR                  U R                  U R                  U-    5      nU =R                  U-  sl        US   U l        US   U l        US   U l        US   U l        US   U l	        US   U l
        g)	zReads header portion of packets   !HHHHHHr   r   r   r   r   r   N)structcalcsizeunpackr  r  idflagsr  r  r  r  rI   formatlengthinfos       r+   r  DNSIncoming.readHeader  s    (}}IIdkkDKK&,@A
 	vq'!W
 Gq'"1g"1gr*   c                   Sn[         R                  " U5      n[        SU R                  5       H  nU R	                  5       n[         R
                  " XR                  U R                  U R                  U-    5      nU =R                  U-  sl         [        XES   US   5      nU R                  R                  U5        M     g! [         a     M  f = f)z!Reads questions section of packets   !HHr   r   N)r  r  ranger  readNamer  r  r  r   r  appendr.   )rI   r  r  irU   r   questions          r+   r  DNSIncoming.readQuestions+  s    (q$++,A==?D==		$++f0DED KK6!K&t!Wd1g>%%h/ - ) s   -C
CCc                    Sn[         R                  " U5      n[         R                  " XR                  U R                  U R                  U-    5      nU =R                  U-  sl        US   $ )z Reads an integer from the packet   !Ir   r  r  r  r  r  r  s       r+   readIntDNSIncoming.readInt<  W    (}}IIdkkDKK&,@A
 	vAwr*   c                    [        U R                  U R                     5      nU =R                  S-  sl        U R                  U5      $ )z(Reads a character string from the packetr   )ordr  r  
readString)rI   r  s     r+   readCharacterStringDNSIncoming.readCharacterStringF  s6    TYYt{{+,qv&&r*   c                    SU-  n[         R                  " U5      n[         R                  " X R                  U R                  U R                  U-    5      nU =R                  U-  sl        US   $ )z0Reads a string of a given length from the packets   !%dsr   r+  )rI   r   r  r  r   s        r+   r1  DNSIncoming.readStringL  s[    3(}}IIdkkDKK&,@A
 	vAwr*   c                    Sn[         R                  " U5      n[         R                  " XR                  U R                  U R                  U-    5      nU =R                  U-  sl        US   $ )z'Reads an unsigned short from the packet   !Hr   r+  r  s       r+   readUnsignedShortDNSIncoming.readUnsignedShortV  r.  r*   c                   Sn[         R                  " U5      nU R                  U R                  -   U R                  -   n[        SU5       GH#  nU R                  5       n[         R                  " XR                  U R                  U R                  U-    5      nU =R                  U-  sl	        SnUS   [        :X  a(  [        XVS   US   US   U R                  S5      5      nGOhUS   [        :X  d  US   [        :X  a'  [        XVS   US   US   U R                  5       5      nGO'US   [         :X  a*  [#        XVS   US   US   U R                  US   5      5      nOUS   [$        :X  aT  ['        UUS   US   US   U R)                  5       U R)                  5       U R)                  5       U R                  5       5      nOUS   [*        :X  a6  [-        UUS   US   US   U R/                  5       U R/                  5       5      nOLUS   [0        :X  a'  [        XVS   US   US   U R                  S5      5      nOU =R                  US   -  sl	        Uc  GM  U R2                  R5                  U5        GM&     g)	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   r1  _TYPE_CNAME	_TYPE_PTRr   	_TYPE_TXTr   	_TYPE_SRVr   r8  _TYPE_HINFOr   r2  
_TYPE_AAAAr   r%  )rI   r  r  nr&  domainr   r   s           r+   r  DNSIncoming.readOthers`  s@   (OOd111D4G4GGq!A]]_F==		$++f0DED KK6!KCAw'! GT!Wd1gtq7I aK'47i+? GT!Wd1gt}} aI%GT!Wd1gttAw7O aI% GGG**,**,**,MMO	 aK'GGG,,.,,. aJ& GT!Wd1gtr7J tAw&##C(q r*   c                6    U R                   [        -  [        :H  $ )zReturns true if this is a query)r  _FLAGS_QR_MASK_FLAGS_QR_QUERYr   s    r+   isQueryDNSIncoming.isQuery  s    

^+??r*   c                6    U R                   [        -  [        :H  $ )z"Returns true if this is a response)r  rF  _FLAGS_QR_RESPONSEr   s    r+   
isResponseDNSIncoming.isResponse  s    

^+0BBBr*   c                B    U R                   XU-    R                  S5      $ )z6Reads a UTF-8 string of a given length from the packetutf-8)r  decode)rI   r  r   s      r+   readUTFDNSIncoming.readUTF  s     yy3,/66w??r*   c                   SnU R                   nSnUn [        U R                  X"S-    5      nUS-  nUS:X  a  OUS-  nUS:X  a)  SR                  XR	                  X%5      S-   45      nX%-  nORUS:X  aA  US:  a  US-   nUS-  S-  [        U R                  X"S-    5      -  nX$:  a  [        U5      eUnO[        U5      eM  US:  a  X0l         U$ X l         U$ )	z#Reads a domain name from the packet r   r      .?   r   )r  r0  r  joinrQ  rM   rD   )rI   rz   offnextfirstr   ts          r+   r$  DNSIncoming.readName  s    kkdiiAg./C1HCaxd
ADy&,,s*@3*F!GH
d!87Dd
q(C		#a0H,II</44#C((# & 19K  Kr*   )
r   r  r  r  r  r  r  r  r  r  N)r1   r2   r3   r4   r}   rH   r  r  r,  r2  r1  r8  r  rH  rL  rQ  r$  r5   r)   r*   r+   r
  r
  	  sE    9& "'=)~@C@r*   r
  c                  |    \ rS rSrSrSS jrS rS rS rS r	S r
S	 rS
 rS rS rS rS rS rS rS rS rSrg)DNSOutgoingi  z+Object representation of an outgoing packetc                    SU l         SU l        X l        Xl        0 U l        / U l        SU l        / U l        / U l        / U l	        / U l
        g )Nr   r   )finishedr  	multicastr  namesr  sizer  r   authoritiesadditionals)rI   r  rc  s      r+   rH   DNSOutgoing.__init__  sM    "

		r*   c                :    U R                   R                  U5        g)zAdds a questionN)r  r%  rI   r   s     r+   addQuestionDNSOutgoing.addQuestion  s    f%r*   c                V    UR                  U5      (       d  U R                  US5        gg)zAdds an answerr   N)r   addAnswerAtTime)rI   inpr   s      r+   	addAnswerDNSOutgoing.addAnswer  s(    ""3''  + (r*   c                ~    Ub:  US:X  d  UR                  U5      (       d  U R                  R                  X45        ggg)z6Adds an answer if if does not expire by a certain timeNr   )r   r   r%  )rI   r   r   s      r+   rn  DNSOutgoing.addAnswerAtTime  s=    axv//44##VM2  5 r*   c                :    U R                   R                  U5        g)zAdds an authoritative answerN)rf  r%  rj  s     r+   addAuthoritativeAnswer"DNSOutgoing.addAuthoritativeAnswer      'r*   c                :    U R                   R                  U5        g)zAdds an additional answerN)rg  r%  rj  s     r+   addAdditionalAnswerDNSOutgoing.addAdditionalAnswer  rw  r*   c                    SnU R                   R                  [        R                  " U[	        U5      5      5        U =R
                  S-  sl        g)z"Writes a single byte to the packet   !cr   N)r  r%  r  packchrre  rI   valuer  s      r+   	writeByteDNSOutgoing.writeByte  5    		VSZ89		Q	r*   c                    SnU R                   R                  U[        R                  " X25      5        U =R                  S-  sl        g)z=Inserts an unsigned short in a certain position in the packetr7  r   N)r  insertr  r}  re  )rI   indexr  r  s       r+   insertShortDNSOutgoing.insertShort  s1    		F :;		Q	r*   c                    SnU R                   R                  [        R                  " X!5      5        U =R                  S-  sl        g)z&Writes an unsigned short to the packetr7  r   N)r  r%  r  r}  re  r  s      r+   r  DNSOutgoing.writeShort  s/    		V34		Q	r*   c                    SnU R                   R                  [        R                  " U[	        U5      5      5        U =R
                  S-  sl        g)z(Writes an unsigned integer to the packetr*  r   N)r  r%  r  r}  intre  r  s      r+   writeIntDNSOutgoing.writeInt  r  r*   c                    S[        U5      -   S-   nU R                  R                  [        R                  " X15      5        U =R
                  U-  sl        g)zWrites a string to the packet!sN)r   r  r%  r  r}  re  )rI   r  r  r  s       r+   r   DNSOutgoing.writeString  s>    s6{"S(		V34		V	r*   c                    UR                  S5      n[        U5      nUS:  a  [        eU R                  U5        U R	                  X#5        g)z5Writes a UTF-8 string of a given length to the packetrO  r   N)r   r   r;   r  r   )rI   r  utfstrr  s       r+   writeUTFDNSOutgoing.writeUTF  s@    '"VB;**v(r*   c                Z    U R                   U   nU R                  US-	  S-  5        U R                  U5        g! [         af    U R                  U R                   U'   UR                  S5      nUS   S:X  a  USS nU H  nU R	                  U5        M     U R                  S5         gf = f)z"Writes a domain name to the packet   .rU  r*   Nr   r   rV  )rd  rl   re  splitr  r  )rI   rU   r  partsparts        r+   r   DNSOutgoing.writeName  s    	 JJt$E" 	
d*+u#  	
  $yyDJJtJJt$ERyCcr
d# NN1	s   : A-B*)B*c                    U R                  UR                  5        U R                  UR                  5        U R                  UR                  5        g)zWrites a question to the packetN)r   rU   r  rV   rX   )rI   r'  s     r+   writeQuestionDNSOutgoing.writeQuestion6  s2    x}}%&'r*   c                   U R                  UR                  5        U R                  UR                  5        UR                  (       a4  U R
                  (       a#  U R                  UR                  [        -  5        OU R                  UR                  5        US:X  a  U R                  UR                  5        O U R                  UR                  U5      5        [        U R                  5      nU =R                  S-  sl        UR                  U 5        U =R                  S-  sl        [        SR                  U R                  US 5      5      nU R!                  X45        g)zHWrites a record (answer, authoritative answer, additional) to
the packetr   r   r*   N)r   rU   r  rV   rZ   rc  rX   rY   r  r   r   r   r  re  r   rY  r  )rI   r   r   r  r  s        r+   writeRecordDNSOutgoing.writeRecord<  s     	v{{#$==T^^OOFLL=89OOFLL)!8MM&**%MM&0056DII 			Q	T		Q	SXXdii/01'r*   c                r   U R                   (       Gd  SU l         U R                   H  nU R                  U5        M     U R                   H  u  p#U R	                  X#5        M     U R
                   H  nU R	                  US5        M     U R                   H  nU R	                  US5        M     U R                  S[        U R                  5      5        U R                  S[        U R
                  5      5        U R                  S[        U R                  5      5        U R                  S[        U R                  5      5        U R                  SU R                  5        U R                  (       a  U R                  SS5        OU R                  SU R                  5        SR                  U R                  5      $ )zqReturns a string containing the packet's bytes

No further parts should be added to the packet once this
is done.r   r   r*   )rb  r  r  r   r  rf  rg  r  r   r  rc  r  rY  r  )rI   r'  answertime_	authority
additionals         r+   packetDNSOutgoing.packetS  sJ   
 }}}DM NN""8, +!%  / ".!--	  A. ."..
  Q/ / QD$4$4 56QD$4$4 56QDLL 12QDNN 34Q

+~~  A&  DGG,xx		""r*   )rg  r   rf  r  rb  r  r  rc  rd  r  re  N)r   )r1   r2   r3   r4   r}   rH   rk  rp  rn  ru  ry  r  r  r  r  r   r  r   r  r  r  r5   r)   r*   r+   r`  r`    sU    5&,
3(()4((.#r*   r`  c                  B    \ rS rSrSrS rS rS rS rS r	S r
S	 rS
rg)DNSCacheio  zA cache of DNS entriesc                    0 U l         g r   cacher   s    r+   rH   DNSCache.__init__r  s	    
r*   c                     U R                   UR                     nUR                  U5        g! [         a    / =o R                   UR                  '    N8f = f)zAdds an entryN)r  rT   rl   r%  rI   entrylists      r+   addDNSCache.addu  sM    	.::eii(D 	E  	.+--D::eii(	.s   - $AAc                z     U R                   UR                     nUR                  U5        g! [         a     gf = f)zRemoves an entryN)r  rT   removerl   r  s      r+   r  DNSCache.remove}  s7    	::eii(DKK 		s   *- 
::c                     U R                   UR                     nX"R                  U5         $ ! [        [        4 a     gf = f)zFGets an entry by key.  Will return None if there is no
matching entry.N)r  rT   r  rl   
ValueErrorr  s      r+   getDNSCache.get  sB    	::eii(D

5)***% 		s   +. A Ac                <    [        XU5      nU R                  U5      $ )zJGets an entry by details.  Will return None if there is
no matching entry.)rP   r  )rI   rU   rV   rX   r  s        r+   getByDetailsDNSCache.getByDetails  s     U+xxr*   c                F     U R                   U   $ ! [         a    / s $ f = f)z5Returns a list of entries whose key matches the name.)r  rl   )rI   rU   s     r+   entriesWithNameDNSCache.entriesWithName  s*    	::d## 	I	s      c                     [        [        R                  R                  U R                  R                  5       5      5      $ ! [         a    / s $ f = f)zReturns a list of all entries)r  	itertoolschainfrom_iterabler  valuesrG   r   s    r+   entriesDNSCache.entries  sB    		55djj6G6G6IJKK 	I	s   ?A AAr  N)r1   r2   r3   r4   r}   rH   r  r  r  r  r  r  r5   r)   r*   r+   r  r  o  s(     r*   r  c                  <    \ rS rSrSrS rS rS rS rS r	S r
S	rg
)Enginei  aG  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                    [         R                  R                  U 5        Xl        0 U l        SU l        [         R                  " 5       U l        U R                  5         g )Nr   )		threadingThreadrH   zeroconfreaderstimeout	Condition	conditionstartrI   r  s     r+   rH   Engine.__init__  sB    !!$' ",,.

r*   c                v   [        5       S   (       d  U R                  5       n[        U5      S:X  aZ  U R                  R	                  5         U R                  R                  U R                  5        U R                  R                  5         ON [        R                  " U/ / U R                  5      u  p#nU H!  n U R                  U   R                  5         M#     [        5       S   (       d  M  g g ! [         a.    [        5       S   (       d  [        R                  " 5          Mo   Mr  f = f! [         a     N]f = f)Nr   r   )globals
getReadersr   r  acquirewaitr  releaseselectr  handle_readrG   	traceback	print_exc)rI   rsrrwrersocks         r+   run
Engine.run  s    )N+"B2w!| &&(##DLL1&&(	!'r2r4<<!HJBB "6 LL.::< !# )N++  ) 6#*9^#< ) 3 3 5 $=6 ! s6   +D+ 9C0D+ 01D(!D+ 'D((D+ +
D87D8c                    U R                   R                  5         U R                  R                  5       nU R                   R	                  5         U$ r   )r  r  r  keysr  rI   rz   s     r+   r  Engine.getReaders  s9     ""$ r*   c                    U R                   R                  5         XR                  U'   U R                   R                  5         U R                   R	                  5         g r   r  r  r  notifyr  )rI   readerr   s      r+   	addReaderEngine.addReader  s>     %V r*   c                    U R                   R                  5         U R                  U	 U R                   R                  5         U R                   R	                  5         g r   r  )rI   r   s     r+   	delReaderEngine.delReader  s>     LL  r*   c                    U R                   R                  5         U R                   R                  5         U R                   R                  5         g r   )r  r  r  r  r   s    r+   r  Engine.notify  s2      r*   )r  r  r  r  N)r1   r2   r3   r4   r}   rH   r  r  r  r  r  r5   r)   r*   r+   r  r    s%    	,!!!r*   r  c                  $    \ rS rSrSrS rS rSrg)Listeneri  a$  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                    Xl         U R                   R                  R                  X R                   R                  5        g r   )r  enginer  r   r  s     r+   rH   Listener.__init__  s)     &&t]]-A-ABr*   c                N   U R                   R                  n UR                  [        5      u  nu  p4X l        [        U5      nUR                  5       (       a}  U[        :X  a&  U R                   R                  U[        [        5        g U[        :X  aB  U R                   R                  XcU5        U R                   R                  U[        [        5        g g U R                   R                  U5        g ! [         a)  nUR
                  [
        R                  :X  a   S nAg e S nAff = fr   )r  r   recvfrom_MAX_MSG_ABSOLUTEOSErrorerrnoEBADFr  r
  rH  
_MDNS_PORThandleQuery
_MDNS_ADDR	_DNS_PORThandleResponse)rI   r  r  addrr   er   s          r+   r  Listener.handle_read  s    }}##	!%/@!AD,4 	$;;== z!))#z:F "))#T:))#z:F # MM((-)  	ww%++%	s   C1 1
D$;DDD$)r  r  N)r1   r2   r3   r4   r}   rH   r  r5   r)   r*   r+   r  r    s    HC.r*   r  c                  $    \ rS rSrSrS rS rSrg)Reaperi  zJA Reaper is used by this module to remove cache entries that
have expired.c                n    [         R                  R                  U 5        Xl        U R	                  5         g r   )r  r  rH   r  r  r  s     r+   rH   Reaper.__init__  s$    !!$' 

r*   c                ~    U R                   R                  S5        [        5       S   (       a  g [        5       nU R                   R                  R                  5        H[  nUR                  U5      (       d  M  U R                   R                  X5        U R                   R                  R                  U5        M]     M  )Ni'  r   )	r  r  r  r,   r  r  r   updateRecordr  )rI   r   r   s      r+   r  
Reaper.run  s    MMy)y(#%C----557##C((MM..s;MM''..v6 8 r*   )r  N)r1   r2   r3   r4   r}   rH   r  r5   r)   r*   r+   r  r    s    
	7r*   r  c                  0    \ rS rSrSrS rS rS rS rSr	g)	r   i!  zUsed 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                V   [         R                  R                  U 5        Xl        X l        X0l        0 U l        [        5       U l        [        U l
        / U l        SU l        U R                  R                  U [        U R                  [        [         5      5        U R#                  5         g)z%Creates a browser for a specific typer   N)r  r  rH   r  rV   listenerservicesr,   nexttime_BROWSER_TIMEdelayr  doneaddListenerr   r=  	_CLASS_INr  )rI   r  rV   r  s       r+   rH   ServiceBrowser.__init__(  sz    !!$' 	 )+"
		!!+diiI>	
 	

r*   c                  ^ ^ TR                   [        :X  a  TR                  T R                   :X  a  TR                  U5      n T R                  TR
                  R                  5          nU(       d  UR                  T5        OHT R                  TR
                  R                  5       	 UU 4S jnT R                  R                  U5        gTR                  S5      nUT R                  :  a  UT l        gggg! [         aS    U(       dI  TT R                  TR
                  R                  5       '   UU 4S jnT R                  R                  U5         Nf = f)zzCallback invoked by Zeroconf when new information arrives.

Updates information required by browser in the Zeroconf cache.c                f   > TR                   R                  U TR                  TR                  5      $ r   )r  removeServicerV   r   xr   rI   s    r+   <lambda>-ServiceBrowser.updateRecord.<locals>.<lambda>F  s#    )D)D499fll*r*   Nc                f   > TR                   R                  U TR                  TR                  5      $ r   )r  
addServicerV   r   r  s    r+   r!  r"  N  s#    )A)A499fll*r*   K   )rV   r=  rU   r   r  r   rS   r   r  r%  rG   r   r  )rI   r  r   r   expired	oldrecordcallbackexpiress   `  `    r+   r  ServiceBrowser.updateRecord:  s    ;;)#tyy(@&&s+G/ MM&,,*<*<*>?	&&v.fll&8&8&:; H II$$X. ..r2G& ' '- )A#  /:@DMM&,,"4"4"67 H II$$X./s   ?C7 AC7 7AEEc                F    SU l         U R                  R                  5         g )Nr   )r  r  	notifyAllr   s    r+   cancelServiceBrowser.cancelW  s    	!r*   c                x    S n[        5       n[        U R                  5      S:X  a8  U R                  U:  a(  U R                  R                  U R                  U-
  5        [        5       S   (       d  U R                  (       a  g [        5       nU R                  U::  a  [        [        5      nUR                  [        U R                  [        [        5      5        U R                  R!                  5        H,  nUR#                  U5      (       a  M  UR%                  XB5        M.     U R                  R'                  U5        X R(                  -   U l        [+        SU R(                  S-  5      U l        [        U R                  5      S:  a  U R                  R-                  S5      nUb  U" U R                  5        GM  )Nr   r   i N  r   )r,   r   r  r  r  r  r  r  r`  rG  rk  r   rV   r=  r  r  r  r   rn  sendr  minpop)rI   eventr   r   r   s        r+   r  ServiceBrowser.run[  s9   E#%C499~"t}}s':""4==3#67y(DII#%C}}#!/2DIIy) LM"mm224F!++C00++F8 5 ""3' #jj 0 DJJN;
499~!		a( dmm$/ r*   )r  r  r  r  r  r  rV   r  N)
r1   r2   r3   r4   r}   rH   r  r-  r  r5   r)   r*   r+   r   r   !  s    7$(:"%r*   r   c                      \ rS rSrSr      SS jrS rS rS rS r	S	 r
S
 rS rS rS rS rS rS rS rS rS rS rSrg)r   iv  zService informationNc	                    UR                  U5      (       d  [        eXl        X l        X0l        X@l        XPl        X`l        U(       a  Xl        OX l        U R                  U5        g)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)
r   rA   rV   rU   r   r   r   r   r   setProperties)	rI   rV   rU   r   r   r   r   
propertiesr   s	            r+   rH   ServiceInfo.__init__y  sR    . }}T""((			  KK:&r*   c                   [        U[        5      (       a  Xl        / nSnU Hj  nX   nUc  SnO<[        U[        5      (       a  UnO$[        U[        5      (       a  U(       a  SnOSnOSnUR                  SR                  XF45      5        Ml     U HI  nSR                  U[        R                  " S[        R                  " [        U5      5      5      U45      nMK     X0l        gXl        g)z7Sets properties and text of this info from a dictionaryr*   N   true   false   =r|  )r^   dictr8  r   r  r%  rY  r  r}  r   bytechrr   r   )rI   r8  r  rz   rT   r  suffixitems           r+   r7  ServiceInfo.setProperties  s    j$''(ODF!"= Fs++"Fs++!(!) FDIIsm45 " E8+;+;CI+FG  I"Ir*   c                   Xl          0 n[        U5      nSn/ nXC:  a2  [        X   5      nUS-  nUR                  XXF-    5        XF-  nXC:  a  M2  U Hd  nUR	                  S5      nUS:X  a  Un	Sn
O$USU n	XxS-   S n
U
S:X  a  Sn
OU
S:X  d  U
(       d  Sn
U	(       d  ML  UR                  U	5      b  M`  XU	'   Mf     X l        g! [         a    [        R                  " 5         SU l         gf = f)z+Sets properties and text given a text fieldr   r   r=  rU  Nr;  r<  )
r   r   r0  r%  findr  r8  rG   r  r  )rI   r   rz   endr  strsr  r  eindexrT   r  s              r+   setTextServiceInfo.setText  s   	 	#Fd)CED+T[)
D89	 + R<CEGV*CqjlOE' !(*% ! 36::c?2"'3K! $ %O 	#!"DO	#s%   AC A
C C 2C &C*)C*c                    U R                   $ )rq   )rV   r   s    r+   rs   ServiceInfo.getType      yyr*   c                   U R                   bh  U R                  R                  SU R                   -   5      (       a;  U R                  S[        U R                  5      [        U R                   5      -
  S-
   $ U R                  $ )zName accessorNr  r   )rV   rU   r   r   r   s    r+   getNameServiceInfo.getName  s_    99 TYY%7%7tyy8H%I%I99Bs499~DII>BCCyyr*   c                    U R                   $ )zAddress accessorr   r   s    r+   
getAddressServiceInfo.getAddress  s    ||r*   c                    U R                   $ )zPort accessor)r   r   s    r+   getPortServiceInfo.getPort  rL  r*   c                    U R                   $ )zPriority accessor)r   r   s    r+   getPriorityServiceInfo.getPriority  s    }}r*   c                    U R                   $ )zWeight accessor)r   r   s    r+   	getWeightServiceInfo.getWeight      {{r*   c                    U R                   $ )zProperties accessor)r8  r   s    r+   getPropertiesServiceInfo.getProperties  s    r*   c                    U R                   $ )zText accessorr   r   s    r+   getTextServiceInfo.getText  rL  r*   c                    U R                   $ )zServer accessor)r   r   s    r+   	getServerServiceInfo.getServer  r\  r*   c           	        UGbY  UR                  U5      (       GdA  UR                  [        :X  a-  UR                  U R                  :X  a  UR
                  U l        ggUR                  [        :X  a  UR                  U R                  :X  a  UR                  U l        UR                  U l        UR                  U l        UR                  U l	        U R                  UUUR                  R                  U R                  [        [        5      5        ggUR                  [        :X  a7  UR                  U R                  :X  a  U R                  UR                   5        ggggg)z-Updates service information from a DNS recordN)r   rV   r;  rU   r   r   r?  r   r   r   r  r  r  r  r>  rH  r   )rI   r  r   r   s       r+   r  ServiceInfo.updateRecord	  s   f&6&6s&;&;{{g%;;$++-#)>>DL .	);;$))+"(--DK &DI"(--DK$*OODM%%  33 KK) , 	);;$))+LL- , *' '<r*   c                    [        5       n[        nX4-   nX2-   nSn UR                  U [        U R                  [
        [        5      5        U R                  b  U R                  b  U R                  Gc  Xc::  a   UR                  U 5        gXS::  Ga}  [        [        5      nUR                  [        U R                  [        [        5      5        UR                  UR                   R#                  U R                  [        [        5      U5        UR                  [        U R                  [$        [        5      5        UR                  UR                   R#                  U R                  [$        [        5      U5        U R                  bm  UR                  [        U R                  [&        [        5      5        UR                  UR                   R#                  U R                  [&        [        5      U5        UR)                  U5        X4-   nUS-  nUR+                  [-        XV5      U-
  5        [        5       nU R                  c  GM  U R                  c  GM  U R                  c  GM  SnUR                  U 5        U$ ! UR                  U 5        f = f)zqReturns true if the service could be discovered on the
network, and updates this object with details discovered.
Fr   r   T)r,   _LISTENER_TIMEr  r   rU   r   r  r   r   r   removeListenerr`  rG  rk  r?  rn  r  r  r>  r;  r0  r  r1  )	rI   r  r  r   r  r[  lastrz   r   s	            r+   requestServiceInfo.request"  s     !{}/	*  k$))Y	B #t||';tyy?P;N ##D)M ;%o6COO#DIIy)D '' 33 IIy) 	 OO#DIIy)D '' 33 IIy) 	 {{.'WiH ++$NN77 $Wi  	 MM#&;D!AIEc$o34')O #t||';tyy?PP F##D) ##D)s%   AI: F7I: I: I: %I: :Jc                `    [        U[        5      (       a  UR                  U R                  :H  $ g)zTests equality of service namer   )r^   r   rU   r_   s     r+   ra   ServiceInfo.__eq__^  s%    e[))::**r*   c                .    U R                  U5      (       + $ rd   re   r_   s     r+   rf   ServiceInfo.__ne__d  rh   r*   c                *   SU R                   [        R                  " U R                  5       5      U R                  4-  nU R
                  c  US-  nO<[        U R
                  5      S:  a  XR
                  -  nOXR
                  SS S-   -  nUS-  nU$ )r   s   service[%s,%s:%s,Ns   None      r   rx   )rU   r   r   rQ  r   r   r   r  s     r+   r   ServiceInfo.__repr__h  s    %IIT__./II)
 

 99gF499~"))#))CR.611$r*   )	r   rU   r   r   r8  r   r   rV   r   )NNr   r   NN)r1   r2   r3   r4   r}   rH   r7  rH  rs   rN  rQ  rT  rW  rZ  r^  ra  rd  r  rl  ra   rf   r   r5   r)   r*   r+   r   r   v  sr     #'J#@##J.2:x&r*   r   c                      \ rS rSrSrSS jrS rS rS rS r	SS	 jr
S
 rS r\4S jrS rS rS rS rS rS rS rS r\\4S jrS rSrg)r   iz  zyImplementation of Zeroconf Multicast DNS Service Discovery

Supports registration, unregistration, queries and browsing.
Nc                   S[        5       S'   Uc/  [        R                  " [        R                  " 5       5      U l        OXl        S[
        4U l        [        R                  " [        R                  [        R                  5      U l         U R                  R                  [        R                  [        R                  S5        U R                  R                  [        R                  [        R                  S5        U R                  R                  [        [        R                  S5        U R                  R                  [        [        R                   S5         U R                  R#                  U R                  5        U R                  R                  [        [        R$                  [        R&                  " [(        5      [        R&                  " S5      -   5        / U l        / U l        0 U l        0 U l        [3        5       U l        [6        R8                  " 5       U l        [=        U 5      U l        [A        U 5      U l!        [E        U 5      U l#        g! [         a     GNef = f! [         a     Nf = f)	zpCreates an instance of the Zeroconf class, establishing
multicast communications, listening and reaping threads.r   r   Nr*   r         0.0.0.0)$r  r   gethostbynamegethostnameintfr  groupAF_INET
SOCK_DGRAM
setsockopt
SOL_SOCKETSO_REUSEADDRSO_REUSEPORTrG   _SOL_IPIP_MULTICAST_TTLIP_MULTICAST_LOOPbindIP_ADD_MEMBERSHIP	inet_atonr  	listenersbrowsersr  servicetypesr  r  r  r  r  r  r  r  r  r  reaper)rI   bindaddresss     r+   rH   Zeroconf.__init__  s    %&	.!,,V-?-?-ABDI#I:&
mmFNNF4E4EF	KK""6#4#4f6I6I1MKK""6#4#4f6I6I1M 	w(?(?Iw(@(@'J	KKTZZ(
 	$$Z(6+;+;I+FF	
 Z
",,.Tl TlI  
	 
	  	 	s%   A2I %I' 
I$#I$'
I43I4c                8    U R                   R                  S5      $ )Ns	   127.0.0.1r}  
startswithr   s    r+   
isLoopbackZeroconf.isLoopback  s    yy##L11r*   c                8    U R                   R                  S5      $ )Ns   169.254.r  r   s    r+   isLinklocalZeroconf.isLinklocal  s    yy##K00r*   c                    U R                   R                  5         U R                   R                  US-  5        U R                   R                  5         g)zJCalling thread waits for a given number of milliseconds or
until notified.r'   N)r  r  r  r  )rI   r  s     r+   r  Zeroconf.wait  s:     	 GdN+ r*   c                    U R                   R                  5         U R                   R                  5         U R                   R                  5         g)zNotifies all waiting threadsN)r  r  
notify_allr  r   s    r+   r,  Zeroconf.notifyAll  s2     !!# r*   c                J    [        X5      nUR                  X5      (       a  U$ g)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   rl  )rI   rV   rU   r  r   s        r+   getServiceInfoZeroconf.getServiceInfo  s%     4&<<&&Kr*   c                p    U R                  U5        U R                  R                  [        XU5      5        g)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   )rI   rV   r  s      r+   addServiceListenerZeroconf.addServiceListener  s+     	""8,^DABr*   c                p    U R                    H&  nUR                  U:X  d  M  UR                  5         AM(     g)z<Removes a listener from the set that is currently listening.N)r  r  r-  )rI   r  browsers      r+   r  Zeroconf.removeServiceListener  s+    }}G8+  %r*   c                B   U R                  U5        XR                  UR                  R                  5       '   UR                  U R
                  ;   a"  U R
                  UR                  ==   S-  ss'   OSU R
                  UR                  '   [        5       nUnSnUS:  Ga~  X4:  a  U R                  XC-
  5        [        5       nM+  [        [        [        -  5      nUR                  [        UR                  [        [        X!R                  5      S5        UR                  [        UR                  [         [        UUR"                  UR$                  UR&                  UR(                  5      S5        UR                  [+        UR                  [,        [        X!R.                  5      S5        UR0                  (       a:  UR                  [3        UR(                  [4        [        X!R0                  5      S5        U R7                  U5        US-  nU[8        -  nUS:  a  GM}  gg)zRegisters 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  rU   rS   rV   r  r,   r  r`  rK  	_FLAGS_AArn  r   r=  r  r   r?  r   r   r   r   r   r>  r   r   r   r;  r0  _REGISTER_TIME)rI   r   r   r   r  r&  r   s          r+   registerServiceZeroconf.registerService  s   
 	$+/diioo'(99)))dii(A-(+,Ddii(!!e~		(.)')09<=C499iCKQ IIMMKKIIKK	  		9iiiH! ||##Will 	 IIcNFA&HE !eer*   c                L    U R                   UR                  R                  5       	 U R                  UR                     S:  a"  U R                  UR                  ==   S-  ss'   OU R                  UR                  	  [        5       nUnSnUS:  Ga  X#:  a  U R                  X2-
  5        [        5       nM+  [        [        [        -  5      nUR                  [        UR                  [        [        SUR                  5      S5        UR                  [        UR                  [         [        SUR"                  UR$                  UR&                  UR                  5      S5        UR                  [)        UR                  [*        [        SUR,                  5      S5        UR.                  (       a;  UR                  [1        UR2                  [4        [        SUR.                  5      S5        U R7                  U5        US-  nU[8        -  nUS:  a  GM  gg! [
         a     GNf = f)zUnregister a service.r   r   r   N)r  rU   rS   r  rV   rl   r,   r  r`  rK  r  rn  r   r=  r  r   r?  r   r   r   r   r>  r   r   r   r   r;  r0  _UNREGISTER_TIME)rI   r   r   r  r&  r   s         r+   unregisterServiceZeroconf.unregisterService  s   	diioo/0  +a/!!$)),1,%%dii0  !!e~		(.)')09<=C499iAtyyI1 IIMMKKIIII	  		9iDIIF ||##WiDLL 	 IIcNFA((HE !ee  		s   A#H &H 
H#"H#c                   [        U R                  5      S:  Ga  [        5       nUnSnUS:  Ga  X:  a  U R                  X!-
  5        [        5       nM+  [	        [
        [        -  5      nU R                  R                  5        GH$  nUR                  [        UR                  [        [        SUR                  5      S5        UR                  [        UR                  [        [        SUR                   UR"                  UR$                  UR&                  5      S5        UR                  [)        UR                  [*        [        SUR,                  5      S5        UR.                  (       d  M  UR                  [1        UR&                  [2        [        SUR.                  5      S5        GM'     U R5                  U5        US-  nU[6        -  nUS:  a  GM  ggg)z#Unregister all registered services.r   r   r   N)r   r  r,   r  r`  rK  r  r  rn  r   rV   r=  r  rU   r   r?  r   r   r   r   r   r>  r   r   r   r;  r0  r  )rI   r   r  r&  r   r   s         r+   unregisterAllServicesZeroconf.unregisterAllServices@  s~   t}}!#%CHAa%>IIhn-+-C!"4y"@A MM002D''" IIy)Q		 	 ''" II%% MM KK II KK	  ''		9iDIIN |||++& $WiDLL 	3 3> 		#Q,,O a%%	 "r*   c           	        [        5       nUnSnUS:  Ga  U R                  R                  UR                  5       H  nUR                  [        :X  d  M  UR                  U5      (       a  M1  UR                  UR                  :X  d  MM  UR                  R                  S5      S:  aI  SUR                  UR                  UR                  UR                  4-  Ul        U R                  U5          g[        e   X#:  a   U R                  X2-
  5        [        5       nGM  [        [        [         -  5      nX`l        UR%                  ['        UR                  [        [(        5      5        UR+                  [-        UR                  [        [(        [.        UR                  5      5        U R1                  U5        US-  nU[2        -  nUS:  a  GM  gg)zfChecks the network for a unique service name, modifying the
ServiceInfo passed in if it is not unique.r   r   r  s   %s.[%s:%d].%sNr   )r,   r  r  rV   r=  r   r   rU   rD  r   r   r  r8   r  r`  rG  r  debugrk  r   r  ru  r   _DNS_TTLr0  _CHECK_TIME)rI   r   r   r  r&  r   r   s          r+   r  Zeroconf.checkServiceo  sa     !!e**44TYY?KK9,",,S11		1yy~~d+a/$4 II LL II II	8 %	 ))$/00 @  ~		(.)')o	9:CJOOK		9iHI&&499iHdiiP IIcNFA#H; !eer*   c                P   [        5       nU R                  R                  U5        Ubn  U R                  R	                  UR
                  5       HE  nUR                  U5      (       d  M  UR                  U5      (       a  M3  UR                  XU5        MG     U R                  5         g)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%  r  r  rU   r   r   r  r,  )rI   r  r'  r   r   s        r+   r  Zeroconf.addListener  s      !h'**44X]]C&&v..v7G7G7L7L))$V< D 	r*   c                |     U R                   R                  U5        U R                  5         g! [         a     gf = f)zRemoves a listener.N)r  r  r,  rG   )rI   r  s     r+   rj  Zeroconf.removeListener  s5    	NN!!(+NN 		s   +. 
;;c                n    U R                    H  nUR                  XU5        M     U R                  5         g)zFUsed to notify listeners of new information that has updated
a record.N)r  r  r,  )rI   r   r   r  s       r+   r  Zeroconf.updateRecord  s,     H!!$S1 'r*   c                   [        5       nUR                   H  nUR                  U5      nX0R                  R	                  5       ;   aU  U(       a  U R                  R                  U5        OMU R                  R                  U5      nUb  UR                  U5        UnOU R                  R                  U5        U R                  X#5        M     g)zdDeal with incoming response packets.  All answers
are held in the cache, and listeners are notified.N)
r,   r   r   r  r  r  r  r   r  r  )rI   r   r   r   r&  r  s         r+   r  Zeroconf.handleResponse  s      !kkF&&s+G++--JJ%%f- JJNN62E(v.!&

v&c* "r*   c                   SnU[         :w  a;  [        [        [        -  S5      nUR                   H  nUR                  U5        M     UR                   GH  nUR                  [        :X  Ga  UR                  S:X  ae  U R                  R                  5        HG  nUc  [        [        [        -  5      nUR                  U[        S[        [        [        U5      5        MI     U R                  R!                  5        Hw  nUR                  UR                  :X  d  M  Uc  [        [        [        -  5      nUR                  U[        UR                  [        [        [        UR                  5      5        My     GM&   Uc  [        [        [        -  5      nUR                  ["        :X  d  UR                  [$        :X  a  U R                  R!                  5        Hs  nUR&                  UR                  R)                  5       :X  d  M-  UR                  U[+        UR                  ["        [        [,        -  [        UR.                  5      5        Mu     U R                  R1                  UR                  R)                  5       S5      nU(       d  GM7  UR                  [2        :X  d  UR                  [$        :X  ag  UR                  U[5        UR                  [2        [        [,        -  [        UR6                  UR8                  UR:                  UR&                  5      5        UR                  [<        :X  d  UR                  [$        :X  aF  UR                  U[?        UR                  [<        [        [,        -  [        UR@                  5      5        UR                  [2        :X  aH  URC                  [+        UR&                  ["        [        [,        -  [        UR.                  5      5        GM  GM     Ub6  URJ                  (       a$  URL                  Ul&        U RO                  XBU5        ggg! [D         a    [F        RH                  " 5          GM  f = f)zCDeal with incoming query packets.  Provides a response if
possible.Nr   s   _services._dns-sd._udp.local.)(r  r`  rK  r  r  rk  rV   r=  rU   r  r  rp  r   r  r  r  r  r;  r   r   rS   r   rY   r   r  r?  r   r   r   r   r>  r   r   ry  rG   r  r  r   r  r0  )rI   r   r  r   r   r'  stypeservices           r+   r  Zeroconf.handleQuery  s*     :09<a@CMM) * H}}	)==$DD!%!2!2!7!7!9;"-.@9.L"MC& @ ) ) ( %	 ":  $}}335G}}4;"-.@9.L"MC& ' ) ) ( '		  6;*{)*<y*HI  }}/8==I3M'+}}';';'=G&~~1D1D1FF #$'$.(0(/(1M(A(0(/%&	!" (> #mm//0C0C0EtLG" }}	1X]]i5O& ( ) )M 9 ( ' 0 0 ' ' '	  }}	1X]]i5O# ( ) )M 9 ( '	  }}	1//& ' ' )M 9 ( ' 2_ &x ?s{{VVCFIIc&  +? ! *''))*s!   ;BP#BP#EP##QQc                ~     U R                   R                  UR                  5       SX#45        g! [         a     gf = f)zSends an outgoing packet.r   N)r   sendtor  rG   )rI   r   r  r   s       r+   r0  Zeroconf.send.  s7    	KKszz|Q= 		s   ,/ 
<<c                   [        5       S   S:X  a  S[        5       S'   U R                  5         U R                  R                  5         U R	                  5         U R
                  R                  [        [
        R                  [
        R                  " [        5      [
        R                  " S5      -   5        U R
                  R                  5         gg)zVEnds the background threads, and prevent this instance from
servicing further queries.r   r   r   rz  N)r  r,  r  r  r  r   r  r  IP_DROP_MEMBERSHIPr  r  closer   s    r+   r  Zeroconf.close8  s     9^$)()GIn%NNKK &&(KK""))  ,v/?/?	/JJ
 KK *r*   )r  r  r  r  r  r~  r}  r  r  r  r  r  r   r   )i  )r1   r2   r3   r4   r}   rH   r  r  r  r,  r  r  r  r  r  r  r  r  r  rj  r  r  r  r  r  r0  r  r5   r)   r*   r+   r   r   z  sz    
1#f21!!C )1 0'd/)b--^#$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.z	127.0.0.1i  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.)m
__future__r   
__author__	__email____version__r   r  r  r   r  r  r(   r  	mercurialr   __all__r  r  r  r  ri  r  r  r  r  r  _MAX_MSG_TYPICALr  rF  rG  rK  r  	_FLAGS_TC	_FLAGS_RD	_FLAGS_RA_FLAGS_Z	_FLAGS_AD	_FLAGS_CDr  	_CLASS_CS	_CLASS_CH	_CLASS_HS_CLASS_NONE
_CLASS_ANYrW   rY   r;  _TYPE_NS_TYPE_MD_TYPE_MFr<  	_TYPE_SOA_TYPE_MB_TYPE_MG_TYPE_MR
_TYPE_NULL	_TYPE_WKSr=  r@  _TYPE_MINFO_TYPE_MXr>  rA  r?  r   rk   rr   r,   rG   r.   r8   r;   r>   rA   rD   rM   SOL_IPr  	iswindows
IPPROTO_IPrP   r   r   r   r   r   r   r   r
  r`  r  r  r  r  r  r   r   r   r1   printrdescr  r   r  r   r  r  r  r)   r*   r+   <module>r     s   "0IO	J; .#
@4C
 "
0	         
7 	.    

	   										

	
			
		
 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 	 -- G6 6r:( :.?7 ?7D   2)y )0. .,1i 12G GBA AH_# _#D1 1h?!Y ?!D$. $.N7Y 7*R%Y%% R%jA AHK  K b z	
@+N
A	
45}<LMD,%		D 

&'d	
"#	
78	"A13KLM 

	
/0	$&J	
 

	
<=	
 !GGII r*   