o
    �õ±jïh  ã                   @   sn  d dl mZmZmZmZmZmZmZmZm	Z	m
Z
 ddlmZmZmZmZmZmZmZ ddlmZmZmZ ddlmZmZ ddlmZ ddlmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z& ddl'm(Z(m)Z)m*Z* dd	l+m,Z,m-Z- g d
¢Z.G dd„ de*e*d�Z/G dd„ de*e*d�Z0dZ1de
eef de2fdd„Z3de4de
eef dee5e
ed ee6 f f fdd„Z7G dd„ dƒZ8dS )é    )
ÚAnyÚCallableÚcastÚDictÚListÚOptionalÚoverloadÚTupleÚTypeÚUnioné   )ÚConnectionClosedÚDataÚEndOfMessageÚEventÚInformationalResponseÚRequestÚResponse)Úget_comma_headerÚhas_expect_100_continueÚset_comma_header)ÚREADERSÚReadersType)ÚReceiveBuffer)
Ú_SWITCH_CONNECTÚ_SWITCH_UPGRADEÚCLIENTÚConnectionStateÚDONEÚERRORÚMIGHT_SWITCH_PROTOCOLÚ	SEND_BODYÚSERVERÚSWITCHED_PROTOCOL)ÚLocalProtocolErrorÚRemoteProtocolErrorÚSentinel)ÚWRITERSÚWritersType)Ú
ConnectionÚ	NEED_DATAÚPAUSEDc                   @   ó   e Zd ZdS )r*   N©Ú__name__Ú
__module__Ú__qualname__© r1   r1   ú‚/root/aizidognhua/tmp/workspace/projects/ec89d86c-575f-41c9-af57-ac45cbdbf775/venv/lib/python3.10/site-packages/h11/_connection.pyr*   3   ó    r*   )Ú	metaclassc                   @   r,   )r+   Nr-   r1   r1   r1   r2   r+   7   r3   r+   i @  ÚeventÚreturnc                 C   s0   t | jdƒ}d|v rdS t| ddƒdk rdS dS )Nó
   connectionó   closeFÚhttp_versionó   1.1T)r   ÚheadersÚgetattr)r5   Ú
connectionr1   r1   r2   Ú_keep_aliveT   s   r>   Úrequest_methodr1   c                 C   sÀ   t |ƒttfv s
J ‚t |ƒtu r4|jdv s+| dks+| dkr-d|j  kr)dk r-dS  ndS |jdks4J ‚t|jdƒ}|rE|dgksCJ ‚d	S t|jd
ƒ}|rVdt|d ƒffS t |ƒtu r^dS dS )N)éÌ   i0  ó   HEADó   CONNECTéÈ   é,  )úcontent-length)r   ó   transfer-encodingó   chunked)Úchunkedr1   ó   content-lengthrE   r   )úhttp/1.0r1   )Útyper   r   Ústatus_coder   r;   Úint)r?   r5   Útransfer_encodingsÚcontent_lengthsr1   r1   r2   Ú_body_framing]   s&   
þrP   c                   @   sR  e Zd ZdZefdee deddfdd„Ze	de
ee ee f fdd	„ƒZe	dee fd
d„ƒZe	dee fdd„ƒZe	defdd„ƒZd6dd„Zdee ddfdd„Zdedeee  fdd„Zdee deddfdd„Zdee dee deeef deedef  fdd„Z	d7de
ee ee f dee ddfdd „Ze	deeef fd!d"„ƒZd#eddfd$d%„Z deeee! ee" f fd&d'„Z#deeee! ee" f fd(d)„Z$e%de&ddfd*d+„ƒZ'e%dee(e)e*e+e,f defd,d+„ƒZ'e%dedee fd-d+„ƒZ'dedee fd.d+„Z'dedee-e  fd/d0„Z.d6d1d2„Z/d3e*de*fd4d5„Z0dS )8r)   aB  An object encapsulating the state of an HTTP connection.

    Args:
        our_role: If you're implementing a client, pass :data:`h11.CLIENT`. If
            you're implementing a server, pass :data:`h11.SERVER`.

        max_incomplete_event_size (int):
            The maximum number of bytes we're willing to buffer of an
            incomplete event. In practice this mostly sets a limit on the
            maximum size of the request/response line + headers. If this is
            exceeded, then :meth:`next_event` will raise
            :exc:`RemoteProtocolError`.

    Úour_roleÚmax_incomplete_event_sizer6   Nc                 C   s�   || _ |ttfvrtd|›�ƒ‚|| _|  |tu rt| _nt| _tƒ | _|  | jd t	¡| _
