a
    )(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   4lib/python3.9/site-packages/twisted/spread/banana.pyr      s   r   c                 C   sH   | dkr|d d S | dks$J d| rD|t | d@ f | d? } q$d S )Nr       z!can only encode positive integers      )bytes)Z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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&   r   s
    zBanana.setPrefixLimitc                 C   s   dS )zPSurrogate for connectionMade
        Called after protocol negotiation.
        Nr   r1   r   r   r   connectionReady~   s    zBanana.connectionReadyc                 C   s   || _ |   d S N)currentDialectr3   )r1   Zdialectr   r   r   _selectDialect   s    zBanana._selectDialectc                 C   s   | j r| | nr| jrZ|D ]&}|| jv r| | | |  qqtd | j	  n*|| jv 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.)
r5   expressionReceivedisClientknownDialectssendEncodedr6   r   msg	transportZloseConnection)r1   objZ	serverVerr   r   r   callExpressionReceived   s$    



zBanana.callExpressionReceivedc                 C   s&   |  t d | _| js"| | j d S r4   )r&   r$   r5   r8   r:   r9   r2   r   r   r   connectionMade   s    
zBanana.connectionMadec                 C   s,   | j }|r|d d | n
| | d S )Nr   )	listStackappendr>   )r1   itemlr   r   r   gotItem   s    zBanana.gotItem    c                 C   s  | j | }| j}| j}|r| j |ks@J dt| j t||| _ 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||rt	|d d |d d kr| d }
||
 qq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 r@   rF   )bufferrA   rE   formatreprr   HIGH_BIT_SETr,   r   lenLISTr   
SIZE_LIMITrB   STRINGINTLONGINTLONGNEGNEGVOCABincomingVocabularyr5   NotImplementedErrorFLOATstructZunpackpop)r1   chunkrI   rA   rE   posZchZnumZtypebyterestrC   r   r   r   dataReceived   s    
















 zBanana.dataReceivedc                 C   s
   t  dS )z=Called when an expression (list, string, or int) is received.N)rW   )r1   lstr   r   r   r7     s    zBanana.expressionReceivedr   r+               r   rG   	   
                                                                  )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   )rA   copyoutgoingVocabularyoutgoingSymbolsZoutgoingSymbolCountr8   )r1   r8   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<   )r1   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 ]}| || qFn\t |t	r|| j
k sz|| 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r`|| jv r`| 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 is too large to send (%d)r   rH   r)   z$byte string is too long to send (%d)z#Banana cannot send {} objects: {!r})
isinstancelisttuplerM   rO   r   r   rN   r   intr-   r0   r.   rS   rT   r/   rQ   rR   floatrX   rY   Zpackr   r5   r}   rU   rP   rJ   r   type)r1   r=   r   elemZsymbolIDr   r   r   r   J  sR    












zBanana._encode)r   )r	   r
   r   __doc__r9   r,   rO   Z	sizeLimitr&   r3   r6   r>   r?   rE   rI   r^   r7   r|   rV   itemskvr~   r:   r   r   r   r   r   r(   a   sf   S%

r(   r*   c                 C   s   t  }|t_t|  | S )zEncode a list s-expression.)r   _ir<   r:   r   )r_   r   r   r   r   encode  s    
r   c                 C   s:   g }|j t_zt|  W dt_t`ndt_t`0 |d S )z)
    Decode a banana-encoded string.
    rF   r   )rB   r   r7   r^   rI   )r   rD   r   r   r   decode  s    r   )'r   r{   rY   ior   Ztwisted.internetr   Ztwisted.persistedr   Ztwisted.pythonr   Ztwisted.python.compatr   Ztwisted.python.reflectr   	Exceptionr   r   r   rN   rQ   rP   rT   rX   rR   rS   rU   rL   r&   r$   rO   ProtocolZ	Ephemeralr(   r   r?   r6   r   r   r   r   r   r   <module>   s@   
  
