o
    .jV                     @  s  d dl m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mZmZ ej	Zzd dlmZ W n eyD   eZY nw zejjZW n eyV   eZY nw ejrld dlZd dlmZ dd	lmZmZ dddZe du ZG dd dZG dd deZ dddZ!dZ"dS )    )annotationsN   )timeout)open_dgram_connectionDatagramReaderDatagramWriter)TimeoutError)Literal   )_TYPE_PEER_CERT_RET_TYPE_PEER_CERT_RET_DICTreturnboolc                  C  s@   dd l } |  dkr|  d d dkrt|  d dkS dS )Nr   Windows   )37   T)platformsystempython_version_tupleint)r    r   X/home/thesage/.local/lib/python3.10/site-packages/urllib3_future/contrib/ssa/__init__.py)_can_shutdown_and_close_selector_loop_bug!   s    r   Fc                   @  s,  e Zd ZdZejejddfdTddZdUddZdVddZ	dVddZ
dVddZejdkr0dWddZdXd"d#ZejdYd$d%ZejdZd(d%Z	d[d\d)d%Zd]d+d,Zd^d/d0Zddd1d_d9d:Zd`dad=d>Zd`dad?d@ZdbdAdBZdcdEdFZdcdGdHZdcdIdJZd[dddKdLZdedMdNZdfdPdQZdgdRdSZdS )hAsyncSocketa  
    This class is brought to add a level of abstraction to an asyncio transport (reader, or writer)
    We don't want to have two distinct code (async/sync) but rather a unified and easily verifiable
    code base.

    'ssa' stands for Simplified - Socket - Asynchronous.
    r   Nfamilysocket.AddressFamilytypesocket.SocketKindprotor   fileno
int | Noner   Nonec                 C  s   || _ || _|| _|| _d| _t | _tj| j | j| j|d| _	| j	
d d | _d | _t | _t | _d | _d | _d| _d | _d S )NF)r   r   r!   r"   r   )r   r   r!   _fileno_connect_calledasyncioEvent_establishedsocket_sock
settimeout_writer_reader	Semaphore_writer_semaphore_reader_semaphore_addr_external_timeout_tls_in_tls_ech_config)selfr   r   r!   r"   r   r   r   __init__>   s$   



zAsyncSocket.__init__c                 C  s   | j d ur| j S | j S N)r%   r+   r"   r6   r   r   r   r"   a   s   zAsyncSocket.filenoc              	     s   | j rd S | jd u rd S z
| jdd u}W n ty"   d}Y nw |r3tdI d H  | jj  z+td4 I d H  | j	 I d H  W d   I d H  W d S 1 I d H sWw   Y  W d S  t
yh   Y d S w )N
ssl_objectFr   r   )r&   r-   get_extra_infoAttributeErrorr'   sleep	transportabortr   wait_closedOSError)r6   is_sslr   r   r   wait_for_closed   s(   
2zAsyncSocket.wait_for_closec                 C  s  | j dur%z| j   W n ty$   d| _| j  d| _ d| _Y dS w t}|s>t	 dkr>t
tdr>tt tjr>d}zd}d}d}t
| jdrz| jtj d}W n[ ty   d}z	| j  d}W nF ty   ztj| j d}W n ttfy   Y n'w z z
|tj d}W n ty   tdt Y nw W |  n|  w Y nw Y nw t| jtjrt
| jd	r|s|sz	| j  d}W n ttfy   Y nw |r|st
| jd
r|sz| jj  W n tttfy   Y nw W nG tyA   t| jtjrz| j  W n- tttfy   Y n!w t
| jd
r?|s?z| jj  W n tttfy>   Y nw Y nw d| _| j  dS )ziThe closing procedure is a real challenge. There's a ton of edge cases. Act carefully around this method.NFr   SelectorEventLoopTshutdown)r"   zurllib3-future is unable to properly close your async socket. This mean that you are probably using an asyncio implementation like uvloop that does not support shutdown() or/and close() on the socket transport. This will lead to unclosed socket (fd).closer+   )r-   rF   r<   r&   r)   clearr.   !_CPYTHON_SELECTOR_CLOSE_BUG_EXISTr   r   hasattrr'   
isinstanceget_running_looprD   r+   rE   r*   SHUT_RD	TypeErrorr"   rA   
ValueErrorwarningswarnResourceWarningdetach)r6   edge_case_close_bug_existuvloop_edge_case_bugshutdown_calledclose_calleddirect_sockr   r   r   rF      s   







