"""
mssp.py
Adds MSSP support to NakedMud. Add new variables with register_mssp_var.
"""
import hooks, mudsock, telnetlib, types, time
################################################################################
# variables
################################################################################
# the character for MSSP
MSSP = 'F' # "%c" % 70
# markers for sending MSSP info
MSSP_VAR = '\x01' # "%c" % 1
MSSP_VAL = '\x02' # "%c" % 2
# handshake crap
server_will_mssp = telnetlib.IAC + telnetlib.WILL + MSSP
client_do_mssp = telnetlib.IAC + telnetlib.DO + MSSP
# subnegotion crap
subneg_start_mssp = telnetlib.IAC + telnetlib.SB + MSSP
subneg_end_mssp = telnetlib.IAC + telnetlib.SE
# a table of MSSP variables and functions to build their values
mssp_variables = { }
################################################################################
# functions
################################################################################
def register_mssp_var(var, val):
"""register a new variable to build info for when we are sending MSSP info.
val should either a function that builds the arguments, or something
that can be cast as a string. If val is a string, it should return
either something that can be cast as a string or, if multiple values are
acceptable (e.g., in the case of ports) a list of things that can be cast
as a string.
"""
mssp_variables[var] = val
################################################################################
# local functions
################################################################################
def build_one_mssp_info(var, val):
"""returns MSSP info for one var:val pair.
"""
# first, if it's a function, figure out what it returns
if type(val) == types.FunctionType:
val = val()
# next, if the return was a list, turn everything to strings for join()
if type(val) == list:
val = MSSP_VAL.join([str(x) for x in val])
# return our info
return MSSP_VAR + var + MSSP_VAL + str(val)
def build_mssp_info():
"""returns a string for our current MSSP info.
"""
buf=[build_one_mssp_info(var,val) for var,val in mssp_variables.iteritems()]
return subneg_start_mssp + "".join(buf) + subneg_end_mssp
################################################################################
# hooks
################################################################################
def will_mssp_hook(info):
"""connection has been received. See if they are an MSSP crawler.
"""
sock, = hooks.parse_info(info)
sock.send_raw(server_will_mssp)
def do_mssp_hook(info):
"""check to see if the iac command was a signal that the client handles MSSP
"""
sock, cmd = hooks.parse_info(info)
if cmd == client_do_mssp:
sock.send_raw(build_mssp_info())
################################################################################
# initialization
################################################################################
hooks.add("receive_iac", do_mssp_hook)
hooks.add("receive_connection", will_mssp_hook)
# register all of our default MSSP variables
register_mssp_var("PLAYERS", lambda : len(mudsock.socket_list()))
register_mssp_var("UPTIME", int(time.time()))
register_mssp_var("FAMILY", "Custom")
register_mssp_var("ANSI", 1)