Cleaned up the webclient and changed how it handles sessions and identifies with the server. Fixed some reported bugs caused by the changed layout of sessionhandler.

This commit is contained in:
Griatch 2010-12-11 13:37:26 +00:00
parent b1682f78c9
commit 0eb5d29560
16 changed files with 191 additions and 107 deletions

View file

@ -22,7 +22,7 @@ from django.db import connection
from django.conf import settings
from src.utils import reloads
from src.config.models import ConfigValue
from src.server import sessionhandler
from src.server.sessionhandler import SESSIONS
from src.server import initial_setup
from src.utils.utils import get_evennia_version
@ -77,7 +77,7 @@ class Evennia(object):
self.run_initial_setup()
# we have to null this here.
sessionhandler.SESSIONS.session_count(0)
SESSIONS.session_count(0)
self.start_time = time.time()
@ -152,7 +152,7 @@ class Evennia(object):
"""
if not message:
message = 'The server has been shutdown. Please check back soon.'
sessionhandler.SESSIONS.disconnect_all_sessions(reason=message)
SESSIONS.disconnect_all_sessions(reason=message)
reactor.callLater(0, reactor.stop)

View file

@ -12,7 +12,7 @@ from django.conf import settings
from src.comms.models import Channel
from src.utils import logger, reloads
from src.commands import cmdhandler
from src.server import sessionhandler
from src.server.sessionhandler import SESSIONS
IDLE_TIMEOUT = settings.IDLE_TIMEOUT
IDLE_COMMAND = settings.IDLE_COMMAND
@ -75,7 +75,7 @@ class SessionBase(object):
# Total number of commands issued.
self.cmd_total = 0
#self.channels_subscribed = {}
sessionhandler.SESSIONS.add_unloggedin_session(self)
SESSIONS.add_unloggedin_session(self)
# call hook method
self.at_connect()
@ -101,7 +101,7 @@ class SessionBase(object):
reloads.reload_scripts(obj=self.player.character, init_mode=True)
#add session to connected list
sessionhandler.SESSIONS.add_loggedin_session(self)
SESSIONS.add_loggedin_session(self)
#call hook
self.at_login()
@ -123,7 +123,7 @@ class SessionBase(object):
uaccount.last_login = datetime.now()
uaccount.save()
self.logged_in = False
sessionhandler.SESSIONS.remove_session(self)
SESSIONS.remove_session(self)
def session_validate(self):
"""

View file

@ -151,6 +151,14 @@ class SessionHandler(object):
num = max(0, num + add)
ConfigValue.objects.conf('nr_sessions', str(num))
def player_count(self):
"""
Get the number of connected players (not sessions since a player
may have more than one session connected if ALLOW_MULTISESSION is True)
Only logged-in players are counted here.
"""
return len(set(sess.uid for sess in self.get_sessions()))
def sessions_from_player(self, player):
"""
Given a player, return any matching sessions.
@ -179,6 +187,13 @@ class SessionHandler(object):
"""
return [sess for sess in self.get_sessions(include_unloggedin=True) if sess.suid and sess.suid == suid]
def announce_all(self, message):
"""
Send message to all connected sessions
"""
for sess in self.get_sessions(include_unloggedin=True):
sess.msg(message)
SESSIONS = SessionHandler()

View file

@ -16,6 +16,8 @@ found on http://localhost:8020/webclient.)
handle these requests and act as a gateway
to sessions connected over the webclient.
"""
import time
from hashlib import md5
from twisted.web import server, resource
from twisted.internet import defer
@ -27,7 +29,8 @@ from django.conf import settings
from src.utils import utils
from src.utils.text2html import parse_html
from src.config.models import ConnectScreen
from src.server import session, sessionhandler
from src.server import session
from src.server.sessionhandler import SESSIONS
SERVERNAME = settings.SERVERNAME
ENCODINGS = settings.ENCODINGS
@ -94,8 +97,8 @@ class WebClient(resource.Resource):
self.databuffer[suid] = dataentries
def disconnect(self, suid):
"Disconnect session"
sess = sessionhandler.SESSIONS.session_from_suid(suid)
"Disconnect session with given suid."
sess = SESSIONS.session_from_suid(suid)
if sess:
sess[0].session_disconnect()
if self.requests.has_key(suid):
@ -110,32 +113,35 @@ class WebClient(resource.Resource):
This is called by render_POST when the client
requests an init mode operation (at startup)
"""
csess = request.getSession() # obs, this is a cookie, not an evennia session!
#csess = request.getSession() # obs, this is a cookie, not an evennia session!
#csees.expireCallbacks.append(lambda : )
suid = csess.uid
suid = request.args.get('suid', ['0'])[0]
remote_addr = request.getClientIP()
host_string = "%s (%s:%s)" % (SERVERNAME, request.getHost().host, request.getHost().port)
self.requests[suid] = []
self.databuffer[suid] = []
if suid == '0':
# creating a unique id hash string
suid = md5(str(time.time())).hexdigest()
self.requests[suid] = []
self.databuffer[suid] = []
sess = sessionhandler.SESSIONS.session_from_suid(suid)
if not sess:
sess = WebClientSession()
sess.client = self
sess.session_connect(remote_addr, suid)
sessionhandler.SESSIONS.add_unloggedin_session(sess)
return jsonify({'msg':host_string})
sess.client = self
sess.session_connect(remote_addr, suid)
return jsonify({'msg':host_string, 'suid':suid})
def mode_input(self, request):
"""
This is called by render_POST when the client
is sending data to the server.
"""
string = request.args.get('msg', [''])[0]
data = request.args.get('data', [None])[0]
suid = request.getSession().uid
sess = sessionhandler.SESSIONS.session_from_suid(suid)
suid = request.args.get('suid', ['0'])[0]
if suid == '0':
return ''
sess = SESSIONS.session_from_suid(suid)
if sess:
string = request.args.get('msg', [''])[0]
data = request.args.get('data', [None])[0]
sess[0].at_data_in(string, data)
return ''
@ -147,16 +153,29 @@ class WebClient(resource.Resource):
mechanism: the server will wait to reply until data is
available.
"""
suid = request.getSession().uid
suid = request.args.get('suid', ['0'])[0]
if suid == '0':
return ''
dataentries = self.databuffer.get(suid, [])
if dataentries:
return dataentries.pop(0)
return dataentries.pop(0)
reqlist = self.requests.get(suid, [])
request.notifyFinish().addErrback(self._responseFailed, suid, request)
reqlist.append(request)
self.requests[suid] = reqlist
return server.NOT_DONE_YET
def mode_close(self, request):
"""
This is called by render_POST when the client is signalling
that it is about to be closed.
"""
suid = request.args.get('suid', ['0'])[0]
if suid == '0':
self.disconnect(suid)
return ''
def render_POST(self, request):
"""
This function is what Twisted calls with POST requests coming
@ -176,6 +195,9 @@ class WebClient(resource.Resource):
elif dmode == 'receive':
# the client is waiting to receive data.
return self.mode_receive(request)
elif dmode == 'close':
# the client is closing
return self.mode_close(request)
else:
# this should not happen if client sends valid data.
return ''
@ -234,8 +256,7 @@ class WebClientSession(session.Session):
# string handling is similar to telnet
if self.encoding:
try:
string = utils.to_str(string, encoding=self.encoding)
#self.client.lineSend(self.suid, ansi.parse_ansi(string, strip_ansi=True))
string = utils.to_str(string, encoding=self.encoding)
self.client.lineSend(self.suid, parse_html(string))
return
except Exception:
@ -256,7 +277,7 @@ class WebClientSession(session.Session):
self.client.lineSend(self.suid, parse_html(string))
def at_data_in(self, string, data=None):
"""
Input from Player -> Evennia (called by client).
Input from Player -> Evennia (called by client protocol).
Use of 'data' is up to the client - server implementation.
"""