Getting an improved version of the shared session system vaguely in shape.
This commit is contained in:
parent
a31441b3ce
commit
eebd41f46d
11 changed files with 143 additions and 130 deletions
|
|
@ -27,7 +27,6 @@ from evennia.players.models import PlayerDB
|
||||||
from evennia.utils.logger import log_err
|
from evennia.utils.logger import log_err
|
||||||
from evennia.utils.utils import to_str, to_unicode
|
from evennia.utils.utils import to_str, to_unicode
|
||||||
|
|
||||||
# django browser sessions
|
|
||||||
BrowserSessionStore = importlib.import_module(settings.SESSION_ENGINE).SessionStore
|
BrowserSessionStore = importlib.import_module(settings.SESSION_ENGINE).SessionStore
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ class PortalSessionHandler(SessionHandler):
|
||||||
sessdata = dict((key, val) for key, val in sessdata.items() if key in ("protocol_key",
|
sessdata = dict((key, val) for key, val in sessdata.items() if key in ("protocol_key",
|
||||||
"address",
|
"address",
|
||||||
"sessid",
|
"sessid",
|
||||||
"suid",
|
"csessid",
|
||||||
"conn_time",
|
"conn_time",
|
||||||
"protocol_flags",
|
"protocol_flags",
|
||||||
"server_data",))
|
"server_data",))
|
||||||
|
|
@ -274,20 +274,20 @@ class PortalSessionHandler(SessionHandler):
|
||||||
"""
|
"""
|
||||||
return len(self.get_sessions(include_unloggedin=include_unloggedin))
|
return len(self.get_sessions(include_unloggedin=include_unloggedin))
|
||||||
|
|
||||||
def session_from_suid(self, suid):
|
def session_from_csessid(self, csessid):
|
||||||
"""
|
"""
|
||||||
Given a session id, retrieve the session (this is primarily
|
Given a session id, retrieve the session (this is primarily
|
||||||
intended to be called by web clients)
|
intended to be called by web clients)
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
suid (int): Session id.
|
csessid (int): Session id.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
session (list): The matching session, if found.
|
session (list): The matching session, if found.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return [sess for sess in self.get_sessions(include_unloggedin=True)
|
return [sess for sess in self.get_sessions(include_unloggedin=True)
|
||||||
if hasattr(sess, 'suid') and sess.suid == suid]
|
if hasattr(sess, 'csessid') and sess.csessid == csessid]
|
||||||
|
|
||||||
def announce_all(self, message):
|
def announce_all(self, message):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -32,11 +32,12 @@ import json
|
||||||
from twisted.internet.protocol import Protocol
|
from twisted.internet.protocol import Protocol
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from evennia.server.session import Session
|
from evennia.server.session import Session
|
||||||
from evennia.utils.utils import to_str
|
from evennia.utils.utils import to_str, mod_import
|
||||||
from evennia.utils.ansi import parse_ansi
|
from evennia.utils.ansi import parse_ansi
|
||||||
from evennia.utils.text2html import parse_html
|
from evennia.utils.text2html import parse_html
|
||||||
|
|
||||||
_RE_SCREENREADER_REGEX = re.compile(r"%s" % settings.SCREENREADER_REGEX_STRIP, re.DOTALL + re.MULTILINE)
|
_RE_SCREENREADER_REGEX = re.compile(r"%s" % settings.SCREENREADER_REGEX_STRIP, re.DOTALL + re.MULTILINE)
|
||||||
|
_CLIENT_SESSIONS = mod_import(settings.SESSION_ENGINE).SessionStore
|
||||||
|
|
||||||
|
|
||||||
class WebSocketClient(Protocol, Session):
|
class WebSocketClient(Protocol, Session):
|
||||||
|
|
@ -52,6 +53,8 @@ class WebSocketClient(Protocol, Session):
|
||||||
self.transport.validationMade = self.validationMade
|
self.transport.validationMade = self.validationMade
|
||||||
client_address = self.transport.client
|
client_address = self.transport.client
|
||||||
client_address = client_address[0] if client_address else None
|
client_address = client_address[0] if client_address else None
|
||||||
|
print ("connectionMade: webclient address", client_address, self.transport.client, self.transport.client.__dict__, self.transport.__dict__)
|
||||||
|
|
||||||
self.init_session("websocket", client_address, self.factory.sessionhandler)
|
self.init_session("websocket", client_address, self.factory.sessionhandler)
|
||||||
# watch for dead links
|
# watch for dead links
|
||||||
self.transport.setTcpKeepAlive(1)
|
self.transport.setTcpKeepAlive(1)
|
||||||
|
|
@ -123,15 +126,36 @@ class WebSocketClient(Protocol, Session):
|
||||||
kwargs (any): Options from protocol.
|
kwargs (any): Options from protocol.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
The websocket client can send the
|
At initilization, the client will send the special
|
||||||
"websocket_close" command to report
|
'csessid' command to identify its browser session hash
|
||||||
that the client has been closed and
|
with the Evennia side.
|
||||||
that the session should be disconnected.
|
|
||||||
|
The websocket client will also pass 'websocket_close' command
|
||||||
|
to report that the client has been closed and that the
|
||||||
|
session should be disconnected.
|
||||||
|
|
||||||
|
Both those commands are parsed and extracted already at
|
||||||
|
this point.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if "csessid" in kwargs and self.csessid is None:
|
||||||
|
# only allow to change csessid on the very first connect
|
||||||
|
# - this is a safety measure to avoid a clself.transport.client.__dict__, ient to manually
|
||||||
|
# change its csessid later.
|
||||||
|
self.csessid = kwargs.pop("csessid")
|
||||||
|
csession = _CLIENT_SESSIONS(session_key=self.csessid)
|
||||||
|
uid = csession and csession.get("logged_in", False)
|
||||||
|
if uid:
|
||||||
|
# the browser session is already logged in.
|
||||||
|
self.uid = uid
|
||||||
|
self.logged_in = True
|
||||||
|
return
|
||||||
|
|
||||||
if "websocket_close" in kwargs:
|
if "websocket_close" in kwargs:
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
return
|
return
|
||||||
|
|
||||||
self.sessionhandler.data_in(self, **kwargs)
|
self.sessionhandler.data_in(self, **kwargs)
|
||||||
|
|
||||||
def data_out(self, **kwargs):
|
def data_out(self, **kwargs):
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import json
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from time import time
|
from time import time
|
||||||
from hashlib import md5
|
|
||||||
from twisted.web import server, resource
|
from twisted.web import server, resource
|
||||||
from twisted.internet.task import LoopingCall
|
from twisted.internet.task import LoopingCall
|
||||||
from django.utils.functional import Promise
|
from django.utils.functional import Promise
|
||||||
|
|
@ -71,10 +70,10 @@ class WebClient(resource.Resource):
|
||||||
self.last_alive = {}
|
self.last_alive = {}
|
||||||
self.keep_alive = None
|
self.keep_alive = None
|
||||||
|
|
||||||
def _responseFailed(self, failure, suid, request):
|
def _responseFailed(self, failure, csessid, request):
|
||||||
"callback if a request is lost/timed out"
|
"callback if a request is lost/timed out"
|
||||||
try:
|
try:
|
||||||
del self.requests[suid]
|
del self.requests[csessid]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
@ -84,62 +83,62 @@ class WebClient(resource.Resource):
|
||||||
"""
|
"""
|
||||||
now = time()
|
now = time()
|
||||||
to_remove = []
|
to_remove = []
|
||||||
keep_alives = ((suid, remove) for suid, (t, remove)
|
keep_alives = ((csessid, remove) for csessid, (t, remove)
|
||||||
in self.last_alive.iteritems() if now - t > _KEEPALIVE)
|
in self.last_alive.iteritems() if now - t > _KEEPALIVE)
|
||||||
for suid, remove in keep_alives:
|
for csessid, remove in keep_alives:
|
||||||
if remove:
|
if remove:
|
||||||
# keepalive timeout. Line is dead.
|
# keepalive timeout. Line is dead.
|
||||||
to_remove.append(suid)
|
to_remove.append(csessid)
|
||||||
else:
|
else:
|
||||||
# normal timeout - send keepalive
|
# normal timeout - send keepalive
|
||||||
self.last_alive[suid] = (now, True)
|
self.last_alive[csessid] = (now, True)
|
||||||
self.lineSend(suid, ["ajax_keepalive", [], {}])
|
self.lineSend(csessid, ["ajax_keepalive", [], {}])
|
||||||
# remove timed-out sessions
|
# remove timed-out sessions
|
||||||
for suid in to_remove:
|
for csessid in to_remove:
|
||||||
sess = self.sessionhandler.session_from_suid(suid)
|
sess = self.sessionhandler.sessions_from_csessid(csessid)
|
||||||
if sess:
|
if sess:
|
||||||
sess[0].disconnect()
|
sess[0].disconnect()
|
||||||
self.last_alive.pop(suid, None)
|
self.last_alive.pop(csessid, None)
|
||||||
if not self.last_alive:
|
if not self.last_alive:
|
||||||
# no more ajax clients. Stop the keepalive
|
# no more ajax clients. Stop the keepalive
|
||||||
self.keep_alive.stop()
|
self.keep_alive.stop()
|
||||||
self.keep_alive = None
|
self.keep_alive = None
|
||||||
|
|
||||||
def lineSend(self, suid, data):
|
def lineSend(self, csessid, data):
|
||||||
"""
|
"""
|
||||||
This adds the data to the buffer and/or sends it to the client
|
This adds the data to the buffer and/or sends it to the client
|
||||||
as soon as possible.
|
as soon as possible.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
suid (int): Session id.
|
csessid (int): Session id.
|
||||||
data (list): A send structure [cmdname, [args], {kwargs}].
|
data (list): A send structure [cmdname, [args], {kwargs}].
|
||||||
|
|
||||||
"""
|
"""
|
||||||
request = self.requests.get(suid)
|
request = self.requests.get(csessid)
|
||||||
if request:
|
if request:
|
||||||
# we have a request waiting. Return immediately.
|
# we have a request waiting. Return immediately.
|
||||||
request.write(jsonify(data))
|
request.write(jsonify(data))
|
||||||
request.finish()
|
request.finish()
|
||||||
del self.requests[suid]
|
del self.requests[csessid]
|
||||||
else:
|
else:
|
||||||
# no waiting request. Store data in buffer
|
# no waiting request. Store data in buffer
|
||||||
dataentries = self.databuffer.get(suid, [])
|
dataentries = self.databuffer.get(csessid, [])
|
||||||
dataentries.append(jsonify(data))
|
dataentries.append(jsonify(data))
|
||||||
self.databuffer[suid] = dataentries
|
self.databuffer[csessid] = dataentries
|
||||||
|
|
||||||
def client_disconnect(self, suid):
|
def client_disconnect(self, csessid):
|
||||||
"""
|
"""
|
||||||
Disconnect session with given suid.
|
Disconnect session with given csessid.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
suid (int): Session id.
|
csessid (int): Session id.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if suid in self.requests:
|
if csessid in self.requests:
|
||||||
self.requests[suid].finish()
|
self.requests[csessid].finish()
|
||||||
del self.requests[suid]
|
del self.requests[csessid]
|
||||||
if suid in self.databuffer:
|
if csessid in self.databuffer:
|
||||||
del self.databuffer[suid]
|
del self.databuffer[csessid]
|
||||||
|
|
||||||
def mode_init(self, request):
|
def mode_init(self, request):
|
||||||
"""
|
"""
|
||||||
|
|
@ -150,38 +149,32 @@ class WebClient(resource.Resource):
|
||||||
request (Request): Incoming request.
|
request (Request): Incoming request.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
suid = request.args.get('suid', ['0'])[0]
|
csessid = request.args.get('csessid')
|
||||||
|
|
||||||
remote_addr = request.getClientIP()
|
remote_addr = request.getClientIP()
|
||||||
host_string = "%s (%s:%s)" % (_SERVERNAME, request.getRequestHostname(), request.getHost().port)
|
host_string = "%s (%s:%s)" % (_SERVERNAME, request.getRequestHostname(), request.getHost().port)
|
||||||
if suid == '0':
|
|
||||||
# creating a unique id hash string
|
|
||||||
suid = md5(str(time())).hexdigest()
|
|
||||||
self.databuffer[suid] = []
|
|
||||||
|
|
||||||
sess = WebClientSession()
|
sess = WebClientSession()
|
||||||
sess.client = self
|
sess.client = self
|
||||||
sess.init_session("ajax/comet", remote_addr, self.sessionhandler)
|
sess.init_session("ajax/comet", remote_addr, self.sessionhandler)
|
||||||
sess.suid = suid
|
sess.csessid = csessid
|
||||||
sess.sessionhandler.connect(sess)
|
sess.sessionhandler.connect(sess)
|
||||||
|
|
||||||
self.last_alive[suid] = (time(), False)
|
self.last_alive[csessid] = (time(), False)
|
||||||
if not self.keep_alive:
|
if not self.keep_alive:
|
||||||
# the keepalive is not running; start it.
|
# the keepalive is not running; start it.
|
||||||
self.keep_alive = LoopingCall(self._keepalive)
|
self.keep_alive = LoopingCall(self._keepalive)
|
||||||
self.keep_alive.start(_KEEPALIVE, now=False)
|
self.keep_alive.start(_KEEPALIVE, now=False)
|
||||||
|
|
||||||
return jsonify({'msg': host_string, 'suid': suid})
|
return jsonify({'msg': host_string, 'csessid': csessid})
|
||||||
|
|
||||||
def mode_keepalive(self, request):
|
def mode_keepalive(self, request):
|
||||||
"""
|
"""
|
||||||
This is called by render_POST when the
|
This is called by render_POST when the
|
||||||
client is replying to the keepalive.
|
client is replying to the keepalive.
|
||||||
"""
|
"""
|
||||||
suid = request.args.get('suid', ['0'])[0]
|
csessid = request.args.get('csessid')[0]
|
||||||
if suid == '0':
|
self.last_alive[csessid] = (time(), False)
|
||||||
return '""'
|
|
||||||
self.last_alive[suid] = (time(), False)
|
|
||||||
return '""'
|
return '""'
|
||||||
|
|
||||||
def mode_input(self, request):
|
def mode_input(self, request):
|
||||||
|
|
@ -193,12 +186,10 @@ class WebClient(resource.Resource):
|
||||||
request (Request): Incoming request.
|
request (Request): Incoming request.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
suid = request.args.get('suid', ['0'])[0]
|
csessid = request.args.get('csessid')[0]
|
||||||
if suid == '0':
|
|
||||||
return '""'
|
|
||||||
|
|
||||||
self.last_alive[suid] = (time(), False)
|
self.last_alive[csessid] = (time(), False)
|
||||||
sess = self.sessionhandler.session_from_suid(suid)
|
sess = self.sessionhandler.session_from_csessid(csessid)
|
||||||
if sess:
|
if sess:
|
||||||
sess = sess[0]
|
sess = sess[0]
|
||||||
cmdarray = json.loads(request.args.get('data')[0])
|
cmdarray = json.loads(request.args.get('data')[0])
|
||||||
|
|
@ -216,18 +207,16 @@ class WebClient(resource.Resource):
|
||||||
request (Request): Incoming request.
|
request (Request): Incoming request.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
suid = request.args.get('suid', ['0'])[0]
|
csessid = request.args.get('csessid')[0]
|
||||||
if suid == '0':
|
self.last_alive[csessid] = (time(), False)
|
||||||
return '""'
|
|
||||||
self.last_alive[suid] = (time(), False)
|
|
||||||
|
|
||||||
dataentries = self.databuffer.get(suid, [])
|
dataentries = self.databuffer.get(csessid, [])
|
||||||
if dataentries:
|
if dataentries:
|
||||||
return dataentries.pop(0)
|
return dataentries.pop(0)
|
||||||
request.notifyFinish().addErrback(self._responseFailed, suid, request)
|
request.notifyFinish().addErrback(self._responseFailed, csessid, request)
|
||||||
if suid in self.requests:
|
if csessid in self.requests:
|
||||||
self.requests[suid].finish() # Clear any stale request.
|
self.requests[csessid].finish() # Clear any stale request.
|
||||||
self.requests[suid] = request
|
self.requests[csessid] = request
|
||||||
return server.NOT_DONE_YET
|
return server.NOT_DONE_YET
|
||||||
|
|
||||||
def mode_close(self, request):
|
def mode_close(self, request):
|
||||||
|
|
@ -239,16 +228,13 @@ class WebClient(resource.Resource):
|
||||||
request (Request): Incoming request.
|
request (Request): Incoming request.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
suid = request.args.get('suid', ['0'])[0]
|
csessid = request.args.get('csessid')[0]
|
||||||
if suid == '0':
|
try:
|
||||||
self.client_disconnect(suid)
|
sess = self.sessionhandler.session_from_csessid(csessid)[0]
|
||||||
else:
|
sess.sessionhandler.disconnect(sess)
|
||||||
try:
|
except IndexError:
|
||||||
sess = self.sessionhandler.session_from_suid(suid)[0]
|
self.client_disconnect(csessid)
|
||||||
sess.sessionhandler.disconnect(sess)
|
pass
|
||||||
except IndexError:
|
|
||||||
self.client_disconnect(suid)
|
|
||||||
pass
|
|
||||||
return '""'
|
return '""'
|
||||||
|
|
||||||
def render_POST(self, request):
|
def render_POST(self, request):
|
||||||
|
|
@ -306,8 +292,8 @@ class WebClientSession(session.Session):
|
||||||
Args:
|
Args:
|
||||||
reason (str): Motivation for the disconnect.
|
reason (str): Motivation for the disconnect.
|
||||||
"""
|
"""
|
||||||
self.client.lineSend(self.suid, ["connection_close", [reason], {}])
|
self.client.lineSend(self.csessid, ["connection_close", [reason], {}])
|
||||||
self.client.client_disconnect(self.suid)
|
self.client.client_disconnect(self.csessid)
|
||||||
self.sessionhandler.disconnect(self)
|
self.sessionhandler.disconnect(self)
|
||||||
|
|
||||||
def data_out(self, **kwargs):
|
def data_out(self, **kwargs):
|
||||||
|
|
@ -363,7 +349,7 @@ class WebClientSession(session.Session):
|
||||||
args[0] = parse_html(text, strip_ansi=nomarkup)
|
args[0] = parse_html(text, strip_ansi=nomarkup)
|
||||||
|
|
||||||
# send to client on required form [cmdname, args, kwargs]
|
# send to client on required form [cmdname, args, kwargs]
|
||||||
self.client.lineSend(self.suid, [cmd, args, kwargs])
|
self.client.lineSend(self.csessid, [cmd, args, kwargs])
|
||||||
|
|
||||||
def send_prompt(self, *args, **kwargs):
|
def send_prompt(self, *args, **kwargs):
|
||||||
kwargs["options"].update({"send_prompt": True})
|
kwargs["options"].update({"send_prompt": True})
|
||||||
|
|
@ -385,4 +371,4 @@ class WebClientSession(session.Session):
|
||||||
"""
|
"""
|
||||||
if not cmdname == "options":
|
if not cmdname == "options":
|
||||||
#print "ajax.send_default", cmdname, args, kwargs
|
#print "ajax.send_default", cmdname, args, kwargs
|
||||||
self.client.lineSend(self.suid, [cmdname, args, kwargs])
|
self.client.lineSend(self.csessid, [cmdname, args, kwargs])
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ from evennia.utils.utils import make_iter, lazy_property
|
||||||
from evennia.commands.cmdsethandler import CmdSetHandler
|
from evennia.commands.cmdsethandler import CmdSetHandler
|
||||||
from evennia.server.session import Session
|
from evennia.server.session import Session
|
||||||
|
|
||||||
BrowserSessionStore = importlib.import_module(settings.SESSION_ENGINE).SessionStore
|
ClientSessionStore = importlib.import_module(settings.SESSION_ENGINE).SessionStore
|
||||||
|
|
||||||
_GA = object.__getattribute__
|
_GA = object.__getattribute__
|
||||||
_SA = object.__setattr__
|
_SA = object.__setattr__
|
||||||
|
|
@ -163,7 +163,6 @@ class ServerSession(Session):
|
||||||
"Initiate to avoid AttributeErrors down the line"
|
"Initiate to avoid AttributeErrors down the line"
|
||||||
self.puppet = None
|
self.puppet = None
|
||||||
self.player = None
|
self.player = None
|
||||||
self.browserid = None
|
|
||||||
self.cmdset_storage_string = ""
|
self.cmdset_storage_string = ""
|
||||||
self.cmdset = CmdSetHandler(self, True)
|
self.cmdset = CmdSetHandler(self, True)
|
||||||
|
|
||||||
|
|
@ -224,12 +223,14 @@ class ServerSession(Session):
|
||||||
self.puppet = None
|
self.puppet = None
|
||||||
self.cmdset_storage = settings.CMDSET_SESSION
|
self.cmdset_storage = settings.CMDSET_SESSION
|
||||||
|
|
||||||
if self.browserid:
|
if self.csessid:
|
||||||
# this is only set by a webclient inputcommand.
|
# An existing client sessid is registered, thus a matching
|
||||||
bsession = BrowserSessionStore(session_key=self.browserid)
|
# Client Session must also exist. Update it so the website
|
||||||
bsession["logged_in"] = player.id # this also saves the bsession
|
# can also see we are logged in.
|
||||||
bsession.save()
|
csession = ClientSessionStore(session_key=self.browserid)
|
||||||
print ("serversession.login:", bsession.session_key)
|
csession["logged_in"] = player.id
|
||||||
|
csession.save()
|
||||||
|
print ("serversession.login:", csession.session_key)
|
||||||
|
|
||||||
# Update account's last login time.
|
# Update account's last login time.
|
||||||
self.player.last_login = timezone.now()
|
self.player.last_login = timezone.now()
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ class Session(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# names of attributes that should be affected by syncing.
|
# names of attributes that should be affected by syncing.
|
||||||
_attrs_to_sync = ('protocol_key', 'address', 'suid', 'sessid', 'uid',
|
_attrs_to_sync = ('protocol_key', 'address', 'suid', 'sessid', 'uid', 'csessid',
|
||||||
'uname', 'logged_in', 'puid',
|
'uname', 'logged_in', 'puid',
|
||||||
'conn_time', 'cmd_last', 'cmd_last_visible', 'cmd_total',
|
'conn_time', 'cmd_last', 'cmd_last_visible', 'cmd_total',
|
||||||
'protocol_flags', 'server_data', "cmdset_storage_string")
|
'protocol_flags', 'server_data', "cmdset_storage_string")
|
||||||
|
|
@ -64,6 +64,8 @@ class Session(object):
|
||||||
|
|
||||||
# unique id for this session
|
# unique id for this session
|
||||||
self.sessid = 0 # no sessid yet
|
self.sessid = 0 # no sessid yet
|
||||||
|
# client session id, if given by the client
|
||||||
|
self.csessid = None
|
||||||
# database id for the user connected to this session
|
# database id for the user connected to this session
|
||||||
self.uid = None
|
self.uid = None
|
||||||
# user name, for easier tracking of sessions
|
# user name, for easier tracking of sessions
|
||||||
|
|
|
||||||
|
|
@ -593,16 +593,17 @@ class ServerSessionHandler(SessionHandler):
|
||||||
return sessions[0] if len(sessions) == 1 else sessions
|
return sessions[0] if len(sessions) == 1 else sessions
|
||||||
sessions_from_character = sessions_from_puppet
|
sessions_from_character = sessions_from_puppet
|
||||||
|
|
||||||
def sessions_from_browserid(self, browserid):
|
def sessions_from_csessid(self, csessid):
|
||||||
"""
|
"""
|
||||||
Given a browserid, return all sessions having this id.
|
Given a cliend identification hash (for session types that offer them) return all sessions with
|
||||||
|
a matching hash.
|
||||||
|
|
||||||
Args
|
Args
|
||||||
browserid (str): The browserid hash
|
csessid (str): The session hash
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return [session for session in self.values()
|
return [session for session in self.values()
|
||||||
if session.browserid and session.browserid == browserid]
|
if session.csessid and session.csessid == csessid]
|
||||||
|
|
||||||
def announce_all(self, message):
|
def announce_all(self, message):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -217,20 +217,21 @@ An "emitter" object must have a function
|
||||||
var ever_open = false;
|
var ever_open = false;
|
||||||
var websocket = null;
|
var websocket = null;
|
||||||
var wsurl = window.wsurl;
|
var wsurl = window.wsurl;
|
||||||
|
var csessid = window.csessid;
|
||||||
|
|
||||||
var connect = function() {
|
var connect = function() {
|
||||||
if (websocket && websocket.readyState != websocket.CLOSED) {
|
if (websocket && websocket.readyState != websocket.CLOSED) {
|
||||||
// No-op if a connection is already open.
|
// No-op if a connection is already open.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
websocket = new WebSocket(wsurl);
|
websocket = new WebSocket(wsurl + '?' + csessid);
|
||||||
|
|
||||||
// Handle Websocket open event
|
// Handle Websocket open event
|
||||||
websocket.onopen = function (event) {
|
websocket.onopen = function (event) {
|
||||||
open = true;
|
open = true;
|
||||||
ever_open = true;
|
ever_open = true;
|
||||||
Evennia.emit('connection_open', ["websocket"], event);
|
Evennia.emit('connection_open', ["websocket"], event);
|
||||||
Evennia.msg('browser_sessid', [browser_sessid], {});
|
Evennia.msg('csessid', [csessid], {});
|
||||||
};
|
};
|
||||||
// Handle Websocket close event
|
// Handle Websocket close event
|
||||||
websocket.onclose = function (event) {
|
websocket.onclose = function (event) {
|
||||||
|
|
@ -295,22 +296,22 @@ An "emitter" object must have a function
|
||||||
//
|
//
|
||||||
var AjaxCometConnection = function() {
|
var AjaxCometConnection = function() {
|
||||||
log("Trying ajax ...");
|
log("Trying ajax ...");
|
||||||
var client_hash = '0';
|
var open = false;
|
||||||
var stop_polling = false;
|
var stop_polling = false;
|
||||||
var is_closing = false;
|
var is_closing = false;
|
||||||
|
var csessid = window.csessid;
|
||||||
|
|
||||||
// initialize connection and get hash
|
// initialize connection, send csessid
|
||||||
var init = function() {
|
var init = function() {
|
||||||
$.ajax({type: "POST", url: "/webclientdata",
|
$.ajax({type: "POST", url: "/webclientdata",
|
||||||
async: true, cache: false, timeout: 50000,
|
async: true, cache: false, timeout: 50000,
|
||||||
datatype: "json",
|
datatype: "json",
|
||||||
data: {mode: "init", suid: client_hash},
|
data: {mode: "init", csessid: csessid},
|
||||||
|
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
|
open = true;
|
||||||
data = JSON.parse(data);
|
data = JSON.parse(data);
|
||||||
log ("connection_open", ["AJAX/COMET"], data);
|
log ("connection_open", ["AJAX/COMET"], data);
|
||||||
Evennia.msg("browser_sessid", [browser_sessid], {});
|
|
||||||
client_hash = data.suid;
|
|
||||||
stop_polling = false;
|
stop_polling = false;
|
||||||
poll();
|
poll();
|
||||||
},
|
},
|
||||||
|
|
@ -331,7 +332,7 @@ An "emitter" object must have a function
|
||||||
async: true, cache: false, timeout: 30000,
|
async: true, cache: false, timeout: 30000,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
data: {mode: inmode == null ? 'input' : inmode,
|
data: {mode: inmode == null ? 'input' : inmode,
|
||||||
data: JSON.stringify(data), 'suid': client_hash},
|
data: JSON.stringify(data), 'csessid': csessid},
|
||||||
success: function(req, stat, err) {
|
success: function(req, stat, err) {
|
||||||
stop_polling = false;
|
stop_polling = false;
|
||||||
},
|
},
|
||||||
|
|
@ -351,7 +352,7 @@ An "emitter" object must have a function
|
||||||
$.ajax({type: "POST", url: "/webclientdata",
|
$.ajax({type: "POST", url: "/webclientdata",
|
||||||
async: true, cache: false, timeout: 60000,
|
async: true, cache: false, timeout: 60000,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
data: {mode: 'receive', 'suid': client_hash},
|
data: {mode: 'receive', 'csessid': csessid},
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
// log("ajax data received:", data);
|
// log("ajax data received:", data);
|
||||||
if (data[0] === "ajax_keepalive") {
|
if (data[0] === "ajax_keepalive") {
|
||||||
|
|
@ -393,7 +394,7 @@ An "emitter" object must have a function
|
||||||
|
|
||||||
// Kill the connection and do house cleaning on the server.
|
// Kill the connection and do house cleaning on the server.
|
||||||
var close = function webclient_close(){
|
var close = function webclient_close(){
|
||||||
if (is_closing || client_hash === '0') {
|
if (is_closing || !(open)) {
|
||||||
// Already closed or trying to close.
|
// Already closed or trying to close.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -406,11 +407,11 @@ An "emitter" object must have a function
|
||||||
cache: false,
|
cache: false,
|
||||||
timeout: 50000,
|
timeout: 50000,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
data: {mode: 'close', 'suid': client_hash},
|
data: {mode: 'close', 'csessid': csessid},
|
||||||
|
|
||||||
success: function(data){
|
success: function(data){
|
||||||
is_closing = false;
|
is_closing = false;
|
||||||
client_hash = '0';
|
open = false;
|
||||||
Evennia.emit("connection_close", ["AJAX/COMET"], {});
|
Evennia.emit("connection_close", ["AJAX/COMET"], {});
|
||||||
log("AJAX/COMET connection closed cleanly.")
|
log("AJAX/COMET connection closed cleanly.")
|
||||||
},
|
},
|
||||||
|
|
@ -419,13 +420,13 @@ An "emitter" object must have a function
|
||||||
Evennia.emit("connection_error", ["AJAX/COMET close error"], err);
|
Evennia.emit("connection_error", ["AJAX/COMET close error"], err);
|
||||||
// Also emit a close event so that the COMET API mirrors the websocket API.
|
// Also emit a close event so that the COMET API mirrors the websocket API.
|
||||||
Evennia.emit("connection_close", ["AJAX/COMET close unclean"], err);
|
Evennia.emit("connection_close", ["AJAX/COMET close unclean"], err);
|
||||||
client_hash = '0';
|
open = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var isOpen = function () {
|
var isOpen = function () {
|
||||||
return !(is_closing || client_hash === '0');
|
return !(is_closing || !(open));
|
||||||
}
|
}
|
||||||
|
|
||||||
// init
|
// init
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,9 @@ JQuery available.
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if browser_sessid %}
|
{% if browser_sessid %}
|
||||||
var browser_sessid = "{{browser_sessid}}";
|
var csessid = "{{browser_sessid}}";
|
||||||
{% else %}
|
{% else %}
|
||||||
var browser_sessid = false;
|
var csessid = false;
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if websocket_url %}
|
{% if websocket_url %}
|
||||||
|
|
|
||||||
|
|
@ -18,27 +18,26 @@ def webclient(request):
|
||||||
"""
|
"""
|
||||||
print ("webclient session:", request.session.session_key, request.user, request.user.is_authenticated())
|
print ("webclient session:", request.session.session_key, request.user, request.user.is_authenticated())
|
||||||
|
|
||||||
browser_session = request.session
|
csession = request.session
|
||||||
browserid = request.session.session_key
|
csessid = request.session.session_key
|
||||||
player = request.user
|
player = request.user
|
||||||
# check if user has authenticated to website
|
# check if user has authenticated to website
|
||||||
if player.is_authenticated():
|
if player.is_authenticated():
|
||||||
print ("webclient: player auth, trying to connect sessions")
|
print ("webclient: player auth, trying to connect sessions")
|
||||||
# Try to login all the player's webclient sessions - only
|
# Try to login all the player's webclient sessions - only
|
||||||
# unloggedin ones will actually be logged in.
|
# unloggedin ones will actually be logged in.
|
||||||
for session in SESSION_HANDLER.sessions_from_browserid(browserid):
|
for session in SESSION_HANDLER.sessions_from_csessid(csessid):
|
||||||
print ("session to connect:", session)
|
print ("session to connect:", session)
|
||||||
if session.protocol_key in ("websocket", "ajax/comet"):
|
if session.protocol_key in ("websocket", "ajax/comet"):
|
||||||
SESSION_HANDLER.login(session, player)
|
SESSION_HANDLER.login(session, player)
|
||||||
session.browserid = browser_session.session_key
|
csession["logged_in"] = player.id
|
||||||
browser_session["logged_in"] = player.id
|
elif csession.get("logged_in"):
|
||||||
elif browser_session.get("logged_in"):
|
|
||||||
# The webclient has previously registered a login to this browser_session
|
# The webclient has previously registered a login to this browser_session
|
||||||
print ("webclient: browser_session logged in, trying to login")
|
print ("webclient: browser_session logged in, trying to login")
|
||||||
player = PlayerDB.objects.get(browser_session.get("uid"))
|
player = PlayerDB.objects.get(csession.get("logged_in"))
|
||||||
login(player, request)
|
login(player, request)
|
||||||
else:
|
else:
|
||||||
browser_session["logged_in"] = False
|
csession["logged_in"] = False
|
||||||
|
|
||||||
# make sure to store the browser session's hash so the webclient can get to it
|
# make sure to store the browser session's hash so the webclient can get to it
|
||||||
pagevars = {'browser_sessid': request.session.session_key}
|
pagevars = {'browser_sessid': request.session.session_key}
|
||||||
|
|
|
||||||
|
|
@ -26,27 +26,27 @@ def page_index(request):
|
||||||
|
|
||||||
# handle webclient-website shared login
|
# handle webclient-website shared login
|
||||||
|
|
||||||
browser_session = request.session
|
csession = request.session
|
||||||
browserid = request.session.session_key
|
csessid = request.session.session_key
|
||||||
player = request.user
|
player = request.user
|
||||||
# check if user has authenticated to website
|
# check if user has authenticated to website
|
||||||
if player.is_authenticated():
|
if player.is_authenticated():
|
||||||
# Try to login all the player's webclient sessions - only
|
# Try to login all the player's webclient sessions - only
|
||||||
# unloggedin ones will actually be logged in.
|
# unloggedin ones will actually be logged in.
|
||||||
print "website: player auth, trying to connect sessions"
|
print "website: player auth, trying to connect sessions"
|
||||||
for session in SESSION_HANDLER.sessions_from_browserid(browserid):
|
for session in SESSION_HANDLER.sessions_from_csessid(csessid):
|
||||||
print "session to connect:", session
|
print "session to connect:", session
|
||||||
if session.protocol_key in ("websocket", "ajax/comet"):
|
if session.protocol_key in ("websocket", "ajax/comet"):
|
||||||
SESSION_HANDLER.login(session, player)
|
SESSION_HANDLER.login(session, player)
|
||||||
session.browserid = browser_session.session_key
|
session.csessid = csession.session_key
|
||||||
browser_session["logged_in"] = player.id
|
csession["logged_in"] = player.id
|
||||||
elif browser_session.get("logged_in"):
|
elif csession.get("logged_in"):
|
||||||
# The webclient has previously registered a login to this browser_session
|
# The webclient has previously registered a login to this csession
|
||||||
print "website: browser_session logged in, trying to login"
|
print "website: csession logged in, trying to login"
|
||||||
player = PlayerDB.objects.get(id=browser_session.get("logged_in"))
|
player = PlayerDB.objects.get(id=csession.get("logged_in"))
|
||||||
login(request, player)
|
login(request, player)
|
||||||
else:
|
else:
|
||||||
browser_session["logged_in"] = None
|
csession["logged_in"] = None
|
||||||
|
|
||||||
print ("website session:", request.session.session_key, request.user, request.user.is_authenticated())
|
print ("website session:", request.session.session_key, request.user, request.user.is_authenticated())
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue