Ë
    "ïàj#;  ã                   óâ  — d Z ddlZddlZddlZddlZddlZddlZddlmZ ddl	m
Z
 ddlmZ ddlmZ 	 ddlZd„ Z G d„ d«      Z G d„ d«      Z y# e$ r™ 	 ddlZdd	lmZmZ ej,                  j.                  Zej2                  j4                  ej2                  j6                  ej2                  j6                  ge_        ej2                  j:                  e_        d
„ Zn# e$ r d„ ZY nw xY wY Œ²w xY w)z%Utilities to manage open connections.é    N)Úsuppressé   )Úerrors)Ú
IS_WINDOWS)ÚMakeFilec                 óØ   — | j                  «       }t        j                  |t        j                  «      }t        j                  |t        j                  |t        j                  z  «       y)z4Mark the given socket fd as non-inheritable (POSIX).N)ÚfilenoÚfcntlÚF_GETFDÚF_SETFDÚ
FD_CLOEXEC)ÚsockÚfdÚ	old_flagss      úB/srv/dav/.venv/lib/python3.12/site-packages/cheroot/connections.pyÚprevent_socket_inheritancer   -   s@   € à�[‰[‹]ˆÜ—K‘K ¤E§M¡MÓ2ˆ	Ü�‰�BœŸ™ y´5×3CÑ3CÑ'CÕDó    )ÚWinErrorÚwindllc                 óN   — t        | j                  «       dd«      s
t        «       ‚y)z6Mark the given socket fd as non-inheritable (Windows).r   r   N)Ú_SetHandleInformationr	   r   ©r   s    r   r   r   '   s!   € ä(¨¯©«¸¸1Ô=Ü“jÐ ð >r   c                  ó   — y)ztStub inheritance prevention.

            Dummy function, since neither fcntl nor ctypes are available.
            N© r   s    r   r   r       s   � r   c                   óH   — e Zd ZdZd„ Zd„ Zed„ «       Zd
d„Zd„ Z	d
d„Z
d	„ Zy)Ú_ThreadsafeSelectoraí  Thread-safe wrapper around a DefaultSelector.

    There are 2 thread contexts in which it may be accessed:
      * the selector thread
      * one of the worker threads in workers/threadpool.py

    The expected read/write patterns are:
      * :py:func:`~iter`: selector thread
      * :py:meth:`register`: selector thread and threadpool,
        via :py:meth:`~cheroot.workers.threadpool.ThreadPool.put`
      * :py:meth:`unregister`: selector thread only

    Notably, this means :py:class:`_ThreadsafeSelector` never needs to worry
    that connections will be removed behind its back.

    The lock is held when iterating or modifying the selector but is not
    required when :py:meth:`select()ing <selectors.BaseSelector.select>` on it.
    c                 óh   — t        j                  «       | _        t        j                  «       | _        y ©N)Ú	selectorsÚDefaultSelectorÚ	_selectorÚ	threadingÚLockÚ_lock©Úselfs    r   Ú__init__z_ThreadsafeSelector.__init__H   s    € Ü"×2Ñ2Ó4ˆŒÜ—^‘^Ó%ˆ�
r   c                 ó”   — | j                   5  t        | j                  j                  «       xs i «      cd d d «       S # 1 sw Y   y xY wr   )r$   Úlenr!   Úget_mapr%   s    r   Ú__len__z_ThreadsafeSelector.__len__L   s8   € Ø�Z‰Zñ 	7Ü�t—~‘~×-Ñ-Ó/Ò5°2Ó6÷	7÷ 	7ò 	7ús	   �'>¾Ac              #   óÒ   K  — | j                   5  | j                  j                  «       xs i }|j                  «       D ]  \  }\  }}}}||f–— Œ 	 ddd«       y# 1 sw Y   yxY w­w)z2Retrieve connections registered with the selector.N)r$   r!   r*   Úitems)r&   ÚmappingÚ_Úsock_fdÚconns        r   Úconnectionsz_ThreadsafeSelector.connectionsP   sg   è ø€ ð �Z‰Zñ 	&Ø—n‘n×,Ñ,Ó.Ò4°"ˆGØ,3¯M©M«Oò &Ñ(�Ñ(�A�w  4Ø �oÓ%ñ&÷	&÷ 	&ñ 	&üs   ‚A'�AAÁ	A'ÁA$Á A'Nc                 ó€   — | j                   5  | j                  j                  |||«      cddd«       S # 1 sw Y   yxY w)z'Register ``fileobj`` with the selector.N)r$   r!   Úregister)r&   ÚfileobjÚeventsÚdatas       r   r4   z_ThreadsafeSelector.registerX   s8   € à�Z‰Zñ 	BØ—>‘>×*Ñ*¨7°F¸DÓA÷	B÷ 	Bò 	Bús   �4´=c                 ó|   — | j                   5  | j                  j                  |«      cddd«       S # 1 sw Y   yxY w)z)Unregister ``fileobj`` from the selector.N)r$   r!   Ú
unregister)r&   r5   s     r   r9   z_ThreadsafeSelector.unregister]   s0   € à�Z‰Zñ 	6Ø—>‘>×,Ñ,¨WÓ5÷	6÷ 	6ò 	6ús   �2²;c                 óH   — d„ | j                   j                  |¬«      D «       S )z©Return socket fd and data pairs from selectors.select call.

        Returns entries ready to read in the form:
            (socket_file_descriptor, connection)
        c              3   óR   K  — | ]  \  }}|j                   |j                  f–— Œ! y ­wr   )r   r7   )Ú.0Úkeyr/   s      r   ú	<genexpr>z-_ThreadsafeSelector.select.<locals>.<genexpr>h   s)   è ø€ ò 
á��Qð �V‰V�S—X‘XÔñ
ùs   ‚%'©Útimeout)r!   Úselect)r&   r@   s     r   rA   z_ThreadsafeSelector.selectb   s&   € ñ
àŸ.™.×/Ñ/¸Ð/Ó@ô
ð 	
r   c                 óz   — | j                   5  | j                  j                  «        ddd«       y# 1 sw Y   yxY w)zClose the selector.N)r$   r!   Úcloser%   s    r   rC   z_ThreadsafeSelector.closem   s.   € à�Z‰Zñ 	#Ø�N‰N× Ñ Ô"÷	#÷ 	#ñ 	#ús   �1±:r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r'   r+   Úpropertyr2   r4   r9   rA   rC   r   r   r   r   r   4   s:   „ ñò&&ò7ð ñ&ó ð&óBò
6ó
	
ó#r   r   c                   óf   — e Zd ZdZd„ Zd„ Zd„ Zd„ Zd„ Zd„ Z	d„ Z
d	„ Zd
„ Zed„ «       Zed„ «       Zy)ÚConnectionManagerz€Class which manages HTTPConnection objects.

    This is for connections which are being kept-alive for follow-up requests.
    c                 óÔ   — d| _         d| _        || _        t        «       | _        | j                  j                  |j                  j                  «       t        j                  |¬«       y)z¹Initialize ConnectionManager object.

        Args:
            server (cheroot.server.HTTPServer): web server object
                that uses this ConnectionManager instance.
        F©r7   N)
