summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrebs <drebs@riseup.net>2016-09-27 20:44:53 -0300
committerdrebs <drebs@riseup.net>2016-09-30 13:10:14 -0300
commit9c4bf6adf42f0f9553ae11f24ffeb6f7cf39f374 (patch)
treec03b13ae17c0e6267ba8f3ba47c470aed7ad24d4 /src
parent10f35cacf50148c34b11fba719fc8f734f99def1 (diff)
[refactor] turn mail services into twisted services
Diffstat (limited to 'src')
-rw-r--r--src/leap/bitmask/core/mail_services.py78
-rw-r--r--src/leap/bitmask/core/service.py85
-rw-r--r--src/leap/bitmask/mail/imap/service/imap.py5
-rw-r--r--src/leap/bitmask/mail/incoming/service.py10
-rw-r--r--src/leap/bitmask/mail/smtp/__init__.py9
5 files changed, 110 insertions, 77 deletions
diff --git a/src/leap/bitmask/core/mail_services.py b/src/leap/bitmask/core/mail_services.py
index 04306b4..d2967f8 100644
--- a/src/leap/bitmask/core/mail_services.py
+++ b/src/leap/bitmask/core/mail_services.py
@@ -457,10 +457,11 @@ class StandardMailService(service.MultiService, HookableService):
self.addService(IncomingMailService(self))
def startService(self):
- log.msg('Starting Mail Service...')
+ log.msg('starting mail service')
super(StandardMailService, self).startService()
def stopService(self):
+ log.msg('stopping mail service')
super(StandardMailService, self).stopService()
def startInstance(self, userid, soledad, keymanager):
@@ -485,9 +486,6 @@ class StandardMailService(service.MultiService, HookableService):
d.addCallback(self._write_tokens_file, userid)
return d
- def stopInstance(self):
- pass
-
# hooks
def hook_on_new_keymanager_instance(self, **kw):
@@ -564,20 +562,26 @@ class IMAPService(service.Service):
name = 'imap'
def __init__(self, soledad_sessions):
- port, factory = imap.run_service(soledad_sessions)
-
- self._port = port
- self._factory = factory
self._soledad_sessions = soledad_sessions
+ self._port = None
+ self._factory = None
super(IMAPService, self).__init__()
def startService(self):
- log.msg('Starting IMAP Service')
+ log.msg('starting imap service')
+ port, factory = imap.run_service(
+ self._soledad_sessions, factory=self._factory)
+ self._port = port
+ self._factory = factory
super(IMAPService, self).startService()
def stopService(self):
- self._port.stopListening()
- self._factory.doStop()
+ log.msg("stopping imap service")
+ if self._port:
+ self._port.stopListening()
+ self._port = None
+ if self._factory:
+ self._factory.doStop()
super(IMAPService, self).stopService()
@@ -589,35 +593,47 @@ class SMTPService(service.Service):
basedir=DEFAULT_BASEDIR):
self._basedir = os.path.expanduser(basedir)
- port, factory = smtp.run_service(
- soledad_sessions, keymanager_sessions, sendmail_opts)
- self._port = port
- self._factory = factory
self._soledad_sessions = soledad_sessions
self._keymanager_sessions = keymanager_sessions
self._sendmail_opts = sendmail_opts
+ self._port = None
+ self._factory = None
super(SMTPService, self).__init__()
def startService(self):
- log.msg('Starting SMTP Service')
+ log.msg('starting smtp service')
+ port, factory = smtp.run_service(
+ self._soledad_sessions,
+ self._keymanager_sessions,
+ self._sendmail_opts,
+ factory=self._factory)
+ self._port = port
+ self._factory = factory
super(SMTPService, self).startService()
def stopService(self):
- # TODO cleanup all instances
+ log.msg('stopping smtp service')
+ if self._port:
+ self._port.stopListening()
+ self._port = None
+ if self._factory:
+ self._factory.doStop()
super(SMTPService, self).stopService()
-class IncomingMailService(service.Service):
+class IncomingMailService(service.MultiService):
+ """
+ Manage child services that check for incoming mail for individual users.
+ """
name = 'incoming_mail'
def __init__(self, mail_service):
super(IncomingMailService, self).__init__()
self._mail = mail_service
- self._instances = {}
def startService(self):
- log.msg('Starting IncomingMail Service')
+ log.msg('starting incoming mail service')
super(IncomingMailService, self).startService()
def stopService(self):
@@ -625,25 +641,14 @@ class IncomingMailService(service.Service):
# Individual accounts
- # TODO IncomingMail *IS* already a service.
- # I think we should better model the current Service
- # as a startInstance inside a container, and get this
- # multi-tenant service inside the leap.mail.incoming.service.
- # ... or just simply make it a multiService and set per-user
- # instances as Child of this parent.
-
def startInstance(self, userid):
soledad = self._mail.get_soledad_session(userid)
keymanager = self._mail.get_keymanager_session(userid)
- log.msg('Starting Incoming Mail instance for %s' % userid)
+ log.msg('setting up incoming mail service for %s' % userid)
self._start_incoming_mail_instance(
keymanager, soledad, userid)
- def stopInstance(self, userid):
- # TODO toggle offline!
- pass
-
def _start_incoming_mail_instance(self, keymanager, soledad,
userid, start_sync=True):
@@ -652,18 +657,13 @@ class IncomingMailService(service.Service):
keymanager, soledad,
inbox, userid,
check_period=INCOMING_CHECK_PERIOD)
- return incoming_mail
-
- def registerInstance(incoming_instance):
- self._instances[userid] = incoming_instance
- if start_sync:
- incoming_instance.startService()
+ incoming_mail.setName(userid)
+ self.addService(incoming_mail)
acc = Account(soledad, userid)
d = acc.callWhenReady(
lambda _: acc.get_collection_by_mailbox(INBOX_NAME))
d.addCallback(setUpIncomingMail)
- d.addCallback(registerInstance)
d.addErrback(log.err)
return d
diff --git a/src/leap/bitmask/core/service.py b/src/leap/bitmask/core/service.py
index e449a8c..de99ea5 100644
--- a/src/leap/bitmask/core/service.py
+++ b/src/leap/bitmask/core/service.py
@@ -19,10 +19,9 @@ Bitmask-core Service.
"""
import json
import resource
-from os.path import join, abspath
from twisted.internet import reactor
-from twisted.python import log, logfile
+from twisted.python import log
from leap.bitmask import __version__
from leap.bitmask.core import configurable
@@ -61,21 +60,19 @@ class BitmaskBackend(configurable.ConfigurableService):
on_start(self.init_bonafide)
if enabled('mail'):
- on_start(self.init_soledad)
- on_start(self.init_keymanager)
- on_start(self.init_mail)
+ on_start(self._init_mail_services)
if enabled('eip'):
- on_start(self.init_eip)
+ on_start(self._init_eip)
if enabled('zmq'):
- on_start(self.init_zmq)
+ on_start(self._init_zmq)
if enabled('web'):
- on_start(self.init_web)
+ on_start(self._init_web)
if enabled('websockets'):
- on_start(self.init_websockets)
+ on_start(self._init_websockets)
def init_events(self):
event_server.ensure_server()
@@ -93,47 +90,75 @@ class BitmaskBackend(configurable.ConfigurableService):
bf.register_hook('on_bonafide_auth', listener='keymanager')
bf.register_hook('on_bonafide_auth', listener='mail')
- def init_soledad(self):
+ def _start_child_service(self, name):
+ log.msg('starting backend child service: %s' % name)
+ service = self.getServiceNamed(name)
+ if service:
+ service.startService()
+
+ def _stop_child_service(self, name):
+ log.msg('stopping backend child service: %s' % name)
+ service = self.getServiceNamed(name)
+ if service:
+ service.stopService()
+
+ def _init_mail_services(self):
+ self._init_soledad()
+ self._init_keymanager()
+ self._init_mail()
+
+ def _start_mail_services(self):
+ self._start_child_service('soledad')
+ self._start_child_service('keymanager')
+ self._start_child_service('mail')
+
+ def _stop_mail_services(self):
+ self._stop_child_service('mail')
+ self._stop_child_service('keymanager')
+ self._stop_child_service('soledad')
+
+ def _init_soledad(self):
service = mail_services.SoledadService
- sol = self._maybe_start_service(
+ sol = self._maybe_init_service(
'soledad', service, self.basedir)
if sol:
sol.register_hook(
'on_new_soledad_instance', listener='keymanager')
- def init_keymanager(self):
+ def _init_keymanager(self):
service = mail_services.KeymanagerService
- km = self._maybe_start_service(
+ km = self._maybe_init_service(
'keymanager', service, self.basedir)
if km:
km.register_hook('on_new_keymanager_instance', listener='mail')
- def init_mail(self):
+ def _init_mail(self):
service = mail_services.StandardMailService
- self._maybe_start_service('mail', service, self.basedir)
+ self._maybe_init_service('mail', service, self.basedir)
- def init_eip(self):
+ def _init_eip(self):
# FIXME -- land EIP into leap.vpn
pass
- # self._maybe_start_service('eip', EIPService)
+ # self._maybe_init_service('eip', EIPService)
- def init_zmq(self):
+ def _init_zmq(self):
zs = _zmq.ZMQServerService(self)
zs.setServiceParent(self)
- def init_web(self):
+ def _init_web(self):
service = _web.HTTPDispatcherService
- self._maybe_start_service('web', service, self)
+ self._maybe_init_service('web', service, self)
- def init_websockets(self):
+ def _init_websockets(self):
from leap.bitmask.core import websocket
ws = websocket.WebSocketsDispatcherService(self)
ws.setServiceParent(self)
- def _maybe_start_service(self, label, klass, *args, **kw):
+ def _maybe_init_service(self, label, klass, *args, **kw):
try:
self.getServiceNamed(label)
except KeyError:
+ log.msg("initializing service: %s" % label)
service = klass(*args, **kw)
service.setName(label)
service.setServiceParent(self)
@@ -158,24 +183,26 @@ class BitmaskBackend(configurable.ConfigurableService):
self.set_config('services', service, 'True')
if service == 'mail':
- self.init_soledad()
- self.init_keymanager()
- self.init_mail()
+ self._init_mail_services()
+ self._start_mail_services()
elif service == 'eip':
- self.init_eip()
+ self._init_eip()
elif service == 'zmq':
- self.init_zmq()
+ self._init_zmq()
elif service == 'web':
- self.init_web()
+ self._init_web()
return {'enabled': 'ok'}
def do_disable_service(self, service):
assert service in self.service_names
- # TODO -- should stop also?
+
+ if service == 'mail':
+ self._stop_mail_services()
+
self.set_config('services', service, 'False')
return {'disabled': 'ok'}
diff --git a/src/leap/bitmask/mail/imap/service/imap.py b/src/leap/bitmask/mail/imap/service/imap.py
index aac49b6..9ccff4a 100644
--- a/src/leap/bitmask/mail/imap/service/imap.py
+++ b/src/leap/bitmask/mail/imap/service/imap.py
@@ -158,7 +158,7 @@ class LeapIMAPFactory(ServerFactory):
return ServerFactory.doStop(self)
-def run_service(soledad_sessions, port=IMAP_PORT):
+def run_service(soledad_sessions, port=IMAP_PORT, factory=None):
"""
Main entry point to run the service from the client.
@@ -169,7 +169,8 @@ def run_service(soledad_sessions, port=IMAP_PORT):
the factory for the protocol.
:rtype: tuple
"""
- factory = LeapIMAPFactory(soledad_sessions)
+ if not factory:
+ factory = LeapIMAPFactory(soledad_sessions)
try:
interface = "localhost"
diff --git a/src/leap/bitmask/mail/incoming/service.py b/src/leap/bitmask/mail/incoming/service.py
index 05f9bb5..b4cdfcf 100644
--- a/src/leap/bitmask/mail/incoming/service.py
+++ b/src/leap/bitmask/mail/incoming/service.py
@@ -29,12 +29,15 @@ from StringIO import StringIO
from urlparse import urlparse
from twisted.application.service import Service
+from twisted.application.service import IService
from twisted.logger import Logger
from twisted.python.failure import Failure
from twisted.internet import defer, reactor
from twisted.internet.task import LoopingCall
from twisted.internet.task import deferLater
+from zope.interface import implements
+
from leap.common.events import emit_async, catalog
from leap.common.check import leap_assert, leap_assert_type
from leap.common.mail import get_email_charset
@@ -47,7 +50,7 @@ from leap.soledad.common.crypto import ENC_SCHEME_KEY, ENC_JSON_KEY
from leap.soledad.common.errors import InvalidAuthTokenError
-logger = Logger()
+logger = Logger(__name__)
MULTIPART_ENCRYPTED = "multipart/encrypted"
MULTIPART_SIGNED = "multipart/signed"
@@ -79,7 +82,8 @@ class IncomingMail(Service):
This loop will sync the soledad db with the remote server and
process all the documents found tagged as incoming mail.
"""
- # TODO implements IService?
+
+ implements(IService)
name = "IncomingMail"
@@ -227,7 +231,7 @@ class IncomingMail(Service):
def _signal_invalid_auth(failure):
failure.trap(InvalidAuthTokenError)
- logger.info('sync failed: %r' % failure)
+ logger.warn('sync failed because token has expired: %r' % failure)
# if the token is invalid, send an event so the GUI can
# disable mail and show an error message.
emit_async(catalog.SOLEDAD_INVALID_AUTH_TOKEN, self._userid)
diff --git a/src/leap/bitmask/mail/smtp/__init__.py b/src/leap/bitmask/mail/smtp/__init__.py
index 4e0ac89..f8b8e65 100644
--- a/src/leap/bitmask/mail/smtp/__init__.py
+++ b/src/leap/bitmask/mail/smtp/__init__.py
@@ -32,7 +32,7 @@ SMTP_PORT = 2013
def run_service(soledad_sessions, keymanager_sessions, sendmail_opts,
- port=SMTP_PORT):
+ port=SMTP_PORT, factory=None):
"""
Main entry point to run the service from the client.
@@ -46,8 +46,9 @@ def run_service(soledad_sessions, keymanager_sessions, sendmail_opts,
the factory for the protocol.
:rtype: tuple
"""
- factory = SMTPFactory(soledad_sessions, keymanager_sessions,
- sendmail_opts)
+ if not factory:
+ factory = SMTPFactory(soledad_sessions, keymanager_sessions,
+ sendmail_opts)
try:
interface = "localhost"
@@ -60,7 +61,7 @@ def run_service(soledad_sessions, keymanager_sessions, sendmail_opts,
tport = reactor.listenTCP(port, factory, interface=interface)
emit_async(catalog.SMTP_SERVICE_STARTED, str(port))
- return factory, tport
+ return tport, factory
except CannotListenError:
logger.error("SMTP Service failed to start: "
"cannot listen in port %s" % port)