Exclude server_tags from truncation.

They have their own 8191 bytes.
This commit is contained in:
Valentin Lorentz 2020-05-07 18:30:07 +02:00
parent da328b4985
commit 2008f7b815
2 changed files with 37 additions and 13 deletions

View File

@ -60,7 +60,7 @@ from .utils.str import rsplit
from .utils.iter import chain from .utils.iter import chain
from .utils.structures import smallqueue, RingBuffer, TimeoutDict from .utils.structures import smallqueue, RingBuffer, TimeoutDict
MAX_LINE_SIZE = 512 # Including \r\n MAX_LINE_SIZE = 512 # Including \r\n, but excluding server_tags
### ###
# The base class for a callback to be registered with an Irc object. Shows # The base class for a callback to be registered with an Irc object. Shows
@ -990,6 +990,27 @@ class Irc(IrcCommandDispatcher, log.Firewalled):
else: else:
log.warning('Refusing to send %r; %s is a zombie.', msg, self) log.warning('Refusing to send %r; %s is a zombie.', msg, self)
def _truncateMsg(self, msg):
msg_str = str(msg)
if msg_str[0] == '@':
(msg_tags_str, msg_rest_str) = msg_str.split(' ', 1)
msg_tags_str += ' '
else:
msg_tags_str = ''
msg_rest_str = msg_str
if len(msg_rest_str) > MAX_LINE_SIZE:
# Yes, this violates the contract, but at this point it doesn't
# matter. That's why we gotta go munging in private attributes
#
# I'm changing this to a log.debug to fix a possible loop in
# the LogToIrc plugin. Since users can't do anything about
# this issue, there's no fundamental reason to make it a
# warning.
log.debug('Truncating %r, message is too long.', msg)
msg._str = msg_tags_str + msg_rest_str[:MAX_LINE_SIZE-2] + '\r\n'
msg._len = len(str(msg))
# TODO: truncate tags
def takeMsg(self): def takeMsg(self):
"""Called by the IrcDriver; takes a message to be sent.""" """Called by the IrcDriver; takes a message to be sent."""
if not self.callbacks: if not self.callbacks:
@ -1026,17 +1047,9 @@ class Irc(IrcCommandDispatcher, log.Firewalled):
log.debug('%s.outFilter returned None.', callback.name()) log.debug('%s.outFilter returned None.', callback.name())
return self.takeMsg() return self.takeMsg()
world.debugFlush() world.debugFlush()
if len(str(msg)) > MAX_LINE_SIZE:
# Yes, this violates the contract, but at this point it doesn't self._truncateMsg(msg)
# matter. That's why we gotta go munging in private attributes
#
# I'm changing this to a log.debug to fix a possible loop in
# the LogToIrc plugin. Since users can't do anything about
# this issue, there's no fundamental reason to make it a
# warning.
log.debug('Truncating %r, message is too long.', msg)
msg._str = msg._str[:MAX_LINE_SIZE-2] + '\r\n'
msg._len = len(str(msg))
# I don't think we should do this. Why should it matter? If it's # I don't think we should do this. Why should it matter? If it's
# something important, then the server will send it back to us, # something important, then the server will send it back to us,
# and if it's just a privmsg/notice/etc., we don't care. # and if it's just a privmsg/notice/etc., we don't care.

View File

@ -649,7 +649,18 @@ class IrcTestCase(SupyTestCase):
def testNoMsgLongerThan512(self): def testNoMsgLongerThan512(self):
self.irc.queueMsg(ircmsgs.privmsg('whocares', 'x'*1000)) self.irc.queueMsg(ircmsgs.privmsg('whocares', 'x'*1000))
msg = self.irc.takeMsg() msg = self.irc.takeMsg()
self.assertTrue(len(msg) <= 512, 'len(msg) was %s' % len(msg)) self.assertEqual(
len(msg), 512, 'len(msg) was %s (msg=%r)' % (len(msg), msg))
# Server tags don't influence the size limit of the rest of the
# message.
self.irc.queueMsg(ircmsgs.IrcMsg(
command='PRIVMSG', args=['whocares', 'x'*1000],
server_tags={'y': 'z'*500}))
msg2 = self.irc.takeMsg()
self.assertEqual(
len(msg2), 512+504, 'len(msg2) was %s (msg2=%r)' % (len(msg2), msg2))
self.assertEqual(msg.args, msg2.args)
def testReset(self): def testReset(self):
for msg in msgs: for msg in msgs: