-
Notifications
You must be signed in to change notification settings - Fork 0
/
scratch_2.py
139 lines (101 loc) · 4.85 KB
/
scratch_2.py
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import asyncio
import websockets
from pathlib import Path
import struct
# request tags
SEND_REQUEST_TAG = 0x00
REPLY_REQUEST_TAG = 0x01
SELF_ADDRESS_REQUEST_TAG = 0x02
# response tags
ERROR_RESPONSE_TAG = 0x00
RECEIVED_RESPONSE_TAG = 0x01
SELF_ADDRESS_RESPONSE_TAG = 0x02
def make_self_address_request() -> bytes:
return bytes([SELF_ADDRESS_REQUEST_TAG])
def parse_self_address_response(raw_response: bytes) -> bytes:
if len(raw_response) != 97 or raw_response[0] != SELF_ADDRESS_RESPONSE_TAG:
print('Received invalid response!')
raise
return raw_response[1:]
def make_send_request(recipient: bytes, message: bytes, with_reply_surb: bool) -> bytes:
# a big endian uint64
message_len = len(message).to_bytes(length=8, byteorder='big', signed=False)
return bytes([SEND_REQUEST_TAG]) + bytes([with_reply_surb]) + recipient + message_len + message
def make_reply_request(message: bytes, reply_surb: bytes) -> bytes:
message_len = len(message).to_bytes(length=8, byteorder='big', signed=False)
surb_len = len(reply_surb).to_bytes(length=8, byteorder='big', signed=False)
return bytes([REPLY_REQUEST_TAG]) + surb_len + reply_surb + message_len + message
# it should have structure of RECEIVED_RESPONSE_TAG || with_reply || (surb_len || surb) || msg_len || msg
# where surb_len || surb is only present if 'with_reply' is true
def parse_received(raw_response: bytes) -> (bytes, bytes):
if raw_response[0] != RECEIVED_RESPONSE_TAG:
print('Received invalid response!')
raise
if raw_response[1] == 1:
has_surb = True
elif raw_response[1] == 0:
has_surb = False
else:
print("malformed received response!")
raise
data = raw_response[2:]
if has_surb:
(surb_len,), other = struct.unpack(">Q", data[:8]), data[8:]
surb = other[:surb_len]
(msg_len,) = struct.unpack(">Q", other[surb_len:surb_len + 8])
if len(other[surb_len + 8:]) != msg_len:
print("invalid msg len")
raise
msg = other[surb_len + 8:]
return msg, surb
else:
(msg_len,), other = struct.unpack(">Q", data[:8]), data[8:]
if len(other) != msg_len:
print("invalid msg len")
raise
msg = other[:msg_len]
return msg, None
async def send_file_with_reply():
uri = "ws://localhost:1977"
async with websockets.connect(uri) as websocket:
self_address_req = make_self_address_request()
await websocket.send(self_address_req)
self_address = parse_self_address_response(await websocket.recv())
file_data = Path('dummy_file').read_bytes()
send_request = make_send_request(self_address, file_data, True)
print("sending content of 'dummy_file' over the mix network...")
await websocket.send(send_request)
print("waiting to receive the 'dummy_file' from the mix network...")
received_response = await websocket.recv()
received_file, surb = parse_received(received_response)
with open("received_file_withreply", "wb") as output_file:
print("writing the file back to the disk!")
output_file.write(received_file)
reply_message = b"hello from reply SURB! - thanks for sending me the file!"
reply_request = make_reply_request(reply_message, surb)
print("sending '{}' (using reply SURB!) over the mix network...".format(reply_message))
await websocket.send(reply_request)
print("waiting to receive a message from the mix network...")
received_response = await websocket.recv()
received_msg, surb = parse_received(received_response)
assert surb is None # no surbs in replies!
print("received '{}' from the mix network".format(received_msg))
async def send_file_without_reply():
uri = "ws://localhost:1977"
async with websockets.connect(uri) as websocket:
self_address_req = make_self_address_request()
await websocket.send(self_address_req)
self_address = parse_self_address_response(await websocket.recv())
file_data = Path('dummy_file').read_bytes()
send_request = make_send_request(self_address, file_data, False)
print("sending content of 'dummy_file' over the mix network...")
await websocket.send(send_request)
print("waiting to receive the 'dummy_file' from the mix network...")
received_response = await websocket.recv()
received_file, surb = parse_received(received_response)
assert surb is None # we didn't attach a surb so we expect a None here!
with open("received_file_noreply", "wb") as output_file:
print("writing the file back to the disk!")
output_file.write(received_file)
# asyncio.get_event_loop().run_until_complete(send_file_without_reply())
asyncio.get_event_loop().run_until_complete(send_file_with_reply())