U
    4Jel                     @   s  U 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mZmZ ddl	m
Z
 zHddlZejejejdZeedrvejnejed< eedoejZW n ek
r   d	ZY nX dd
l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" dZ#e$e%d< dZ&e$e%d< dZ'e$e%d< dZ(e$e%d< e)e*d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/Z0G d#d$ d$e/Z1dS )%zGModule implementing low-level socket communication with MySQL servers.
    N)ABCabstractmethod)deque)TLSv1TLSv1.1TLSv1.2PROTOCOL_TLSTLSv1.3HAS_TLSv1_3F)AnyDequeListOptionalTupleUnion   )InterfaceErrorNotSupportedErrorOperationalError)StrOrBytesPath2   MIN_COMPRESS_LENGTHi MAX_PAYLOAD_LENGTH   PACKET_HEADER_LENGTH   COMPRESSED_PACKET_HEADER_LENGTH)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#   ;/tmp/pip-unpacked-wheel-7_167w8m/mysql/connector/network.py_strioerrorI   s    r%   c                	   @   sP   e Zd ZdZed	ejeeee	 ee	 ddddZ
eejeed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sockaddresspayloadpacket_numbercompressed_packet_numberr   c                 C   s   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$   sendi   s    	zNetworkBroker.sendr(   r)   r   c                 C   s   dS )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$   recv   s    zNetworkBroker.recv)NN)__name__
__module____qualname____doc__r   socketr!   bytesr   intr.   	bytearrayr0   r#   r#   r#   r$   r&   Q   s     r&   c                   @   s   e Zd ZdZddddZddddZejeeddd	d
Z	deje
edddZdejeeee
 ee
 ddddZejeedddZdS )NetworkBrokerPlain,Broker class for MySQL socket communication.Nr   c                 C   s
   d| _ d S N_pktnrr-   r#   r#   r$   __init__   s    zNetworkBrokerPlain.__init__c                 C   s   | j d d | _ dS zIncrement packet id.r      Nr>   r@   r#   r#   r$   _set_next_pktnr   s    z"NetworkBrokerPlain._set_next_pktnrr(   r)   pktr   c              
   C   sx   z| | W nd tk
rF } ztd|t|fd|W 5 d}~X Y n. tk
rr } ztdd|W 5 d}~X Y nX dS )z!Write packet to the comm channel.  r    valuesNi  r    )sendallIOErrorr   r%   AttributeError)r-   r(   r)   rF   r   r#   r#   r$   	_send_pkt   s     
zNetworkBrokerPlain._send_pktr   )r(   sizer   c                 C   sT   t |}t|}|rP|||}|dkr:|dkr:tdd||d }||8 }q|S )z(Read `size` bytes from the comm channel.r   i  rJ   N)r8   
memoryview	recv_intor   )r-   r(   rO   rF   Zpkt_viewreadr#   r#   r$   _recv_chunk   s    

zNetworkBrokerPlain._recv_chunkr'   c              
   C   s   |dkr|    n|| _t|tkrd}tt|t D ]@}| ||dtd| j |||t    |    |t7 }q8||d }| ||tdt|dd td| j |  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.
        Nr      <B<I   )rD   r?   lenr   rangerN   structpack)r-   r(   r)   r*   r+   r,   offset_r#   r#   r$   r.      s6    

zNetworkBrokerPlain.sendr/   c              
   C   s   zJ| j |td}td|dd d d |d  }| _|| j ||d W S  tk
