Skip to content

Commit

Permalink
Allow socket frames to be split in several packets.
Browse files Browse the repository at this point in the history
  • Loading branch information
janiversen committed Jan 4, 2024
1 parent 7feef8f commit f9c0ec5
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 33 deletions.
55 changes: 24 additions & 31 deletions pymodbus/framer/socket_framer.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,21 @@ def checkFrame(self):
Return true if we were successful.
"""
if self.isFrameReady():
(
self._header["tid"],
self._header["pid"],
self._header["len"],
self._header["uid"],
) = struct.unpack(">HHHB", self._buffer[0 : self._hsize])

# someone sent us an error? ignore it
if self._header["len"] < 2:
self.advanceFrame()
# we have at least a complete message, continue
elif len(self._buffer) - self._hsize + 1 >= self._header["len"]:
return True
if not self.isFrameReady():
return False
(
self._header["tid"],
self._header["pid"],
self._header["len"],
self._header["uid"],
) = struct.unpack(">HHHB", self._buffer[0 : self._hsize])

# someone sent us an error? ignore it
if self._header["len"] < 2:
self.advanceFrame()
# we have at least a complete message, continue
elif len(self._buffer) - self._hsize + 1 >= self._header["len"]:
return True
# we don't have enough of a message yet, wait
return False

Expand Down Expand Up @@ -128,23 +129,15 @@ def frameProcessIncomingPacket(self, single, callback, slave, tid=None, **kwargs
The processed and decoded messages are pushed to the callback
function to process and send.
"""
while True:
if not self.isFrameReady():
if len(self._buffer):
# Possible error ???
if self._header["len"] < 2:
self._process(callback, tid, error=True)
break
if not self.checkFrame():
Log.debug("Frame check failed, ignoring!!")
self.resetFrame()
continue
if not self._validate_slave_id(slave, single):
header_txt = self._header["uid"]
Log.debug("Not a valid slave id - {}, ignoring!!", header_txt)
self.resetFrame()
continue
self._process(callback, tid)
if not self.checkFrame():
Log.debug("Frame check failed, ignoring!!")
return
if not self._validate_slave_id(slave, single):
header_txt = self._header["uid"]
Log.debug("Not a valid slave id - {}, ignoring!!", header_txt)
self.resetFrame()
return
self._process(callback, tid)

def _process(self, callback, tid, error=False):
"""Process incoming packets irrespective error condition."""
Expand Down
6 changes: 4 additions & 2 deletions test/test_framers.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,11 +382,13 @@ def _handle_response(reply):
part2 = message[i:]
response_ok = False
framer = ModbusSocketFramer(ClientDecoder())
if i == 8:
print("jan")
if i:
try:
framer.processIncomingPacket(part1, _handle_response, slave=0)
except Exception:
pytest.fail("Exception should not happen")
assert not response_ok
assert not response_ok, "Response should not be accepted"
framer.processIncomingPacket(part2, _handle_response, slave=0)
assert response_ok
assert response_ok, "Response is valid, but not accepted"

0 comments on commit f9c0ec5

Please sign in to comment.