o
    ha                     @   s   d dl T d dlT d dlmZmZmZ d dlmZmZmZ d dl	m
Z
mZmZ d dlmZ d dlmZ d dlmZ g dZed	Zed
ZdZdd Zdd ZG dd deZdS )   )*)LocalProtocolErrorRemoteProtocolErrormake_sentinel)ConnectionState_SWITCH_UPGRADE_SWITCH_CONNECT)get_comma_headerset_comma_headerhas_expect_100_continue)ReceiveBuffer)READERS)WRITERS)
Connection	NEED_DATAPAUSEDr   r   i @  c                 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)event
connection r   W/var/www/html/magazine_api/magazine_env/lib/python3.10/site-packages/h11/_connection.py_keep_alive0   s   r   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)       transfer-encodings   chunked)chunkedr      content-lengthr"   r#   )http/1.0r   )typeRequestResponsestatus_coder	   r   int)request_methodr   Ztransfer_encodingsZcontent_lengthsr   r   r   _body_framing8   s(   
r.   c                   @   s   e Zd ZdZefddZedd Zedd Zedd	 Z	ed
d Z
dd Zdd Zdd Zdd Zdd Zd)ddZe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 )*r   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`.

    c                 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 {!r}F)_max_incomplete_event_sizeCLIENTSERVER
ValueErrorformatour_role
their_roler   _cstate_get_io_objectr   _writerr   _readerr   _receive_buffer_receive_buffer_closedtheir_http_version_request_method"client_is_waiting_for_100_continue)selfr4   Zmax_incomplete_event_sizer   r   r   __init__|   s"   
zConnection.__init__c                 C   s   t | jjS )zA dictionary like::

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

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

        )dictr6   statesr?   r   r   r   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.
        )r6   rB   r4   rC   r   r   r   	our_state      zConnection.our_statec                 C   rD   )znThe current state of whichever role we are NOT playing. See
        :ref:`state-machine` for details.
        )r6   rB   r5   rC   r   r   r   their_state   rF   zConnection.their_statec                 C   s   | j tu o| jS N)r5   r0   r>   rC   r   r   r   !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   r6   rB   start_next_cycler=   r>   _respond_to_state_changes)r?   
old_statesr   r   r   rJ      s
   

zConnection.start_next_cyclec                 C   s&   t | jj}| j| | | d S rH   )rA   r6   rB   Zprocess_errorrK   )r?   rolerL   r   r   r   _process_error   s   zConnection._process_errorc                 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 )Ne   r    r!   )r(   InformationalResponser+   r   r*   r   r6   Zpending_switch_proposals)r?   r   r   r   r   _server_switch_event   s   zConnection._server_switch_eventc                 C   s0  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 rXt|tttfv rX|j| _t|ttfv rit|si| j  t|tu rvt|rvd| _t|ttfv rd| _|tu rt|ttfv rd| _| || d S )Nr   s   upgradeTF)rA   r6   rB   r0   r(   r)   methodZprocess_client_switch_proposalr   r	   r   r   r1   rQ   Zprocess_eventr=   r5   r*   rP   r   r<   r   Zprocess_keep_alive_disabledr   r>   ZDataZEndOfMessagerK   )r?   rM   r   rL   Zserver_switch_eventr   r   r   _process_event   s0   



zConnection._process_eventc                 C   sB   | j j| }|tu rt| j|\}}|t | | S |||fS rH   )r6   rB   Z	SEND_BODYr.   r=   get)r?   rM   r   Zio_dictstateframing_typeargsr   r   r   r7     s
   zConnection._get_io_objectNc                 C   sL   | j || j kr| | j|t| _| j|| j kr$| | j|t| _d S d S rH   )	rE   r4   r7   r   r8   rG   r5   r   r9   )r?   rL   r   r   r   r   rK     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.
        )bytesr:   r;   rC   r   r   r   trailing_data$  s   	zConnection.trailing_datac                 C   s.   |r| j r	td|  j|7  _dS d| _ dS )a  Add data to our internal recieve 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;   RuntimeErrorr:   )r?   datar   r   r   receive_data/  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   ZDONEr:   r   ZMIGHT_SWITCH_PROTOCOLZSWITCHED_PROTOCOLr9   r;   hasattrr]   ConnectionClosedr   )r?   rU   r   r   r   r   _extract_next_receive_event^  s   z&Connection._extract_next_receive_eventc              
   C   s   | j tu r	tdz2|  }|ttfvr | | j| | j	  |tu r9t
| j| jkr2tddd| jr9td|W S  ty_ } z| | j t|trS|  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  )Zerror_status_hintz#peer unexpectedly closed connectionN)rG   ERRORr   r`   r   r   rS   r5   r:   compresslenr/   r;   BaseExceptionrN   
isinstancer   Z!_reraise_as_remote_protocol_error)r?   r   excr   r   r   
next_eventx  s6   
(


zConnection.next_eventc                 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?   r   	data_listr   r   r   send  s   

zConnection.sendc                 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   ra   r   r(   r*   &_clean_up_response_headers_for_sendingr8   rS   r4   r_   appendrN   )r?   r   writerrk   r   r   r   ri     s$   

z%Connection.send_with_data_passthroughc                 C   s   |  | j dS )zNotify 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)rN   r4   rC   r   r   r   send_failed  s   zConnection.send_failedc                 C   s   t |tu sJ t|j}d}| j}|dkrd}t||\}}|dv rHt|dg  | jd u s3| jdk rAt|dg  | jdkr@d}nt|dd	g | jj	rN|rgt
t|d
}|d |d t|d
t| ||_d S )NFr   s   GET)r%   r'   r&   r   r$   Tr%   r   s
   keep-aliver   )r(   r*   listr   r=   r.   r
   r<   r6   
keep_alivesetr	   discardaddsorted)r?   responser   Z
need_closeZmethod_for_choosing_headersrV   _r   r   r   r   rm     s,   
	





z1Connection._clean_up_response_headers_for_sendingrH   )__name__
__module____qualname____doc__!DEFAULT_MAX_INCOMPLETE_EVENT_SIZEr@   propertyrB   rE   rG   rI   rJ   rN   rQ   rS   r7   rK   rY   r\   r`   rg   rl   ri   rp   rm   r   r   r   r   r   m   s6    
%





,


/C"r   N)Z_events_stateZ_utilr   r   r   r   r   r   _headersr	   r
   r   Z_receivebufferr   _readersr   _writersr   __all__r   r   r}   r   r.   objectr   r   r   r   r   <module>   s   5