o
    .jX                     @  s
  U d Z 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 dZded	< d
Zded< edZded< edZded< dZded< dZded< dZded< dZded< dZded< dZded< dZded< ejdkZded< ejd kZded!< ejZded"< e ed#dZ!ded$< e ed%dZ"ded&< e#ed're$ej%ndZ&ded(< e'd)d* e ed+de ed,dfD Z(ded-< d.Z)ded/< dZd4d5Z*d[d8d9Z+d[d:d;Z,d\d?d@Z-d]dFdGZ.d^dIdJZ/d_dMdNZ0G dOdP dPej1Z2	Qd`dadXdYZ3dS )bz:
Custom asyncio DatagramTransport with optimized UDP I/O.
    )annotationsN)deque   )UdpSocketStateh   ztyping.FinalUDP_GROg   UDP_SEGMENTz=H_UINT16z@i	_GRO_CMSGi  _DEFAULT_GRO_BUFi   _MAX_GRO_BUF   _HIGH_WATERMARKi @  _LOW_WATERMARK@   _GSO_MAX_SEGMENTSi  _GSO_MAX_PAYLOAD    _RECV_BURST_LIMITlinux	_IS_LINUXwin32_IS_UNIX_SOL_UDP	MSG_TRUNC
_MSG_TRUNC
MSG_CTRUNC_MSG_CTRUNC
CMSG_SPACE_ANCBUFSIZEc                 c  s    | ]	}|d ur|V  qd S N ).0er"   r"   K/home/thesage/.local/lib/python3.10/site-packages/qh3/asyncio/_transport.py	<genexpr>7   s    r&   EMSGSIZEWSAEMSGSIZE_MSG_TOO_BIG_ERRNOSi8'  _WSAEMSGSIZE_WINERRORexcOSErrorreturnboolc                 C  s   | j tv rdS t| ddtkS )z@Return True when *exc* means the datagram exceeded the path MTU.TwinerrorN)errnor)   getattrr*   )r+   r"   r"   r%   _is_msg_too_bigE   s   
r2   socksocket.socketc                 C  s>   t sdS z| ttd | ttdkW S  ty   Y dS w )z?Enable UDP GRO on *sock*. Returns True on success (Linux only).F   )r   
setsockoptr   r   
getsockoptr,   r3   r"   r"   r%   
enable_groL      r9   c                 C  s>   t sdS z| ttd t| ttW S  ty   Y dS w )zFReturn True if the kernel supports UDP_SEGMENT on *sock* (Linux only).F   )r   r6   r   r	   r.   r7   r,   r8   r"   r"   r%   has_gsoW   r:   r<   ancdatalist[tuple[int, int, bytes]]
int | Nonec                 C  sv   | D ]6\}}}|t kr8|tkr8t|}|tjkr$tt|dd   S |tjkr5tt|dd   S  dS qd S Nr   )r   r   lenr   sizeintunpack_fromr
   )r=   
cmsg_level	cmsg_type	cmsg_datanr"   r"   r%   _parse_gro_segment_sizeb   s   

rI   bufbytessegment_sizerC   list[bytes]c                   s:   t  }dks|kr gS  fddtd|D S )Nr   c                   s   g | ]
} ||  qS r"   r"   )r#   irJ   rL   r"   r%   
<listcomp>r   s    z%_split_gro_buffer.<locals>.<listcomp>)rA   range)rJ   rL   rH   r"   rO   r%   _split_gro_buffern   s   rR   rB   c                 C  s0   | dkrt S t|  }|dk rdS |t k r|S t S Nr   r5   )r   r   )rB   capr"   r"   r%   _max_segments_foru   s   rU   	datagramslist[tuple[int, list[bytes]]]c                 C  s   | sg S g }| d }t |}|g}t|}| dd  D ]C}t |}||kr1t ||k r1|| q||k rLt ||k rL|| |||f g }d}q|rU|||f |}|g}t|}q|rh|||f |S rS   )rA   rU   append)rV   groupsfirstcurrent_sizecurrent_grouprT   dgramrB   r"   r"   r%   _group_for_gso~   s0   

