3 § f‘Rã@s”dZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZdd„Zdd„Zd+dd„ZGd d „d ejƒZd,Zd ZGdd„de jƒZiZejdƒZejdƒZGdd„deƒZGdd„deƒZdd„Z Gdd„deƒZ!Gdd„de j"eƒZ#Gdd„deƒZ$Gdd„deƒZ%dd„Z&d d!„Z'Gd"d#„d#eƒZ(d$d%„Z)e*d&k�r�dd'l+m,Z,e,d(d)d*�dS)-aRPC Implementation, originally written for the Python Idle IDE For security reasons, GvR requested that Idle's Python execution server process connect to the Idle process, which listens for the connection. Since Idle has only one client per server, this was not a limitation. +---------------------------------+ +-------------+ | socketserver.BaseRequestHandler | | SocketIO | +---------------------------------+ +-------------+ ^ | register() | | | unregister()| | +-------------+ | ^ ^ | | | | + -------------------+ | | | | +-------------------------+ +-----------------+ | RPCHandler | | RPCClient | | [attribute of RPCServer]| | | +-------------------------+ +-----------------+ The RPCServer handler class is expected to provide register/unregister methods. RPCHandler inherits the mix-in class SocketIO, which provides these methods. See the Idle run.main() docstring for further information on how this was accomplished in Idle. éNcCstj|ƒ}t|tjƒst‚|S)z*Return code object from marshal string ms.)ÚmarshalÚloadsÚ isinstanceÚtypesÚCodeTypeÚAssertionError)ÚmsÚco©r ú0/opt/alt/python36/lib64/python3.6/idlelib/rpc.pyÚ unpickle_code-s r cCs$t|tjƒst‚tj|ƒ}t|ffS)zBReturn unpickle function and tuple with marshalled co code object.)rrrrrÚdumpsr )r rr r r Ú pickle_code3s rcCs$tjƒ}t||ƒ}|j|ƒ|jƒS)z.Return pickled (or marshalled) string for obj.)ÚioÚBytesIOÚ CodePicklerÚdumpÚgetvalue)ÚobjZprotocolÚfÚpr r r r 9s  r c@s"eZdZejeiZejejƒdS)rN) Ú__name__Ú __module__Ú __qualname__rrrÚdispatch_tableÚupdateÚcopyregr r r r rBs réiz 127.0.0.1c@s6eZdZd dd„Zdd„Zdd„Zdd „Zd d „ZdS) Ú RPCServerNcCs |dkr t}tjj|||ƒdS)N)Ú RPCHandlerÚ socketserverÚ TCPServerÚ__init__)ÚselfÚaddrZ handlerclassr r r r"LszRPCServer.__init__cCsdS)z@Override TCPServer method, no bind() phase for connecting entityNr )r#r r r Ú server_bindQszRPCServer.server_bindcCs|jj|jƒdS)zÎOverride TCPServer method, connect() instead of listen() Due to the reversed connection, self.server_address is actually the address of the Idle Client to which we are connecting. N)ÚsocketZconnectÚserver_address)r#r r r Úserver_activateUszRPCServer.server_activatecCs |j|jfS)z:Override TCPServer method, return already connected socket)r&r')r#r r r Ú get_request^szRPCServer.get_requestc Csºy‚Wn®tk r‚Ynštj}tddd|d�td|d�tdtjƒj|d�td||d�tdt|ƒ|d�tj |d�td |d�tdd|d�t j d ƒYnXd S) zÜOverride TCPServer method Error message goes to __stderr__. No error message if exiting normally or socket raised EOF. Other exceptions not handled in server code will cause os._exit. Ú ú-é()ÚfilezUnhandled server exception!z Thread: %szClient Address: z Request: z# *** Unrecoverable, server exiting!rN) Ú SystemExitÚsysÚ __stderr__ÚprintÚ threadingÚcurrent_threadÚnameÚreprÚ tracebackÚ print_excÚosÚ_exit)r#ÚrequestZclient_addressZerfr r r Ú handle_errorbs   zRPCServer.handle_error)N)rrrr"r%r(r)r;r r r r rJs   rc@söeZdZdZd;dd„Zdd„Zdd„Zd d „Zd d „Zd d„Z dd„Z dd„Z dd„Z dd„Z dd„Zdd„Zdd„Zdd„Zdd „Zd!d"„Zd#d$„Zd%d&„Zd'd(„Zd)d*„Zd+Zd,ZdZd-d.„Zd/d0„Zd1d2„Zd3d4„Zd5d6„Zd7d8„Z d9d:„Z!dS)<ÚSocketIOrNcCs@tjƒ|_|dk r||_||_|dkr*t}||_i|_i|_dS)N) r2r3Ú sockthreadÚ debuggingÚsockÚ objecttableÚobjtableÚ responsesÚcvars)r#r?rAr>r r r r"…s zSocketIO.__init__cCs |j}d|_|dk r|jƒdS)N)r?Úclose)r#r?r r r rD�szSocketIO.closecCstjdƒdS)z!override for specific exit actionrN)r8r9)r#r r r Úexithook–szSocketIO.exithookcGsR|js dS|jdttjƒjƒ}x|D]}|dt|ƒ}q(Wt|tjd�dS)Nú )r-) r>ÚlocationÚstrr2r3r4r1r/r0)r#ÚargsÚsÚar r r Údebugšs  zSocketIO.debugcCs||j|<dS)N)rA)r#ÚoidÚobjectr r r Úregister¢szSocketIO.registerc Cs&y |j|=Wntk r YnXdS)N)rAÚKeyError)r#rMr r r Ú unregister¥s zSocketIO.unregistercCs´|jd|ƒy|\}\}}}}Wntk r4dSX||jkrNdd|ffS|j|}|dkrvi} t|| ƒd| fS|dkr”i} t|| ƒd| fSt||ƒs¬dd|ffSt||ƒ} y^|d krä| ||Ž} t| tƒrÜt | ƒ} d| fS|d k�rt j || ||ffƒdSdd |fSWnšt k �r,‚Yn„t k �rB‚Ynntk �rX‚YnXtk �r|} zd | fSd} ~ Xn4d}t||| |ftjd�tjtjd�dSdS)Nz localcall:ÚERRORúBad request formatzUnknown object id: %rÚ __methods__ÚOKÚ__attributes__zUnsupported method name: %rÚCALLÚQUEUEÚQUEUEDzUnsupported message type: %sÚCALLEXCzU*** Internal Error: rpc.py:SocketIO.localcall() Object: %s Method: %s Args: %s )r-Ú EXCEPTION)rRrS)rYN)r[N)rLÚ TypeErrorrAÚ _getmethodsÚ_getattributesÚhasattrÚgetattrrÚ RemoteObjectÚ remoterefÚ request_queueZputr.ÚKeyboardInterruptÚOSErrorÚ Exceptionr1r/r0r6r7)r#Úseqr:ÚhowrMÚ methodnamerIÚkwargsrÚmethodsÚ attributesÚmethodZretZexÚmsgr r r Ú localcall«sT          zSocketIO.localcallcCs(|jd||ƒ|j||||ƒ}|j|ƒS)Nzremotecall:asynccall: )rLÚ asynccallÚ asyncreturn)r#rMrirIrjrgr r r Ú remotecallÙszSocketIO.remotecallcCs(|jd||ƒ|j||||ƒ}|j|ƒS)Nzremotequeue:asyncqueue: )rLÚ asyncqueuerq)r#rMrirIrjrgr r r Ú remotequeueÞszSocketIO.remotequeuecCs`d||||ff}|jƒ}tjƒ|jkr8tjƒ}||j|<|jd|||||ƒ|j||fƒ|S)NrWz asynccall:%d:)Únewseqr2r3r=Ú ConditionrCrLÚ putmessage)r#rMrirIrjr:rgÚcvarr r r rpãs zSocketIO.asynccallcCs`d||||ff}|jƒ}tjƒ|jkr8tjƒ}||j|<|jd|||||ƒ|j||fƒ|S)NrXzasyncqueue:%d:)rur2r3r=rvrCrLrw)r#rMrirIrjr:rgrxr r r rsís zSocketIO.asyncqueuecCs6|jd|ƒ|j|dd�}|jd||ƒ|j|ƒS)Nz#asyncreturn:%d:call getresponse(): gš™™™™™©?)Úwaitzasyncreturn:%d:response: )rLÚ getresponseÚdecoderesponse)r#rgÚresponser r r rq÷szSocketIO.asyncreturncCs–|\}}|dkr|S|dkr dS|dkr6|jdƒdS|dkrT|jdƒ|jƒdS|dkrp|jd|ƒt|ƒ‚|d krˆ|jd |ƒ|‚t||ƒ‚dS) NrUrYr[zdecoderesponse: EXCEPTIONÚEOFzdecoderesponse: EOFrRzdecoderesponse: Internal ERROR:rZzdecoderesponse: Call Exception:)rLÚdecode_interrupthookÚ RuntimeErrorÚ SystemError)r#r|rhÚwhatr r r r{ýs&    zSocketIO.decoderesponsecCst‚dS)ÚN)ÚEOFError)r#r r r r~szSocketIO.decode_interrupthookc Cs6y|jddd�Wntk r0|jdƒdSXdS)z¥Listen on socket until I/O not ready or EOF pollresponse() will loop looking for seq number None, which never comes, and exit on EOFError. Ngš™™™™™©?)Úmyseqryzmainloop:return)rzrƒrL)r#r r r Úmainloops  zSocketIO.mainloopcCs6|j||ƒ}|dk r2|\}}|dkr2||j|ƒf}|S)NrU)Ú _getresponseÚ_proxify)r#r„ryr|rhr�r r r rz#s  zSocketIO.getresponsecCs4t|tƒrt||jƒSt|tƒr0tt|j|ƒƒS|S)N)rÚ RemoteProxyÚRPCProxyrMÚlistÚmapr‡)r#rr r r r‡+s    zSocketIO._proxifycCs |jd|ƒtjƒ|jkr:x€|j||ƒ}|dk r|SqWnb|j|}|jƒx||jkrb|jƒqNW|j|}|jd||fƒ|j|=|j|=|j ƒ|SdS)Nz_getresponse:myseq:z-_getresponse:%s: thread woke up: response: %s) rLr2r3r=Ú pollresponserCÚacquirerBryÚrelease)r#r„ryr|rxr r r r†3s"        zSocketIO._getresponsecCs|jd|_}|S)Né)Únextseq)r#rgr r r ruIszSocketIO.newseqcCsÔ|jd|dƒy t|ƒ}Wn,tjk rJtdt|ƒtjd�‚YnXtj dt |ƒƒ|}xnt |ƒdkrÎy0t j g|j ggƒ\}}}|j j |dt…ƒ}Wn ttfk r¾tdƒ‚YnX||d…}qbWdS)Nzputmessage:%d:rzCannot pickle:)r-z .   I r<c@s eZdZdS)raN)rrrr r r r raêsracCst|ƒ}|t|<t|ƒS)N)Úidr@rˆ)rrMr r r rbïsrbc@seZdZdd„ZdS)rˆcCs ||_dS)N)rM)r#rMr r r r"÷szRemoteProxy.__init__N)rrrr"r r r r rˆõsrˆc@s,eZdZdZdZdd„Zdd„Zdd„Zd S) rFz#ScCs(||_tj||ƒtjj||||ƒdS)N)Zcurrent_handlerr<r"r ÚBaseRequestHandler)r#r?r$Zsvrr r r r"s zRPCHandler.__init__cCs |jƒdS)z(handle() method required by socketserverN)r…)r#r r r ÚhandleszRPCHandler.handlecCs t||ƒS)N)r‰)r#rMr r r Úget_remote_proxy szRPCHandler.get_remote_proxyN)rrrr>rGr"r´rµr r r r rûs rc@s:eZdZdZdZdZejejfdd„Z dd„Z dd „Z d S) Ú RPCClientFz#Cr¥cCs*tj||ƒ|_|jj|ƒ|jjdƒdS)Nr¥)r&Úlistening_sockZbindZlisten)r#ÚaddressZfamilyÚtyper r r r"s zRPCClient.__init__cCsV|jjƒ\}}|jr$td|tjd�|dtkr>tj||ƒntd|tjd�t ‚dS)Nz****** Connection request from )r-rz** Invalid host: ) r·Úacceptr>r1r/r0Ú LOCALHOSTr<r"re)r#Z working_sockr¸r r r rºs zRPCClient.acceptcCs t||ƒS)N)r‰)r#rMr r r rµ#szRPCClient.get_remote_proxyN) rrrr>rGr�r&ZAF_INETZ SOCK_STREAMr"rºrµr r r r r¶ s  r¶c@s4eZdZdZdZdd„Zdd„Zdd„Zdd „ZdS) r‰NcCs||_||_dS)N)ÚsockiorM)r#r¼rMr r r r",szRPCProxy.__init__cCsp|jdkr|jƒ|jj|ƒr.t|j|j|ƒS|jdkr@|jƒ||jkrd|jj|jd|fiƒ}|St |ƒ‚dS)NÚ__getattribute__) Ú_RPCProxy__methodsÚ_RPCProxy__getmethodsr«Ú MethodProxyr¼rMÚ_RPCProxy__attributesÚ_RPCProxy__getattributesrrr—)r#r4Úvaluer r r Ú __getattr__0s      zRPCProxy.__getattr__cCs|jj|jdfiƒ|_dS)NrV)r¼rrrMrÁ)r#r r r Z__getattributes>s zRPCProxy.__getattributescCs|jj|jdfiƒ|_dS)NrT)r¼rrrMr¾)r#r r r Z __getmethodsBs zRPCProxy.__getmethods) rrrr¾rÁr"rÄrÂr¿r r r r r‰'s r‰cCsTx*t|ƒD]}t||ƒ}t|ƒr d||<q Wt|tƒrPx|jD]}t||ƒq>WdS)Nr¥)Údirr`Úcallablerr¹Ú __bases__r])rrkr4ÚattrÚsuperr r r r]Fs    r]cCs0x*t|ƒD]}t||ƒ}t|ƒs d||<q WdS)Nr¥)rÅr`rÆ)rrlr4rÈr r r r^Qs r^c@seZdZdd„Zdd„ZdS)rÀcCs||_||_||_dS)N)r¼rMr4)r#r¼rMr4r r r r"ZszMethodProxy.__init__cOs|jj|j|j||ƒ}|S)N)r¼rrrMr4)r#rIrjrÃr r r Ú__call___szMethodProxy.__call__N)rrrr"rÊr r r r rÀXsrÀc Cs~|dkr dSdt_t|ƒ}ytjj|ƒWn<tk rfd}|j|dƒ}|j|dƒ}tjj|ƒYnXtjjdƒ|t_dS)z9Override standard display hook to use non-locale encodingNÚasciiÚbackslashreplaceÚstrictr*) ÚbuiltinsÚ_r5r/ÚstdoutÚwriteÚUnicodeEncodeErrorÚencodeÚdecode)rÃÚtextÚencodingÚbytesr r r Ú displayhookgs   rØÚ__main__)Úmainzidlelib.idle_test.test_rpcr�)Ú verbosity)Ni )-Ú__doc__rÎrrrr8r‘r¬r”r&r r’r/r2r6rr rr ZPicklerrr–r»r!rr@ZQueuercrªrNr<rarbrˆr³rr¶r‰r]r^rÀrØrZunittestrÚr r r r ÚsR 2  k