
    |;iF                    ~   U d Z ddlmZ ddlmZmZ ddlmZmZ ddl	m
Z
mZmZmZmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZmZmZmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$ ddl%m&Z&m'Z'm(Z(m)Z) e!e#heZ*g Z+de,d<   g Z-de,d<   ej\                  Z/e0Z1e2Z3dZ4dZ5dZ6dZ7dZ8erddl9m:Z:  G d d      Z; G d d      Z< G d d      Z=y)a  Multicast DNS Service Discovery for Python, v0.14-wmcbrine
Copyright 2003 Paul Scott-Murphy, 2014 William McBrine

This module provides a framework for the use of DNS Service Discovery
using IP multicast.

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

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

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
USA
    )annotations)TYPE_CHECKINGcast   )DNSCache_UniqueRecordsType)
DNSAddress
DNSPointerDNSQuestion	DNSRecordDNSRRSet)DNSIncoming)ServiceInfo)_WrappedTransport)	IPVersion)_ADDRESS_RECORD_TYPES	_CLASS_IN_DNS_OTHER_TTL
_MDNS_PORT_ONE_SECOND_SERVICE_TYPE_ENUMERATION_NAME_TYPE_A
_TYPE_AAAA	_TYPE_ANY
_TYPE_NSEC	_TYPE_PTR	_TYPE_SRV	_TYPE_TXT   )QuestionAnswers_AnswerWithAdditionalsType$construct_outgoing_multicast_answers"construct_outgoing_unicast_answerslist[ServiceInfo]_EMPTY_SERVICES_LIST	list[str]_EMPTY_TYPES_LIST      )Zeroconfc                  ,    e Zd ZdZ	 	 	 	 	 	 	 	 	 	 ddZy)_AnswerStrategy)questionservicesstrategy_typetypesc                <    || _         || _        || _        || _        y)zCreate an answer strategy.N)r-   r/   r0   r.   )selfr-   r/   r0   r.   s        S/home/ubuntu/myenv/lib/python3.12/site-packages/zeroconf/_handlers/query_handler.py__init__z_AnswerStrategy.__init__N   s!     !*
     N)
r-   r   r/   _intr0   r&   r.   r$   returnNone)__name__
__module____qualname__	__slots__r4    r5   r3   r,   r,   K   s<    BI!! ! 	!
 $! 
!r5   r,   c                  P    e Zd ZdZdZddZddZddZddZ	 	 ddZ	ddZ
dd	Zy
)_QueryResponsez7A pair for unicast and multicast DNSOutgoing responses.)	_additionals_cache	_is_probe_mcast_aggregate_mcast_aggregate_last_second
_mcast_now_now
_questions_ucastc                    || _         || _        || _        || _        i | _        t               | _        t               | _        t               | _        t               | _	        y)zBuild a query response.N)
rB   rG   rF   rA   r@   setrH   rE   rC   rD   )r2   cache	questionsis_probenows        r3   r4   z_QueryResponse.__init__k   sL    !#	8:&)e*-%03<?E)r5   c                J   |j                         D ]  \  }}|| j                  |<   | j                  r| j                  j	                  |       | j                  |      s| j                  j	                  |       i| j                  rv| j                  j	                  |        y)z,Generate a response to a multicast QU query.N)itemsr@   rB   rH   add!_has_mcast_within_one_quarter_ttlrE   )r2   answersrecordadditionalss       r3   add_qu_question_responsez'_QueryResponse.add_qu_question_responsew   sz    #*==? 	(FK(3Df%~~'99&A##F+^^'	(r5   c                p    | j                   j                  |       | j                  j                  |       y)z'Generate a response to a unicast query.N)r@   updaterH   )r2   rS   s     r3   add_ucast_question_responsez*_QueryResponse.add_ucast_question_response   s(      )7#r5   c                   | j                   j                  |       |D ]  }| j                  r| j                  j	                  |       +| j                  |      r| j                  j	                  |       Xt        | j                        dk(  r=| j                  d   }|j                  t        v r| j                  j	                  |       | j                  j	                  |        y)z)Generate a response to a multicast query.r   r   N)r@   rX   rB   rE   rQ    _has_mcast_record_in_last_secondrD   lenrG   type_RESPOND_IMMEDIATE_TYPESrC   )r2   rS   answerr-   s       r3   add_mcast_question_responsez*_QueryResponse.add_mcast_question_response   s      ) 	.F~~##F+44V<1155f=4??#q(??1-==$<<OO''/!!%%f-	.r5   c                ~   | j                   D ci c]  }|| j                  |    }}| j                  D ci c]  }|| j                  |    }}| j                  D ci c]  }|| j                  |    }}| j                  D ci c]  }|| j                  |    }}t        ||||      S c c}w c c}w c c}w c c}w )z'Return answer sets that will be queued.)rH   r@   rE   rC   rD   r    )r2   rucast	mcast_nowmcast_aggregatemcast_aggregate_last_seconds         r3   rS   z_QueryResponse.answers   s     37++>QD%%a((>>6:ooFQ))!,,F	F<@<Q<QRq1d//22RRHLHiHi&j1q$*;*;A*>'>&j#&juiB]^^	 ?FR&js   B+B0B5B:c                    t         rt        t        |      }| j                  j	                  |      }t        |duxr |j                  | j                              S )a  Check to see if a record has been mcasted recently.

        https://datatracker.ietf.org/doc/html/rfc6762#section-5.4
        When receiving a question with the unicast-response bit set, a
        responder SHOULD usually respond with a unicast packet directed back
        to the querier.  However, if the responder has not multicast that
        record recently (within one quarter of its TTL), then the responder
        SHOULD instead multicast the response so as to keep all the peer
        caches up to date
        N)r   r   r   rA   async_get_uniquebool	is_recentrF   r2   rT   maybe_entrys      r3   rR   z0_QueryResponse._has_mcast_within_one_quarter_ttl   sL     ,f5Fkk226:Kt+P0E0Edii0PQQr5   c                    t         rt        t        |      }| j                  j	                  |      }t        |duxr  | j                  |j                  z
  t        k        S )zCheck if an answer was seen in the last second.
        Protect the network against excessive packet flooding
        https://datatracker.ietf.org/doc/html/rfc6762#section-14
        N)	r   r   r   rA   rh   ri   rF   createdr   rk   s      r3   r[   z/_QueryResponse._has_mcast_record_in_last_second   sR    
 ,f5Fkk226:Kt+]		K<O<O0OR]0]^^r5   N)
rK   r   rL   zlist[DNSQuestion]rM   ri   rN   floatr7   r8   )rS   r!   r7   r8   )r7   r    )rT   r   r7   ri   )r9   r:   r;   __doc__r<   r4   rV   rY   r`   rS   rR   r[   r=   r5   r3   r?   r?   \   s<    A
I
B	($
.(_	_R _r5   r?   c                      e Zd ZdZdZddZ	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 	 	 	 	 	 	 ddZ		 	 	 	 	 	 ddZ
	 	 	 	 dd	Z	 	 	 	 	 	 	 	 	 	 	 	 dd
Zy)QueryHandlerzQuery the ServiceRegistry.)rK   out_delay_queue	out_queuequestion_historyregistryzcc                    || _         |j                  | _        |j                  | _        |j                  | _        |j                  | _        |j
                  | _        y)zInit the query handler.N)rw   rv   rK   ru   rt   rs   )r2   rw   s     r3   r4   zQueryHandler.__init__   sF    XX
 " 3 3!11r5   c           	         |D ]A  }t        t        t        t        t        |d      }|j                  |      r5t               ||<   C y)zProvide an answer to a service type enumeration query.

        https://datatracker.ietf.org/doc/html/rfc6763#section-9
        g        N)r
   r   r   r   r   
suppressesrJ   )r2   r0   
answer_setknown_answersstypedns_pointers         r3   +_add_service_type_enumeration_query_answersz8QueryHandler._add_service_type_enumeration_query_answers   sK      
	0E$.K !++K8*-%
;'
	0r5   c                    |D ][  }|j                  d      }|j                  |      r&|j                  d      |j                  d      h|j	                  d      ||<   ] y)zAnswer PTR/ANY question.N)_dns_pointerrz   _dns_service	_dns_text_get_address_and_nsec_records)r2   r.   r{   r|   servicer~   s         r3   _add_pointer_answersz!QueryHandler._add_pointer_answers   ss       
	G "..t4K''4$$T*!!$'' 66t<'J{#
	r5   c                `   |D ](  }g }t               }t               }|j                  dt              D ]a  }	|j                  |	j                         |	j                  |k7  r|j                  |	       ?|j                  |	      rQ|j                  |	       c t        |z
  }
|rL|
r=|j                  J d       |j                  |j                  t        |
      d             |D ]  }|||<   	 ||
v s|j                  J d       t               ||j                  t        |
      d      <   + y)zAnswer A/AAAA/ANY question.Nz+Service server must be set for NSEC record.)rJ   _dns_addresses_IPVersion_ALLrQ   r]   rz   appendr   server	_dns_nseclist)r2   r.   r{   r|   type_r   rS   rU   
seen_typesdns_addressmissing_typesr_   s               r3   _add_address_answersz!QueryHandler._add_address_answers   s%      	QG(*G*-%K#&5J&55dNK 0{//0##u,OOK0&11+>NN;/0 '<j&HM ">>5d7dd5OOG$5$5d=6I4$PQ% 5F)4Jv&5-'~~1`3``1KN5
7,,T--@$GH'	Qr5   c                   i }|t         k(  r| j                  |||       |S |t        k(  r| j                  |||       |S |t        k(  r | j                  ||||j                         |S |t        k(  r=|d   }|j                  d      }|j                  |      s|j                  d      ||<   |S |t        k(  r4|d   }|j                  d      }	|j                  |	      st               ||	<   |S )zAnswer a question.r   N))_ANSWER_STRATEGY_SERVICE_TYPE_ENUMERATIONr   _ANSWER_STRATEGY_POINTERr   _ANSWER_STRATEGY_ADDRESSr   r]   _ANSWER_STRATEGY_SERVICEr   rz   r   _ANSWER_STRATEGY_TEXTr   rJ   )
r2   r-   r/   r0   r.   r|   r{   r   dns_servicedns_texts
             r3   _answer_questionzQueryHandler._answer_question  s    24
EE<<UJP]^$ # 66%%h
MJ   66%%h
M8==Y  66 qkG!..t4K ++K8*1*O*OPT*U
;'  33qkG((.H ++H5'*u
8$r5   c                (   g }|D ]3  }|j                   D ]"  }|j                  | j                  |             $ 5 |syd}|d   }|j                   }g }|D ]4  }|j                         rd}|j                  |j	                                6 t        | j                  |||j                        }	t        |      }
d}|j                  }|D ]  }|j                  }|j                  }|s/||
j                         }| j                  j                  |||       | j                  ||j                  |j                   |j"                  |
      }|s|r|	j%                  |       |r|	j'                  |       |	j)                  |        |	j	                         S )zDeal with incoming query packets. Provides a response if possible.

        This function must be run in the event loop as it is not
        threadsafe.
        NFr   T)rG   extend_get_answer_strategiesrM   rS   r?   rK   rN   r   r-   unique
lookup_setru   add_question_at_timer   r/   r0   r.   rV   rY   r`   )r2   msgsucast_source
strategiesmsgr-   rM   rL   rS   	query_resr|   known_answers_setrN   strategy
is_unicastr{   s                   r3   async_responsezQueryHandler.async_response;  s    -/
 	ICNN I!!$"="=h"GHI	I  1gNN	 $& 	.C||~s{{}-		. #4::y(CGGL	 )37gg" 	>H((H!J$,(5(@(@(B%%%::8SJ[\..&&!!J  J22:>55jA 11*=+	>.   ""r5   c                ~   |j                   }|j                         }|j                  }g }|t        k(  rL|t        k(  rC| j
                  j                         }|r%|j                  t        |t        |t                     |S |t        t        fv rB| j
                  j                  |      }|r%|j                  t        |t        t        |             |t        t         t        fv rB| j
                  j#                  |      }|r%|j                  t        |t$        t        |             |t&        t(        t        fv r| j
                  j+                  |      }|h|t&        t        fv r&|j                  t        |t,        t        |g             |t(        t        fv r&|j                  t        |t.        t        |g             |S )z(Collect strategies to answer a question.)namelowerr]   r   r   rv   async_get_typesr   r,   r   r%   r   async_get_infos_typer   r'   r   r   async_get_infos_serverr   r   r   async_get_info_namer   r   )	r2   r-   r   question_lower_namer   r   r0   r.   r   s	            r3   r   z#QueryHandler._get_answer_strategiesw  s   
 }}"jjl,.
I"59W"WMM113E!!# A,	 Y	**}}99:MNH!!#H.FHY[cd Wj)44}};;<OPH!!#H.FHY[cd Y	955mm778KLG"Y	22%%'$4-$I	 Y	22%%'$1-$I	 r5   c                f   |d   }|t         k7  }| j                  ||      }|y|j                  rO|j                  }	|j                  }
t        |j                  ||	|
      }| j                  j                  |||||       |j                  r.| j                  j                  t        |j                               |j                  r0| j                  j                  |j                  |j                         |j                  r1| j                  j                  |j                  |j                         yy)aW  Respond to a (re)assembled query.

        If the protocol received packets with the TC bit set, it will
        wait a bit for the rest of the packets and only call
        handle_assembled_query once it has a complete set of packets
        or the timer expires. If the TC bit is not set, a single
        packet will be in packets.
        r   N)r   r   rc   rG   idr#   rw   
async_sendrd   r"   re   rt   	async_addrN   rf   rs   )r2   packetsaddrport	transportv6_flow_scopefirst_packetr   question_answersrL   id_outs               r3   handle_assembled_queryz#QueryHandler.handle_assembled_query  s
     qzz)..wE#!!$//I//C45E5K5K\[dfijC GGsD$yI%%GGCDTD^D^_`++NN$$\%5%57G7W7WX77   **<+;+;=M=i=ij	 8r5   N)rw   r*   r7   r8   )r0   r&   r{   r!   r|   r   r7   r8   )r.   r$   r{   r!   r|   r   r7   r8   )
r.   r$   r{   r!   r|   r   r   r6   r7   r8   )r-   r   r/   r6   r0   r&   r.   r$   r|   r   r7   r!   )r   list[DNSIncoming]r   ri   r7   zQuestionAnswers | None)r-   r   r7   zlist[_AnswerStrategy])r   r   r   _strr   r6   r   r   r   ztuple[()] | tuple[int, int]r7   r8   )r9   r:   r;   rp   r<   r4   r   r   r   r   r   r   r   r=   r5   r3   rr   rr      s^   $I200 /0  	0
 
0,# /  	
 
&Q#Q /Q  	Q
 Q 
Q:  	
 $   
$@:#%:#59:#	:#x;; 
;z%k"%k %k 	%k
 %%k 3%k 
%kr5   rr   N)>rp   
__future__r   typingr   r   rA   r   r   _dnsr	   r
   r   r   r   _protocol.incomingr   _services.infor   
_transportr   
_utils.netr   constr   r   r   r   r   r   r   r   r   r   r   r   r   rS   r    r!   r"   r#   r^   r%   __annotations__r'   Allr   intr6   strr   r   r   r   r   r   _corer*   r,   r?   rr   r=   r5   r3   <module>r      s   , # & 1 K K , ( * "     '	J4IJ *, ' ,! 9 !

,- )     ! !"a_ a_HYk Ykr5   