B
    à%Q[Û)  ã               @   sœ   d Z ddlmZmZ ddlZddlmZ ddlmZm	Z	m
Z
 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mZ dd
lmZmZ G dd„ deƒZdS )Ú
é    )ÚThreadÚLockNé   )Úget_config_parameter)ÚLDAPSSLConfigurationErrorÚLDAPStartTLSErrorÚLDAPOperationResult)ÚBaseStrategyÚRESPONSE_COMPLETE)ÚLDAPMessage)ÚlogÚlog_enabledÚformat_ldap_messageÚERRORÚNETWORKÚEXTENDED)ÚdecoderÚdecode_message_fastc               @   sr   e Zd ZdZG dd„ deƒZdd„ Zddd„Zd	d
„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ ZdS )ÚAsyncStrategyaU  
    This strategy is asynchronous. You send the request and get the messageId of the request sent
    Receiving data from socket is managed in a separated thread in a blocking mode
    Requests return an int value to indicate the messageId of the requested Operation
    You get the response with get_response, it has a timeout to wait for response to appear
    Connection.response will contain the whole LDAP response for the messageId requested in a dict form
    Connection.request will contain the result LDAP message in a dict form
    Response appear in strategy._responses dictionary
    c               @   s    e Zd ZdZdd„ Zdd„ ZdS )z"AsyncStrategy.ReceiverSocketThreadzE
        The thread that actually manage the receiver socket
        c             C   s   t  | ¡ || _tdƒ| _d S )NZSOCKET_SIZE)r   Ú__init__Ú
connectionr   Úsocket_size)ÚselfÚldap_connection© r   ú^C:\Users\HIRONO~1\AppData\Local\Temp\pip-install-6i93dh7p\ldap3\ldap3\strategy\asynchronous.pyr   7   s    
z+AsyncStrategy.ReceiverSocketThread.__init__c       
   
   C   s–  d}d}d}d}�xr|�r„|r¶y| j j | j¡}W nd ttjtfk
rX   | j jrTwY n@ tk
r– } z"t	t
ƒr„tt
dt|ƒ| j ƒ ‚ W dd}~X Y nX t|ƒdkr²||7 }d}nd}t |¡}|dksÔt|ƒ|k rÚd}qt|ƒ|kr| j j�r| j j |¡ t	tƒ�rttd|| j ƒ | j j�rBt|d|… ƒ}| j j |¡}n*tj|d|… tƒ d	�d }| j j |¡}t|d
 ƒ}	t	tƒ�r�ttd| j ƒ t	tƒ�r°ttd| j t|dƒƒ |d dk�rt|d dk�sÚt| j dƒ�rt|d dk�r<| j j j!�r| j j j! "| j ¡ n2d| j _#t	t
ƒ�r.tt
d| j j#| j ƒ t$| j j#ƒ‚n2d| j _#t	t
ƒ�rbtt
d| j j#| j ƒ t%| j j#ƒ‚| j `&|	dk�r<| j jj'�^ |	| j jj(k�r°| j jj(|	  )|¡ n|g| j jj(|	< |d dk�râ| j jj(|	  )t*¡ W dQ R X | j jj+�r| j j ,|	|¡ ||d… }|�rdnd}| j j-�s2|�r6dnd}q|d dk�rPd}qd| j _#t	t
ƒ�rvtt
d| j j#| j ƒ t%| j j#ƒ‚qW | j j .¡  dS )z¼
            Wait for data on socket, compute the length of the message and wait for enough bytes to decode the message
            Message are appended to strategy._responses
            ó    Tz<%s> for <%s>Nr   Féÿÿÿÿzreceived %d bytes via <%s>)Zasn1SpecZ	messageIDz received 1 ldap message via <%s>z!ldap message received via <%s>:%sz<<ÚtypeZextendedRespZresponseNamez1.3.6.1.4.1.1466.20037Ú_awaiting_for_async_start_tlsÚresultzno Tls object defined in Serverzasynchronous StartTls failed)ZsearchResEntryZsearchResRefZintermediateResponsez1.3.6.1.4.1.1466.20036z,unknown unsolicited notification from server)/r   ÚsocketÚrecvr   ÚOSErrorÚerrorÚAttributeErrorZreceive_timeoutÚ	Exceptionr   r   r   ÚstrÚlenr
   Zcompute_ldap_message_sizeÚusageZ_usageZupdate_received_messager   Zfast_decoderr   ZstrategyZdecode_response_fastr   Údecoder   Zdecode_responseÚintr   r   ÚhasattrÚserverZtlsZ
_start_tlsZ
last_errorr   r   r    Ú
async_lockÚ
_responsesÚappendr   Ú
can_streamZaccumulate_streamÚ	listeningÚclose)
r   ZunprocessedZget_more_dataÚlistenÚdataÚeÚlengthZ	ldap_respZdict_responseÚ
message_idr   r   r   Úrun<   sŠ    






*



z&AsyncStrategy.ReceiverSocketThread.runN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r:   r   r   r   r   ÚReceiverSocketThread2   s   r?   c             C   sB   t  | |¡ d| _d| _d| _d | _d | _d| _d | _t	ƒ | _
d S )NF)r
   r   ZsyncZno_real_dsaZpooledr0   Ú	_requestsr2   Úreceiverr   r/   )r   r   r   r   r   r   Ž   s    zAsyncStrategy.__init__Tc          	   C   sr   | j j�$ tƒ | _tƒ | _t | ||¡ W dQ R X |rny| j  ¡  W n( tk
rl   d| j j	_
d| j j	_Y nX dS )zV
        Open connection and start listen on the socket in a different thread
        N)r   Úconnection_lockÚdictr0   r@   r
   ÚopenZrefresh_server_infor	   r.   Z	_dsa_infoZ_schema_info)r   Zreset_usageZread_server_infor   r   r   rD   ™   s    

zAsyncStrategy.openc          	   C   s"   | j j� t | ¡ W dQ R X dS )z9
        Close connection and stop socket thread
        N)r   rB   r
   r4   )r   r   r   r   r4   ©   s    
zAsyncStrategy.closec             C   s   d| j _d| j _d| j _|S )zB
        Clears connection.response and returns messageId
        N)r   ÚresponseÚrequestr!   )r   r9   r   r   r   Úpost_send_search°   s    zAsyncStrategy.post_send_searchc             C   s   d| j _d| j _d| j _|S )zC
        Clears connection.response and returns messageId.
        N)r   rE   rF   r!   )r   r9   r   r   r   Úpost_send_single_response¹   s    z'AsyncStrategy.post_send_single_responsec             C   s4   | j js0t | j ¡| _d| j _d| j_| j ¡  dS )z-
        Start thread in daemon mode
        TN)r   r3   r   r?   rA   ÚdaemonÚstart)r   r   r   r   Ú_start_listenÂ   s
    zAsyncStrategy._start_listenc          	   C   sB   | j �2 || jkr0| j| d tkr0| j |¡nd}W dQ R X |S )zŠ
        Performs the capture of LDAP response for this strategy
        Checks lock to avoid race condition with receiver thread
        r   N)r/   r0   r   Úpop)r   r9   Ú	responsesr   r   r   Ú_get_responseÌ   s    6zAsyncStrategy._get_responsec             C   s   t ‚d S )N)ÚNotImplementedError)r   r   r   r   Ú	receivingÖ   s    zAsyncStrategy.receivingc             C   s   t ‚d S )N)rO   )r   r   r   r   Ú
get_streamÙ   s    zAsyncStrategy.get_streamc             C   s   t ‚d S )N)rO   )r   Úvaluer   r   r   Ú
set_streamÜ   s    zAsyncStrategy.set_streamN)TT)r;   r<   r=   r>   r   r?   r   rD   r4   rG   rH   rK   rN   rP   rQ   rS   r   r   r   r   r   &   s   	\
		

r   )r>   Ú	threadingr   r   r"   Ú r   Zcore.exceptionsr   r   r	   Zstrategy.baser
   r   Zprotocol.rfc4511r   Z	utils.logr   r   r   r   r   r   Z
utils.asn1r   r   r   r   r   r   r   Ú<module>   s    