
    RSi                        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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dlmZ ddlmZ ddlmZ  e
j                    5   e
j        d	e           ddlZddlZddd           n# 1 swxY w Y    eed
ej                  Zej        Zej        Zej        ej        ej        ej         ej!        ej"        ej#        hZ$ e%ed          re$&                    ej'                    e%ed          re$&                    ej(                   ej)        ej*        hZ+ e%ed          re+&                    ej,                    G d d          Z- G d d          Z. G d de.          Z/ G d d          Z0 G d de0          Z1 G d de0          Z2 e%ed          r G d de2          Z3 e%ed          r G d de2          Z4 e%ed           r G d! d"e2          Z5 e%ed#          r G d$ d%e0          Z6 e%ed           re5Z7n/ e%ed#          re6Z7n  e%ed          re4Z7n e%ed          re3Z7ne1Z7 G d& d'ej8                  Z9 G d( d)e9          Z: G d* d+e9          Z;dS ),a  
A specialized IO loop on top of asyncore adding support for epoll()
on Linux and kqueue() and OSX/BSD, dramatically increasing performances
offered by base asyncore module.

poll() and select() loops are also reimplemented and are an order of
magnitude faster as they support fd un/registration and modification.

This module is not supposed to be used directly unless you want to
include a new dispatcher which runs within the main FTP server loop,
in which case:
  __________________________________________________________________
 |                      |                                           |
 | INSTEAD OF           | ...USE:                                   |
 |______________________|___________________________________________|
 |                      |                                           |
 | asyncore.dispacher   | Acceptor (for servers)                    |
 | asyncore.dispacher   | Connector (for clients)                   |
 | asynchat.async_chat  | AsyncChat (for a full duplex connection ) |
 | asyncore.loop        | FTPServer.server_forever()                |
 |______________________|___________________________________________|

asyncore.dispatcher_with_send is not supported, same for "map" argument
for asyncore.loop and asyncore.dispatcher and asynchat.async_chat
constructors.

Follows a server example:

import socket
from pyftpdlib.ioloop import IOLoop, Acceptor, AsyncChat

class Handler(AsyncChat):

    def __init__(self, sock):
        AsyncChat.__init__(self, sock)
        self.push('200 hello
')
        self.close_when_done()

class Server(Acceptor):

    def __init__(self, host, port):
        Acceptor.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.set_reuse_addr()
        self.bind((host, port))
        self.listen(5)

    def handle_accepted(self, sock, addr):
        Handler(sock)

server = Server('localhost', 2121)
IOLoop.instance().loop()
    N   )_RetryError)config_logging)debug)is_logging_configured)loggerignore	monotonicWSAECONNRESETWSAECONNABORTEDWSAEWOULDBLOCKc                   6    e Zd ZdZd Zd Zd Zd Zd Zd Z	dS )	
_Schedulerz;Run the scheduled functions due to expire soonest (if any).c                 "    g | _         d| _        d S Nr   )_tasks_cancellationsselfs    D/home/jrussi/.local/lib/python3.11/site-packages/pyftpdlib/ioloop.py__init__z_Scheduler.__init__s   s        c                     t                      }g }| j        rd|| j        d         j        k     rnMt          j        | j                  }|j        r| xj        dz  c_        n|                    |           | j        d|D ]u}|j        r"t          j	        | j        |           d|_        +	 |
                                 A# t          $ r( t          j        t          j                               Y rw xY w| j        dk    rL| j        t!          | j                  dz	  k    r,t#          d| j         d           |                                  	 t'          d| j        d         j        |z
            S # t(          $ r Y dS w xY w)z~Run the scheduled functions due to expire soonest and
        return the timeout of the next one (if any, else None).
        r   r   Fi   zre-heapifying z cancelled tasksN)timerr   timeoutheapqheappop	cancelledr   append_repushheappushcall	Exceptionr   error	traceback
format_exclenr   	reheapifymax
IndexError)r   nowcallsr"   s       r   pollz_Scheduler.pollx   s    ggk 	#T[^+++=--D~ ###q(###T""" k 	#  	5 	5D| t{D111$5		 5 5 5Y133444445 $$)<!*
 *
 H4#6HHHIIINN	q$+a.036777 	 	 	DD	s$   *B??/C10C1"E/ /
E=<E=c                 :    t          j        | j        |           dS )zRegister a _CallLater instance.N)r   r!   r   r   whats     r   registerz_Scheduler.register   s    t{D)))))r   c                 &    | xj         dz  c_         dS )zpUnregister a _CallLater instance.
        The actual unregistration will happen at a later time though.
        r   N)r   r/   s     r   
unregisterz_Scheduler.unregister   s     	q r   c                 r    d| _         d | j        D             | _        t          j        | j                   dS )z>Get rid of cancelled calls and reinitialize the internal heap.r   c                      g | ]}|j         	|S  )r   ).0xs     r   
<listcomp>z(_Scheduler.reheapify.<locals>.<listcomp>   s    AAAQQ[AqAAAr   N)r   r   r   heapifyr   s    r   r(   z_Scheduler.reheapify   s9    AA$+AAAdk"""""r   c                     | j         D ]S}	 |j        s|                                 # t          $ r( t	          j        t          j                               Y Pw xY w| j         d d = d| _        d S r   )	r   r   cancelr#   r   r$   r%   r&   r   )r   r8   s     r   closez_Scheduler.close   s     	5 	5A5{ HHJJJ 5 5 5Y133444445KNs   '/AAN)
__name__
__module____qualname____doc__r   r-   r1   r3   r(   r=   r6   r   r   r   r   p   su        EE     
% % %N* * *! ! !# # #         r   r   c                   J    e Zd ZdZdZd Zd Zd Zd ZeZ	d Z
d Zd	 Zd
 ZdS )
_CallLaterzCContainer object which instance is returned by ioloop.call_later().)	_args_delay_errback_kwargsr    _sched_targetr   r   c                    t          |          sJ | d            t          j        |cxk    rdk    sn J | d            || _        || _        || _        || _        |                    dd           | _        |                    d          | _	        d| _
        |sd| _        nt                      | j        z   | _        d| _        | j	                            |            d S )Nz is not callabler   z* is not greater than or equal to 0 secondsrF   
_schedulerF)callablesysmaxsizerE   rI   rD   rG   poprF   rH   r    r   r   r   r1   r   secondstargetargskwargss        r   r   z_CallLater.__init__   s    <<F!<!<!<<<<K7''''a'''''AAA (''


:t44jj.. 	1DLL 77T[0DLT"""""r   c                 "    | j         |j         k     S Nr   r   others     r   __lt__z_CallLater.__lt__   s    |em++r   c                 "    | j         |j         k    S rV   rW   rX   s     r   __le__z_CallLater.__le__   s    |u},,r   c           	          | j         t                              |           }nt          | j                   }|d| j        pdd| j        pdd| j        d| j        z  }d| dS )	Nz args=z[]z	, kwargs=z{}z, cancelled=z, secs=<>)rI   object__repr__reprrD   rG   r   rE   )r   sigs     r   ra   z_CallLater.__repr__   s}    <//$''CCt|$$CJ$L D  NNNKK	
 	
 3zzzr   c                 @    | j         s|                                  d S d S rV   )r   r<   r   excs     r   
_post_callz_CallLater._post_call   s'    ~ 	KKMMMMM	 	r   c                 (   | j         r
J d            d}	  | j        | j        i | j         n6# t          $ r)}|}| j        |                                  n Y d}~nd}~ww xY w|                     |           dS # |                     |           w xY w)zCall this scheduled function.already cancelledN)r   rI   rD   rG   r#   rF   rg   )r   rf   _s      r   r"   z_CallLater.call   s    >66#6666		!DL$*55555 	 	 	C}(  	 OOC     DOOC    s+   - A: 
A AA: A  A: :Bc                 l    | j         r
J d            t                      | j        z   | _        d| _        dS )z5Reschedule this call resetting the current countdown.ri   TN)r   r   rE   r   r    r   s    r   resetz_CallLater.reset  s6    >66#6666ww,r   c                     | j         s?d| _         dx| _        x| _        x| _        | _        | j                            |            dS dS )zUnschedule this call.TN)r   rI   rD   rG   rF   rH   r3   r   s    r   r<   z_CallLater.cancel  sU    ~ 	)!DNGKKDLK4:Kt}K""4(((((	) 	)r   N)r>   r?   r@   rA   	__slots__r   rZ   r\   ra   __str__rg   r"   rl   r<   r6   r   r   rC   rC      s        MM
I# # #(, , ,- - -   G  ! ! !  ) ) ) ) )r   rC   c                       e Zd ZdZd ZdS )
_CallEveryzCContainer object which instance is returned by IOLoop.call_every().c                     | j         sO|r|                                  d S t                      | j        z   | _        | j                            |            d S d S rV   )r   r<   r   rE   r   rH   r1   re   s     r   rg   z_CallEvery._post_call  s]    ~ 	+ +$ww4$$T*****	+ 	+r   N)r>   r?   r@   rA   rg   r6   r   r   rq   rq     s)        MM+ + + + +r   rq   c                       e Zd ZdZdZdZdZ ej                    Z	dZ
d Zd Zd Zd	 ZeZed
             Zed             Zd Zd Zd Zd ZddZd Zd Zd ZdS )_IOLoopz2Base class which will later be referred as IOLoop.r      NFc                 :    i | _         t                      | _        d S rV   )
