示例#1
0
def updateApplication(app, config):
    profileTable=McFoo.score.ProfileTable()
    filler=McFoo.suggest.Suggestions(config.songdirs, profileTable)
    playqueue = McFoo.playqueue.PlayQueue(filler.get)

    volume = McFoo.volume.VolumeControl()
    auth = DefaultAuthorizer()
    auth.setApplication(app)
    dj=McFoo.dj.Dj(app, auth,
                   playqueue, volume, profileTable)

    perspective=dj.getPerspectiveNamed("guest")
    perspective.setService(dj)
    perspective.makeIdentity("guest")

    portno = config.port
    prot = pb.BrokerFactory(pb.AuthRoot(auth))

    app.listenTCP(portno, prot)
    SaveService("save", app, auth)
示例#2
0
class Application(log.Logger, styles.Versioned,
                  Accessor, _AbstractServiceCollection):
    """I am the `root object' in a Twisted process.
    I represent a set of persistent, potentially interconnected listening TCP
    ports, delayed event schedulers, and service.Services.
    """
    running = 0
    processName = None
    def __init__(self, name, uid=None, gid=None, authorizer=None, authorizer_=None):
        """Initialize me.
        If uid and gid arguments are not provided, this application will
        default to having the uid and gid of the user and group who created it.
        @param name: a name
        @param uid: (optional) a POSIX user-id.  Only used on POSIX systems.
        @param gid: (optional) a POSIX group-id.  Only used on POSIX systems.
        """
        _AbstractServiceCollection.__init__(self)
        self.name = name
        self.tcpPorts = []              # check
        self.udpPorts = []
        self.sslPorts = []
        self.unixPorts = []
        self.extraPorts = []
        self._listenerDict = {}
        self._extraListeners = {}
        self.tcpConnectors = []
        self.udpConnectors = []
        self.sslConnectors = []
        self.unixConnectors = []
        self.extraConnectors = []
        self.services = {}              # check
        a = authorizer or authorizer_
        if a:
            self._authorizer = a
            self._authorizer.setServiceCollection(self)
        if platform.getType() == "posix":
            if uid is None:
                uid = os.getuid()
            self.uid = uid
            if gid is None:
                gid = os.getgid()
            self.gid = gid
    persistenceVersion = 12
    _authorizer = None
    def get_authorizer(self):
        warnings.warn("Application.authorizer attribute is deprecated, use Service.authorizer instead",
                      category=DeprecationWarning, stacklevel=3)
        if not self._authorizer:
            self._authorizer = DefaultAuthorizer()
            self._authorizer.setApplication(self)
        return self._authorizer
    def upgradeToVersion12(self):
        up = []
        for port, factory, backlog in self.unixPorts:
            up.append((port, factory, backlog, 0666))
        self.unixPorts = up
    def upgradeToVersion11(self):
        self._extraListeners = {}
        self.extraPorts = []
        self.extraConnectors = []
        self.unixPorts = []
        self.udpConnectors = []
        toRemove = []
        for t in self.tcpPorts:
            port, factory, backlog, interface = t
            if isinstance(port, types.StringTypes):
                self.unixPorts.append((port, factory, backlog))
                toRemove.append(t)
        for t in toRemove:
            self.tcpPorts.remove(t)
    def upgradeToVersion10(self):
        pass
    def upgradeToVersion9(self):
        self._authorizer = self.authorizer
        del self.authorizer
        self.tcpConnectors = self.connectors
        del self.connectors
        self.sslConnectors = []
        self.unixConnectors = []
    def upgradeToVersion8(self):
        self.persistStyle = "pickle"
        if hasattr(self, 'asXML'):
            if self.asXML:
                self.persistStyle = "xml"
            del self.asXML
    def upgradeToVersion7(self):
        self.tcpPorts = []
        self.udpPorts = []
        self.sslPorts = []
        from twisted.internet import tcp, udp
        for port in self.ports:
            if isinstance(port, tcp.Port):
                self.tcpPorts.append(
                    (port.port, port.factory,
                     port.backlog, port.interface))
            elif isinstance(port, udp.Port):
                self.udpPorts.append(
                    port.port, port.factory,
                    port.interface, port.maxPacketSize)
            else:
                log.msg('upgrade of %s not implemented, sorry' % port.__class__)
        del self.ports
    def upgradeToVersion6(self):
        del self.resolver
    def upgradeToVersion5(self):
        if hasattr(self, "entities"):
            del self.entities
    def upgradeToVersion4(self):
        """Version 4 Persistence Upgrade
        """
    def upgradeToVersion3(self):
        """Version 3 Persistence Upgrade
        """
        pass
    def upgradeToVersion2(self):
        """Version 2 Persistence Upgrade
        """
        self.resolver = None # will be deleted in upgrade to v6
    def upgradeToVersion1(self):
        """Version 1 Persistence Upgrade
        """
        log.msg("Upgrading %s Application." % repr(self.name))
        self.authorizer = DefaultAuthorizer()
        self.services = {}
    def __repr__(self):
        return "<%s app>" % repr(self.name)
    def __getstate__(self):
        dict = styles.Versioned.__getstate__(self)
        if dict.has_key("running"):
            del dict['running']
        if dict.has_key("_boundPorts"):
            del dict['_boundPorts']
        if dict.has_key("_listenerDict"):
            del dict['_listenerDict']
        if dict.has_key("_extraListeners"):
            del dict["_extraListeners"]
        return dict
    def listenWith(self, portType, *args, **kw):
        """
        Start an instance of the given C{portType} listening.
        @type portType: type which implements C{IListeningPort}
        """
        self.extraPorts.append((portType, args, kw))
        if self.running:
            from twisted.internet import reactor
            p = reactor.listenWith(portType, *args, **kw)
            self._extraListeners[(portType, args, kw)] = p
            return p
    def unlistenWith(self, portType, *args, **kw):
        """
        Stop a Port listening with the given parameters.
        """
        toRemove = []
        for t in self.extraPorts:
            _portType, _args, _kw = t
            if portType == _portType:
                if args == _args[:len(args)]:
                    for (k, v) in kw.items():
                        if _kw.has_key(k) and _kw[k] != v:
                            break
                    else:
                        toRemove.append(t)
        if toRemove:
            for t in toRemove:
                self.extraPorts.remove(t)
                if self._extraListeners.has_key(t):
                    self._extraListeners[t].stopListening()
                    del self._extraListeners[t]
        else:
            raise error.NotListeningError, (portType, args, kw)
    def listenTCP(self, port, factory, backlog=50, interface=''):
        """
        Connects a given protocol factory to the given numeric TCP/IP port.
        """
        self.tcpPorts.append((port, factory, backlog, interface))
        if self.running:
            from twisted.internet import reactor
            return reactor.listenTCP(port, factory, backlog, interface)
    def unlistenTCP(self, port, interface=''):
        """
        Stop a Port listening on the given port and interface.
        """
        toRemove = []
        for t in self.tcpPorts:
            port_, factory_, backlog_, interface_ = t
            if port == port_ and interface == interface_:
                toRemove.append(t)
        if toRemove:
            for t in toRemove:
                self.tcpPorts.remove(t)
            if self._listenerDict.has_key((port, interface)):
                self._listenerDict[(port, interface)].stopListening()
        else:
            raise error.NotListeningError, (interface, port)
    def listenUNIX(self, filename, factory, backlog=50, mode=0666):
        """
        Connects a given protocol factory to the UNIX socket with the given filename.
        """
        self.unixPorts.append((filename, factory, backlog, mode))
        if self.running:
            from twisted.internet import reactor
            return reactor.listenUNIX(filename, factory, backlog, mode)
    def unlistenUNIX(self, filename):
        """
        Stop a Port listening on the given filename.
        """
        toRemove = []
        for t in self.unixPorts:
            filename_, factory_, backlog_, mode_ = t
            if filename == filename_:
                toRemove.append(t)
        if toRemove:
            for t in toRemove:
                self.unixPorts.remove(t)
            if self._listenerDict.has_key(filename):
                self._listenerDict[filename].stopListening()
        else:
            raise error.NotListeningError, filename
    def listenUDP(self, port, proto, interface='', maxPacketSize=8192):
        """
        Connects a given DatagramProtocol to the given numeric UDP port.
        """
        self.udpPorts.append((port, proto, interface, maxPacketSize))
        if self.running:
            from twisted.internet import reactor
            return reactor.listenUDP(port, proto, interface, maxPacketSize)
    def unlistenUDP(self, port, interface=''):
        """
        Stop a DatagramProtocol listening on the given local port and
        interface.
        """
        toRemove = []
        for t in self.udpPorts:
            port_, factory_, interface_, size_ = t
            if port_ == port and interface_ == interface:
                toRemove.append(t)
        if toRemove:
            for t in toRemove:
                self.udpPorts.remove(t)
        else:
            raise error.NotListeningError, (interface, port)
    def listenSSL(self, port, factory, ctxFactory, backlog=50, interface=''):
        """
        Connects a given protocol factory to the given numeric TCP/IP port.
        The connection is a SSL one, using contexts created by the context
        factory.
        """
        self.sslPorts.append((port, factory, ctxFactory, backlog, interface))
        if self.running:
            from twisted.internet import reactor
            return reactor.listenSSL(port, factory, ctxFactory, backlog, interface)
    def unlistenSSL(self, port, interface=''):
        """
        Stop an SSL Port listening on the given interface and port.
        """
        toRemove = []
        for t in self.sslPorts:
            port_, factory_, ctx_, back_, interface_ = t
            if port_ == port and interface_ == interface:
                toRemove.append(t)
        if toRemove:
            for t in toRemove:
                self.sslPorts.remove(t)
        else:
            raise error.NotListeningError, (interface, port)
    def connectWith(self, connectorType, *args, **kw):
        """
        Start an instance of the given C{connectorType} connecting.
        @type connectorType: type which implements C{IConnector}
        """
        self.extraConnectors.append((connectorType, args, kw))
        if self.running:
            from twisted.internet import reactor
            return reactor.connectWith(connectorType, *args, **kw)
    def connectUDP(self, remotehost, remoteport, protocol, localport=0,
                  interface='', maxPacketSize=8192):
        """Connects a L{ConnectedDatagramProtocol} instance to a UDP port."""
        self.udpConnectors.append((
            remotehost, remoteport, protocol,
            localport, interface, maxPacketSize
        ))
        if self.running:
            from twisted.internet import reactor
            return reactor.connectUDP(
                remotehost, remoteport, protocol,
                localport, interface, maxPacketSize
            )
    def connectTCP(self, host, port, factory, timeout=30, bindAddress=None):
        """Connect a given client protocol factory to a specific TCP server."""
        self.tcpConnectors.append((host, port, factory, timeout, bindAddress))
        if self.running:
            from twisted.internet import reactor
            return reactor.connectTCP(host, port, factory, timeout, bindAddress)
    def connectSSL(self, host, port, factory, ctxFactory, timeout=30, bindAddress=None):
        """Connect a given client protocol factory to a specific SSL server."""
        self.sslConnectors.append((host, port, factory, ctxFactory, timeout, bindAddress))
        if self.running:
            from twisted.internet import reactor
            return reactor.connectSSL(host, port, factory, ctxFactory, timeout, bindAddress)
    def connectUNIX(self, address, factory, timeout=30):
        """Connect a given client protocol factory to a specific UNIX socket."""
        self.unixConnectors.append((address, factory, timeout))
        if self.running:
            from twisted.internet import reactor
            return reactor.connectUNIX(address, factory, timeout)
    def setEUID(self):
        """Retrieve persistent uid/gid pair (if possible) and set the current
        process's euid/egid.
        """
        try:
            os.setegid(self.gid)
            os.seteuid(self.uid)
        except (AttributeError, OSError):
            pass
        else:
            log.msg('set euid/egid %s/%s' % (self.uid, self.gid))
    def setUID(self):
        """Retrieve persistent uid/gid pair (if possible) and set the current process's uid/gid
        """
        try:
            os.setgid(self.gid)
            os.setuid(self.uid)
        except (AttributeError, OSError):
            pass
        else:
            log.msg('set uid/gid %s/%s' % (self.uid, self.gid))
    persistStyle = "pickle"
    def save(self, tag=None, filename=None, passphrase=None):
        """Save a pickle of this application to a file in the current directory.
        """
        if self.persistStyle == "xml":
            from twisted.persisted.marmalade import jellyToXML
            dumpFunc = jellyToXML
            ext = "tax"
        elif self.persistStyle == "aot":
            from twisted.persisted.aot import jellyToSource
            dumpFunc = jellyToSource
            ext = "tas"
        else:
            def dumpFunc(obj, file, _dump=pickle.dump):
                _dump(obj, file, 1)
            ext = "tap"
        if filename:
            finalname = filename
            filename = finalname + "-2"
        else:
            if passphrase:
                ext = 'e' + ext
            if tag:
                filename = "%s-%s-2.%s" % (self.name, tag, ext)
                finalname = "%s-%s.%s" % (self.name, tag, ext)
            else:
                filename = "%s-2.%s" % (self.name, ext)
                finalname = "%s.%s" % (self.name, ext)
        log.msg("Saving "+self.name+" application to "+finalname+"...")
        if passphrase is None:
            f = open(filename, 'wb')
            dumpFunc(self, f)
            f.flush()
            f.close()
        else:
            f = StringIO.StringIO()
            dumpFunc(self, f)
            s = encrypt(passphrase, f.getvalue())
            f = open(filename, 'wb')
            f.write(s)
            f.flush()
            f.close()
        if platform.getType() == "win32":
            if os.path.isfile(finalname):
                os.remove(finalname)
        os.rename(filename, finalname)
        log.msg("Saved.")
    def logPrefix(self):
        """A log prefix which describes me.
        """
        return "*%s*" % self.name
    def _beforeShutDown(self):
        l = []
        services = self.services.values()
        for service in services:
            try:
                d = service.stopService()
                if isinstance(d, defer.Deferred):
                    l.append(d)
            except:
                log.deferr()
        if l:
            return defer.DeferredList(l)
    def _afterShutDown(self):
        if self._save:
            self.save("shutdown")
    _boundPorts = 0
    def bindPorts(self):
        log.callWithLogger(self, self._doBindPorts)
    def _doBindPorts(self):
        from twisted.internet import reactor
        self._listenerDict= {}
        self._boundPorts = 1
        if not self.running:
            for filename, factory, backlog, mode in self.unixPorts:
                try:
                    self._listenerDict[filename] = reactor.listenUNIX(filename, factory, backlog, mode)
                except error.CannotListenError, msg:
                    log.msg('error on UNIX socket %s: %s' % (filename, msg))
                    return
            for port, factory, backlog, interface in self.tcpPorts:
                try:
                    self._listenerDict[port, interface] = reactor.listenTCP(port, factory, backlog, interface)
                except error.CannotListenError, msg:
                    log.msg('error on TCP port %s: %s' % (port, msg))
                    return
            for port, factory, interface, maxPacketSize in self.udpPorts:
                try:
                    reactor.listenUDP(port, factory, interface, maxPacketSize)
                except error.CannotListenError, msg:
                    log.msg('error on UDP port %s: %s' % (port, msg))
                    return
示例#3
0
class Application(log.Logger, styles.Versioned, Accessor,
                  _AbstractServiceCollection):
    """I am the `root object' in a Twisted process.

    I represent a set of persistent, potentially interconnected listening TCP
    ports, delayed event schedulers, and service.Services.
    """

    running = 0
    processName = None

    #
    # XXX
    #
    # The profusion of xyzPorts, xyzListeners, _listenerDict, and
    # _extraListeners has long since passed the point of excess.
    # Someone who feels like taking the time should merge all of these
    # into a set of "universal" trackers.  One for ports, one for listeners,
    # one for things that are -actually- listening and connecting.
    # This requires another version bump and an upgrade function, of course.
    #

    def __init__(self,
                 name,
                 uid=None,
                 gid=None,
                 authorizer=None,
                 authorizer_=None):
        """Initialize me.

        If uid and gid arguments are not provided, this application will
        default to having the uid and gid of the user and group who created it.

        @param name: a name

        @param uid: (optional) a POSIX user-id.  Only used on POSIX systems.

        @param gid: (optional) a POSIX group-id.  Only used on POSIX systems.
        """
        _AbstractServiceCollection.__init__(self)
        self.name = name
        # a list of (tcp, ssl, udp) Ports
        self.tcpPorts = []  # check
        self.udpPorts = []
        self.sslPorts = []
        self.unixPorts = []
        self.extraPorts = []
        self._listenerDict = {}
        self._extraListeners = {}
        # a list of (tcp, ssl, udp) Connectors
        self.tcpConnectors = []
        self.udpConnectors = []
        self.sslConnectors = []
        self.unixConnectors = []
        self.extraConnectors = []
        # a dict of ApplicationServices
        self.services = {}  # check
        # a cred authorizer
        a = authorizer or authorizer_
        if a:
            self._authorizer = a
            self._authorizer.setServiceCollection(self)
        if platform.getType() == "posix":
            if uid is None:
                uid = os.getuid()
            self.uid = uid
            if gid is None:
                gid = os.getgid()
            self.gid = gid

    persistenceVersion = 12

    _authorizer = None

    def get_authorizer(self):
        warnings.warn(
            "Application.authorizer attribute is deprecated, use Service.authorizer instead",
            category=DeprecationWarning,
            stacklevel=3)
        if not self._authorizer:
            self._authorizer = DefaultAuthorizer()
            self._authorizer.setApplication(self)
        return self._authorizer

    def upgradeToVersion12(self):
        up = []
        for port, factory, backlog in self.unixPorts:
            up.append((port, factory, backlog, 0666))
        self.unixPorts = up

    def upgradeToVersion11(self):
        self._extraListeners = {}
        self.extraPorts = []
        self.extraConnectors = []
        self.unixPorts = []
        self.udpConnectors = []

        toRemove = []
        for t in self.tcpPorts:
            port, factory, backlog, interface = t
            if isinstance(port, types.StringTypes):
                self.unixPorts.append((port, factory, backlog))
                toRemove.append(t)
        for t in toRemove:
            self.tcpPorts.remove(t)

    def upgradeToVersion10(self):
        # persistenceVersion was 10, but this method did not exist
        # I do not know why.
        pass

    def upgradeToVersion9(self):
        self._authorizer = self.authorizer
        del self.authorizer
        self.tcpConnectors = self.connectors
        del self.connectors
        self.sslConnectors = []
        self.unixConnectors = []

    def upgradeToVersion8(self):
        self.persistStyle = "pickle"
        if hasattr(self, 'asXML'):
            if self.asXML:
                self.persistStyle = "xml"
            del self.asXML

    def upgradeToVersion7(self):
        self.tcpPorts = []
        self.udpPorts = []
        self.sslPorts = []
        from twisted.internet import tcp, udp
        for port in self.ports:
            if isinstance(port, tcp.Port):
                self.tcpPorts.append(
                    (port.port, port.factory, port.backlog, port.interface))
            elif isinstance(port, udp.Port):
                self.udpPorts.append(port.port, port.factory, port.interface,
                                     port.maxPacketSize)
            else:
                log.msg('upgrade of %s not implemented, sorry' %
                        port.__class__)
        del self.ports

    def upgradeToVersion6(self):
        del self.resolver

    def upgradeToVersion5(self):
        if hasattr(self, "entities"):
            del self.entities

    def upgradeToVersion4(self):
        """Version 4 Persistence Upgrade
        """

    def upgradeToVersion3(self):
        """Version 3 Persistence Upgrade
        """
        #roots.Locked.__init__(self)
        #self._addEntitiesAndLock()
        pass

    def upgradeToVersion2(self):
        """Version 2 Persistence Upgrade
        """
        self.resolver = None  # will be deleted in upgrade to v6

    def upgradeToVersion1(self):
        """Version 1 Persistence Upgrade
        """
        log.msg("Upgrading %s Application." % repr(self.name))
        self.authorizer = DefaultAuthorizer()
        self.services = {}

    def __repr__(self):
        return "<%s app>" % repr(self.name)

    def __getstate__(self):
        dict = styles.Versioned.__getstate__(self)
        if dict.has_key("running"):
            del dict['running']
        if dict.has_key("_boundPorts"):
            del dict['_boundPorts']
        if dict.has_key("_listenerDict"):
            del dict['_listenerDict']
        if dict.has_key("_extraListeners"):
            del dict["_extraListeners"]
        return dict

    def listenWith(self, portType, *args, **kw):
        """
        Start an instance of the given C{portType} listening.

        @type portType: type which implements C{IListeningPort}
        """
        self.extraPorts.append((portType, args, kw))
        if self.running:
            from twisted.internet import reactor
            p = reactor.listenWith(portType, *args, **kw)
            self._extraListeners[(portType, args, kw)] = p
            return p

    def unlistenWith(self, portType, *args, **kw):
        """
        Stop a Port listening with the given parameters.
        """
        toRemove = []
        for t in self.extraPorts:
            _portType, _args, _kw = t
            if portType == _portType:
                if args == _args[:len(args)]:
                    for (k, v) in kw.items():
                        if _kw.has_key(k) and _kw[k] != v:
                            break
                    else:
                        toRemove.append(t)
        if toRemove:
            for t in toRemove:
                self.extraPorts.remove(t)
                if self._extraListeners.has_key(t):
                    self._extraListeners[t].stopListening()
                    del self._extraListeners[t]
        else:
            raise error.NotListeningError, (portType, args, kw)

    def listenTCP(self, port, factory, backlog=50, interface=''):
        """
        Connects a given protocol factory to the given numeric TCP/IP port.
        """
        self.tcpPorts.append((port, factory, backlog, interface))
        if self.running:
            from twisted.internet import reactor
            return reactor.listenTCP(port, factory, backlog, interface)

    def unlistenTCP(self, port, interface=''):
        """
        Stop a Port listening on the given port and interface.
        """
        toRemove = []
        for t in self.tcpPorts:
            port_, factory_, backlog_, interface_ = t
            if port == port_ and interface == interface_:
                toRemove.append(t)
        if toRemove:
            for t in toRemove:
                self.tcpPorts.remove(t)
            if self._listenerDict.has_key((port, interface)):
                self._listenerDict[(port, interface)].stopListening()
        else:
            raise error.NotListeningError, (interface, port)

    def listenUNIX(self, filename, factory, backlog=50, mode=0666):
        """
        Connects a given protocol factory to the UNIX socket with the given filename.
        """
        self.unixPorts.append((filename, factory, backlog, mode))
        if self.running:
            from twisted.internet import reactor
            return reactor.listenUNIX(filename, factory, backlog, mode)

    def unlistenUNIX(self, filename):
        """
        Stop a Port listening on the given filename.
        """
        toRemove = []
        for t in self.unixPorts:
            filename_, factory_, backlog_, mode_ = t
            if filename == filename_:
                toRemove.append(t)
        if toRemove:
            for t in toRemove:
                self.unixPorts.remove(t)
            if self._listenerDict.has_key(filename):
                self._listenerDict[filename].stopListening()
        else:
            raise error.NotListeningError, filename

    def listenUDP(self, port, proto, interface='', maxPacketSize=8192):
        """
        Connects a given DatagramProtocol to the given numeric UDP port.
        """
        self.udpPorts.append((port, proto, interface, maxPacketSize))
        if self.running:
            from twisted.internet import reactor
            return reactor.listenUDP(port, proto, interface, maxPacketSize)

    def unlistenUDP(self, port, interface=''):
        """
        Stop a DatagramProtocol listening on the given local port and
        interface.
        """
        toRemove = []
        for t in self.udpPorts:
            port_, factory_, interface_, size_ = t
            if port_ == port and interface_ == interface:
                toRemove.append(t)
        if toRemove:
            for t in toRemove:
                self.udpPorts.remove(t)
        else:
            raise error.NotListeningError, (interface, port)

    def listenSSL(self, port, factory, ctxFactory, backlog=50, interface=''):
        """
        Connects a given protocol factory to the given numeric TCP/IP port.
        The connection is a SSL one, using contexts created by the context
        factory.
        """
        self.sslPorts.append((port, factory, ctxFactory, backlog, interface))
        if self.running:
            from twisted.internet import reactor
            return reactor.listenSSL(port, factory, ctxFactory, backlog,
                                     interface)

    def unlistenSSL(self, port, interface=''):
        """
        Stop an SSL Port listening on the given interface and port.
        """
        toRemove = []
        for t in self.sslPorts:
            port_, factory_, ctx_, back_, interface_ = t
            if port_ == port and interface_ == interface:
                toRemove.append(t)
        if toRemove:
            for t in toRemove:
                self.sslPorts.remove(t)
        else:
            raise error.NotListeningError, (interface, port)

    def connectWith(self, connectorType, *args, **kw):
        """
        Start an instance of the given C{connectorType} connecting.

        @type connectorType: type which implements C{IConnector}
        """
        self.extraConnectors.append((connectorType, args, kw))
        if self.running:
            from twisted.internet import reactor
            return reactor.connectWith(connectorType, *args, **kw)

    def connectUDP(self,
                   remotehost,
                   remoteport,
                   protocol,
                   localport=0,
                   interface='',
                   maxPacketSize=8192):
        """Connects a L{ConnectedDatagramProtocol} instance to a UDP port."""
        self.udpConnectors.append((remotehost, remoteport, protocol, localport,
                                   interface, maxPacketSize))
        if self.running:
            from twisted.internet import reactor
            return reactor.connectUDP(remotehost, remoteport, protocol,
                                      localport, interface, maxPacketSize)

    def connectTCP(self, host, port, factory, timeout=30, bindAddress=None):
        """Connect a given client protocol factory to a specific TCP server."""
        self.tcpConnectors.append((host, port, factory, timeout, bindAddress))
        if self.running:
            from twisted.internet import reactor
            return reactor.connectTCP(host, port, factory, timeout,
                                      bindAddress)

    def connectSSL(self,
                   host,
                   port,
                   factory,
                   ctxFactory,
                   timeout=30,
                   bindAddress=None):
        """Connect a given client protocol factory to a specific SSL server."""
        self.sslConnectors.append(
            (host, port, factory, ctxFactory, timeout, bindAddress))
        if self.running:
            from twisted.internet import reactor
            return reactor.connectSSL(host, port, factory, ctxFactory, timeout,
                                      bindAddress)

    def connectUNIX(self, address, factory, timeout=30):
        """Connect a given client protocol factory to a specific UNIX socket."""
        self.unixConnectors.append((address, factory, timeout))
        if self.running:
            from twisted.internet import reactor
            return reactor.connectUNIX(address, factory, timeout)

    def setEUID(self):
        """Retrieve persistent uid/gid pair (if possible) and set the current
        process's euid/egid.
        """
        try:
            os.setegid(self.gid)
            os.seteuid(self.uid)
        except (AttributeError, OSError):
            pass
        else:
            log.msg('set euid/egid %s/%s' % (self.uid, self.gid))

    def setUID(self):
        """Retrieve persistent uid/gid pair (if possible) and set the current process's uid/gid
        """
        try:
            os.setgid(self.gid)
            os.setuid(self.uid)
        except (AttributeError, OSError):
            pass
        else:
            log.msg('set uid/gid %s/%s' % (self.uid, self.gid))

    persistStyle = "pickle"

    def save(self, tag=None, filename=None, passphrase=None):
        """Save a pickle of this application to a file in the current directory.
        """
        if self.persistStyle == "xml":
            from twisted.persisted.marmalade import jellyToXML
            dumpFunc = jellyToXML
            ext = "tax"
        elif self.persistStyle == "aot":
            from twisted.persisted.aot import jellyToSource
            dumpFunc = jellyToSource
            ext = "tas"
        else:

            def dumpFunc(obj, file, _dump=pickle.dump):
                _dump(obj, file, 1)

            ext = "tap"
        if filename:
            finalname = filename
            filename = finalname + "-2"
        else:
            if passphrase:
                ext = 'e' + ext
            if tag:
                filename = "%s-%s-2.%s" % (self.name, tag, ext)
                finalname = "%s-%s.%s" % (self.name, tag, ext)
            else:
                filename = "%s-2.%s" % (self.name, ext)
                finalname = "%s.%s" % (self.name, ext)
        log.msg("Saving " + self.name + " application to " + finalname + "...")

        if passphrase is None:
            f = open(filename, 'wb')
            dumpFunc(self, f)
            f.flush()
            f.close()
        else:
            f = StringIO.StringIO()
            dumpFunc(self, f)
            s = encrypt(passphrase, f.getvalue())
            f = open(filename, 'wb')
            f.write(s)
            f.flush()
            f.close()

        if platform.getType() == "win32":
            if os.path.isfile(finalname):
                os.remove(finalname)
        os.rename(filename, finalname)
        log.msg("Saved.")

    def logPrefix(self):
        """A log prefix which describes me.
        """
        return "*%s*" % self.name

    def _beforeShutDown(self):
        l = []
        services = self.services.values()
        for service in services:
            try:
                d = service.stopService()
                if isinstance(d, defer.Deferred):
                    l.append(d)
            except:
                log.deferr()
        if l:
            return defer.DeferredList(l)

    def _afterShutDown(self):
        if self._save:
            self.save("shutdown")

    _boundPorts = 0

    def bindPorts(self):
        log.callWithLogger(self, self._doBindPorts)

    def _doBindPorts(self):
        from twisted.internet import reactor
        self._listenerDict = {}
        self._boundPorts = 1
        if not self.running:
            for filename, factory, backlog, mode in self.unixPorts:
                try:
                    self._listenerDict[filename] = reactor.listenUNIX(
                        filename, factory, backlog, mode)
                except error.CannotListenError, msg:
                    log.msg('error on UNIX socket %s: %s' % (filename, msg))
                    return
            for port, factory, backlog, interface in self.tcpPorts:
                try:
                    self._listenerDict[port, interface] = reactor.listenTCP(
                        port, factory, backlog, interface)
                except error.CannotListenError, msg:
                    log.msg('error on TCP port %s: %s' % (port, msg))
                    return
            for port, factory, interface, maxPacketSize in self.udpPorts:
                try:
                    reactor.listenUDP(port, factory, interface, maxPacketSize)
                except error.CannotListenError, msg:
                    log.msg('error on UDP port %s: %s' % (port, msg))
                    return