[CalendarServer-changes] [2906] CalendarServer/trunk

source_changes at macosforge.org source_changes at macosforge.org
Thu Aug 28 21:39:45 PDT 2008


Revision: 2906
          http://trac.macosforge.org/projects/calendarserver/changeset/2906
Author:   sagen at apple.com
Date:     2008-08-28 21:39:43 -0700 (Thu, 28 Aug 2008)
Log Message:
-----------
Fix for <rdar://problem/6166330> Calendar server should periodically publish a heartbeat node to let clients know notifications are in fact working

Modified Paths:
--------------
    CalendarServer/trunk/conf/caldavd-test.plist
    CalendarServer/trunk/conf/caldavd.plist
    CalendarServer/trunk/twistedcaldav/config.py
    CalendarServer/trunk/twistedcaldav/customxml.py
    CalendarServer/trunk/twistedcaldav/notify.py
    CalendarServer/trunk/twistedcaldav/static.py
    CalendarServer/trunk/twistedcaldav/test/test_notify.py

Modified: CalendarServer/trunk/conf/caldavd-test.plist
===================================================================
--- CalendarServer/trunk/conf/caldavd-test.plist	2008-08-29 02:43:07 UTC (rev 2905)
+++ CalendarServer/trunk/conf/caldavd-test.plist	2008-08-29 04:39:43 UTC (rev 2906)
@@ -526,6 +526,10 @@
         <key>KeepAliveSeconds</key>
         <integer>120</integer>
 
+        <!-- Sends a pubsub publish to a particular heartbeat node at this interval -->
+        <key>HeartbeatSeconds</key>
+        <integer>1800</integer>
+
         <!-- List of glob-like expressions defining which XMPP JIDs can converse with the server -->
         <key>AllowedJIDs</key>
         <array>

Modified: CalendarServer/trunk/conf/caldavd.plist
===================================================================
--- CalendarServer/trunk/conf/caldavd.plist	2008-08-29 02:43:07 UTC (rev 2905)
+++ CalendarServer/trunk/conf/caldavd.plist	2008-08-29 04:39:43 UTC (rev 2906)
@@ -318,6 +318,10 @@
         <!-- Sends a presence notification to XMPP server at this interval (prevents disconnect) -->
         <key>KeepAliveSeconds</key>
         <integer>120</integer>
+
+        <!-- Sends a pubsub publish to a particular heartbeat node at this interval -->
+        <key>HeartbeatSeconds</key>
+        <integer>1800</integer>
       </dict>
     </array>
   </dict>

Modified: CalendarServer/trunk/twistedcaldav/config.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/config.py	2008-08-29 02:43:07 UTC (rev 2905)
+++ CalendarServer/trunk/twistedcaldav/config.py	2008-08-29 04:39:43 UTC (rev 2906)
@@ -242,6 +242,7 @@
                 "Password" : "",
                 "ServiceAddress" : "", # "pubsub.xmpp.host.name"
                 "KeepAliveSeconds" : 120,
+                "HeartbeatSeconds" : 1800, # 30 minute pubsub heartbeat
                 "AllowedJIDs": [],
             },
         ]

Modified: CalendarServer/trunk/twistedcaldav/customxml.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/customxml.py	2008-08-29 02:43:07 UTC (rev 2905)
+++ CalendarServer/trunk/twistedcaldav/customxml.py	2008-08-29 04:39:43 UTC (rev 2906)
@@ -253,6 +253,15 @@
     name = "xmpp-uri"
     protected = True
 
+class PubSubHeartbeatURIProperty (davxml.WebDAVTextElement):
+    """
+    A calendarhomefile property to indicate the pubsub XMPP URI to subscribe to
+    for server heartbeats.
+    """
+    namespace = calendarserver_namespace
+    name = "xmpp-heartbeat-uri"
+    protected = True
+
 class IScheduleInbox (davxml.WebDAVEmptyElement):
     """
     Denotes the resourcetype of a iSchedule Inbox.
@@ -269,6 +278,7 @@
     namespace = calendarserver_namespace
     name = "free-busy-url"
 
+
 ##
 # Extensions to davxml.ResourceType
 ##

Modified: CalendarServer/trunk/twistedcaldav/notify.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/notify.py	2008-08-29 02:43:07 UTC (rev 2905)
+++ CalendarServer/trunk/twistedcaldav/notify.py	2008-08-29 04:39:43 UTC (rev 2906)
@@ -34,7 +34,6 @@
 
 # TODO: bindAddress to local
 # TODO: add CalDAVTester test for examining new xmpp-uri property
-# TODO: auto-registration and roster management for XMPP
 
 from twisted.internet import protocol
 from twisted.protocols import basic
@@ -55,6 +54,7 @@
     "Coalescer",
     "getNotificationClient",
     "getPubSubConfiguration",
+    "getPubSubHeartbeatURI",
     "getPubSubPath",
     "getPubSubXMPPURI",
     "INotifier",
@@ -488,16 +488,25 @@
         'pubsub#persist_items'   : '0',
     }
 
-    def __init__(self, settings, reactor=None, configOverride=None):
+    def __init__(self, settings, reactor=None, configOverride=None,
+        heartbeat=True, roster=True):
         self.xmlStream = None
         self.settings = settings
         if reactor is None:
             from twisted.internet import reactor
         self.reactor = reactor
         self.config = configOverride or config
+        self.doHeartbeat = heartbeat
+        self.doRoster = roster
 
         self.roster = {}
 
+    def sendHeartbeat(self):
+        if self.doHeartbeat and self.xmlStream is not None:
+            self.enqueue("")
+            self.reactor.callLater(self.settings['HeartbeatSeconds'],
+                self.sendHeartbeat)
+
     def enqueue(self, uri):
         if self.xmlStream is not None:
             # Convert uri to node
@@ -634,11 +643,12 @@
 
 
     def requestRoster(self):
-        self.roster = {}
-        rosterIq = IQ(self.xmlStream, type='get')
-        rosterIq.addElement("query", "jabber:iq:roster")
-        rosterIq.addCallback(self.handleRoster)
-        rosterIq.send()
+        if self.doRoster:
+            self.roster = {}
+            rosterIq = IQ(self.xmlStream, type='get')
+            rosterIq.addElement("query", "jabber:iq:roster")
+            rosterIq.addCallback(self.handleRoster)
+            rosterIq.send()
 
     def allowedInRoster(self, jid):
         for pattern in self.settings.get("AllowedJIDs", []):
@@ -720,6 +730,7 @@
         xmlStream.addObserver('/message', self.handleMessage)
         xmlStream.addObserver('/presence', self.handlePresence)
         self.requestRoster()
+        self.sendHeartbeat()
 
 
     def streamClosed(self):
@@ -789,7 +800,7 @@
 
 class XMPPNotificationFactory(xmlstream.XmlStreamFactory, LoggingMixIn):
 
-    def __init__(self, notifier, settings, reactor=None):
+    def __init__(self, notifier, settings, reactor=None, keepAlive=True):
         self.log_info("Setting up XMPPNotificationFactory")
 
         self.notifier = notifier
@@ -798,6 +809,7 @@
         self.keepAliveSeconds = settings.get('KeepAliveSeconds', 120)
         self.xmlStream = None
         self.presenceCall = None
+        self.doKeepAlive = keepAlive
         if reactor is None:
             from twisted.internet import reactor
         self.reactor = reactor
@@ -845,7 +857,7 @@
             (self.jid,))
 
     def sendPresence(self):
-        if self.xmlStream is not None:
+        if self.doKeepAlive and self.xmlStream is not None:
             presence = domish.Element(('jabber:client', 'presence'))
             self.xmlStream.send(presence)
             self.presenceCall = self.reactor.callLater(self.keepAliveSeconds,
@@ -876,13 +888,20 @@
     return results
 
 def getPubSubPath(uri, pubSubConfiguration):
-    return ("/Public/CalDAV/%s/%d/%s/" % (pubSubConfiguration['host'],
-        pubSubConfiguration['port'], uri.strip("/")))
+    path = "/Public/CalDAV/%s/%d/" % (pubSubConfiguration['host'],
+        pubSubConfiguration['port'])
+    if uri:
+        path += "%s/" % (uri.strip("/"),)
+    return path
 
 def getPubSubXMPPURI(uri, pubSubConfiguration):
     return "xmpp:%s?pubsub;node=%s" % (pubSubConfiguration['service'],
         getPubSubPath(uri, pubSubConfiguration))
 
+def getPubSubHeartbeatURI(pubSubConfiguration):
+    return "xmpp:%s?pubsub;node=%s" % (pubSubConfiguration['service'],
+        getPubSubPath("", pubSubConfiguration))
+
 #
 # Notification Server service config
 #

Modified: CalendarServer/trunk/twistedcaldav/static.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/static.py	2008-08-29 02:43:07 UTC (rev 2905)
+++ CalendarServer/trunk/twistedcaldav/static.py	2008-08-29 04:39:43 UTC (rev 2906)
@@ -75,6 +75,7 @@
 from twistedcaldav.timezoneservice import TimezoneServiceResource
 from twistedcaldav.cache import DisabledCacheNotifier, PropfindCacheMixin
 from twistedcaldav.notify import getPubSubConfiguration, getPubSubXMPPURI
+from twistedcaldav.notify import getPubSubHeartbeatURI
 
 log = Logger()
 
@@ -598,6 +599,7 @@
 
     liveProperties = CalDAVFile.liveProperties + (
         (customxml.calendarserver_namespace, "xmpp-uri"),
+        (customxml.calendarserver_namespace, "xmpp-heartbeat-uri"),
     )
 
     def __init__(self, path, parent, record):
@@ -663,6 +665,14 @@
             else:
                 return succeed(customxml.PubSubXMPPURIProperty())
 
+        elif qname == (customxml.calendarserver_namespace, "xmpp-heartbeat-uri"):
+            pubSubConfiguration = getPubSubConfiguration(config)
+            if pubSubConfiguration['enabled']:
+                return succeed(customxml.PubSubHeartbeatURIProperty(
+                    getPubSubHeartbeatURI(pubSubConfiguration)))
+            else:
+                return succeed(customxml.PubSubHeartbeatURIProperty())
+
         return super(CalendarHomeFile, self).readProperty(property, request)
 
 

Modified: CalendarServer/trunk/twistedcaldav/test/test_notify.py
===================================================================
--- CalendarServer/trunk/twistedcaldav/test/test_notify.py	2008-08-29 02:43:07 UTC (rev 2905)
+++ CalendarServer/trunk/twistedcaldav/test/test_notify.py	2008-08-29 04:39:43 UTC (rev 2906)
@@ -335,7 +335,7 @@
         self.xmlStream = StubXmlStream()
         self.settings = { 'ServiceAddress' : 'pubsub.example.com' }
         self.notifier = XMPPNotifier(self.settings, reactor=Clock(),
-            configOverride=self.xmppEnabledConfig)
+            configOverride=self.xmppEnabledConfig, heartbeat=False)
         self.notifier.streamOpened(self.xmlStream)
 
     def test_sendWhileConnected(self):
@@ -456,7 +456,41 @@
                     str(valueElement))
 
 
+    def test_sendHeartbeat(self):
 
+        xmppConfig = Config(config_mod.defaultConfig)
+        xmppConfig.Notifications['Services'][1]['Enabled'] = True
+        xmppConfig.ServerHostName = "server.example.com"
+        xmppConfig.HTTPPort = 80
+
+        clock = Clock()
+        xmlStream = StubXmlStream()
+        settings = { 'ServiceAddress' : 'pubsub.example.com', 'JID' : 'jid',
+            'Password' : 'password', 'KeepAliveSeconds' : 5,
+            'HeartbeatSeconds' : 1800 }
+        notifier = XMPPNotifier(settings, reactor=clock, heartbeat=True,
+            roster=False, configOverride=xmppConfig)
+        factory = XMPPNotificationFactory(notifier, settings, reactor=clock,
+            keepAlive=False)
+        factory.connected(xmlStream)
+        factory.authenticated(xmlStream)
+
+        self.assertEquals(len(xmlStream.elements), 1)
+        heartbeat = xmlStream.elements[0]
+        self.assertEquals(heartbeat.name, 'iq')
+
+        clock.advance(1800)
+
+        self.assertEquals(len(xmlStream.elements), 2)
+        heartbeat = xmlStream.elements[1]
+        self.assertEquals(heartbeat.name, 'iq')
+
+        factory.disconnected(xmlStream)
+        clock.advance(1800)
+        self.assertEquals(len(xmlStream.elements), 2)
+
+
+
 class XMPPNotificationFactoryTests(TestCase):
 
     def test_sendPresence(self):
@@ -464,7 +498,7 @@
         xmlStream = StubXmlStream()
         settings = { 'ServiceAddress' : 'pubsub.example.com', 'JID' : 'jid',
             'Password' : 'password', 'KeepAliveSeconds' : 5 }
-        notifier = XMPPNotifier(settings, reactor=clock)
+        notifier = XMPPNotifier(settings, reactor=clock, heartbeat=False)
         factory = XMPPNotificationFactory(notifier, settings, reactor=clock)
         factory.connected(xmlStream)
         factory.authenticated(xmlStream)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20080828/52371dcf/attachment-0001.html 


More information about the calendarserver-changes mailing list