r^   c                      s2  e Zd ZdZdZdX fddZdYdZddZd[ddZd\ddZd]d d!Z	d^d"d#Z
d_d$d%Zd_d&d'Zd`d*d+Zd_d,d-Zd_d.d/Zd_d0d1Zd_d2d3Zd_d4d5Zd_d6d7Zdad;d<ZdYdad=d>ZdYdbdAdBZdbdCdDZdadEdFZd_dGdHZd_dIdJZdYdcdMdNZd_dOdPZdddRdSZd_dTdUZd_dVdWZ  Z S )eOptimizedDatagramTransportzDatagramTransport that uses recvmmsg/sendmsg for GRO/GSO on Linux.

    When quinn-udp Rust is available, uses it for batched recvmmsg and
    GSO sendmsg. Falls back to Python recvmsg/sendmsg otherwise.
    )_loop_sock_sock_fd	_protocol_address_gro_enabled_gso_enabled_gro_segment_size_recv_buf_size_closing_closed_paused_extra_send_queue_buffer_size_protocol_paused_writer_registered_reader_registered_protocol_supports_batch
_udp_stateloopasyncio.AbstractEventLoopr3   r4   protocolasyncio.DatagramProtocoladdresstuple[str, int] | Nonegro_enabledr.   gso_enabledgro_segment_sizerC   r-   Nonec           	        s   t    || _|| _| | _|| _|| _|| _|| _	|| _
d| _d| _d| _d| _d| _t | _d| _d| _t|d| _|rBtnt|d| _d | _zt| j| _W n	 ty\   Y nw z| }W n tyn   d }Y nw ||||j|jd| _ d S )NFr   datagrams_receivedi  )peernamesocketsocknamefamilytype)!super__init__r`   ra   filenorb   rc   rd   re   rf   rg   ri   rj   rk   rp   rq   r   rm   rn   ro   hasattrrr   r   maxrh   rs   _UdpSocketState	Exceptiongetsocknamer,   r   r   rl   )	selfrt   r3   rv   rx   rz   r{   r|   r   	__class__r"   r%   r      sJ   


z#OptimizedDatagramTransport.__init__Nnamestrdefault
typing.Anyc                 C  s   | j ||S r!   )rl   get)r   r   r   r"   r"   r%   get_extra_info   s   z)OptimizedDatagramTransport.get_extra_infoc                 C     | j S r!   )ri   r   r"   r"   r%   
is_closing      z%OptimizedDatagramTransport.is_closingasyncio.BaseProtocolc                 C  r   r!   )rc   r   r"   r"   r%   get_protocol   r   z'OptimizedDatagramTransport.get_protocolc                 C  s   || _ t|d| _d S )Nr~   )rc   r   rr   )r   rv   r"   r"   r%   set_protocol   s   z'OptimizedDatagramTransport.set_protocolc                 C  r   r!   )rn   r   r"   r"   r%   get_write_buffer_size   r   z0OptimizedDatagramTransport.get_write_buffer_sizec                 C  s6   | j rd S d| _ |   | js| j| jd  d S d S NT)ri   _unregister_readerrm   r`   	call_soon_call_connection_lostr   r"   r"   r%   close  s   z OptimizedDatagramTransport.closec                 C  s4   | j rd S d| _ | j  d| _| j| jd  d S )NTr   )ri   rm   clearrn   r`   r   r   r   r"   r"   r%   abort  s   
z OptimizedDatagramTransport.abortr+   Exception | Nonec                 C  s   | j rd S d| _ |   |   z2z| j| W n ttfy#     ty+   Y nw W d | _z| j	
  W d S  tyB   Y d S w d | _z| j	
  W w  tyV   Y w w r   )rj   r   _unregister_writerrc   connection_lostKeyboardInterrupt
SystemExitBaseExceptionrs   ra   r   r,   )r   r+   r"   r"   r%   r     s2   z0OptimizedDatagramTransport._call_connection_lostc              	   C  H   | j s| jrd S z| j| j| j d| _ W d S  ttfy#   Y d S w r   )rq   rj   r`   
add_readerrb   _on_readabler,   
ValueErrorr   r"   r"   r%   _register_reader&     z+OptimizedDatagramTransport._register_readerc              	   C  >   | j sd S d| _ z
| j| j W d S  ttfy   Y d S w NF)rq   r`   remove_readerrb   r,   r   r   r"   r"   r%   r   /     z-OptimizedDatagramTransport._unregister_readerc              	   C  r   r   )rp   rj   r`   
add_writerrb   _on_write_readyr,   r   r   r"   r"   r%   _register_writer8  r   z+OptimizedDatagramTransport._register_writerc              	   C  r   r   )rp   r`   remove_writerrb   r,   r   r   r"   r"   r%   r   A  r   z-OptimizedDatagramTransport._unregister_writerc                 C  s   | j sd| _ |   d S d S r   )rk   r   r   r"   r"   r%   pause_readingJ     z(OptimizedDatagramTransport.pause_readingc                 C  s   | j rd| _ |   d S d S r   )rk   r   r   r"   r"   r%   resume_readingO  r   z)OptimizedDatagramTransport.resume_readingdatarK   addrc              
   C  s   z'|d ur| j || W d S | jd ur| j || j W d S | j | W d S  ty? } zt|s4 W Y d }~d S d }~ww r!   )ra   sendtord   sendr,   r2   )r   r   r   r$   r"   r"   r%   	_raw_sendT  s   
z$OptimizedDatagramTransport._raw_sendc              
   C  s   | j rd S | jr| || d S z	| || W d S  ty-   |   | || Y d S  tyE } z| j| W Y d }~d S d }~ww r!   )	ri   rm   _queue_writer   BlockingIOErrorr   r,   rc   error_received)r   r   r   r+   r"   r"   r%   r   `  s   z!OptimizedDatagramTransport.sendtorV   rM   c                 C  s   | j s|sdS | jr|D ]}| || qdS | j}|dur_|dur$|n| j}|dur_z||t|d t|d  W dS  tyV   | 	  |D ]}| || qJY dS  t
