U
    ª€ljæ  ã                   @   sŠ   d dgZ ddlmZ ddlmZmZ ddlmZmZm	Z	m
Z
 ddlmZ ddlmZmZ ddlmZ G d	d„ dejƒZG d
d „ d eƒZdS )ÚSecondaryAuthorityÚSecondaryAuthorityServiceé    )Úservice)ÚdeferÚtask)ÚclientÚcommonÚdnsÚresolve)ÚFileAuthority)ÚfailureÚlog)ÚnativeStringc                   @   sD   e Zd ZdZdZdZdd„ Zedd„ ƒZdd	„ Z	d
d„ Z
dd„ ZdS )r   a:  
    A service that keeps one or more authorities up to date by doing hourly
    zone transfers from a master.

    @ivar primary: IP address of the master.
    @type primary: L{str}

    @ivar domains: An authority for each domain mirrored from the master.
    @type domains: L{list} of L{SecondaryAuthority}
    Né5   c                    s"   t ˆ ƒ| _‡ fdd„|D ƒ| _dS )a  
        @param primary: The IP address of the server from which to perform
        zone transfers.
        @type primary: L{str}

        @param domains: A sequence of domain names for which to perform
        zone transfers.
        @type domains: L{list} of L{bytes}
        c                    s   g | ]}t ˆ |ƒ‘qS © )r   ©Ú.0Úd©Úprimaryr   ú;/tmp/pip-unpacked-wheel-aghyhbke/twisted/names/secondary.pyÚ
<listcomp>+   s     z6SecondaryAuthorityService.__init__.<locals>.<listcomp>N)r   r   Údomains)Úselfr   r   r   r   r   Ú__init__    s    

z"SecondaryAuthorityService.__init__c                    s0   ˆ \}}| |g ƒ}||_ ‡ fdd„|D ƒ|_|S )aˆ  
        Construct a new L{SecondaryAuthorityService} from a tuple giving a
        server address and a C{str} giving the name of a domain for which this
        is an authority.

        @param serverAddress: A two-tuple, the first element of which is a
            C{str} giving an IP address and the second element of which is a
            C{int} giving a port number.  Together, these define where zone
            transfers will be attempted from.

        @param domains: Domain names for which to perform zone transfers.
        @type domains: sequence of L{bytes}

        @return: A new instance of L{SecondaryAuthorityService}.
        c                    s   g | ]}t  ˆ |¡‘qS r   )r   ÚfromServerAddressAndDomainr   ©ÚserverAddressr   r   r   A   s   ÿzISecondaryAuthorityService.fromServerAddressAndDomains.<locals>.<listcomp>)Ú_portr   )Úclsr   r   r   Úportr   r   r   r   ÚfromServerAddressAndDomains-   s    

þz5SecondaryAuthorityService.fromServerAddressAndDomainsc                 C   s   t  | j¡S )z_
        Get a resolver for the transferred domains.

        @rtype: L{ResolverChain}
        )r
   ZResolverChainr   ©r   r   r   r   ÚgetAuthorityG   s    z&SecondaryAuthorityService.getAuthorityc                 C   sV   t j | ¡ dd„ | jD ƒ| _d}ddlm} | jD ]}| ||jd¡ |d7 }q4d S )Nc                 S   s   g | ]}t  |j¡‘qS r   )r   ZLoopingCallÚtransferr   r   r   r   r   Q   s     z:SecondaryAuthorityService.startService.<locals>.<listcomp>r   ©Úreactori  é   )	r   ÚServiceÚstartServicer   ÚcallsÚtwisted.internetr&   Z	callLaterÚstart)r   Úir&   Úcr   r   r   r)   O   s    
z&SecondaryAuthorityService.startServicec                 C   s$   t j | ¡ | jD ]}| ¡  qd S ©N)r   r(   ÚstopServicer*   Ústop)r   r.   r   r   r   r0   Z   s    
z%SecondaryAuthorityService.stopService)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r*   r   r   Úclassmethodr!   r#   r)   r0   r   r   r   r   r      s   
c                   @   sr   e Zd ZdZdZd ZZdZdZdd„ Z	e
dd„ ƒZd	d
„ Zddd„Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ ZdS )r   a  
    An Authority that keeps itself updated by performing zone transfers.

    @ivar primary: The IP address of the server from which zone transfers will
    be attempted.
    @type primary: L{str}

    @ivar _port: The port number of the server from which zone transfers will
    be attempted.
    @type _port: L{int}

    @ivar domain: The domain for which this is the secondary authority.
    @type domain: L{bytes}

    @ivar _reactor: The reactor to use to perform the zone transfers, or
    L{None} to use the global reactor.
    FNr   c                 C   s&   t j | ¡ t|ƒ| _t |¡| _dS )z�
        @param domain: The domain for which this will be the secondary
            authority.
        @type domain: L{bytes} or L{str}
        N)r   ZResolverBaser   r   r   r	   ZdomainStringÚdomain)r   Z	primaryIPr7   r   r   r   r   x   s    	
zSecondaryAuthority.__init__c                 C   s   |\}}| ||ƒ}||_ |S )af  
        Construct a new L{SecondaryAuthority} from a tuple giving a server
        address and a C{bytes} giving the name of a domain for which this is an
        authority.

        @param serverAddress: A two-tuple, the first element of which is a
            C{str} giving an IP address and the second element of which is a
            C{int} giving a port number.  Together, these define where zone
            transfers will be attempted from.

        @param domain: A C{bytes} giving the domain to transfer.
        @type domain: L{bytes}

        @return: A new instance of L{SecondaryAuthority}.
        )r   )r   r   r7   r   r    Z	secondaryr   r   r   r   …   s    
z-SecondaryAuthority.fromServerAddressAndDomainc                 C   s^   | j r
dS d| _| j}|dkr*ddlm} tj| j| jfg|d�}| 	| j
¡ | j¡ | j¡S )z›
        Attempt a zone transfer.

        @returns: A L{Deferred} that fires with L{None} when attempted zone
            transfer has completed.
        NTr   r%   )Zserversr&   )ÚtransferringZtransferingÚ_reactorr+   r&   r   ÚResolverr   r   Z
lookupZoner7   ZaddCallbackÚ_cbZoneZ
addErrbackÚ_ebZone)r   r&   Úresolverr   r   r   r$   ›   s     	 ÿÿþÿzSecondaryAuthority.transferc                 C   s4   | j r| js"t t t |¡¡¡S t 	| ||||¡S r/   )
ÚsoaÚrecordsr   Zfailr   ZFailurer	   ZDomainErrorr   Ú_lookup)r   Únamer   ÚtypeÚtimeoutr   r   r   r@   µ   s    zSecondaryAuthority._lookupc                 C   sf   |\}}}i  | _ }|D ]H}| jsD|jtjkrD|jj ¡ |jf| _q| |jj ¡ g ¡ 	|j¡ qd S r/   )
r?   r>   rB   r	   ZSOArA   ÚlowerÚpayloadÚ
setdefaultÚappend)r   ÚzoneZansÚ_ÚrZrecr   r   r   r;   ¼   s    

zSecondaryAuthority._cbZonec                 C   s$   t  d| j| jf ¡ t  |¡ d S )Nz/Updating %s from %s failed during zone transfer)r   Úmsgr7   r   Úerr©r   r   r   r   r   r<   Å   s    
ÿÿzSecondaryAuthority._ebZonec                 C   s   |   ¡  | j| j¡ d S r/   )r$   ZaddCallbacksÚ_cbTransferredÚ_ebTransferredr"   r   r   r   ÚupdateÌ   s    zSecondaryAuthority.updatec                 C   s
   d| _ d S )NF)r8   )r   Úresultr   r   r   rN   Ï   s    z!SecondaryAuthority._cbTransferredc                 C   s*   d| _ t d| j| jf ¡ t |¡ d S )NFz2Transferring %s from %s failed after zone transfer)Ztransferredr   rK   r7   r   rL   rM   r   r   r   rO   Ò   s    
ÿÿz!SecondaryAuthority._ebTransferred)N)r2   r3   r4   r5   r8   r>   r?   r   r9   r   r6   r   r$   r@   r;   r<   rP   rN   rO   r   r   r   r   r   `   s   

	N)Ú__all__Ztwisted.applicationr   r+   r   r   Ztwisted.namesr   r   r	   r
   Ztwisted.names.authorityr   Ztwisted.pythonr   r   Ztwisted.python.compatr   r(   r   r   r   r   r   r   Ú<module>   s   P