-
Notifications
You must be signed in to change notification settings - Fork 0
/
channel.py
192 lines (152 loc) · 6.27 KB
/
channel.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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
import sys
import socket
import select
import socket
import select
import random
import packet
import pickle
def store_in_buffer(packet):
#this is a function that receive a packet and then put the data into a buffer to send
the_tuple = (packet.magicno, packet.the_type, packet.seqno, packet.dataLen, packet.data)
packet_buffer = pickle.dumps(the_tuple)
return packet_buffer
def recover_from_buffer(the_buffer):
#this is a function that receive the buffer and then convert it into a packet
the_tuple = pickle.loads(the_buffer)
new_packet = packet.Packet(the_tuple[0], the_tuple[1], the_tuple[2], the_tuple[3], the_tuple[4])
return new_packet
# a function receive a list of number, return True if they are all distinct
# otherwise, return False
def are_different(number_list):
new_list = []
new_list.append(number_list[0])
length = len(number_list)
current = 1
stop = False
while (current < length and not stop):
if number_list[current] not in new_list:
new_list.append(number_list[current])
current += 1
else:
stop = True
if stop == True:
return False
else:
return True
def main(argv):
#check the seven parameters from command line
try:
cs_in_portnum = int(argv[1])
cs_out_portnum = int(argv[2])
cr_in_portnum = int(argv[3])
cr_out_portnum = int(argv[4])
#check their range valid or not
for portnum in [cs_in_portnum, cs_out_portnum, cr_in_portnum, cs_out_portnum]:
if not ((portnum <= 64000 and portnum >= 1024) or type(portnum) == int):
raise Exception ("Error on port number - out of range")
s_in_portnum = int(argv[5])
r_in_portnum = int(argv[6])
packet_loss_rate = float(argv[7])
#check the rate
if not (packet_loss_rate >= 0 and packet_loss_rate < 1):
raise Exception ("Error on packet loss rate")
except:
print("-------------------------------------------------------------------------------------------------------------")
print("Please Enter 7 arguments in the order following:")
print("python3 channel.py CS_IN_portnumber CS_OUT_portnumber CR_IN_portnumber CR_OUT_portnumber S_IN_portnumber R_IN_portnumber LOSS_RATE")
print("-------------------------------------------------------------------------------------------------------------")
raise Exception ("Error on accepting command line parameters")
#create its four sockets
try:
cs_out = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
except socket.error:
print ("Failed to create socket cs_out")
sys.exit()
try:
cs_in = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
except socket.error:
print ("Failed to create socket cs_in")
sys.exit()
try:
cr_out = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
except socket.error:
print ("Failed to create socket cr_out")
sys.exit()
try:
cr_in = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
except socket.error:
print ("Failed to create socket cr_in")
sys.exit()
#bind all sockets
try:
cs_out.connect(("localhost", s_in_portnum))
cr_out.connect(("localhost", r_in_portnum))
except:
raise Exception ("Error on binding sockets")
try:
cs_in.bind(("localhost", cs_in_portnum))
except (socket.error , msg):
print ('Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
sys.exit()
try:
cr_in.bind(("localhost", cr_in_portnum))
except (socket.error , msg):
print ('Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
sys.exit()
#check the port numbers used are all dinstinct
if not are_different([cs_out_portnum, cs_in_portnum, cr_in_portnum, cr_out_portnum]):
raise Exception ("Error on port numbers, they should be distinct")
input_list = [cs_in, cr_in] # this is a list for select() function
#Now, enter an infinite loop
while True:
#use the select() function to process all packets
inputready, outputready, exceptready = select.select(input_list, [], [])
for s in inputready:
if s == cs_in:
#handle the cs_in socket
try:
rcvd = cs_in.recv(600)
except:
raise Exception ("Error on receiving data at cs_in socket")
the_packet = recover_from_buffer(rcvd)
print("the size of cs_in packet is: ", sys.getsizeof(the_packet))
if the_packet.magicno != 0x497E:
break
u = random.random()
if u < packet_loss_rate:
#drop this packet
break
else:
#keep this packet
packet_buffer = store_in_buffer(the_packet)
print("the size of cs_in packet_buffer is: ", sys.getsizeof(packet_buffer))
try:
cr_out.send(packet_buffer)
except:
raise Exception ("Error on sending data from cr_out socket")
elif s == cr_in:
#handle the sr_in socket
try:
rcvd = cr_in.recv(600)
except:
raise Exception ("Error on receiving data at cr_in socket")
the_packet = recover_from_buffer(rcvd)
print("the size of cr_in packet is: ", sys.getsizeof(the_packet))
if the_packet.magicno != 0x497E:
break
u = random.random()
if u < packet_loss_rate:
#drop the packet
break
else:
#keep the packet
packet_buffer = store_in_buffer(the_packet)
print("the size of cr_in packet_buffer is: ", sys.getsizeof(packet_buffer))
try:
cs_out.send(packet_buffer)
except:
raise Exception ("Error on sending data from cs_out socket")
else:
print ("Unknown socket.")
main(sys.argv)