-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAlice.py
More file actions
61 lines (53 loc) · 1.91 KB
/
Alice.py
File metadata and controls
61 lines (53 loc) · 1.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import os, sys
import json
from socket import *
import zlib
# Sender Alice with 4 states: SEND_-1 -> WAIT_ACK_-1 -> SEND_1 -> WAIT_ACK_1 -> repeat
# packet has format = [ack, payload, checksum]
class Alice:
def __init__(self, port):
self.socket = socket(AF_INET, SOCK_DGRAM)
self.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
self.socket.connect(('127.0.0.1',port))
def set_timeout(self, timeout):
self.socket.settimeout(timeout)
def send(self, pkt):
self.socket.send(pkt)
def receive(self, bytes):
return self.socket.recvfrom(bytes)
def make_pkt(ack, payload):
checksum = zlib.crc32(json.dumps([ack, payload]).encode())
return zlib.compress(json.dumps([ack, payload, checksum]).encode())
def is_corrupt(pkt):
try:
pkt = json.loads(zlib.decompress(pkt).decode())
return pkt[2] != zlib.crc32(json.dumps(pkt[0:2]).encode())
except:
return True
def is_ack(pkt, num):
pkt = json.loads(zlib.decompress(pkt).decode())
return pkt[0] == num and pkt[1] == 'ack'
if __name__ == '__main__':
alice = Alice(int(sys.argv[1]))
data = sys.stdin
payload = ''
more_data = True
acknum = 1
# Keep sending the same piece when time out, until we get the correct ACK packet
while more_data:
payload = data.read(60)
pkt = make_pkt(acknum, payload)
not_done = True
while not_done:
try:
alice.set_timeout(0.0007)
msg, addr = alice.receive(4096)
if is_corrupt(msg) or is_ack(msg, -acknum):
alice.send(pkt)
else:
acknum = -acknum
not_done = False
except timeout:
alice.send(pkt)
if (payload == ''):
more_data = False