o
    ¯bÉ$  ã                   @   sÀ   d Z ddlmZ ddlmZ ddlmZmZ ddlmZ G dd„ dƒZ	G dd	„ d	eƒZ
ee
ƒG d
d„ dƒƒZG dd„ deƒZG dd„ deƒZG dd„ dejƒZG dd„ deƒZG dd„ dƒZdS )a¼  
Hierarchical Token Bucket traffic shaping.

Patterned after U{Martin Devera's Hierarchical Token Bucket traffic
shaper for the Linux kernel<http://luxik.cdi.cz/~devik/qos/htb/>}.

@seealso: U{HTB Linux queuing discipline manual - user guide
  <http://luxik.cdi.cz/~devik/qos/htb/manual/userg.htm>}
@seealso: U{Token Bucket Filter in Linux Advanced Routing & Traffic Control
    HOWTO<http://lartc.org/howto/lartc.qdisc.classless.html#AEN682>}
é    )Útime)ÚOptional)Ú	InterfaceÚimplementer)Úpcpc                   @   sP   e Zd ZU dZdZee ed< dZee ed< dZ	ddd„Z
dd	„ Zd
d„ ZdS )ÚBucketaë  
    Implementation of a Token bucket.

    A bucket can hold a certain number of tokens and it drains over time.

    @cvar maxburst: The maximum number of tokens that the bucket can
        hold at any given time. If this is L{None}, the bucket has
        an infinite size.
    @type maxburst: C{int}
    @cvar rate: The rate at which the bucket drains, in number
        of tokens per second. If the rate is L{None}, the bucket
        drains instantaneously.
    @type rate: C{int}
    NÚmaxburstÚrater   c                 C   s   d| _ || _tƒ | _dS )a(  
        Create a L{Bucket} that may have a parent L{Bucket}.

        @param parentBucket: If a parent Bucket is specified,
            all L{add} and L{drip} operations on this L{Bucket}
            will be applied on the parent L{Bucket} as well.
        @type parentBucket: L{Bucket}
        r   N)ÚcontentÚparentBucketr   ÚlastDrip)Úselfr   © r   ú7/usr/lib/python3/dist-packages/twisted/protocols/htb.pyÚ__init__3   s   	zBucket.__init__c                 C   sR   |   ¡  | jdu r|}n	t|| j| j ƒ}| jdur | j |¡}|  j|7  _|S )at  
        Adds tokens to the L{Bucket} and its C{parentBucket}.

        This will add as many of the C{amount} tokens as will fit into both
        this L{Bucket} and its C{parentBucket}.

        @param amount: The number of tokens to try to add.
        @type amount: C{int}

        @returns: The number of tokens that actually fit.
        @returntype: C{int}
        N)Údripr   Úminr
   r   Úadd)r   ÚamountÚ	allowabler   r   r   r   @   s   

z
Bucket.addc                 C   sb   | j dur
| j  ¡  | jdu rd| _ntƒ }|| j }|| j }td| j| ƒ| _|| _| jdkS )zê
        Let some of the bucket drain.

        The L{Bucket} drains at the rate specified by the class
        variable C{rate}.

        @returns: C{True} if the bucket is empty after this drip.
        @returntype: C{bool}
        Nr   )r   r   r	   r
   r   r   Úmax)r   ÚnowÚ	deltaTimeÚdeltaTokensr   r   r   r   X   s   






zBucket.drip©N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   ÚintÚ__annotations__r	   Ú	_refcountr   r   r   r   r   r   r   r      s   
 
r   c                   @   s   e Zd Zdd„ ZdS )ÚIBucketFilterc                  O   ó   dS )zn
        Return a L{Bucket} corresponding to the provided parameters.

        @returntype: L{Bucket}
        Nr   )Ú
somethingsÚsome_kwr   r   r   ÚgetBucketForq   s    zIBucketFilter.getBucketForN)r   r   r   r&   r   r   r   r   r"   p   s    r"   c                   @   sH   e Zd ZU dZeZdZee e	d< ddd„Z
dd„ Zdd	„ Zd
d„ ZdS )ÚHierarchicalBucketFilterz÷
    Filter things into buckets that can be nested.

    @cvar bucketFactory: Class of buckets to make.
    @type bucketFactory: L{Bucket}
    @cvar sweepInterval: Seconds between sweeping out the bucket cache.
    @type sweepInterval: C{int}
    NÚsweepIntervalc                 C   s   i | _ || _tƒ | _d S r   )ÚbucketsÚparentFilterr   Ú	lastSweep)r   r*   r   r   r   r   ‡   s   z!HierarchicalBucketFilter.__init__c                 O   s†   | j durtƒ | j | j kr|  ¡  | jr#| jj| g|¢R i |¤Ž}nd}| j|i |¤Ž}| j |¡}|du rA|  	|¡}|| j|< |S )zã
        Find or create a L{Bucket} corresponding to the provided parameters.

        Any parameters are passed on to L{getBucketKey}, from them it
        decides which bucket you get.

        @returntype: L{Bucket}
        N)
r(   r   r+   Úsweepr*   r&   ÚgetBucketKeyr)   ÚgetÚbucketFactory)r   ÚaÚkwr   ÚkeyÚbucketr   r   r   r&   Œ   s   
	

z%HierarchicalBucketFilter.getBucketForc                 O   r#   )a%  
        Construct a key based on the input parameters to choose a L{Bucket}.

        The default implementation returns the same key for all
        arguments. Override this method to provide L{Bucket} selection.

        @returns: Something to be used as a key in the bucket cache.
        Nr   )r   r0   r1   r   r   r   r-   ¦   s   	z%HierarchicalBucketFilter.getBucketKeyc                 C   s>   | j  ¡ D ]\}}| ¡ }|jdkr|r| j |= qtƒ | _dS )z'
        Remove empty buckets.
        r   N)r)   Úitemsr   r!   r   r+   )r   r2   r3   Úbucket_is_emptyr   r   r   r,   ±   s   €zHierarchicalBucketFilter.sweepr   )r   r   r   r   r   r/   r(   r   r   r    r   r&   r-   r,   r   r   r   r   r'   y   s   
 	
r'   c                   @   ó   e Zd ZdZdZdd„ ZdS )ÚFilterByHostzF
    A Hierarchical Bucket filter with a L{Bucket} for each host.
    i°  c                 C   ó   |  ¡ d S ©Né   )ÚgetPeer©r   Ú	transportr   r   r   r-   Ä   ó   zFilterByHost.getBucketKeyN©r   r   r   r   r(   r-   r   r   r   r   r7   ½   ó    r7   c                   @   s   e Zd ZdZdZdd„ ZdS )ÚFilterByServerzI
    A Hierarchical Bucket filter with a L{Bucket} for each service.
    Nc                 C   r8   )Né   )ÚgetHostr<   r   r   r   r-   Ï   r>   zFilterByServer.getBucketKeyr?   r   r   r   r   rA   È   r@   rA   c                   @   s,   e Zd ZdZdZdd„ Zdd„ Zdd„ Zd	S )
ÚShapedConsumerzL
    Wraps a C{Consumer} and shapes the rate at which it receives data.
    Fc                 C   s(   t j | |¡ || _| j jd7  _d S r9   )r   ÚProducerConsumerProxyr   r3   r!   )r   Úconsumerr3   r   r   r   r   Ü   s   zShapedConsumer.__init__c                 C   s&   | j  t|ƒ¡}tj | |d |… ¡S r   )r3   r   Úlenr   rE   Ú_writeSomeData)r   Údatar   r   r   r   rH   á   s   zShapedConsumer._writeSomeDatac                 C   s    t j | ¡ | j jd8  _d S r9   )r   rE   ÚstopProducingr3   r!   )r   r   r   r   rJ   é   s   zShapedConsumer.stopProducingN)r   r   r   r   ÚiAmStreamingr   rH   rJ   r   r   r   r   rD   Ó   s    rD   c                   @   r6   )ÚShapedTransportaR  
    Wraps a C{Transport} and shapes the rate at which it receives data.

    This is a L{ShapedConsumer} with a little bit of magic to provide for
    the case where the consumer it wraps is also a C{Transport} and people
    will be attempting to access attributes this does not proxy as a
    C{Consumer} (e.g. C{loseConnection}).
    Fc                 C   s   t | j|ƒS r   )ÚgetattrrF   )r   Únamer   r   r   Ú__getattr__ü   s   zShapedTransport.__getattr__N)r   r   r   r   rK   rO   r   r   r   r   rL   î   s    rL   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚShapedProtocolFactorya�  
    Dispense C{Protocols} with traffic shaping on their transports.

    Usage::

        myserver = SomeFactory()
        myserver.protocol = ShapedProtocolFactory(myserver.protocol,
                                                  bucketFilter)

    Where C{SomeServerFactory} is a L{twisted.internet.protocol.Factory}, and
    C{bucketFilter} is an instance of L{HierarchicalBucketFilter}.
    c                 C   s   || _ || _dS )aœ  
        Tell me what to wrap and where to get buckets.

        @param protoClass: The class of C{Protocol} this will generate
          wrapped instances of.
        @type protoClass: L{Protocol<twisted.internet.interfaces.IProtocol>}
          class
        @param bucketFilter: The filter which will determine how
          traffic is shaped.
        @type bucketFilter: L{HierarchicalBucketFilter}.
        N)ÚprotocolÚbucketFilter)r   Ú
protoClassrR   r   r   r   r     s   
zShapedProtocolFactory.__init__c                    s.   ˆj |i |¤Ž}|j‰ ‡ ‡fdd„}||_|S )zÔ
        Make a C{Protocol} instance with a shaped transport.

        Any parameters will be passed on to the protocol's initializer.

        @returns: A C{Protocol} instance with a L{ShapedTransport}.
        c                    s   ˆj  | ¡}t| |ƒ}ˆ |ƒS r   )rR   r&   rL   )r=   r3   ÚshapedTransport©ÚorigMakeConnectionr   r   r   ÚmakeConnection,  s   
z6ShapedProtocolFactory.__call__.<locals>.makeConnection)rQ   rW   )r   r0   r1   ÚprotorW   r   rU   r   Ú__call__!  s
   zShapedProtocolFactory.__call__N)r   r   r   r   r   rY   r   r   r   r   rP     s    rP   N)r   r   Útypingr   Úzope.interfacer   r   Útwisted.protocolsr   r   r"   r'   r7   rA   rE   rD   rL   rP   r   r   r   r   Ú<module>   s   R	C