î j fñ™ã @s dZdgZddlZddlZddlZddlZddlZyddlZWnek rudZYnXddl m Z ddl m Z ddl m Z ddl m Z dd l mZdd l mZdd l mZdd l mZdd lmZddlmZdd„ZGdd„de jƒZGdd„dejejƒZGdd„deƒZGdd„deƒZGdd„deƒZdS)zÄEvent loop using a selector and related classes. A selector is a "notify-when-ready" multiplexer. For a subclass which also includes support for signal handling, see the unix_events sub-module. ÚBaseSelectorEventLoopéNé)Ú base_events)Úcompat)Ú constants)Úevents)Úfutures)Ú selectors)Ú transports)Ússlproto)Ú coroutine)Úloggerc CsAy|j|ƒ}Wntk r+dSYnXt|j|@ƒSdS)NF)Úget_keyÚKeyErrorÚboolr)ÚselectorÚfdZeventÚkey©rúd?„Z d@dA„Z!dBdC„Z"dDdE„Z#‡S)FrzJSelector event loop. See events.EventLoop for API specification. NcsUtƒjƒ|dkr(tjƒ}ntjd|jjƒ||_|j ƒdS)NzUsing selector: %s) ÚsuperÚ__init__r ZDefaultSelectorr ÚdebugÚ __class__Ú__name__Ú _selectorÚ_make_self_pipe)Úselfr)rrrr0s    zBaseSelectorEventLoop.__init__ÚextraÚservercCst||||||ƒS)N)Ú_SelectorSocketTransport)rÚsockÚprotocolÚwaiterrr rrrÚ_make_socket_transport9sz,BaseSelectorEventLoop._make_socket_transportÚ server_sideFÚserver_hostnamec Cs{tjƒs:|j||||d|d|d|d|ƒStj||||||ƒ} t||| d|d|ƒ| jS)Nr&r'rr )r Z_is_sslproto_availableÚ_make_legacy_ssl_transportZ SSLProtocolr!Z_app_transport) rÚrawsockr#Ú sslcontextr$r&r'rr Z ssl_protocolrrrÚ_make_ssl_transport>s     z)BaseSelectorEventLoop._make_ssl_transportc Cs"t|||||||||ƒ S)N)Ú_SelectorSslTransport) rr)r#r*r$r&r'rr rrrr(Msz0BaseSelectorEventLoop._make_legacy_ssl_transportcCst||||||ƒS)N)Ú_SelectorDatagramTransport)rr"r#Úaddressr$rrrrÚ_make_datagram_transportWs z.BaseSelectorEventLoop._make_datagram_transportcsn|jƒrtdƒ‚n|jƒr+dS|jƒtƒjƒ|jdk rj|jjƒd|_ndS)Nz!Cannot close a running event loop)Z is_runningÚ RuntimeErrorÚ is_closedÚ_close_self_piperÚcloser)r)rrrr3\s     zBaseSelectorEventLoop.closecCs t‚dS)N)ÚNotImplementedError)rrrrÚ _socketpairgsz!BaseSelectorEventLoop._socketpaircCsU|j|jjƒƒ|jjƒd|_|jjƒd|_|jd8_dS)Nr)Ú remove_readerÚ_ssockÚfilenor3Ú_csockÚ _internal_fds)rrrrr2js     z&BaseSelectorEventLoop._close_self_pipecCsg|jƒ\|_|_|jjdƒ|jjdƒ|jd7_|j|jjƒ|jƒdS)NFr)r5r7r9Ú setblockingr:Ú add_readerr8Ú_read_from_self)rrrrrrs z%BaseSelectorEventLoop._make_self_pipecCsdS)Nr)rÚdatarrrÚ_process_self_datazsz(BaseSelectorEventLoop._process_self_datac Csbx[y-|jjdƒ}|s"Pn|j|ƒWqtk rGwYqtk rYPYqXqWdS)Ni)r7Úrecvr?ÚInterruptedErrorÚBlockingIOError)rr>rrrr=}s  z%BaseSelectorEventLoop._read_from_selfc Csa|j}|dk r]y|jdƒWq]tk rY|jrUtjdddƒnYq]XndS)Nsz3Fail to write a null byte into the self-pipe socketÚexc_infoT)r9ÚsendÚOSErrorÚ_debugr r)rZcsockrrrÚ_write_to_self‰s     z$BaseSelectorEventLoop._write_to_selfcCs)|j|jƒ|j||||ƒdS)N)r<r8Ú_accept_connection)rÚprotocol_factoryr"r*r rrrÚ_start_serving™sz$BaseSelectorEventLoop._start_servingc CsDyE|jƒ\}}|jr7tjd|||ƒn|jdƒWnÃtttfk rbYnÞtk r }z‰|j t j t j t j t j fkrõ|jidd6|d6|d6ƒ|j|jƒƒ|jtj|j||||ƒn‚WYdd}~Xn6Xi|d6}|j|||||ƒ} |j| ƒdS)Nz#%r got a new connection from %r: %rFz&socket.accept() out of system resourceÚmessageÚ exceptionÚsocketÚpeername)ÚacceptrFr rr;rBrAÚConnectionAbortedErrorrEÚerrnoZEMFILEZENFILEZENOBUFSZENOMEMÚcall_exception_handlerr6r8Z call_laterrZACCEPT_RETRY_DELAYrJÚ_accept_connection2Z create_task) rrIr"r*r ÚconnÚaddrÚexcrrOrrrrHžs0       z(BaseSelectorEventLoop._accept_connectionc cs5d}d}yž|ƒ}tjd|ƒ}|r`|j|||d|ddd|d|ƒ}n$|j||d|d|d|ƒ}y |DdHWn|jƒ‚YnXWn„tk r0} zd|jridd6| d 6} |dk rõ|| d ÚmodifyÚcancel) rrÚcallbackÚargsÚhandlerÚmaskÚreaderÚwriterrrrr<ås    z BaseSelectorEventLoop.add_readerc Cs½|jƒrdSy|jj|ƒ}Wntk r>dSYn{X|j|j}\}}|tjM}|s|jj|ƒn|jj ||d|fƒ|dk rµ|j ƒdSdSdS)zRemove a reader callback.FNT) r1rrrrr>r r_Ú unregisterr`ra)rrrrerfrgrrrr6õs     z#BaseSelectorEventLoop.remove_readerc GsÂ|jƒtj|||ƒ}y|jj|ƒ}Wn1tk rh|jj|tjd|fƒYnVX|j|j }\}}|jj ||tjB||fƒ|dk r¾|j ƒndS)zAdd a writer callback..N) r\rr]rrrr^r Ú EVENT_WRITEr>r`ra) rrrbrcrdrrerfrgrrrÚ add_writer s    z BaseSelectorEventLoop.add_writerc Cs½|jƒrdSy|jj|ƒ}Wntk r>dSYn{X|j|j}\}}|tjM}|s|jj|ƒn|jj |||dfƒ|dk rµ|j ƒdSdSdS)zRemove a writer callback.FNT) r1rrrrr>r rirhr`ra)rrrrerfrgrrrÚ remove_writers     z#BaseSelectorEventLoop.remove_writercCsV|jr*|jƒdkr*tdƒ‚ntjd|ƒ}|j|d||ƒ|S)zñReceive data from the socket. The return value is a bytes object representing the data received. The maximum amount of data to be received at once is specified by nbytes. This method is a coroutine. rzthe socket must be non-blockingrWF)rFÚ gettimeoutÚ ValueErrorrrYÚ _sock_recv)rr"ÚnÚfutrrrÚ sock_recv2s zBaseSelectorEventLoop.sock_recvcCsÁ|jƒ}|r"|j|ƒn|jƒr2dSy|j|ƒ}Wnhttfk r~|j||j|d||ƒYn?tk r¯}z|j |ƒWYdd}~XnX|j |ƒdS)NT) r8r6Ú cancelledr@rBrAr<rnrZÚ set_exceptionÚ set_result)rrpÚ registeredr"rorr>rVrrrrnAs  # z BaseSelectorEventLoop._sock_recvcCsl|jr*|jƒdkr*tdƒ‚ntjd|ƒ}|r[|j|d||ƒn |jdƒ|S)a¿Send data to the socket. The socket must be connected to a remote socket. This method continues to send data from data until either all data has been sent or an error occurs. None is returned on success. On error, an exception is raised, and there is no way to determine how much data, if any, was successfully processed by the receiving end of the connection. This method is a coroutine. rzthe socket must be non-blockingrWFN)rFrlrmrrYÚ _sock_sendallrt)rr"r>rprrrÚ sock_sendallVs  z"BaseSelectorEventLoop.sock_sendallcCsù|jƒ}|r"|j|ƒn|jƒr2dSy|j|ƒ}WnSttfk red}Yn6tk rš}z|j|ƒdSWYdd}~XnX|t|ƒkr½|j dƒn8|rÖ||d…}n|j ||j |d||ƒdS)NrT) r8rkrrrDrBrArZrsÚlenrtrjrv)rrprur"r>rrorVrrrrvjs"    z#BaseSelectorEventLoop._sock_sendallcCsœ|jr*|jƒdkr*tdƒ‚ntjd|ƒ}ytj||ƒWn2tk r„}z|j|ƒWYdd}~XnX|j|||ƒ|S)a Connect to a remote socket at address. The address must be already resolved to avoid the trap of hanging the entire event loop when the address requires doing a DNS lookup. For example, it must be an IP address, not an hostname, for AF_INET and AF_INET6 address families. Use getaddrinfo() to resolve the hostname asynchronously. This method is a coroutine. rzthe socket must be non-blockingrWN) rFrlrmrrYrZ_check_resolved_addressrsÚ _sock_connect)rr"r.rpÚerrrrrÚ sock_connect�s  z"BaseSelectorEventLoop.sock_connectcCs²|jƒ}y|j|ƒWn�ttfk ro|jtj|j|ƒƒ|j||j |||ƒYn?t k r }z|j |ƒWYdd}~XnX|j dƒdS)N) r8ZconnectrBrAZadd_done_callbackÚ functoolsÚpartialÚ_sock_connect_donerjÚ_sock_connect_cbrZrsrt)rrpr"r.rrVrrrry—s    z#BaseSelectorEventLoop._sock_connectcCs|j|ƒdS)N)rk)rrrprrrr~¨sz(BaseSelectorEventLoop._sock_connect_donecCs®|jƒrdSyA|jtjtjƒ}|dkrPt|d|fƒ‚nWnIttfk rkYn?tk rœ}z|j |ƒWYdd}~XnX|j dƒdS)NrzConnect call failed %s) rrZ getsockoptrMZ SOL_SOCKETZSO_ERRORrErBrArZrsrt)rrpr"r.rzrVrrrr«s   z&BaseSelectorEventLoop._sock_connect_cbcCsS|jr*|jƒdkr*tdƒ‚ntjd|ƒ}|j|d|ƒ|S)a|Accept a connection. The socket must be bound to an address and listening for connections. The return value is a pair (conn, address) where conn is a new socket object usable to send and receive data on the connection, and address is the address bound to the socket on the other end of the connection. This method is a coroutine. rzthe socket must be non-blockingrWF)rFrlrmrrYÚ _sock_accept)rr"rprrrÚ sock_accept¼s z!BaseSelectorEventLoop.sock_acceptcCsÔ|jƒ}|r"|j|ƒn|jƒr2dSy#|jƒ\}}|jdƒWnettfk r‹|j||j|d|ƒYnEt k r¼}z|j |ƒWYdd}~XnX|j ||fƒdS)NFT) r8r6rrrOr;rBrAr<r€rZrsrt)rrprur"rrTr.rVrrrr€Ìs    z"BaseSelectorEventLoop._sock_acceptcCs¸x±|D]©\}}|j|j}\}}|tj@rn|dk rn|jr^|j|ƒqn|j|ƒn|tj@r|dk r|jr |j|ƒq°|j|ƒqqWdS)N) Úfileobjr>r r_Z _cancelledr6Z _add_callbackrirk)rZ event_listrrer‚rfrgrrrÚ_process_eventsÜs  z%BaseSelectorEventLoop._process_eventscCs!|j|jƒƒ|jƒdS)N)r6r8r3)rr"rrrÚ _stop_servingêsz#BaseSelectorEventLoop._stop_serving)$rÚ __module__Ú __qualname__Ú__doc__rr%r+r(r/r3r5r2rr?r=rGrJrHr rSr<r6rjrkrqrnrwrvr{ryr~rr�r€rƒr„rr)rrr*sL          !#               csµeZdZdZeZdZdd‡fdd†Zdd„Zdd „Z d d „Z d d „Z e j r~dd„Znddd„Zdd„Zdd„Zdd„Z‡S)Ú_SelectorTransportéiNc søtƒj||ƒ||jd<|jƒ|jdz<%s>ú )rrrŒÚappendr”r�Ú_loopr1rrr r_riÚget_write_buffer_sizeÚjoin)rÚinfor—ÚstateÚbufsizerrrÚ__repr__s*       z_SelectorTransport.__repr__cCs|jdƒdS)N)Ú _force_close)rrrrÚabort+sz_SelectorTransport.abortcCs|jS)N)r”)rrrrÚ is_closing.sz_SelectorTransport.is_closingcCs^|jr dSd|_|jj|jƒ|jsZ|jd7_|jj|jdƒndS)NTr)r”ršr6r�r’r“Ú call_soonÚ_call_connection_lost)rrrrr31s   z_SelectorTransport.closecCs7|jdk r3tjd|tƒ|jjƒndS)Nzunclosed transport %r)rŒÚwarningsÚwarnÚResourceWarningr3)rrrrÚ__del__>sz_SelectorTransport.__del__zFatal error on transportcCs†t|tttfƒrF|jjƒrutjd||ddƒqun/|jji|d6|d6|d6|j d6ƒ|j |ƒdS)Nz%r: %srCTrKrLrXr#) Ú isinstanceÚBrokenPipeErrorÚConnectionResetErrorrPršÚ get_debugr rrRrŽr¡)rrVrKrrrÚ _fatal_errorCs  z_SelectorTransport._fatal_errorcCsŠ|jr dS|jr9|jjƒ|jj|jƒn|jsad|_|jj|jƒn|jd7_|jj|j |ƒdS)NTr) r“r’Úclearršrkr�r”r6r¤r¥)rrVrrrr¡Rs     z_SelectorTransport._force_closec Cs{z |jr|jj|ƒnWd|jjƒd|_d|_d|_|j}|dk rv|jƒd|_nXdS)N)r�rŽZconnection_lostrŒr3ršr�Z_detach)rrVr rrrr¥^s        z(_SelectorTransport._call_connection_lostcCs t|jƒS)N)rxr’)rrrrr›lsz(_SelectorTransport.get_write_buffer_sizei)rr…r†Úmax_sizeÚ bytearrayr‘rŒrr r¢r£r3rZPY34r©r®r¡r¥r›rr)rrrˆïs      rˆcseZdZddd‡fdd†Zdd„Zdd„Zdd „Zd d „Zd d „Zdd„Z dd„Z ‡S)r!Ncs•tƒj|||||ƒd|_d|_|jj|jj|ƒ|jj|jj|j |j ƒ|dk r‘|jjt j |dƒndS)NF) rrÚ_eofÚ_pausedršr¤rŽÚconnection_mader<r�Ú _read_readyrÚ_set_result_unless_cancelled)rrWr"r#r$rr )rrrrrs   z!_SelectorSocketTransport.__init__cCsr|jrtdƒ‚n|jr0tdƒ‚nd|_|jj|jƒ|jjƒrntjd|ƒndS)Nz#Cannot pause_reading() when closingzAlready pausedTz%r pauses reading) r”r0r³ršr6r�r­r r)rrrrÚ pause_reading�s   z&_SelectorSocketTransport.pause_readingcCsm|jstdƒ‚nd|_|jr.dS|jj|j|jƒ|jjƒritj d|ƒndS)Nz Not pausedFz%r resumes reading) r³r0r”ršr<r�rµr­r r)rrrrÚresume_reading‹s   z'_SelectorSocketTransport.resume_readingcCsÜy|jj|jƒ}WnLttfk r3Yn¥tk rg}z|j|dƒWYdd}~XnqX|r�|jj|ƒnW|j j ƒr£t j d|ƒn|jj ƒ}|rÎ|j j|jƒn |jƒdS)Nz$Fatal read error on socket transportz%r received EOF)rŒr@r°rBrArZr®rŽÚ data_receivedršr­r rÚ eof_receivedr6r�r3)rr>rVÚ keep_openrrrrµ•s#z$_SelectorSocketTransport._read_readycCsVt|tttfƒs0tdt|ƒƒ‚n|jrHtdƒ‚n|sRdS|jr�|jt j kr}t j dƒn|jd7_dS|j s8y|jj|ƒ}WnPttfk rÉYnStk r}z|j|dƒdSWYdd}~XnX||d…}|sdS|jj|j|jƒn|j j|ƒ|jƒdS)Nz#data argument must be byte-ish (%r)z%Cannot call write() after write_eof()zsocket.send() raised exception.rz%Fatal write error on socket transport)rªÚbytesr±Ú memoryviewÚ TypeErrorÚtyper²r0r“rÚ!LOG_THRESHOLD_FOR_CONNLOST_WRITESr Úwarningr’rŒrDrBrArZr®ršrjr�Ú _write_readyÚextendÚ_maybe_pause_protocol)rr>rorVrrrÚwrite«s4   z_SelectorSocketTransport.writecCsy|jj|jƒ}Wnlttfk r3YnÏtk r‡}z5|jj|jƒ|jj ƒ|j |dƒWYdd}~Xn{X|r¡|jd|…=n|j ƒ|js|jj|jƒ|j rà|j dƒq|jr|jjtjƒqndS)Nz%Fatal write error on socket transport)rŒrDr’rBrArZršrkr�r¯r®Ú_maybe_resume_protocolr”r¥r²ÚshutdownrMÚSHUT_WR)rrorVrrrrÂÎs" #    z%_SelectorSocketTransport._write_readycCs9|jr dSd|_|js5|jjtjƒndS)NT)r²r’rŒrÇrMrÈ)rrrrÚ write_eofäs    z"_SelectorSocketTransport.write_eofcCsdS)NTr)rrrrÚ can_write_eofësz&_SelectorSocketTransport.can_write_eof) rr…r†rr·r¸rµrÅrÂrÉrÊrr)rrr!ps   #  r!csšeZdZeZddddd‡fdd†Zddd„Zdd„Zd d „Zd d „Z d d„Z dd„Z dd„Z dd„Z ‡S)r,NFc stdkrtdƒ‚n|s6tj||ƒ}ni|d6dd6} |rd| rd|| drVr»rrrrµzs0     #z!_SelectorSslTransport._read_readycCs†|jrMd|_|jƒ|jp+|jsM|jj|j|jƒqMn|jr@y|jj |jƒ}Wn²t t t j fk r•d}Yn�t jk rËd}|jj|jƒd|_YnYtk r#}z9|jj|jƒ|jjƒ|j|dƒdSWYdd}~XnX|r@|jd|…=q@n|jƒ|js‚|jj|jƒ|jr‚|jdƒq‚ndS)NFrTz"Fatal write error on SSL transport)rÛrµr³r”ršr<r�r’rŒrDrBrArËrØr×rkrÜrZr¯r®rÆr¥)rrorVrrrršs4          z"_SelectorSslTransport._write_readycCs»t|tttfƒs0tdt|ƒƒ‚n|s:dS|jrx|jtjkret j dƒn|jd7_dS|j s�|j j |j|jƒn|j j|ƒ|jƒdS)Nz#data argument must be byte-ish (%r)zsocket.send() raised exception.r)rªr¼r±r½r¾r¿r“rrÀr rÁr’ršrjr�rÂrÃrÄ)rr>rrrrÅ»s  z_SelectorSslTransport.writecCsdS)NFr)rrrrrÊÏsz#_SelectorSslTransport.can_write_eof)rr…r†r±r‘rrÓrÑr·r¸rµrÂrÅrÊrr)rrr,ïs " ?  ! r,csgeZdZejZddd‡fdd†Zdd„Zdd„Zddd „Z d d „Z ‡S) r-Ncs‰tƒj||||ƒ||_|jj|jj|ƒ|jj|jj|j|j ƒ|dk r…|jjt j |dƒndS)N) rrÚ_addressršr¤rŽr´r<r�rµrr¶)rrWr"r#r.r$r)rrrr×s  z#_SelectorDatagramTransport.__init__cCstdd„|jDƒƒS)Ncss!|]\}}t|ƒVqdS)N)rx)Ú.0r>Ú_rrrú åszC_SelectorDatagramTransport.get_write_buffer_size..)Úsumr’)rrrrr›äsz0_SelectorDatagramTransport.get_write_buffer_sizecCs¹y|jj|jƒ\}}Wn€ttfk r9Yn|tk rm}z|jj|ƒWYdd}~XnHtk r¡}z|j |dƒWYdd}~XnX|jj ||ƒdS)Nz&Fatal read error on datagram transport) rŒZrecvfromr°rBrArErŽÚerror_receivedrZr®Zdatagram_received)rr>rUrVrrrrµçs"#z&_SelectorDatagramTransport._read_readycCsÉt|tttfƒs0tdt|ƒƒ‚n|s:dS|jrq|d|jfkrqtd|jfƒ‚n|jr¸|jr¸|jt j kr¥t j dƒn|jd7_dS|j sŸy7|jrà|jj|ƒn|jj||ƒdSWqŸttfk r+|jj|j|jƒYqŸtk rc}z|jj|ƒdSWYdd}~XqŸtk r›}z|j|dƒdSWYdd}~XqŸXn|j jt|ƒ|fƒ|jƒdS)Nz#data argument must be byte-ish (%r)z#Invalid address: must be None or %szsocket.send() raised exception.rz'Fatal write error on datagram transport)rªr¼r±r½r¾r¿rÝrmr“rrÀr rÁr’rŒrDÚsendtorBrAršrjr�Ú _sendto_readyrErŽrârZr®r™rÄ)rr>rUrVrrrrãós<   z!_SelectorDatagramTransport.sendtocCs@x÷|jrù|jjƒ\}}y3|jr@|jj|ƒn|jj||ƒWqttfk r…|jj||fƒPYqt k r½}z|j j |ƒdSWYdd}~Xqt k rõ}z|j |dƒdSWYdd}~XqXqW|jƒ|js<|jj|jƒ|jr<|jdƒq<ndS)Nz'Fatal write error on datagram transport)r’ÚpopleftrÝrŒrDrãrBrAÚ appendleftrErŽrârZr®rÆršrkr�r”r¥)rr>rUrVrrrräs*      z(_SelectorDatagramTransport._sendto_ready) rr…r†Ú collectionsÚdequer‘rr›rµrãrärr)rrr-Ós    'r-)r‡Ú__all__rçrQr|rMr¦rËÚ ImportErrorÚrrrrrr r r Z coroutinesr Úlogr rZ BaseEventLooprZ_FlowControlMixinZ Transportrˆr!r,r-rrrrÚs8         ÿÆ €ä