U
    hh                     @   sf  d Z ddlZddlZddlZddlZddlZddlmZmZm	Z	m
Z
mZ ddlZddlZddlZddlZddlZddlZddlZddlZddlZddl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# e"rddl$Z$ej%j&Z'dd Z(d6dd	Z)d7ej*j+eej,j-e.f ee	e/ e
e0e/f d
ddZ1d8ej*j+e	e e	e/ e2e2e	eej3j4ej5j6f  e	e. e2e2e2e	ej,j- edddZ7d9ej,j-e8e	e/ e0e	e8 e0e2e2e2e2e	ej*j+ e	ej*j9 e2ej,j-dddZ:d:ej,j-e8e	e/ e0e	e8 e0e2e2e2e	ej*j+ e	ej*j; e	ej*j9 e2e
ej,j-e2f dddZ<d;ej*j;eej,j-e.f e	e/ e
e0e/f dddZ=dd Z>d<ej*j;e	e/ e2e	eej3j4ej5j6f  e	e. e2e
ej,j-e/f ddd Z?d=ej,j-e8e	e/ e0e	e8 e0e2e2e	ej*j; e	ej*j9 ej,j-d!d"d#Z@d>ej,j-e8e	e/ e0e	e8 e0e2e2e	ej*j; e	ej*j9 e	e#jA e	e8 ee2e8f ej,j-d&d'd(ZBdd)dddddd*d%d%ddejCfej,j-e8e	e/ e0e	e8 e0e2e2e	d+ e8e2ee2e8f e	e8 e	d, e	e0 ej,j-d-d.d/ZDddddddejEdfe8ejFjGe	ej,j- e0e	e/ e	e/ e	e8 e0ee	ej*j9 dd0d1d2ZHd?ej,j-e8e	e/ e0e	e8 e0e2e2e	ejIjJ ee2e8f e	ej*j9 e	e8 ej,j-d3d4d5ZIdS )@zTalk to a DNS server.    N)AnyDictOptionalTupleUnion)NullContext)
BadResponseNoDOHNoDOQUDPMode_compute_times_make_dot_ssl_context_matches_destination
_remaininghave_dohsslc                 C   sN   |s|rF|d kr>| t jkr d}n| t jkr0d}ntd|  ||fS d S d S )Nz0.0.0.0z::zunknown address family )socketAF_INETAF_INET6NotImplementedError)afZaddressport r   4./venv/lib/python3.8/site-packages/dns/asyncquery.py_source_tuple:   s    

r   c                 C   s*   | d k	r"|st   }t| | dS d S d S )Nr   )timemax)
expirationZnowr   r   r   _timeoutJ   s
    r   )sockwhatdestinationr   returnc                    s@   t |tjjr| }t }| ||t||I dH }||fS )a  Send a DNS message to the specified UDP socket.

    *sock*, a ``dns.asyncbackend.DatagramSocket``.

    *what*, a ``bytes`` or ``dns.message.Message``, the message to send.

    *destination*, a destination tuple appropriate for the address family
    of the socket, specifying where to send the query.

    *expiration*, a ``float`` or ``None``, the absolute time at which
    a timeout exception should be raised.  If ``None``, no timeout will
    occur.  The expiration value is meaningless for the asyncio backend, as
    asyncio's transport sendto() never blocks.

    Returns an ``(int, float)`` tuple of bytes sent and the sent time.
    N)
isinstancednsmessageMessageto_wirer   sendtor   )r   r    r!   r   	sent_timenr   r   r   send_udpS   s
    r+   F    )r   r!   r   ignore_unexpectedone_rr_per_rrsetkeyringrequest_macignore_trailingraise_on_truncationignore_errorsqueryr"   c              
      s   d}|  dt|I dH \}}t| j|||s0qt }ztjj||||||d}W nj tjjk
r } z*|	r|
dk	r|
	| sW Y 
qn W 5 d}~X Y n  t
k
r   |	rY qn Y nX |	r|
dk	r|
	|sq|||fS )aj  Read a DNS message from a UDP socket.

    *sock*, a ``dns.asyncbackend.DatagramSocket``.

    See :py:func:`dns.query.receive_udp()` for the documentation of the other
    parameters, and exceptions.

    Returns a ``(dns.message.Message, float, tuple)`` tuple of the received message, the
    received time, and the address where the message arrived from.
    r,     N)r/   r0   r.   r1   r2   )recvfromr   r   familyr   r$   r%   	from_wire	Truncatedis_response	Exception)r   r!   r   r-   r.   r/   r0   r1   r2   r3   r4   wirefrom_addressreceived_timerer   r   r   receive_udpq   sF       

rA   5   )qwheretimeoutr   sourcesource_portr-   r.   r1   r2   r   backendr3   r"   c                    s  |   }t|\}}tj|}t||f|}|
r<t|
}nJ|sJtj }t	|||}|
 rh||f}nd}||tjd||I dH }|4 I dH t}t||||I dH  t|||||| j| j||	|| I dH \}}}|| |_|s| |st|W  5 Q I dH R  S Q I dH R X dS )aF  Return the response obtained after sending a query via UDP.

    *sock*, a ``dns.asyncbackend.DatagramSocket``, or ``None``,
    the socket to use for the query.  If ``None``, the default, a
    socket is created.  Note that if a socket is provided, the
    *source*, *source_port*, and *backend* are ignored.

    *backend*, a ``dns.asyncbackend.Backend``, or ``None``.  If ``None``,
    the default, then dnspython will use the default backend.

    See :py:func:`dns.query.udp()` for the documentation of the other
    parameters, exceptions, and return type of this method.
    Nr   )r'   r   r$   inetaf_for_address_lltupler   asyncbackendget_default_backendr   Zdatagram_connection_requiredmake_socketr   
SOCK_DGRAMr+   rA   r/   macr   r:   r   )rC   rD   rE   r   rF   rG   r-   r.   r1   r2   r   rH   r3   r<   
begin_timer   r   r!   cmstupledtuplesr?   r>   _r   r   r   udp   s@    



rW   )rC   rD   rE   r   rF   rG   r-   r.   r1   udp_socktcp_sockrH   r3   r"   c                    sv   z0t | ||||||||d|	||I dH }|dfW S  tjjk
rp   t| ||||||||
|
I dH }|df Y S X dS )a  Return the response to the query, trying UDP first and falling back
    to TCP if UDP results in a truncated response.

    *udp_sock*, a ``dns.asyncbackend.DatagramSocket``, or ``None``,
    the socket to use for the UDP query.  If ``None``, the default, a
    socket is created.  Note that if a socket is provided the *source*,
    *source_port*, and *backend* are ignored for the UDP query.

    *tcp_sock*, a ``dns.asyncbackend.StreamSocket``, or ``None``, the
    socket to use for the TCP query.  If ``None``, the default, a
    socket is created.  Note that if a socket is provided *where*,
    *source*, *source_port*, and *backend*  are ignored for the TCP query.

    *backend*, a ``dns.asyncbackend.Backend``, or ``None``.  If ``None``,
    the default, then dnspython will use the default backend.

    See :py:func:`dns.query.udp_with_fallback()` for the documentation
    of the other parameters, exceptions, and return type of this
    method.
    TNF)rW   r$   r%   r9   tcp)rC   rD   rE   r   rF   rG   r-   r.   r1   rX   rY   rH   r3   responser   r   r   udp_with_fallback   s>    #


r\   )r   r    r   r"   c                    s\   t |tjjr|jdd}nt|dd| }t }| |t	||I dH  t||fS )zSend a DNS message to the specified TCP socket.

    *sock*, a ``dns.asyncbackend.StreamSocket``.

    See :py:func:`dns.query.send_tcp()` for the documentation of the other
    parameters, exceptions, and return type of this method.
    T)Zprepend_length   ZbigN)
r#   r$   r%   r&   r'   lento_bytesr   sendallr   )r   r    r   tcpmsgr)   r   r   r   send_tcp4  s    rb   c                    sH   d}|dkrD|  |t|I dH }|dkr.t|t| }|| }q|S )z|Read the specified number of bytes from stream.  Keep trying until we
    either get the desired amount, or we hit EOF.
    r,   r   N)Zrecvr   EOFErrorr^   )r   countr   rU   r*   r   r   r   _read_exactlyM  s    
re   )r   r   r.   r/   r0   r1   r"   c                    sX   t | d|I dH }td|\}t | ||I dH }t }	tjj|||||d}
|
|	fS )zRead a DNS message from a TCP socket.

    *sock*, a ``dns.asyncbackend.StreamSocket``.

    See :py:func:`dns.query.receive_tcp()` for the documentation of the other
    parameters, exceptions, and return type of this method.
    r]   N!Hr/   r0   r.   r1   )re   structunpackr   r$   r%   r8   )r   r   r.   r/   r0   r1   ldatalr<   r>   r?   r   r   r   receive_tcp[  s    rl   )rC   rD   rE   r   rF   rG   r.   r1   r   rH   r"   c
                    s   |   }
t|\}}|r0| I dH  t|}nJtj|}t|||}||f}|	s^tj	 }	|	
|tjd|||I dH }|4 I dH b}t||
|I dH  t|||| j| j|I dH \}}|| |_| |st|W  5 Q I dH R  S Q I dH R X dS )aO  Return the response obtained after sending a query via TCP.

    *sock*, a ``dns.asyncbacket.StreamSocket``, or ``None``, the
    socket to use for the query.  If ``None``, the default, a socket
    is created.  Note that if a socket is provided
    *where*, *port*, *source*, *source_port*, and *backend* are ignored.

    *backend*, a ``dns.asyncbackend.Backend``, or ``None``.  If ``None``,
    the default, then dnspython will use the default backend.

    See :py:func:`dns.query.tcp()` for the documentation of the other
    parameters, exceptions, and return type of this method.
    Nr   )r'   r   Zgetpeernamer   r$   rI   rJ   r   rL   rM   rN   r   SOCK_STREAMrb   rl   r/   rP   r   r:   r   )rC   rD   rE   r   rF   rG   r.   r1   r   rH   r<   rQ   r   rR   r   rS   rT   rU   r?   r>   r   r   r   rZ   y  s@    

     
     

rZ   U  T)rC   rD   rE   r   rF   rG   r.   r1   r   rH   ssl_contextserver_hostnameverifyr"   c                    s   t |\}}|rt|}n`|
dkr,t||}
tj|}t|||}||f}|	sZtj }	|		|t
jd||||
|I dH }|4 I dH R}t|}t| |||||||||	
I dH }t }|| |_|W  5 Q I dH R  S Q I dH R X dS )a  Return the response obtained after sending a query via TLS.

    *sock*, an ``asyncbackend.StreamSocket``, or ``None``, the socket
    to use for the query.  If ``None``, the default, a socket is
    created.  Note that if a socket is provided, it must be a
    connected SSL stream socket, and *where*, *port*,
    *source*, *source_port*, *backend*, *ssl_context*, and *server_hostname*
    are ignored.

    *backend*, a ``dns.asyncbackend.Backend``, or ``None``.  If ``None``,
    the default, then dnspython will use the default backend.

    See :py:func:`dns.query.tls()` for the documentation of the other
    parameters, exceptions, and return type of this method.
    Nr   )r   r   r   r$   rI   rJ   r   rL   rM   rN   r   rm   r   rZ   r   )rC   rD   rE   r   rF   rG   r.   r1   r   rH   ro   rp   rq   rQ   r   rR   r   rS   rT   rU   r[   Zend_timer   r   r   tls  sJ    






rr   i  z
/dns-queryzhttpx.AsyncClientzdns.asyncresolver.Resolver)rC   rD   rE   r   rF   rG   r.   r1   clientpathpostrq   bootstrap_addressresolverr7   r"   c              
      s
  t st|r t|tjs td|  }ztj	|}W n tk
rP   d}Y nX d}ddi}|dk	rtj
|r|tjkrd|||	}q|tjkrd|||	}n|}tj }|dkrd}d}n|}|}| |dd|||||d	}|rt|}ntjdd||d
}|4 I dH ~}|
rV|dtt|d ||j|||d|I dH }n:t|d}| }||j||d|id|I dH }W 5 Q I dH R X |jdk s|jdkrtd||j|jtjj |j| j!| j"||d}|j#$ |_%| &|st'|S )a  Return the response obtained after sending a query via DNS-over-HTTPS.

    *client*, a ``httpx.AsyncClient``.  If provided, the client to use for
    the query.

    Unlike the other dnspython async functions, a backend cannot be provided
    in this function because httpx always auto-detects the async backend.

    See :py:func:`dns.query.https()` for the documentation of the other
    parameters, exceptions, and return type of this method.
    z.session parameter must be an httpx.AsyncClientNZacceptzapplication/dns-messagezhttps://{}:{}{}zhttps://[{}]:{}{}r   T)local_addresshttp1http2rq   