|  | jd t¡| _tƒ | _d| _d | _d | _d| _d S )Nzexpected CLIENT or SERVER, not F)Ú_max_incomplete_event_sizer   r"   Ú
ValueErrorrQ   Ú
their_roler   Ú_cstateÚ_get_io_objectr'   Ú_writerr   Ú_readerr   Ú_receive_bufferÚ_receive_buffer_closedÚtheir_http_versionÚ_request_methodÚ"client_is_waiting_for_100_continue)ÚselfrQ   rR   r1   r1   r2   Ú__init__§   s    
zConnection.__init__c                 C   s   t | jjƒS )z‰A dictionary like::

           {CLIENT: <client state>, SERVER: <server state>}

        See :ref:`state-machine` for details.

        )ÚdictrV   Ústates©r_   r1   r1   r2   rb   Î   s   	zConnection.statesc                 C   ó   | j j| j S )zjThe current state of whichever role we are playing. See
        :ref:`state-machine` for details.
        )rV   rb   rQ   rc   r1   r1   r2   Ú	our_stateÙ   ó   zConnection.our_statec                 C   rd   )znThe current state of whichever role we are NOT playing. See
        :ref:`state-machine` for details.
        )rV   rb   rU   rc   r1   r1   r2   Útheir_stateà   rf   zConnection.their_statec                 C   s   | j tu o| jS ©N)rU   r   r^   rc   r1   r1   r2   Ú!they_are_waiting_for_100_continueç   s   z,Connection.they_are_waiting_for_100_continuec                 C   s4   t | jjƒ}| j ¡  d| _| jrJ ‚|  |¡ dS )a�  Attempt to reset our connection state for a new request/response
        cycle.

        If both client and server are in :data:`DONE` state, then resets them
        both to :data:`IDLE` state in preparation for a new request/response
        cycle on this same connection. Otherwise, raises a
        :exc:`LocalProtocolError`.

        See :ref:`keepalive-and-pipelining`.

        N)ra   rV   rb   Ústart_next_cycler]   r^   Ú_respond_to_state_changes)r_   Ú
old_statesr1   r1   r2   rj   ë   s
   

zConnection.start_next_cycleÚrolec                 C   s&   t | jjƒ}| j |¡ |  |¡ d S rh   )ra   rV   rb   Úprocess_errorrk   )r_   rm   rl   r1   r1   r2   Ú_process_errorÿ   s   zConnection._process_errorr5   c                 C   sT   t |ƒtu r|jdkrtS t |ƒtu r(t| jjv r(d|j  kr%dk r(tS  d S d S )Née   rC   rD   )rK   r   rL   r   r   r   rV   Úpending_switch_proposals©r_   r5   r1   r1   r2   Ú_server_switch_event  s   þzConnection._server_switch_eventc                 C   sR  t | jjƒ}|tu r't|ƒtu r'|jdkr| j t¡ t	|j
dƒr'| j t¡ d }|tu r2|  |¡}| j |t|ƒ|¡ t|ƒtu rF|j| _|| ju rbt|ƒtttfv rbtttttf |ƒ}|j| _t|ƒttfv rztttttf |ƒƒsz| j ¡  t|ƒtu r‡t|ƒr‡d| _t|ƒttfv r’d| _|tu r¡t|ƒttfv r¡d| _|  ||¡ d S )NrB   s   upgradeTF)ra   rV   rb   r   rK   r   ÚmethodÚprocess_client_switch_proposalr   r   r;   r   r"   rs   Úprocess_eventr]   rU   r   r   r   r   r9   r\   r>   Úprocess_keep_alive_disabledr   r^   r   r   rk   )r_   rm   r5   rl   Úserver_switch_eventr1   r1   r2   Ú_process_event  s<   