Ú_servingÚ_stop_requestedÚserverr   r!   r4   Úsocketr	   r   Ú
EVENT_READ)r&   rO   s     r   r'   zConnectionManager.__init__y   sW   € ð ˆŒØ$ˆÔàˆŒÜ,Ó.ˆŒà�‰×ÑØ�M‰M× Ñ Ó"Ü× Ñ Øð 	 õ 	
r   c                 ó*  — t        j                   «       |_        |j                  j                  «       r| j                  j                  |«       y| j                  j                  |j                  j                  «       t        j                  |¬«       y)z¬Put idle connection into the ConnectionManager to be managed.

        :param conn: HTTP connection to be managed
        :type conn: cheroot.server.HTTPConnection
        rL   N)ÚtimeÚ	last_usedÚrfileÚhas_datarO   Úprocess_connr!   r4   rP   r	   r   rQ   )r&   r1   s     r   ÚputzConnectionManager.putŒ   sh   € ô Ÿ™›ˆŒð �:‰:×ÑÔ Ø�K‰K×$Ñ$ TÕ*à�N‰N×#Ñ#Ø—‘×"Ñ"Ó$Ü×$Ñ$Øð $õ r   c                 ó
  — | j                   j                  D ��cg c]'  \  }}|| j                  k7  r|j                  |k  r||f‘Œ) }}}|D ]0  \  }}| j                   j	                  |«       |j                  «        Œ2 yc c}}w )aI  Expire least recently used connections.

        :param threshold: Connections that have not been used within this \
                          duration (in seconds), are considered expired and \
                          are closed and removed.
        :type threshold: float

        This should be called periodically.
        N)r!   r2   rO   rT   r9   rC   )r&   Ú	thresholdr0   r1   Útimed_out_connectionss        r   Ú_expirezConnectionManager._expirež   s€   € ð $(§>¡>×#=Ñ#=÷!
á�˜$Ø�t—{‘{Ò" t§~¡~¸	Ò'Að �dŠOð!
Ðñ !
ð
 3ò 	‰MˆG�TØ�N‰N×%Ñ% gÔ.Ø�J‰J�Lñ	ùó!
s   š,A?c                 óp   — d| _         | j                  r#t        j                  d«       | j                  rŒ"yy)z^Stop the selector loop in run() synchronously.

        May take up to half a second.
        Tg{®Gáz„?N)rN   rM   rS   Úsleepr%   s    r   ÚstopzConnectionManager.stop³   s(   € ð
  $ˆÔØ�mŠmÜ�J‰J�tÔð �m�mr   c                 ó\   — d| _         	 | j                  |«       d| _         y# d| _         w xY w)aÚ  Run the connections selector indefinitely.

        Args:
            expiration_interval (float): Interval, in seconds, at which
                connections will be checked for expiration.

        Connections that are ready to process are submitted via
        self.server.process_conn()

        Connections submitted for processing must be `put()`
        back if they should be examined again for another request.

        Can be shut down by calling `stop()`.
        TFN)rM   Ú_run)r&   Úexpiration_intervals     r   ÚrunzConnectionManager.run¼   s,   € ð ˆŒð	"Ø�I‰IÐ)Ô*à!ˆD�Mø˜EˆD�Mús   ‰" ¢	+c                 óº  — t        j                   «       }t        rt        |d«      }n|}| j                  �s	 | j                  j                  |¬«      }|D ]�  \  }}|| j                  u rD| j                  | j                  j                  «      }|€Œ<| j                  j                  |«       ŒX| j                  j                  |«       | j                  j                  |«       Œ� t        j                   «       }||z
  |kD  r+| j                  || j                  j                  z
  ¬«       |}| j                  s�Œyy# t        $ r | j                  «        Y �Œ/w xY w)a  Run connection handler loop until stop was requested.

        :param expiration_interval: Interval, in seconds, at which \
                                    connections will be checked for \
                                    expiration.
        :type expiration_interval: float

        Use ``expiration_interval`` as ``select()`` timeout
        to assure expired connections are closed in time.

        On Windows cap the timeout to 0.05 seconds
        as ``select()`` does not return when a socket is ready.
        gš™™™™™©?r?   N)rZ   )rS   r   ÚminrN   r!   rA   ÚOSErrorÚ_remove_invalid_socketsrO   Ú_from_server_socketrP   rW   r9   r\   r@   )	r&   rb   Úlast_expiration_checkÚselect_timeoutÚactive_listr0   r1   Únew_connÚnows	            r   ra   zConnectionManager._runÑ   s/  € ô !%§	¡	£ÐÝô !Ð!4°dÓ;‰Nà0ˆNà×&Ó&ðØ"Ÿn™n×3Ñ3¸NÐ3ÓK�ð
 "-ò 
3‘�˜Ø˜4Ÿ;™;Ñ&à#×7Ñ7¸¿¹×8JÑ8JÓK�HØÑ+ØŸ™×0Ñ0°Õ:ð —N‘N×-Ñ-¨gÔ6Ø—K‘K×,Ñ,¨TÕ2ð
3ô —)‘)“+ˆCØÐ+Ñ+Ð/BÒBØ—‘ s¨T¯[©[×-@Ñ-@Ñ'@�ÔAØ(+Ð%ð- ×&Ö&øô ò Ø×,Ñ,Ô.Úðús   ¸D= Ä=EÅEc                 ó„  — g }| j                   j                  D ]*  \  }}|| j                  u rŒ	 t        j                  |«       Œ, |D ]H  \  }}| j                   j                  |«       t        t
        «      5  |j                  «        ddd«       ŒJ y# t
        $ r |j                  ||f«       Y Œ™w xY w# 1 sw Y   ŒwxY w)a  Clean up the resources of any broken connections.

        This method attempts to detect any connections in an invalid state,
        unregisters them from the selector and closes the file descriptors of
        the corresponding network sockets where possible.
        N)
r!   r2   rO   ÚosÚfstatrf   Úappendr9   r   rC   )r&   Úinvalid_connsr0   r1   s       r   rg   z)ConnectionManager._remove_invalid_sockets  s½   € ð ˆØ!Ÿ^™^×7Ñ7ò 	6‰MˆG�TØ�t—{‘{Ñ"Øð6Ü—‘˜Õ!ð	6ð +ò 	‰MˆG�TØ�N‰N×%Ñ% gÔ.ô œ'Ó"ñ Ø—
‘
”÷ð ñ	øô ò 6Ø×$Ñ$ g¨t _Ö5ð6ú÷ð ús   ¯BÁ8B6ÂB3Â2B3Â6B?	c                 óN  — 	 |j                  «       \  }}| j                  j                  d   r!| j                  j                  dxx   dz  cc<   t        |«       t	        |d«      r%|j                  | j                  j                  «       t        }i }| j                  j                  �z	 | j                  j                  j                  |«      \  }}| j                  j                  j0                  }t	        |d«      r%|j                  | j                  j                  «       | j                  j3                  | j                  ||«      }t5        | j                  j6                  t8        t:        f«      s7|€!t        |j=                  «       «      dk(  rd}nd}|d   |_        |d   |_         ||_!        |S # t        j                  $ r+}| j                  j                  d|›d|›�«       Y d }~y d }~wt        j                  $ rÕ}| j                  j                  d|›d|›�«       d}d	| j                  j                  z  d
t        |«      z  d|g}	 ||dt         j"                  «      }
	 |
j%                  dj'                  |	«      j)                  d«      «       n6# t*        $ r*}|j,                  d   t        j.                  vr‚ Y d }~nd }~ww xY wY d }~y d }~ww xY w# tD        j                  $ r Y y t*        $ r¬}| j                  j                  d   r!| j                  j                  dxx   dz  cc<   |j,                  d   t        jF                  v rY d }~y |j,                  d   t        jH                  v rY d }~y |j,                  d   t        j.                  v rY d }~y ‚ d }~ww xY w)NÚEnabledÚAcceptsr   Ú
settimeoutzClient uF    lost â€” peer dropped the TLS connection suddenly, during handshake: uŠ    attempted to speak plain HTTP into a TCP connection configured for TLS-only traffic â€” trying to send back a plain HTTP error response: zUThe client sent a plain HTTP request, but this server only speaks HTTPS on this port.z%s 400 Bad Request
zContent-Length: %s
zContent-Type: text/plain

ÚwbÚ z
ISO-8859-1r   é   )z0.0.0.0r   )z::r   zSocket Errors)%ÚacceptrO   Ústatsr   Úhasattrrv   r@   r   Ússl_adapterÚwrapr   ÚFatalSSLAlertÚ	error_logÚ
NoSSLErrorÚprotocolr)   ÚioÚDEFAULT_BUFFER_SIZEÚwriteÚjoinÚencoderf   ÚargsÚsocket_errors_to_ignoreÚmakefileÚConnectionClassÚ
isinstanceÚ	bind_addrÚstrÚbytesÚgetsocknameÚremote_addrÚremote_portÚssl_envrP   Úsocket_error_eintrÚsocket_errors_nonblocking)r&   Úserver_socketÚsÚaddrÚmfr“   Útls_connection_drop_errorÚhttp_over_https_errÚmsgÚbufÚwfileÚexr1   s                r   rh   z%ConnectionManager._from_server_socket  s-  € ð^	Ø#×*Ñ*Ó,‰GˆAˆtØ�{‰{× Ñ  Ò+Ø—‘×!Ñ! )Ó,°Ñ1Ó,Ü& qÔ)Ü�q˜,Ô'Ø—‘˜TŸ[™[×0Ñ0Ô1äˆBØˆGà�{‰{×&Ñ&Ð2ð! Ø!%§¡×!8Ñ!8×!=Ñ!=¸aÓ!@‘J�A�wðB —[‘[×,Ñ,×5Ñ5�ä˜1˜lÔ+Ø—L‘L §¡×!4Ñ!4Ô5à—;‘;×.Ñ.¨t¯{©{¸A¸rÓBˆDä˜dŸk™k×3Ñ3´c¼5°\ÔBð �<ä˜1Ÿ=™=›?Ó+¨qÒ0à-™ð  )˜Ø#'¨¡7�Ô Ø#'¨¡7�Ô à"ˆDŒLØˆKøôm ×+Ñ+ò  Ø—K‘K×)Ñ)Ø! $ ð *Bà4Ð7ð9ôô
  ûÜ×(Ñ(ò  Ø—K‘K×)Ñ)Ø! $ ð *Lð /Ð1ð3ôðFð ð
 1°4·;±;×3GÑ3GÑGØ0´3°s³8Ñ;Ø:Øð	�Cñ ˜q $¬×(>Ñ(>Ó?�Eð"ØŸ™ B§G¡G¨C£L×$7Ñ$7¸Ó$EÕFøÜ"ò "ØŸ7™7 1™:¬V×-KÑ-KÑKØ!ô Lûð"úô  ûð1 ûôb �~‰~ò 	ñ Üò 	Ø�{‰{× Ñ  Ò+Ø—‘×!Ñ! /Ó2°aÑ7Ó2Ø�w‰w�q‰zœV×6Ñ6Ñ6ô Ø�w‰w�q‰zœV×=Ñ=Ñ=ô Ø�w‰w�q‰zœV×;Ñ;Ñ;ô Øûð'	ús™   ‚B'K Â*(F4 ÃC!K Æ4KÇ!G-Ç(K Ç-KÈA$KÉ(/JÊKÊ	KÊ! KËKËKËKËK ËKËK ËN$Ë0N$Ë8ANÍNÍ:NÎNÎN$c                 ó²   — | j                   j                  D ]$  \  }}|| j                  usŒ|j                  «        Œ& | j                   j                  «        y)z Close all monitored connections.N)r!   r2   rO   rC   )r&   r/   r1   s      r   rC   zConnectionManager.close€  sF   € à—~‘~×1Ñ1ò 	‰GˆAˆtØ˜4Ÿ;™;Ò&Ø—
‘
•ð	ð 	�‰×ÑÕr   c                 ó2   — t        | j                  «      dz
  S )zÑReturn the current number of connections.

        Includes all connections registered with the selector,
        minus one for the server socket, which is always registered
        with the selector.
        r   )r)   r!   r%   s    r   Ú_num_connectionsz"ConnectionManager._num_connections‡  s   € ô �4—>‘>Ó" QÑ&Ð&r   c                 óX   — | j                   j                  }|du xs | j                  |k  S )z>Flag whether it is allowed to add a new keep-alive connection.N)rO   Úkeep_alive_conn_limitr¢   )r&   Úka_limits     r   Úcan_add_keepalive_connectionz.ConnectionManager.can_add_keepalive_connection‘  s.   € ð —;‘;×4Ñ4ˆØ˜4ÐÒC 4×#8Ñ#8¸8Ñ#CÐCr   N)rD   rE   rF   rG   r'   rX   r\   r_   rc   ra   rg   rh   rC   rH   r¢   r¦   r   r   r   rJ   rJ   s   sa   „ ñò

ò&ò$ò*ò"ò*3,òjò2_òBð ñ'ó ð'ð ñDó ñDr   rJ   )!rG   rƒ   ro   r   rP   r"   rS   Ú
contextlibr   rx   r   Ú_compatr   rŠ   r   r
   r   ÚImportErrorÚctypes.wintypesÚctypesr   r   Úkernel32ÚSetHandleInformationr   ÚwintypesÚHANDLEÚDWORDÚargtypesÚBOOLÚrestyper   rJ   r   r   r   ú<module>r´      sÝ   ðÙ +ã 	Û 	Û Û Û Û Ý å Ý Ý ð!EÛò8E÷<#ñ <#÷~bDò bDøðC ò !ð!Ûß+à &§¡× DÑ DÐà�O‰O×"Ñ"Ø�O‰O×!Ñ!Ø�O‰O×!Ñ!ð*
ÐÔ&ð
 )/¯©×(<Ñ(<ÐÔ%ó	!øð ò ô	ðüð!ús6   ´A ÁC.ÁBCÃC.ÃC(Ã%C.Ã'C(Ã(C.Ã-C.