local_portrv   rw   r7   )ry   rz   rq   	transport)zcontent-typezcontent-length)headerscontent   =r$   )r}   params   i+  z4{} responded with status code {}
Response body: {!r}rg   )(r   r	   r#   httpxZAsyncClient
ValueErrorr'   r$   rI   rJ   Z
is_addressr   r   formatr   rL   rM   Zget_transport_classr   updatestrr^   wait_forru   base64Zurlsafe_b64encoderstripdecodegetZstatus_coder~   r%   r8   r/   r0   elapsedZtotal_secondsr   r:   r   )rC   rD   rE   r   rF   rG   r.   r1   rs   rt   ru   rq   rv   rw   r7   r<   r   r|   r}   ZurlrH   rx   r{   rR   Z
the_clientr[   Ztwirer?   r   r   r   https  s    




   
    r   )rD   txn_managerr4   r   rE   lifetimerF   rG   udp_moderH   r"   c
           #         s  |dkrt j|\}}
nt j|}
|jd j}|t jjk}| }|	 }t j
| }t|||}| |f}t|\}}d}|rd}|r|tjkrtj}d}n
tj}d}|	st j }	|	||d||t|I dH }|4 I dH  |r|||t|I dH  n&tdt|| }|||I dH  t j|||
|p}d}d}|st|\}}|dks||dk	r||kr|}|rt| |f|}t|}|d|I dH \}}t|||drqqn2t |d|I dH } t!d| \}!t ||!|I dH }|t jjk}t j"j#||j$|j%d||| |d}"z|&|"}W nF t jj'k
r   |sZt(|tj)krh d}d}tj}Y qLY nX |"j*}qL|s|j$r|"j+st j,-d	W 5 Q R X W 5 Q I dH R X q~dS )
am  Conduct an inbound transfer and apply it via a transaction from the
    txn_manager.

    *backend*, a ``dns.asyncbackend.Backend``, or ``None``.  If ``None``,
    the default, then dnspython will use the default backend.

    See :py:func:`dns.query.inbound_xfr()` for the documentation of
    the other parameters, exceptions, and return type of this method.
    Nr   TFrf   r5   r]   )r/   r0   xfrorigintsig_ctxZmultir.   zmissing TSIG).r$   r   Z
make_queryZextract_serial_from_queryZquestionrdtypeZ	rdatatypeZIXFRZfrom_wire_originr'   rI   rJ   r   r   r   NEVERr   rO   rm   rL   rM   rN   r   r(   rh   packr^   r`   ZInboundrK   r6   r   re   ri   r%   r8   r/   rP   Zprocess_messageZUseTCPAssertionErrorZONLYr   Zhad_tsigZ	exceptionZ	FormError)#rD   r   r4   r   rE   r   rF   rG   r   rH   serialr   Zis_ixfrr   r<   r   rS   rT   rV   r   ZretryZ	sock_typeZis_udprU   ra   ZinboundZdoner   Zmexpirationr!   Zrwirer=   rj   rk   r?   r   r   r   inbound_xfrl  s    
     

   



r   )rC   rD   rE   r   rF   rG   r.   r1   
connectionrq   rH   rp   r"   c                    sJ  t jjstdd| _|  }|r8t jj}t jj}|}nt j|
\}}| 4 I dH }|||	|d4 I dH }|s|||||}t	|\}}|
|I dH }|4 I dH , ||dI dH  |t|I dH }W 5 Q I dH R X t }W 5 Q I dH R X t jj|| j| j||d}W 5 Q I dH R X t|| d|_| |sFt|S )ai  Return the response obtained after sending an asynchronous query via
    DNS-over-QUIC.

    *backend*, a ``dns.asyncbackend.Backend``, or ``None``.  If ``None``,
    the default, then dnspython will use the default backend.

    See :py:func:`dns.query.quic()` for the documentation of the other
    parameters, exceptions, and return type of this method.
    zDNS-over-QUIC is not available.r   N)Zverify_modeZserver_nameTrg   g        )r$   quicZ	have_quicr
   idr'   Znull_factoryZfactories_for_backendZconnectr   Zmake_streamsendZreceiver   r   r%   r8   r/   r0   r   r:   r   )rC   rD   rE   r   rF   rG   r.   r1   r   rq   rH   rp   r<   ZcfactoryZmfactoryZthe_connectioncontextZthe_managerstartr   streamZfinishr?   r   r   r   r     sF      $r   )N)N)
NNFFNr,   FFFN)NrB   Nr   FFFFNNF)NrB   Nr   FFFNNNF)N)NFNr,   F)NrB   Nr   FFNN)Nrn   Nr   FFNNNNT)
Nrn   Nr   FFNTNN)K__doc__r   
contextlibr   rh   r   typingr   r   r   r   r   Zdns.asyncbackendr$   Zdns.exceptionZdns.inetZdns.messageZdns.nameZdns.quicZ	dns.rcodeZdns.rdataclassZdns.rdatatypeZdns.transactionZdns._asyncbackendr   Z	dns.queryr   r	   r
   r   r   r   r   r   r   r   r   rI   Zlow_level_address_tuplerK   r   r   rL   ZDatagramSocketr%   r&   bytesfloatintr+   boolnameNameZtsigZKeyrA   r   ZBackendrW   ZStreamSocketr\   rb   re   rl   rZ   Z
SSLContextrr   Z	AF_UNSPECr   r   ZtransactionZTransactionManagerr   r   ZAsyncQuicConnectionr   r   r   r   <module>   s   0
 
           
@           

E           


G 
     !        

;           


I
x

h          