y^   Y nw | jrj| || dS |D ]}| || | j sz| jr} dS qldS )z2Send multiple datagrams, using GSO when available.Nr   r5   )ri   rm   r   rs   rd   r   r   rC   r   r   r,   rf   _send_gso_pythonr   rj   )r   rV   r   r]   statetargetr"   r"   r%   sendto_manyp  s:   
z&OptimizedDatagramTransport.sendto_manyc                 C  sN  t |}| j}|dur|n| j}t|D ]\}\}}z2t|dkr+| |d | n!|dur?||ttt	
|fgd| n||ttt	
|fg W q tyr   |   ||d D ]\}	}
|
D ]}| || qdq^Y  dS  ty$ } zt|dkr|D ]}z| || W q ty   |   | || ||d }||d D ]}| || q||d d D ]\}	}
|
D ]}| || qqY  W Y d}~ dS  ty } z | j| | js| jrW Y d}~ W Y d}~ dS W Y d}~qd}~ww n| j| | js| jrW Y d}~ dS W Y d}~qd}~ww dS )z/Python fallback: sendmsg with UDP_SEGMENT cmsg.Nr5   r   )r^   ra   rd   	enumeraterA   r   sendmsgr   r	   r
   packr   r   r   r,   indexrc   r   ri   rj   )r   rV   r   rY   r3   r   rN   rL   group_szgr]   r+   idxtaildinnerr"   r"   r%   r     sp   z+OptimizedDatagramTransport._send_gso_pythonc              	   C  sx   | j ||f |  jt|7  _| jtkr8| js:d| _z| j  W d S  tt	fy.     t
y7   Y d S w d S d S r   )rm   rX   rn   rA   r   ro   rc   pause_writingr   r   r   )r   r   r   r"   r"   r%   r     s   z'OptimizedDatagramTransport._queue_writec                 C  s@  | j }| j}|r|d \}}z||| W n[ ty   Y d S  ty'   Y q typ } z>|  |  jt|8  _|   z| j	
| W n ttfyQ     tyY   Y nw | js`| jrfW Y d }~nW Y d }~qd }~ww |  |  jt|8  _|   |s|s|   | jr| js| j| jd  d S d S d S d S r@   )rm   r   r   InterruptedErrorr,   popleftrn   rA   _maybe_resume_protocolrc   r   r   r   r   ri   rj   r   r`   r   r   )r   queueraw_sendr   r   r+   r"   r"   r%   r     sH   z*OptimizedDatagramTransport._on_write_readyc              	   C  sV   | j r'| jtkr)d| _ z| j  W d S  ttfy     ty&   Y d S w d S d S r   )ro   rn   r   rc   resume_writingr   r   r   r   r"   r"   r%   r     s   z1OptimizedDatagramTransport._maybe_resume_protocolwaiterasyncio.Future[None] | Nonec                 C  s@   | j | jj|  | j | j |d ur| j |jd  d S d S r!   )r`   r   rc   connection_mader   
set_result)r   r   r"   r"   r%   _start  s
   z!OptimizedDatagramTransport._startc                 C  sD   | j rd S | j}|d ur| | d S | jr|   d S |   d S r!   )ri   rs   
