Created
December 22, 2016 08:27
-
-
Save alex-pat/929d79caff8333995a48e5d5a56c88c3 to your computer and use it in GitHub Desktop.
token ring
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import os | |
import sys | |
import random | |
import time | |
SD = b'S' | |
ED = b'E' | |
RING_SIZE = 5 | |
MONITOR = False | |
NAME = None | |
def eprint(*args, **kwargs): | |
print(*args, file=sys.stderr, **kwargs) | |
sys.stderr.flush() | |
def read(*args, **kwargs): | |
data = os.read(*args, **kwargs) | |
if len(data) == 0: | |
raise Exception | |
# eprint(data) | |
return data | |
def write(*args, **kwargs): | |
# eprint("write", *args, ** kwargs) | |
ret = os.write(*args, **kwargs) | |
sys.stdout.flush() | |
return ret | |
def countdown(): | |
for i in reversed(range(10)): | |
os.write(2, " Starting in {}\r".format(i).encode()) | |
time.sleep(1) | |
eprint("Started \n") | |
write(1, SD + b'\x00' + ED) | |
def parity_bit(bytes): | |
i = int.from_bytes(bytes, byteorder='little') | |
i = i - ((i >> 1) & 0x55555555) | |
i = (i & 0x33333333) + ((i >> 2) & 0x33333333) | |
i = (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24 | |
return int(i % 2) | |
def try_create_data(data): | |
dest = None | |
if not (data or random.randint(0, 5)): | |
data = os.urandom(3) | |
dest = random.randint(1, RING_SIZE) | |
if dest == NAME[0]: | |
dest = (dest - 2) % RING_SIZE + 1 | |
dest = bytes([dest]) | |
eprint("I have new data to send") | |
return data, dest | |
def getopts(): | |
global NAME, MONITOR | |
if len(sys.argv) >= 2: | |
NAME = bytes([int(sys.argv[1])]) | |
if sys.argv[2] == "-m": | |
MONITOR = True | |
else: | |
eprint("Bad params") | |
sys.exit(1) | |
def main(): | |
getopts() | |
os.write(2, "Name: {}, Monitor: {}\n".format(NAME, MONITOR).encode()) | |
MONITOR and countdown() | |
data = None | |
while True: | |
time.sleep(1) | |
if not data: | |
data, dest = try_create_data(data) | |
start = read(0, 1) | |
while start != SD: | |
write(1, start) | |
start = read(0, 1) | |
AC = int.from_bytes(read(0, 1), byteorder='little') | |
frame = AC & 0x10 | |
if MONITOR: | |
if AC & 0xE0: | |
AC = AC & 0xF7 | |
if frame and AC & 0x08: | |
eprint("BAD ERROR! FRAME CYCLED!") | |
sys.exit(1) | |
if not frame and AC & 0x08: | |
AC = AC & 0xF7 | |
if frame or AC & 0xE0: | |
AC = AC | 0x08 | |
Pr = (AC & 0xE0) >> 5 | |
Rr = AC & 0x07 | |
Pf = NAME[0] | |
if not frame: | |
if read(0, 1) != ED: | |
eprint("BAD ERROR! ED IS NOT ED!") | |
sys.exit(1) | |
if not data: | |
write(1, SD + bytes([AC]) + ED) | |
continue | |
if Pf < Pr: | |
if Pf > Rr: | |
eprint("Can't reserve empty marker: Rr is too big") | |
write(1, SD + bytes([AC]) + ED) | |
continue | |
eprint("Reserving empty marker") | |
marker = SD + bytes([(Pr << 5) | (AC & 0x18) | Pf]) + ED | |
write(1, marker) | |
continue | |
res_frame = SD + bytes([(Pf << 5) | 0x10 | (AC & 0x08)]) | |
res_frame += dest + NAME + data | |
res_frame += bytes([parity_bit(data)]) | |
res_frame += ED | |
write(1, res_frame) | |
eprint("Sending 0x{data} to {dest} ...".format( | |
data=data.hex(), | |
dest=dest[0] | |
)) | |
continue | |
frame_tail = read(0, 7) | |
r_DA = frame_tail[0] | |
r_SA = frame_tail[1] | |
r_DATA = frame_tail[2:5] | |
r_PB = frame_tail[5] | |
r_ED = frame_tail[6] | |
if bytes([r_ED]) != ED: | |
eprint("BAD ERROR! ED IS NOT ED!") | |
sys.exit(1) | |
if r_PB != parity_bit(r_DATA): | |
eprint("BAD ERROR! PARITY BIT WRONG!") | |
sys.exit(1) | |
if r_DA == NAME[0]: | |
eprint("Received message 0x{data} from {source}".format( | |
data=r_DATA.hex(), | |
source=r_SA | |
)) | |
t_frame = ( | |
SD + | |
bytes([AC, 0, r_SA]) + | |
r_DATA + | |
bytes([r_PB, r_ED]) | |
) | |
write(1, t_frame) | |
data = None | |
continue | |
if r_SA == NAME[0]: | |
if r_DA: | |
eprint("Message not readed") | |
eprint("Releasing marker...") | |
t_marker = ( | |
SD + | |
bytes([(Rr << 5) | (AC & 8)]) + | |
ED | |
) | |
write(1, t_marker) | |
data = None | |
continue | |
if data and Pf >= Pr: | |
eprint("Reserving marker") | |
AC = (AC & 0xF8) | Pf | |
t_frame = ( | |
SD + | |
bytes([AC]) + | |
frame_tail | |
) | |
write(1, t_frame) | |
if __name__ == "__main__": | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
myncat() { | |
while ! ncat "$1" "$2" 2>/dev/null | |
do | |
sleep 0.1 | |
done | |
} | |
if [ -z "$5" ]; then | |
echo "Usage: $0 LISTEN_IP LISTEN_PORT WRITE_IP WRITE_PORT NAME [-m]" | |
exit 1 | |
fi | |
ncat -l "$1" "$2" | python3 ./main.py "$5" "$6" | myncat "$3" "$4" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment