-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhelper.py
161 lines (135 loc) · 4.56 KB
/
helper.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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
import time
from dataclasses import dataclass
from enum import Enum
import struct
import socket
import threading
import random
class SegmentType(Enum):
DATA = 0
ACK = 1
SYN = 2
FIN = 3
class State(Enum):
CLOSED = 0
LISTEN = 1
SYN_SENT = 2
EST = 3
CLOSING = 4
FIN_WAIT = 5
TIME_WAIT = 6
FINISHED = 7
@dataclass
class SenderSegment:
""""Segment Data structure to store in sender buffer"""
seqno: int
segtype: SegmentType
data: bytes
@dataclass
class ReceiverSegment:
""""Segment Data structure to store in receiver buffer"""
seqno: int
segtype: SegmentType
data: int
@dataclass
class Control:
"""Control block: parameters for the sender program."""
sender_port: int # Port number of the sender
receiver_port: int # Port number of the receiver
socket: socket.socket # Socket for sending/receiving messages
run_time: int # Run time in seconds
start_time: float
timer: threading.Timer
last_segment_seqno: int
lock: threading.Lock
isn: int
dupACK_count= 0
send_base = 0
is_alive: bool = True # Flag to signal the sender program to terminate
sender_state: State = State.CLOSED
drop_fin: bool = False
drop_syn: bool = False
def log_message(user, type, seqno, num_bytes, action, start_time, first):
log_file = f"{user}_log.txt"
with open(log_file, 'a') as file:
if (first):
tim = 0.00
file.write(f"{action:<3} {tim:<11} {type.name:<4} {seqno:<5} 0\n")
else:
timestamp = round(time.time()*1000 - start_time, 2)
# print("timestamp:", timestamp)
file.write(f"{action:<3} {timestamp:<11} {type.name:<4} {seqno:<5} {num_bytes}\n")
def print_buff(buffer):
for segment in buffer:
if segment == None: print('None ', end='')
else: print(segment.seqno, end=' ')
print()
def create_segment(segtype, seqno, data):
segtype_bytes = segtype.value.to_bytes(2, "big")
seqno = seqno.to_bytes(2, "big")
header = segtype_bytes + seqno
header_int = int.from_bytes(header, "big")
stp_header = struct.pack('>I', header_int)
# segment = stp_header + data.encode('utf-8')
if type(data) is str: data = data.encode('utf-8')
segment = stp_header + data
return segment
def unpack_segment(buffer):
header = struct.unpack_from('>I', buffer, offset=0)[0]
segtype = SegmentType((header >> 16) & 0xFFFF)
seqno = header & 0xFFFF
if (segtype == SegmentType.SYN or segtype == SegmentType.FIN): data = ''
else: data = buffer[4:]
return segtype,seqno, data
def find_expected_segno(max_win, receive_buffer, index, buf, file_received):
expected_seqno = None
# f.write(str(receive_buffer[index].data, encoding='utf-8'))
cur_index = (index + 1) % len(receive_buffer)
# f = open(file_received, 'a')
while True:
current = receive_buffer[cur_index]
if current is None:
# f.write()
return expected_seqno, cur_index
else:
f = open(file_received, 'a')
f.write(str(receive_buffer[cur_index].data, encoding='utf-8'))
f.close()
expected_seqno = (current.seqno + len(receive_buffer[cur_index].data)) % (2**16)
# print(f"cur index: {cur_index}, len: {len(receive_buffer[cur_index].data)}")
print(f'write seqno: {current.seqno}')
receive_buffer[cur_index] = None
cur_index += 1
if cur_index == len(receive_buffer):
cur_index = 0
# f.close()
def write_to_file(max_win, receive_buffer, file_received):
for i in range(0, int(max_win / 1000)):
if not receive_buffer[i]:
break
else:
if (i == 0):
with open(file_received, 'w') as file:
file.write(chr(receive_buffer[i].data))
else:
with open(file_received, 'a') as file:
file.write(chr(receive_buffer[i].data))
return file
def is_to_be_dropped(probability):
# random.seed(1)
random_value = random.random()
if (random_value < probability):
return True
else:
return False
def remove_all_in_recv_buffer_if_full(buffer, max_win):
flag = True
for i in range(0, int(max_win / 1000)):
if buffer[i] == None:
flag = False
break
else: continue
if (flag == True):
for i in range(0, int(max_win / 1000)):
buffer[i] = None
return buffer