_recv_rustre   _recv_gro_python_recv_plain)r   r   r"   r"   r%   r     s   z'OptimizedDatagramTransport._on_readabler   c              	   C  s  | j }| jr	|jnd}|j}d}|durFg }d}ttD ]}z| \}	}
W n
 ty/   Y  nw |	s4 n
||	 |
}qd}|rE||| n.|j}ttD ]$}z| \}	}W n tya   Y  dS w |	sg dS |	D ]}||| qiqMd}|r| j	s| j
r| j| j dS dS dS dS )z!Batch-receive via quinn-udp Rust.NFT)rc   rr   r~   recvrQ   r   r,   extenddatagram_receivedri   rq   r`   r   r   )r   r   rv   batch_cb_recv	hit_limitall_segmentsr   _segmentsar   segr"   r"   r%   r     sP   

z%OptimizedDatagramTransport._recv_rustc                 C  s   | j }| j}ttD ]B}z	|d\}}W n+ ty    Y  d S  ty(   Y q
 ty@ } z|| W Y d }~ d S d }~ww |sF d S |	|| q
d S )Nr   )
ra   rc   rQ   r   recvfromr   r   r,   r   r   )r   r3   rv   r   r   r   r+   r"   r"   r%   r   C  s$   
z&OptimizedDatagramTransport._recv_plainc                 C  s  | j j}| j}|j}| jr|jnd}| j}t}tt	D ]}z|| j
|\}}	}
}W n@ ty4   Y  dS  ty<   Y q tyi } z"z|| W n ttfyT     ty\   Y nw W Y d}~ dS d}~ww |so dS |
t@ r| j
}|tk rt|d t| _
q|
t@ r||| qt|	}|du r||| q|dkr|n|}t||kr||| qt||}|dur||| q|D ]}||| qq| js| jr| j| j dS dS dS )z/Python fallback: recvmsg with GRO cmsg parsing.Nr   r   )ra   recvmsgrc   r   rr   r~   rg   r    rQ   r   rh   r   r   r,   r   r   r   r   r   r   minr   rI   rA   rR   ri   rq   r`   r   r   )r   sock_recvmsgrv   r   r   default_segment_size
ancbufsizer   r   r=   flagsr   r+   bufsizeparsedrL   r   r   r"   r"   r%   r   T  sp   	



z+OptimizedDatagramTransport._recv_gro_python)rt   ru   r3   r4   rv   rw   rx   ry   rz   r.   r{   r.   r|   rC   r-   r}   r!   )r   r   r   r   r-   r   )r-   r.   )r-   r   )rv   r   r-   r}   )r-   rC   )r-   r}   )r+   r   r-   r}   )r   rK   r   r   r-   r}   )rV   rM   r   r   r-   r}   )r   r   r-   r}   )r   r   r-   r}   )!__name__
__module____qualname____doc__	__slots__r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__r"   r"   r   r%   r_      s<    7








	
	
	
	


$
5

#



/r_   r;   rt   ru   protocol_factory-typing.Callable[[], asyncio.DatagramProtocol]r|   :tuple[asyncio.DatagramTransport, asyncio.DatagramProtocol]c           	   	     st   t |}t|}ts| j||dI dH S |d | }t| ||d|||d}|  }|| |I dH  ||fS )z?Create a DatagramTransport with optimized UDP I/O if available.r8   NF)rt   r3   rv   rx   rz   r{   r|   )r9   r<   r   create_datagram_endpointsetblockingr_   create_futurer   )	rt   r   r3   r|   rz   r{   rv   	transportr   r"   r"   r%   #create_optimized_datagram_transport  s(   
	

r  )r+   r,   r-   r.   )r3   r4   r-   r.   )r=   r>   r-   r?   )rJ   rK   rL   rC   r-   rM   )rB   rC   r-   rC   )rV   rM   r-   rW   )r;   )
rt   ru   r   r   r3   r4   r|   rC   r-   r   )4r   
__future__r   asyncior0   r   structsystypingcollectionsr   _hazmatr   r   r   __annotations__r	   Structr
   r   r   r   r   r   r   r   r   platformr   r   SOL_UDPr   r1   r   r   r   r   rB   r    	frozensetr)   r*   r2   r9   r<   rI   rR   rU   r^   DatagramTransportr_   r  r"   r"   r"   r%   <module>   s^    









	    ~