o
    NK&h,                     @   s   d dl Z d dlZd dlmZ d dlmZmZ d dlmZm	Z	 d dl
mZ d dlmZ er2ddlmZ ed	ZG d
d dZdS )    N)AsyncIterator)TYPE_CHECKINGOptional)FrameOpcode)Data)ServerError   )WebsocketImplProtocolzutf-8c                   @   s   e Zd ZU dZdZerHded< ejed< ejed< ej	ed< ej	ed< ej
ed	< eed
< eej ed< ee ed< eej
ee   ed< eed< dddZddee dee fddZdee fddZdeddfddZdS )WebsocketFrameAssemblerz
    Assemble a message from frames.
    Code borrowed from aaugustin/websockets project:
    https://github.com/aaugustin/websockets/blob/6eb98dd8fa5b2c896b9f6be7e8d117708da82a39/src/websockets/sync/messages.py
    )protocol
read_mutexwrite_mutexmessage_completemessage_fetchedget_in_progressdecodercompleted_queuechunkschunks_queuepausedget_idput_idr
   r   r   r   r   r   r   r   r   r   r   r   returnNc                 C   s^   || _ t | _t | _tjdd| _t | _t | _	d| _
d | _g | _d | _d| _d S )Nr	   )maxsizeF)r   asyncioLockr   r   Queuer   Eventr   r   r   r   r   r   r   )selfr    r    P/var/www/html/venv/lib/python3.10/site-packages/sanic/server/websockets/frame.py__init__7   s   



	
z WebsocketFrameAssembler.__init__timeoutc              	      s  | j 4 I dH  |dur"|dkr"| j s"	 W d  I dH  dS | jr)tdd| _|du r9| j I dH }n2|dkrC| j }n(z!ztj| j |dI dH  W n
 tjy]   Y nw W | j }n| j }w | j	rv| j
  d| _	| js}tdd| _|s	 W d  I dH  dS | j s	 W d  I dH  dS | j  | jdu rdnd	}|| j}| j rtd
| j  g | _d| _|W  d  I dH  S 1 I dH sw   Y  dS )ai  
        Read the next message.
        :meth:`get` returns a single :class:`str` or :class:`bytes`.
        If the :message was fragmented, :meth:`get` waits until the last frame
        is received, then it reassembles the message.
        If ``timeout`` is set and elapses before a complete message is
        received, :meth:`get` returns ``None``.
        Nr   zXCalled get() on Websocket frame assembler while asynchronous get is already in progress.T)r#   FZState of Websocket frame assembler was modified while an asynchronous get was in progress.     z?Websocket get() found a message when state was already fetched.)r   r   is_setr   r   waitr   wait_forTimeoutErrorr   r   resume_framesclearr   joinr   r   setr   )r   r#   	completedjoinermessager    r    r!   getY   sd   




.
1

0zWebsocketFrameAssembler.getc              	   C  s*  | j 4 I dH  | jrtdd| _| j}g | _t | _| j r,| j	dI dH  |D ]}|V  q.	 | j
 I dH }|du rBn|V  q5| jrQ| j  d| _| jsXtdd| _| j sdtd| j  | j rrtd| j  g | _d| _W d  I dH  dS 1 I dH sw   Y  dS )z
        Stream the next message.
        Iterating the return value of :meth:`get_iter` yields a :class:`str`
        or :class:`bytes` for each frame in the message.
        Nz[Called get_iter on Websocket frame assembler while asynchronous get is already in progress.TFr$   zIWebsocket frame assembler chunks queue ended before message was complete.zDWebsocket get_iter() found a message when state was already fetched.)r   r   r   r   r   r   r   r   r'   putr2   r   r   r+   r,   r   r.   )r   r   cchunkr    r    r!   get_iter   sR   






.z WebsocketFrameAssembler.get_iterframec              	      s~  | j 4 I dH  |jtju rtdd| _n|jtju r d| _n|jtju r'n	 W d  I dH  dS | jdurB| j|j	|j
}n|j	}| jdu rQ| j| n	| j|I dH  |j
si	 W d  I dH  dS | jsr| j | _| jdur| jdI dH  | j rtd| j  | j rtd| j I dH  | j  d| _W d  I dH  dS 1 I dH sw   Y  dS )a  
        Add ``frame`` to the next message.
        When ``frame`` is the final frame in a message, :meth:`put` waits
        until the message is fetched, either by calling :meth:`get` or by
        iterating the return value of :meth:`get_iter`.
        :meth:`put` assumes that the stream of frames respects the protocol.
        If it doesn't, the behavior is undefined.
        Nstrict)errorszLWebsocket put() got a new message when a message was already in its chamber.zPWebsocket put() got a new message when the previous message was not yet fetched.)r   opcoder   TEXTUTF8Decoderr   BINARYCONTdecodedatafinr   r   appendr3   r   r   pause_framesr   r   r'   r   r.   r   r(   r,   )r   r7   r@   r    r    r!   r3      sH   







.zWebsocketFrameAssembler.put)r   N)N)__name__
__module____qualname____doc__	__slots__r   __annotations__r   r   r   r   boolr   codecsIncrementalDecoderlistr   r"   floatr2   r   r6   r   r3   r    r    r    r!   r      s&   
 





"NEr   )r   rK   collections.abcr   typingr   r   websockets.framesr   r   websockets.typingr   sanic.exceptionsr   implr
   getincrementaldecoderr<   r   r    r    r    r!   <module>   s    
