Made webclient aware of the server dropping (both websocket and AJAX). The server currently reacts to the websocket client dropping but not to the AJAX one (the latter forms ghost players)
This commit is contained in:
parent
c46e115901
commit
d5b3b59eb7
8 changed files with 51 additions and 37 deletions
|
|
@ -168,6 +168,8 @@ class Portal(object):
|
||||||
# we get here due to us calling reactor.stop below. No need
|
# we get here due to us calling reactor.stop below. No need
|
||||||
# to do the shutdown procedure again.
|
# to do the shutdown procedure again.
|
||||||
return
|
return
|
||||||
|
for session in self.sessions.itervalues():
|
||||||
|
session.disconnect()
|
||||||
self.set_restart_mode(restart)
|
self.set_restart_mode(restart)
|
||||||
if os.name == 'nt' and os.path.exists(PORTAL_PIDFILE):
|
if os.name == 'nt' and os.path.exists(PORTAL_PIDFILE):
|
||||||
# for Windows we need to remove pid files manually
|
# for Windows we need to remove pid files manually
|
||||||
|
|
|
||||||
|
|
@ -206,7 +206,6 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
|
||||||
|
|
||||||
def _write(self, data):
|
def _write(self, data):
|
||||||
"hook overloading the one used in plain telnet"
|
"hook overloading the one used in plain telnet"
|
||||||
print "Activated GMCP"
|
|
||||||
data = data.replace('\n', '\r\n').replace('\r\r\n', '\r\n')
|
data = data.replace('\n', '\r\n').replace('\r\r\n', '\r\n')
|
||||||
#data = data.replace('\n', '\r\n')
|
#data = data.replace('\n', '\r\n')
|
||||||
super(TelnetProtocol, self)._write(mccp_compress(self, data))
|
super(TelnetProtocol, self)._write(mccp_compress(self, data))
|
||||||
|
|
@ -246,8 +245,7 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session):
|
||||||
reason (str): Reason for disconnecting.
|
reason (str): Reason for disconnecting.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if reason:
|
self.data_out(connection_close=((reason or "",), {}))
|
||||||
self.data_out(text=[[reason], {}])
|
|
||||||
self.connectionLost(reason)
|
self.connectionLost(reason)
|
||||||
|
|
||||||
def data_in(self, **kwargs):
|
def data_in(self, **kwargs):
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,6 @@ class TelnetOOB(object):
|
||||||
"""
|
"""
|
||||||
# no msdp, check GMCP
|
# no msdp, check GMCP
|
||||||
self.protocol.handshake_done()
|
self.protocol.handshake_done()
|
||||||
print "No MSDP."
|
|
||||||
|
|
||||||
def do_msdp(self, option):
|
def do_msdp(self, option):
|
||||||
"""
|
"""
|
||||||
|
|
@ -118,7 +117,6 @@ class TelnetOOB(object):
|
||||||
self.MSDP = True
|
self.MSDP = True
|
||||||
self.protocol.protocol_flags['OOB'] = True
|
self.protocol.protocol_flags['OOB'] = True
|
||||||
self.protocol.handshake_done()
|
self.protocol.handshake_done()
|
||||||
print "Activated MSDP"
|
|
||||||
|
|
||||||
def no_gmcp(self, option):
|
def no_gmcp(self, option):
|
||||||
"""
|
"""
|
||||||
|
|
@ -130,7 +128,6 @@ class TelnetOOB(object):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.protocol.handshake_done()
|
self.protocol.handshake_done()
|
||||||
print "No GMCP."
|
|
||||||
|
|
||||||
def do_gmcp(self, option):
|
def do_gmcp(self, option):
|
||||||
"""
|
"""
|
||||||
|
|
@ -143,7 +140,6 @@ class TelnetOOB(object):
|
||||||
self.GMCP = True
|
self.GMCP = True
|
||||||
self.protocol.protocol_flags['OOB'] = True
|
self.protocol.protocol_flags['OOB'] = True
|
||||||
self.protocol.handshake_done()
|
self.protocol.handshake_done()
|
||||||
print "Activated GMCP"
|
|
||||||
|
|
||||||
# encoders
|
# encoders
|
||||||
|
|
||||||
|
|
@ -177,7 +173,7 @@ class TelnetOOB(object):
|
||||||
if not (args or kwargs):
|
if not (args or kwargs):
|
||||||
return msdp_cmdname
|
return msdp_cmdname
|
||||||
|
|
||||||
print "encode_msdp in:", cmdname, args, kwargs
|
#print "encode_msdp in:", cmdname, args, kwargs
|
||||||
|
|
||||||
msdp_args = ''
|
msdp_args = ''
|
||||||
if args:
|
if args:
|
||||||
|
|
@ -210,7 +206,7 @@ class TelnetOOB(object):
|
||||||
|
|
||||||
msdp_string = msdp_args + msdp_kwargs
|
msdp_string = msdp_args + msdp_kwargs
|
||||||
|
|
||||||
print "msdp_string:", msdp_string
|
#print "msdp_string:", msdp_string
|
||||||
return msdp_string
|
return msdp_string
|
||||||
|
|
||||||
def encode_gmcp(self, cmdname, *args, **kwargs):
|
def encode_gmcp(self, cmdname, *args, **kwargs):
|
||||||
|
|
@ -246,7 +242,7 @@ class TelnetOOB(object):
|
||||||
else: # only kwargs
|
else: # only kwargs
|
||||||
gmcp_string = "%s %s" % (cmdname, json.dumps(kwargs))
|
gmcp_string = "%s %s" % (cmdname, json.dumps(kwargs))
|
||||||
|
|
||||||
print "gmcp string", gmcp_string
|
#print "gmcp string", gmcp_string
|
||||||
return gmcp_string
|
return gmcp_string
|
||||||
|
|
||||||
def decode_msdp(self, data):
|
def decode_msdp(self, data):
|
||||||
|
|
@ -276,7 +272,7 @@ class TelnetOOB(object):
|
||||||
if hasattr(data, "__iter__"):
|
if hasattr(data, "__iter__"):
|
||||||
data = "".join(data)
|
data = "".join(data)
|
||||||
|
|
||||||
print "decode_msdp in:", data
|
#print "decode_msdp in:", data
|
||||||
|
|
||||||
tables = {}
|
tables = {}
|
||||||
arrays = {}
|
arrays = {}
|
||||||
|
|
@ -331,7 +327,7 @@ class TelnetOOB(object):
|
||||||
for key, var in variables.iteritems():
|
for key, var in variables.iteritems():
|
||||||
cmds[key] = [[var], {}]
|
cmds[key] = [[var], {}]
|
||||||
|
|
||||||
print "msdp data in:", cmds
|
#print "msdp data in:", cmds
|
||||||
self.protocol.data_in(**cmds)
|
self.protocol.data_in(**cmds)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -358,7 +354,7 @@ class TelnetOOB(object):
|
||||||
if hasattr(data, "__iter__"):
|
if hasattr(data, "__iter__"):
|
||||||
data = "".join(data)
|
data = "".join(data)
|
||||||
|
|
||||||
print "decode_gmcp in:", data
|
#print "decode_gmcp in:", data
|
||||||
if data:
|
if data:
|
||||||
try:
|
try:
|
||||||
cmdname, structure = data.split(None, 1)
|
cmdname, structure = data.split(None, 1)
|
||||||
|
|
@ -398,7 +394,7 @@ class TelnetOOB(object):
|
||||||
if self.MSDP:
|
if self.MSDP:
|
||||||
msdp_cmdname = cmdname
|
msdp_cmdname = cmdname
|
||||||
encoded_oob = self.encode_msdp(msdp_cmdname, *args, **kwargs)
|
encoded_oob = self.encode_msdp(msdp_cmdname, *args, **kwargs)
|
||||||
print "sending MSDP:", encoded_oob
|
#print "sending MSDP:", encoded_oob
|
||||||
self.protocol._write(IAC + SB + MSDP + encoded_oob + IAC + SE)
|
self.protocol._write(IAC + SB + MSDP + encoded_oob + IAC + SE)
|
||||||
|
|
||||||
if self.GMCP:
|
if self.GMCP:
|
||||||
|
|
@ -408,5 +404,5 @@ class TelnetOOB(object):
|
||||||
gmcp_cmdname = "Custom.Cmd"
|
gmcp_cmdname = "Custom.Cmd"
|
||||||
kwargs["cmdname"] = cmdname
|
kwargs["cmdname"] = cmdname
|
||||||
encoded_oob = self.encode_gmcp(gmcp_cmdname, *args, **kwargs)
|
encoded_oob = self.encode_gmcp(gmcp_cmdname, *args, **kwargs)
|
||||||
print "sending GMCP:", encoded_oob
|
#print "sending GMCP:", encoded_oob
|
||||||
self.protocol._write(IAC + SB + GMCP + encoded_oob + IAC + SE)
|
self.protocol._write(IAC + SB + GMCP + encoded_oob + IAC + SE)
|
||||||
|
|
|
||||||
|
|
@ -64,8 +64,7 @@ class WebSocketClient(Protocol, Session):
|
||||||
reason (str): Motivation for the disconnection.
|
reason (str): Motivation for the disconnection.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if reason:
|
self.data_out(connection_close=((reason or "",), {}))
|
||||||
self.data_out(text=[[reason],{}])
|
|
||||||
self.connectionLost(reason)
|
self.connectionLost(reason)
|
||||||
|
|
||||||
def connectionLost(self, reason):
|
def connectionLost(self, reason):
|
||||||
|
|
@ -123,7 +122,6 @@ class WebSocketClient(Protocol, Session):
|
||||||
if "websocket_close" in kwargs:
|
if "websocket_close" in kwargs:
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
return
|
return
|
||||||
print "websocket in:", kwargs
|
|
||||||
self.sessionhandler.data_in(self, **kwargs)
|
self.sessionhandler.data_in(self, **kwargs)
|
||||||
|
|
||||||
def data_out(self, **kwargs):
|
def data_out(self, **kwargs):
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ from twisted.web import server, resource
|
||||||
from django.utils.functional import Promise
|
from django.utils.functional import Promise
|
||||||
from django.utils.encoding import force_unicode
|
from django.utils.encoding import force_unicode
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from evennia.utils import utils, logger
|
from evennia.utils import utils
|
||||||
from evennia.utils.text2html import parse_html
|
from evennia.utils.text2html import parse_html
|
||||||
from evennia.server import session
|
from evennia.server import session
|
||||||
|
|
||||||
|
|
@ -245,15 +245,14 @@ class WebClientSession(session.Session):
|
||||||
This represents a session running in a webclient.
|
This represents a session running in a webclient.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def disconnect(self, reason=None):
|
def disconnect(self, reason="Server disconnected."):
|
||||||
"""
|
"""
|
||||||
Disconnect from server.
|
Disconnect from server.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
reason (str): Motivation for the disconnect.
|
reason (str): Motivation for the disconnect.
|
||||||
"""
|
"""
|
||||||
if reason:
|
self.client.lineSend(self.suid, ["connection_close", [reason], {}])
|
||||||
self.client.lineSend(self.suid, ["text", [reason], {}])
|
|
||||||
self.client.client_disconnect(self.suid)
|
self.client.client_disconnect(self.suid)
|
||||||
|
|
||||||
def data_out(self, **kwargs):
|
def data_out(self, **kwargs):
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,6 @@ a:hover, a:active { color: #ccc }
|
||||||
strong {font-weight:normal;}
|
strong {font-weight:normal;}
|
||||||
|
|
||||||
div {margin:0px;}
|
div {margin:0px;}
|
||||||
/* Base style for new messages in the main message area */
|
|
||||||
/*.msg {
|
|
||||||
white-space: pre-wrap; }
|
|
||||||
padding: .5em .9em;} */
|
|
||||||
/*border-bottom: 1px dotted #222 } /*optional line between messages */
|
|
||||||
|
|
||||||
/* Utility messages (green) */
|
/* Utility messages (green) */
|
||||||
.sys { color: #0f0 }
|
.sys { color: #0f0 }
|
||||||
|
|
@ -45,7 +40,7 @@ div {margin:0px;}
|
||||||
.out { color: #aaa }
|
.out { color: #aaa }
|
||||||
|
|
||||||
/* Error messages (red) */
|
/* Error messages (red) */
|
||||||
.err { color: #f00 }
|
.err { color: #f00; }
|
||||||
|
|
||||||
/* Prompt base (white) */
|
/* Prompt base (white) */
|
||||||
.prompt {color: #fff }
|
.prompt {color: #fff }
|
||||||
|
|
|
||||||
|
|
@ -195,20 +195,31 @@ An "emitter" object must have a function
|
||||||
//
|
//
|
||||||
var WebsocketConnection = function () {
|
var WebsocketConnection = function () {
|
||||||
log("Trying websocket ...");
|
log("Trying websocket ...");
|
||||||
|
wsurl = "ws://blah";
|
||||||
|
var open = false;
|
||||||
var websocket = new WebSocket(wsurl);
|
var websocket = new WebSocket(wsurl);
|
||||||
// Handle Websocket open event
|
// Handle Websocket open event
|
||||||
websocket.onopen = function (event) {
|
websocket.onopen = function (event) {
|
||||||
|
open = true;
|
||||||
Evennia.emit('connection_open', ["websocket"], event);
|
Evennia.emit('connection_open', ["websocket"], event);
|
||||||
};
|
};
|
||||||
// Handle Websocket close event
|
// Handle Websocket close event
|
||||||
websocket.onclose = function (event) {
|
websocket.onclose = function (event) {
|
||||||
Evennia.emit('connection_close', ["websocket"], event);
|
if (open) {
|
||||||
|
// only emit if websocket was ever open at all
|
||||||
|
Evennia.emit('connection_close', ["websocket"], event);
|
||||||
|
}
|
||||||
|
open = false;
|
||||||
};
|
};
|
||||||
// Handle websocket errors
|
// Handle websocket errors
|
||||||
websocket.onerror = function (event) {
|
websocket.onerror = function (event) {
|
||||||
Evennia.emit('connection_error', ["websocket"], event);
|
|
||||||
if (websocket.readyState === websocket.CLOSED) {
|
if (websocket.readyState === websocket.CLOSED) {
|
||||||
log("Websocket failed. Falling back to Ajax...");
|
log("Websocket failed. Falling back to Ajax...");
|
||||||
|
if (open) {
|
||||||
|
// only emit if websocket was ever open at all.
|
||||||
|
Evennia.emit('connection_error', ["websocket"], event);
|
||||||
|
}
|
||||||
|
open = false;
|
||||||
Evennia.connection = AjaxCometConnection();
|
Evennia.connection = AjaxCometConnection();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -232,6 +243,7 @@ An "emitter" object must have a function
|
||||||
// tied to when the client window is closed). This
|
// tied to when the client window is closed). This
|
||||||
// Makes use of a websocket-protocol specific instruction.
|
// Makes use of a websocket-protocol specific instruction.
|
||||||
websocket.send(JSON.stringify(["websocket_close", [], {}]));
|
websocket.send(JSON.stringify(["websocket_close", [], {}]));
|
||||||
|
open = false;
|
||||||
}
|
}
|
||||||
return websocket;
|
return websocket;
|
||||||
};
|
};
|
||||||
|
|
@ -264,7 +276,6 @@ An "emitter" object must have a function
|
||||||
|
|
||||||
// Send Client -> Evennia. Called by Evennia.msg
|
// Send Client -> Evennia. Called by Evennia.msg
|
||||||
var msg = function(data) {
|
var msg = function(data) {
|
||||||
log("AJAX.msg:", data);
|
|
||||||
$.ajax({type: "POST", url: "/webclientdata",
|
$.ajax({type: "POST", url: "/webclientdata",
|
||||||
async: true, cache: false, timeout: 30000,
|
async: true, cache: false, timeout: 30000,
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
|
|
@ -287,8 +298,8 @@ An "emitter" object must have a function
|
||||||
dataType: "json",
|
dataType: "json",
|
||||||
data: {mode: 'receive', 'suid': client_hash},
|
data: {mode: 'receive', 'suid': client_hash},
|
||||||
success: function(data) {
|
success: function(data) {
|
||||||
|
log("ajax data received:", data);
|
||||||
Evennia.emit(data[0], data[1], data[2]);
|
Evennia.emit(data[0], data[1], data[2]);
|
||||||
log("AJAX/COMET: Evennia->client", data);
|
|
||||||
poll(); // immiately start a new request
|
poll(); // immiately start a new request
|
||||||
},
|
},
|
||||||
error: function(req, stat, err) {
|
error: function(req, stat, err) {
|
||||||
|
|
|
||||||
|
|
@ -179,9 +179,10 @@ function doWindowResize() {
|
||||||
// Handle text coming from the server
|
// Handle text coming from the server
|
||||||
function onText(args, kwargs) {
|
function onText(args, kwargs) {
|
||||||
// append message to previous ones, then scroll so latest is at
|
// append message to previous ones, then scroll so latest is at
|
||||||
// the bottom.
|
// the bottom. Send 'cls' kwarg to modify the output class.
|
||||||
var mwin = $("#messagewindow");
|
var mwin = $("#messagewindow");
|
||||||
mwin.append("<div class='msg out'>" + args[0] + "</div>");
|
var cls = kwargs == null ? 'out' : kwargs['cls'];
|
||||||
|
mwin.append("<div class='" + cls + "'>" + args[0] + "</div>");
|
||||||
mwin.animate({
|
mwin.animate({
|
||||||
scrollTop: document.getElementById("messagewindow").scrollHeight
|
scrollTop: document.getElementById("messagewindow").scrollHeight
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
@ -191,7 +192,7 @@ function onText(args, kwargs) {
|
||||||
function onPrompt(args, kwargs) {
|
function onPrompt(args, kwargs) {
|
||||||
// show prompt
|
// show prompt
|
||||||
$('#prompt')
|
$('#prompt')
|
||||||
.addClass("msg out")
|
.addClass("out")
|
||||||
.html(args[0]);
|
.html(args[0]);
|
||||||
doWindowResize();
|
doWindowResize();
|
||||||
}
|
}
|
||||||
|
|
@ -199,9 +200,22 @@ function onPrompt(args, kwargs) {
|
||||||
// Silences events we don't do anything with.
|
// Silences events we don't do anything with.
|
||||||
function onSilence(cmdname, args, kwargs) {}
|
function onSilence(cmdname, args, kwargs) {}
|
||||||
|
|
||||||
|
// Handle the server connection closing
|
||||||
|
function onConnectionClose(conn_name, evt) {
|
||||||
|
onText(["The connection was closed or lost."], {'cls': 'err'});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle a connection error
|
||||||
|
function onConnectionError(conn_name, evt) {
|
||||||
|
if (conn_name[0].lastIndexOf("AJAX/COMET", 0) === 0) {
|
||||||
|
// only display anything if the error is in AJAX/COMET
|
||||||
|
onText(["The connection was closed or lost."], {'cls': 'err'});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handle unrecognized commands from server
|
// Handle unrecognized commands from server
|
||||||
function onDefault(cmdname, args, kwargs) {
|
function onDefault(cmdname, args, kwargs) {
|
||||||
mwin = $("#messagewindow");
|
var mwin = $("#messagewindow");
|
||||||
mwin.append(
|
mwin.append(
|
||||||
"<div class='msg err'>"
|
"<div class='msg err'>"
|
||||||
+ "Error or Unhandled event:<br>"
|
+ "Error or Unhandled event:<br>"
|
||||||
|
|
@ -240,7 +254,8 @@ $(document).ready(function() {
|
||||||
Evennia.emitter.on("default", onDefault);
|
Evennia.emitter.on("default", onDefault);
|
||||||
// silence currently unused events
|
// silence currently unused events
|
||||||
Evennia.emitter.on("connection_open", onSilence);
|
Evennia.emitter.on("connection_open", onSilence);
|
||||||
Evennia.emitter.on("connection_close", onSilence);
|
Evennia.emitter.on("connection_close", onConnectionClose);
|
||||||
|
Evennia.emitter.on("connection_error", onConnectionError);
|
||||||
|
|
||||||
// Handle pressing the send button
|
// Handle pressing the send button
|
||||||
$("#inputsend").bind("click", doSendText);
|
$("#inputsend").bind("click", doSendText);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue