o ^Ub @sFddlmZmZ dZdZdZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlmZgdZded<d Zd Zd Zd Zd ZdZdZdZdZdZdZdZdZdZdZ dZ!dZ"dZ#dZ$dZ%dZ&dZ'dZ(dZ)dZ*dZ+d Z,d!Z-dZ.dZ/dZ0dZ1dZ2d"Z3d#Z4d$Z5d%Z6d&Z7d'Z8d(Z9d)Z:d*Z;d+Zd-Z?d.Z@d ZAe'd/e(d0e)d1e*d2e+d3e,d4iZBie/d5e0d6e1d7e2d8e3d9e4d:e5d;e6d<e7d=e8d>e9d?e:d@e;dAedDe?dEe@dFeAd4iZCdGdHZDGdIdJdJeEZFGdKdLdLeEZGGdMdNdNeEZHGdOdPdPeEZIGdQdRdReEZJGdSdTdTeEZKGdUdVdVeKZLGdWdXdXeMZNGdYdZdZeNZOGd[d\d\eNZPGd]d^d^ePZQGd_d`d`ePZRGdadbdbePZSGdcddddePZTGdedfdfePZUGdgdhdheMZVGdidjdjeMZWGdkdldleMZXGdmdndne jYZZGdodpdpeMZ[Gdqdrdre jYZ\Gdsdtdte jYZ]GdudvdveMZ^GdwdxdxeMZ_e`dykr!eadzee_Zbead{d|d}d~dZce^dde dddddecZeeadebfeeeadeadeadegebhddeadeadeadegebhddeadeadebieeeadebjdSdS))absolute_importprint_functionsPaul Scott-Murphys!paul at scott dash murphy dot coms0.12N)pycompat)sZeroconfs ServiceInfosServiceBrowser _GLOBAL_DONE}iz 224.0.0.251i5iii #iii@ i !sinscsschshssnonesanyasnssmdsmfscnamessoasmbsmgsmrsnullswkssptrshinfosminfosmxstxtsquadassrvcCs tdS)z#Current system time in milliseconds)timer%r%9/usr/lib/python3/dist-packages/hgext/zeroconf/Zeroconf.pycurrentTimeMillis r'c@ eZdZdS)NonLocalNameExceptionN__name__ __module__ __qualname__r%r%r%r&r*r*c@r))NonUniqueNameExceptionNr+r%r%r%r&r0r/r0c@r))NamePartTooLongExceptionNr+r%r%r%r&r1r/r1c@r))AbstractMethodExceptionNr+r%r%r%r&r2r/r2c@r))BadTypeInNameExceptionNr+r%r%r%r&r3r/r3c@seZdZddZdS) BadDomainNamecCst|d|dS)Nsat position %s) Exception__init__)selfposr%r%r&r6szBadDomainName.__init__N)r,r-r.r6r%r%r%r&r4s r4c@r))BadDomainNameCircularNr+r%r%r%r&r9r/r9c@@eZdZdZddZddZddZdd Zd d Zd d Z dS)DNSEntryz A DNS entrycCs2||_||_||_|t@|_|t@dk|_dS)Nr)lowerkeynametype _CLASS_MASKclazz _CLASS_UNIQUEuniquer7r>r?rAr%r%r&r6s  zDNSEntry.__init__cCs2t|tr|j|jko|j|jko|j|jkSdS)z&Equality test on name, type, and classr) isinstancer;r>r?rAr7otherr%r%r&__eq__s    zDNSEntry.__eq__cC || SzNon-equality testrHrFr%r%r&__ne__r(zDNSEntry.__ne__cC&zt|WStyd|YSw)zClass accessor?(%s))_CLASSESKeyError)r7rAr%r%r&getClazz    zDNSEntry.getClazzcCrM) Type accessorrN)_TYPESrP)r7r?r%r%r&getType rRzDNSEntry.getTypecCsdd|||j||jf}|jr|d7}n|d7}||j7}|dur,|d|7}|S|d7}|S)1String representation with additional informations%s[%s,%ss-unique,,Ns,%s]])rUr?rQrArCr>)r7hdrrGresultr%r%r&toStrings     zDNSEntry.toStringN) r,r-r.__doc__r6rHrLrQrUr[r%r%r%r&r;s  r;c@s(eZdZdZddZddZddZdS) DNSQuestionzA DNS question entrycCs@tjr t|tr |d}|dst|t||||dS)Nasciis.local.) rispy3rEstrencodeendswithr*r;r6rDr%r%r&r6(s   zDNSQuestion.__init__cCs.|j|jko|j|jkp|jtko|j|jkS)z6Returns true if the question is answered by the record)rAr? _TYPE_ANYr>)r7recr%r%r& answeredBy/s  zDNSQuestion.answeredBycCst|ddS)String representationsquestionN)r;r[r7r%r%r&__repr__7zDNSQuestion.__repr__N)r,r-r.r\r6rerhr%r%r%r&r]%s  r]c@sheZdZdZddZddZddZdd Zd d Zd d Z ddZ ddZ ddZ ddZ ddZdS) DNSRecordz.A DNS record - like a DNS entry, but has a TTLcCs"t||||||_t|_dSN)r;r6ttlr'created)r7r>r?rArlr%r%r&r6?s zDNSRecord.__init__cCst|tr t||SdS)zTests equality as per DNSRecordr)rErjr;rHrFr%r%r&rHD  zDNSRecord.__eq__cCs |jD] }||r dSqdS)zdReturns true if any answer in a message can suffice for the information held in this record.rr)answerssuppressedByAnswer)r7msgrecordr%r%r& suppressedByJs  zDNSRecord.suppressedBycCs ||kr|j|jdkrdSdS)zwReturns true if another record has same name, type and class, and if its TTL is at least half of this record's.rrr)rlrFr%r%r&rpRszDNSRecord.suppressedByAnswercCs|j||jdS)zXReturns the time at which this record will have expired by a certain percentage.rrmrl)r7percentr%r%r&getExpirationTimeYszDNSRecord.getExpirationTimecCstd|d|dS)z%Returns the remaining TTL in seconds.rdr#)maxrvr7nowr%r%r&getRemainingTTL^zDNSRecord.getRemainingTTLcC|d|kS)z(Returns true if this record has expired.rwrvryr%r%r& isExpiredbrizDNSRecord.isExpiredcCr})z9Returns true if this record is at least half way expired.2r~ryr%r%r&isStalefrizDNSRecord.isStalecCs|j|_|j|_dS)zJSets this record's TTL and created time to that of another record.NrtrFr%r%r&resetTTLjs zDNSRecord.resetTTLcCst)zAbstract method)r2r7outr%r%r&writepszDNSRecord.writecCs&d|j|t|f}t|d|S)rVs%s/%s,%ssrecord)rlr{r'r;r[)r7rGargr%r%r&r[ts  zDNSRecord.toStringN)r,r-r.r\r6rHrsrprvr{rrrrr[r%r%r%r&rj<s rjc@0eZdZdZddZddZddZdd Zd S) DNSAddresszA DNS address recordcCt|||||||_dSrk)rjr6address)r7r>r?rArlrr%r%r&r6 zDNSAddress.__init__cC||jt|jdSz'Used in constructing an outgoing packetN) writeStringrlenrr%r%r&rr|zDNSAddress.writecCt|tr |j|jkSdS)zTests equality on addressr)rErrrFr%r%r&rHrnzDNSAddress.__eq__cCs(zt|jWSty|jYSwrf)socket inet_ntoarr5rgr%r%r&rhs   zDNSAddress.__repr__Nr,r-r.r\r6rrHrhr%r%r%r&r~  rc@r) DNSHinfozA DNS host information recordcCs"t|||||||_||_dSrk)rjr6cpuos)r7r>r?rArlrrr%r%r&r6s zDNSHinfo.__init__cCs,||jt|j||jt|jdSr)rrrrrr%r%r&rszDNSHinfo.writecCs&t|tr|j|jko|j|jkSdS)zTests equality on cpu and osr)rErrrrFr%r%r&rHs zDNSHinfo.__eq__cCs|jd|jS)rf )rrrgr%r%r&rhzDNSHinfo.__repr__Nrr%r%r%r&rs  rc@r) DNSPointerzA DNS pointer recordcCrrk)rjr6alias)r7r>r?rArlrr%r%r&r6rzDNSPointer.__init__cCs||jdSr) writeNamerrr%r%r&rrzDNSPointer.writecCr)zTests equality on aliasr)rErrrFr%r%r&rHrnzDNSPointer.__eq__cCs ||jSr)r[rrgr%r%r&rhr(zDNSPointer.__repr__Nrr%r%r%r&rrrc@r) DNSTextzA DNS text recordcCrrk)rjr6text)r7r>r?rArlrr%r%r&r6rzDNSText.__init__cCrr)rrrrr%r%r&rr|z DNSText.writecCr)zTests equality on textr)rErrrFr%r%r&rHrnzDNSText.__eq__cCs2t|jdkr||jdddS||jS)rfrNr...)rrr[rgr%r%r&rhs zDNSText.__repr__Nrr%r%r%r&rrrc@r) DNSServicezA DNS service recordc Cs.t|||||||_||_||_||_dSrk)rjr6priorityweightportserver) r7r>r?rArlrrrrr%r%r&r6s  zDNSService.__init__cCs4||j||j||j||jdSr) writeShortrrrrrrr%r%r&rs   zDNSService.writecCs>t|tr|j|jko|j|jko|j|jko|j|jkSdS)z3Tests equality on priority, weight, port and serverr)rErrrrrrFr%r%r&rHs     zDNSService.__eq__cCs|d|j|jfS)rfs%s:%s)r[rrrgr%r%r&rhszDNSService.__repr__Nrr%r%r%r&rs  rc@speZdZdZddZddZddZdd Zd d Zd d Z ddZ ddZ ddZ ddZ ddZddZdS) DNSIncomingz/Object representation of an incoming DNS packetcCsLd|_||_g|_g|_d|_d|_d|_d|_|| | dS)z/Constructor from string holding bytes of packetrN) offsetdata questionsro numquestions numanswersnumauthoritiesnumadditionals readHeader readQuestions readOthers)r7rr%r%r&r6s zDNSIncoming.__init__cCszd}t|}t||j|j|j|}|j|7_|d|_|d|_|d|_|d|_|d|_ |d|_ dS) zReads header portion of packets!HHHHHHrrrrrrN) structcalcsizeunpackrridflagsrrrrr7formatlengthinfor%r%r&rs      zDNSIncoming.readHeaderc Csd}t|}td|jD]7}|}t||j|j|j|}|j|7_zt||d|d}|j |Wq t yDYq wdS)z!Reads questions section of packets!HHrrN) rrrangerreadNamerrrr]rappendr*)r7rrir>rquestionr%r%r&r!s  zDNSIncoming.readQuestionscCBd}t|}t||j|j|j|}|j|7_|dS)z Reads an integer from the packet!Irrrrrrrr%r%r&readInt2 zDNSIncoming.readIntcCs(t|j|j}|jd7_||S)z(Reads a character string from the packetr)ordrr readString)r7rr%r%r&readCharacterString<s zDNSIncoming.readCharacterStringcCsFd|}t|}t||j|j|j|}|j|7_|dS)z0Reads a string of a given length from the packets!%dsrr)r7rrrrr%r%r&rBs zDNSIncoming.readStringcCr)z'Reads an unsigned short from the packet!Hrrrr%r%r&readUnsignedShortLrzDNSIncoming.readUnsignedShortc Csd}t|}|j|j|j}td|D]}|}t||j|j |j |}|j |7_ d}|dt krKt ||d|d|d| d}n|dt ksW|dtkrht||d|d|d|}nu|dtkrt||d|d|d| |d}n[|dtkrt||d|d|d||||}n;|dtkrt||d|d|d||}n!|dtkrt ||d|d|d| d}n |j |d7_ |dur|j|qdS) z@Reads answers, authorities and additionals section of the packets!HHiHrNrrrrr)rrrrrrrrrr_TYPE_Arr _TYPE_CNAME _TYPE_PTRr _TYPE_TXTr _TYPE_SRVrr _TYPE_HINFOrr _TYPE_AAAAror)r7rrnrdomainrrdr%r%r&rVsf         zDNSIncoming.readOtherscC|jt@tkS)zReturns true if this is a query)r_FLAGS_QR_MASK_FLAGS_QR_QUERYrgr%r%r&isQueryrizDNSIncoming.isQuerycCr)z"Returns true if this is a response)rr_FLAGS_QR_RESPONSErgr%r%r& isResponserizDNSIncoming.isResponsecCs|j|||dS)z6Reads a UTF-8 string of a given length from the packetutf-8)rdecode)r7rrr%r%r&readUTFr|zDNSIncoming.readUTFcCsd}|j}d}|} t|j||d}|d7}|dkrnG|d@}|dkr8d||||df}||7}n,|dkr`|dkrD|d}|d@d >t|j||dB}||kr]t||}nt|q |dkrn||_|S||_|S) z#Reads a domain name from the packetTrr.?r)rrrjoinrr9r4)r7rZoffnextfirstrtr%r%r&rs6 "zDNSIncoming.readNameN)r,r-r.r\r6rrrrrrrrrrrr%r%r%r&rs   ? rc@seZdZdZd$ddZddZddZd d Zd d Zd dZ ddZ ddZ ddZ ddZ ddZddZddZddZdd Zd!d"Zd#S)% DNSOutgoingz+Object representation of an outgoing packetrcCsFd|_d|_||_||_i|_g|_d|_g|_g|_g|_ g|_ dS)Nrr) finishedr multicastrnamesrsizerro authorities additionals)r7rrr%r%r&r6s zDNSOutgoing.__init__cC|j|dS)zAdds a questionN)rrr7rrr%r%r& addQuestionrzDNSOutgoing.addQuestioncCs||s ||ddSdS)zAdds an answerrN)rsaddAnswerAtTime)r7inprrr%r%r& addAnswers zDNSOutgoing.addAnswercCs6|dur|dks ||s|j||fdSdSdS)z6Adds an answer if if does not expire by a certain timeNr)rror)r7rrrzr%r%r&rs zDNSOutgoing.addAnswerAtTimecCr)zAdds an authoritative answerN)rrrr%r%r&addAuthoritativeAnswerrz"DNSOutgoing.addAuthoritativeAnswercCr)zAdds an additional answerN)rrrr%r%r&addAdditionalAnswerrzDNSOutgoing.addAdditionalAnswercC.d}|jt|t||jd7_dS)z"Writes a single byte to the packet!crN)rrrpackchrrr7valuerr%r%r& writeBytezDNSOutgoing.writeBytecCs,d}|j|t|||jd7_dS)z=Inserts an unsigned short in a certain position in the packetrrN)rinsertrrr)r7indexrrr%r%r& insertShortszDNSOutgoing.insertShortcCs*d}|jt|||jd7_dS)z&Writes an unsigned short to the packetrrN)rrrrrrr%r%r&rszDNSOutgoing.writeShortcCr)z(Writes an unsigned integer to the packetrrN)rrrrintrrr%r%r&writeIntrzDNSOutgoing.writeIntcCs6dt|d}|jt|||j|7_dS)zWrites a string to the packet!sN)r`rrrrr)r7rrrr%r%r&rszDNSOutgoing.writeStringcCs8|d}t|}|dkrt|||||dS)z5Writes a UTF-8 string of a given length to the packetrr N)rarr1rr)r7rutfstrrr%r%r&writeUTF s  zDNSOutgoing.writeUTFcCsz|j|}Wn0ty7|j|j|<|d}|ddkr%|dd}|D]}||q'|dYdSw||d?dB||dS)z"Writes a domain name to the packet.rNrrr)rrPrsplitrr)r7r>rpartspartr%r%r&rs       zDNSOutgoing.writeNamecCs(||j||j||jdS)zWrites a question to the packetN)rr>rr?rA)r7rr%r%r& writeQuestion,s  zDNSOutgoing.writeQuestioncCs||j||j|jr|jr||jtBn||j|dkr,||j n|| |t |j }|j d7_ |||j d8_ t d|j |d}|||dS)zPWrites a record (answer, authoritative answer, additional) to the packetrrrN)rr>rr?rCrrArBrrlr{rrrrrr)r7rrrzrrr%r%r& writeRecord2s      zDNSOutgoing.writeRecordcCs|jssd|_|jD]}||q |jD] \}}|||q|jD]}||dq"|jD]}||dq.|dt|j|dt|j|dt|j|dt|j|d|j |j rl|ddn|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.rrr)rrr ror rrrrrrrrr)r7ranswertime_ authority additionalr%r%r&packetIs&     zDNSOutgoing.packetN)r)r,r-r.r\r6rrrrrrrrrrrrr r rr%r%r%r&rs$   rc@sHeZdZdZddZddZddZdd Zd d Zd d Z ddZ dS)DNSCachezA cache of DNS entriescCs i|_dSrk)cachergr%r%r&r6hs zDNSCache.__init__cCsBz|j|j}Wntyg}|j|j<Ynw||dS)z Adds an entryN)rr=rPrr7entrylistr%r%r&addks  z DNSCache.addcCs2z|j|j}||WdStyYdSw)zRemoves an entryN)rr=removerPrr%r%r&rss   zDNSCache.removec Cs6z|j|j}|||WSttfyYdSw)zNGets an entry by key. Will return None if there is no matching entry.N)rr=rrP ValueErrorrr%r%r&get{s  z DNSCache.getcCst|||}||S)zRGets an entry by details. Will return None if there is no matching entry.)r;r)r7r>r?rArr%r%r& getByDetailss  zDNSCache.getByDetailscCs$z|j|WStygYSw)z5Returns a list of entries whose key matches the name.)rrP)r7r>r%r%r&entriesWithNames   zDNSCache.entriesWithNamecCs0z ttj|jWStygYSw)zReturns a list of all entries)r itertoolschain from_iterablervaluesr5rgr%r%r&entriess  zDNSCache.entriesN) r,r-r.r\r6rrrrrr!r%r%r%r&res  rc@r:)EngineacAn 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. cCs4tj|||_i|_d|_t|_|dS)Nr) threadingThreadr6zeroconfreaderstimeout Condition conditionstartr7r%r%r%r&r6s   zEngine.__init__c Cstds`|}t|dkr!|j|j|j|jn8z.t|gg|j\}}}|D]}z |j | Wq0t yMtdsKt Yq0wWn t yXYnwtdrdSdS)Nrr)globals getReadersrr)acquirewaitr'releaseselectr& handle_readr5 traceback print_exc)r7rsrrwrersockr%r%r&runs*       z Engine.runcCs"|j|j}|j|Srk)r)r.r&keysr0r7rZr%r%r&r-s   zEngine.getReaderscCs,|j||j|<|j|jdSrkr)r.r&notifyr0)r7readerrr%r%r& addReaders   zEngine.addReadercCs*|j|j|=|j|jdSrkr=)r7rr%r%r& delReaders  zEngine.delReadercCs"|j|j|jdSrk)r)r.r>r0rgr%r%r&r>s  z Engine.notifyN) r,r-r.r\r6r:r-r@rAr>r%r%r%r&r"s  r"c@ eZdZdZddZddZdS)Listenera4A 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.cCs||_|jj||jjdSrk)r%enginer@rr+r%r%r&r6szListener.__init__c Cs|jj}z |t\}\}}Wntjy*}z|jtjkr%WYd}~dSd}~ww||_t|}| r\|t krD|j |t t dS|t krZ|j ||||j |t t dSdS|j|dSrk)r%rrecvfrom_MAX_MSG_ABSOLUTEerrorerrnoEBADFrrr _MDNS_PORT handleQuery _MDNS_ADDR _DNS_PORThandleResponse)r7r9raddrrerqr%r%r&r2s& zListener.handle_readN)r,r-r.r\r6r2r%r%r%r&rCs rCc@rB)ReaperzNA Reaper is used by this module to remove cache entries that have expired.cCstj|||_|dSrk)r#r$r6r%r*r+r%r%r&r6s  zReaper.__init__cCs\ |jdtdrdSt}|jjD]}||r,|j|||jj|qq)NTi'r) r%r/r,r'rr!r updateRecordr)r7rzrrr%r%r&r: s   z Reaper.runN)r,r-r.r\r6r:r%r%r%r&rQs rQc@r) 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.cCsbtj|||_||_||_i|_t|_t |_ g|_ d|_ |j |t|jtt|dS)z%Creates a browser for a specific typerN)r#r$r6r%r?listenerservicesr'nexttime _BROWSER_TIMEdelayrdone addListenerr]r _CLASS_INr*)r7r%r?rTr%r%r&r6s  zServiceBrowser.__init__csjtkrijjkrk|}z)jj}|s!|njj=fdd}j |WdSWn t yY|sWjj<fdd}j |Ynw d}|j krm|_ dSdSdSdS)zCallback invoked by Zeroconf when new information arrives. Updates information required by browser in the Zeroconf cache.cj|jjSrk)rT removeServicer?rxrrr7r%r&< z-ServiceBrowser.updateRecord..Ncr\rk)rT addServicer?rr^r`r%r&raDrbK) r?rr>rrUrr<rrrr5rvrV)r7r%rzrrexpired oldrecordcallbackexpiresr%r`r&rR0s.        zServiceBrowser.updateRecordcCsd|_|jdS)Nr)rYr% notifyAllrgr%r%r&cancelMszServiceBrowser.cancelcCs d}t}t|jdkr|j|kr|j|j|tds#|jr%dSt}|j|krctt }| t |j t t|jD] }||sM|||q@|j|||j|_td|jd|_t|jdkrp|jd}|dury||jq)NTrri Nr)r'rrrVr%r/r,rYrrrr]r?rr[rUr rrsendrXminpop)r7eventrzrrrr%r%r&r:Qs.       zServiceBrowser.runN)r,r-r.r\r6rRrjr:r%r%r%r&rSs  rSc@seZdZdZ      d&ddZddZdd Zd d Zd d ZddZ ddZ ddZ ddZ ddZ ddZddZddZddZd d!Zd"d#Zd$d%ZdS)' ServiceInfozService informationNrc CsR||st||_||_||_||_||_||_|r||_n||_| |dS)aCreate 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) rbr3r?r>rrrrr setProperties) r7r?r>rrrr propertiesrr%r%r&r6os zServiceInfo.__init__c Cst|trX||_g}d}|D].}||}|durd}nt|tr#|}nt|tr0|r-d}nd}nd}|d||fq|D]}d|tdt t ||f}q?||_ dS||_ dS)z7Sets properties and text of this info from a dictionaryrNtruefalse=r) rEdictrqr`rrrrrrbytechrrr)r7rqrrZr=rsuffixitemr%r%r&rps2     zServiceInfo.setPropertiesc Cs||_zni}t|}d}g}||kr/t||}|d7}|||||||7}||ks|D]:}|d}|dkrA|} d} n|d|} ||dd} | dkrVd} n| dks\| s^d} | rk|| durk| || <q1||_WdStyt d|_YdSw)z+Sets properties and text given a text fieldrrrtrNrrrs) rrrrfindrrqr5r3r4) r7rrZendrstrsrreindexr=rr%r%r&setTexts>       zServiceInfo.setTextcC|jS)rS)r?rgr%r%r&rUzServiceInfo.getTypecCsD|jdur|jd|jr|jdt|jt|jdS|jS)z Name accessorNrr)r?r>rbrrgr%r%r&getNames"zServiceInfo.getNamecCr~)zAddress accessor)rrgr%r%r& getAddressrzServiceInfo.getAddresscCr~)z Port accessor)rrgr%r%r&getPortrzServiceInfo.getPortcCr~)zPriority accessor)rrgr%r%r& getPriorityrzServiceInfo.getPrioritycCr~)zWeight accessor)rrgr%r%r& getWeightrzServiceInfo.getWeightcCr~)zProperties accessor)rqrgr%r%r& getPropertiesrzServiceInfo.getPropertiescCr~)z Text accessor)rrgr%r%r&getTextrzServiceInfo.getTextcCr~)zServer accessor)rrgr%r%r& getServerrzServiceInfo.getServerc Cs|dur\||s^|jtkr|j|jkr|j|_dSdS|jtkrI|j|jkrG|j|_|j|_|j|_|j |_ | |||j |jtt dSdS|jtkr`|j|jkrb||jdSdSdSdSdS)z-Updates service information from a DNS recordN)rr?rr>rrrrrrrRrrr[rr}r)r7r%rzrrr%r%r&rRs2      zServiceInfo.updateRecordc Cs~t}t}||}||}z||t|jtt|jdus(|jdus(|j dur||kr4W| |dS||krt t }| t|jtt||j|jtt|| t|jtt||j|jtt||jdur| t|jtt||j|jtt|||||}|d}|t|||t}|jdus(|jdus(|j dus(d}W| ||S| |w)zReturns true if the service could be discovered on the network, and updates this object with details discovered. Nrrr)r'_LISTENER_TIMErZr]r>rcr[rrrremoveListenerrrrrrrrrrrkr/rl) r7r%r'rzrXrlastrrZr%r%r&requestsh'     (  zServiceInfo.requestcCst|tr |j|jkSdS)zTests equality of service namer)rEror>rFr%r%r&rHSrnzServiceInfo.__eq__cCrIrJrKrFr%r%r&rLYr(zServiceInfo.__ne__cCsld|jt||jf}|jdur|d7}nt|jdkr%||j7}n ||jddd7}|d7}|S)rfsservice[%s,%s:%s,NsNonerrX)r>rrrrrrr<r%r%r&rh]s    zServiceInfo.__repr__)NNrrNN)r,r-r.r\r6rpr}rUrrrrrrrrrRrrHrLrhr%r%r%r&rols2 % %; roc@seZdZdZd*ddZddZddZd d Zd d Zd+ddZ ddZ ddZ e fddZ ddZddZddZddZddZd d!Zd"d#Zd$d%Zeefd&d'Zd(d)ZdS),ZeroconfzImplementation of Zeroconf Multicast DNS Service Discovery Supports registration, unregistration, queries and browsing. NcCsDdtd<|durtt|_n||_dtf|_ttjtj|_z|j tj tj d|j tj tj dWn t yBYnw|j tjtjd|j tjtjdz |j|jWn t yiYnw|j tjtjtttdg|_g|_i|_i|_t|_t|_t||_t ||_!t"||_#dS) zxCreates an instance of the Zeroconf class, establishing multicast communications, listening and reaping threads.rrNrr0.0.0.0)$r,r gethostbyname gethostnameintfrJgroupAF_INET SOCK_DGRAM setsockopt SOL_SOCKET SO_REUSEADDR SO_REUSEPORTr5SOL_IPIP_MULTICAST_TTLIP_MULTICAST_LOOPbindIP_ADD_MEMBERSHIP inet_atonrL listenersbrowsersrU servicetypesrrr#r(r)r"rDrCrTrQreaper)r7 bindaddressr%r%r&r6usB         zZeroconf.__init__cC |jdS)N 127.0.0.1r startswithrgr%r%r& isLoopback zZeroconf.isLoopbackcCr)Ns169.254.rrgr%r%r& isLinklocalrzZeroconf.isLinklocalcCs(|j|j|d|jdS)zRCalling thread waits for a given number of milliseconds or until notified.r#N)r)r.r/r0)r7r'r%r%r&r/s z Zeroconf.waitcCs"|j|j|jdS)zNotifies all waiting threadsN)r)r. notify_allr0rgr%r%r&ris  zZeroconf.notifyAll cCst||}|||r |SdS)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)ror)r7r?r>r'rr%r%r&getServiceInfos  zZeroconf.getServiceInfocCs"|||jt|||dS)zAdds a listener for a particular service type. This object will then have its updateRecord method called when information arrives for that type.N)removeServiceListenerrrrS)r7r?rTr%r%r&addServiceListeners zZeroconf.addServiceListenercCs$|jD] }|j|kr|~qdS)z|||t}q+tt t B}| t |jt t||jd| t|jtt||j|j|j|jd| t|jtt||jd|jr| t|jtt||jd|||d7}|t7}|dks/dSdS)aRegisters 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.rrrN) checkServicerUr>r<r?rr'r/rr _FLAGS_AArrrr[rrrrrrrrrrrrrk_REGISTER_TIME)r7rrlrzrVrrr%r%r&registerServicesX       zZeroconf.registerServicec CsBz!|j|j=|j|jdkr|j|jd8<n|j|j=Wn ty*Ynwt}|}d}|dkr||krE|||t}q2tt t B}| t |jt td|jd| t|jttd|j|j|j|jd| t|jttd|jd|jr| t|jttd|jd|||d7}|t7}|dks6dSdS)zUnregister a service.rrrN)rUr>r<rr?rPr'r/rrrrrrr[rrrrrrrrrrrrrk_UNREGISTER_TIME)r7rrzrVrrr%r%r&unregisterServices`      zZeroconf.unregisterServicec Cst|jdkrt}|}d}|dkr||kr!|||t}qtttB}|jD]C}|t |j t t d|j d|t|j tt d|j|j|j|jd|t|j tt d|jd|jro|t|jtt d|jdq,|||d7}|t7}|dksdSdSdS)z#Unregister all registered services.rrrN)rrUr'r/rrrr rrr?rr[r>rrrrrrrrrrrrrkr)r7rzrVrrrr%r%r&unregisterAllServices5s`     zZeroconf.unregisterAllServicescCst}|}d}|dkr|j|jD]1}|jtkrC||sC|j|jkrC|jddkrAd|j|j |j |jf|_| |dSt q||krS| ||t}qtttB}||_|t|jtt|t|jttt|j|||d7}|t7}|dks dSdS)znChecks the network for a unique service name, modifying the ServiceInfo passed in if it is not unique.rrrs %s.[%s:%d].%sNr)r'rrr?rrrr>ryrrrr0r/rrrdebugrr]r[rr_DNS_TTLrk _CHECK_TIME)r7rrzrVrrrrr%r%r&rdsD     zZeroconf.checkServicecCs\t}|j||dur(|j|jD]}||r'||s'||||q| dS)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'rrrrr>rerrRri)r7rTrrzrrr%r%r&rZs  zZeroconf.addListenercCs0z |j||WdStyYdSw)zRemoves a listener.N)rrrir5)r7rTr%r%r&rs   zZeroconf.removeListenercCs&|jD] }||||q|dS)zNUsed to notify listeners of new information that has updated a record.N)rrRri)r7rzrdrTr%r%r&rRs  zZeroconf.updateRecordcCs|t}|jD]5}||}||jvr/|r|j|n|j|}|dur.|||}n|j|| ||qdS)zlDeal with incoming response packets. All answers are held in the cache, and listeners are notified.N) r'rorrr!rrrrrR)r7rqrzrrrerr%r%r&rNs     zZeroconf.handleResponsec CsNd}|tkrtttBd}|jD]}||q|jD]}|jtkrl|jdkrE|j D]}|dur8tttB}| |t dtt t|q,|jD] }|j|jkrj|dur\tttB}| |t |jtt t|jqJqz|durwtttB}|jtks|jtkr|jD]}|j|jkr| |t|jtt tBt|jq|j|jd}|sWq|jtks|jtkr| |t|jtt tBt|j|j|j|j|jtks|jtkr| |t|jtt tBt|j |jtkr|!t|jtt tBt|jWqt"y t#$Yqw|dur#|j%r%|j&|_&|'|||dSdSdS)zKDeal with incoming query packets. Provides a response if possible.Nrs_services._dns-sd._udp.local.)(rJrrrrrr?rr>rr;rrr[rrUr rrcrr<rrBrrrrrrrrrrrr5r3r4rorrk)r7rqrOrrrstypeservicer%r%r&rKs             zZeroconf.handleQuerycCs4z|j|d||fWdStyYdSw)zSends an outgoing packet.rN)rsendtorr5)r7rrOrr%r%r&rk#s  z Zeroconf.sendcCshtddkr2dtd<||j||jtjtjt t t d|j dSdS)z^Ends the background threads, and prevent this instance from servicing further queries.rrrrN) r,rirDr>rrrrIP_DROP_MEMBERSHIPrrLclosergr%r%r&r-s  zZeroconf.closerk)r)r,r-r.r\r6rrr/rirrrrrrrrrZrrRrNrKrLrJrkrr%r%r%r&ros* 3   21/% l r__main__s3Multicast DNS Service Discovery for Python, versions'1. Testing registration of a service...s0.10s test values another value)sversionr"bs_http._tcp.local.s!My Service Name._http._tcp.local.ris Registering service...s Registration done.s*2. Testing query of service information...s Getting ZOE service:sZOE._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.)k __future__rr __author__ __email__ __version__rHrr1rrr#r$r3 mercurialr__all__r,rrrrrWrLrJrMr_MAX_MSG_TYPICALrFrrrr _FLAGS_TC _FLAGS_RD _FLAGS_RA_FLAGS_Z _FLAGS_AD _FLAGS_CDr[ _CLASS_CS _CLASS_CH _CLASS_HS _CLASS_NONE _CLASS_ANYr@rBr_TYPE_NS_TYPE_MD_TYPE_MFr _TYPE_SOA_TYPE_MB_TYPE_MG_TYPE_MR _TYPE_NULL _TYPE_WKSrr _TYPE_MINFO_TYPE_MXrrrrcrOrTr'r5r*r0r1r2r3r4r9objectr;r]rjrrrrrrrrr$r"rCrQrSrorr,printrdescrrrr`rrrr%r%r%r&sx           9B!E#4B'U T