Changeset 40:2bcb10fb4da4 for wokkel
- Timestamp:
- Oct 18, 2008, 12:18:02 PM (14 years ago)
- Branch:
- default
- Convert:
- svn:b33ecbfc-034c-dc11-8662-000475d9059e/trunk@112
- Location:
- wokkel
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
wokkel/component.py
r39 r40 134 134 """ 135 135 Authenticator for accepting components. 136 """ 136 137 @ivar secret: The shared used to authorized incoming component connections. 138 @type secret: C{str}. 139 """ 140 137 141 namespace = NS_COMPONENT_ACCEPT 138 142 … … 143 147 144 148 def associateWithStream(self, xs): 149 """ 150 Associate the authenticator with a stream. 151 152 This sets the stream's version to 0.0, because the XEP-0114 component 153 protocol was not designed for XMPP 1.0. 154 """ 145 155 xs.version = (0, 0) 146 156 xmlstream.ListenAuthenticator.associateWithStream(self, xs) … … 148 158 149 159 def streamStarted(self, rootElement): 160 """ 161 Called by the stream when it has started. 162 163 This examines the default namespace of the incoming stream and whether 164 there is a requested hostname for the component. Then it generates a 165 stream identifier, sends a response header and adds an observer for 166 the first incoming element, triggering L{onElement}. 167 """ 168 150 169 xmlstream.ListenAuthenticator.streamStarted(self, rootElement) 170 171 # Compatibility fix 172 if not self.xmlstream.sid: 173 from twisted.python import randbytes 174 self.xmlstream.sid = randbytes.secureRandom(8).encode('hex') 151 175 152 176 if rootElement.defaultUri != self.namespace: … … 156 180 157 181 # self.xmlstream.thisEntity is set to the address the component 158 # wants to assume. This should probably be checked.182 # wants to assume. 159 183 if not self.xmlstream.thisEntity: 160 184 exc = error.StreamError('improper-addressing') … … 162 186 return 163 187 164 self.xmlstream.sid = 'random' # FIXME165 166 188 self.xmlstream.sendHeader() 167 189 self.xmlstream.addOnetimeObserver('/*', self.onElement) … … 169 191 170 192 def onElement(self, element): 193 """ 194 Called on incoming XML Stanzas. 195 196 The very first element received should be a request for handshake. 197 Otherwise, the stream is dropped with a 'not-authorized' error. If a 198 handshake request was received, the hash is extracted and passed to 199 L{onHandshake}. 200 """ 171 201 if (element.uri, element.name) == (self.namespace, 'handshake'): 172 202 self.onHandshake(unicode(element)) 173 203 else: 174 exc = error. streamError('not-authorized')204 exc = error.StreamError('not-authorized') 175 205 self.xmlstream.sendStreamError(exc) 176 206 177 207 178 208 def onHandshake(self, handshake): 209 """ 210 Called upon receiving the handshake request. 211 212 This checks that the given hash in C{handshake} is equal to a 213 calculated hash, responding with a handshake reply or a stream error. 214 If the handshake was ok, the stream is authorized, and XML Stanzas may 215 be exchanged. 216 """ 179 217 calculatedHash = xmlstream.hashPassword(self.xmlstream.sid, self.secret) 180 218 if handshake != calculatedHash: … … 188 226 189 227 190 class Router Service(service.Service):191 """ 192 XMPP Server's Router Service.193 194 This service connects the different components of the XMPP service and195 routesmessages between them based on the given routing table.228 class Router(object): 229 """ 230 XMPP Server's Router. 231 232 A router connects the different components of the XMPP service and routes 233 messages between them based on the given routing table. 196 234 197 235 Connected components are trusted to have correct addressing in the … … 251 289 @type stanza: L{domish.Element}. 252 290 """ 253 if not list(stanza.elements()):254 return255 256 291 destination = JID(stanza['to']) 257 292 … … 265 300 266 301 267 class ComponentServer(service.Service):268 """ 269 XMPP Component Server service.270 271 This serviceaccepts XMPP external component connections and makes302 class XMPPComponentServerFactory(xmlstream.XmlStreamServerFactory): 303 """ 304 XMPP Component Server factory. 305 306 This factory accepts XMPP external component connections and makes 272 307 the router service route traffic for a component's bound domain 273 308 to that component. … … 276 311 logTraffic = False 277 312 278 def __init__(self, router, port=5347,secret='secret'):313 def __init__(self, router, secret='secret'): 279 314 self.router = router 280 self.port = port281 315 self.secret = secret 282 316 … … 284 318 return ListenComponentAuthenticator(self.secret) 285 319 286 self.factory = xmlstream.XmlStreamServerFactory(authenticatorFactory)287 self. factory.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT,288 289 self. factory.addBootstrap(xmlstream.STREAM_AUTHD_EVENT,290 320 xmlstream.XmlStreamServerFactory.__init__(self, authenticatorFactory) 321 self.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, 322 self.makeConnection) 323 self.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, 324 self.connectionInitialized) 291 325 292 326 self.serial = 0 293 294 295 def startService(self):296 service.Service.startService(self)297 reactor.listenTCP(self.port, self.factory)298 327 299 328 -
wokkel/test/test_component.py
r39 r40 24 24 25 25 def setUp(self): 26 self.router = component.Router Service()26 self.router = component.Router() 27 27 self.component = component.InternalComponent(self.router, 'component') 28 28 … … 114 114 message = domish.Element((None, 'message')) 115 115 116 self.router.route = fn 116 117 self.component.startService() 117 self.router.routes['component'].addObserver('/message', fn)118 118 self.component.send(message) 119 119 … … 122 122 123 123 124 class Router ServiceTest(unittest.TestCase):125 """ 126 Tests for L{component.Router Service}.124 class RouterTest(unittest.TestCase): 125 """ 126 Tests for L{component.Router}. 127 127 """ 128 128 … … 131 131 Test route registration and routing on incoming stanzas. 132 132 """ 133 router = component.Router Service()133 router = component.Router() 134 134 routed = [] 135 135 router.route = lambda element: routed.append(element) … … 151 151 component1 = XmlPipe() 152 152 component2 = XmlPipe() 153 router = component.Router Service()153 router = component.Router() 154 154 router.addRoute('component1.example.org', component1.sink) 155 155 router.addRoute('component2.example.org', component2.sink) … … 158 158 component2.source.addObserver('/*', 159 159 lambda element: outgoing.append(element)) 160 stanza = domish.Element((None, ' route'))160 stanza = domish.Element((None, 'presence')) 161 161 stanza['from'] = 'component1.example.org' 162 162 stanza['to'] = 'component2.example.org' 163 stanza.addElement('presence')164 163 component1.source.send(stanza) 165 164 self.assertEquals([stanza], outgoing) … … 176 175 component1 = XmlPipe() 177 176 s2s = XmlPipe() 178 router = component.Router Service()177 router = component.Router() 179 178 router.addRoute('component1.example.org', component1.sink) 180 179 router.addRoute(None, s2s.sink) … … 182 181 outgoing = [] 183 182 s2s.source.addObserver('/*', lambda element: outgoing.append(element)) 184 stanza = domish.Element((None, ' route'))183 stanza = domish.Element((None, 'presence')) 185 184 stanza['from'] = 'component1.example.org' 186 185 stanza['to'] = 'example.com' 187 stanza.addElement('presence')188 186 component1.source.send(stanza) 189 187 self.assertEquals([stanza], outgoing) … … 211 209 212 210 def test_streamStarted(self): 211 """ 212 The received stream header should set several attributes. 213 """ 213 214 observers = [] 214 215 … … 249 250 250 251 def test_streamStartedNoTo(self): 252 """ 253 The received stream header should have a 'to' attribute. 254 """ 251 255 streamErrors = [] 252 256 … … 274 278 self.assertEqual('1234', handshakes[-1]) 275 279 280 def test_onElementNotHandshake(self): 281 """ 282 Reject elements that are not handshakes 283 """ 284 handshakes = [] 285 streamErrors = [] 286 287 xs = self.xmlstream 288 xs.authenticator.onHandshake = handshakes.append 289 xs.sendStreamError = streamErrors.append 290 291 element = domish.Element(('jabber:component:accept', 'message')) 292 xs.authenticator.onElement(element) 293 self.assertFalse(handshakes) 294 self.assertEquals('not-authorized', streamErrors[-1].condition) 295 296 276 297 def test_onHandshake(self): 277 xs = self.xmlstream 298 """ 299 Receiving a handshake matching the secret authenticates the stream. 300 """ 301 authd = [] 302 303 def authenticated(xs): 304 authd.append(xs) 305 306 xs = self.xmlstream 307 xs.addOnetimeObserver(xmlstream.STREAM_AUTHD_EVENT, authenticated) 278 308 xs.sid = '1234' 279 309 theHash = '32532c0f7dbf1253c095b18b18e36d38d94c1256' 280 310 xs.authenticator.onHandshake(theHash) 281 311 self.assertEqual('<handshake/>', self.output[-1]) 312 self.assertEquals(1, len(authd)) 282 313 283 314 284 315 def test_onHandshakeWrongHash(self): 316 """ 317 Receiving a bad handshake should yield a stream error. 318 """ 285 319 streamErrors = [] 286 320 authd = [] 287 321 288 def authenticated( self,xs):322 def authenticated(xs): 289 323 authd.append(xs) 290 324 … … 301 335 302 336 303 class ComponentServerTest(unittest.TestCase):304 """ 305 Tests for L{component. ComponentServer}.337 class XMPPComponentServerFactoryTest(unittest.TestCase): 338 """ 339 Tests for L{component.XMPPComponentServerFactory}. 306 340 """ 307 341 308 342 def setUp(self): 309 self.router = component.RouterService() 310 self.server = component.ComponentServer(self.router) 311 self.xmlstream = self.server.factory.buildProtocol(None) 343 self.router = component.Router() 344 self.factory = component.XMPPComponentServerFactory(self.router, 345 'secret') 346 self.xmlstream = self.factory.buildProtocol(None) 312 347 self.xmlstream.thisEntity = JID('component.example.org') 313 348 … … 320 355 xmlstream.STREAM_CONNECTED_EVENT) 321 356 self.assertEqual(0, self.xmlstream.serial) 322 self.assertEqual(1, self. server.serial)357 self.assertEqual(1, self.factory.serial) 323 358 self.assertIdentical(None, self.xmlstream.rawDataInFn) 324 359 self.assertIdentical(None, self.xmlstream.rawDataOutFn) … … 329 364 Setting logTraffic should set up raw data loggers. 330 365 """ 331 self. server.logTraffic = True366 self.factory.logTraffic = True 332 367 self.xmlstream.dispatch(self.xmlstream, 333 368 xmlstream.STREAM_CONNECTED_EVENT)
Note: See TracChangeset
for help on using the changeset viewer.