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|ƒ}|S)z*Return code object from marshal string ms.)ÚmarshalÚloads)ÚmsÚco©rú0/opt/alt/python36/lib64/python3.6/idlelib/rpc.pyÚ unpickle_code-s rcCstj|ƒ}t|ffS)zBReturn unpickle function and tuple with marshalled co code object.)rÚdumpsr)rrrrrÚ pickle_code3s r cCs$tjƒ}t||ƒ}|j|ƒ|jƒS)z.Return pickled (or marshalled) string for obj.)ÚioÚBytesIOÚ CodePicklerÚdumpÚgetvalue)ÚobjZprotocolÚfÚprrrr 9s  r c@s"eZdZejeiZejejƒdS)r N) Ú__name__Ú __module__Ú __qualname__ÚtypesÚCodeTyper Údispatch_tableÚupdateÚcopyregrrrrr Bs 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 handlerclassrrrr LszRPCServer.__init__cCsdS)z@Override TCPServer method, no bind() phase for connecting entityNr)r!rrrÚ 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!rrrÚserver_activateUszRPCServer.server_activatecCs |j|jfS)z:Override TCPServer method, return already connected socket)r$r%)r!rrrÚ 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_addressZerfrrrÚ handle_errorbs   zRPCServer.handle_error)N)rrrr r#r&r'r9rrrrrJs   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) r0r1Ú sockthreadÚ debuggingÚsockÚ objecttableÚobjtableÚ responsesÚcvars)r!r=r?r<rrrr …s zSocketIO.__init__cCs |j}d|_|dk r|jƒdS)N)r=Úclose)r!r=rrrrB�szSocketIO.closecCstjdƒdS)z!override for specific exit actionrN)r6r7)r!rrrÚexithook–szSocketIO.exithookcGsR|js dS|jdttjƒjƒ}x|D]}|dt|ƒ}q(Wt|tjd�dS)Nú )r+) r<ÚlocationÚstrr0r1r2r/r-r.)r!ÚargsÚsÚarrrÚdebugšs  zSocketIO.debugcCs||j|<dS)N)r?)r!ÚoidÚobjectrrrÚregister¢szSocketIO.registerc Cs&y |j|=Wntk r YnXdS)N)r?ÚKeyError)r!rKrrrÚ 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)rPrQ)rWN)rYN)rJÚ TypeErrorr?Ú _getmethodsÚ_getattributesÚhasattrÚgetattrÚ isinstanceÚ RemoteObjectÚ remoterefÚ request_queueZputr,ÚKeyboardInterruptÚOSErrorÚ Exceptionr/r-r.r4r5)r!Úseqr8ÚhowrKÚ methodnamerGÚkwargsrÚmethodsÚ attributesÚmethodZretZexÚmsgrrrÚ localcall«sT          zSocketIO.localcallcCs(|jd||ƒ|j||||ƒ}|j|ƒS)Nzremotecall:asynccall: )rJÚ asynccallÚ asyncreturn)r!rKrhrGrirfrrrÚ remotecallÙszSocketIO.remotecallcCs(|jd||ƒ|j||||ƒ}|j|ƒS)Nzremotequeue:asyncqueue: )rJÚ asyncqueuerp)r!rKrhrGrirfrrrÚ remotequeueÞszSocketIO.remotequeuecCs`d||||ff}|jƒ}tjƒ|jkr8tjƒ}||j|<|jd|||||ƒ|j||fƒ|S)NrUz asynccall:%d:)Únewseqr0r1r;Ú ConditionrArJÚ putmessage)r!rKrhrGrir8rfÚcvarrrrroãs zSocketIO.asynccallcCs`d||||ff}|jƒ}tjƒ|jkr8tjƒ}||j|<|jd|||||ƒ|j||fƒ|S)NrVzasyncqueue:%d:)rtr0r1r;rurArJrv)r!rKrhrGrir8rfrwrrrrrís zSocketIO.asyncqueuecCs6|jd|ƒ|j|dd�}|jd||ƒ|j|ƒS)Nz#asyncreturn:%d:call getresponse(): gš™™™™™©?)Úwaitzasyncreturn:%d:response: )rJÚ getresponseÚdecoderesponse)r!rfÚresponserrrrp÷szSocketIO.asyncreturncCs–|\}}|dkr|S|dkr dS|dkr6|jdƒdS|dkrT|jdƒ|jƒdS|dkrp|jd|ƒt|ƒ‚|d krˆ|jd |ƒ|‚t||ƒ‚dS) NrSrWrYzdecoderesponse: EXCEPTIONÚEOFzdecoderesponse: EOFrPzdecoderesponse: Internal ERROR:rXzdecoderesponse: Call Exception:)rJÚdecode_interrupthookÚ RuntimeErrorÚ SystemError)r!r{rgÚwhatrrrrzýs&    zSocketIO.decoderesponsecCst‚dS)ÚN)ÚEOFError)r!rrrr}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š™™™™™©?)Úmyseqrxzmainloop:return)ryr‚rJ)r!rrrÚmainloops  zSocketIO.mainloopcCs6|j||ƒ}|dk r2|\}}|dkr2||j|ƒf}|S)NrS)Ú _getresponseÚ_proxify)r!rƒrxr{rgr€rrrry#s  zSocketIO.getresponsecCs4t|tƒrt||jƒSt|tƒr0tt|j|ƒƒS|S)N)r_Ú RemoteProxyÚRPCProxyrKÚlistÚmapr†)r!rrrrr†+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) rJr0r1r;Ú pollresponserAÚacquirer@rxÚrelease)r!rƒrxr{rwrrrr…3s"        zSocketIO._getresponsecCs|jd|_}|S)Né)Únextseq)r!rfrrrrtIszSocketIO.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)r`N)rrrrrrrr`êsr`cCst|ƒ}|t|<t|ƒS)N)Úidr>r‡)rrKrrrraïsrac@seZdZdd„ZdS)r‡cCs ||_dS)N)rK)r!rKrrrr ÷szRemoteProxy.__init__N)rrrr rrrrr‡õsr‡c@s,eZdZdZdZdd„Zdd„Zdd„Zd S) rFz#ScCs(||_tj||ƒtjj||||ƒdS)N)Zcurrent_handlerr:r rÚBaseRequestHandler)r!r=r"Zsvrrrrr s zRPCHandler.__init__cCs |jƒdS)z(handle() method required by socketserverN)r„)r!rrrÚhandleszRPCHandler.handlecCs t||ƒS)N)rˆ)r!rKrrrÚget_remote_proxy szRPCHandler.get_remote_proxyN)rrrr<rEr r³r´rrrrrûs rc@s:eZdZdZdZdZejejfdd„Z dd„Z dd „Z d S) Ú RPCClientFz#Cr¤cCs*tj||ƒ|_|jj|ƒ|jjdƒdS)Nr¤)r$Úlistening_sockZbindZlisten)r!ÚaddressZfamilyÚtyperrrr s zRPCClient.__init__cCsV|jjƒ\}}|jr$td|tjd�|dtkr>tj||ƒntd|tjd�t ‚dS)Nz****** Connection request from )r+rz** Invalid host: ) r¶Úacceptr<r/r-r.Ú LOCALHOSTr:r rd)r!Z working_sockr·rrrr¹s zRPCClient.acceptcCs t||ƒS)N)rˆ)r!rKrrrr´#szRPCClient.get_remote_proxyN) rrrr<rEr�r$ZAF_INETZ SOCK_STREAMr r¹r´rrrrrµ s  rµc@s4eZdZdZdZdd„Zdd„Zdd„Zdd „ZdS) rˆNcCs||_||_dS)N)ÚsockiorK)r!r»rKrrrr ,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»rKÚ_RPCProxy__attributesÚ_RPCProxy__getattributesrqr–)r!r2ÚvaluerrrÚ __getattr__0s      zRPCProxy.__getattr__cCs|jj|jdfiƒ|_dS)NrT)r»rqrKrÀ)r!rrrZ__getattributes>s zRPCProxy.__getattributescCs|jj|jdfiƒ|_dS)NrR)r»rqrKr½)r!rrrZ __getmethodsBs zRPCProxy.__getmethods) rrrr½rÀr rÃrÁr¾rrrrrˆ's rˆcCsTx*t|ƒD]}t||ƒ}t|ƒr d||<q Wt|tƒrPx|jD]}t||ƒq>WdS)Nr¤)Údirr^Úcallabler_r¸Ú __bases__r[)rrjr2ÚattrÚsuperrrrr[Fs    r[cCs0x*t|ƒD]}t||ƒ}t|ƒs d||<q WdS)Nr¤)rÄr^rÅ)rrkr2rÇrrrr\Qs r\c@seZdZdd„Zdd„ZdS)r¿cCs||_||_||_dS)N)r»rKr2)r!r»rKr2rrrr ZszMethodProxy.__init__cOs|jj|j|j||ƒ}|S)N)r»rqrKr2)r!rGrirÂrrrÚ__call___szMethodProxy.__call__N)rrrr rÉrrrrr¿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Ú_r3r-ÚstdoutÚwriteÚUnicodeEncodeErrorÚencodeÚdecode)rÂÚtextÚencodingÚbytesrrrÚ displayhookgs   r×Ú__main__)Úmainzidlelib.idle_test.test_rpcrŽ)Ú verbosity)Ni )-Ú__doc__rÍrr rr6r�r«r“r$rr‘r-r0r4rrr r ZPicklerr r•rºrrr>ZQueuerbr©rLr:r`rar‡r²rrµrˆr[r\r¿r×rZunittestrÙrrrrÚsR 2  k