changeset 554:471b6babe960

server_side: set a timeout to reset the waiting connection requests after 5 minutes
author souliane <souliane@mailoo.org>
date Sun, 21 Sep 2014 14:09:59 +0200
parents 8492c2bb463b
children db1b330c1eb1
files src/server/constants.py src/server/server.py
diffstat 2 files changed, 43 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/src/server/constants.py	Fri Sep 19 15:39:12 2014 +0200
+++ b/src/server/constants.py	Sun Sep 21 14:09:59 2014 +0200
@@ -30,7 +30,7 @@
     APP_NAME_FILE = "libervia"
     SERVICE_PROFILE = 'libervia'  # the SàT profile that is used for exporting the service
 
-    TIMEOUT = 300  # Session's time out, after that the user will be disconnected
+    TIMEOUT = 300  # Session's time out, after that the user will be disconnected or a waiting connection request will be reset
     HTML_DIR = "html/"
     SERVER_CSS_DIR = "server_css/"
     MEDIA_DIR = "media/"
--- a/src/server/server.py	Fri Sep 19 15:39:12 2014 +0200
+++ b/src/server/server.py	Sun Sep 21 14:09:59 2014 +0200
@@ -564,6 +564,39 @@
         return self.sat_host.bridge.skipOTR(profile)
 
 
+class WaitingRequests(dict):
+
+    def setRequest(self, request, profile):
+        """Add the given profile to the waiting list.
+
+        @param request (server.Request): the connection request
+        @param profile (str): %(doc_profile)s
+        """
+        dc = reactor.callLater(C.TIMEOUT, self.purgeRequest, profile)
+        self[profile] = (request, dc)
+
+    def purgeRequest(self, profile):
+        """Remove the given profile from the waiting list.
+
+        @param profile (str): %(doc_profile)s
+        """
+        try:
+            dc = self[profile][1]
+        except KeyError:
+            return
+        if dc.active():
+            dc.cancel()
+        del self[profile]
+
+    def getRequest(self, profile):
+        """Get the waiting request for the given profile.
+
+        @param profile (str): %(doc_profile)s
+        @return: the waiting request or None
+        """
+        return self[profile][0] if profile in self else None
+
+
 class Register(JSONRPCMethodManager):
     """This class manage the registration procedure with SàT
     It provide an api for the browser, check password and setup the web server"""
@@ -572,13 +605,7 @@
         JSONRPCMethodManager.__init__(self, sat_host)
         self.profiles_waiting = {}
         self.request = None
-
-    def getWaitingRequest(self, profile):
-        """Tell if a profile is trying to log in"""
-        if profile in self.profiles_waiting:
-            return self.profiles_waiting[profile]
-        else:
-            return None
+        self.waiting_profiles = WaitingRequests()
 
     def render(self, request):
         """
@@ -647,12 +674,12 @@
             return C.PROFILE_AUTH_ERROR
             # profiles with empty passwords are restricted to local frontends
 
-        if login_ in self.profiles_waiting:
+        if self.waiting_profiles.getRequest(login_):
             return C.ALREADY_WAITING
 
         def auth_eb(failure):
             fault = failure.value.faultString
-            self.__cleanWaiting(login_)
+            self.waiting_profiles.purgeRequest(login_)
             if fault == 'PasswordError':
                 log.info("Profile %s doesn't exist or the submitted password is wrong" % login_)
                 request.write(C.PROFILE_AUTH_ERROR)
@@ -667,12 +694,13 @@
                 request.write(C.UNKNOWN_ERROR % fault)
             request.finish()
 
-        self.profiles_waiting[login_] = request
+        self.waiting_profiles.setRequest(request, login_)
         d = self.asyncBridgeCall("asyncConnect", login_, password_)
         d.addCallbacks(lambda connected: self._logged(login_, request) if connected else None, auth_eb)
 
         return server.NOT_DONE_YET
 
+
     def _registerNewAccount(self, request):
         """Create a new account, or return error
         @param request: request of the register form
@@ -716,13 +744,6 @@
         d.addErrback(registeringError)
         return server.NOT_DONE_YET
 
-    def __cleanWaiting(self, login):
-        """Remove login from waiting queue"""
-        try:
-            del self.profiles_waiting[login]
-        except KeyError:
-            pass
-
     def _logged(self, profile, request):
         """Set everything when a user just logged in
 
@@ -732,7 +753,7 @@
             - C.PROFILE_LOGGED
             - C.SESSION_ACTIVE
         """
-        self.__cleanWaiting(profile)
+        self.waiting_profiles.purgeRequest(profile)
         _session = request.getSession()
         sat_session = ISATSession(_session)
         if sat_session.profile:
@@ -766,9 +787,9 @@
     def jsonrpc_asyncConnect(self):
         _session = self.request.getSession()
         profile = ISATSession(_session).profile
-        if profile in self.profiles_waiting:
+        if self.waiting_profiles.getRequest(profile):
             raise jsonrpclib.Fault(1, C.ALREADY_WAITING)  # FIXME: define some standard error codes for libervia
-        self.profiles_waiting[profile] = self.request
+        self.waiting_profiles.setRequest(self.request, profile)
         self.sat_host.bridge.asyncConnect(profile)
         return server.NOT_DONE_YET
 
@@ -877,7 +898,7 @@
 
     def connected(self, profile):
         assert(self.register)  # register must be plugged
-        request = self.register.getWaitingRequest(profile)
+        request = self.register.waiting_profiles.getRequest(profile)
         if request:
             self.register._logged(profile, request)