U
    
W[.0                     @   s6  d Z ddlmZmZ ddlZddl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 dd	lmZ G d
d deZdd Zdd ZedZedZedZedZedZedZedZedZ edZ!dd Z"da#e"d dZ$G dd de	j%ej&Z'e' Z(e()  e(*d dd  Z+d!d" Z,dS )#z
Banana -- s-exp based protocol.

Future Plans: This module is almost entirely stable.  The same caveat applies
to it as applies to L{twisted.spread.jelly}, however.  Read its future plans
for more details.

@author: Glyph Lefkowitz
    )absolute_importdivisionN)BytesIO)protocol)styles)log)	iterbyteslong	_bytesChr)fullyQualifiedNamec                   @   s   e Zd ZdS )BananaErrorN)__name__
__module____qualname__ r   r   7/usr/lib/python3/dist-packages/twisted/spread/banana.pyr      s   r   c                 C   sJ   | dkr|t d d S | dks(td| rF|t | d@  | d? } q(d S )Nr   z!can only encode positive integers      )chrAssertionError)Zintegerstreamr   r   r   int2b128   s    r   c                 C   s6   d}d}t | D ] }t|}||| 7 }|dK }q|S )a  
    Convert an integer represented as a base 128 string into an L{int} or
    L{long}.

    @param st: The integer encoded in a byte string.
    @type st: L{bytes}

    @return: The integer value extracted from the byte string.
    @rtype: L{int} or L{long}
       r   r   )r   ord)steicharnr   r   r   b1282int'   s    
r                           c                 C   s   | a dS )ak  
    Set the limit on the prefix length for all Banana connections
    established after this call.

    The prefix length limit determines how many bytes of prefix a banana
    decoder will allow before rejecting a potential object as too large.

    @type limit: L{int}
    @param limit: The number of bytes of prefix for banana to allow when
    decoding.
    N)_PREFIX_LIMIT)limitr   r   r   setPrefixLimitI   s    r*   @   i  
 c                    @   s   e Zd ZdZddgZdZeZdd Zdd Z	d	d
 Z
dd Zdd Zdd ZdZdd Zdd Zddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5Zi Ze D ]\ZZeee< qd<d6d7Zd8d9 Zd:d; ZdS )=Bananaz
    L{Banana} implements the I{Banana} s-expression protocol, client and
    server.

    @ivar knownDialects: These are the profiles supported by this Banana
        implementation.
    @type knownDialects: L{list} of L{bytes}
       pb   noneNc                 C   s<   || _ d|d   d | _d| _d| _d|d  d | _dS )zt
        Set the prefix limit for decoding done by this protocol instance.

        @see: L{setPrefixLimit}
           r   r   i   iN)prefixLimit_smallestLongInt_smallestInt_largestInt_largestLongInt)selfr)   r   r   r   r*   n   s
    zBanana.setPrefixLimitc                 C   s   dS )zPSurrogate for connectionMade
        Called after protocol negotiation.
        Nr   r5   r   r   r   connectionReady{   s    zBanana.connectionReadyc                 C   s   || _ |   d S N)currentDialectr7   )r5   Zdialectr   r   r   _selectDialect   s    zBanana._selectDialectc                 C   s   | j r| | nr| jrZ|D ]&}|| jkr| | | |  qqtd | j	  n*|| jkrp| | ntd | j	  d S )NzSThe client doesn't speak any of the protocols offered by the server: disconnecting.zYThe client selected a protocol the server didn't suggest and doesn't know: disconnecting.)
r9   expressionReceivedisClientknownDialectssendEncodedr:   r   msg	transportZloseConnection)r5   objZ	serverVerr   r   r   callExpressionReceived   s    





zBanana.callExpressionReceivedc                 C   s&   |  t d | _| js"| | j d S r8   )r*   r(   r9   r<   r>   r=   r6   r   r   r   connectionMade   s    
zBanana.connectionMadec                 C   s,   | j }|r|d d | n
| | d S )Nr   )	listStackappendrB   )r5   itemlr   r   r   gotItem   s    zBanana.gotItem    c                 C   s  | j | }| j}| j}|r| j |ks@tdt| j t|f || _ d}t|D ]}|tkrb q|d }qR|| jkrtd| jf d S |d | }|||d  }||d d  }	t	|| jkrtd| jf |t
krt|}|tkrtd||g f |	}nz|tkrdt|}|tkr0tdt	|	|kr\|	|d  }||	d |  nd S n"|tkr|	}t|}|| n |tkr|	}t|}|| n|tkr|	}t|}||  n|tkr|	}t| }|| n|tkr0|	}t|}| j| }
| jdkr ||
 ntd	|
