B ãxác‘Rã@s”dZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZdd„Zdd„Zd*dd„ZGd d „d ejƒZd Zd ZGd d„de jƒZiZe d¡Ze d¡ZGdd„deƒZGdd„deƒZdd„Z Gdd„deƒZ!Gdd„de j"eƒZ#Gdd„deƒZ$Gdd„deƒZ%dd„Z&dd „Z'Gd!d"„d"eƒZ(d#d$„Z)e*d%krdd&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. éNcCst |¡}|S)z*Return code object from marshal string ms.)ÚmarshalÚloads)ÚmsÚco©rú0/opt/alt/python37/lib64/python3.7/idlelib/rpc.pyÚ unpickle_code-s rcCst |¡}t|ffS)zBReturn unpickle function and tuple with marshalled co code object.)rÚdumpsr)rrrrrÚ pickle_code3s r cCs$t ¡}t||ƒ}| |¡| ¡S)z.Return pickled (or marshalled) string for obj.)ÚioÚBytesIOÚ CodePicklerÚdumpÚgetvalue)ÚobjZprotocolÚfÚprrrr 9s  r c@s"eZdZejeiZe ej¡dS)r N) Ú__name__Ú __module__Ú __qualname__ÚtypesÚCodeTyper Údispatch_tableÚupdateÚcopyregrrrrr Bs r i z 127.0.0.1c@s6eZdZd dd„Zdd„Zdd„Zdd „Zd d „ZdS) Ú RPCServerNcCs |dkr t}tj |||¡dS)N)Ú RPCHandlerÚ socketserverÚ TCPServerÚ__init__)ÚselfÚaddrZ handlerclassrrrrLszRPCServer.__init__cCsdS)z@Override TCPServer method, no bind() phase for connecting entityNr)r rrrÚ server_bindQszRPCServer.server_bindcCs|j |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 rrrÚserver_activateUszRPCServer.server_activatecCs |j|jfS)z:Override TCPServer method, return already connected socket)r#r$)r rrrÚ get_request^szRPCServer.get_requestcCs®y‚Wn¢tk r‚YnŽtj}td|dtd|dtdt ¡j|dtd||dtdt|ƒ|dtj |dtd|dtd|dt   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. z) ----------------------------------------)ÚfilezUnhandled server exception!z Thread: %szClient Address: z Request: z# *** Unrecoverable, server exiting!z(----------------------------------------rN) Ú SystemExitÚsysÚ __stderr__ÚprintÚ threadingÚcurrent_threadÚnameÚreprÚ tracebackÚ print_excÚosÚ_exit)r ÚrequestZclient_addressZerfrrrÚ handle_errorbs     zRPCServer.handle_error)N)rrrrr"r%r&r5rrrrrJs   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@t ¡|_|dk r||_||_|dkr*t}||_i|_i|_dS)N) r,r-Ú sockthreadÚ debuggingÚsockÚ objecttableÚobjtableÚ responsesÚcvars)r r9r;r8rrrr…s zSocketIO.__init__cCs |j}d|_|dk r| ¡dS)N)r9Úclose)r r9rrrr>szSocketIO.closecCst d¡dS)z!override for specific exit actionrN)r2r3)r rrrÚexithook–szSocketIO.exithookcGsR|js dS|jdtt ¡jƒ}x|D]}|dt|ƒ}q(Wt|tjddS)Nú )r') r8ÚlocationÚstrr,r-r.r+r)r*)r ÚargsÚsÚarrrÚdebugšs  zSocketIO.debugcCs||j|<dS)N)r;)r ÚoidÚobjectrrrÚregister¢szSocketIO.registercCs&y |j|=Wntk r YnXdS)N)r;ÚKeyError)r rGrrrÚ unregister¥s zSocketIO.unregisterc Cs¶| d|¡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 krt   || ||ff¡d Sdd |fSWnœt k r,‚Yn†t k rB‚Ynptk rX‚YnZtk r~} zd | fSd} ~ XYn4d}t||| |ftjdtjtjddSdS)Nz localcall:)ÚERRORzBad request formatrLzUnknown object id: %rÚ __methods__ÚOKÚ__attributes__zUnsupported method name: %rÚCALLÚQUEUE)ÚQUEUEDNzUnsupported message type: %sÚCALLEXCzU*** Internal Error: rpc.py:SocketIO.localcall() Object: %s Method: %s Args: %s )r')Ú EXCEPTIONN)rFÚ TypeErrorr;Ú _getmethodsÚ_getattributesÚhasattrÚgetattrÚ isinstanceÚ RemoteObjectÚ remoterefÚ request_queueZputr(ÚKeyboardInterruptÚOSErrorÚ Exceptionr+r)r*r0r1)r Úseqr4ÚhowrGÚ methodnamerCÚkwargsrÚmethodsÚ attributesÚmethodZretZexÚmsgrrrÚ localcall«sT          zSocketIO.localcallcCs(| d||¡| ||||¡}| |¡S)Nzremotecall:asynccall: )rFÚ asynccallÚ asyncreturn)r rGrcrCrdrarrrÚ remotecallÙszSocketIO.remotecallcCs(| d||¡| ||||¡}| |¡S)Nzremotequeue:asyncqueue: )rFÚ asyncqueuerk)r rGrcrCrdrarrrÚ remotequeueÞszSocketIO.remotequeuecCs`d||||ff}| ¡}t ¡|jkr8t ¡}||j|<| d|||||¡| ||f¡|S)NrPz asynccall:%d:)Únewseqr,r-r7Ú Conditionr=rFÚ putmessage)r rGrcrCrdr4raÚcvarrrrrjãs zSocketIO.asynccallcCs`d||||ff}| ¡}t ¡|jkr8t ¡}||j|<| d|||||¡| ||f¡|S)NrQzasyncqueue:%d:)ror,r-r7rpr=rFrq)r rGrcrCrdr4rarrrrrrmís zSocketIO.asyncqueuecCs6| d|¡|j|dd}| d||¡| |¡S)Nz#asyncreturn:%d:call getresponse(): gš™™™™™©?)Úwaitzasyncreturn:%d:response: )rFÚ getresponseÚdecoderesponse)r raÚresponserrrrk÷szSocketIO.asyncreturncCs–|\}}|dkr|S|dkr dS|dkr6| d¡dS|dkrT| d¡| ¡dS|dkrp| d|¡t|ƒ‚|d krˆ| d |¡|‚t||ƒ‚dS) NrNrRrTzdecoderesponse: EXCEPTIONÚEOFzdecoderesponse: EOFrLzdecoderesponse: Internal ERROR:rSzdecoderesponse: Call Exception:)rFÚdecode_interrupthookÚ RuntimeErrorÚ SystemError)r rvrbÚwhatrrrruýs&    zSocketIO.decoderesponsecCst‚dS)ÚN)ÚEOFError)r rrrrxszSocketIO.decode_interrupthookcCs6y|jdddWntk r0| d¡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š™™™™™©?)Úmyseqrszmainloop:return)rtr}rF)r rrrÚmainloops  zSocketIO.mainloopcCs6| ||¡}|dk r2|\}}|dkr2|| |¡f}|S)NrN)Ú _getresponseÚ_proxify)r r~rsrvrbr{rrrrt#s  zSocketIO.getresponsecCs4t|tƒrt||jƒSt|tƒr0tt|j|ƒƒS|S)N)rZÚ RemoteProxyÚRPCProxyrGÚlistÚmapr)r rrrrr+s    zSocketIO._proxifycCs | d|¡t ¡|jkr:x€| ||¡}|dk r|SqWnb|j|}| ¡x||jkrb| ¡qNW|j|}| d||f¡|j|=|j|=|  ¡|SdS)Nz_getresponse:myseq:z-_getresponse:%s: thread woke up: response: %s) rFr,r-r7Ú pollresponser=Úacquirer<rsÚrelease)r r~rsrvrrrrrr€3s"        zSocketIO._getresponsecCs|jd|_}|S)Né)Únextseq)r rarrrroIszSocketIO.newseqc CsÔ| d|d¡y t|ƒ}Wn,tjk rJtdt|ƒtjd‚YnXt  dt |ƒ¡|}xnt |ƒdkrÎy0t   g|j gg¡\}}}|j   |dt…¡}Wn ttfk r¾tdƒ‚YnX||d…}qbWdS)Nzputmessage:%d:rzCannot pickle:)r'zr?rFrIrKrirlrnrjrmrkrurxrrtrr€rorqršr›r ržr™rr£r†r§rªrrrrr6s> .   I r6c@s eZdZdS)r[N)rrrrrrrr[êsr[cCst|ƒ}|t|<t|ƒS)N)Úidr:r‚)rrGrrrr\ïsr\c@seZdZdd„ZdS)r‚cCs ||_dS)N)rG)r rGrrrr÷szRemoteProxy.__init__N)rrrrrrrrr‚õsr‚c@s,eZdZdZdZdd„Zdd„Zdd„Zd S) rFz#ScCs(||_t ||¡tj ||||¡dS)N)Zcurrent_handlerr6rrÚBaseRequestHandler)r r9r!Zsvrrrrrs zRPCHandler.__init__cCs | ¡dS)z(handle() method required by socketserverN)r)r rrrÚhandleszRPCHandler.handlecCs t||ƒS)N)rƒ)r rGrrrÚget_remote_proxy szRPCHandler.get_remote_proxyN)rrrr8rArr®r¯rrrrrûs rc@s:eZdZdZdZdZejejfdd„Z dd„Z dd „Z d S) Ú RPCClientFz#CrŸcCs*t ||¡|_|j |¡|j d¡dS)NrŸ)r#Úlistening_sockZbindZlisten)r ÚaddressZfamilyÚtyperrrrs zRPCClient.__init__cCsV|j ¡\}}|jr$td|tjd|dtkr>t ||¡ntd|tjdt ‚dS)Nz****** Connection request from )r'rz** Invalid host: ) r±Úacceptr8r+r)r*Ú LOCALHOSTr6rr_)r Z working_sockr²rrrr´s zRPCClient.acceptcCs t||ƒS)N)rƒ)r rGrrrr¯#szRPCClient.get_remote_proxyN) rrrr8rArŠr#ZAF_INETZ SOCK_STREAMrr´r¯rrrrr° s  r°c@s4eZdZdZdZdd„Zdd„Zdd„Zdd „ZdS) rƒNcCs||_||_dS)N)ÚsockiorG)r r¶rGrrrr,szRPCProxy.__init__cCsp|jdkr| ¡|j |¡r.t|j|j|ƒS|jdkr@| ¡||jkrd|j |jd|fi¡}|St |ƒ‚dS)NÚ__getattribute__) Ú_RPCProxy__methodsÚ_RPCProxy__getmethodsr¥Ú MethodProxyr¶rGÚ_RPCProxy__attributesÚ_RPCProxy__getattributesrlr‘)r r.ÚvaluerrrÚ __getattr__0s      zRPCProxy.__getattr__cCs|j |jddi¡|_dS)NrOr)r¶rlrGr»)r rrrZ__getattributes>s zRPCProxy.__getattributescCs|j |jddi¡|_dS)NrMr)r¶rlrGr¸)r rrrZ __getmethodsBs zRPCProxy.__getmethods) rrrr¸r»rr¾r¼r¹rrrrrƒ's rƒcCsTx*t|ƒD]}t||ƒ}t|ƒr d||<q Wt|tƒrPx|jD]}t||ƒq>WdS)NrŸ)ÚdirrYÚcallablerZr³Ú __bases__rV)rrer.ÚattrÚsuperrrrrVFs    rVcCs0x*t|ƒD]}t||ƒ}t|ƒs d||<q WdS)NrŸ)r¿rYrÀ)rrfr.rÂrrrrWQs rWc@seZdZdd„Zdd„ZdS)rºcCs||_||_||_dS)N)r¶rGr.)r r¶rGr.rrrrZszMethodProxy.__init__cOs|j |j|j||¡}|S)N)r¶rlrGr.)r rCrdr½rrrÚ__call___szMethodProxy.__call__N)rrrrrÄrrrrrºXsrºcCs~|dkr dSdt_t|ƒ}ytj |¡Wn<tk rfd}| |d¡}| |d¡}tj |¡YnXtj d¡|t_dS)z9Override standard display hook to use non-locale encodingNÚasciiÚbackslashreplaceÚstrictÚ ) ÚbuiltinsÚ_r/r)ÚstdoutÚwriteÚUnicodeEncodeErrorÚencodeÚdecode)r½ÚtextÚencodingÚbytesrrrÚ displayhookgs   rÓÚ__main__)Úmainzidlelib.idle_test.test_rpcr‰)Ú verbosity)N)-Ú__doc__rÉrr rr2r‹r¦rŽr#rrŒr)r,r0rrr r ZPicklerr rrµrrr:ZQueuer]r¤rHr6r[r\r‚r­rr°rƒrVrWrºrÓrZunittestrÕrrrrÚsR 2  k