r } ztd|t|fd|W 5 d}~X Y nX dS )	z+Receive `one` packet from the MySQL server.rO   rV   r   rW       rG   rH   N)rS   r   rZ   unpackr?   rL   r   r%   )r-   r(   r)   headerZpayload_lenr   r#   r#   r$   r0      s     
zNetworkBrokerPlain.recv)r   )NN)r1   r2   r3   r4   rA   rD   r5   r!   r6   rN   r7   r8   rS   r   r.   r0   r#   r#   r#   r$   r9      s      ,r9   c                       s   e Zd ZdZdd fddZeeeee dddZ	ddd	d
Z
ejeedd fddZdejeeee ee dd fddZejeedd fddZejeed fddZ  ZS )NetworkBrokerCompressedr:   Nr;   c                    s   t    d| _t | _d S r<   )superrA   _compressed_pktnrr   _queue_readr@   	__class__r#   r$   rA      s    
z NetworkBrokerCompressed.__init__)r*   pktnrr   c                 C   s   g }t | tkrpd}tt | t D ]>}|dtd| | ||t    |d d }|t7 }q$| |d } |tdt | dd td| |   |S )	z2Prepare a payload for sending to the MySQL server.r   rT   rU   r   rC   NrV   rW   )rX   r   rY   appendrZ   r[   )r*   rh   Zpktsr\   r]   r#   r#   r$   _prepare_packets  s$    

&z(NetworkBrokerCompressed._prepare_packetsc                 C   s   | j d d | _ dS rB   )rd   r@   r#   r#   r$   _set_next_compressed_pktnr  s    z2NetworkBrokerCompressed._set_next_compressed_pktnrrE   c                    s\   t |}tdt|dd td| j tdt|dd  | }t |||S )z1Compress packet and write it to the comm channel.rV   r   rW   rU   )zlibcompressrZ   r[   rX   rd   rc   rN   )r-   r(   r)   rF   compressed_pktrf   r#   r$   rN     s    
z!NetworkBrokerCompressed._send_pktr'   c           	   	      s  |dkr|    n|| _|dkr*|   n|| _td| || j}t|tt	 krd}t
t|t D ].}| |||||t   |   |t7 }ql| ||||d  nft|tkr| ||| nJt ||tdt|dd td| j tdddd  |  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.
        N    r   rV   rW   rU   )rD   r?   rk   rd   r8   joinrj   rX   r   r   rY   rN   r   rc   rZ   r[   )	r-   r(   r)   r*   r+   r,   Zpayload_prepr\   r]   rf   r#   r$   r.   *  s>    

  
zNetworkBrokerCompressed.send)r(   compressed_plluncompressed_pllr   c           	         s"  t  j||d}|dkr|ntt|}d}|t|k rtd|||t d  d d }t| t|| krt  j|t	d}td|dd d d |d td|dd d d   }| _
}t  j||d}||dkr|nt|7 }| j|||t |   |t| 7 }q.d	S )
z&Handle reading of a compressed packet.r^   r   rV   r   r_   rW   r   r   N)rc   rS   r8   rl   
decompressrX   rZ   r`   r   r   rd   re   ri   )	r-   r(   rq   rr   rn   rF   r\   Zpllra   rf   r#   r$   _recv_compressed_pktg  s>     z,NetworkBrokerCompressed._recv_compressed_pktr/   c              
      s   | j szht j|td}td|dd d d |d td|dd d d   }| _}| ||| W n8 tk
r } zt	d|t
|fd	|W 5 d
}~X Y nX | j sd
S | j  }|d | _|S )z{Receive `one` or `several` packets from the MySQL server, enqueue them, and
        return the packet at the head.
        r^   rV   r   rW   r_   r   r   rG   rH   N)re   rc   rS   r   rZ   r`   rd   rt   rL   r   r%   popleftr?   )r-   r(   r)   ra   rq   rr   r   rF   rf   r#   r$   r0     s0     


zNetworkBrokerCompressed.recv)NN)r1   r2   r3   r4   rA   staticmethodr6   r7   r   rj   rk   r5   r!   rN   r   r.   rt   r8   r0   __classcell__r#   r#   rf   r$   rb      s,     >  0rb   c                
   @   s   e Zd ZdZddddZddddZdddd	Zddd
