Ϫfj;dZddlmZddlmZddlmZddlmZddl m Z m Z m Z m Z ddlmZddlmZd Zd ZGd d ZGd de j,ZGdde j0Zee j4Gddej6ZGddej8ZdZGddZGdde j@Z!y)a External server-side components. Most Jabber server implementations allow for add-on components that act as a separate entity on the Jabber network, but use the server-to-server functionality of a regular Jabber IM server. These so-called 'external components' are connected to the Jabber server using the Jabber Component Protocol as defined in U{JEP-0114}. This module allows for writing external server-side component by assigning one or more services implementing L{ijabber.IService} up to L{ServiceManager}. The ServiceManager connects to the Jabber server and is responsible for the corresponding XML stream. ) implementer)service)defer)log)errorijabber jstrports xmlstream) internJID)domishzjabber:component:acceptcDt||}tj|S)z XML stream factory for external server-side components. @param componentid: JID of the component. @type componentid: L{unicode} @param password: password used to authenticate to the server. @type password: C{str} )ConnectComponentAuthenticatorr XmlStreamFactory) componentidpasswordas J/usr/lib/python3/dist-packages/twisted/words/protocols/jabber/component.pycomponentFactoryr!s! &k8  )~~rc|jj|j_|jj dyr)r otherEntity thisEntityrcallback)r_s rr)z+ComponentInitiatingInitializer._cbHandshakeGs,%)NN$>$>! %rN)__name__ __module__ __qualname____doc__rr.r)rrrr.s &rrc eZdZdZeZdZdZy)rz Authenticator to permit an XmlStream to authenticate against a Jabber server as an external component (where the Authenticator is initiating the stream). cRtjj||||_y)z @type componentjid: C{str} @param componentjid: Jabber ID that this component wishes to bind to. @type password: C{str} @param password: Password/secret this component uses to authenticate. N)r ConnectAuthenticatorrr)r componentjidrs rrz&ConnectComponentAuthenticator.__init__Ws! &&//lC  rctd|_tjj||t |g|_y)Nrr)versionr r;associateWithStreamr initializersrs rr@z1ConnectComponentAuthenticator.associateWithStreamcs. &&::4D9"=>rN)r4r5r6r7NS_COMPONENT_ACCEPTr"rr@r8rrrrNs $I !?rrc2eZdZdZeZdZdZdZdZ dZ y)ListenComponentAuthenticatorz Authenticator for accepting components. @since: 8.2 @ivar secret: The shared secret used to authorized incoming component connections. @type secret: C{unicode}. cP||_tjj|yr)secretr ListenAuthenticatorr)rrFs rrz%ListenComponentAuthenticator.__init__vs %%..t4rcRd|_tjj||y)z Associate the authenticator with a stream. This sets the stream's version to 0.0, because the XEP-0114 component protocol was not designed for XMPP 1.0. r>N)r?r rGr@rs rr@z0ListenComponentAuthenticator.associateWithStreamzs! %%99$Crctjj|||j|jk7r1t j d}|jj|y|jjs1t j d}|jj|y|jj|jjd|jy)aa Called by the stream when it has started. This examines the default namespace of the incoming stream and whether there is a requested hostname for the component. Then it generates a stream identifier, sends a response header and adds an observer for the first incoming element, triggering L{onElement}. zinvalid-namespaceNzimproper-addressing/*) r rG streamStarted defaultUrir"r StreamErrorsendStreamErrorr1 sendHeaderr( onElement)r rootElementexcs rrKz*ListenComponentAuthenticator.streamStarteds %%33D+F  ! !T^^ 3##$78C NN * *3 / ~~((##$9:C NN * *3 /  !!# ))$?rc|j|jf|jdfk(r|jt |yt j d}|jj|y)a. Called on incoming XML Stanzas. The very first element received should be a request for handshake. Otherwise, the stream is dropped with a 'not-authorized' error. If a handshake request was received, the hash is extracted and passed to L{onHandshake}. r not-authorizedN) urinamer" onHandshaker'rrMr rN)relementrRs rrPz&ListenComponentAuthenticator.onElementsW KK &4>>;*G G   S\ *##$45C NN * *3 /rctj|jjt|j}||k7r3t j dd}|jj|y|jjd|jj|jtjy)a9 Called upon receiving the handshake request. This checks that the given hash in C{handshake} is equal to a calculated hash, responding with a handshake reply or a stream error. If the handshake was ok, the stream is authorized, and XML Stanzas may be exchanged. rTz Invalid hash)textz N) r r#r$r'rFrrMrNr*dispatchSTREAM_AUTHD_EVENT)rr calculatedHashrRs rrWz(ListenComponentAuthenticator.onHandshakes#//0B0BC DTU  &##$4>JC NN * *3 / NN   / NN # #DNNI4P4P QrN) r4r5r6r7rBr"rr@rKrPrWr8rrrDrDjs*$I5D@6 0RrrDc(eZdZdZdZdZdZdZy)Servicez1 External server-side component service. cyrr8rs rcomponentConnectedzService.componentConnected rcyrr8rs rcomponentDisconnectedzService.componentDisconnectedrbrcyrr8rs rtransportConnectedzService.transportConnectedrbrc:|jj|y)a Send data over service parent's XML stream. @note: L{ServiceManager} maintains a queue for data sent using this method when there is no current established XML stream. This data is then sent as soon as a new stream has been established and initialized. Subsequently, L{componentConnected} will be called again. If this queueing is not desired, use C{send} on the XmlStream object (passed to L{componentConnected}) directly. @param obj: data to be sent over the XML stream. This is usually an object providing L{domish.IElement}, or serialized XML. See L{xmlstream.XmlStream} for details. N)parentr*robjs rr*z Service.sends rN)r4r5r6r7rarergr*r8rrr_r_s   rr_c4eZdZdZdZdZdZdZdZdZ y) ServiceManagera[ Business logic for a managed component connection to a Jabber router. This service maintains a single connection to a Jabber router and provides facilities for packet routing and transmission. Business logic modules are services implementing L{ijabber.IService} (like subclasses of L{Service}), and added as sub-service. cFtjj|||_d|_g|_t |j||_|jjtj|j|jjtj|j|jjtj|j|jj|_|jj|_yr)r MultiServicerjabberIdr _packetQueuer _xsFactory addBootstrapSTREAM_CONNECTED_EVENT _connectedr\_authdSTREAM_END_EVENT _disconnectedremoveBootstrap)rjidrs rrzServiceManager.__init__s%%d+ +4==(C $$Y%E%EtW $$Y%A%A4;;O $$Y%?%?ASAST !OO88#>>rc|jSr)rrrds r getFactoryzServiceManager.getFactorys rc||_|D]3}tjj|s#|j |5yr)r rIService providedByrg)rrcs rruzServiceManager._connecteds: )A**1-$$R( )rc|jD]}|jj|g|_|D]3}tjj |s#|j |5yr)rqr r*rr~rra)rrprs rrvzServiceManager._authdsd"" #A NN   " # )A**1-$$R( )rcd|_|D]2}tjj|s#|j 4yr)r rr~rre)rr3rs rrxzServiceManager._disconnecteds: *A**1-'') *rc|jdk7r|jj|y|jj|y)a Send data over the XML stream. When there is no established XML stream, the data is queued and sent out when a new XML stream has been established and initialized. @param obj: data to be sent over the XML stream. This is usually an object providing L{domish.IElement}, or serialized XML. See L{xmlstream.XmlStream} for details. N)r r*rqappendrjs rr*zServiceManager.send"s6 >>T ! NN   $    $ $S )rN) r4r5r6r7rr|rurvrxr*r8rrrmrms%?2) )**rrmct||}tj||j}|j ||S)z[ Constructs a pre-built L{ServiceManager}, using the specified strport string. )rmr clientr|setServiceParent)rzrstrportsvc client_svcs rbuildServiceManagerr4s< h 'C!!'3>>+;}s that should receive the traffic. A key of L{None} means the default route. @type routes: C{dict} ci|_yr)routesrds rrzRouter.__init__Us  rcZ||j|<|jd|jy)a Add a new route. The passed XML Stream C{xs} will have an observer for all stanzas added to route its outgoing traffic. In turn, traffic for C{destination} will be passed to this stream. @param destination: Destination of the route to be added as a host name or L{None} for the default route. @type destination: C{str} or L{None}. @param xs: XML Stream to register the route for. @type xs: L{EventDispatcher}. rJN)r addObserverrouter destinationrs raddRoutezRouter.addRouteXs$$& K  tTZZ(rc||jd|j||j|k(r|j|=yy)a Remove a route. @param destination: Destination of the route that should be removed. @type destination: C{str}. @param xs: XML Stream to remove the route for. @type xs: L{EventDispatcher}. rJN)removeObserverrrrs r removeRoutezRouter.removeRouteis: $ + [) ) K( *rcLt|d}tjd|jd|j |j |j vr)|j |j j|y|j dj|y)z{ Route a stanza. @param stanza: The stanza to be routed. @type stanza: L{domish.Element}. toz Routing to z: N)JIDrmsgfulltoXmlhostrr*)rstanzars rrz Router.routevs&,'  +k..01FLLN3EFG   t{{ * KK (( ) . .v 6 KK  " "6 *rN)r4r5r6r7rrrrr8rrrr@s()" )+rrc4eZdZdZdZd dZdZdZdZdZ y) XMPPComponentServerFactoryz XMPP Component Server factory. This factory accepts XMPP external component connections and makes the router service route traffic for a component's bound domain to that component. @since: 8.2 Fc"|_|_fd}tjj |j tj jj tjjd_ y)Nc.tjSr)rDrFrdsrauthenticatorFactoryzAXMPPComponentServerFactory.__init__..authenticatorFactorys/ < XMPPComponentServerFactory.onConnectionMade..logDataIn GGOryy#&66 7rcNtjdj|fzy)Nz SEND (%d): %rrrs r logDataOutz?XMPPComponentServerFactory.onConnectionMade..logDataOutrrN)r logTraffic rawDataInFn rawDataOutFnrr STREAM_ERROR_EVENTonError)rrrrs ` rrz+XMPPComponentServerFactory.onConnectionMadesW KK  q  8 8 ??&BN(BO y33T\\Brc|jj}|jj|||j t j |jd||y)z Called when a component has successfully authenticated. Add the component to the routing table and establish a handler for a closed connection. rN)r1rrrrr rwonConnectionLost)rrrs rrz*XMPPComponentServerFactory.onAuthenticatedsJmm((  ["-   & &(=(=q+r rc0tj|dy)Nz Stream Error)rerr)rreasons rrz"XMPPComponentServerFactory.onErrors 'rc<|jj||yr)rr)rrrrs rrz+XMPPComponentServerFactory.onConnectionLosts  R0rN)rF) r4r5r6r7rrrrrrr8rrrrs(J C*  (1rrN)"r7zope.interfacertwisted.applicationrtwisted.internetrtwisted.pythonrtwisted.words.protocols.jabberrrr r "twisted.words.protocols.jabber.jidr rtwisted.words.xishr rBrrr;rrGrDr~r_rormrrrrr8rrrs ''"OO?%/ )&&@?I$B$B?8SR9#@#@SRl W  gooBO*W))O*d D+D+NA1!A!AA1r