o
    jsc                     @   s  d Z ddlmZ ddl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mZ dd	l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! dZ"dZ#dZ$dZ%dZ&z
ddl'm(Z(m)Z) W n e*y   ddl(m(Z(m)Z) Y nw G dd deZ+dS )
    )datetime)linesep)ThreadLock)sleep   )RESTARTABLEget_config_parameterAUTO_BIND_DEFAULTAUTO_BIND_NONEAUTO_BIND_NO_TLSAUTO_BIND_TLS_AFTER_BINDAUTO_BIND_TLS_BEFORE_BIND   )BaseStrategy)ConnectionUsage)&LDAPConnectionPoolNameIsMandatoryError!LDAPConnectionPoolNotStartedErrorLDAPOperationResultLDAPExceptionErrorLDAPResponseTimeoutError)loglog_enabledERRORBASIC)LDAP_MAX_INTTERMINATE_REUSABLE_CONNECTION)QueueEmptyc                   @   s   e Zd ZdZe Zdd Zdd Zdd Zdd	 Z	d
d Z
G dd deZG dd deZG dd deZdd Zd'ddZdd Zdd Zd(ddZdd Zd)d!d"Zd#d$ Zd%d& ZdS )*ReusableStrategya  
    A pool of reusable SyncWaitRestartable connections with lazy behaviour and limited lifetime.
    The connection using this strategy presents itself as a normal connection, but internally the strategy has a pool of
    connections that can be used as needed. Each connection lives in its own thread and has a busy/available status.
    The strategy performs the requested operation on the first available connection.
    The pool of connections is instantiated at strategy initialization.
    Strategy has two customizable properties, the total number of connections in the pool and the lifetime of each connection.
    When lifetime is expired the connection is closed and will be open again when needed.
    c                 C      t NNotImplementedErrorself r+   /root/aizidognhua/tmp/workspace/projects/ec89d86c-575f-41c9-af57-ac45cbdbf775/venv/lib/python3.10/site-packages/ldap3/strategy/reusable.py	receivingA      zReusableStrategy.receivingc                 C   r%   r&   r'   r)   r+   r+   r,   _start_listenD   r.   zReusableStrategy._start_listenc                 C   r%   r&   r'   )r*   
message_idtimeoutr+   r+   r,   _get_responseG   r.   zReusableStrategy._get_responsec                 C   r%   r&   r'   r)   r+   r+   r,   
get_streamJ   r.   zReusableStrategy.get_streamc                 C   r%   r&   r'   )r*   valuer+   r+   r,   
set_streamM   r.   zReusableStrategy.set_streamc                   @   sX   e Zd Z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d ZdS )zReusableStrategy.ConnectionPoolz6
        Container for the Connection Threads
        c                 C   s   |j tjv rFtj|j  }|jstj|j = t| S |jr&|j|jkr&|j|_|jr3|j	|jkr3|j|_	|j
rD|j
|j
krD|  |j
|_
|S t| S r&   )	pool_namer$   poolsstartedobject__new__pool_keepalive	keepalivepool_lifetimelifetime	pool_sizeterminate_pool)cls
connectionpoolr+   r+   r,   r:   U   s   


z'ReusableStrategy.ConnectionPool.__new__c                 C   s   t | ds\|j| _|| _g | _|jptd| _|jptd| _|j	| _
t | _d| _d| _d| _t | _d| _|jr=t nd | _d| _t | _| tj| j< d| _ttr^ttd|  d S d S d S )NworkersREUSABLE_THREADED_POOL_SIZEREUSABLE_THREADED_LIFETIMEFr   z!instantiated ConnectionPool: <%r>)hasattrr6   namemaster_connectionrD   r?   r
   r=   r>   r;   r<   r"   request_queue	open_pool	bind_pooltls_pooldict	_incomingcounter_usager   terminated_usage
terminatedr   	pool_lockr$   r7   r8   r   r   r   )r*   rB   r+   r+   r,   __init__f   s,   
z(ReusableStrategy.ConnectionPool.__init__c                 C   s  dt | j d | jrdnd }|dt t| j 7 }|dt | j 7 }|dt | j 7 }|dt | j 7 }|d	t | j 7 }|d
t | j	 7 }|dt | j
 t 7 }|dt | j t 7 }|d7 }| jrt| jD ]\}}|tt |d d t | 7 }qj|S |td 7 }|S )NzPOOL: z - status: r8   rS   z - responses in queue: z - pool size: z - lifetime: z - keepalive: z	 - open: z	 - bind: z - tls: zMASTER CONN: zWORKERS:   z: z    no active workers in pool)strrH   r8   lenrO   r?   r>   r<   rK   rL   rM   r   rI   rD   	enumeraterjust)r*   siworkerr+   r+   r,   __str__|   s     $z'ReusableStrategy.ConnectionPool.__str__c                 C   s   |   S r&   )r^   r)   r+   r+   r,   __repr__   s   z(ReusableStrategy.ConnectionPool.__repr__c              	   C   sX   | j D ]&}|j |jjjr|jjjsd|_nd|_W d    n1 s$w   Y  qd S NTF)rD   worker_lockrB   serverschemainfoget_info_from_serverr*   r]   r+   r+   r,   re      s   
z4ReusableStrategy.ConnectionPool.get_info_from_serverc              	   C   s^   | j D ])}|j |j| jj| jj| jj| jj| jj	 W d    n1 s'w   Y  qd S r&   )
rD   ra   rB   rebindrI   userpasswordauthenticationsasl_mechanismsasl_credentialsrf   r+   r+   r,   rebind_pool   s   
z+ReusableStrategy.ConnectionPool.rebind_poolc              	   C   sr   | j s7|   | jD ]}|j |j  W d    n1 sw   Y  q
d| _ d| _ttr5t	td|  dS dS )NTFzworker started for pool <%s>)
r8   create_poolrD   ra   threadstartrS   r   r   r   rf   r+   r+   r,   
start_pool   s   
z*ReusableStrategy.ConnectionPool.start_poolc                    s2   t tr
ttd   fddt jD  _d S )Nzcreated pool <%s>c                    s   g | ]
}t  j jqS r+   )r$   PooledConnectionWorkerrI   rJ   ).0_r)   r+   r,   
<listcomp>   s    z?ReusableStrategy.ConnectionPool.create_pool.<locals>.<listcomp>)r   r   r   ranger?   rD   r)   r+   r)   r,   rn      s   z+ReusableStrategy.ConnectionPool.create_poolc                 C   s   | j sBttrttd|  d| _| j  ttdd | j	D D ]}| j
td d d f q!| j  d| _ ttrDttd|  d S d S d S )Nzterminating pool <%s>Fc                 S   s   g | ]	}|j  r|qS r+   )ro   is_alive)rs   r]   r+   r+   r,   ru      s    zBReusableStrategy.ConnectionPool.terminate_pool.<locals>.<listcomp>Tzpool terminated for <%s>)rS   r   r   r   r8   rJ   joinrv   rX   rD   putTERMINATE_REUSABLE)r*   rt   r+   r+   r,   r@      s   

	z.ReusableStrategy.ConnectionPool.terminate_poolN)__name__
__module____qualname____doc__r:   rU   r^   r_   re   rm   rq   rn   r@   r+   r+   r+   r,   ConnectionPoolQ   s    	r   c                   @   s    e Zd ZdZdd Zdd ZdS )z'ReusableStrategy.PooledConnectionThreadz
        The thread that holds the Reusable connection and receive operation request via the queue
        Result are sent back in the pool._incoming list when ready
        c                 C   s8   t |  d| _|| _|| _ttrttd|  d S d S )NTz)instantiated PooledConnectionThread: <%r>)r   rU   daemonr]   rI   r   r   r   )r*   r]   rI   r+   r+   r,   rU      s   
z0ReusableStrategy.PooledConnectionThread.__init__c           
      C   sn  d| j _d}| jjj}|sz|jjd| jjjjd\}}}}W n ty5   | j j	j
s3| j j	d Y qw | j jR d| j _|tkrjd}| j j	jrhz| j j	  ttr[ttd W n tyg   Y nw nt | j j j| jjjjkrz| j j	  W n	 ty   Y nw | j   ttrttd |dvruz|jr| j j	j
r| j j	jdd |jr| j j	js| j j	jdd |j r| j j	js| j j	j!dd n|jr| j j	j
s|jr| j j	js| j j	jdd | j j"r|r| j j	#  d| j _"d }d }|d	kr| j j	$| j j	%|||}n| j j	&| j j	%|||}| j j	j'}|j( ||t)*|||f|j+|< W d    n	1 s?w   Y  W n/ t,yt }	 z"|j( |	d d f|j+|< W d    n	1 sew   Y  W Y d }	~	nd }	~	ww d| j _|j-  | j  j.d
7  _.W d    n	1 sw   Y  |rttrttd | jj/r| j0| j j	j/7  _0d| j _d S )NTF)blockr1   r   zthread terminatedzthread respawn)bindRequestunbindRequestread_server_infosearchRequestr   )1r]   runningrI   strategyrC   rJ   getr<   r#   rB   closedabandonra   busyrz   boundunbindr   r   r   r   r   nowcreation_timesecondsr>   new_connectionrK   openrM   tls_started	start_tlsrL   bindre   refresh_server_infopost_send_searchsendpost_send_single_responseresultrT   r   decode_requestrO   r   	task_donetask_counterusagerR   )
r*   	terminaterC   rP   message_typerequestcontrolsresponser   er+   r+   r,   run   s   
$









B

z+ReusableStrategy.PooledConnectionThread.runN)r{   r|   r}   r~   rU   r   r+   r+   r+   r,   PooledConnectionThread   s    	r   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	z'ReusableStrategy.PooledConnectionWorkerz
        Container for the restartable connection. it includes a thread and a lock to execute the connection in the pool
        c                 C   sl   || _ || _d| _d| _d| _d | _d | _d| _|   t	
| | j | _t | _ttr4ttd|  d S d S )NFr   z)instantiated PooledConnectionWorker: <%s>)rI   rJ   r   r   re   rB   r   r   r   r$   r   ro   r   ra   r   r   r   )r*   rB   rJ   r+   r+   r,   rU      s   z0ReusableStrategy.PooledConnectionWorker.__init__c                 C   s   dt | j t d }|| jrdnd7 }|d| jrdnd 7 }|dd| j   7 }|d	t | jjj	j
t | j j  7 }|d
t | j 7 }|S )NzCONN: z       THREAD: r   haltedz - r   	availablezcreated at: z - time to live: z - requests served: )rW   rB   r   r   r   r   	isoformatrI   r   rC   r>   r   r   r   r   )r*   r[   r+   r+   r,   r^   /  s   (z/ReusableStrategy.PooledConnectionWorker.__str__c                 C   s  ddl m} t | _|di d| jjr| jjn| jjd| jjd| jj	dt
d| jjd| jjd	td
| jjd| jjd| jjd| jjd| jjd| jjd| jjd| jjddd| jjd| jjd| jj| _| jjr| jjt
tfvrttrttd| j | jjdd | jjt kr| jj!dd n)| jjt"kr| jj#dd | jj!dd n| jjt$kr| jj!dd | jj#dd | jjr| jj| j_| jj%| j d S d S )Nr   )
Connectionrb   rh   ri   	auto_bindversionrj   client_strategyauto_referrals
auto_rangerk   rl   check_namescollect_usage	read_onlyraise_exceptionslazyFfast_decoderreceive_timeoutreturn_empty_attributesz"performing automatic bind for <%s>r   r+   )&core.connectionr   r   r   r   rI   server_poolrb   rh   ri   r   r   rj   r	   r   r   rk   rl   r   rQ   r   r   r   r   empty_attributesrB   r   r   r   r   r   r   r   r   r   r   r   
initialize)r*   r   r+   r+   r,   r   9  sr   
 	
z6ReusableStrategy.PooledConnectionWorker.new_connectionN)r{   r|   r}   r~   rU   r^   r   r+   r+   r+   r,   rr     s
    
rr   c                 C   s^   t | | d| _d| _d| _d| _t|dr"|jr"t	|| _
d S ttr+ttd td)NFTr6   z)reusable connection must have a pool_name)r   rU   syncno_real_dsapooled
can_streamrG   r6   r$   r   rC   r   r   r   r   )r*   ldap_connectionr+   r+   r,   rU   d  s   
zReusableStrategy.__init__Tc                 C   sH   d| j _| j   d| j_| jjr |s| jjjs"| jj  d S d S d S r`   )	rC   rK   rq   rB   r   r   rQ   initial_connection_start_timerp   )r*   reset_usager   r+   r+   r,   r   q  s   
zReusableStrategy.openc                 C   s6   | j   d| j _d| j_d| j_d| j _d| j _d S )NFT)rC   r@   rK   rB   r   r   rL   rM   r)   r+   r+   r,   r   z  s   
zReusableStrategy.terminatec                 C   s*   d| j _| j jr| j j jd7  _dS dS )z1
        Doesn't really close the socket
        Tr   N)rB   r   r   rQ   closed_socketsr)   r+   r+   r,   _close_socket  s   zReusableStrategy._close_socketNc                 C   s   | j jrk|dkrd| j _t}|S |dkrd| j _t}|S |dkr$t}|S |dkr4| jjr4d| j _t	}|S | j j
 | j  jd7  _| j jtkrKd| j _| j j}W d    n1 sYw   Y  | j j||||f |S ttrtttd td)	Nr   Tr   FabandonRequestextendedReqr   z$reusable connection pool not started)rC   r8   rL   
BOGUS_BINDBOGUS_UNBINDBOGUS_ABANDONrB   starting_tlsrM   BOGUS_EXTENDEDrT   rP   r   rJ   ry   r   r   r   r   )r*   r   r   r   rP   r+   r+   r,   r     s6   


zReusableStrategy.sendc                 C   s&  | j j| jjjks-| j j| jjjks-| j j| jjjks-| j j| jjjks-| j j| jjjkrU| j j| jj_| j j| jj_| j j| jj_| j j| jj_| j j| jj_| j  | jj	d j }|j
}d|_
| j jjrl| j jjsx| jj	d j j|d}n| jj	d j j|dd}|  ||_
|rd| j_|S )Nr   F)r   )r   r   T)rB   rh   rC   rI   ri   rj   rk   rl   rm   rD   r   rb   rc   rd   r   r   rL   )r*   r   temp_connectionold_lazyr   r+   r+   r,   validate_bind  s,   
zReusableStrategy.validate_bindFc              	   C   sj  t d}d }|d u rt d}|tkr t }dd ddddd d}n|tkr)d }d }nz|tkr<t }dd d	d
ddddd}ng|tkrSt }dd d	d
ddddd}d| j_nPd }d }|dkrz$| jjj	j
 | jjj	j|\}}}W d    n1 syw   Y  W n ty   t| ||8 }Y qWw 	 |dkrttrttd tdt|tr||r|||fS ||fS )NRESPONSE_SLEEPTIMERESPONSE_WAITING_TIMEOUTsuccessbindResponser    z<bogus Bind response>)description	referralstyper   dnmessage	saslCredsz1.3.6.1.4.1.1466.20037extendedRespNonez<bogus StartTls response>)r   r   responseNamer   r   responseValuer   r   Fz6no response from worker threads in Reusable connection)r
   r   listr   r   r   rB   r   r   rC   rT   rO   popKeyErrorr   r   r   r   r   
isinstancer   )r*   rP   r1   get_request	sleeptimer   r   r   r+   r+   r,   get_response  sP   



zReusableStrategy.get_responsec                 C      |S r&   r+   r*   rP   r+   r+   r,   r     r.   z*ReusableStrategy.post_send_single_responsec                 C   r   r&   r+   r   r+   r+   r,   r     r.   z!ReusableStrategy.post_send_search)TTr&   )NF)r{   r|   r}   r~   rN   r7   r-   r/   r2   r3   r5   r9   r   r   r   rr   rU   r   r   r   r   r   r   r   r   r+   r+   r+   r,   r$   5   s(    	qZH
	
	
,r$   N),r~   r   osr   	threadingr   r   timer   r   r	   r
   r   r   r   r   r   baser   
core.usager   core.exceptionsr   r   r   r   r   	utils.logr   r   r   r   protocol.rfc4511r   rz   r   r   r   r   queuer"   r#   ImportErrorr$   r+   r+   r+   r,   <module>   s,    $