U
    Ê¼µbs  ã                   @   sT   d Z ddlmZ ddlmZmZmZmZ ddlm	Z	m
Z
mZ dZG dd„ deƒZd	S )
zy
h2/frame_buffer
~~~~~~~~~~~~~~~

A data structure that provides a way to iterate over a byte buffer in terms of
frames.
é    )ÚInvalidFrameError)ÚFrameÚHeadersFrameÚContinuationFrameÚPushPromiseFrameé   )ÚProtocolErrorÚFrameTooLargeErrorÚFrameDataMissingErroré@   c                   @   sR   e Zd ZdZddd„Zdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ Z	dd„ Z
dd„ ZdS )ÚFrameBufferz‚
    This is a data structure that expects to act as a buffer for HTTP/2 data
    that allows iteraton in terms of H2 frames.
    Fc                 C   s0   d| _ d| _|rdnd| _t| jƒ| _g | _d S )Nó    r   s   PRI * HTTP/2.0

SM

)ÚdataÚmax_frame_sizeÚ	_preambleÚlenÚ_preamble_lenÚ_headers_buffer)ÚselfÚserver© r   ú3/tmp/pip-unpacked-wheel-n0jtiqmd/h2/frame_buffer.pyÚ__init__"   s
    zFrameBuffer.__init__c                 C   sx   | j rft|ƒ}t| j |ƒ}| jd|… |d|… kr<tdƒ‚||d… }|  j |8  _ | j|d… | _|  j|7  _dS )zs
        Add more data to the frame buffer.

        :param data: A bytestring containing the byte buffer.
        NzInvalid HTTP/2 preamble.)r   r   Úminr   r   r   )r   r   Zdata_lenZof_which_preambler   r   r   Úadd_data)   s    zFrameBuffer.add_datac              
   C   sV   zt  |dd… ¡\}}W n2 tk
rL } ztdt|ƒ ƒ‚W 5 d}~X Y nX ||fS )zË
        Parses the frame header from the data. Either returns a tuple of
        (frame, length), or throws an exception. The returned frame may be None
        if the frame is of unknown type.
        Né	   z!Invalid frame header received: %s)r   Zparse_frame_headerÚ
ValueErrorr   Ústr)r   r   ÚframeÚlengthÚer   r   r   Ú_parse_frame_header<   s
    "zFrameBuffer._parse_frame_headerc                 C   s    || j krtd|| j f ƒ‚dS )zB
        Confirm that the frame is an appropriate length.
        z*Received overlong frame: length %d, max %dN)r   r	   )r   r   r   r   r   Ú_validate_frame_lengthJ   s    
ÿÿz"FrameBuffer._validate_frame_lengthc                 C   sÎ   | j r¢| j d j}|dk	o,t|tƒo,|j|k}|s:tdƒ‚| j  |¡ t| j ƒtkr\tdƒ‚d|jkrœ| j d }|j 	d¡ d 
dd„ | j D ƒ¡|_g | _ qÊd}n(t|ttfƒrÊd|jkrÊ| j  |¡ d}|S )	z¡
        Updates the internal header buffer. Returns a frame that should replace
        the current one. May throw exceptions if this frame is invalid.
        r   Nz"Invalid frame during header block.z&Too many continuation frames received.ZEND_HEADERSr   c                 s   s   | ]}|j V  qd S ©N)r   )Ú.0Úxr   r   r   Ú	<genexpr>t   s     z4FrameBuffer._update_header_buffer.<locals>.<genexpr>)r   Ú	stream_idÚ
isinstancer   r   Úappendr   ÚCONTINUATION_BACKLOGÚflagsÚaddÚjoinr   r   r   )r   Úfr'   Zvalid_framer   r   r   Ú_update_header_bufferT   s0    
ÿý

ÿz!FrameBuffer._update_header_bufferc                 C   s   | S r#   r   ©r   r   r   r   Ú__iter__‚   s    zFrameBuffer.__iter__c                 C   sà   t | jƒdk rtƒ ‚z|  | j¡\}}W n tk
rD   tdƒ‚Y nX t | jƒ|d k r^tƒ ‚|  |¡ |d k	r®z | t| jdd| … ƒ¡ W n tk
r¬   t	dƒ‚Y nX | jd| d … | _|  
|¡}|d k	rØ|S |  ¡ S )Nr   z)Received frame with invalid frame header.zFrame data missing or invalid)r   r   ÚStopIterationr!   r   r   r"   Z
parse_bodyÚ
memoryviewr
   r/   Únext)r   r.   r   r   r   r   r4   …   s"    
 
zFrameBuffer.nextc                 C   s   |   ¡ S r#   )r4   r0   r   r   r   Ú__next__®   s    zFrameBuffer.__next__N)F)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r!   r"   r/   r1   r4   r5   r   r   r   r   r      s   

.)r   N)r9   Zhyperframe.exceptionsr   Zhyperframe.framer   r   r   r   Ú
exceptionsr   r	   r
   r*   Úobjectr   r   r   r   r   Ú<module>   s
   