o
    #f+a                     @   sL  d Z ddgZddlZddlZddlZzddlZejejejej	dZ
W n ey.   dZY nw 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 d	d
lmZmZmZmZ d	dlmZmZmZm Z  ddl!m"Z"m#Z# de$de%fddZ&G dd deZ'G dd de'Z(G dd de(Z)G dd deZ*G dd de*Z+G dd de*Z,dS )zFModule implementing low-level socket communication with MySQL servers.MySQLTcpSocketMySQLUnixSocket    N)TLSv1TLSv1.1TLSv1.2TLSv1.3)ABCabstractmethod)deque)AnyDequeListOptionalTuple   )InterfaceErrorNotSupportedErrorOperationalErrorProgrammingError)COMPRESSED_PACKET_HEADER_LENGTHMAX_PAYLOAD_LENGTHMIN_COMPRESS_LENGTHPACKET_HEADER_LENGTH   )StreamWriteropen_connectionerrreturnc                 C   s    | j st| S | j  d| j S )z`Reformat the IOError error message.

    This function reformats the IOError error message.
     )errnostrstrerror)r    r"   Q/home/ubuntu/dev/venv/lib/python3.10/site-packages/mysql/connector/aio/network.py_strioerrorG   s    r$   c                   @   s`   e Zd ZdZe		ddedededee	 dee	 ddfd	d
Z
edejdedefddZdS )NetworkBrokeraP  Broker class interface.

    The network object is a broker used as a delegate by a socket object. Whenever the
    socket wants to deliver or get packets to or from the MySQL server it needs to rely
    on its network broker (netbroker).

    The netbroker sends `payloads` and receives `packets`.

    A packet is a bytes sequence, it has a header and body (referred to as payload).
    The first `PACKET_HEADER_LENGTH` or `COMPRESSED_PACKET_HEADER_LENGTH`
    (as appropriate) bytes correspond to the `header`, the remaining ones represent the
    `payload`.

    The maximum payload length allowed to be sent per packet to the server is
    `MAX_PAYLOAD_LENGTH`. When  `send` is called with a payload whose length is greater
    than `MAX_PAYLOAD_LENGTH` the netbroker breaks it down into packets, so the caller
    of `send` can provide payloads of arbitrary length.

    Finally, data received by the netbroker comes directly from the server, expect to
    get a packet for each call to `recv`. The received packet contains a header and
    payload, the latter respecting `MAX_PAYLOAD_LENGTH`.
    Nwriteraddresspayloadpacket_numbercompressed_packet_numberr   c                       dS )a  Send `payload` to the MySQL server.

        If provided a payload whose length is greater than `MAX_PAYLOAD_LENGTH`, it is
        broken down into packets.

        Args:
            sock: Object holding the socket connection.
            address: Socket's location.
            payload: Packet's body to send.
            packet_number: Sequence id (packet ID) to attach to the header when sending
                           plain packets.
            compressed_packet_number: Same as `packet_number` but used when sending
                                      compressed packets.

        Raises:
            :class:`OperationalError`: If something goes wrong while sending packets to
                                       the MySQL server.
        Nr"   )selfr&   r'   r(   r)   r*   r"   r"   r#   writeg       zNetworkBroker.writereaderc                    r+   )a)  Get the next available packet from the MySQL server.

        Args:
            sock: Object holding the socket connection.
            address: Socket's location.

        Returns:
            packet: A packet from the MySQL server.

        Raises:
            :class:`OperationalError`: If something goes wrong while receiving packets
                                       from the MySQL server.
            :class:`InterfaceError`: If something goes wrong while receiving packets
                                     from the MySQL server.
        Nr"   )r,   r/   r'   r"   r"   r#   read   r.   zNetworkBroker.readNN)__name__
__module____qualname____doc__r	   r   r    bytesr   intr-   asyncioStreamReader	bytearrayr0   r"   r"   r"   r#   r%   O   s(    r%   c                   @   s   e Zd ZdZdddZededeeef fddZ	dd	e
e ddfd
dZdedededdfddZ	ddejdedefddZ		ddededede
e de
e ddfddZdejdedefddZdS ) NetworkBrokerPlain,Broker class for MySQL socket communication.r   Nc                 C   s
   d| _ d S N_pktnrr,   r"   r"   r#   __init__   s   
