B
    Ceg                 @   sf  d dl 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, d
ddgZ-G dd de)e)dZ.G dd de)e)dZ/dZ0e	eef e1dddZ2e3e	eef ee4e	ed ee5 f f dddZ6G dd
 d
Z7dS )    )	AnyCallablecastDictListOptional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               @   s   e Zd ZdS )r)   N)__name__
__module____qualname__ r.   r.   c/var/www/downstreamdata.science/rtclock/rtclock-venv/lib/python3.7/site-packages/h11/_connection.pyr)   (   s   )	metaclassc               @   s   e Zd ZdS )r*   N)r+   r,   r-   r.   r.   r.   r/   r*   ,   s   i @  )eventreturnc             C   s0   t | jd}d|krdS t| dddk r,dS dS )Ns
   connections   closeFhttp_versions   1.1T)r   headersgetattr)r1   
connectionr.   r.   r/   _keep_aliveH   s    r7   r.   )request_methodr1   r2   c             C   s   t |ttfkstt |tkrf|jdksT| dksT| dkrXd|j  krPdk rXn ndS |jdksftt|jd}|r|dgkstd	S t|jd
}|rdt|d ffS t |tkrdS dS d S )N)   i0  s   HEADs   CONNECT   i,  )zcontent-length)r   s   transfer-encodings   chunked)chunkedr.   s   content-lengthzcontent-lengthr   )zhttp/1.0r.   )typer   r   AssertionErrorstatus_coder   r4   int)r8   r1   Ztransfer_encodingsZcontent_lengthsr.   r.   r/   _body_framingQ   s"    
"r@   c               @   s  e Zd ZdZefee eddddZe	e
ee ee f dddZe	ee dd	d
Ze	ee dddZe	edddZddddZee ddddZeeee  dddZee eddddZee ee eeef eedef  dddZd3e
ee ee f ee dddd Ze	eeef dd!d"Zedd#d$d%Z eeee! ee" f dd&d'Z#eeee! ee" f dd(d)Z$eee dd*d+Z%eee&e  dd,d-Z'ddd.d/Z(e)e)d0d1d2Z*dS )4r(   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`.

    N)our_rolemax_incomplete_event_sizer2   c             C   s   || _ |ttfkr td||| _|  |tk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_sizer   r!   
ValueErrorformatrA   
their_roler   _cstate_get_io_objectr&   _writerr   _readerr   _receive_buffer_receive_buffer_closedtheir_http_version_request_method"client_is_waiting_for_100_continue)selfrA   rB   r.   r.   r/   __init__   s     zConnection.__init__)r2   c             C   s   t | jjS )zA dictionary like::

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

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

        )dictrG   states)rP   r.   r.   r/   rS      s    	zConnection.statesc             C   s   | j j| j S )zjThe current state of whichever role we are playing. See
        :ref:`state-machine` for details.
        )rG   rS   rA   )rP   r.   r.   r/   	our_state   s    zConnection.our_statec             C   s   | j j| j S )znThe current state of whichever role we are NOT playing. See
        :ref:`state-machine` for details.
        )rG   rS   rF   )rP   r.   r.   r/   their_state   s    zConnection.their_statec             C   s   | j tko| jS )N)rF   r   rO   )rP   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&t| | 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)rR   rG   rS   start_next_cyclerN   rO   r=   _respond_to_state_changes)rP   
old_statesr.   r.   r/   rW      s
    

zConnection.start_next_cycle)roler2   c             C   s&   t | jj}| j| | | d S )N)rR   rG   rS   Zprocess_errorrX   )rP   rZ   rY   r.   r.   r/   _process_error   s    zConnection._process_error)r1   r2   c             C   sT   t |tkr|jdkrtS t |tkrPt| jjkrPd|j  krHdk rPn ntS d S )Ne   r:   i,  )r<   r   r>   r   r   r   rG   Zpending_switch_proposals)rP   r1   r.   r.   r/   _server_switch_event   s    zConnection._server_switch_event)rZ   r1   r2   c             C   s\  t | jj}|tkrNt|tkrN|jdkr6| jt t	|j
drN| jt d }|tkrd| |}| j|t|| t|tkr|j| _|| jkrt|tttfkrtttttf |}|j| _t|ttfkrtttttf |s| j  t|tkrt|rd| _t|ttfkr*d| _|tkrLt|ttfkrLd| _| || d S )Ns   CONNECTs   upgradeTF)rR   rG   rS   r   r<   r   methodZprocess_client_switch_proposalr   r   r4   r   r!   r]   Zprocess_eventrN   rF   r   r   r   r
   r3   rM   r7   Zprocess_keep_alive_disabledr   rO   r   r   rX   )rP   rZ   r1   rY   Zserver_switch_eventr.   r.   r/   _process_event  s8    


zConnection._process_event.)rZ   r1   io_dictr2   c             C   sZ   | j j| }|tkrHttt| jtttt	f |\}}|t | | S |
||fS d S )N)rG   rS   r    r@   r   bytesrN   r
   r   r   get)rP   rZ   r1   r`   stateframing_typeargsr.   r.   r/   rH   4  s    "zConnection._get_io_object)rY   r1   r2   c             C   sH   | j || j kr"| | j|t| _| j|| j krD| | j|t| _d S )N)	rT   rA   rH   r&   rI   rU   rF   r   rJ   )rP   rY   r1   r.   r.   r/   rX   J  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.
        )ra   rK   rL   )rP   r.   r.   r/   trailing_dataU  s    	zConnection.trailing_data)datar2   c             C   s,   |r"| j rtd|  j|7  _n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)rL   RuntimeErrorrK   )rP   rg   r.   r.   r/   receive_data`  s
    'zConnection.receive_datac             C   s   | j }|tkr| jrtS |tks(|tkr,tS | jd k	s:t| | j}|d krx| jsx| jrxt	| jdrr| j
 }nt }|d krt}|S )Nread_eof)rU   r   rK   r*   r   r"   rJ   r=   rL   hasattrrj   r   r)   )rP   rc   r1   r.   r.   r/   _extract_next_receive_event  s    z&Connection._extract_next_receive_eventc          
   C   s   | j tkrtdy^|  }|ttgkr<| | jtt	| |tkrnt
| j| jkr`tddd| jrntd|S  tk
r } z&| | j t|tr|  n W dd}~X Y nX dS )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)rU   r   r$   rl   r)   r*   r_   rF   r   r   lenrK   rC   rL   BaseExceptionr[   
isinstancer#   Z!_reraise_as_remote_protocol_error)rP   r1   excr.   r.   r/   
next_event  s$    (



zConnection.next_eventc             C   s$   |  |}|dkrdS 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)rP   r1   	data_listr.   r.   r/   send  s    
zConnection.sendc             C   s   | j tkrtdy^t|tkr*| |}| j}| | j| t|t	krNdS |dk	sZt
g }|||j |S W n   | | j  Y nX dS )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)rT   r   r#   r<   r   &_clean_up_response_headers_for_sendingrI   r_   rA   r   r=   appendr[   )rP   r1   writerru   r.   r.   r/   rs     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)r[   rA   )rP   r.   r.   r/   send_failed'  s    zConnection.send_failed)responser2   c             C   s   t |tkst|j}d}tt| j}|dkr2d}t||\}}|dkrt|dg }| j	d ksh| j	dk rt|dg }| jdkrd}nt|dd	g}| j
jr|rtt|d
}|d |d t|d
t|}t||j|j|jdS )NFs   HEADs   GET)r;   zhttp/1.0s   content-lengths   1.1s   transfer-encodingTs   chunkeds
   connections
   keep-alives   close)r4   r>   r3   reason)r<   r   r=   r4   r   ra   rN   r@   r   rM   rG   
keep_alivesetr   discardaddsortedr>   r3   r|   )rP   r{   r4   Z
need_closeZmethod_for_choosing_headersrd   _r6   r.   r.   r/   rw   @  s0    	


z1Connection._clean_up_response_headers_for_sending)N)+r+   r,   r-   __doc__!DEFAULT_MAX_INCOMPLETE_EVENT_SIZEr	   r%   r?   rQ   propertyr   rS   rT   rU   boolrV   rW   r[   r   r   r]   r_   r
   r   r'   r   r   rH   rX   r   ra   rf   ri   r)   r*   rl   rq   rv   r   rs   rz   r   rw   r.   r.   r.   r/   r(      s<   # 
2

0  A!N)8typingr   r   r   r   r   r   r   r	   r
   Z_eventsr   r   r   r   r   r   r   _headersr   r   r   _readersr   r   Z_receivebufferr   _stater   r   r   r   r   r   r   r    r!   r"   Z_utilr#   r$   r%   _writersr&   r'   __all__r)   r*   r   r   r7   ra   strr?   r@   r(   r.   r.   r.   r/   <module>   s   ,$	0

&8