nV|tkrxt	|	d
krr|	d
d  }|td|	d d
 d  nd S ntd|f |rt	|d d |d d kr| d }
||
 qqd| _ d S )NzThis ain't right: %s %sr   r   z1Security precaution: more than %d bytes of prefixz9Security precaution: longer than %d bytes worth of prefixz#Security precaution: List too long.z%Security precaution: String too long.r-   z"Invalid item for pb protocol {0!r}   !dzInvalid Type Byte %rrD   rJ   )bufferrE   rI   r   reprr   HIGH_BIT_SETr0   r   lenLISTr   
SIZE_LIMITrF   STRINGINTLONGINTLONGNEGNEGVOCABincomingVocabularyr9   NotImplementedErrorformatFLOATstructZunpackpop)r5   chunkrM   rE   rI   posZchZnumZtypebyterestrG   r   r   r   dataReceived   s    
$















 zBanana.dataReceivedc                 C   s
   t  dS )zFCalled when an expression (list, string, or int) is received.
        N)rZ   )r5   lstr   r   r   r;      s    zBanana.expressionReceivedr   r/               r   rK   	   
                                                                  )s   Nones   classs   dereferences	   references
   dictionarys   functions   instances   lists   modules
   persistents   tuples   unpersistables   copys   caches   cacheds   remotes   locals   lcaches   versions   logins   passwords	   challenges	   logged_ins   not_logged_ins   cachemessages   messages   answers   errors   decrefs   decaches   uncachec                 C   s$   g | _ t| j| _d| _|| _d S )Nr   )rE   copyoutgoingVocabularyoutgoingSymbolsZoutgoingSymbolCountr<   )r5   r<   r   r   r   __init__/  s    zBanana.__init__c                 C   s,   t  }| ||j | }| j| dS )a  
        Send the encoded representation of the given object:

        @param obj: An object to encode and send.

        @raise BananaError: If the given object is not an instance of one of
            the types supported by Banana.

        @return: L{None}
        N)r   _encodewritegetvaluer@   )r5   rA   encodeStreamvaluer   r   r   r>   6  s    zBanana.sendEncodedc                 C   s  t |ttfr\t|tkr,tdt|f tt|| |t |D ]}| || qFn`t |t	t
fr|| jk s~|| jkrtd|f || jk rt| | |t nN|dk rt| | |t n0|| jkrt|| |t nt|| |t nt |tr"|t |td| nt |tr| jdkrd|| jkrd| j| }t|| |t n>t|tkrtdt|f tt|| |t || ntdtt||d S )Nz#list/tuple is too long to send (%d)z"int/long is too large to send (%d)r   rL   r-   z$byte string is too long to send (%d)z%Banana cannot send {0} objects: {1!r})
isinstancelisttuplerP   rR   r   r   rQ   r   intr	   r1   r4   r2   rV   rW   r3   rT   rU   floatr\   r]   Zpackbytesr9   r   rX   rS   r[   r   type)r5   rA   r   elemZsymbolIDr   r   r   r   G  sX    












 zBanana._encode)r   )r   r   r   __doc__r=   r0   rR   Z	sizeLimitr*   r7   r:   rB   rC   rI   rM   rb   r;   r   rY   itemskvr   r>   r   r   r   r   r   r,   ]   sf   L'

r,   r.   c                 C   s   t  }|t_t|  | S )zEncode a list s-expression.)r   _ir@   r>   r   )rc   r   r   r   r   encode{  s    
r   c                 C   s0   g }|j t_zt|  W 5 dt_t`X |d S )z)
    Decode a banana-encoded string.
    rJ   r   )rF   r   r;   rM   rb   )r   rH   r   r   r   decode  s    r   )-r   Z
__future__r   r   r   r]   ior   Ztwisted.internetr   Ztwisted.persistedr   Ztwisted.pythonr   Ztwisted.python.compatr   r	   r
   r   Ztwisted.python.reflectr   	Exceptionr   r   r   rQ   rT   rS   rW   r\   rU   rV   rX   rO   r*   r(   rR   ZProtocolZ	Ephemeralr,   r   rC   r:   r   r   r   r   r   r   <module>   s@   

  
