o
    b/                     @   s   d 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 ddlmZ G d	d
 d
eZdd Zdd ZdZdZdZdZdZdZdZdZ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
    N)BytesIO)protocol)styles)log)	iterbytes)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   sN   | dkr
|d d S | dksJ d| r%|t | d@ f | d? } | sd S d S )Nr       z!can only encode positive integers      )bytes)integerstreamr   r   r   int2b128   s   r   c                 C   s6   d}d}t | D ]}t|}||| 7 }|dK }q|S )z
    Convert an integer represented as a base 128 string into an L{int}.

    @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}
       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   setPrefixLimitK   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i 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/d0d1d2d3d4d5d6d7d8d9d:d;d<d=d>d?d@dAdBdCdDdEdFZi Ze D ]\ZZeee< q|dMdGdHZdIdJ ZdKdL ZdS )N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'   r   s
   zBanana.setPrefixLimitc                 C   s   dS )zPSurrogate for connectionMade
        Called after protocol negotiation.
        Nr   r2   r   r   r   connectionReady~   s    zBanana.connectionReadyc                 C   s   || _ |   d S N)currentDialectr4   )r2   dialectr   r   r   _selectDialect   s   zBanana._selectDialectc                 C   s   | j r
| | d S | jr0|D ]}|| jv r#| | | |  d S qtd | j	  d S || jv r<| | d S 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.)
r6   expressionReceivedisClientknownDialectssendEncodedr8   r   msg	transportloseConnection)r2   obj	serverVerr   r   r   callExpressionReceived   s&   



zBanana.callExpressionReceivedc                 C   s*   |  t d | _| js| | j d S d S r5   )r'   r%   r6   r:   r<   r;   r3   r   r   r   connectionMade   s
   
zBanana.connectionMadec                 C   s.   | j }|r|d d | d S | | d S )Nr   )	listStackappendrB   )r2   itemlr   r   r   gotItem   s   zBanana.gotItem    c                 C   s  | j | }| j}| j}|re| j |ks J dt| j t||| _ d}t|D ]}|tkr1 n|d }q)|| jkrCtd| jf d S |d | }|||d  }||d d  }	t	|| jkrjtd| jf |t
krt|}|tkrztd||g f |	}n|tkrt|}|tkrtdt	|	|kr|	|d  }||	d |  nd S |tkr|	}t|}|| n{|tkr|	}t|}|| nl|tkr|	}t|}||  n\|tkr|	}t| }|| nL|tkr|	}t|}| j| }
| jdkr||
 n1td	|
|tkr.t	|	d
kr,|	d
d  }|td|	d d
 d  n	d S td||rct	|d d |d d krc| d }
||
 |rct	|d d |d d ksG|sd| _ d S )NzThis ain't right: {} {}r   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    !dzInvalid Type Byte rD   rJ   )bufferrE   rI   formatreprr   HIGH_BIT_SETr-   r   lenLISTr   
SIZE_LIMITrF   STRINGINTLONGINTLONGNEGNEGVOCABincomingVocabularyr6   NotImplementedErrorFLOATstructunpackpop)r2   chunkrM   rE   rI   poschnumtypebyterestrG   r   r   r   dataReceived   s   










$$
MzBanana.dataReceivedc                 C   s   t  )z=Called when an expression (list, string, or int) is received.)r[   )r2   lstr   r   r   r9     s   zBanana.expressionReceiveds   Noner   s   classr,   s   dereference   s	   reference   s
   dictionary   s   function   s   instancer   s   listrK   s   module	   s
   persistent
   s   tuple   s   unpersistable   s   copy   s   cache   s   cached   s   remote   s   local                                             )s   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outgoingSymbolsoutgoingSymbolCountr:   )r2   r:   r   r   r   __init__4  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>   )r2   r@   encodeStreamvaluer   r   r   r<   :  s   zBanana.sendEncodedc                 C   s  t |ttfr.t|tkrtdt|f tt|| |t |D ]}| || q#d S t |t	r|| j
k s=|| jkrDtd|f || jk rUt| | |t d S |dk ret| | |t d S || jkrut|| |t d S t|| |t d S t |tr|t |td| d S t |tr| jdkr|| jv r| j| }t|| |t d S t|tkrtdt|f tt|| |t || d S tdtt||)Nz#list/tuple is too long to send (%d)zint is too large to send (%d)r   rL   r*   z$byte string is too long to send (%d)z#Banana cannot send {} objects: {!r})
isinstancelisttuplerQ   rS   r   r   rR   r   intr.   r1   r/   rW   rX   r0   rU   rV   floatr\   r]   packr   r6   r   rY   rT   rN   r   type)r2   r@   r   elemsymbolIDr   r   r   r   J  sT   








zBanana._encode)r   )r	   r
   r   __doc__r;   r-   rS   	sizeLimitr'   r4   r8   rB   rC   rI   rM   rf   r9   r   rZ   itemskvr   r<   r   r   r   r   r   r)   a   s    S	
%

r)   r+   c                 C   s   t  }|t_t|  | S )zEncode a list s-expression.)r   _ir>   r<   r   )rg   r   r   r   r   encode  s   
r   c                 C   s8   g }|j t_zt|  W dt_t`|d S dt_t`w )z)
    Decode a banana-encoded string.
    rJ   r   )rF   r   r9   rf   rM   )r   rH   r   r   r   decode  s   r   )'r   r   r]   ior   twisted.internetr   twisted.persistedr   twisted.pythonr   twisted.python.compatr   twisted.python.reflectr   	Exceptionr   r   r   rR   rU   rT   rX   r\   rV   rW   rY   rP   r'   r%   rS   Protocol	Ephemeralr)   r   rC   r8   r   r   r   r   r   r   <module>   sB   
  