dZddddZe	e
 ddddZdeeeeee	e e	ee  ddddZdee	e
 e	e
 ddddZedddZeddddZeeedddZdS ) MySQLSocketzMySQL socket communication interface.

    Examples:
        Subclasses: network.MySQLTCPSocket and network.MySQLUnixSocket.
    Nr;   c                 C   s   d| _ d| _d| _t | _dS )zsNetwork layer where transactions are made with plain (uncompressed) packets
        is enabled by default.
        N)r(   _connection_timeoutserver_hostr9   
_netbrokerr@   r#   r#   r$   rA     s    zMySQLSocket.__init__c                 C   s   t  | _dS )zIEnable network layer where transactions are made with compressed packets.N)rb   r{   r@   r#   r#   r$   switch_to_compressed_mode  s    z%MySQLSocket.switch_to_compressed_modec              	   C   s:   z| j tj | j   W n ttfk
r4   Y nX dS )z'Shut down the socket before closing it.N)r(   shutdownr5   	SHUT_RDWRcloserM   OSErrorr@   r#   r#   r$   r}     s
    zMySQLSocket.shutdownc              	   C   s,   z| j   W n ttfk
r&   Y nX dS )zClose the socket.N)r(   r   rM   r   r@   r#   r#   r$   close_connection  s    zMySQLSocket.close_connectionc                 C   s   |    d S N)r}   r@   r#   r#   r$   __del__  s    zMySQLSocket.__del__)timeoutr   c                 C   s   || _ | jr| j| dS )zSet the connection timeout.N)ry   r(   
settimeout)r-   r   r#   r#   r$   set_connection_timeout  s    z"MySQLSocket.set_connection_timeoutF)cacertkeyverify_certverify_identitycipher_suitestls_versionsr   c                 C   s  | j stddz|r tj}n|r,tj}ntj}|dks>|sRt }	|sd|	_n|jdd |d }
t	s|
dkrt
|d	kr|d	 }
t|
 }t|}	|
dkrd
|kr|	 jtjO  _d|kr|	 jtjO  _d|kr|	 jtjO  _d|	_||	_|	  |rVz|	| W nD ttjfk
rT } z| j   td| |W 5 d}~X Y nX |rz|	|| W nD ttjfk
r } z| j   td| |W 5 d}~X Y nX |r|	| t| dr|	j| j | jd| _ n|	| j | _ |rd|	_| jr| jgng }tjdkrV| jdkrVddg}t| j}| |d g|d	   d}g }|D ]\}zt!| j " | W n4 tj#k
r } z|$t%| W 5 d}~X Y nX d} qqb|s| j   tdd&| W n t'k
r } zt(d|W 5 d}~X Y n tjtfk
rT } ztd| j)t*|fd|W 5 d}~X Y nd tj#k
r } ztt%||W 5 d}~X Y n2 t+k
r } ztt%||W 5 d}~X Y nX dS )zSwitch the socket to use SSLi   rJ   NFT)reverser   r	   r   r   r   r   zInvalid CA Certificate: zInvalid Certificate/Key: rz   )server_hostnament	localhost	127.0.0.1z"Unable to verify server identity: z, z&Python installation has no SSL supportrG   rH   ),r(   r   sslCERT_REQUIREDCERT_OPTIONAL	CERT_NONEcreate_default_contextcheck_hostnamesortTLS_V1_3_SUPPORTEDrX   TLS_VERSIONS
SSLContextoptionsOP_NO_TLSv1_2OP_NO_TLSv1_1OP_NO_TLSv1verify_modeload_default_certsload_verify_locationsrL   SSLErrorr   load_cert_chainset_ciphershasattrwrap_socketrz   osnamer5   gethostbyaddrextendmatch_hostnamegetpeercertCertificateErrorri   r!   rp   	NameErrorr   r)   r%   NotImplementedError)r-   r   r   r   r   r   r   r   	cert_reqscontextZtls_versionZssl_protocolr   Z	hostnamesaliasesZmatch_foundZerrshostnamer#   r#   r$   switch_to_ssl  s    



"
"
 
 

 zMySQLSocket.switch_to_ssl)r*   r+   r,   r   c                 C   s   | j j| j| j|||dS )z#Send `payload` to the MySQL server.)r+   r,   )r{   r.   r(   r)   )r-   r*   r+   r,   r#   r#   r$   r.   U  s    zMySQLSocket.sendc                 C   s   | j | j| jS )z.Get packet from the MySQL server comm channel.)r{   r0   r(   r)   r@   r#   r#   r$   r0   d  s    zMySQLSocket.recvc                 C   s   dS )zOpen the socket.Nr#   r@   r#   r#   r$   open_connectionh  s    zMySQLSocket.open_connectionc                 C   s   dS )zGet the location of the socket.Nr#   r@   r#   r#   r$   r)   l  s    zMySQLSocket.address)FFNN)NN)r1   r2   r3   r4   rA   r|   r}   r   r   r   r7   r   r   boolr!   r   r   r6   r.   r8   r0   r   r   propertyr)   r#   r#   r#   r$   rx     sF   
    
r  rx   c                       s\   e Zd ZdZdedd fddZeeddd	Zddd
dZe	e	ddddZ
  ZS )MySQLUnixSocketzpMySQL socket class using UNIX sockets.

    Opens a connection through the UNIX socket of the MySQL Server.
    /tmp/mysql.sockN)unix_socketr   c                    s   t    || _|| _d S r   )rc   rA   r   _address)r-   r   rf   r#   r$   rA   x  s    
zMySQLUnixSocket.__init__r;   c                 C   s   | j S r   r   r@   r#   r#   r$   r)   }  s    zMySQLUnixSocket.addressc              
   C   s   z2t  t jt j| _| j| j | j| j W nh tk
rl } zt	d| j
t|fd|W 5 d }~X Y n0 tk
r } zt	t||W 5 d }~X Y nX d S )Ni  rH   )r5   AF_UNIXSOCK_STREAMr(   r   ry   connectr   rL   r   r)   r%   	Exceptionr!   )r-   r   r#   r#   r$   r     s       zMySQLUnixSocket.open_connection)argskwargsr   c                 O   s   t dt dS )zSwitch the socket to use SSL.z2SSL is disabled when using unix socket connectionsN)warningswarnWarning)r-   r   r   r#   r#   r$   r     s    zMySQLUnixSocket.switch_to_ssl)r   )r1   r2   r3   r4   r!   rA   r   r)   r   r   r   rw   r#   r#   rf   r$   r   r  s    r   c                       sN   e Zd ZdZdeeedd fddZeed	d
dZ	dd	ddZ
  ZS )MySQLTCPSocketzYMySQL socket class using TCP/IP.

    Opens a TCP/IP connection to the MySQL Server.
    r     FN)hostport
force_ipv6r   c                    s6   t    || _|| _|| _d| _| d| | _d S )Nr   :)rc   rA   rz   server_portr   _familyr   )r-   r   r   r   rf   r#   r$   rA     s    
zMySQLTCPSocket.__init__r;   c                 C   s   | j S r   r   r@   r#   r#   r$   r)     s    zMySQLTCPSocket.addressc           	   
   C   s  d}zt | j| jdt jt j}|D ]6}| jrD|d t jkrD|} q\|d t jkr$|} q\q$| jr~|d dkr~t	d| j |d dkr|d }W n: t
k
r } zt	d| jt|fd|W 5 d}~X Y nX |\| _}}}}z0t  | j||| _| j| j | j| W np t
k
rP } z t	d| j| jt|fd|W 5 d}~X Y n2 tk
r } ztt||W 5 d}~X Y nX dS )z/Open the TCP/IP connection to the MySQL server.)NNNNNr   NzNo IPv6 address found for i  rH   )r5   getaddrinforz   r   r   SOL_TCPr   AF_INET6AF_INETr   rL   r)   r%   r   r(   r   ry   r   r   r   r!   )	r-   ZaddrinfoZ	addrinfosinfor   socktypeprotor]   Zsockaddrr#   r#   r$   r     sZ    
 zMySQLTCPSocket.open_connection)r   r   F)r1   r2   r3   r4   r!   r7   r   rA   r   r)   r   rw   r#   r#   rf   r$   r     s      r   )2r4   r   r5   rZ   r   rl   abcr   r   collectionsr   r   PROTOCOL_TLSv1PROTOCOL_TLSv1_1PROTOCOL_TLSv1_2r   r   r   PROTOCOL_SSLv23r
   r   ImportErrortypingr   r   r   r   r   r   errorsr   r   r   typesr   r   r7   __annotations__r   r   r   rL   r!   r%   r&   r9   rb   rx   r   r   r#   r#   r#   r$   <module>   sH   
 Ga A :'