a
    sd_BJ                  
   @   s   d Z ddlZddlZddlZddlZddlZddlZddlZddl	Zddl
ZddlZddlZddlmZmZmZmZ ejjZdd ZdddZddd	Zd ddZd!ddZd"ddZd#ddZdd Zd$ddZd%ddZd&ddZdS )'zTalk to a DNS server.    N)_compute_times_matches_destinationBadResponsesslc                 C   sN   |s|rF|d u 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 )socketZAF_INETZAF_INET6NotImplementedError)afZaddressport r
   0/usr/lib/python3/dist-packages/dns/asyncquery.py_source_tuple(   s    

r   c                 C   s&   | r|st   }t| | dS d S d S )Nr   )timemax)
expirationZnowr
   r
   r   _timeout8   s
    r   c                    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.

    Returns an ``(int, float)`` tuple of bytes sent and the sent time.
    N)
isinstancednsmessageMessageto_wirer   Zsendtor   )sockwhatdestinationr   	sent_timenr
   r
   r   send_udpA   s
    r   F    c	                    s\   d}	|  dt|I dH \}	}
t| j|
||rq2qt }tjj|	|||||d}|||
fS )a  Read a DNS message from a UDP socket.

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

    *destination*, a destination tuple appropriate for the address family
    of the socket, specifying where the message is expected to arrive from.
    When receiving a response, this would be where the associated query was
    sent.

    *expiration*, a ``float`` or ``None``, the absolute time at which
    a timeout exception should be raised.  If ``None``, no timeout will
    occur.

    *ignore_unexpected*, a ``bool``.  If ``True``, ignore responses from
    unexpected sources.

    *one_rr_per_rrset*, a ``bool``.  If ``True``, put each RR into its own
    RRset.

    *keyring*, a ``dict``, the keyring to use for TSIG.

    *request_mac*, a ``bytes``, the MAC of the request (for TSIG).

    *ignore_trailing*, a ``bool``.  If ``True``, ignore trailing
    junk at end of the received message.

    *raise_on_truncation*, a ``bool``.  If ``True``, raise an exception if
    the TC bit is set.

    Raises if the message is malformed, if network errors occur, of if
    there is a timeout.

    Returns a ``(dns.message.Message, float, tuple)`` tuple of the received
    message, the received time, and the address where the message arrived from.
    r   i  N)keyringrequest_macone_rr_per_rrsetignore_trailingraise_on_truncation)Zrecvfromr   r   Zfamilyr   r   r   	from_wire)r   r   r   ignore_unexpectedr   r   r   r    r!   wireZfrom_addressreceived_timerr
   r
   r   receive_udpY   s    (
r'   5   c              
      s  |   }t|\}}d}ztj|}t||f|}|
r>|
}n2|sLtj }t|||}|	|t
jd|I dH }t||||I dH  t|||||| j| j||		I dH \}}}|| |_| |st|W |
s|r| I dH  S n|
 s| r| I dH  0 dS )a  Return the response obtained after sending a query via UDP.

    *q*, a ``dns.message.Message``, the query to send

    *where*, a ``str`` containing an IPv4 or IPv6 address,  where
    to send the message.

    *timeout*, a ``float`` or ``None``, the number of seconds to wait before the
    query times out.  If ``None``, the default, wait forever.

    *port*, an ``int``, the port send the message to.  The default is 53.

    *source*, a ``str`` containing an IPv4 or IPv6 address, specifying
    the source address.  The default is the wildcard address.

    *source_port*, an ``int``, the port from which to send the message.
    The default is 0.

    *ignore_unexpected*, a ``bool``.  If ``True``, ignore responses from
    unexpected sources.

    *one_rr_per_rrset*, a ``bool``.  If ``True``, put each RR into its own
    RRset.

    *ignore_trailing*, a ``bool``.  If ``True``, ignore trailing
    junk at end of the received message.

    *raise_on_truncation*, a ``bool``.  If ``True``, raise an exception if
    the TC bit is set.

    *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.

    Returns a ``dns.message.Message``.
    Nr   )r   r   r   inetaf_for_address_lltupleasyncbackendget_default_backendr   make_socketr   Z
SOCK_DGRAMr   r'   r   macr   is_responser   close)qwheretimeoutr	   sourcesource_portr#   r   r    r!   r   backendr$   
begin_timer   sr   r   stupler&   r%   _r
   r
   r   udp   s>    ,


 r<   c                    sr   z.t | ||||||||d|	|I dH }|dfW S  tjjyl   t| ||||||||
|
I dH }|df Y S 0 dS )a  Return the response to the query, trying UDP first and falling back
    to TCP if UDP results in a truncated response.

    *q*, a ``dns.message.Message``, the query to send

    *where*, a ``str`` containing an IPv4 or IPv6 address,  where
    to send the message.

    *timeout*, a ``float`` or ``None``, the number of seconds to wait before the
    query times out.  If ``None``, the default, wait forever.

    *port*, an ``int``, the port send the message to.  The default is 53.

    *source*, a ``str`` containing an IPv4 or IPv6 address, specifying
    the source address.  The default is the wildcard address.

    *source_port*, an ``int``, the port from which to send the message.
    The default is 0.

    *ignore_unexpected*, a ``bool``.  If ``True``, ignore responses from
    unexpected sources.

    *one_rr_per_rrset*, a ``bool``.  If ``True``, put each RR into its own
    RRset.

    *ignore_trailing*, a ``bool``.  If ``True``, ignore trailing
    junk at end of the received message.

    *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.

    Returns a (``dns.message.Message``, tcp) tuple where tcp is ``True``
    if and only if TCP was used.
    TNF)r<   r   r   Z	Truncatedtcp)r2   r3   r4   r	   r5   r6   r#   r   r    Zudp_sockZtcp_sockr7   responser
   r
   r   udp_with_fallback   s    0


r?   c                    sT   t |tjjr| }t|}td|| }t }| 	||I dH  t||fS )a{  Send a DNS message to the specified TCP socket.

    *sock*, a ``socket``.

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

    *expiration*, a ``float`` or ``None``, the absolute time at which
    a timeout exception should be raised.  If ``None``, no timeout will
    occur.

    Returns an ``(int, float)`` tuple of bytes sent and the sent time.
    !HN)
r   r   r   r   r   lenstructZpackr   Zsendall)r   r   r   lZtcpmsgr   r
   r
   r   send_tcp  s    rD   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   EOFErrorrA   )r   countr   r9   r   r
   r
   r   _read_exactly-  s    
rG   c                    sX   t | d|I dH }td|\}t | ||I dH }t }	tjj|||||d}
|
|	fS )a  Read a DNS message from a TCP socket.

    *sock*, a ``socket``.

    *expiration*, a ``float`` or ``None``, the absolute time at which
    a timeout exception should be raised.  If ``None``, no timeout will
    occur.

    *one_rr_per_rrset*, a ``bool``.  If ``True``, put each RR into its own
    RRset.

    *keyring*, a ``dict``, the keyring to use for TSIG.

    *request_mac*, a ``bytes``, the MAC of the request (for TSIG).

    *ignore_trailing*, a ``bool``.  If ``True``, ignore trailing
    junk at end of the received message.

    Raises if the message is malformed, if network errors occur, of if
    there is a timeout.

    Returns a ``(dns.message.Message, float)`` tuple of the received message
    and the received time.
       Nr@   )r   r   r   r    )rG   rB   Zunpackr   r   r   r"   )r   r   r   r   r   r    ZldatarC   r$   r%   r&   r
   r
   r   receive_tcp;  s    rI   c
                    s  |   }
t|\}}d}z|r2| I dH  |}nJtj|}t|||}||f}|	s`tj }	|		|t
jd|||I dH }t||
|I dH  t|||| j| j|I dH \}}|| |_| |st|W |s|r| I dH  S n| s| r| I dH  0 dS )a  Return the response obtained after sending a query via TCP.

    *q*, a ``dns.message.Message``, the query to send

    *where*, a ``str`` containing an IPv4 or IPv6 address, where
    to send the message.

    *timeout*, a ``float`` or ``None``, the number of seconds to wait before the
    query times out.  If ``None``, the default, wait forever.

    *port*, an ``int``, the port send the message to.  The default is 53.

    *source*, a ``str`` containing an IPv4 or IPv6 address, specifying
    the source address.  The default is the wildcard address.

    *source_port*, an ``int``, the port from which to send the message.
    The default is 0.

    *one_rr_per_rrset*, a ``bool``.  If ``True``, put each RR into its own
    RRset.

    *ignore_trailing*, a ``bool``.  If ``True``, ignore trailing
    junk at end of the received message.

    *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.

    Returns a ``dns.message.Message``.
    Nr   )r   r   Zgetpeernamer   r)   r*   r   r,   r-   r.   r   SOCK_STREAMrD   rI   r   r/   r   r0   r   r1   )r2   r3   r4   r	   r5   r6   r   r    r   r7   r$   r8   r   r9   r   r:   dtupler&   r%   r
   r
   r   r=   `  s>    &



 r=   U  c                    s  t |\}}|s|
du r0t }
|du r8d|
_nd}
d}tj|}t|||}||f}|	sftj	 }	|	
|tjd||||
|I dH }n|}zXt|}t| |||||||||	
I dH }t }|| |_|W |s|r| I dH  S n|s |r | I dH  0 dS )a  Return the response obtained after sending a query via TLS.

    *q*, a ``dns.message.Message``, the query to send

    *where*, a ``str`` containing an IPv4 or IPv6 address,  where
    to send the message.

    *timeout*, a ``float`` or ``None``, the number of seconds to wait before the
    query times out.  If ``None``, the default, wait forever.

    *port*, an ``int``, the port send the message to.  The default is 853.

    *source*, a ``str`` containing an IPv4 or IPv6 address, specifying
    the source address.  The default is the wildcard address.

    *source_port*, an ``int``, the port from which to send the message.
    The default is 0.

    *one_rr_per_rrset*, a ``bool``.  If ``True``, put each RR into its own
    RRset.

    *ignore_trailing*, a ``bool``.  If ``True``, ignore trailing
    junk at end of the received message.

    *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.

    *ssl_context*, an ``ssl.SSLContext``, the context to use when establishing
    a TLS connection. If ``None``, the default, creates one with the default
    configuration.

    *server_hostname*, a ``str`` containing the server's hostname.  The
    default is ``None``, which means that no hostname is known, and if an
    SSL context is created, hostname checking will be disabled.

    Returns a ``dns.message.Message``.
    NFr   )r   r   Zcreate_default_contextZcheck_hostnamer   r)   r*   r   r,   r-   r.   r   rJ   r   r=   r   r1   )r2   r3   r4   r	   r5   r6   r   r    r   r7   Zssl_contextZserver_hostnamer8   r   r   r:   rK   r9   r>   Zend_timer
   r
   r   tls  sB    0


 rM   )N)N)NNFFNr   FF)
Nr(   Nr   FFFFNN)
Nr(   Nr   FFFNNN)N)NFNr   F)Nr(   Nr   FFNN)
NrL   Nr   FFNNNN) __doc__r   rB   r   Zdns.asyncbackendr   Zdns.exceptionZdns.inetZdns.nameZdns.messageZ	dns.rcodeZdns.rdataclassZdns.rdatatypeZ	dns.queryr   r   r   r   r)   Zlow_level_address_tupler+   r   r   r   r'   r<   r?   rD   rG   rI   r=   rM   r
   r
   r
   r   <module>   sX   
	
    
5    
I    
<
  
%   
H   