Fixed a bit of everything in WAMP, and added web settings for that same extension. nevow_service_rework
authorEdouard Tisserant
Fri, 06 Jul 2018 15:09:44 +0200
branchnevow_service_rework
changeset 2218 7a4deed94eb2
parent 2217 a603d1ba287b
child 2219 73042b2d8d65
Fixed a bit of everything in WAMP, and added web settings for that same extension.
runtime/WampClient.py
tests/wamp/project_files/wampconf.json
--- a/runtime/WampClient.py	Fri Jul 06 15:07:40 2018 +0200
+++ b/runtime/WampClient.py	Fri Jul 06 15:09:44 2018 +0200
@@ -35,6 +35,9 @@
 from twisted.internet.defer import inlineCallbacks
 from twisted.internet.protocol import ReconnectingClientFactory
 
+import runtime.NevowServer as NS
+
+from formless import annotate
 
 mandatoryConfigItems = ["ID", "active", "realm", "url"]
 
@@ -67,6 +70,7 @@
 """ things to do on join (callables) """
 DoOnJoin = []
 
+lastKnownConfig = None
 
 def GetCallee(name):
     """ Get Callee or Subscriber corresponding to '.' spearated object path """
@@ -87,9 +91,12 @@
 
     def onChallenge(self, challenge):
         if challenge.method == u"wampcra":
-            secret = self.config.extra["secret"].encode('utf8')
-            signature = auth.compute_wcs(secret, challenge.extra['challenge'].encode('utf8'))
-            return signature.decode("ascii")
+            if "secret" in self.config.extra:
+                secret = self.config.extra["secret"].encode('utf8')
+                signature = auth.compute_wcs(secret, challenge.extra['challenge'].encode('utf8'))
+                return signature.decode("ascii")
+            else:
+                raise Exception("no secret given for authentication")
         else:
             raise Exception("don't know how to handle authmethod {}".format(challenge.method))
 
@@ -157,51 +164,55 @@
             del connector
 
 
+def CheckConfiguration(WSClientConf):
+    url = WSClientConf["url"]
+    if not IsCorrectUri(url):
+        raise annotate.ValidateError(
+            {"url":"Invalid URL: {}".format(url)},
+            _("WAMP confiuration error:"))
+
 def GetConfiguration():
+    global lastKnownConfig
+
     WSClientConf = json.load(open(_WampConf))
     for itemName in mandatoryConfigItems:
         if WSClientConf.get(itemName, None) is None :
             raise Exception(_("WAMP configuration error : missing '{}' parameter.").format(itemName))
 
+    CheckConfiguration(WSClientConf)
+
+    lastKnownConfig = WSClientConf.copy()
     return WSClientConf
 
 
 def SetConfiguration(WSClientConf):
-    try:
-        with open(os.path.realpath(_WampConf), 'w') as f:
-            json.dump(WSClientConf, f, sort_keys=True, indent=4)
-        if 'active' in WSClientConf and WSClientConf['active']:
-            if _transportFactory and _WampSession:
-                StopReconnectWampClient()
-            StartReconnectWampClient()
-        else:
+    global lastKnownConfig
+
+    CheckConfiguration(WSClientConf)
+
+    lastKnownConfig = WSClientConf.copy()
+    
+    with open(os.path.realpath(_WampConf), 'w') as f:
+        json.dump(WSClientConf, f, sort_keys=True, indent=4)
+    if 'active' in WSClientConf and WSClientConf['active']:
+        if _transportFactory and _WampSession:
             StopReconnectWampClient()
-
-        return WSClientConf
-    except ValueError, ve:
-        print(_("WAMP save error: "), ve)
-        return None
-    except Exception, e:
-        print(_("WAMP save error: "), e)
-        return None
+        StartReconnectWampClient()
+    else:
+        StopReconnectWampClient()
+
+    return WSClientConf
 
 
 def LoadWampSecret(secretfname):
-    try:
-        WSClientWampSecret = open(secretfname, 'rb').read()
-        return WSClientWampSecret
-    except ValueError, ve:
-        print(_("Wamp secret load error:"), ve)
-        return None
-    except Exception:
-        return None
+    WSClientWampSecret = open(secretfname, 'rb').read()
+    if len(WSClientWampSecret) == 0 :
+        raise Exception(_("WAMP secret empty"))
+    return WSClientWampSecret
 
 
 def IsCorrectUri(uri):
-    if re.match(r'w{1}s{1,2}:{1}/{2}.+:{1}[0-9]+/{1}.+', uri):
-        return True
-    else:
-        return False
+    return re.match(r'wss?://[^\s?:#-]+(:[0-9]+)?(/[^\s]*)?$', uri) is not None
 
 
 def RegisterWampClient(wampconf=None, wampsecret=None):
@@ -213,17 +224,12 @@
 
     WSClientConf = GetConfiguration()
 
-    if not IsCorrectUri(WSClientConf["url"]):
-        raise Exception(_("WAMP url {} is not correct!").format(WSClientConf["url"]))
-
     if not WSClientConf["active"]:
         print(_("WAMP deactivated in configuration"))
         return
 
-    WampSecret = LoadWampSecret(_WampSecret)
-
-    if WampSecret is not None:
-        WSClientConf["secret"] = WampSecret
+    if _WampSecret is not None:
+        WSClientConf["secret"] = LoadWampSecret(_WampSecret)
 
     # create a WAMP application session factory
     component_config = types.ComponentConfig(
@@ -251,8 +257,10 @@
 
 
 def StopReconnectWampClient():
-    _transportFactory.stopTrying()
-    return _WampSession.leave()
+    if _transportFactory is not None :
+        _transportFactory.stopTrying()
+    if _WampSession is not None :
+        _WampSession.leave()
 
 
 def StartReconnectWampClient():
@@ -269,10 +277,54 @@
 def GetSession():
     return _WampSession
 
-
-def StatusWampClient():
-    return _WampSession and _WampSession.is_attached()
+def getWampStatus():
+    if _transportFactory is not None :
+        if _WampSession is not None :
+            if _WampSession.is_attached() :
+                return "Attached"
+            return "Established"
+        return "Connecting"
+    return "Disconnected"
 
 
 def SetServer(pysrv):
     _PySrv = pysrv
+
+
+#### WEB CONFIGURATION INTERFACE ####
+
+webExposedConfigItems = ['active', 'url', 'ID']
+
+def wampConfigDefault(ctx,argument):
+    if lastKnownConfig is not None :
+        return lastKnownConfig.get(argument.name, None)
+
+def wampConfig(**kwargs):
+    newConfig = lastKnownConfig.copy()
+    for argname in webExposedConfigItems:
+        newConfig[argname] = kwargs[argname]
+
+    SetConfiguration(newConfig)
+
+webFormInterface = [
+    ("status",
+       annotate.String(label=_("Current status"),
+                       immutable = True,
+                       default = lambda *k:getWampStatus())),
+    ("ID",
+       annotate.String(label=_("ID"),
+                       default = wampConfigDefault)),
+    ("active",
+       annotate.Boolean(label=_("Enable WAMP connection"),
+                        default=wampConfigDefault)),
+    ("url",
+       annotate.String(label=_("WAMP Server URL"),
+                       default=wampConfigDefault))]
+
+
+NS.ConfigurableSettings.addExtension(
+    "wamp", 
+    _("Wamp Settings"),
+    webFormInterface,
+    _("Set"),
+    wampConfig)
--- a/tests/wamp/project_files/wampconf.json	Fri Jul 06 15:07:40 2018 +0200
+++ b/tests/wamp/project_files/wampconf.json	Fri Jul 06 15:09:44 2018 +0200
@@ -1,8 +1,6 @@
 {
     "ID": "wamptest", 
     "active": true, 
-    "key": "ABCDEFGHIJ", 
-    "password": "1234567890", 
     "protocolOptions": {
         "autoPingInterval": 60, 
         "autoPingTimeout": 20