ýÿ
zConnection._process_eventÚio_dict.c                 C   sV   | j j| }|tu r$ttt| jƒtttt	f |ƒƒ\}}|t | |Ž S | 
||f¡S rh   )rV   rb   r!   rP   r   Úbytesr]   r   r   r   Úget)r_   rm   r5   rz   ÚstateÚframing_typeÚargsr1   r1   r2   rW   @  s   ÿzConnection._get_io_objectrl   c                 C   sL   | j || j kr|  | j|t¡| _| j|| j kr$|  | j|t¡| _d S d S rh   )	re   rQ   rW   r'   rX   rg   rU   r   rY   )r_   rl   r5   r1   r1   r2   rk   V  s
   ÿz$Connection._respond_to_state_changesc                 C   s   t | jƒ| jfS )ab  Data that has been received, but not yet processed, represented as
        a tuple with two elements, where the first is a byte-string containing
        the unprocessed data itself, and the second is a bool that is True if
        the receive connection was closed.

        See :ref:`switching-protocols` for discussion of why you'd want this.
        )r{   rZ   r[   rc   r1   r1   r2   Útrailing_dataa  s   	zConnection.trailing_dataÚdatac                 C   s.   |r| j r	tdƒ‚|  j|7  _dS d| _ dS )aØ  Add data to our internal receive buffer.

        This does not actually do any processing on the data, just stores
        it. To trigger processing, you have to call :meth:`next_event`.

        Args:
            data (:term:`bytes-like object`):
                The new data that was just received.

                Special case: If *data* is an empty byte-string like ``b""``,
                then this indicates that the remote side has closed the
                connection (end of file). Normally this is convenient, because
                standard Python APIs like :meth:`file.read` or
                :meth:`socket.recv` use ``b""`` to indicate end-of-file, while
                other failures to read are indicated using other mechanisms
                like raising :exc:`TimeoutError`. When using such an API you
                can just blindly pass through whatever you get from ``read``
                to :meth:`receive_data`, and everything will work.

                But, if you have an API where reading an empty string is a
                valid non-EOF condition, then you need to be aware of this and
                make sure to check for such strings and avoid passing them to
                :meth:`receive_data`.

        Returns:
            Nothing, but after calling this you should call :meth:`next_event`
            to parse the newly received data.

        Raises:
            RuntimeError:
                Raised if you pass an empty *data*, indicating EOF, and then
                pass a non-empty *data*, indicating more data that somehow
                arrived after the EOF.

                (Calling ``receive_data(b"")`` multiple times is fine,
                and equivalent to calling it once.)

        z(received close, then received more data?TN)r[   ÚRuntimeErrorrZ   )r_   r�   r1   r1   r2   Úreceive_datal  s
   '
zConnection.receive_datac                 C   sˆ   | j }|tu r| jrtS |tu s|tu rtS | jd usJ ‚|  | j¡}|d u r<| js<| jr<t| jdƒr9| j 	¡ }nt
ƒ }|d u rBt}|S )NÚread_eof)rg   r   rZ   r+   r    r#   rY   r[   Úhasattrr„   r   r*   )r_   r}   r5   r1   r1   r2   Ú_extract_next_receive_eventš  s   z&Connection._extract_next_receive_eventc              
   C   s¼   | j tu r	tdƒ‚z0|  ¡ }|ttfvr|  | jtt	|ƒ¡ |tu r7t
| jƒ| jkr0tddd�‚| jr7tdƒ‚|W S  ty] } z|  | j¡ t|tƒrQ| ¡  n‚ W Y d}~dS d}~ww )aF  Parse the next event out of our receive buffer, update our internal
        state, and return it.

        This is a mutating operation -- think of it like calling :func:`next`
        on an iterator.

        Returns:
            : One of three things:

            1) An event object -- see :ref:`events`.

            2) The special constant :data:`NEED_DATA`, which indicates that
               you need to read more data from your socket and pass it to
               :meth:`receive_data` before this method will be able to return
               any more events.

            3) The special constant :data:`PAUSED`, which indicates that we
               are not in a state where we can process incoming data (usually
               because the peer has finished their part of the current
               request/response cycle, and you have not yet called
               :meth:`start_next_cycle`). See :ref:`flow-control` for details.

        Raises:
            RemoteProtocolError:
                The peer has misbehaved. You should close the connection
                (possibly after sending some kind of 4xx response).

        Once this method returns :class:`ConnectionClosed` once, then all
        subsequent calls will also return :class:`ConnectionClosed`.

        If this method raises any exception besides :exc:`RemoteProtocolError`
        then that's a bug -- if it happens please file a bug report!

        If this method raises any exception then it also sets
        :attr:`Connection.their_state` to :data:`ERROR` -- see
        :ref:`error-handling` for discussion.

        z+Can't receive data when peer state is ERRORzReceive buffer too longi¯  )Úerror_status_hintz#peer unexpectedly closed connectionN)rg   r   r%   r†   r*   r+   ry   rU   r   r   ÚlenrZ   rS   r[   ÚBaseExceptionro   Ú
isinstancer$   Ú!_reraise_as_remote_protocol_error)r_   r5   Úexcr1   r1   r2   Ú
next_event¶  s,   
(ÿ

þ€ýzConnection.next_eventc                 C   ó   d S rh   r1   rr   r1   r1   r2   Úsend÷  ó   zConnection.sendc                 C   rŽ   rh   r1   rr   r1   r1   r2   r�   û  s   c                 C   rŽ   rh   r1   rr   r1   r1   r2   r�     r�   c                 C   s    |   |¡}|du rdS d |¡S )a³  Convert a high-level event into bytes that can be sent to the peer,
        while updating our internal state machine.

        Args:
            event: The :ref:`event <events>` to send.

        Returns:
            If ``type(event) is ConnectionClosed``, then returns
            ``None``. Otherwise, returns a :term:`bytes-like object`.

        Raises:
            LocalProtocolError:
                Sending this event at this time would violate our
                understanding of the HTTP/1.1 protocol.

        If this method raises any exception then it also sets
        :attr:`Connection.our_state` to :data:`ERROR` -- see
        :ref:`error-handling` for discussion.

        Nó    )Úsend_with_data_passthroughÚjoin)r_   r5   Ú	data_listr1   r1   r2   r�     s   

c                 C   s†   | j tu r	tdƒ‚z/t|ƒtu r|  |¡}| j}|  | j|¡ t|ƒt	u r(W dS |dus.J ‚g }|||j
ƒ |W S    |  | j¡ ‚ )ah  Identical to :meth:`send`, except that in situations where
        :meth:`send` returns a single :term:`bytes-like object`, this instead
        returns a list of them -- and when sending a :class:`Data` event, this
        list is guaranteed to contain the exact object you passed in as
        :attr:`Data.data`. See :ref:`sendfile` for discussion.

        z'Can't send data when our state is ERRORN)re   r   r$   rK   r   Ú&_clean_up_response_headers_for_sendingrX   ry   rQ   r   Úappendro   )r_   r5   Úwriterr”   r1   r1   r2   r’      s    

z%Connection.send_with_data_passthroughc                 C   s   |   | j¡ dS )záNotify the state machine that we failed to send the data it gave
        us.

        This causes :attr:`Connection.our_state` to immediately become
        :data:`ERROR` -- see :ref:`error-handling` for discussion.

        N)ro   rQ   rc   r1   r1   r2   Úsend_failedA  s   zConnection.send_failedÚresponsec                 C   sæ   t |ƒtu sJ ‚|j}d}tt| jƒ}|dkrd}t||ƒ\}}|dv rIt|dg ƒ}| jd u s4| jdk rBt|dg ƒ}| jdkrAd}nt|dd	gƒ}| j	j
rO|rhtt|d
ƒƒ}| d¡ | d¡ t|d
t|ƒƒ}t||j|j|jd�S )NFrA   s   GET)rH   rJ   rI   r:   rF   TrG   r7   s
   keep-aliver8   )r;   rL   r9   Úreason)rK   r   r;   r   r{   r]   rP   r   r\   rV   Ú
keep_aliveÚsetr   ÚdiscardÚaddÚsortedrL   r9   rš   )r_   r™   r;   Ú
need_closeÚmethod_for_choosing_headersr~   Ú_r=   r1   r1   r2   r•   Z  s4   	
€

üz1Connection._clean_up_response_headers_for_sending)r6   Nrh   )1r.   r/   r0   Ú__doc__Ú!DEFAULT_MAX_INCOMPLETE_EVENT_SIZEr
   r&   rM   r`   Úpropertyr   rb   re   rg   Úboolri   rj   ro   r   r   rs   ry   r   r   r(   r   r   rW   rk   r	   r{   r€   rƒ   r*   r+   r†   r�   r   r   r�   r   r   r   r   r   r   r’   r˜   r•   r1   r1   r1   r2   r)   —   sx    ýþý
ü' 

0þý
ü
ûýþý
ü
.
þ Aÿþ
!r)   N)9Útypingr   r   r   r   r   r   r   r	   r
   r   Ú_eventsr   r   r   r   r   r   r   Ú_headersr   r   r   Ú_readersr   r   Ú_receivebufferr   Ú_stater   r   r   r   r   r   r    r!   r"   r#   Ú_utilr$   r%   r&   Ú_writersr'   r(   Ú__all__r*   r+   r¤   r¦   r>   r{   ÚstrrM   rP   r)   r1   r1   r1   r2   Ú<module>   s*   0$	0	ÿ
ÿ
þ: