Commit 2985fbce authored by Vincent Pelletier's avatar Vincent Pelletier

Avoid parsing packet header multiple times when there is not enough data.

git-svn-id: https://svn.erp5.org/repos/neo/trunk@2001 71dcc9de-d417-0410-9af5-da40c76e7ee4
parent c1101e85
......@@ -20,7 +20,7 @@ from time import time
from neo import logging
from neo.locking import RLock
from neo.protocol import PacketMalformedError, Packets
from neo.protocol import PacketMalformedError, Packets, ParserState
from neo.connector import ConnectorException, ConnectorTryAgainException, \
ConnectorInProgressException, ConnectorConnectionRefusedException, \
ConnectorConnectionClosedException
......@@ -293,6 +293,7 @@ class Connection(BaseConnection):
self.uuid = None
self._queue = []
self._on_close = None
self._parser_state = ParserState()
event_manager.addReader(self)
def setOnClose(self, callback):
......@@ -359,7 +360,7 @@ class Connection(BaseConnection):
while True:
# parse a packet
try:
packet = Packets.parse(self.read_buf)
packet = Packets.parse(self.read_buf, self._parser_state)
if packet is None:
break
except PacketMalformedError, msg:
......
......@@ -1575,6 +1575,21 @@ def register(code, request, answer=None):
return (request, answer)
return request
class ParserState(object):
"""
Parser internal state.
To be considered opaque datatype outside of PacketRegistry.parse .
"""
payload = None
def set(self, payload):
self.payload = payload
def get(self):
return self.payload
def clear(self):
self.payload = None
class PacketRegistry(dict):
"""
......@@ -1586,11 +1601,12 @@ class PacketRegistry(dict):
# load packet classes
self.update(StaticRegistry)
def parse(self, buf):
if len(buf) < PACKET_HEADER_SIZE:
def parse(self, buf, state_container):
state = state_container.get()
if state is None:
header = buf.read(PACKET_HEADER_SIZE)
if header is None:
return None
header = buf.peek(PACKET_HEADER_SIZE)
assert header is not None
msg_id, msg_type, msg_len = unpack(PACKET_HEADER_FORMAT, header)
try:
packet_klass = self[msg_type]
......@@ -1600,14 +1616,17 @@ class PacketRegistry(dict):
raise PacketMalformedError('message too big (%d)' % msg_len)
if msg_len < MIN_PACKET_SIZE:
raise PacketMalformedError('message too small (%d)' % msg_len)
if len(buf) < msg_len:
msg_len -= PACKET_HEADER_SIZE
else:
msg_id, packet_klass, msg_len = state
data = buf.read(msg_len)
if data is None:
# Not enough.
state_container.set((msg_id, packet_klass, msg_len))
return None
buf.skip(PACKET_HEADER_SIZE)
msg_len -= PACKET_HEADER_SIZE
if state:
state_container.clear()
packet = packet_klass()
data = buf.read(msg_len)
assert data is not None
packet.setContent(msg_id, data)
return packet
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment