due to educational purposes I have some scenarios to deal with.
The main one is to simulate a noisy serial line using socat (I currently have version 1.7.4)
I’ll elaborate:
I have software that has to do with protocols over serial. I need to test its reliability and performance against errors and communication problems, in short against noisy channels.
With socat I can create a “clean” virtual channel:
socat -d -d -v -x pty,raw,echo=0,link=/tmp/ttyV1 pty,raw,echo=0,link=/tmp/ttyV2
I’m looking for a way for the data to be “corrupted” in the way between ttyV1
and ttyV2
(and vice versa).
I was thinking of a python script that somehow receives the data sent to ttyV1
, processes it, and then transmits it to ttyV2
.
I tried it by running 3 instances of socat:
- socatX: is what creates pty with
socat -d -d -v -x pty,raw,echo=0,link=/tmp/ttyV1 pty,raw,echo=0,link=/tmp/ttyV2
- socat1: is
socat -d -d -v -x /tmp/ttyV1,raw,echo=0 EXEC: "python3 disturb_script.py",pty,raw,echo=0
- socat2: is
socat -d -d -v -x /tmp/ttyV2,raw,echo=0 EXEC: "python3 disturb_script.py",pty,raw,echo=0
in this case by sending data to /tmp/ttyV1
, for example with cat >/tmp/ttyV1
, I see data flowing without modification. I see the data trace (thanks to the -x -v
parameters of socat) only in the socatX session.
I tried terminating socat1 and socat2, without touching socatX, and the data continues to flow. So I thought that sending the data to /tmp/ttyV1
only involves socatX.
then I changed something:
- socat1: create the first pty with
socat -d -d -v -x pty,raw,echo=0,link=/tmp/ttyV1 EXEC: "python3 disturb_script.py",pty,raw,echo=0
- socat2: create the second pty with
socat -d -d -v -x pty,raw,echo=0,link=/tmp/ttyV2 EXEC: "python3 disturb_script.py",pty,raw,echo=0
- socatX: I would like it to link the two pty using
socat -d -d -v -x /tmp/ttyV1,raw,echo=0 /tmp/ttyV2,raw,echo=0
in this case the data, always sent with cat >/tmp/ttyV1
, does not pass on /tmp/ttyV2
. And I can see the data traces only on socat1.
the python script is this:
import sys
import random
import os
def disturb(data):
""" Disturb data by altering or deleting characters. """
result = bytearray()
for byte in data:
if random.random() < 0.1: # 10% chance to change a bit in a byte
byte ^= 1 << random.randint(0, 7)
if random.random() > 0.05: # 95% chance to keep the byte
result.append(byte)
return bytes(result)
def main():
while True:
data = sys.stdin.buffer.read(128)
if not data:
break
print(f"Received data: {data}") # Debug print
disturbed_data = disturb(data)
print(f"Sending data: {disturbed_data}") # Debug print
sys.stdout.buffer.write(disturbed_data)
sys.stdout.buffer.flush()
if __name__ == '__main__':
main()
How can I get to my goal?
PS:
In the beginning I told you about other scenarios.
Another scenario is one where I have a true serial; I should create a virtual serial connected to it, and in between put a script that processes (encrypts/decrypts) the data