zNetworkBrokerPlain.__init__pktc                 C   sB   t | tk r
tdtd| dd d d | d }}||fS )-Recover the header information from a packet.3Can't recover header info from an incomplete packet<Ir          )lenr   
ValueErrorstructunpack)rC   pllseqidr"   r"   r#   
get_header   s   zNetworkBrokerPlain.get_headernext_idc                 C   0   |du r|  j d7  _ n|| _ |  j d;  _ dS z:Set the given packet id, if any, else increment packet id.Nr      r?   r,   rP   r"   r"   r#   _set_next_pktnr      z"NetworkBrokerPlain._set_next_pktnrr&   r'   c              
      sr   z| | | I dH  W dS  ty' } ztd|t|fd|d}~w ty8 } ztdd|d}~ww )z!Write packet to the comm channel.N  r   valuesi  r   )r-   drainIOErrorr   r$   AttributeError)r,   r&   r'   rC   r   r"   r"   r#   
_write_pkt   s   
zNetworkBrokerPlain._write_pktr   r/   sizec                    sT   t d}t||k r(||t| I dH }|stdd||7 }t||k s|S )z(Read `size` bytes from the comm channel.    Ni  rZ   )r:   rI   r0   r   )r,   r/   r_   rC   chunkr"   r"   r#   _read_chunk   s   
zNetworkBrokerPlain._read_chunkr(   r)   r*   c              
      s   |  | d}tt|t D ]#}| ||dtd| j |||t   I dH  |    |t7 }q| ||tdt|| dd td| j ||d  I dH  dS )zSend payload to the MySQL server.

        If provided a payload whose length is greater than `MAX_PAYLOAD_LENGTH`, it is
        broken down into packets.
        r      <BNrF   rG   )rU   rangerI   r   r^   rK   packr@   )r,   r&   r'   r(   r)   r*   offset_r"   r"   r#   r-      s0   



zNetworkBrokerPlain.writec              
      sp   z| j |tdI dH }| |\}| _|| j ||dI dH  W S  ty7 } ztd|t|fd|d}~ww )z+Receive `one` packet from the MySQL server.r_   NrW   rX   )rb   r   rO   r@   r\   r   r$   )r,   r/   r'   headerpayload_lenr   r"   r"   r#   r0      s   zNetworkBrokerPlain.readr   NN)r   r1   )r2   r3   r4   r5   rB   staticmethodr6   r   r7   rO   r   rU   r   r    r^   r8   r9   r:   rb   r-   r0   r"   r"   r"   r#   r;      s>    


&r;   c                       s  e Zd ZdZd fddZedededee fdd	Z	ed
ede
eeef fddZddee ddfddZdeded
eddf fddZ		d dedededee dee ddf fddZdejdeddf fddZdejdedef fddZ  ZS )!NetworkBrokerCompressedr<   r   Nc                    s   t    d| _t | _d S r=   )superrB   _compressed_pktnrr
   _queue_readrA   	__class__r"   r#   rB     s   
z NetworkBrokerCompressed.__init__r(   pktnrc                 C   s   d}g }t t| t D ]}|dtd| | ||t    |d d }|t7 }q|tdt| | dd td| | |d   |S )	z2Prepare a payload for sending to the MySQL server.r   rc   rd   r   rS   rF   rG   N)re   rI   r   appendrK   rf   )r(   ru   rg   pktsrh   r"   r"   r#   _prepare_packets  s(   



z(NetworkBrokerCompressed._prepare_packetsrC   c                 C   sb   t | tk r
tdtd| dd d d | d td| dd d d }}}|||fS )rD   rE   rF   r   rG   rH         )rI   r   rJ   rK   rL   )rC   compressed_pllrN   uncompressed_pllr"   r"   r#   rO   !  s   

z"NetworkBrokerCompressed.get_headerrP   c                 C   rQ   rR   )rq   rT   r"   r"   r#   _set_next_compressed_pktnr/  rV   z2NetworkBrokerCompressed._set_next_compressed_pktnrr&   r'   c                    sd   t |}tdt|dd td| j tdt|dd  | }t |||I dH S )z1Compress packet and write it to the comm channel.rF   r   rG   rd   N)zlibcompressrK   rf   rI   rq   rp   r^   )r,   r&   r'   rC   compressed_pktrs   r"   r#   r^   7  s   
z"NetworkBrokerCompressed._write_pktr)   r*   c           	   	      s   |  | | | td| || j}t|tt krTd}t	t|t D ]}| 
|||||t  I dH  |   |t7 }q)| 
||||d I dH  dS t|tkrf| 
|||I dH  dS t 
||tdt|dd td| j tdddd  | I dH  dS )zSend `payload` as compressed packets to the MySQL server.

        If provided a payload whose length is greater than `MAX_PAYLOAD_LENGTH`, it is
        broken down into packets.
        r`   r   NrF   rG   rd   )rU   r}   r:   joinrx   r@   rI   r   r   re   r^   r   rp   rK   rf   rq   )	r,   r&   r'   r(   r)   r*   payload_preprg   rh   rs   r"   r#   r-   B  s4   



 zNetworkBrokerCompressed.writer/   r{   c           	         s   t tt j||dI dH }d}|t|k r}td|||t d  d d }t| t|| krat j|t	dI dH }| 
|\}| _}t j||dI dH }||dkr[|nt|7 }| j|||t |   |t| 7 }|t|k sdS dS )z&Handle reading of a compressed packet.ri   Nr   rF   r   rH   )r:   r~   
decompressrp   rb   rI   rK   rL   r   r   rO   rq   rr   rv   )	r,   r/   r{   rC   rg   rM   rj   r|   r   rs   r"   r#   _read_compressed_pkty  s:   	z,NetworkBrokerCompressed._read_compressed_pktc              
      s   | j sOz3t j|tdI dH }| |\}| _}|dkr-| j t j||dI dH  n	| ||I dH  W n tyN } zt	d|t
|fd|d}~ww | j sTdS | j  }|d | _|S )z{Receive `one` or `several` packets from the MySQL server, enqueue them, and
        return the packet at the head.
        ri   Nr   rW   rX   rG   )rr   rp   rb   r   rO   rq   rv   r   r\   r   r$   popleftr@   )r,   r/   r'   rj   r{   r|   r   rC   rs   r"   r#   r0     s<   	

zNetworkBrokerCompressed.readrl   rm   r1   )r2   r3   r4   r5   rB   rn   r6   r7   r   rx   r   rO   r   r}   r   r    r^   r-   r8   r9   r   r:   r0   __classcell__r"   r"   rs   r#   ro      s@    7$(ro   c                   @   s   e Zd ZdZd(ddZedefddZede	ddfd	d
Z
d(ddZdefddZdeddfddZd(ddZdejddfddZ		d)dedee dee ddfddZdefddZdddddg g fdee d ee d!ee d"ee d#ee d$eee  d%eee  dejfd&d'ZdS )*MySQLSocketzMySQL socket communication interface.

    Examples:
        Subclasses: network.MySQLTCPSocket and network.MySQLUnixSocket.
    r   Nc                 C   s*   d| _ d| _d| _d| _t | _d| _dS )zsNetwork layer where transactions are made with plain (uncompressed) packets
        is enabled by default.
        NF)_reader_writer_connection_timeout_addressr;   
_netbroker_is_connectedrA   r"   r"   r#   rB     s   
zMySQLSocket.__init__c                 C      | j S )zSocket location.)r   rA   r"   r"   r#   r'     s   zMySQLSocket.addresskwargsc                    r+   )zOpen the socket.Nr"   r,   r   r"   r"   r#   r     r.   zMySQLSocket.open_connectionc                    sD   | j r| j   | j jdur| j j  | j  I dH  d| _dS )zClose the connection.NF)r   close	transportabortwait_closedr   rA   r"   r"   r#   close_connection  s   

zMySQLSocket.close_connectionc                 C   r   )zCheck if the socket is connected.

        Return:
            bool: Returns `True` if the socket is connected to MySQL server.
        )r   rA   r"   r"   r#   is_connected  s   zMySQLSocket.is_connectedtimeoutc                 C   s
   || _ dS )zSet the connection timeout.N)r   )r,   r   r"   r"   r#   set_connection_timeout  s   
z"MySQLSocket.set_connection_timeoutc                 C   s   t  | _dS )zIEnable network layer where transactions are made with compressed packets.N)ro   r   rA   r"   r"   r#   switch_to_compressed_mode  s   z%MySQLSocket.switch_to_compressed_modessl_contextc                    sF   | j dusJ | j jd}|jdkrtd| j |I dH  dS )a?  Upgrade an existing stream-based connection to TLS.

        The `start_tls()` method from `asyncio.streams.StreamWriter` is only available
        in Python 3.11. This method is used as a workaround.

        The MySQL TLS negotiation happens in the middle of the TCP connection.
        Therefore, passing a socket to open connection will cause it to negotiate
        TLS on an existing connection.

        Args:
            ssl_context: The SSL Context to be used.

        Raises:
            RuntimeError: If the transport does not expose the socket instance.
        Nsocketr   z,SSL is not supported when using Unix sockets)r   r   get_extra_infofamilyr   	start_tls)r,   r   r   r"   r"   r#   switch_to_ssl  s   
zMySQLSocket.switch_to_sslr(   r)   r*   c                    s&   | j j| j| j|||dI dH  dS )z!Send packets to the MySQL server.)r)   r*   N)r   r-   r   r'   )r,   r(   r)   r*   r"   r"   r#   r-     s   zMySQLSocket.writec                    s   | j | j| jI dH S )z#Read packets from the MySQL server.N)r   r0   r   r'   rA   r"   r"   r#   r0   &  s   zMySQLSocket.readFssl_cassl_certssl_keyssl_verify_certssl_verify_identitytls_versionstls_cipher_suitesc                 C   s  | j stddtdu rtdz|rO|jdd |d }t| }	t|	}
|dkrNd	|vr6|
 jtjO  _d
|vrB|
 jtj	O  _d|vrN|
 jtj
O  _nt }
||
_|r]tj|
_n|rdtj|
_ntj|
_|
  |rz|
| W n ttjfy } ztd| |d}~ww |rz|
|| W n ttjfy } ztd| |d}~ww |r|
d| |
W S  ty } ztd|d}~w tttjtjfy } ztt||d}~ww )zBuild a SSLContext.i   rZ   Nz&Python installation has no SSL supportT)reverser   r   r   r   r   zInvalid CA Certificate: zInvalid Certificate/Key: :)r   r   sslRuntimeErrorsortTLS_VERSIONS
SSLContextoptionsOP_NO_TLSv1_2OP_NO_TLSv1_1OP_NO_TLSv1create_default_contextcheck_hostnameCERT_REQUIREDverify_modeCERT_OPTIONAL	CERT_NONEload_default_certsload_verify_locationsr\   SSLErrorload_cert_chainset_ciphersr   	NameErrorr   NotImplementedErrorCertificateErrorr    )r,   r   r   r   r   r   r   r   tls_versionssl_protocolcontextr   r"   r"   r#   build_ssl_context*  sn   




zMySQLSocket.build_ssl_contextrl   r1   )r2   r3   r4   r5   rB   propertyr    r'   r	   r   r   r   boolr   r7   r   r   r   r   r   r6   r   r-   r:   r0   r   r   r"   r"   r"   r#   r     s`    






	r   c                       sD   e Zd ZdZ	ddededef fdd	Zd
eddfddZ	  Z
S )r   zMySQL socket class using TCP/IP.

    Args:
        host: MySQL host name.
        port: MySQL port.
        force_ipv6: Force IPv6 usage.
    	127.0.0.1  Fhostport
force_ipv6c                    s0   t    || _|| _|| _| d| | _d S )Nr   )rp   rB   _host_port_force_ipv6r   )r,   r   r   r   rs   r"   r#   rB   z  s
   
zMySQLTcpSocket.__init__r   r   Nc                    s2   t d| j| jd|I dH \| _| _d| _dS )zOpen TCP/IP connection.)r   r   NTr"   )r   r   r   r   r   r   r   r"   r"   r#   r     s   
zMySQLTcpSocket.open_connection)r   r   F)r2   r3   r4   r5   r    r7   r   rB   r   r   r   r"   r"   rs   r#   r   q  s    		c                       s:   e Zd ZdZddef fddZdeddfd	d
Z  ZS )r   zbMySQL socket class using UNIX sockets.

    Args:
        unix_socket: UNIX socket file path.
    /tmp/mysql.sockunix_socketc                    s   t    || _d S rm   )rp   rB   r   )r,   r   rs   r"   r#   rB     s   

zMySQLUnixSocket.__init__r   r   Nc                    s0   t jdd| ji|I dH \| _| _d| _dS )zOpen UNIX socket connection.pathNTr"   )r8   open_unix_connectionr   r   r   r   r   r"   r"   r#   r     s   

zMySQLUnixSocket.open_connection)r   )	r2   r3   r4   r5   r    rB   r   r   r   r"   r"   rs   r#   r     s    )-r5   __all__r8   rK   r~   r   PROTOCOL_TLSv1PROTOCOL_TLSv1_1PROTOCOL_TLSv1_2PROTOCOL_TLSr   ImportErrorabcr   r	   collectionsr
   typingr   r   r   r   r   errorsr   r   r   r   networkr   r   r   r   utilsr   r   r\   r    r$   r%   r;   ro   r   r   r   r"   r"   r"   r#   <module>   s<   
Gj J )