socket_mapr   schedr   s    r   r   z_IOLoop.__init__(  s    \\


r   c                     | S rV   r6   r   s    r   	__enter__z_IOLoop.__enter__,  s    r   c                 .    |                                   d S rV   )r=   )r   rS   s     r   __exit__z_IOLoop.__exit__/  s    

r   c                    | j         j        dz   | j         j        z   g}|                    dt	          | j                   dt	          | j        j                   d           dd                    |          t          |           fz  S )N.z(fds=z, tasks=)z<%s at %#x> )
	__class__r?   r>   r   r'   rw   rx   r   joinid)r   statuss     r   ra   z_IOLoop.__repr__2  s    .+c1DN4KKLKC((KK#dj6G2H2HKKK	
 	
 	
  0 0"T((;;;r   c                     | j         5| j        5  | j          |             | _         ddd           n# 1 swxY w Y   | j         S )z Return a global IOLoop instance.N)	_instance_lockclss    r   instancez_IOLoop.instance;  s     =  * *=($'CEECM* * * * * * * * * * * * * * * }s   266c                      |             S )z!Constructs a new IOLoop instance.r6   r   s    r   factoryz_IOLoop.factoryD  s     suur   c                      t          d          )z8Register a fd, handled by instance for the given events.must be implemented in subclassNotImplementedErrorr   fdr   eventss       r   r1   z_IOLoop.registerI      !"CDDDr   c                      t          d          )zRegister fd.r   r   )r   r   s     r   r3   z_IOLoop.unregisterM  r   r   c                      t          d          )z#Changes the events assigned for fd.r   r   )r   r   r   s      r   modifyz_IOLoop.modifyQ  r   r   c                      t          d          )zPoll once.  The subclass overriding this method is supposed
        to poll over the registered handlers and the scheduled functions
        and then return.
        r   r   r   r   s     r   r-   z_IOLoop.pollU  s    
 ""CDDDr   Tc                    t           j        s(dt           _        t                      st                       |rX| j        }| j        }| j        j        }||r ||            |             |dS dS d}|r ||            |            }|dS dS | j        }| j        r|                     |           |j        r|                                S dS )a  Start the asynchronous IO loop.

        - (float) timeout: the timeout passed to the underlying
          multiplex syscall (select(), epoll() etc.).

        - (bool) blocking: if True poll repeatedly, as long as there
          are registered handlers and/or scheduled functions.
          If False poll only once and return the timeout of the next
          scheduled call (if any, else None).
        TN)rt   _started_oncer   r   r-   rw   rx   r   )r   r   blockingr-   rw   
sched_pollsoonest_timeoutrx   s           r   loopz_IOLoop.loop\  s%    $ 	!$(G!(** !
     	$9DJJ"  !DMMMJLLL ! ! ! ! ! ! #'  3D)))&0jllO ! 3 3 3 3 3 JE #		'"""| $zz||#$ $r   c                 8    | j         |d<   t          ||g|R i |S )a\  Calls a function at a later time.
        It can be used to asynchronously schedule a call within the polling
        loop without blocking it. The instance returned is an object that
        can be used to cancel or reschedule the call.

         - (int) seconds: the number of seconds to wait
         - (obj) target: the callable object to call later
         - args: the arguments to call it with
         - kwargs: the keyword arguments to call it with; a special
           '_errback' parameter can be passed: it is a callable
           called in case target function raises an exception.
        rK   )rx   rC   rP   s        r   
call_laterz_IOLoop.call_later  s0      $z|'6;D;;;F;;;r   c                 8    | j         |d<   t          ||g|R i |S )z7Schedules the given callback to be called periodically.rK   )rx   rq   rP   s        r   
call_everyz_IOLoop.call_every  s.    #z|'6;D;;;F;;;r   c                 *   t          d|            d| j        _        t          | j                                        d           }|D ]}	 |                                 # t          $ rD}|j        t          j	        k    r%t          j        t          j                               Y d}~ad}~wt          $ r( t          j        t          j                               Y w xY w| j                                         | j                                         dS )z.Closes the IOLoop, freeing any resources used.zclosing IOLoopNc                     | j         S rV   )_fileno)r8   s    r   <lambda>z_IOLoop.close.<locals>.<lambda>  s    19 r   )key)r   r   r   sortedrw   valuesr=   OSErrorerrnoEBADFr   r$   r%   r&   r#   clearrx   )r   	instancesinsterrs       r   r=   z_IOLoop.close  s   %%%#'  4?11339L9LMMM	 	5 	5D5

 9 9 99++L!5!7!7888 5 5 5Y133444445 	
s   A  
C*:B))2CC)NT)r>   r?   r@   rA   READWRITEr   	threadingLockr   r   r   rz   r|   ra   ro   classmethodr   r   r1   r3   r   r-   r   r   r   r=   r6   r   r   rt   rt     s>       <<DEIINEM" " "    < < < G  [   [E E EE E EE E EE E E($ ($ ($ ($T< < < < < <
    r   rt   c                   0    e Zd ZdZd Zd Zd Zd Zd ZdS )Selectzselect()-based poller.c                 V    t                               |            g | _        g | _        d S rV   )rt   r   _r_wr   s    r   r   zSelect.__init__  s(    r   c                     || j         vrT|| j         |<   || j        z  r| j                            |           || j        z  r| j                            |           d S d S d S rV   )rw   r   r   r   r   r   r   s       r   r1   zSelect.register  sy    T_$$"*DOB	! #r"""
" #r""""" %$# #r   c                     	 | j         |= n # t          $ r t          d|            Y nw xY w| j        | j        fD ](}	 |                    |           # t          $ r Y %w xY wd S )N2call: unregister(); fd was no longer in socket_map)rw   KeyErrorr   r   r   remove
ValueError)r   r   lss      r   r3   zSelect.unregister  s    	N## 	N 	N 	NFMMMMM	N7DG$ 	 	B		"   	 	s    ((A
AAc                     | j                             |          }|.|                     |           |                     |||           d S t	          d|            d S )Nz.call: modify(); fd was no longer in socket_map)rw   getr3   r1   r   r   r   r   r   s       r   r   zSelect.modify  sb    ""2&&OOBMM"dF+++++BDIIIIIr   c                 f   	 t          j         | j        | j        g |          \  }}}n# t          $ r Y d S w xY w| j        j        }|D ]3} ||          }||                                s$t          |           4|D ]3} ||          }||                                s$t          |           4d S rV   )
selectr   r   InterruptedErrorrw   r   readable_readwritable_write)r   r   rwrj   smap_getr   objs           r   r-   zSelect.poll  s    	mDGTWb'BBGAq!! 	 	 	FF	 ?& 	 	B(2,,C{#,,..{#JJJJ 	 	B(2,,C{#,,..{3KKKK		 	s   %( 
66N	r>   r?   r@   rA   r   r1   r3   r   r-   r6   r   r   r   r     sh            
# # #	 	 	J J J    r   r   c                   0    e Zd ZdZd Zd Zd Zd Zd ZdS )_BasePollEpollzThis is common to both poll() (UNIX), epoll() (Linux) and
    /dev/poll (Solaris) implementations which share almost the same
    interface.
    Not supposed to be used directly.
    c                 l    t                               |            |                                 | _        d S rV   )rt   r   _pollerr   s    r   r   z_BasePollEpoll.__init__  s)    ||~~r   c                     	 | j                             ||           n # t          $ r t          d|            Y nw xY w|| j        |<   d S Nz/call: register(); poller raised EEXIST; ignored)r   r1   FileExistsErrorr   rw   r   s       r   r1   z_BasePollEpoll.register  sk    	KL!!"f---- 	K 	K 	KCTJJJJJ	K&s    ;;c                 *   	 | j         |= 	 | j                            |           d S # t          $ r@}|j        t          j        t          j        fv rt          d|d|            n Y d }~d S d }~ww xY w# t          $ r t          d|            Y d S w xY w)N$call: unregister(); poller returned ; ignoring itr   )	rw   r   r3   r   r   ENOENTr   r   r   )r   r   r   s      r   r3   z_BasePollEpoll.unregister  s    	#
''+++++   9u{ ;;;'s ' ' '           	N 	N 	NFMMMMMM	Ns%   A4 ' 
A15A,,A14BBc                     	 | j                             ||           d S # t          $ r2 || j        v r'| j        |         }|                     |||           Y d S  w xY wrV   )r   r   FileNotFoundErrorrw   r1   r   r   r   r   s       r   r   z_BasePollEpoll.modify  s}    		LF+++++  	 	 	T_$$  ?2.b(F333333	s    7AAc                    |d}	 | j                             |          }n# t          $ r Y d S w xY w| j        j        }|D ]\  }} ||          }||| j        z  r|| j        z  s|                                 <|| j        z  r#|                                rt          |           || j
        z  r#|                                rt          |           d S )N)r   r-   r   rw   r   _ERRORr   handle_closer   r   r   r   r   )r   r   r   r   r   eventr   s          r   r-   z_BasePollEpoll.poll   s   ?G	\&&w//FF 	 	 	FF	 ?& 
	! 
	!IB8B<<D|t{" !549+< !!!####49$    $KKK4:% !$--// !4LLL
	! 
	!s   ! 
//Nr   r6   r   r   r   r     si         & & &' ' '  $
 
 
! ! ! ! !r   r   r-   c                   v    e Zd ZdZej        Zej        Zej	        ej
        z  ej        z  Zej        Zd Zd ZdS )Pollzpoll() based poller.c                 x    | j         |         }|                     |           |                     |||           d S rV   rw   r3   r1   r   s       r   r   zPoll.modifyD  <    ?2&DOOBMM"dF+++++r   c                 d    |t          |dz            }t                              | |           d S Ni  intr   r-   r   s     r   r-   z	Poll.pollI  5    "gn--g.....r   N)r>   r?   r@   rA   r   POLLINr   POLLOUTr   POLLERRPOLLHUPPOLLNVALr   r-   r   r   r6   r   r   r   r   <  sb        ""}&.06?B+	, 	, 	,
	/ 	/ 	/ 	/ 	/r   r   devpollc                       e Zd ZdZej        Zej        Zej	        ej
        z  ej        z  Zej        Z eej        d          rd Zd Zd Z eej        d          rd ZdS dS )	DevPollz2/dev/poll based poller (introduced in python 3.3).filenoc                 4    | j                                         S )zReturn devpoll() fd.r   r   r   s    r   r   zDevPoll.filenoa  s    |**,,,r   c                 x    | j         |         }|                     |           |                     |||           d S rV   r   r   s       r   r   zDevPoll.modifye  r   r   c                 d    |t          |dz            }t                              | |           d S r   r   r   s     r   r-   zDevPoll.pollj  r   r   r=   c                 l    t                               |            | j                                         d S rV   rt   r=   r   r   s    r   r=   zDevPoll.closes  s.    d###""$$$$$r   N)r>   r?   r@   rA   r   r   r   r   r   r   r   r   r   r   r   hasattrr   r   r-   r=   r6   r   r   r   r   V  s        @@}&.06?B. 76>8,, 	-- - -	, 	, 	,
	/ 	/ 	/ 76>7++ 	%% % % % %	% 	%r   r   epollc                   f    e Zd ZdZej        Zej        Zej	        ej
        z  Zej        Zd Zd ZdS )Epollzepoll() based poller.c                 4    | j                                         S )zReturn epoll() fd.r   r   s    r   r   zEpoll.fileno      <&&(((r   c                 l    t                               |            | j                                         d S rV   r   r   s    r   r=   zEpoll.close  .    MM$L     r   N)r>   r?   r@   rA   r   EPOLLINr   EPOLLOUTr   EPOLLERREPOLLHUPr   r   r   r   r=   r6   r   r   r  r  ~  s[        ##~6?2,	) 	) 	)	! 	! 	! 	! 	!r   r  kqueuec                   v    e Zd ZdZd Zd Zd Zd Zd Zd Z	d Z
eej        ej        ej        ej        fd	Zd
S )Kqueuezkqueue() based poller.c                 x    t                               |            t          j                    | _        i | _        d S rV   )rt   r   r   r
  _kqueue_activer   s    r   r   zKqueue.__init__  s.    T"""!=??DLDLLLr   c                 4    | j                                         S )zReturn kqueue() fd.)r  r   r   s    r   r   zKqueue.fileno  r  r   c                 l    t                               |            | j                                         d S rV   )rt   r=   r  r   s    r   r=   zKqueue.close  r  r   c                     || j         |<   	 |                     ||t          j                   n # t          $ r t          d|            Y nw xY w|| j        |<   d S r   )rw   _controlr   	KQ_EV_ADDr   r   r  r   s       r   r1   zKqueue.register  sx    "*DOBOb&&*:;;;;" O O OGNNNNNO%DLs   !. A
Ac                 L   	 | j         |= | j                            |          }	 |                     ||t          j                   d S # t          $ r@}|j        t          j        t          j	        fv rt          d|d|            n Y d }~d S d }~ww xY w# t          $ r Y d S w xY w)Nr   r   )rw   r  rO   r  r   KQ_EV_DELETEr   r   r   r   r   r   )r   r   r   r   s       r   r3   zKqueue.unregister  s    OB'))"--
MM"ff.ABBBBB   yU\5;$???+3 + + +              s(   "B !A 
B5BB
B#"B#c                 x    | j         |         }|                     |           |                     |||           d S rV   r   r   s       r   r   zKqueue.modify  s<    r*HOOBMM"h/////r   c                 H   g }|| j         z  r4|                    t          j        |t          j        |                     || j        z  s|s4|                    t          j        |t          j        |                     |D ]}| j                            |gd           d S )N)filterflagsr   )	r   r   r   keventKQ_FILTER_WRITEr   KQ_FILTER_READr  control)r   r   r   r  keventsr  s         r   r  zKqueue._control  s    G
" M6#9    
 	!  M6#8     " 2 2$$fXq11112 2r   c                     	 | j                             d  || j                  |          }n# t          $ r Y d S w xY w|D ]}| j                            |j                  }	|	$|j        |k    r#|	                                rt          |	           |j        |k    rB|j	        |z  r|	
                                 n#|	                                rt          |	           |j	        |z  r|	
                                 d S rV   )r  r  rw   r   r   identr  r   r   r  r   r   r   )
r   r   _len_READ_WRITE_EOFr   r  r  r   s
             r   r-   zKqueue.poll  s$   ,..$$t//  $   ! ( (**6<88<=E))dmmoo)$KKK=F**|d* 
% ))++++ %t<&( (%%''''( (s   *- 
;;N)r>   r?   r@   rA   r   r   r=   r1   r3   r   r  r'   r   r  r  	KQ_EV_EOFKQ_EV_ERRORr-   r6   r   r   r  r    s        $$	 	 	
	) 	) 	)	! 	! 	!	& 	& 	&	 	 	&	0 	0 	0
	2 	2 	22 ')!%"	( "	( "	( "	( "	( "	(r   r  c                   j    e Zd ZdZddZddZddZddZd Zd	 Z	dd
Z
d Zd Zd Zd Zd Zd ZdS )	AsyncChatzSame as asynchat.async_chat, only working with the new IO poller
    and being more clever in avoid registering for read events when
    it shouldn't.
    Nc                 .   |pt                                           | _        | j        j        | _        | j        j        | _        d| _        d| _        |r|                                nd | _	        g | _
        t          j                            | |           d S )NF)IOLoopr   ioloopr   _wanted_io_events_current_io_events_closed_closingr   r   r   asynchat
async_chatr   )r   sockr,  s      r   r   zAsyncChat.__init__  s~    1 1 1!%!1"&+"2(,6t{{}}}$$$T400000r   c                     | j         sJ t          | j                               ||n| j        j        }| j                            | j         | |           || _        || _        d S rV   )r   rb   r,  r   r1   r-  r.  r   mapr   s      r   add_channelzAsyncChat.add_channel*  sg    |//T$,/////!-4;3CT\4888!'"(r   c                 V    | j         !| j                            | j                    d S d S rV   )r   r,  r3   )r   r6  s     r   del_channelzAsyncChat.del_channel1  s0    <#K""4<00000 $#r   Fc                    | j         s| j        sJ t          | j                              | j        | j        j        vr(t          d|            |                     |           n|| j        k    r~|r\|| j        j        k    rd}n5|| j        j	        k    rd}n"|| j        j        | j        j	        z  k    rd}n|}t          d|d|            | j        
                    | j        |           || _        d S t          d	|            d S )
NzXcall: modify_ioloop_events(), fd was no longer in socket_map, had to register() it againr   )r   RWRWzcall: IOLoop.modify(); setting z
 IO eventszRcall: modify_ioloop_events(), handler had already been close()d, skipping modify())r/  r   rb   r,  rw   r   r7  r.  r   r   r   )r   r   logdebugevs       r   modify_ioloop_eventszAsyncChat.modify_ioloop_events5  sY   | 	<33dl!3!3333|4;#999=   
    ////4222 !111 4;#444 4;#3dk6G#GGG!#J"JJJ   ""4<888&,D###.     r   c                     d|vrt          | d          r
| j        |d<    | j        j        ||g|R i |}| j                            |           |S )zeSame as self.ioloop.call_later but also cancel()s the
        scheduled function on close().
        rF   handle_error)r   rC  r,  r   r   r   )r   rQ   rR   rS   rT   callbacks         r   r   zAsyncChat.call_laterX  sl     V##n(E(E#!%!2F:)4;)'6KDKKKFKK8$$$r   c                     |                      | j        j                   t          j                            | |           d S rV   )rA  r,  r   r1  r2  connect)r   addrs     r   rF  zAsyncChat.connectd  s:    !!$+"3444##D$/////r   c                    | j         J |\  }}d}t          j        ||t           j        t           j        dt           j                  }|D ]}d| _         |\  }}	}
}}	 |                     ||	           |rH|d                             d          r|d         dd         |d         f}|                     |           |                     ||f           nT# t          $ rG}|}| j         4| j         
                                 |                                  d| _         Y d}~d}~ww xY w | j         #|                                  t          |          |S )zsSame as connect() but guesses address family from addr.
        Return the address family just determined.
        N$getaddrinfo() returned an empty listr   z::ffff:   r   )socketgetaddrinfo	AF_UNSPECSOCK_STREAM
AI_PASSIVEcreate_socket
startswithbindrF  r   r=   r9  )r   rG  source_addresshostportr   inforesafsocktype_proto
_canonname_sarj   s                 r   connect_af_unspecifiedz AsyncChat.connect_af_unspecifiedh  s    {"""
d4!
 
  	 	CDK471B&*c""2x000! .%a(33I>>  +1-abb1*1-* IIn---dD\****   ;*K%%'''$$&&&"&DK ;#,,	s   A7C
D%=D  D%c                     	 | j                             |          S # t          $ rV}t          d| |            |j        t
          v rY d }~dS |j        t          v r|                                  Y d }~dS  d }~ww xY w)Nzcall: send(), err: r;  r   )rK  sendr   r   r   _ERRNOS_RETRY_ERRNOS_DISCONNECTEDr   )r   datar   s      r   r_  zAsyncChat.send  s    
	;##D))) 	 	 	---D9999yM))qqqqq222!!###qqqqq	s     
A<"A7"A76A77A<c                 6   	 | j                             |          }|s|                                  dS |S # t          $ rX}t	          d| |            |j        t          v r|                                  Y d }~dS |j        t          v rt          | d }~ww xY w)Nr   zcall: recv(), err: r;  )	rK  recvr   r   r   r   ra  r`  r   )r   buffer_sizerb  r   s       r   rd  zAsyncChat.recv  s    	;##K00D   !!###s!  	 	 	---D9999y000!!###sssssm++!s*	s   6 
B 6B<BBc                 h    	 t           j                            |            d S # t          $ r Y d S w xY wrV   )r1  r2  handle_readr   r   s    r   rg  zAsyncChat.handle_read  sF    	++D11111 	 	 	DD	s   # 
11c                 :   t           j                            |            | j        sc| j        s| j        j        }n| j        j        | j        j        z  }| j        |k    r)| j        	                    | j
        |           || _        d S d S t          d|            d S )Nz0call: initiate_send(); called with no connectionr;  )r1  r2  initiate_sendr/  producer_fifor,  r   r   r-  r   r   r   )r   wanteds     r   ri  zAsyncChat.initiate_send  s    ))$///| 	 % >)
 )DK,==%//""4<888)/&&& 0/ B     r   c                     t          | j                  dk    r|                                  d S d| _        t          j                            |            d S )Nr   T)r'   rj  r   r0  r1  r2  close_when_doner   s    r   rm  zAsyncChat.close_when_done  sT    t!""a'' DM//55555r   c                 2   | j         sd| _         	 t          j                            |            | j        D ]L}	 |                                 # t          $ r( t          j        t          j
                               Y Iw xY wg | _        d| _         d| _        d| _        d S # | j        D ]L}	 |                                 # t          $ r( t          j        t          j
                               Y Iw xY wg | _        d| _         d| _        d| _        w xY wd S )NTF)r/  r1  r2  r=   r   r<   r#   r   r$   r%   r&   r0  	connected)r   funs     r   r=   zAsyncChat.close  sB   | 	'DL'#))$///; = =C=

$ = = =Y%9%;%;<<<<<= # %!&  ; = =C=

$ = = =Y%9%;%;<<<<<= # %!&&&&&	' 	's@   B" A/B B"
D-CD/C4	1D3C4	4 DNNrV   )F)r>   r?   r@   rA   r   r7  r9  rA  r   rF  r]  r_  rd  rg  ri  rm  r=   r6   r   r   r)  r)    s         
1 1 1 1) ) ) )1 1 1 1   F  0 0 00 0 0 0n    *    (6 6 6' ' ' ' 'r   r)  c                       e Zd ZdZddZdS )	ConnectorzDSame as base AsyncChat and supposed to be used for
    clients.
    Nc                 T    t                               | || j        j                   d S N)r6  r   )r)  r7  r,  r   r5  s      r   r7  zConnector.add_channel  s(    dDK4EFFFFFr   rq  )r>   r?   r@   rA   r7  r6   r   r   rs  rs    s8         G G G G G Gr   rs  c                   d    e Zd ZdZddZd Zd Zd Zd Ze	j
        dv sej        d	k    rd
 ZdS dS )AcceptorzRSame as base AsyncChat and supposed to be used to
    accept new connections.
    Nc                 T    t                               | || j        j                   d S ru  )r)  r7  r,  r   r5  s      r   r7  zAcceptor.add_channel  s(    dDK4DEEEEEr   c                 j   | j         J |\  }}|sd}d}t          j        ||t           j        t           j        dt           j                  }|D ]}d| _         |                                  |\  }}}	}
}	 |                     ||           |                                  |                     |           nT# t          $ rG}|}| j         4| j         
                                 |                                  d| _         Y d}~d}~ww xY w | j         #|                                  t          |          |S )zpSame as bind() but guesses address family from addr.
        Return the address family just determined.
        NrI  r   )rK  rL  rM  rN  rO  r9  rP  set_reuse_addrrR  r   r=   )r   rG  rT  rU  r   rV  rW  rX  rY  rZ  r[  sarj   s                r   bind_af_unspecifiedzAcceptor.bind_af_unspecified  sh    {"""
d 	
 D4!
 
  	 	CDK360B&*b
""2x000##%%%		"   ;*K%%'''$$&&&"&DK ;#,,	s   4?B44
D>=D  Dc                     t                               | |           	 t          | j        t                    r,| j                            | j        | j        j                   d S d S # t          $ r Y d S w xY wrV   )	r)  listen
isinstancer,  r  r   r   r   	NameError)r   nums     r   r~  zAcceptor.listen/  s    s###	$+v.. C""4<1ABBBBBC C 	 	 	DD	s   AA% %
A32A3c                    	 |                                  \  }}||                     ||           d S d S # t          $ r t          d|            Y d S t          $ r1}|j        t
          j        k    r t          d|            Y d }~d S d }~ww xY w)Nz-call: handle_accept(); accept() returned Nonez5call: handle_accept(); accept() returned ECONNABORTED)accepthandle_accepted	TypeErrorr   r   r   ECONNABORTED)r   r3  rG  r   s       r   handle_acceptzAcceptor.handle_accept9  s    	1JD$$ $$T400000  #  	 	 	 A4HHHFF 		 		 		 yE...K        		s   5 B	B&BBc                 Z    |                                  |                     dd           d S )Nzunhandled accepted eventwarning)r=   log_info)r   r3  rG  s      r   r  zAcceptor.handle_acceptedP  s*    

0)<<<<<r   )ntcecygwinc                     d S rV   r6   r   s    r   rz  zAcceptor.set_reuse_addrW  s    Dr   rq  )r>   r?   r@   rA   r7  r|  r~  r  r  osnamerM   platformrz  r6   r   r   rw  rw    s         F F F F( ( (T  1 1 1.= = =
 	<S\X%=%=	 	 	 	 	 &>%=r   rw  )<rA   r   r   r  r   rK  rM   r   timer%   warnings
exceptionsr   logr   r   r   r   catch_warningssimplefilterDeprecationWarningr1  asyncoregetattrr   readr   writer   
ECONNRESETENOTCONN	ESHUTDOWNr  EPIPEr   	ETIMEDOUTra  r   addr   r   EAGAINEWOULDBLOCKr`  r   r   rC   rq   rt   r   r   r   r   r  r  r+  r2  r)  rs  rw  r6   r   r   <module>r     s  
4 4l   				   



           # # # # # #             & & & & & &      X  H($6777OOOOOO              
 	k49--	 
	N	O		K	K	O  75/"" 2U0111
75#$$ 4U2333 u01
75"## ,e*+++G  G  G  G  G  G  G  G TV) V) V) V) V) V) V) V)r	+ 	+ 	+ 	+ 	+ 	+ 	+ 	+N N N N N N N Nl3 3 3 3 3W 3 3 3vC! C! C! C! C!W C! C! C!T 766 // / / / /~ / / /0 769 !%% % % % %. % % %L 767 !! ! ! ! ! ! ! !* 768 j(h( h( h( h( h( h( h( h(^ 767 	FFWVX FFWVY FFWVV FFFY' Y' Y' Y' Y'# Y' Y' Y'xG G G G G	 G G G[ [ [ [ [y [ [ [ [ [s   A>>BB