Changeset 7:0fbac5c2e97d in ralphm-patches
- Timestamp:
- Apr 7, 2009, 11:53:45 AM (13 years ago)
- Branch:
- default
- Files:
-
- 1 added
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
compat-pre-twisted-8.0.0.patch
r5 r7 1 diff -r 6fa0283e522bwokkel/compat.py2 --- a/wokkel/compat.py Wed Mar 25 18:14:08 2009 +01003 +++ b/wokkel/compat.py Wed Mar 25 18:15:15 2009 +01001 diff -r 84ffc75012b4 wokkel/compat.py 2 --- a/wokkel/compat.py Tue Apr 07 11:14:44 2009 +0200 3 +++ b/wokkel/compat.py Tue Apr 07 11:15:52 2009 +0200 4 4 @@ -7,40 +7,6 @@ 5 5 from twisted.words.protocols.jabber import xmlstream … … 43 43 """ 44 44 XmlStream factory mixin to install bootstrap event observers. 45 diff -r 6fa0283e522bwokkel/subprotocols.py46 --- a/wokkel/subprotocols.py Wed Mar 25 18:14:08 2009 +010047 +++ b/wokkel/subprotocols.py Wed Mar 25 18:15:15 2009 +010045 diff -r 84ffc75012b4 wokkel/subprotocols.py 46 --- a/wokkel/subprotocols.py Tue Apr 07 11:14:44 2009 +0200 47 +++ b/wokkel/subprotocols.py Tue Apr 07 11:15:52 2009 +0200 48 48 @@ -1,6 +1,6 @@ 49 49 # -*- test-case-name: wokkel.test.test_subprotocols -*- … … 70 70 71 71 class XMPPHandler(object): 72 diff -r 6fa0283e522bwokkel/test/test_compat.py73 --- a/wokkel/test/test_compat.py Wed Mar 25 18:14:08 2009 +010074 +++ b/wokkel/test/test_compat.py Wed Mar 25 18:15:15 2009 +010072 diff -r 84ffc75012b4 wokkel/test/test_compat.py 73 --- a/wokkel/test/test_compat.py Tue Apr 07 11:14:44 2009 +0200 74 +++ b/wokkel/test/test_compat.py Tue Apr 07 11:15:52 2009 +0200 75 75 @@ -1,5 +1,5 @@ 76 76 -# Copyright (c) 2001-2007 Twisted Matrix Laboratories. … … 166 166 """ 167 167 Tests for L{XmlStreamServerFactory}. 168 diff -r 6fa0283e522bwokkel/test/test_disco.py169 --- a/wokkel/test/test_disco.py Wed Mar 25 18:14:08 2009 +0100170 +++ b/wokkel/test/test_disco.py Wed Mar 25 18:15:15 2009 +0100168 diff -r 84ffc75012b4 wokkel/test/test_disco.py 169 --- a/wokkel/test/test_disco.py Tue Apr 07 11:14:44 2009 +0200 170 +++ b/wokkel/test/test_disco.py Tue Apr 07 11:15:52 2009 +0200 171 171 @@ -10,6 +10,7 @@ 172 172 from twisted.internet import defer … … 189 189 NS_DISCO_ITEMS = 'http://jabber.org/protocol/disco#items' 190 190 191 diff -r 6fa0283e522bwokkel/test/test_pubsub.py192 --- a/wokkel/test/test_pubsub.py Wed Mar 25 18:14:08 2009 +0100193 +++ b/wokkel/test/test_pubsub.py Wed Mar 25 18:15:15 2009 +0100191 diff -r 84ffc75012b4 wokkel/test/test_pubsub.py 192 --- a/wokkel/test/test_pubsub.py Tue Apr 07 11:14:44 2009 +0200 193 +++ b/wokkel/test/test_pubsub.py Tue Apr 07 11:15:52 2009 +0200 194 194 @@ -1,4 +1,4 @@ 195 195 -# Copyright (c) 2003-2008 Ralph Meijer … … 198 198 199 199 """ 200 @@ -12,1 6 +12,12@@200 @@ -12,15 +12,11 @@ 201 201 from twisted.words.xish import domish 202 202 from twisted.words.protocols.jabber import error … … 205 205 206 206 from wokkel import data_form, disco, iwokkel, pubsub, shim 207 from wokkel.generic import parseXml208 207 from wokkel.test.helpers import TestableRequestHandlerMixin, XmlStreamStub 209 208 -
pubsub_request.patch
r6 r7 11 11 that is passed to the corresponding handler methods. 12 12 13 diff -r 0bfc0b2a633cwokkel/generic.py14 --- a/wokkel/generic.py Wed Apr 01 17:25:11 2009 +020015 +++ b/wokkel/generic.py Wed Apr 01 17:26:462009 +020013 diff -r 556fc011f965 wokkel/generic.py 14 --- a/wokkel/generic.py Tue Apr 07 11:16:01 2009 +0200 15 +++ b/wokkel/generic.py Tue Apr 07 11:17:21 2009 +0200 16 16 @@ -10,7 +10,7 @@ 17 17 from zope.interface import implements … … 61 61 protocol = xmlstream.XmlStream 62 62 63 diff -r 0bfc0b2a633cwokkel/iwokkel.py64 --- a/wokkel/iwokkel.py Wed Apr 01 17:25:11 2009 +020065 +++ b/wokkel/iwokkel.py Wed Apr 01 17:26:462009 +020063 diff -r 556fc011f965 wokkel/iwokkel.py 64 --- a/wokkel/iwokkel.py Tue Apr 07 11:16:01 2009 +0200 65 +++ b/wokkel/iwokkel.py Tue Apr 07 11:17:21 2009 +0200 66 66 @@ -278,6 +278,7 @@ 67 67 C{list} of L{domish.Element}) … … 343 343 + @rtype: L{defer.Deferred} 344 344 """ 345 diff -r 0bfc0b2a633cwokkel/pubsub.py346 --- a/wokkel/pubsub.py Wed Apr 01 17:25:11 2009 +0200347 +++ b/wokkel/pubsub.py Wed Apr 01 17:26:462009 +0200345 diff -r 556fc011f965 wokkel/pubsub.py 346 --- a/wokkel/pubsub.py Tue Apr 07 11:16:01 2009 +0200 347 +++ b/wokkel/pubsub.py Tue Apr 07 11:17:21 2009 +0200 348 348 @@ -16,7 +16,7 @@ 349 349 from twisted.words.protocols.jabber import jid, error, xmlstream … … 1415 1415 + def delete(self, request): 1416 1416 raise Unsupported('delete-nodes') 1417 diff -r 0bfc0b2a633cwokkel/test/test_pubsub.py1418 --- a/wokkel/test/test_pubsub.py Wed Apr 01 17:25:11 2009 +02001419 +++ b/wokkel/test/test_pubsub.py Wed Apr 01 17:26:462009 +02001420 @@ -1 4,6 +14,7 @@1421 from twisted.words.protocols.jabber. jid import JID1422 1423 from wokkel import data_form, iwokkel, pubsub, shim1417 diff -r 556fc011f965 wokkel/test/test_pubsub.py 1418 --- a/wokkel/test/test_pubsub.py Tue Apr 07 11:16:01 2009 +0200 1419 +++ b/wokkel/test/test_pubsub.py Tue Apr 07 11:17:21 2009 +0200 1420 @@ -15,6 +15,7 @@ 1421 from twisted.words.protocols.jabber.xmlstream import toResponse 1422 1423 from wokkel import data_form, disco, iwokkel, pubsub, shim 1424 1424 +from wokkel.generic import parseXml 1425 1425 from wokkel.test.helpers import TestableRequestHandlerMixin, XmlStreamStub 1426 1426 1427 try:1428 @@ -4 90,6 +491,630 @@1427 NS_PUBSUB = 'http://jabber.org/protocol/pubsub' 1428 @@ -487,6 +488,630 @@ 1429 1429 1430 1430 … … 2057 2057 """ 2058 2058 Tests for L{pubsub.PubSubService}. 2059 @@ -50 7,6 +1132,29 @@2059 @@ -504,6 +1129,29 @@ 2060 2060 verify.verifyObject(iwokkel.IPubSubService, self.service) 2061 2061 … … 2087 2087 """ 2088 2088 Test getDiscoInfo calls getNodeInfo and returns some minimal info. 2089 @@ -5 24,28 +1172,6 @@2089 @@ -569,28 +1217,6 @@ 2090 2090 return d 2091 2091 … … 2116 2116 """ 2117 2117 A publish request should result in L{PubSubService.publish} being 2118 @@ - 561,27 +1187,147 @@2118 @@ -606,27 +1232,147 @@ 2119 2119 </iq> 2120 2120 """ … … 2271 2271 </iq> 2272 2272 """ 2273 @@ -6 27,14 +1373,141 @@2273 @@ -672,14 +1418,141 @@ 2274 2274 self.assertEqual('subscribed', subscription['subscription']) 2275 2275 … … 2416 2416 d.addCallback(cb) 2417 2417 return d 2418 @@ - 665,10 +1538,7 @@2418 @@ -710,10 +1583,7 @@ 2419 2419 "label": "Deliver payloads with event notifications"} 2420 2420 } … … 2428 2428 2429 2429 def cb(element): 2430 @@ - 686,6 +1556,85 @@2430 @@ -731,6 +1601,85 @@ 2431 2431 return d 2432 2432 … … 2514 2514 """ 2515 2515 On a node configuration get request L{PubSubService.getConfiguration} 2516 @@ -7 14,14 +1663,11 @@2516 @@ -759,14 +1708,11 @@ 2517 2517 "label": "Owner of the node"} 2518 2518 } … … 2532 2532 def cb(element): 2533 2533 self.assertEqual('pubsub', element.name) 2534 @@ -7 49,8 +1695,12 @@2534 @@ -794,8 +1740,12 @@ 2535 2535 field.typeCheck() 2536 2536 self.assertEqual(JID('user@example.org'), field.value) … … 2545 2545 d.addCallback(cb) 2546 2546 return d 2547 @@ - 789,16 +1739,14 @@2547 @@ -834,16 +1784,14 @@ 2548 2548 "label": "Deliver payloads with event notifications"} 2549 2549 } … … 2565 2565 2566 2566 2567 @@ -8 23,10 +1771,11 @@2567 @@ -868,10 +1816,11 @@ 2568 2568 </iq> 2569 2569 """ … … 2578 2578 2579 2579 2580 @@ - 862,14 +1811,47 @@2580 @@ -907,14 +1856,47 @@ 2581 2581 "label": "Deliver payloads with event notifications"} 2582 2582 } … … 2628 2628 """ 2629 2629 On a items request, return all items for the given node. 2630 @@ - 883,12 +1865,7 @@2630 @@ -928,12 +1910,7 @@ 2631 2631 </iq> 2632 2632 """ … … 2642 2642 2643 2643 def cb(element): 2644 @@ -9 25,11 +1902,7 @@2644 @@ -970,11 +1947,7 @@ 2645 2645 </iq> 2646 2646 """ … … 2655 2655 2656 2656 self.service.retract = retract 2657 @@ -9 51,10 +1924,7 @@2657 @@ -996,10 +1969,7 @@ 2658 2658 </iq> 2659 2659 """ … … 2667 2667 2668 2668 self.service.purge = purge 2669 @@ - 976,10 +1946,7 @@2669 @@ -1021,10 +1991,7 @@ 2670 2670 </iq> 2671 2671 """ … … 2679 2679 2680 2680 self.service.delete = delete 2681 @@ -10 31,3 +1998,461 @@2681 @@ -1076,3 +2043,461 @@ 2682 2682 self.assertEqual(NS_PUBSUB_EVENT, message.event.delete.redirect.uri) 2683 2683 self.assertTrue(message.event.delete.redirect.hasAttribute('uri')) -
pubsub_resource.patch
r5 r7 1 diff -r 2ea6196efcdcwokkel/iwokkel.py2 --- a/wokkel/iwokkel.py Wed Mar 25 18:14:07 2009 +01003 +++ b/wokkel/iwokkel.py Mon Mar 30 08:35:052009 +02001 diff -r cf770fa6bcb7 wokkel/iwokkel.py 2 --- a/wokkel/iwokkel.py Tue Apr 07 11:17:23 2009 +0200 3 +++ b/wokkel/iwokkel.py Tue Apr 07 11:25:27 2009 +0200 4 4 @@ -297,75 +297,46 @@ 5 5 """ … … 208 208 Called when a node configuration change request has been received. 209 209 210 diff -r 2ea6196efcdcwokkel/pubsub.py211 --- a/wokkel/pubsub.py Wed Mar 25 18:14:07 2009 +0100212 +++ b/wokkel/pubsub.py Mon Mar 30 08:35:052009 +0200210 diff -r cf770fa6bcb7 wokkel/pubsub.py 211 --- a/wokkel/pubsub.py Tue Apr 07 11:17:23 2009 +0200 212 +++ b/wokkel/pubsub.py Tue Apr 07 11:25:27 2009 +0200 213 213 @@ -13,12 +13,13 @@ 214 214 from zope.interface import implements … … 296 296 @@ -852,17 +845,33 @@ 297 297 298 info.append(form .toElement())298 info.append(form) 299 299 300 300 - d = self.getNodeInfo(requestor, target, nodeIdentifier or '') … … 765 765 + def subscriptionsSet(self, request): 766 766 + return defer.fail(Unsupported('manage-subscriptions')) 767 diff -r 2ea6196efcdc wokkel/test/test_pubsub.py 768 --- a/wokkel/test/test_pubsub.py Wed Mar 25 18:14:07 2009 +0100 769 +++ b/wokkel/test/test_pubsub.py Mon Mar 30 08:35:05 2009 +0200 770 @@ -13,7 +13,7 @@ 771 from twisted.words.protocols.jabber import error 772 from twisted.words.protocols.jabber.jid import JID 773 774 -from wokkel import data_form, iwokkel, pubsub, shim 775 +from wokkel import data_form, disco, iwokkel, pubsub, shim 776 from wokkel.generic import parseXml 777 from wokkel.test.helpers import TestableRequestHandlerMixin, XmlStreamStub 778 779 @@ -1225,7 +1225,8 @@ 767 diff -r cf770fa6bcb7 wokkel/test/test_pubsub.py 768 --- a/wokkel/test/test_pubsub.py Tue Apr 07 11:17:23 2009 +0200 769 +++ b/wokkel/test/test_pubsub.py Tue Apr 07 11:25:27 2009 +0200 770 @@ -1222,7 +1222,8 @@ 780 771 781 772 def setUp(self): … … 787 778 788 779 def test_interface(self): 789 @@ -126 3,19 +1264,120@@780 @@ -1260,12 +1261,12 @@ 790 781 Test getDiscoInfo calls getNodeInfo and returns some minimal info. 791 782 """ … … 805 796 JID('pubsub.example.org'), '') 806 797 d.addCallback(cb) 798 @@ -1282,11 +1283,11 @@ 799 discoInfo.append(item) 800 self.assertIn(('pubsub', 'collection'), discoInfo.identities) 801 802 - def getNodeInfo(requestor, target, nodeIdentifier): 803 + def getInfo(requestor, target, nodeIdentifier): 804 return defer.succeed({'type': 'collection', 805 'meta-data': {}}) 806 807 - self.service.getNodeInfo = getNodeInfo 808 + self.resource.getInfo = getInfo 809 d = self.service.getDiscoInfo(JID('user@example.org/home'), 810 JID('pubsub.example.org'), '') 811 d.addCallback(cb) 812 @@ -1307,20 +1308,100 @@ 813 form = discoInfo.extensions[NS_PUBSUB_META_DATA] 814 self.assertIn('pubsub#node_type', form.fields) 815 816 - def getNodeInfo(requestor, target, nodeIdentifier): 817 + def getInfo(requestor, target, nodeIdentifier): 818 metaData = [{'var': 'pubsub#persist_items', 819 'label': 'Persist items to storage', 820 'value': True}] 821 return defer.succeed({'type': 'leaf', 'meta-data': metaData}) 822 823 - self.service.getNodeInfo = getNodeInfo 824 + self.resource.getInfo = getInfo 825 d = self.service.getDiscoInfo(JID('user@example.org/home'), 826 JID('pubsub.example.org'), '') 827 d.addCallback(cb) 807 828 return d 808 829 809 830 810 831 - def test_onPublish(self): 811 + def test_getDiscoInfoNodeType(self):812 + """813 + Test getDiscoInfo calls getNodeInfo and returns some minimal info.814 + """815 + def cb(info):816 + discoInfo = disco.DiscoInfo()817 + for item in info:818 + discoInfo.append(item)819 + self.assertIn(('pubsub', 'collection'), discoInfo.identities)820 +821 + def getInfo(requestor, target, nodeIdentifier):822 + return defer.succeed({'type': 'collection',823 + 'meta-data': {}})824 +825 + self.resource.getInfo = getInfo826 + d = self.service.getDiscoInfo(JID('user@example.org/home'),827 + JID('pubsub.example.org'), '')828 + d.addCallback(cb)829 + return d830 +831 +832 832 + def test_getDiscoInfoResourceFeatures(self): 833 833 + """ 834 + Test getDiscoInfo calls getNodeInfo and returns some minimal info.834 + Test getDiscoInfo with the resource features. 835 835 + """ 836 836 + def cb(info): … … 914 914 A publish request should result in L{PubSubService.publish} being 915 915 called. 916 @@ -1 293,12 +1395,12 @@916 @@ -1338,12 +1419,12 @@ 917 917 def publish(request): 918 918 return defer.succeed(None) … … 930 930 A successful subscription should return the current subscription. 931 931 """ 932 @@ -13 26,14 +1428,14 @@932 @@ -1371,14 +1452,14 @@ 933 933 self.assertEqual('user@example.org/Home', subscription['jid']) 934 934 self.assertEqual('subscribed', subscription['subscription']) … … 948 948 A successful subscription on root node should return no node attribute. 949 949 """ 950 @@ -1 355,14 +1457,14 @@950 @@ -1400,14 +1481,14 @@ 951 951 def cb(element): 952 952 self.assertFalse(element.subscription.hasAttribute('node')) … … 966 966 A successful unsubscription should return an empty response. 967 967 """ 968 @@ -1 382,14 +1484,14 @@968 @@ -1427,14 +1508,14 @@ 969 969 def cb(element): 970 970 self.assertIdentical(None, element) … … 984 984 Getting subscription options is not supported. 985 985 """ 986 @@ -14 14,7 +1516,7 @@986 @@ -1459,7 +1540,7 @@ 987 987 return d 988 988 … … 993 993 Setting subscription options is not supported. 994 994 """ 995 @@ -14 46,7 +1548,7 @@995 @@ -1491,7 +1572,7 @@ 996 996 return d 997 997 … … 1002 1002 A subscriptions request should result in 1003 1003 L{PubSubService.subscriptions} being called and the result prepared 1004 @@ -1 462,6 +1564,11 @@1004 @@ -1507,6 +1588,11 @@ 1005 1005 </iq> 1006 1006 """ … … 1014 1014 self.assertEqual('pubsub', element.name) 1015 1015 self.assertEqual(NS_PUBSUB, element.uri) 1016 @@ -1 475,20 +1582,14 @@1016 @@ -1520,20 +1606,14 @@ 1017 1017 self.assertEqual('test', subscription['node']) 1018 1018 self.assertEqual('subscribed', subscription['subscription']) … … 1038 1038 A subscriptions request should result in 1039 1039 L{PubSubService.affiliations} being called and the result prepared 1040 @@ -15 04,6 +1605,10 @@1040 @@ -1549,6 +1629,10 @@ 1041 1041 </iq> 1042 1042 """ … … 1049 1049 self.assertEqual('pubsub', element.name) 1050 1050 self.assertEqual(NS_PUBSUB, element.uri) 1051 @@ -15 16,19 +1621,14 @@1051 @@ -1561,19 +1645,14 @@ 1052 1052 self.assertEqual('test', affiliation['node']) 1053 1053 self.assertEqual('owner', affiliation['affiliation']) … … 1072 1072 Replies to create node requests don't return the created node. 1073 1073 """ 1074 @@ -15 48,14 +1648,14 @@1074 @@ -1593,14 +1672,14 @@ 1075 1075 def cb(element): 1076 1076 self.assertIdentical(None, element) … … 1090 1090 Replies to create node requests return the created node if changed. 1091 1091 """ 1092 @@ -1 579,14 +1679,14 @@1092 @@ -1624,14 +1703,14 @@ 1093 1093 self.assertEqual(u'myrenamednode', 1094 1094 element.create.getAttribute('node')) … … 1108 1108 Replies to create instant node requests return the created node. 1109 1109 """ 1110 @@ -16 09,14 +1709,14 @@1110 @@ -1654,14 +1733,14 @@ 1111 1111 self.assertEqual(NS_PUBSUB, element.create.uri) 1112 1112 self.assertEqual(u'random', element.create.getAttribute('node')) … … 1126 1126 A default request should result in 1127 1127 L{PubSubService.getDefaultConfiguration} being called. 1128 @@ -16 41,7 +1741,7 @@1128 @@ -1686,7 +1765,7 @@ 1129 1129 "label": "Deliver payloads with event notifications"} 1130 1130 } … … 1135 1135 1136 1136 def cb(element): 1137 @@ -16 51,15 +1751,15 @@1137 @@ -1696,15 +1775,15 @@ 1138 1138 form = data_form.Form.fromElement(element.default.x) 1139 1139 self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace) … … 1155 1155 Responses to default requests should depend on passed node type. 1156 1156 """ 1157 @@ -1 690,19 +1790,19 @@1157 @@ -1735,19 +1814,19 @@ 1158 1158 "label": "Deliver payloads with event notifications"} 1159 1159 } … … 1181 1181 1182 1182 xml = """ 1183 @@ -17 24,24 +1824,25 @@1183 @@ -1769,24 +1848,25 @@ 1184 1184 </iq> 1185 1185 """ … … 1213 1213 1214 1214 xml = """ 1215 @@ -1 766,7 +1867,7 @@1215 @@ -1811,7 +1891,7 @@ 1216 1216 "label": "Owner of the node"} 1217 1217 } … … 1222 1222 'pubsub#persist_items': '1', 1223 1223 'pubsub#owner': JID('user@example.org'), 1224 @@ -18 00,19 +1901,18 @@1224 @@ -1845,19 +1925,18 @@ 1225 1225 1226 1226 self.assertNotIn('x-myfield', fields) … … 1247 1247 1248 1248 xml = """ 1249 @@ -18 42,21 +1942,21 @@1249 @@ -1887,21 +1966,21 @@ 1250 1250 "label": "Deliver payloads with event notifications"} 1251 1251 } … … 1276 1276 1277 1277 xml = """ 1278 @@ -1 874,15 +1974,15 @@1278 @@ -1919,15 +1998,15 @@ 1279 1279 </iq> 1280 1280 """ … … 1296 1296 On a node configuration set request unknown fields should be ignored. 1297 1297 """ 1298 @@ -19 14,17 +2014,17 @@1298 @@ -1959,17 +2038,17 @@ 1299 1299 "label": "Deliver payloads with event notifications"} 1300 1300 } … … 1319 1319 On a node configuration set request unknown fields should be ignored. 1320 1320 """ 1321 @@ - 1955,7 +2055,7 @@1321 @@ -2000,7 +2079,7 @@ 1322 1322 return d 1323 1323 … … 1328 1328 On a items request, return all items for the given node. 1329 1329 """ 1330 @@ - 1981,16 +2081,17 @@1330 @@ -2026,16 +2105,17 @@ 1331 1331 self.assertEqual(NS_PUBSUB, item.uri) 1332 1332 self.assertEqual('current', item['id']) … … 1350 1350 1351 1351 xml = """ 1352 @@ -20 08,13 +2109,14 @@1352 @@ -2053,13 +2133,14 @@ 1353 1353 def retract(request): 1354 1354 return defer.succeed(None) … … 1368 1368 """ 1369 1369 1370 @@ -20 30,13 +2132,14 @@1370 @@ -2075,13 +2156,14 @@ 1371 1371 def purge(request): 1372 1372 return defer.succeed(None) … … 1386 1386 """ 1387 1387 1388 @@ -20 52,7 +2155,8 @@1388 @@ -2097,7 +2179,8 @@ 1389 1389 def delete(request): 1390 1390 return defer.succeed(None) … … 1396 1396 1397 1397 1398 @@ -21 03,7 +2207,7 @@1398 @@ -2148,7 +2231,7 @@ 1399 1399 self.assertEqual(redirectURI, message.event.delete.redirect['uri']) 1400 1400 … … 1405 1405 Getting subscription options is not supported. 1406 1406 """ 1407 @@ -21 30,7 +2234,7 @@1407 @@ -2175,7 +2258,7 @@ 1408 1408 return d 1409 1409 … … 1414 1414 Setting subscription options is not supported. 1415 1415 """ 1416 @@ -2 157,7 +2261,7 @@1416 @@ -2202,7 +2285,7 @@ 1417 1417 return d 1418 1418 … … 1423 1423 Getting subscription options is not supported. 1424 1424 """ 1425 @@ -2 184,7 +2288,7 @@1425 @@ -2229,7 +2312,7 @@ 1426 1426 return d 1427 1427 … … 1432 1432 Setting subscription options is not supported. 1433 1433 """ 1434 @@ -22 11,18 +2315,38 @@1434 @@ -2256,18 +2339,38 @@ 1435 1435 return d 1436 1436 … … 1481 1481 1482 1482 def cb(result): 1483 @@ -22 31,7 +2355,7 @@1483 @@ -2276,7 +2379,7 @@ 1484 1484 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 1485 1485 self.assertEquals('publish', result.appCondition['feature']) … … 1490 1490 d.addCallback(cb) 1491 1491 return d 1492 @@ -22 39,16 +2363,7 @@1492 @@ -2284,16 +2387,7 @@ 1493 1493 1494 1494 def test_subscribe(self): … … 1508 1508 1509 1509 def cb(result): 1510 @@ -2 257,7 +2372,7 @@1510 @@ -2302,7 +2396,7 @@ 1511 1511 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 1512 1512 self.assertEquals('subscribe', result.appCondition['feature']) … … 1517 1517 d.addCallback(cb) 1518 1518 return d 1519 @@ -2 265,16 +2380,7 @@1519 @@ -2310,16 +2404,7 @@ 1520 1520 1521 1521 def test_unsubscribe(self): … … 1535 1535 1536 1536 def cb(result): 1537 @@ -2 283,7 +2389,7 @@1537 @@ -2328,7 +2413,7 @@ 1538 1538 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 1539 1539 self.assertEquals('subscribe', result.appCondition['feature']) … … 1544 1544 d.addCallback(cb) 1545 1545 return d 1546 @@ -2 291,16 +2397,7 @@1546 @@ -2336,16 +2421,7 @@ 1547 1547 1548 1548 def test_subscriptions(self): … … 1562 1562 1563 1563 def cb(result): 1564 @@ -23 10,7 +2407,7 @@1564 @@ -2355,7 +2431,7 @@ 1565 1565 self.assertEquals('retrieve-subscriptions', 1566 1566 result.appCondition['feature']) … … 1571 1571 d.addCallback(cb) 1572 1572 return d 1573 @@ -23 18,16 +2415,7 @@1573 @@ -2363,16 +2439,7 @@ 1574 1574 1575 1575 def test_affiliations(self): … … 1589 1589 1590 1590 def cb(result): 1591 @@ -23 37,7 +2425,7 @@1591 @@ -2382,7 +2449,7 @@ 1592 1592 self.assertEquals('retrieve-affiliations', 1593 1593 result.appCondition['feature']) … … 1598 1598 d.addCallback(cb) 1599 1599 return d 1600 @@ -23 45,16 +2433,7 @@1600 @@ -2390,16 +2457,7 @@ 1601 1601 1602 1602 def test_create(self): … … 1616 1616 1617 1617 def cb(result): 1618 @@ -2 363,87 +2442,51 @@1618 @@ -2408,87 +2466,51 @@ 1619 1619 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 1620 1620 self.assertEquals('create-nodes', result.appCondition['feature']) … … 1715 1715 1716 1716 def cb(result): 1717 @@ -24 52,7 +2495,7 @@1717 @@ -2497,7 +2519,7 @@ 1718 1718 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 1719 1719 self.assertEquals('config-node', result.appCondition['feature']) … … 1724 1724 d.addCallback(cb) 1725 1725 return d 1726 @@ -2 460,15 +2503,7 @@1726 @@ -2505,15 +2527,7 @@ 1727 1727 1728 1728 def test_items(self): … … 1741 1741 1742 1742 def cb(result): 1743 @@ -2 477,7 +2512,7 @@1743 @@ -2522,7 +2536,7 @@ 1744 1744 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 1745 1745 self.assertEquals('retrieve-items', result.appCondition['feature']) … … 1750 1750 d.addCallback(cb) 1751 1751 return d 1752 @@ -2 485,18 +2520,7 @@1752 @@ -2530,18 +2544,7 @@ 1753 1753 1754 1754 def test_retract(self): … … 1770 1770 1771 1771 def cb(result): 1772 @@ -25 05,7 +2529,7 @@1772 @@ -2550,7 +2553,7 @@ 1773 1773 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 1774 1774 self.assertEquals('retract-items', result.appCondition['feature']) … … 1779 1779 d.addCallback(cb) 1780 1780 return d 1781 @@ -25 13,15 +2537,7 @@1781 @@ -2558,15 +2561,7 @@ 1782 1782 1783 1783 def test_purge(self): … … 1796 1796 1797 1797 def cb(result): 1798 @@ -25 30,7 +2546,7 @@1798 @@ -2575,7 +2570,7 @@ 1799 1799 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 1800 1800 self.assertEquals('purge-nodes', result.appCondition['feature']) … … 1805 1805 d.addCallback(cb) 1806 1806 return d 1807 @@ -25 38,15 +2554,7 @@1807 @@ -2583,15 +2578,7 @@ 1808 1808 1809 1809 def test_delete(self): … … 1822 1822 1823 1823 def cb(result): 1824 @@ -2 555,7 +2563,7 @@1824 @@ -2600,7 +2587,7 @@ 1825 1825 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 1826 1826 self.assertEquals('delete-nodes', result.appCondition['feature']) -
release-0.5.patch
r1 r7 1 diff -r 64319a254f83LICENSE2 --- a/LICENSE Wed Feb 04 14:42:34 2009 +01003 +++ b/LICENSE Wed Feb 04 15:30:11 2009 +01001 diff -r a3563a451736 LICENSE 2 --- a/LICENSE Tue Apr 07 09:22:25 2009 +0200 3 +++ b/LICENSE Tue Apr 07 09:24:47 2009 +0200 4 4 @@ -1,4 +1,4 @@ 5 5 -Copyright (c) 2003-2008 Ralph Meijer … … 8 8 Permission is hereby granted, free of charge, to any person obtaining 9 9 a copy of this software and associated documentation files (the 10 diff -r 64319a254f83NEWS11 --- a/NEWS Wed Feb 04 14:42:34 2009 +010012 +++ b/NEWS Wed Feb 04 15:30:11 2009 +010010 diff -r a3563a451736 NEWS 11 --- a/NEWS Tue Apr 07 09:22:25 2009 +0200 12 +++ b/NEWS Tue Apr 07 09:24:47 2009 +0200 13 13 @@ -1,3 +1,37 @@ 14 +0.5.0 (2009-0 2-04)14 +0.5.0 (2009-04-07) 15 15 +================== 16 16 + … … 36 36 +----- 37 37 + 38 + - Publish-Subscribe subscriptions requests work again (#22 , Mike Malone).38 + - Publish-Subscribe subscriptions requests work again (#22). 39 39 + - Publish-Subscribe delete node requests now have the correct namespace (#27). 40 40 + - NodeIDs in Service Discovery requests are now returned in responses (#7). … … 49 49 ================== 50 50 51 diff -r 64319a254f83README52 --- a/README Wed Feb 04 14:42:34 2009 +010053 +++ b/README Wed Feb 04 15:30:11 2009 +010051 diff -r a3563a451736 README 52 --- a/README Tue Apr 07 09:22:25 2009 +0200 53 +++ b/README Tue Apr 07 09:24:47 2009 +0200 54 54 @@ -1,30 +1,53 @@ 55 55 -Wokkel 0.4.0 … … 117 117 Ralph Meijer 118 118 <xmpp:ralphm@ik.nu> 119 diff -r 64319a254f83setup.py120 --- a/setup.py Wed Feb 04 14:42:34 2009 +0100121 +++ b/setup.py Wed Feb 04 15:30:11 2009 +0100119 diff -r a3563a451736 setup.py 120 --- a/setup.py Tue Apr 07 09:22:25 2009 +0200 121 +++ b/setup.py Tue Apr 07 09:24:47 2009 +0200 122 122 @@ -1,12 +1,12 @@ 123 123 #!/usr/bin/env python -
s2s.patch
r6 r7 1 diff -r c52801c0d6c2wokkel/server.py1 diff -r 842c0a2f8fa1 wokkel/server.py 2 2 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3 +++ b/wokkel/server.py Wed Apr 01 17:23:432009 +02004 @@ -0,0 +1, 566@@3 +++ b/wokkel/server.py Tue Apr 07 09:17:35 2009 +0200 4 @@ -0,0 +1,684 @@ 5 5 +# -*- test-case-name: wokkel.test.test_server -*- 6 6 +# … … 225 225 + 226 226 +class XMPPServerConnectAuthenticator(xmlstream.ConnectAuthenticator): 227 + """ 228 + Authenticator for an outgoing XMPP server-to-server connection. 229 + 230 + This authenticator connects to C{otherHost} (the Receiving Server) and then 231 + initiates dialback as C{thisHost} (the Originating Server) using 232 + L{OriginatingDialbackInitializer}. 233 + 234 + @ivar thisHost: The domain this server connects from (the Originating 235 + Server) . 236 + @ivar otherHost: The domain of the server this server connects to (the 237 + Receiving Server). 238 + @ivar secret: The shared secret that is used for verifying the validity 239 + of this new connection. 240 + """ 227 241 + namespace = 'jabber:server' 228 242 + … … 250 264 + 251 265 +class XMPPServerVerifyAuthenticator(xmlstream.ConnectAuthenticator): 266 + """ 267 + Authenticator for an outgoing connection to verify an incoming connection. 268 + 269 + This authenticator connects to C{otherHost} (the Authoritative Server) and 270 + then initiates dialback as C{thisHost} (the Receiving Server) using 271 + L{ReceivingDialbackInitializer}. 272 + 273 + @ivar thisHost: The domain this server connects from (the Receiving 274 + Server) . 275 + @ivar otherHost: The domain of the server this server connects to (the 276 + Authoritative Server). 277 + @ivar originalStreamID: The stream ID of the incoming connection that is 278 + being verified. 279 + @ivar key: The key provided by the Receving Server to be verified. 280 + """ 252 281 + namespace = 'jabber:server' 253 282 + … … 276 305 + 277 306 +class XMPPServerListenAuthenticator(xmlstream.ListenAuthenticator): 307 + """ 308 + Authenticator for an incoming XMPP server-to-server connection. 309 + 310 + This authenticator handles two types of incoming connections. Regular 311 + server-to-server connections are from the Originating Server to the 312 + Receiving Server, where this server is the Receiving Server. These 313 + connections start out by receiving a dialback key, verifying the 314 + key with the Authoritative Server, and then accept normal XMPP stanzas. 315 + 316 + The other type of connections is from a Receiving Server to an 317 + Authoritative Server, where this server acts as the Authoritative Server. 318 + These connections are used to verify the validity of an outgoing connection 319 + from this server. In this case, this server receives a verification 320 + request, checks the key and then returns the result. 321 + 322 + @ivar service: The service that keeps the list of domains we accept 323 + connections for. 324 + """ 278 325 + namespace = 'jabber:server' 279 + connectorClass = XMPPServerConnector 280 + 281 + def __init__(self, domain, secret): 326 + 327 + def __init__(self, service): 282 328 + xmlstream.ListenAuthenticator.__init__(self) 283 + self.domain = domain 284 + self.secret = secret 329 + self.service = service 285 330 + 286 331 + … … 293 338 + self.xmlstream.sid = randbytes.secureRandom(8).encode('hex') 294 339 + 295 + def prepareStream(): 340 + if self.xmlstream.thisEntity: 341 + targetDomain = self.xmlstream.thisEntity.host 342 + else: 343 + targetDomain = self.service.defaultDomain 344 + 345 + def prepareStream(domain): 296 346 + self.xmlstream.namespace = self.namespace 297 347 + self.xmlstream.prefixes = {xmlstream.NS_STREAMS: 'stream', 298 348 + NS_DIALBACK: 'db'} 299 + self.xmlstream.thisEntity = jid.internJID( self.domain)349 + self.xmlstream.thisEntity = jid.internJID(domain) 300 350 + 301 351 + try: … … 305 355 + raise error.StreamError('invalid-namespace') 306 356 + 307 + if self.xmlstream.thisEntity.full() != self.domain:357 + if targetDomain not in self.service.domains: 308 358 + raise error.StreamError('host-unknown') 309 359 + except error.StreamError, exc: 310 + prepareStream( )360 + prepareStream(self.service.defaultDomain) 311 361 + self.xmlstream.sendStreamError(exc) 312 362 + return … … 318 368 + self.onResult) 319 369 + 320 + prepareStream( )370 + prepareStream(targetDomain) 321 371 + self.xmlstream.sendHeader() 322 372 + … … 326 376 + 327 377 + 328 +329 378 + def onVerify(self, verify): 330 379 + try: 331 + receivingServer = jid.JID(verify['from']) 332 + originatingServer = jid.JID(verify['to']) 380 + receivingServer = jid.JID(verify['from']).host 381 + originatingServer = jid.JID(verify['to']).host 333 382 + except (KeyError, jid.InvalidFormat): 334 383 + raise error.StreamError('improper-addressing') 335 384 + 336 + if originatingServer != self.domain:385 + if originatingServer not in self.service.domains: 337 386 + raise error.StreamError('host-unknown') 338 387 + 339 + if receivingServer != self.xmlstream.thisEntity: 388 + if (self.xmlstream.otherEntity and 389 + receivingServer != self.xmlstream.otherEntity.host): 340 390 + raise error.StreamError('invalid-from') 341 391 + … … 343 393 + key = unicode(verify) 344 394 + 345 + calculatedKey = generateKey(self.se cret, receivingServer,395 + calculatedKey = generateKey(self.service.secret, receivingServer, 346 396 + originatingServer, streamID) 347 397 + validity = (key == calculatedKey) and 'valid' or 'invalid' … … 356 406 + 357 407 + def onResult(self, result): 358 + def connected(xs):359 + self.verifyStream = xs360 +361 + def logDataIn(buf):362 + log.msg("RECV!: %r" % buf)363 +364 + def logDataOut(buf):365 + log.msg("SEND!: %r" % buf)366 +367 + xs.rawDataInFn = logDataIn368 + xs.rawDataOutFn = logDataOut369 +370 408 + def reply(validity): 371 + factory.stopTrying()372 + self.verifyStream.transport.loseConnection()373 + self.verifyStream = None374 +375 409 + reply = domish.Element((NS_DIALBACK, 'result')) 376 410 + reply['from'] = result['to'] … … 386 420 + 387 421 + def invalid(failure): 422 + log.err(failure) 388 423 + reply('invalid') 389 424 + 425 + receivingServer = result['to'] 390 426 + originatingServer = result['from'] 391 + 392 + authenticator = XMPPServerVerifyAuthenticator(self.domain, 393 + originatingServer, 394 + self.xmlstream.sid, 395 + unicode(result)) 396 + factory = xmlstream.XmlStreamFactory(authenticator) 397 + factory.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, connected) 398 + factory.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, valid) 399 + factory.addBootstrap(xmlstream.INIT_FAILED_EVENT, invalid) 400 + connector = self.connectorClass(reactor, 401 + originatingServer, 402 + factory) 403 + connector.connect() 427 + key = unicode(result) 428 + 429 + d = self.service.validateConnection(receivingServer, originatingServer, 430 + self.xmlstream.sid, key) 431 + d.addCallbacks(valid, invalid) 432 + return d 404 433 + 405 434 + … … 414 443 + """ 415 444 + 416 + def __init__(self, domain, otherHost, secret): 417 + authenticator = XMPPServerConnectAuthenticator(domain, 418 + otherHost, 419 + secret) 445 + def __init__(self, authenticator): 420 446 + DeferredXmlStreamFactory.__init__(self, authenticator) 447 + 448 + self.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, 449 + self.onConnectionMade) 450 + 451 + self.serial = 0 452 + 453 + 454 + def onConnectionMade(self, xs): 455 + xs.serial = self.serial 456 + self.serial += 1 457 + 458 + def logDataIn(buf): 459 + log.msg("RECV (%d): %r" % (xs.serial, buf)) 460 + 461 + def logDataOut(buf): 462 + log.msg("SEND (%d): %r" % (xs.serial, buf)) 463 + 464 + if self.logTraffic: 465 + xs.rawDataInFn = logDataIn 466 + xs.rawDataOutFn = logDataOut 421 467 + 422 468 + … … 430 476 + 431 477 + 432 +class ServerService(service.Service): 478 +class XMPPS2SServerFactory(XmlStreamServerFactory): 479 + """ 480 + XMPP Server-to-Server Server factory. 481 + 482 + This factory accepts XMPP server-to-server connections. 483 + """ 484 + 485 + logTraffic = False 486 + 487 + def __init__(self, service): 488 + self.service = service 489 + 490 + def authenticatorFactory(): 491 + return XMPPServerListenAuthenticator(service) 492 + 493 + XmlStreamServerFactory.__init__(self, authenticatorFactory) 494 + self.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, 495 + self.onConnectionMade) 496 + self.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, 497 + self.onAuthenticated) 498 + 499 + self.serial = 0 500 + 501 + 502 + def onConnectionMade(self, xs): 503 + """ 504 + Called when a server-to-server connection was made. 505 + 506 + This enables traffic debugging on incoming streams. 507 + """ 508 + xs.serial = self.serial 509 + self.serial += 1 510 + 511 + def logDataIn(buf): 512 + log.msg("RECV (%d): %r" % (xs.serial, buf)) 513 + 514 + def logDataOut(buf): 515 + log.msg("SEND (%d): %r" % (xs.serial, buf)) 516 + 517 + if self.logTraffic: 518 + xs.rawDataInFn = logDataIn 519 + xs.rawDataOutFn = logDataOut 520 + 521 + xs.addObserver(xmlstream.STREAM_ERROR_EVENT, self.onError) 522 + 523 + 524 + def onAuthenticated(self, xs): 525 + thisHost = xs.thisEntity.host 526 + otherHost = xs.otherEntity.host 527 + 528 + log.msg("Incoming connection %d from %r to %r established" % 529 + (xs.serial, otherHost, thisHost)) 530 + 531 + xs.addObserver(xmlstream.STREAM_END_EVENT, self.onConnectionLost, 532 + 0, xs) 533 + xs.addObserver('/*', self.onElement, 0, xs) 534 + 535 + 536 + def onConnectionLost(self, xs, reason): 537 + thisHost = xs.thisEntity.host 538 + otherHost = xs.otherEntity.host 539 + 540 + log.msg("Incoming connection %d from %r to %r disconnected" % 541 + (xs.serial, otherHost, thisHost)) 542 + 543 + 544 + def onError(self, reason): 545 + log.err(reason, "Stream Error") 546 + 547 + 548 + def onElement(self, element, xs): 549 + """ 550 + Called when an element was received from one of the connected streams. 551 + 552 + """ 553 + if element.handled: 554 + return 555 + 556 + if jid.internJID(element["from"]).host != xs.otherEntity.host: 557 + xs.sendStreamError(error.StreamError('invalid-from')) 558 + else: 559 + self.service.dispatch(element) 560 + 561 + 562 + 563 +class ServerService(object): 433 564 + """ 434 565 + Service for managing XMPP server to server connections. … … 437 568 + logTraffic = False 438 569 + 439 + def __init__(self, router, domain, port=5222):570 + def __init__(self, router, secret, domain): 440 571 + self.router = router 441 + self.domain = domain 442 + self.port = port 443 + self.secret = 'woei!' 444 + 445 + def authenticatorFactory(): 446 + return XMPPServerListenAuthenticator(self.domain, self.secret) 447 + self.factory = XmlStreamServerFactory(authenticatorFactory) 448 + self.factory.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, 449 + self.makeConnection) 450 + self.factory.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, 451 + self.incomingInitialized) 452 + 453 + self.incomingStreams = {} 454 + self.outgoingStreams = {} 455 + self.outgoingQueues = {} 456 + self.outgoingConnecting = set() 572 + self.secret = secret 573 + self.defaultDomain = domain 574 + self.domains = set([domain]) 575 + 576 + self._outgoingStreams = {} 577 + self._outgoingQueues = {} 578 + self._outgoingConnecting = set() 457 579 + self.serial = 0 458 580 + 459 +460 + def startService(self):461 581 + pipe = XmlPipe() 462 582 + self.xmlstream = pipe.source … … 464 584 + self.xmlstream.addObserver('/*', self.send) 465 585 + 466 + service.Service.startService(self)467 + reactor.listenTCP(self.port, self.factory)468 +469 +470 + def makeConnection(self, xs):471 + xs.serial = self.serial472 + self.serial += 1473 +474 + def logDataIn(buf):475 + log.msg("RECV (%d): %r" % (xs.serial, buf))476 +477 + def logDataOut(buf):478 + log.msg("SEND (%d): %r" % (xs.serial, buf))479 +480 + if self.logTraffic:481 + xs.rawDataInFn = logDataIn482 + xs.rawDataOutFn = logDataOut483 +484 +485 + def incomingInitialized(self, xs):486 + self.incomingStreams[xs.otherEntity.host] = xs487 + xs.addObserver(xmlstream.STREAM_END_EVENT,488 + lambda _: self.incomingDisconnected(xs))489 + xs.addObserver('/*', lambda element: self.onElement(element, xs))490 +491 +492 + def incomingDisconnected(self, xs):493 + del self.incomingStreams[xs.otherEntity.host]494 +495 586 + 496 587 + def outgoingInitialized(self, xs): 497 + self.outgoingStreams[xs.otherEntity.host] = xs 588 + thisHost = xs.thisEntity.host 589 + otherHost = xs.otherEntity.host 590 + 591 + log.msg("Outgoing connection %d from %r to %r established" % 592 + (xs.serial, thisHost, otherHost)) 593 + 594 + self._outgoingStreams[thisHost, otherHost] = xs 498 595 + xs.addObserver(xmlstream.STREAM_END_EVENT, 499 596 + lambda _: self.outgoingDisconnected(xs)) 500 597 + 501 + if xs.otherEntity.host in self.outgoingQueues: 502 + print "Hier!" 503 + for element in self.outgoingQueues[xs.otherEntity.host]: 598 + if (thisHost, otherHost) in self._outgoingQueues: 599 + for element in self._outgoingQueues[thisHost, otherHost]: 504 600 + xs.send(element) 505 + del self. outgoingQueues[xs.otherEntity.host]601 + del self._outgoingQueues[thisHost, otherHost] 506 602 + 507 603 + 508 604 + def outgoingDisconnected(self, xs): 509 + del self.outgoingStreams[xs.otherEntity.host] 510 + 511 + 512 + def initiateOutgoingStream(self, otherHost): 513 + if otherHost in self.outgoingConnecting: 605 + thisHost = xs.thisEntity.host 606 + otherHost = xs.otherEntity.host 607 + 608 + log.msg("Outgoing connection %d from %r to %r disconnected" % 609 + (xs.serial, thisHost, otherHost)) 610 + 611 + del self._outgoingStreams[thisHost, otherHost] 612 + 613 + 614 + def initiateOutgoingStream(self, thisHost, otherHost): 615 + """ 616 + Initiate an outgoing XMPP server-to-server connection. 617 + """ 618 + 619 + def resetConnecting(_): 620 + self._outgoingConnecting.remove((thisHost, otherHost)) 621 + 622 + if (thisHost, otherHost) in self._outgoingConnecting: 514 623 + return 515 624 + 516 + factory = DeferredS2SClientFactory(self.domain, 517 + otherHost, 518 + self.secret) 519 + factory.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, 520 + self.makeConnection) 625 + authenticator = XMPPServerConnectAuthenticator(thisHost, 626 + otherHost, 627 + self.secret) 628 + factory = DeferredS2SClientFactory(authenticator) 521 629 + factory.addBootstrap(xmlstream.STREAM_AUTHD_EVENT, 522 630 + self.outgoingInitialized) 523 631 + 524 + def resetConnecting(_): 525 + self.outgoingConnecting.remove(otherHost) 632 + self._outgoingConnecting.add((thisHost, otherHost)) 526 633 + 527 634 + d = initiateS2S(factory) 528 + def debug(result):529 + print result530 + return result531 + d.addBoth(debug)532 635 + d.addBoth(resetConnecting) 533 + self.outgoingConnecting.add(otherHost) 534 + 535 + 536 + def onElement(self, element, xs): 537 + """ 538 + Called when an element was received from one of the connected streams. 539 + 540 + """ 541 + if element.handled: 542 + return 543 + 544 + if jid.internJID(element["from"]).host != xs.otherEntity.host: 545 + xs.sendStreamError(error.StreamError('invalid-from')) 546 + else: 547 + self.xmlstream.send(element) 636 + return d 637 + 638 + 639 + def validateConnection(self, thisHost, otherHost, sid, key): 640 + """ 641 + Validate an incoming XMPP server-to-server connection. 642 + """ 643 + 644 + def connected(xs): 645 + # Set up stream for immediate disconnection. 646 + def disconnect(_): 647 + xs.transport.loseConnection() 648 + xs.addObserver(xmlstream.STREAM_AUTHD_EVENT, disconnect) 649 + xs.addObserver(xmlstream.INIT_FAILED_EVENT, disconnect) 650 + 651 + authenticator = XMPPServerVerifyAuthenticator(thisHost, otherHost, 652 + sid, key) 653 + factory = DeferredS2SClientFactory(authenticator) 654 + factory.addBootstrap(xmlstream.STREAM_CONNECTED_EVENT, connected) 655 + 656 + d = initiateS2S(factory) 657 + return d 548 658 + 549 659 + … … 556 666 + """ 557 667 + 558 + destination = jid.internJID(stanza["to"]).host 559 + 560 + if destination not in self.outgoingStreams: 668 + otherHost = jid.internJID(stanza["to"]).host 669 + thisHost = jid.internJID(stanza["from"]).host 670 + 671 + if (thisHost, otherHost) not in self._outgoingStreams: 561 672 + # There is no connection with the destination (yet). Cache the 562 673 + # outgoing stanza until the connection has been established. 563 674 + # XXX: If the connection cannot be established, the queue should 564 675 + # be emptied at some point. 565 + if destination not in self.outgoingQueues:566 + self. outgoingQueues[destination] = []567 + self. outgoingQueues[destination].append(stanza)568 + self.initiateOutgoingStream( destination)676 + if (thisHost, otherHost) not in self._outgoingQueues: 677 + self._outgoingQueues[(thisHost, otherHost)] = [] 678 + self._outgoingQueues[(thisHost, otherHost)].append(stanza) 679 + self.initiateOutgoingStream(thisHost, otherHost) 569 680 + else: 570 + self.outgoingStreams[destination].send(stanza) 571 diff -r c52801c0d6c2 wokkel/test/test_server.py 681 + self._outgoingStreams[(thisHost, otherHost)].send(stanza) 682 + 683 + 684 + def dispatch(self, element): 685 + """ 686 + Send on element to be routed within the server. 687 + """ 688 + self.xmlstream.send(element) 689 diff -r 842c0a2f8fa1 wokkel/test/test_server.py 572 690 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 573 +++ b/wokkel/test/test_server.py Wed Apr 01 17:23:432009 +0200574 @@ -0,0 +1, 227@@691 +++ b/wokkel/test/test_server.py Tue Apr 07 09:17:35 2009 +0200 692 @@ -0,0 +1,412 @@ 575 693 +# Copyright (c) 2003-2008 Ralph Meijer 576 694 +# See LICENSE for details. … … 580 698 +""" 581 699 + 700 +from twisted.internet import defer 701 +from twisted.python import failure 702 +from twisted.test.proto_helpers import StringTransport 582 703 +from twisted.trial import unittest 583 +from twisted.words.protocols.jabber import error, xmlstream584 +from twisted. test.proto_helpers import StringTransport585 + 586 +from wokkel import server704 +from twisted.words.protocols.jabber import error, jid, xmlstream 705 +from twisted.words.xish import domish 706 + 707 +from wokkel import component, server 587 708 + 588 709 +NS_STREAMS = 'http://etherx.jabber.org/streams' 589 + DIALBACK_NS= "jabber:server:dialback"710 +NS_DIALBACK = "jabber:server:dialback" 590 711 + 591 712 +class GenerateKeyTest(unittest.TestCase): … … 595 716 + 596 717 + def testBasic(self): 718 + originating = "example.org" 719 + receiving = "xmpp.example.com" 720 + sid = "D60000229F" 597 721 + secret = "s3cr3tf0rd14lb4ck" 598 + receiving = "example.net" 599 + originating = "example.com" 600 + id = "D60000229F" 601 + 602 + key = server.generateKey(secret, receiving, originating, id) 722 + 723 + key = server.generateKey(secret, receiving, originating, sid) 603 724 + 604 725 + self.assertEqual(key, 605 + ' 008c689ff366b50c63d69a3e2d2c0e0e1f8404b0118eb688a0102c87cb691bdc')726 + '37c69b1cf07a3f67c04a5ef5902fa5114f2c76fe4a2686482ba5b89323075643') 606 727 + 607 728 + … … 612 733 + """ 613 734 + 614 + receiving = "example.org" 615 + originating = "example.net" 616 + id_ = "2093845023948" 617 + secret = "not-telling" 735 + secret = "s3cr3tf0rd14lb4ck" 736 + originating = "example.org" 737 + receiving = "xmpp.example.com" 738 + sid = "D60000229F" 739 + key = '37c69b1cf07a3f67c04a5ef5902fa5114f2c76fe4a2686482ba5b89323075643' 618 740 + 619 741 + def setUp(self): 620 742 + self.output = [] 621 + self.authenticator = server.XMPPServerListenAuthenticator( 622 + self.receiving, self.secret) 743 + 744 + class MyService(object): 745 + pass 746 + 747 + self.service = MyService() 748 + self.service.defaultDomain = self.receiving 749 + self.service.domains = [self.receiving, 'pubsub.'+self.receiving] 750 + self.service.secret = self.secret 751 + 752 + self.authenticator = server.XMPPServerListenAuthenticator(self.service) 623 753 + self.xmlstream = xmlstream.XmlStream(self.authenticator) 624 754 + self.xmlstream.send = self.output.append … … 630 760 + Test attributes of authenticator and stream objects. 631 761 + """ 632 + self.assertEquals(self.secret, self.authenticator.secret) 633 + self.assertEquals(self.receiving, self.authenticator.domain) 634 + self.assertEquals(self.xmlstream.initiating, False) 762 + self.assertEqual(self.service, self.authenticator.service) 763 + self.assertEqual(self.xmlstream.initiating, False) 635 764 + 636 765 + … … 644 773 + "xmlns:db='jabber:server:dialback' " 645 774 + "xmlns='jabber:server' " 646 + "to=' example.org'>")775 + "to='xmpp.example.com'>") 647 776 + self.assertEqual((0, 0), self.xmlstream.version) 648 777 + … … 657 786 + "xmlns:db='jabber:server:dialback' " 658 787 + "xmlns='jabber:server' " 659 + "to=' example.org' "788 + "to='xmpp.example.com' " 660 789 + "version='1.0'>") 661 790 + self.assertEqual((1, 0), self.xmlstream.version) … … 673 802 + "xmlns:db='jabber:server:dialback' " 674 803 + "xmlns='jabber:server' " 675 + "to=' example.org' "804 + "to='xmpp.example.com' " 676 805 + "version='1.0'>") 677 806 + self.assertNotIdentical(None, self.xmlstream.sid) … … 689 818 + "xmlns:db='jabber:server:dialback' " 690 819 + "xmlns='jabber:server' " 691 + "to=' example.org'>")820 + "to='xmpp.example.com'>") 692 821 + self.assertTrue(self.xmlstream._headerSent) 693 822 + … … 702 831 + "xmlns:db='jabber:server:dialback' " 703 832 + "xmlns='jabber:server' " 704 + "to=' example.org'>")833 + "to='xmpp.example.com'>") 705 834 + self.assertEqual(1, len(self.output)) 706 835 + … … 715 844 + "xmlns:db='jabber:server:dialback' " 716 845 + "xmlns='jabber:server' " 717 + "to=' example.org' "846 + "to='xmpp.example.com' " 718 847 + "version='1.0'>") 719 848 + self.assertEqual(2, len(self.output)) … … 732 861 + "xmlns:db='jabber:server:dialback' " 733 862 + "xmlns='jabber:server' " 734 + "to=' example.org'>")735 + 736 + self.assertEqual s(3, len(self.output))863 + "to='xmpp.example.com'>") 864 + 865 + self.assertEqual(3, len(self.output)) 737 866 + exc = error.exceptionFromStreamError(self.output[1]) 738 + self.assertEqual s('invalid-namespace', exc.condition)867 + self.assertEqual('invalid-namespace', exc.condition) 739 868 + 740 869 + … … 748 877 + "xmlns:db='jabber:server:dialback' " 749 878 + "xmlns='badns' " 750 + "to=' example.org'>")751 + 752 + self.assertEqual s(3, len(self.output))879 + "to='xmpp.example.com'>") 880 + 881 + self.assertEqual(3, len(self.output)) 753 882 + exc = error.exceptionFromStreamError(self.output[1]) 754 + self.assertEqual s('invalid-namespace', exc.condition)883 + self.assertEqual('invalid-namespace', exc.condition) 755 884 + 756 885 + … … 763 892 + "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' " 764 893 + "xmlns='jabber:server' " 765 + "to=' example.org'>")766 + 767 + self.assertEqual s(3, len(self.output))894 + "to='xmpp.example.com'>") 895 + 896 + self.assertEqual(3, len(self.output)) 768 897 + exc = error.exceptionFromStreamError(self.output[1]) 769 + self.assertEqual s('invalid-namespace', exc.condition)898 + self.assertEqual('invalid-namespace', exc.condition) 770 899 + 771 900 + … … 779 908 + "xmlns:db='badns' " 780 909 + "xmlns='jabber:server' " 781 + "to=' example.org'>")782 + 783 + self.assertEqual s(3, len(self.output))910 + "to='xmpp.example.com'>") 911 + 912 + self.assertEqual(3, len(self.output)) 784 913 + exc = error.exceptionFromStreamError(self.output[1]) 785 + self.assertEqual s('invalid-namespace', exc.condition)914 + self.assertEqual('invalid-namespace', exc.condition) 786 915 + 787 916 + … … 797 926 + "to='badhost'>") 798 927 + 799 + self.assertEqual s(3, len(self.output))928 + self.assertEqual(3, len(self.output)) 800 929 + exc = error.exceptionFromStreamError(self.output[1]) 801 + self.assertEquals('host-unknown', exc.condition) 930 + self.assertEqual('host-unknown', exc.condition) 931 + 932 + 933 + def test_streamToOtherLocalHost(self): 934 + """ 935 + The authenticator supports XMPP 1.0 streams. 936 + """ 937 + self.xmlstream.connectionMade() 938 + self.xmlstream.dataReceived( 939 + "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' " 940 + "xmlns:db='jabber:server:dialback' " 941 + "xmlns='jabber:server' " 942 + "to='pubsub.xmpp.example.com' " 943 + "version='1.0'>") 944 + 945 + self.assertEqual(2, len(self.output)) 946 + self.assertEqual(jid.JID('pubsub.xmpp.example.com'), 947 + self.xmlstream.thisEntity) 948 + 949 + def test_onResult(self): 950 + def cb(result): 951 + self.assertEqual(1, len(self.output)) 952 + reply = self.output[0] 953 + self.assertEqual(self.originating, reply['to']) 954 + self.assertEqual(self.receiving, reply['from']) 955 + self.assertEqual('valid', reply['type']) 956 + 957 + def validateConnection(thisHost, otherHost, sid, key): 958 + self.assertEqual(thisHost, self.receiving) 959 + self.assertEqual(otherHost, self.originating) 960 + self.assertEqual(sid, self.sid) 961 + self.assertEqual(key, self.key) 962 + return defer.succeed(None) 963 + 964 + self.xmlstream.sid = self.sid 965 + self.service.validateConnection = validateConnection 966 + 967 + result = domish.Element((NS_DIALBACK, 'result')) 968 + result['to'] = self.receiving 969 + result['from'] = self.originating 970 + result.addContent(self.key) 971 + 972 + d = self.authenticator.onResult(result) 973 + d.addCallback(cb) 974 + return d 975 + 976 + 977 + def test_onResultFailure(self): 978 + class TestError(Exception): 979 + pass 980 + 981 + def cb(result): 982 + reply = self.output[0] 983 + self.assertEqual('invalid', reply['type']) 984 + self.assertEqual(1, len(self.flushLoggedErrors(TestError))) 985 + 986 + 987 + def validateConnection(thisHost, otherHost, sid, key): 988 + return defer.fail(TestError()) 989 + 990 + self.xmlstream.sid = self.sid 991 + self.service.validateConnection = validateConnection 992 + 993 + result = domish.Element((NS_DIALBACK, 'result')) 994 + result['to'] = self.receiving 995 + result['from'] = self.originating 996 + result.addContent(self.key) 997 + 998 + d = self.authenticator.onResult(result) 999 + d.addCallback(cb) 1000 + return d 1001 + 1002 + 1003 + 1004 +class FakeService(object): 1005 + domains = set(['example.org', 'pubsub.example.org']) 1006 + defaultDomain = 'example.org' 1007 + secret = 'mysecret' 1008 + 1009 + def __init__(self): 1010 + self.dispatched = [] 1011 + 1012 + def dispatch(self, element): 1013 + self.dispatch.append(element) 1014 + 1015 + 1016 + 1017 +class XMPPS2SServerFactoryTest(unittest.TestCase): 1018 + """ 1019 + Tests for L{component.XMPPS2SServerFactory}. 1020 + """ 1021 + 1022 + def setUp(self): 1023 + self.service = FakeService 1024 + self.factory = server.XMPPS2SServerFactory(self.service) 1025 + self.xmlstream = self.factory.buildProtocol(None) 1026 + self.xmlstream.thisEntity = jid.JID('example.org') 1027 + self.xmlstream.otherEntity = jid.JID('example.com') 1028 + 1029 + 1030 + def test_makeConnection(self): 1031 + """ 1032 + A new connection increases the stream serial count. No logs by default. 1033 + """ 1034 + self.xmlstream.dispatch(self.xmlstream, 1035 + xmlstream.STREAM_CONNECTED_EVENT) 1036 + self.assertEqual(0, self.xmlstream.serial) 1037 + self.assertEqual(1, self.factory.serial) 1038 + self.assertIdentical(None, self.xmlstream.rawDataInFn) 1039 + self.assertIdentical(None, self.xmlstream.rawDataOutFn) 1040 + 1041 + 1042 + def test_makeConnectionLogTraffic(self): 1043 + """ 1044 + Setting logTraffic should set up raw data loggers. 1045 + """ 1046 + self.factory.logTraffic = True 1047 + self.xmlstream.dispatch(self.xmlstream, 1048 + xmlstream.STREAM_CONNECTED_EVENT) 1049 + self.assertNotIdentical(None, self.xmlstream.rawDataInFn) 1050 + self.assertNotIdentical(None, self.xmlstream.rawDataOutFn) 1051 + 1052 + 1053 + def test_onError(self): 1054 + """ 1055 + An observer for stream errors should trigger onError to log it. 1056 + """ 1057 + self.xmlstream.dispatch(self.xmlstream, 1058 + xmlstream.STREAM_CONNECTED_EVENT) 1059 + 1060 + class TestError(Exception): 1061 + pass 1062 + 1063 + reason = failure.Failure(TestError()) 1064 + self.xmlstream.dispatch(reason, xmlstream.STREAM_ERROR_EVENT) 1065 + self.assertEqual(1, len(self.flushLoggedErrors(TestError))) 1066 + 1067 + 1068 + def test_connectionInitialized(self): 1069 + """ 1070 + """ 1071 + self.xmlstream.dispatch(self.xmlstream, 1072 + xmlstream.STREAM_CONNECTED_EVENT) 1073 + self.xmlstream.dispatch(self.xmlstream, xmlstream.STREAM_AUTHD_EVENT) 1074 + 1075 + 1076 + def test_connectionLost(self): 1077 + """ 1078 + """ 1079 + self.xmlstream.dispatch(self.xmlstream, 1080 + xmlstream.STREAM_CONNECTED_EVENT) 1081 + self.xmlstream.dispatch(self.xmlstream, xmlstream.STREAM_AUTHD_EVENT) 1082 + self.xmlstream.dispatch(None, xmlstream.STREAM_END_EVENT) 1083 + 1084 + 1085 + def test_ElementNotAuthenticated(self): 1086 + self.xmlstream.dispatch(self.xmlstream, 1087 + xmlstream.STREAM_CONNECTED_EVENT) 1088 + self.xmlstream.dataReceived("<presence/>") 1089 + 1090 + 1091 +class ServerServiceTest(unittest.TestCase): 1092 + 1093 + def setUp(self): 1094 + self.router = component.Router() 1095 + self.service = server.ServerService(self.router, 1096 + secret='mysecret', 1097 + domain='example.org') 1098 + 1099 + 1100 + def test_defaultDomainInDomains(self): 1101 + """ 1102 + The default domain is part of the domains considered local. 1103 + """ 1104 + self.assertIn(self.service.defaultDomain, self.service.domains) -
series
r6 r7 1 pubsub-disco-info-42.patch 2 compat-pre-twisted-8.0.0.patch 3 release-0.5.patch 1 4 component_multiple.patch 2 5 deferred_xmlstream_factory.patch … … 6 9 pubsub_client_sender.patch 7 10 pubsub_resource.patch 8 compat-pre-twisted-8.0.0.patch9 release-0.5.patch
Note: See TracChangeset
for help on using the changeset viewer.