zAsyncSocket.closec                   s   | j  I d H  d S r8   )r)   waitr9   r   r   r   wait_for_readiness      zAsyncSocket.wait_for_readinesswin32controloption!int | tuple[int, int, int] | boolc                 C  s   | j ||S r8   )r+   ioctl)r6   r\   r]   r   r   r   r_      s   zAsyncSocket.ioctl_AsyncSocket__level_AsyncSocket__optname_AsyncSocket__valueint | bytesc                 C  s   | j ||| d S r8   )r+   
setsockopt)r6   r`   ra   rb   r   r   r   rd     s   zAsyncSocket.setsockoptc                 C     d S r8   r   )r6   r`   ra   r   r   r   
getsockopt     zAsyncSocket.getsockoptbuflenbytesc                 C  re   r8   r   r6   r`   ra   rh   r   r   r   rf   	  rg   c                 C  s&   |d u r| j ||S | j |||S r8   )r+   rf   rj   r   r   r   rf     s   r   c                 C  s
   | j du S )NF)r&   r9   r   r   r   should_connect     
zAsyncSocket.should_connectaddr+tuple[str, int] | tuple[str, int, int, int]c              
     s  | j rtdd| _ t dkrIddlm}m} |d d \}}||sI||sIt j	||| j
| jdI d H }|sCtd| |d d	 }| jd urz-t| j4 I d H  t | j|I d H  W d   I d H  n1 I d H suw   Y  W n9 tttfy } zd
| _ t|d }~w ty   tdw zt | j|I d H  W n ty   tdw | jtjks| jd	krtj| jdI d H \| _| _n| jtjkrt| jdI d H \| _| _| jd usJ | jd| j| _|| _| j !  d S )Nz>attempted to connect twice on a already established connectionTr   r   )is_ipv4is_ipv6)r   r   zunable to resolve hostname r   r   Fz@Likely FD Kernel/Loop Racing Allocation Error. You should retry.)sockr*   )"r&   rA   r   r   resolver.utilsro   rp   r'   rK   getaddrinfor   r   r*   gaierrorr3   r   sock_connectr+   FutureTimeoutErrorAsyncioTimeoutErrorr   StandardTimeoutErrorRuntimeErrorConnectionErrorSOCK_STREAMopen_connectionr.   r-   
SOCK_DGRAMr   r;   r2   r)   set)r6   rm   ro   rp   hostportreser   r   r   connect  sb   
(zAsyncSocket.connectserver_hostnamessl_handshake_timeoutctxssl.SSLContextr   
str | Noner   float | NoneSSLAsyncSocketc          	        sT  | j  I d H  | j   z
ttjjdd W n	 ty!   Y nw ztjj}t|ds3dd }||_	W n	 ty=   Y nw | j
tjkr| jd usKJ t| jtjsTJ | jj}| j I d H  | jjj| jj||d||dI d H }|d u r| jr}tdtd	|| j_| jj}| j|_||_|d
d u|_|| _ntd| j   t| _| S )N_start_tls_compatibleT_force_closec                 S  sF   d| _ | jd ur!z	| j| W d S  ty    | j  Y d S w d S )NT)_closed_ssl_protocol_abortrM   )r6   excr   r   r   r   m  s   
z-AsyncSocket.wrap_socket.<locals>._force_closeF)server_sider   r   zTAsyncio TLS-in-TLS failed. The transport failed silently during inner TLS handshake.zMAsyncio start TLS failed. The transport failed silently during TLS handshake.
sslcontextzUnsupported socket type) r)   rX   rG   setattrr'   sslproto_SSLProtocolTransportr<   rI   r   r   r*   r{   r-   rJ   StreamWriter	_protocoldrain_loop	start_tls
_transportr4   rA   r>   _stream_writerr;   	_over_ssl_tls_ctxry   r~   r   	__class__)	r6   r   r   r   _ssl_tpr   protocolnew_transportr>   r   r   r   wrap_socketR  sh   

		
zAsyncSocket.wrap_socketsizebytes | list[bytes]c              
     s&  |dkrd}| j dusJ | j s| j I dH  | j I dH  zi| jdur}z2t| j4 I dH  | j j|dI dH W  d  I dH  W W | j	  S 1 I dH sUw   Y  W n! t
ttfym } zt|d}~w ty| } zt |d}~ww | j j|dI dH W | j	  S | j	  w )ae  Receive data from the socket.

        Returns ``bytes`` for a single datagram (or stream chunk), or
        ``list[bytes]`` when GRO / batch-receive delivered multiple
        coalesced datagrams in one syscall.  The caller can then feed
        all segments to the QUIC state-machine in a tight loop before
        probing, avoiding per-datagram overhead.r   i   N)n)r.   r)   is_setrX   r1   acquirer3   r   readreleaserv   rw   r   rx   rA   ConnectionResetError)r6   r   r   r   r   r   recv  s0   

zAsyncSocket.recvc                   s   | j |dI dH S )MJust an alias for recv(), it is needed due to our custom AsyncSocks override.)r   Nr   )r6   r   r   r   r   
read_exact  s   zAsyncSocket.read_exactc                   s   |   I dH S )r   Nr   r9   r   r   r   r     s   zAsyncSocket.readdata,bytes | bytearray | memoryview | list[bytes]c                   s   | j d usJ | j I d H  | j I d H  z!z| j | | j  I d H  W n ty1    w W | j  d S | j  w r8   )	r-   r)   rX   r0   r   writer   	Exceptionr   r6   r   r   r   r   sendall  s   zAsyncSocket.sendallc                   s   |  |I dH  dS )zPJust an alias for sendall(), it is needed due to our custom AsyncSocks override.Nr   r   r   r   r   	write_all  s   zAsyncSocket.write_allc                   s   |  |I d H  d S r8   r   r   r   r   r   send  rZ   zAsyncSocket.sendc                 C  s
   || _ d S r8   r3   )r6   rb   r   r   r   r,     rl   zAsyncSocket.settimeoutc                 C     | j S r8   r   r9   r   r   r   
gettimeout  s   zAsyncSocket.gettimeouttuple[str, int]c                 C  
   | j  S r8   )r+   getpeernamer9   r   r   r   r     rl   zAsyncSocket.getpeernamec                 C  s   | j | d S r8   )r+   bind)r6   rm   r   r   r   r     s   zAsyncSocket.bind)
r   r   r   r    r!   r   r"   r#   r   r$   )r   r   )r   r$   )r\   r   r]   r^   r   r$   )r`   r   ra   r   rb   rc   r   r$   )r`   r   ra   r   r   r   )r`   r   ra   r   rh   r   r   ri   r8   )r`   r   ra   r   rh   r#   r   rc   r   r   )rm   rn   r   r$   r   r   r   r   r   r   r   r   )r   )r   r   r   r   )r   r   )r   r   r   r$   )rb   r   r   r$   )r   r   )r   r   )rm   r   r   r$   ) __name__
__module____qualname____doc__r*   AF_INETr{   r7   r"   rC   rF   rY   sysr   r_   rd   typingoverloadrf   rk   r   r   r   r   r   r   r   r   r,   r   r   r   r   r   r   r   r   5   sF    

#

"
s




@T





r   c                      s   e Zd ZU ded< ded< ej	d)d*d
dZejd+ddZd,d-ddZd.ddZed/ddZ	d.ddZ
ed0ddZed/ddZd1dd Zd!d!d"d2 fd'd(Z  ZS )3r   r   r   r   r4   .binary_formLiteral[False]r   _TYPE_PEER_CERT_RET_DICT | Nonec                 C  re   r8   r   r6   r   r   r   r   getpeercert  s   zSSLAsyncSocket.getpeercertLiteral[True]bytes | Nonec                 C  re   r8   r   r   r   r   r   r     rg   Fr   c                 C  s   | j j|dS )N)r   )sslobjr   r   r   r   r   r     s   r   c                 C  r   r8   )r   selected_alpn_protocolr9   r   r   r   r     rl   z%SSLAsyncSocket.selected_alpn_protocolssl.SSLSocket | ssl.SSLObjectc                 C  s*   | j d ur| j d}|d ur|S td)Nr:   zC"ssl_object" could not be extracted from this SslAsyncSock instance)r-   r;   ry   )r6   r   r   r   r   r     s   
zSSLAsyncSocket.sslobjc                 C  r   r8   )r   versionr9   r   r   r   r     rl   zSSLAsyncSocket.versionc                 C  s   | j jS r8   )r   contextr9   r   r   r   r     s   zSSLAsyncSocket.contextc                 C  r   r8   )r   r9   r   r   r   _sslobj  s   zSSLAsyncSocket._sslobjtuple[str, str, int] | Nonec                 C  r   r8   )r   cipherr9   r   r   r   r     rl   zSSLAsyncSocket.cipherNr   r   r   r   r   c                  s    d| _ t j|||dI d H S )NTr   )r4   superr   )r6   r   r   r   r   r   r   r     s   zSSLAsyncSocket.wrap_socket).)r   r   r   r   )r   r   r   r   )F)r   r   r   r   )r   r   )r   r   )r   r   )r   r   r   )r   r   r   __annotations__r   r   r   r   propertyr   r   r   r   r   r   __classcell__r   r   r   r   r     s*   
 


r   c                  C  sX   ddl } |  dkr*|  dkr*zddl}W n
 ty    Y dS w t|dr(dS dS dS )u  A bug exist in PyPy asyncio implementation that prevent us to use a DGRAM socket.
    This piece of code inform us, potentially, if PyPy has fixed the winapi implementation.
    See https://github.com/pypy/pypy/issues/4008 and https://github.com/jawah/niquests/pull/87

    The stacktrace look as follows:
    File "C:\hostedtoolcache\windows\PyPy.10.13\Libsyncio\windows_events.py", line 594, in connect
    _overlapped.WSAConnect(conn.fileno(), address)
        AttributeError: module '_overlapped' has no attribute 'WSAConnect'
    r   Nr   PyPyF
WSAConnectT)r   r   python_implementation_overlappedImportErrorrI   )r   r   r   r   r   _has_complete_support_dgram+  s   

r   )r   r   r   r   )#
__future__r   r'   r   r*   r   r   rO   _timeoutr   _gror   r   r   rx   concurrent.futuresr   rv   r   
exceptionsrw   r<   TYPE_CHECKINGssltyping_extensionsr	   _typingr   r   r   rH   r   r   r   __all__r   r   r   r   <module>   sB    

   ;
>