__author__ = 'Me'
import sys, json
from twisted.internet import reactor, ssl, protocol
from twisted.python import log
from OpenSSL import SSL
from twisted.web.server import Site
from twisted.web.static import File
from autobahn.twisted.websocket import WebSocketServerFactory, WebSocketServerProtocol, listenWS,http
from autobahn.twisted.resource import WebSocketResource
import hashlib
import os,binascii
import time
from twisted.web.util import redirectTo
from twisted.python import log
from twisted.web.resource import Resource
from time import sleep
blockedClients = []
def search(value, list,key):
return [element for element in list if element[key] == value]
class BroadcastServerProtocol(WebSocketServerProtocol):
global blockedClients
def onConnect(self,request):
print 'client connecting: '+self.peer
ip, port = self.transport.client
isclient = {"ip":ip}
connectiontime = time.time()
blocked = search(ip, blockedClients, 'ip')
#check client on connect and deny access if he's added to block list
if blocked:
dude = blocked[0]
print (connectiontime-dude['time'])
if connectiontime-(dude['time']) > 60:
blockedClients.remove(blocked[0])
else:
raise http.HttpException(1008,"Nope")
#on client open send challenge
def onOpen(self):
print "connection opened"
self.challenge=binascii.b2a_hex(os.urandom(128))
self.sendMessage(json.dumps({"challenge": self.challenge}))
def onMessage(self, payload, isBinary):
#only send mmessages to clients that have been authorized
if(self in self.factory.clients):
if not isBinary:
data = json.loads(payload)
print data
if data.has_key('Output'):
output = data["Output"]
current = factory.lighting.output_status()[int(output)]
newval = not int(current)
print(output,' ',current,' ',newval)
factory.lighting.output_cmd(int(output), newval, False)
else: #if message was received from an unauthorized client check it's hash against local computed hash
#print self.challenge
hash_object = hashlib.sha256(self.challenge+'secret')
hex_dig = hash_object.hexdigest()
if(payload==hex_dig):
self.factory.register(self)
else:
self.sendMessage("Sorry UnAuthorized")
self.failConnection(1008.,"Sorry UnAuthorized")
ip, port = self.transport.client
block = {"ip":ip, "time":time.time()}
blockedClients.append(block)
print 'blocked:{0}'.format(ip)
def connectionLost(self, reason):
WebSocketServerProtocol.connectionLost(self, reason)
self.factory.unregister(self)
class BroadcastServerFactory(WebSocketServerFactory):
def __init__(self, url, debug=False, debugCodePaths=False):
WebSocketServerFactory.__init__(self, url, debug=debug, debugCodePaths=debugCodePaths)
self.clients = []
def register(self, client):
if client not in self.clients:
self.clients.append(client)
def unregister(self, client):
if client in self.clients:
print("unregistered client {}".format(client.peer))
self.clients.remove(client)
def broadcast(self, msg):
print("broadcasting message '{}' ..".format(msg))
for c in self.clients:
c.sendMessage(msg.encode('utf8'))
print("message sent to {}".format(c.peer))
if __name__ == '__main__':
if len(sys.argv) > 1 and sys.argv[1] == 'debug':
log.startLogging(sys.stdout)
debug = True
else:
debug = False
contextFactory = ssl.DefaultOpenSSLContextFactory('keys/server.key','keys/server.crt')
ServerFactory = BroadcastServerFactory
factory = ServerFactory("wss://localhost:9000", debug=True, debugCodePaths=True)
factory.protocol = BroadcastServerProtocol
listenWS(factory, contextFactory)
webdir = File("web/")
webdir.contentTypes['.crt'] = 'application/x-x509-ca-cert'
web = Site(webdir)
reactor.listenSSL(443,web,contextFactory)
print 'starting server'
reactor.run()