summaryrefslogtreecommitdiffstats
path: root/module/remote/wsbackend
diff options
context:
space:
mode:
authorGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2013-03-11 19:49:20 +0100
committerGravatar RaNaN <Mast3rRaNaN@hotmail.de> 2013-03-11 19:50:54 +0100
commit763b142db70ce77952cb46cfccf84d9800f15651 (patch)
treed2636e48766d365bd8a9d079de603b127ab88744 /module/remote/wsbackend
parentMerge pull request #33 from stickell/patch-3 (diff)
downloadpyload-763b142db70ce77952cb46cfccf84d9800f15651.tar.xz
websocket login via session, websocket pushes server status, webui renders server status
Diffstat (limited to 'module/remote/wsbackend')
-rw-r--r--module/remote/wsbackend/AbstractHandler.py54
-rw-r--r--module/remote/wsbackend/ApiHandler.py13
-rw-r--r--module/remote/wsbackend/AsyncHandler.py35
3 files changed, 72 insertions, 30 deletions
diff --git a/module/remote/wsbackend/AbstractHandler.py b/module/remote/wsbackend/AbstractHandler.py
index f843fc278..45fbb134c 100644
--- a/module/remote/wsbackend/AbstractHandler.py
+++ b/module/remote/wsbackend/AbstractHandler.py
@@ -41,11 +41,38 @@ class AbstractHandler:
def do_extra_handshake(self, req):
self.log.debug("WS Connected: %s" % req)
+ req.api = None #when api is set client is logged in
+
+ # allow login via session when webinterface is active
+ if self.core.config['webinterface']['activated']:
+ cookie = req.headers_in.getheader('Cookie')
+ s = self.load_session(cookie)
+ if s:
+ uid = s.get('uid', None)
+ req.api = self.api.withUserContext(uid)
+ self.log.debug("WS authenticated with cookie: %d" % uid)
+
self.on_open(req)
def on_open(self, req):
pass
+ def load_session(self, cookies):
+ from Cookie import SimpleCookie
+ from beaker.session import Session
+ from module.web.webinterface import session
+
+ cookies = SimpleCookie(cookies)
+ sid = cookies.get(session.options['key'])
+ if not sid:
+ return None
+
+ s = Session({}, use_cookies=False, id=sid.value, **session.options)
+ if s.is_new:
+ return None
+
+ return s
+
def passive_closing_handshake(self, req):
self.log.debug("WS Closed: %s" % req)
self.on_close(req)
@@ -59,8 +86,6 @@ class AbstractHandler:
def handle_call(self, msg, req):
""" Parses the msg for an argument call. If func is null an response was already sent.
- :param msg:
- :param req:
:return: func, args, kwargs
"""
try:
@@ -70,11 +95,15 @@ class AbstractHandler:
self.send_result(req, self.ERROR, "No JSON request")
return None, None, None
- if type(o) != list and len(o) not in range(1,4):
+ if not isinstance(o, basestring) and type(o) != list and len(o) not in range(1, 4):
self.log.debug("Invalid Api call: %s" % o)
self.send_result(req, self.ERROR, "Invalid Api call")
return None, None, None
- if len(o) == 1: # arguments omitted
+
+ # called only with name, no args
+ if isinstance(o, basestring):
+ return o, [], {}
+ elif len(o) == 1: # arguments omitted
return o[0], [], {}
elif len(o) == 2:
func, args = o
@@ -85,5 +114,20 @@ class AbstractHandler:
else:
return tuple(o)
+ def do_login(self, req, args, kwargs):
+ user = self.api.checkAuth(*args, **kwargs)
+ if user:
+ req.api = self.api.withUserContext(user.uid)
+ return self.send_result(req, self.OK, True)
+ else:
+ return self.send_result(req, self.FORBIDDEN, "Forbidden")
+
+ def do_logout(self, req):
+ req.api = None
+ return self.send_result(req, self.OK, True)
+
def send_result(self, req, code, result):
- return send_message(req, dumps([code, result])) \ No newline at end of file
+ return send_message(req, dumps([code, result]))
+
+ def send(self, req, obj):
+ return send_message(req, dumps(obj)) \ No newline at end of file
diff --git a/module/remote/wsbackend/ApiHandler.py b/module/remote/wsbackend/ApiHandler.py
index eec546d47..e985e10be 100644
--- a/module/remote/wsbackend/ApiHandler.py
+++ b/module/remote/wsbackend/ApiHandler.py
@@ -55,18 +55,9 @@ class ApiHandler(AbstractHandler):
return # handle_call already sent the result
if func == 'login':
- user = self.api.checkAuth(*args, **kwargs)
- if user:
- req.api = self.api.withUserContext(user.uid)
- return self.send_result(req, self.OK, True)
-
- else:
- return self.send_result(req, self.OK, False)
-
+ return self.do_login(req, args, kwargs)
elif func == 'logout':
- req.api = None
- return self.send_result(req, self.OK, True)
-
+ return self.do_logout(req)
else:
if not req.api:
return self.send_result(req, self.FORBIDDEN, "Forbidden")
diff --git a/module/remote/wsbackend/AsyncHandler.py b/module/remote/wsbackend/AsyncHandler.py
index a8382a211..2f9b43ad2 100644
--- a/module/remote/wsbackend/AsyncHandler.py
+++ b/module/remote/wsbackend/AsyncHandler.py
@@ -16,7 +16,7 @@
# @author: RaNaN
###############################################################################
-from Queue import Queue
+from Queue import Queue, Empty
from threading import Lock
from mod_pywebsocket.msgutil import receive_message
@@ -34,13 +34,13 @@ class AsyncHandler(AbstractHandler):
Progress information are continuous and will be pushed in a fixed interval when available.
After connect you have to login and can set the interval by sending the json command ["setInterval", xy].
- To start receiving updates call "start", afterwards no more incoming messages will be accept!
+ To start receiving updates call "start", afterwards no more incoming messages will be accepted!
"""
PATH = "/async"
COMMAND = "start"
- PROGRESS_INTERVAL = 1
+ PROGRESS_INTERVAL = 2
STATUS_INTERVAL = 60
def __init__(self, api):
@@ -57,7 +57,10 @@ class AsyncHandler(AbstractHandler):
@lock
def on_close(self, req):
- self.clients.remove(req)
+ try:
+ self.clients.remove(req)
+ except ValueError: # ignore when not in list
+ pass
@lock
def add_event(self, event):
@@ -86,21 +89,15 @@ class AsyncHandler(AbstractHandler):
return # Result was already sent
if func == 'login':
- user = self.api.checkAuth(*args, **kwargs)
- if user:
- req.api = self.api.withUserContext(user.uid)
- return self.send_result(req, self.OK, True)
-
- else:
- return self.send_result(req, self.FORBIDDEN, "Forbidden")
+ return self.do_login(req, args, kwargs)
elif func == 'logout':
- req.api = None
- return self.send_result(req, self.OK, True)
+ return self.do_logout(req)
else:
if not req.api:
return self.send_result(req, self.FORBIDDEN, "Forbidden")
+
if func == "setInterval":
req.interval = args[0]
elif func == self.COMMAND:
@@ -109,4 +106,14 @@ class AsyncHandler(AbstractHandler):
def mode_running(self, req):
""" Listen for events, closes socket when returning True """
- self.send_result(req, "update", "test") \ No newline at end of file
+ try:
+ ev = req.queue.get(True, req.interval)
+ self.send(req, ev)
+
+ except Empty:
+ # TODO: server status is not enough
+ # modify core api to include progress? think of other needed information to show
+ # notifications
+
+ self.send(req, self.api.getServerStatus())
+ self.send(req, self.api.getProgressInfo()) \ No newline at end of file