5 # Copyright 2012 Intel Corporation.
7 # Licensed under the Apache License, Version 2.0 (the "License");
8 # you may not use this file except in compliance with the License.
9 # You may obtain a copy of the License at
11 # http://www.apache.org/licenses/LICENSE-2.0
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # See the License for the specific language governing permissions and
17 # limitations under the License.
19 # Luc Yriarte <luc.yriarte@intel.com>
20 # Christophe Guiraud <christophe.guiraud@intel.com>
21 # Frederic Paut <frederic.paut@intel.com>
25 import argparse, dbus, json, sys
27 from twisted.internet import glib2reactor
28 # Configure the twisted mainloop to be run inside the glib mainloop.
29 # This must be done before importing the other twisted modules
30 glib2reactor.install()
31 from twisted.internet import reactor, defer
33 from autobahn.websocket import listenWS
34 from autobahn.wamp import exportRpc, WampServerFactory, WampCraServerProtocol
36 from dbus.mainloop.glib import DBusGMainLoop
41 gobject.threads_init()
47 from twisted.python import log
50 from xml.etree.ElementTree import XMLParser
52 ###############################################################################
61 ###############################################################################
63 ## Convert an ip or an IP mask (such as ip/24 or ip/255.255.255.0) in hex value (32bits)
66 if mask.rfind(".") == -1:
68 maskHex = (2**(int(mask))-1)
69 maskHex = maskHex << (32-int(mask))
71 raise Exception("Illegal mask (larger than 32 bits) " + mask)
73 maskField = mask.split(".")
74 # Check if mask has four fields (byte)
75 if len(maskField) != 4:
76 raise Exception("Illegal ip address / mask (should be 4 bytes) " + mask)
77 for maskQuartet in maskField:
78 byte = int(maskQuartet)
79 # Check if each field is really a byte
81 raise Exception("Illegal ip address / mask (digit larger than a byte) " + mask)
83 maskHex = maskHex << 8
84 maskHex = maskHex >> 8
87 ###############################################################################
90 Global cache of DBus connexions and signal handlers
93 self.dbusConnexions = {}
94 self.signalHandlers = {}
99 Disconnect signal handlers before resetting cache.
101 self.dbusConnexions = {}
102 # disconnect signal handlers
103 for key in self.signalHandlers:
104 self.signalHandlers[key].disconnect()
105 self.signalHandlers = {}
108 def dbusConnexion(self, busName):
109 if not self.dbusConnexions.has_key(busName):
110 if busName == "session":
111 self.dbusConnexions[busName] = dbus.SessionBus()
112 elif busName == "system":
113 self.dbusConnexions[busName] = dbus.SystemBus()
115 raise Exception("Error: invalid bus: %s" % busName)
116 return self.dbusConnexions[busName]
120 ###############################################################################
121 class DbusSignalHandler:
123 signal hash id as busName#senderName#objectName#interfaceName#signalName
125 def __init__(self, busName, senderName, objectName, interfaceName, signalName):
126 self.id = "#".join([busName, senderName, objectName, interfaceName, signalName])
127 # connect handler to signal
128 self.bus = cache.dbusConnexion(busName)
129 self.bus.add_signal_receiver(self.handleSignal, signalName, interfaceName, senderName, objectName)
132 def disconnect(self):
133 names = self.id.split("#")
134 self.bus.remove_signal_receiver(self.handleSignal, names[4], names[3], names[1], names[2])
137 def handleSignal(self, *args):
139 publish dbus args under topic hash id
141 factory.dispatch(self.id, json.dumps(args))
145 ###############################################################################
146 class DbusCallHandler:
148 deferred reply to return dbus results
150 def __init__(self, method, args):
152 self.request = defer.Deferred()
157 def callMethod(self):
159 dbus method async call
162 self.method(*self.args, reply_handler=self.dbusSuccess, error_handler=self.dbusError)
166 def dbusSuccess(self, *result):
168 return JSON string result array
170 self.request.callback(json.dumps(result))
174 def dbusError(self, error):
176 return dbus error message
178 self.request.errback(Exception(error.get_dbus_message()))
183 ################################################################################
186 Execute DynDBusClass generated code
188 def __init__(self, globalCtx, localCtx) :
189 self.exec_string = ""
190 self.exec_code = None
191 self.exec_code_valid = 1
192 self.indent_level = 0
193 self.indent_increment = 1
195 self.localCtx = localCtx
196 self.globalCtx = globalCtx
199 def append_stmt(self, stmt) :
200 self.exec_code_valid = 0
202 for x in range(0,self.indent_level):
203 self.exec_string = self.exec_string + ' '
204 self.exec_string = self.exec_string + stmt + '\n'
207 self.indent_level = self.indent_level + self.indent_increment
210 self.indent_level = self.indent_level - self.indent_increment
212 # compile : Compile exec_string into exec_code using the builtin
213 # compile function. Skip if already in sync.
215 if not self.exec_code_valid :
216 self.exec_code = compile(self.exec_string, "<string>", "exec")
217 self.exec_code_valid = True
220 if not self.exec_code_valid :
222 exec(self.exec_code, self.globalCtx, self.localCtx)
226 ################################################################################
227 class XmlCbParser: # The target object of the parser
230 def __init__(self, dynDBusClass):
231 self.dynDBusClass = dynDBusClass
233 def start(self, tag, attrib): # Called for each opening tag.
237 if (tag == 'interface'):
238 self.dynDBusClass.set_interface(attrib['name'])
241 if (tag == 'method'):
243 self.dynDBusClass.def_method(attrib['name'])
245 if (tag == 'signal'):
247 self.dynDBusClass.def_signal(attrib['name'])
250 # Set signature (in/out & name) for method
252 if (self.current == 'method'):
253 if (attrib.has_key('direction') == False):
254 attrib['direction'] = "in"
255 self.dynDBusClass.add_signature(attrib['name'],
259 if (self.current == 'signal'):
260 if (attrib.has_key('name') == False):
261 attrib['name'] = 'value'
262 self.dynDBusClass.add_signature(attrib['name'], 'in',
265 def end(self, tag): # Called for each closing tag.
266 if (tag == 'method'):
267 self.dynDBusClass.add_dbus_method()
268 self.dynDBusClass.add_body_method()
269 self.dynDBusClass.end_method()
270 if (tag == 'signal'):
271 self.dynDBusClass.add_dbus_signal()
272 self.dynDBusClass.add_body_signal()
273 self.dynDBusClass.end_method()
275 def data(self, data):
276 pass # We do not need to do anything with data.
277 def close(self): # Called when all data has been parsed.
282 ###############################################################################
283 def createClassName(objectPath):
284 return re.sub('/', '_', objectPath[1:])
286 ################################################################################
287 class DynDBusClass():
288 def __init__(self, className, globalCtx, localCtx):
289 self.xmlCB = XmlCbParser(self)
291 self.class_code = ExecCode(globalCtx, localCtx)
292 self.class_code.indent_increment = 4
293 self.class_code.append_stmt("import dbus")
294 self.class_code.append_stmt("\n")
295 self.class_code.append_stmt("class " + className + "(dbus.service.Object):")
296 self.class_code.indent()
298 ## Overload of __init__ method
299 self.def_method("__init__")
300 self.add_method("bus, callback=None, objPath='/sample', srvName='org.cloudeebus'")
301 self.add_stmt("self.bus = bus")
302 self.add_stmt("self.objPath = objPath")
303 self.add_stmt("self.srvName = srvName")
304 self.add_stmt("self.callback = callback")
305 self.add_stmt("dbus.service.Object.__init__(self, conn=bus, bus_name=srvName)")
308 ## Create 'add_to_connection' method
309 self.def_method("add_to_connection")
310 self.add_method("connection=None, path=None")
311 self.add_stmt("dbus.service.Object.add_to_connection(self, connection=self.bus, path=self.objPath)")
314 ## Create 'remove_from_connection' method
315 self.def_method("remove_from_connection")
316 self.add_method("connection=None, path=None")
317 self.add_stmt("dbus.service.Object.remove_from_connection(self, connection=None, path=self.objPath)")
320 def createDBusServiceFromXML(self, xml):
321 self.parser = XMLParser(target=self.xmlCB)
322 self.parser.feed(xml)
325 def set_interface(self, ifName):
328 def def_method(self, methodName):
329 self.methodToAdd = methodName
330 self.signalToAdd = None
331 self.args_str = str()
333 self.signature['name'] = str()
334 self.signature['in'] = str()
335 self.signature['out'] = str()
337 def def_signal(self, signalName):
338 self.methodToAdd = None
339 self.signalToAdd = signalName
340 self.args_str = str()
342 self.signature['name'] = str()
343 self.signature['in'] = str()
344 self.signature['out'] = str()
346 def add_signature(self, name, direction, signature):
347 if (direction == 'in'):
348 self.signature['in'] += signature
349 if (self.signature['name'] != str()):
350 self.signature['name'] += ", "
351 self.signature['name'] += name
352 if (direction == 'out'):
353 self.signature['out'] = signature
355 def add_method(self, args = None, async_success_cb = None, async_err_cb = None):
357 if (self.methodToAdd != None):
358 name = self.methodToAdd
360 name = self.signalToAdd
363 if (async_success_cb != None):
364 async_cb_str = async_success_cb
365 if (async_err_cb != None):
366 if (async_cb_str != str()):
368 async_cb_str += async_err_cb
370 parameters = self.args_str
371 if (async_cb_str != str()):
372 if (parameters != str()):
374 parameters +=async_cb_str
376 if (parameters != str()):
377 self.class_code.append_stmt("def " + name + "(self, %s):" % parameters)
379 self.class_code.append_stmt("def " + name + "(self):")
380 self.class_code.indent()
382 def end_method(self):
383 self.class_code.append_stmt("\n")
384 self.class_code.dedent()
386 def add_dbus_method(self):
387 decorator = '@dbus.service.method("' + self.ifName + '"'
388 if (self.signature.has_key('in') and self.signature['in'] != str()):
389 decorator += ", in_signature='" + self.signature['in'] + "'"
390 if (self.signature.has_key('out') and self.signature['out'] != str()):
391 decorator += ", out_signature='" + self.signature['out'] + "'"
392 decorator += ", async_callbacks=('dbus_async_cb', 'dbus_async_err_cb')"
394 self.class_code.append_stmt(decorator)
395 if (self.signature.has_key('name') and self.signature['name'] != str()):
396 self.add_method(self.signature['name'], async_success_cb='dbus_async_cb', async_err_cb='dbus_async_err_cb')
398 self.add_method(async_success_cb='dbus_async_cb', async_err_cb='dbus_async_err_cb')
400 def add_dbus_signal(self):
401 decorator = '@dbus.service.signal("' + self.ifName + '"'
402 if (self.signature.has_key('in') and self.signature['in'] != str()):
403 decorator += ", signature='" + self.signature['in'] + "'"
405 self.class_code.append_stmt(decorator)
406 if (self.signature.has_key('name') and self.signature['name'] != str()):
407 self.add_method(self.signature['name'])
411 def add_body_method(self):
412 if (self.methodToAdd != None):
413 if (self.args_str != str()):
414 self.class_code.append_stmt("self.callback(self.srvName,'" + self.methodToAdd + "', self.objPath, '" + self.ifName + "', " + "dbus_async_cb, dbus_async_err_cb, %s)" % self.args_str)
416 self.class_code.append_stmt("self.callback(self.srvName,'" + self.methodToAdd + "', self.objPath, '" + self.ifName + "', " + "dbus_async_cb, dbus_async_err_cb)")
418 def add_body_signal(self):
419 self.class_code.append_stmt("return") ## TODO: Remove and fix with code ad hoc
420 self.class_code.append_stmt("\n")
422 def add_stmt(self, stmt) :
423 self.class_code.append_stmt(stmt)
426 self.class_code.execute()
430 ###############################################################################
431 class CloudeebusService:
433 support for sending DBus messages and registering for DBus signals
435 def __init__(self, permissions):
436 self.permissions = {};
437 self.permissions['permissions'] = permissions['permissions']
438 self.permissions['authextra'] = permissions['authextra']
439 self.permissions['services'] = permissions['services']
440 self.proxyObjects = {}
441 self.proxyMethods = {}
442 self.pendingCalls = []
443 self.dynDBusClasses = {} # DBus class source code generated dynamically (a list because one by classname)
444 self.services = {} # DBus service created
445 self.serviceAgents = {} # Instantiated DBus class previously generated dynamically, for now, one by classname
446 self.servicePendingCalls = {} # JS methods called (and waiting for a Success/error response), containing 'methodId', (successCB, errorCB)
447 self.localCtx = locals()
448 self.globalCtx = globals()
450 self.patternDbus = re.compile('^dbus\.(\w+)')
451 self.patternDbusBoolean = re.compile('^dbus.Boolean\((\w+)\)$')
452 self.patternDbusByte = re.compile('^dbus.Byte\((\d+)\)$')
453 self.patternDbusInt16 = re.compile('^dbus.Int16\((\d+)\)$')
454 self.patternDbusInt32 = re.compile('^dbus.Int32\((\d+)\)$')
455 self.patternDbusInt64 = re.compile('^dbus.Int64\((\d+)\)$')
456 self.patternDbusUInt16 = re.compile('^dbus.UInt16\((\d+)\)$')
457 self.patternDbusUInt32 = re.compile('^dbus.UInt32\((\d+)\)$')
458 self.patternDbusUInt64 = re.compile('^dbus.UInt64\((\d+)\)$')
459 self.patternDbusDouble = re.compile('^dbus.Double\((\d+\.\d+)\)$')
461 def proxyObject(self, busName, serviceName, objectName):
463 object hash id as busName#serviceName#objectName
465 id = "#".join([busName, serviceName, objectName])
466 if not self.proxyObjects.has_key(id):
468 # check permissions, array.index throws exception
469 self.permissions['permissions'].index(serviceName)
470 bus = cache.dbusConnexion(busName)
471 self.proxyObjects[id] = bus.get_object(serviceName, objectName)
472 return self.proxyObjects[id]
475 def proxyMethod(self, busName, serviceName, objectName, interfaceName, methodName):
477 method hash id as busName#serviceName#objectName#interfaceName#methodName
479 id = "#".join([busName, serviceName, objectName, interfaceName, methodName])
480 if not self.proxyMethods.has_key(id):
481 obj = self.proxyObject(busName, serviceName, objectName)
482 self.proxyMethods[id] = obj.get_dbus_method(methodName, interfaceName)
483 return self.proxyMethods[id]
485 def decodeArgs( self, args ):
486 if isinstance( args, list ):
489 newArgs.append( self.decodeArgs( arg ))
491 elif isinstance( args, dict ):
493 for key, value in args.iteritems():
494 key = self.decodeArgs( key )
495 newValue = self.decodeArgs( value )
496 newDict[key] = newValue
498 elif isinstance( args, basestring ):
499 newArg = self.decodeDbusString( args )
504 def decodeDbusString( self, dbusString ):
505 matchDbus = self.patternDbus.match( dbusString )
512 "Boolean" : lambda x : dbus.Boolean( self.patternDbusBoolean.match( x ).group( 1 ).lower() in ("yes", "true", "t", "1")),
513 "Byte" : lambda x : dbus.Byte( int( self.patternDbusByte.match( x ).group( 1 ))),
514 "Int16" : lambda x : dbus.Int16( self.patternDbusInt16.match( x ).group( 1 )),
515 "Int32" : lambda x : dbus.Int32( self.patternDbusInt32.match( x ).group( 1 )),
516 "Int64" : lambda x : dbus.Int64( self.patternDbusInt64.match( x ).group( 1 )),
517 "UInt16" : lambda x : dbus.UInt16( self.patternDbusUInt16.match( x ).group( 1 )),
518 "UInt32" : lambda x : dbus.UInt32( self.patternDbusUInt32.match( x ).group( 1 )),
519 "UInt64" : lambda x : dbus.UInt64( self.patternDbusUInt64.match( x ).group( 1 )),
520 "Double" : lambda x : dbus.Double( self.patternDbusDouble.match( x ).group( 1 ))
521 }[matchDbus.group(1)](dbusString)
526 def dbusRegister(self, list):
528 arguments: bus, sender, object, interface, signal
531 raise Exception("Error: expected arguments: bus, sender, object, interface, signal)")
534 # check permissions, array.index throws exception
535 self.permissions['permissions'].index(list[1])
537 # check if a handler exists
538 sigId = "#".join(list)
539 if cache.signalHandlers.has_key(sigId):
542 # create a handler that will publish the signal
543 dbusSignalHandler = DbusSignalHandler(*list)
544 cache.signalHandlers[sigId] = dbusSignalHandler
546 return dbusSignalHandler.id
550 def dbusSend(self, list):
552 arguments: bus, destination, object, interface, message, [args]
554 # clear pending calls
555 for call in self.pendingCalls:
557 self.pendingCalls.remove(call)
560 raise Exception("Error: expected arguments: bus, destination, object, interface, message, [args])")
562 # parse JSON arg list
565 jsonArgs = json.loads(list[5])
567 args = self.decodeArgs( jsonArgs )
569 # get dbus proxy method
570 method = self.proxyMethod(*list[0:5])
572 # use a deferred call handler to manage dbus results
573 dbusCallHandler = DbusCallHandler(method, args)
574 self.pendingCalls.append(dbusCallHandler)
575 return dbusCallHandler.callMethod()
579 def emitSignal(self, list):
581 arguments: agentObjectPath, signalName, args (to emit)
584 className = re.sub('/', '_', objectPath[1:])
587 jsonArgs = json.loads(list[2])
588 print "JSON Arguments:", jsonArgs
590 args = self.decodeArgs( jsonArgs )
591 print "Decoded Arguments: ", args
593 if (self.serviceAgents.has_key(className) == True):
594 exe_str = "self.serviceAgents['"+ className +"']."+ signalName + "("
596 exe_str += json.dumps(args[0])
598 exe_str += "," + json.dumps(idx)
600 eval(exe_str, self.globalCtx, self.localCtx)
602 raise Exception("No object path " + objectPath)
605 def returnMethod(self, list):
607 arguments: methodId, callIndex, success (=true, error otherwise), result (to return)
613 if (self.servicePendingCalls.has_key(methodId)):
614 cb = self.servicePendingCalls[methodId]['calls'][callIndex]
616 raise Exception("No pending call " + str(callIndex) + " for methodID " + methodId)
618 successCB = cb["successCB"]
624 errorCB = cb["errorCB"]
629 self.servicePendingCalls[methodId]['calls'][callIndex] = None
630 self.servicePendingCalls[methodId]['count'] = self.servicePendingCalls[methodId]['count'] - 1
631 if self.servicePendingCalls[methodId]['count'] == 0:
632 del self.servicePendingCalls[methodId]
634 raise Exception("No methodID " + methodId)
636 def srvCB(self, srvName, name, objPath, ifName, async_succes_cb, async_error_cb, *args):
637 methodId = srvName + "#" + objPath + "#" + ifName + "#" + name
638 cb = { 'successCB': async_succes_cb,
639 'errorCB': async_error_cb}
640 if methodId not in self.servicePendingCalls:
641 self.servicePendingCalls[methodId] = {'count': 0, 'calls': []}
644 pendingCallStr = json.dumps({'callIndex': len(self.servicePendingCalls[methodId]['calls']), 'args': args})
646 args = eval( str(args).replace("dbus.Byte", "dbus.Int16") )
647 pendingCallStr = json.dumps({'callIndex': len(self.servicePendingCalls[methodId]['calls']), 'args': args})
649 self.servicePendingCalls[methodId]['calls'].append(cb)
650 self.servicePendingCalls[methodId]['count'] = self.servicePendingCalls[methodId]['count'] + 1
651 factory.dispatch(methodId, pendingCallStr)
654 def serviceAdd(self, list):
656 arguments: busName, srvName
659 self.bus = cache.dbusConnexion( busName )
661 if not OPENDOOR and (SERVICELIST == [] or SERVICELIST != [] and self.permissions['services'] == None):
662 SERVICELIST.index(srvName)
664 if (self.services.has_key(srvName) == False):
665 self.services[srvName] = dbus.service.BusName(name = srvName, bus = self.bus)
669 def serviceRelease(self, list):
671 arguments: busName, srvName
674 if (self.services.has_key(srvName) == True):
675 self.services.pop(srvName)
678 raise Exception(srvName + " does not exist")
681 def serviceAddAgent(self, list):
683 arguments: objectPath, xmlTemplate
686 agentObjectPath = list[1]
687 xmlTemplate = list[2]
688 className = createClassName(agentObjectPath)
689 if (self.dynDBusClasses.has_key(className) == False):
690 self.dynDBusClasses[className] = DynDBusClass(className, self.globalCtx, self.localCtx)
691 self.dynDBusClasses[className].createDBusServiceFromXML(xmlTemplate)
692 self.dynDBusClasses[className].declare()
694 ## Class already exist, instanciate it if not already instanciated
695 if (self.serviceAgents.has_key(className) == False):
696 self.serviceAgents[className] = eval(className + "(self.bus, callback=self.srvCB, objPath='" + agentObjectPath + "', srvName='" + srvName + "')", self.globalCtx, self.localCtx)
698 self.serviceAgents[className].add_to_connection()
699 return (agentObjectPath)
702 def serviceDelAgent(self, list):
704 arguments: objectPath, xmlTemplate
706 agentObjectPath = list[0]
707 className = createClassName(agentObjectPath)
709 if (self.serviceAgents.has_key(className)):
710 self.serviceAgents[className].remove_from_connection()
711 self.serviceAgents.pop(className)
713 raise Exception(agentObjectPath + " doesn't exist!")
715 return (agentObjectPath)
718 def getVersion(self):
720 return current version string
726 ###############################################################################
727 class CloudeebusServerProtocol(WampCraServerProtocol):
729 connexion and session authentication management
732 def onSessionOpen(self):
733 # CRA authentication options
734 self.clientAuthTimeout = 0
735 self.clientAuthAllowAnonymous = OPENDOOR
736 # CRA authentication init
737 WampCraServerProtocol.onSessionOpen(self)
740 def getAuthPermissions(self, key, extra):
741 return {'permissions': extra.get("permissions", None),
742 'authextra': extra.get("authextra", None),
743 'services': extra.get("services", None)}
745 def getAuthSecret(self, key):
746 secret = CREDENTIALS.get(key, None)
749 # secret must be of str type to be hashed
753 def onAuthenticated(self, key, permissions):
758 for netfilter in NETMASK:
759 ipHex=ipV4ToHex(self.peer.host)
760 ipAllowed = (ipHex & netfilter['mask']) == netfilter['ipAllowed'] & netfilter['mask']
764 raise Exception("host " + self.peer.host + " is not allowed!")
765 # check authentication key
767 raise Exception("Authentication failed")
768 # check permissions, array.index throws exception
769 if (permissions['permissions'] != None):
770 for req in permissions['permissions']:
771 WHITELIST.index(req);
772 # check allowed service creation, array.index throws exception
773 if (permissions['services'] != None):
774 for req in permissions['services']:
775 SERVICELIST.index(req);
776 # create cloudeebus service instance
777 self.cloudeebusService = CloudeebusService(permissions)
778 # register it for RPC
779 self.registerForRpc(self.cloudeebusService)
780 # register for Publish / Subscribe
781 self.registerForPubSub("", True)
784 def connectionLost(self, reason):
785 WampCraServerProtocol.connectionLost(self, reason)
786 if factory.getConnectionCount() == 0:
791 ###############################################################################
793 if __name__ == '__main__':
797 parser = argparse.ArgumentParser(description='Javascript DBus bridge.')
798 parser.add_argument('-v', '--version', action='store_true',
799 help='print version and exit')
800 parser.add_argument('-d', '--debug', action='store_true',
801 help='log debug info on standard output')
802 parser.add_argument('-o', '--opendoor', action='store_true',
803 help='allow anonymous access to all services')
804 parser.add_argument('-p', '--port', default='9000',
806 parser.add_argument('-c', '--credentials',
807 help='path to credentials file')
808 parser.add_argument('-w', '--whitelist',
809 help='path to whitelist file (DBus services to use)')
810 parser.add_argument('-s', '--servicelist',
811 help='path to servicelist file (DBus services to export)')
812 parser.add_argument('-n', '--netmask',
813 help='netmask,IP filter (comma separated.) eg. : -n 127.0.0.1,192.168.2.0/24,10.12.16.0/255.255.255.0')
815 args = parser.parse_args(sys.argv[1:])
818 print("Cloudeebus version " + VERSION)
822 log.startLogging(sys.stdout)
824 OPENDOOR = args.opendoor
827 jfile = open(args.credentials)
828 CREDENTIALS = json.load(jfile)
832 jfile = open(args.whitelist)
833 WHITELIST = json.load(jfile)
837 jfile = open(args.servicelist)
838 SERVICELIST = json.load(jfile)
842 iplist = args.netmask.split(",")
844 if ip.rfind("/") != -1:
850 mask = "255.255.255.255"
851 NETMASK.append( {'ipAllowed': ipV4ToHex(ipAllowed), 'mask' : ipV4ToHex(mask)} )
853 uri = "ws://localhost:" + args.port
855 factory = WampServerFactory(uri, debugWamp = args.debug)
856 factory.protocol = CloudeebusServerProtocol
857 factory.setProtocolOptions(allowHixie76 = True)
861 DBusGMainLoop(set_as_default=True)