fixing memory leaks

This commit is contained in:
A Rodian Jedi 2024-10-06 17:39:08 -06:00
parent 25ddad219e
commit fa5c7301fc
8 changed files with 97 additions and 86 deletions

View file

@ -15,6 +15,7 @@ This protocol is implemented by the telnet protocol importing
mccp_compress and calling it from its write methods.
"""
import weakref
import zlib
# negotiations for v1 and v2 of the protocol
@ -57,10 +58,10 @@ class Mccp:
"""
self.protocol = protocol
self.protocol.protocol_flags["MCCP"] = False
self.protocol = weakref.ref(protocol)
self.protocol().protocol_flags["MCCP"] = False
# ask if client will mccp, connect callbacks to handle answer
self.protocol.will(MCCP).addCallbacks(self.do_mccp, self.no_mccp)
self.protocol().will(MCCP).addCallbacks(self.do_mccp, self.no_mccp)
def no_mccp(self, option):
"""
@ -70,10 +71,10 @@ class Mccp:
option (Option): Option dict (not used).
"""
if hasattr(self.protocol, "zlib"):
del self.protocol.zlib
self.protocol.protocol_flags["MCCP"] = False
self.protocol.handshake_done()
if hasattr(self.protocol(), "zlib"):
del self.protocol().zlib
self.protocol().protocol_flags["MCCP"] = False
self.protocol().handshake_done()
def do_mccp(self, option):
"""
@ -84,7 +85,7 @@ class Mccp:
option (Option): Option dict (not used).
"""
self.protocol.protocol_flags["MCCP"] = True
self.protocol.requestNegotiation(MCCP, b"")
self.protocol.zlib = zlib.compressobj(9)
self.protocol.handshake_done()
self.protocol().protocol_flags["MCCP"] = True
self.protocol().requestNegotiation(MCCP, b"")
self.protocol().zlib = zlib.compressobj(9)
self.protocol().handshake_done()

View file

@ -11,6 +11,7 @@ active players and so on.
"""
import weakref
from django.conf import settings
from evennia.utils import utils
@ -39,8 +40,8 @@ class Mssp:
protocol (Protocol): The active protocol instance.
"""
self.protocol = protocol
self.protocol.will(MSSP).addCallbacks(self.do_mssp, self.no_mssp)
self.protocol = weakref.ref(protocol)
self.protocol().will(MSSP).addCallbacks(self.do_mssp, self.no_mssp)
def get_player_count(self):
"""
@ -50,7 +51,7 @@ class Mssp:
count (int): The number of players in the MUD.
"""
return str(self.protocol.sessionhandler.count_loggedin())
return str(self.protocol().sessionhandler.count_loggedin())
def get_uptime(self):
"""
@ -60,7 +61,7 @@ class Mssp:
uptime (int): Number of seconds of uptime.
"""
return str(self.protocol.sessionhandler.uptime)
return str(self.protocol().sessionhandler.uptime)
def no_mssp(self, option):
"""
@ -71,7 +72,7 @@ class Mssp:
option (Option): Not used.
"""
self.protocol.handshake_done()
self.protocol().handshake_done()
def do_mssp(self, option):
"""
@ -132,5 +133,5 @@ class Mssp:
)
# send to crawler by subnegotiation
self.protocol.requestNegotiation(MSSP, varlist)
self.protocol.handshake_done()
self.protocol().requestNegotiation(MSSP, varlist)
self.protocol().handshake_done()

View file

@ -15,6 +15,7 @@ http://www.gammon.com.au/mushclient/addingservermxp.htm
"""
import re
import weakref
from django.conf import settings
@ -61,10 +62,10 @@ class Mxp:
protocol (Protocol): The active protocol instance.
"""
self.protocol = protocol
self.protocol.protocol_flags["MXP"] = False
self.protocol = weakref.ref(protocol)
self.protocol().protocol_flags["MXP"] = False
if settings.MXP_ENABLED:
self.protocol.will(MXP).addCallbacks(self.do_mxp, self.no_mxp)
self.protocol().will(MXP).addCallbacks(self.do_mxp, self.no_mxp)
def no_mxp(self, option):
"""
@ -74,8 +75,8 @@ class Mxp:
option (Option): Not used.
"""
self.protocol.protocol_flags["MXP"] = False
self.protocol.handshake_done()
self.protocol().protocol_flags["MXP"] = False
self.protocol().handshake_done()
def do_mxp(self, option):
"""
@ -86,8 +87,8 @@ class Mxp:
"""
if settings.MXP_ENABLED:
self.protocol.protocol_flags["MXP"] = True
self.protocol.requestNegotiation(MXP, b"")
self.protocol().protocol_flags["MXP"] = True
self.protocol().requestNegotiation(MXP, b"")
else:
self.protocol.wont(MXP)
self.protocol.handshake_done()
self.protocol().wont(MXP)
self.protocol().handshake_done()

View file

@ -11,6 +11,7 @@ client and update it when the size changes
"""
from codecs import encode as codecs_encode
import weakref
from django.conf import settings
@ -41,13 +42,13 @@ class Naws:
"""
self.naws_step = 0
self.protocol = protocol
self.protocol.protocol_flags["SCREENWIDTH"] = {
self.protocol = weakref.ref(protocol)
self.protocol().protocol_flags["SCREENWIDTH"] = {
0: DEFAULT_WIDTH
} # windowID (0 is root):width
self.protocol.protocol_flags["SCREENHEIGHT"] = {0: DEFAULT_HEIGHT} # windowID:width
self.protocol.negotiationMap[NAWS] = self.negotiate_sizes
self.protocol.do(NAWS).addCallbacks(self.do_naws, self.no_naws)
self.protocol().negotiationMap[NAWS] = self.negotiate_sizes
self.protocol().do(NAWS).addCallbacks(self.do_naws, self.no_naws)
def no_naws(self, option):
"""
@ -58,8 +59,8 @@ class Naws:
option (Option): Not used.
"""
self.protocol.protocol_flags["AUTORESIZE"] = False
self.protocol.handshake_done()
self.protocol().protocol_flags["AUTORESIZE"] = False
self.protocol().handshake_done()
def do_naws(self, option):
"""
@ -69,8 +70,8 @@ class Naws:
option (Option): Not used.
"""
self.protocol.protocol_flags["AUTORESIZE"] = True
self.protocol.handshake_done()
self.protocol().protocol_flags["AUTORESIZE"] = True
self.protocol().handshake_done()
def negotiate_sizes(self, options):
"""
@ -83,6 +84,6 @@ class Naws:
if len(options) == 4:
# NAWS is negotiated with 16bit words
width = options[0] + options[1]
self.protocol.protocol_flags["SCREENWIDTH"][0] = int(codecs_encode(width, "hex"), 16)
self.protocol().protocol_flags["SCREENWIDTH"][0] = int(codecs_encode(width, "hex"), 16)
height = options[2] + options[3]
self.protocol.protocol_flags["SCREENHEIGHT"][0] = int(codecs_encode(height, "hex"), 16)
self.protocol().protocol_flags["SCREENHEIGHT"][0] = int(codecs_encode(height, "hex"), 16)

View file

@ -14,6 +14,8 @@ http://www.faqs.org/rfcs/rfc858.html
"""
import weakref
SUPPRESS_GA = bytes([3]) # b"\x03"
# default taken from telnet specification
@ -36,14 +38,14 @@ class SuppressGA:
protocol (Protocol): The active protocol instance.
"""
self.protocol = protocol
self.protocol = weakref.ref(protocol)
self.protocol.protocol_flags["NOGOAHEAD"] = True
self.protocol.protocol_flags["NOPROMPTGOAHEAD"] = (
self.protocol().protocol_flags["NOGOAHEAD"] = True
self.protocol().protocol_flags["NOPROMPTGOAHEAD"] = (
True # Used to send a GA after a prompt line only, set in TTYPE (per client)
)
# tell the client that we prefer to suppress GA ...
self.protocol.will(SUPPRESS_GA).addCallbacks(self.will_suppress_ga, self.wont_suppress_ga)
self.protocol().will(SUPPRESS_GA).addCallbacks(self.will_suppress_ga, self.wont_suppress_ga)
def wont_suppress_ga(self, option):
"""
@ -53,8 +55,8 @@ class SuppressGA:
option (Option): Not used.
"""
self.protocol.protocol_flags["NOGOAHEAD"] = False
self.protocol.handshake_done()
self.protocol().protocol_flags["NOGOAHEAD"] = False
self.protocol().handshake_done()
def will_suppress_ga(self, option):
"""
@ -64,5 +66,5 @@ class SuppressGA:
option (Option): Not used.
"""
self.protocol.protocol_flags["NOGOAHEAD"] = True
self.protocol.handshake_done()
self.protocol().protocol_flags["NOGOAHEAD"] = True
self.protocol().handshake_done()

View file

@ -306,6 +306,8 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, _BASE_SESSION_CLASS):
"""
self.sessionhandler.disconnect(self)
if self.nop_keep_alive and self.nop_keep_alive.running:
self.toggle_nop_keepalive()
self.transport.loseConnection()
def applicationDataReceived(self, data):

View file

@ -26,6 +26,7 @@ This implements the following telnet OOB communication protocols:
import json
import re
import weakref
# General Telnet
from twisted.conch.telnet import IAC, SB, SE
@ -84,16 +85,16 @@ class TelnetOOB:
protocol (Protocol): The active protocol.
"""
self.protocol = protocol
self.protocol.protocol_flags["OOB"] = False
self.protocol = weakref.ref(protocol)
self.protocol().protocol_flags["OOB"] = False
self.MSDP = False
self.GMCP = False
# ask for the available protocols and assign decoders
# (note that handshake_done() will be called twice!)
self.protocol.negotiationMap[MSDP] = self.decode_msdp
self.protocol.negotiationMap[GMCP] = self.decode_gmcp
self.protocol.will(MSDP).addCallbacks(self.do_msdp, self.no_msdp)
self.protocol.will(GMCP).addCallbacks(self.do_gmcp, self.no_gmcp)
self.protocol().negotiationMap[MSDP] = self.decode_msdp
self.protocol().negotiationMap[GMCP] = self.decode_gmcp
self.protocol().will(MSDP).addCallbacks(self.do_msdp, self.no_msdp)
self.protocol().will(GMCP).addCallbacks(self.do_gmcp, self.no_gmcp)
self.oob_reported = {}
def no_msdp(self, option):
@ -105,7 +106,7 @@ class TelnetOOB:
"""
# no msdp, check GMCP
self.protocol.handshake_done()
self.protocol().handshake_done()
def do_msdp(self, option):
"""
@ -116,8 +117,8 @@ class TelnetOOB:
"""
self.MSDP = True
self.protocol.protocol_flags["OOB"] = True
self.protocol.handshake_done()
self.protocol().protocol_flags["OOB"] = True
self.protocol().handshake_done()
def no_gmcp(self, option):
"""
@ -128,7 +129,7 @@ class TelnetOOB:
option (Option): Not used.
"""
self.protocol.handshake_done()
self.protocol().handshake_done()
def do_gmcp(self, option):
"""
@ -139,8 +140,8 @@ class TelnetOOB:
"""
self.GMCP = True
self.protocol.protocol_flags["OOB"] = True
self.protocol.handshake_done()
self.protocol().protocol_flags["OOB"] = True
self.protocol().handshake_done()
# encoders
@ -375,7 +376,7 @@ class TelnetOOB:
cmds["msdp_{}".format(remap)] = cmds.pop(lower_case[remap])
# print("msdp data in:", cmds) # DEBUG
self.protocol.data_in(**cmds)
self.protocol().data_in(**cmds)
def decode_gmcp(self, data):
"""
@ -424,7 +425,7 @@ class TelnetOOB:
if cmdname.lower().startswith(b"core_"):
# if Core.cmdname, then use cmdname
cmdname = cmdname[5:]
self.protocol.data_in(**{cmdname.lower().decode(): [args, kwargs]})
self.protocol().data_in(**{cmdname.lower().decode(): [args, kwargs]})
# access methods
@ -441,8 +442,8 @@ class TelnetOOB:
if self.MSDP:
encoded_oob = self.encode_msdp(cmdname, *args, **kwargs)
self.protocol._write(IAC + SB + MSDP + encoded_oob + IAC + SE)
self.protocol()._write(IAC + SB + MSDP + encoded_oob + IAC + SE)
if self.GMCP:
encoded_oob = self.encode_gmcp(cmdname, *args, **kwargs)
self.protocol._write(IAC + SB + GMCP + encoded_oob + IAC + SE)
self.protocol()._write(IAC + SB + GMCP + encoded_oob + IAC + SE)

View file

@ -12,6 +12,8 @@ under the 'TTYPE' key.
"""
import weakref
# telnet option codes
TTYPE = bytes([24]) # b"\x18"
IS = bytes([0]) # b"\x00"
@ -55,16 +57,16 @@ class Ttype:
"""
self.ttype_step = 0
self.protocol = protocol
self.protocol = weakref.ref(protocol)
# we set FORCEDENDLINE for clients not supporting ttype
self.protocol.protocol_flags["FORCEDENDLINE"] = True
self.protocol.protocol_flags["TTYPE"] = False
self.protocol().protocol_flags["FORCEDENDLINE"] = True
self.protocol().protocol_flags["TTYPE"] = False
# is it a safe bet to assume ANSI is always supported?
self.protocol.protocol_flags["ANSI"] = True
self.protocol().protocol_flags["ANSI"] = True
# setup protocol to handle ttype initialization and negotiation
self.protocol.negotiationMap[TTYPE] = self.will_ttype
self.protocol().negotiationMap[TTYPE] = self.will_ttype
# ask if client will ttype, connect callback if it does.
self.protocol.do(TTYPE).addCallbacks(self.will_ttype, self.wont_ttype)
self.protocol().do(TTYPE).addCallbacks(self.will_ttype, self.wont_ttype)
def wont_ttype(self, option):
"""
@ -74,8 +76,8 @@ class Ttype:
option (Option): Not used.
"""
self.protocol.protocol_flags["TTYPE"] = False
self.protocol.handshake_done()
self.protocol().protocol_flags["TTYPE"] = False
self.protocol().handshake_done()
def will_ttype(self, option):
"""
@ -104,7 +106,7 @@ class Ttype:
if self.ttype_step == 0:
# just start the request chain
self.protocol.requestNegotiation(TTYPE, SEND)
self.protocol().requestNegotiation(TTYPE, SEND)
elif self.ttype_step == 1:
# this is supposed to be the name of the client/terminal.
@ -125,9 +127,9 @@ class Ttype:
xterm256 = clientname.split("MUDLET", 1)[1].strip() >= "1.1"
# Mudlet likes GA's on a prompt line for the prompt trigger to
# match, if it's not wanting NOGOAHEAD.
if not self.protocol.protocol_flags["NOGOAHEAD"]:
self.protocol.protocol_flags["NOGOAHEAD"] = True
self.protocol.protocol_flags["NOPROMPTGOAHEAD"] = False
if not self.protocol().protocol_flags["NOGOAHEAD"]:
self.protocol().protocol_flags["NOGOAHEAD"] = True
self.protocol().protocol_flags["NOPROMPTGOAHEAD"] = False
if (
clientname.startswith("XTERM")
@ -153,11 +155,11 @@ class Ttype:
truecolor = True
# all clients supporting TTYPE at all seem to support ANSI
self.protocol.protocol_flags["ANSI"] = True
self.protocol.protocol_flags["XTERM256"] = xterm256
self.protocol.protocol_flags["TRUECOLOR"] = truecolor
self.protocol.protocol_flags["CLIENTNAME"] = clientname
self.protocol.requestNegotiation(TTYPE, SEND)
self.protocol().protocol_flags["ANSI"] = True
self.protocol().protocol_flags["XTERM256"] = xterm256
self.protocol().protocol_flags["TRUECOLOR"] = truecolor
self.protocol().protocol_flags["CLIENTNAME"] = clientname
self.protocol().requestNegotiation(TTYPE, SEND)
elif self.ttype_step == 2:
# this is a term capabilities flag
@ -170,11 +172,11 @@ class Ttype:
and not tupper.endswith("-COLOR") # old Tintin, Putty
)
if xterm256:
self.protocol.protocol_flags["ANSI"] = True
self.protocol.protocol_flags["XTERM256"] = xterm256
self.protocol.protocol_flags["TERM"] = term
self.protocol().protocol_flags["ANSI"] = True
self.protocol().protocol_flags["XTERM256"] = xterm256
self.protocol().protocol_flags["TERM"] = term
# request next information
self.protocol.requestNegotiation(TTYPE, SEND)
self.protocol().requestNegotiation(TTYPE, SEND)
elif self.ttype_step == 3:
# the MTTS bitstring identifying term capabilities
@ -186,12 +188,12 @@ class Ttype:
support = dict(
(capability, True) for bitval, capability in MTTS if option & bitval > 0
)
self.protocol.protocol_flags.update(support)
self.protocol().protocol_flags.update(support)
else:
# some clients send erroneous MTTS as a string. Add directly.
self.protocol.protocol_flags[option.upper()] = True
self.protocol().protocol_flags[option.upper()] = True
self.protocol.protocol_flags["TTYPE"] = True
self.protocol().protocol_flags["TTYPE"] = True
# we must sync ttype once it'd done
self.protocol.handshake_done()
self.protocol().handshake_done()
self.ttype_step += 1