-
Notifications
You must be signed in to change notification settings - Fork 0
/
FSM.py
370 lines (330 loc) · 13.8 KB
/
FSM.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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
import time
from threading import Thread
from State import State as ST
from Packet import Packet as pk
"""
以下是各种状态的转换方法
xxx_transition表示现在正在xxx状态下
"""
# 因为CLOSE WAIT->LAST_ACK是过一段时间主动发送,所以我们记录从ESTABLISH->CLOSE_WAIT的包
CLOSEWAIT_Seq = 0
CLOSEWAIT_ACK = 0
class FSM(Thread):
def __init__(self):
super().__init__()
self.state = ST.CLOSED
def CLOSED_Transition(self, option=None) -> (ST, pk):
# ActiveOpen 不收包,发包
if option == 'ActiveOpen':
self.state, send_packet = self.CLOSED_2_SYN_SENT()
return self.state, send_packet
# PassiveOpen 不收包,不发包
elif option == 'PassiveOpen':
self.state = self.CLOSED_2_LISTEN()
return self.state
else:
return self.state
def LISTEN_Transition(self, recv_packet=None, option=None) -> (ST, pk):
# ActiveOpen 不收包,发包
if option == 'ActiveOpen':
self.state, send_packet = self.LISTEN_2_SYN_SENT()
return self.state, send_packet
# 收包,发包
else:
self.state, send_packet = self.LISTEN_2_SYN_RCVD(recv_packet)
return self.state, send_packet
def SYN_SENT_Transition(self, recv_packet=None, option=None) -> (ST, pk):
# TimeOut 不收包,不发包
if option == 'TimeOut':
self.state = self.SYN_SENT_2_CLOSED()
return self.state
# ActiveClose 不收包,不发包
elif option == 'ActiveClose':
self.state = self.SYN_SENT_2_CLOSED()
return self.state
# 进入Establish 收包,不发包
# 进入SYN_RCVD 收包,发包
else:
self.state, send_packet = self.SYN_SENT_2_transition(recv_packet)
return self.state, send_packet
def SYN_RCVD_Transition(self, recv_packet=None, option=None) -> (ST, pk):
# ActiveClose 收包,发包
if option == 'ActiveClose':
self.state, send_packet = self.SYN_RCVD_2_FIN_WAIT_1(recv_packet)
return self.state, send_packet
# 进入Established 收包,不发包
else:
self.state = self.SYN_RCVD_2_ESTABLISHED(recv_packet)
return self.state
def ESTABLISH_Transition(self, recv_packet=None, option=None) -> (ST, pk):
# ActiveClose 收包,发包
if option == 'ActiveClose':
self.state, send_packet = self.ESTABLISHED_2_FIN_WAIT_1_transition()
return self.state, send_packet
# 正常传包/收到Fin关闭 收包,发包
else:
self.state, send_packet = self.ESTABLISHED_2_transmit(recv_packet)
return self.state, send_packet
def CLOSE_WAIT_Transition(self, option=None) -> (ST, pk):
# 自动关闭,不收包,发包
self.state, send_packet = self.CLOSE_WAIT_2_LAST_ACK()
return self.state, send_packet
def LAST_ACK_Transition(self, recv_packet=None, option=None) -> (ST, pk):
# 收到ACK关闭,收包,不发包
self.state = self.LAST_ACK_2_CLOSED(recv_packet)
return self.state
def FIN_WAIT_1_Transition(self, recv_packet=None) -> (ST, pk):
# Receive ACK for FIN
# transitions to the FIN-WAIT-2 state
# Receive FIN, Send ACK
# moves to the CLOSING state
# Receive FIN and ACK, Send ACK
# moves to the TIME_WAIT state
self.state, send_packet = self.FIN_WAIT_1_transition(recv_packet)
return self.state, send_packet
def FIN_WAIT_2_Transition(self, recv_packet=None, option=None) -> (ST, pk):
# 收包,发包
self.state, send_packet = self.FIN_WAIT_2_2_TIME_WAIT(recv_packet)
return self.state, send_packet
def CLOSING_Transition(self, recv_packet=None, option=None) -> (ST, pk):
# 收包,不发包
self.state, send_packet = self.CLOSING_2_TIME_WAIT(recv_packet)
return self.state
def TIME_WAIT_Transition(self, recv_packet=None, option=None) -> (ST, pk):
# 不收包,不发包
self.state, send_packet = self.TIME_WAIT_2_CLOSED()
return self.state, send_packet
# 主动打开
# Active Open, Send SYN
# transitions to the SYN-SENT state
def CLOSED_2_SYN_SENT(self) -> (ST, pk):
assert self.state == ST.CLOSED
self.state = ST.SYN_SENT
send_packet = pk()
send_packet.set_SYN()
send_packet.set_th_seq(0) # 初次建立从0开始
send_packet.set_th_ack(0)
return self.state, send_packet
# Passive Open
# transitions to the LISTEN state
def CLOSED_2_LISTEN(self) -> (ST, pk):
assert self.state == ST.CLOSED
self.state = ST.LISTEN
return self.state
# 主动打开
# Send SYN
# transitions to the SYN_SENT state
def LISTEN_2_SYN_SENT(self) -> (ST, pk):
assert self.state == ST.LISTEN
self.state = ST.SYN_SENT
send_packet = pk()
send_packet.set_SYN()
send_packet.set_th_seq(0) # 初次建立从0开始
send_packet.set_th_ack(0)
return self.state, send_packet
# Receive Client SYN, Send SYN+ACK
# moves to the SYN-RECEIVED state
def LISTEN_2_SYN_RCVD(self, recv_packet) -> (ST, pk):
assert self.state == ST.LISTEN
if recv_packet.get_SYN():
self.state = ST.SYN_RCVD
send_packet = pk()
send_packet.set_ACK()
send_packet.set_SYN()
send_packet.set_th_seq(0) # 初次建立从0开始
if len(recv_packet.get_PAYLOAD()) == 0:
send_packet.set_th_ack(recv_packet.get_th_seq() + 1)
else:
send_packet.set_th_ack(recv_packet.get_th_seq() + len(recv_packet.get_th_PAYLOAD()))
return self.state, send_packet
else:
return self.state
# Receive SYN, Send ACK
# transitions to SYN-RECEIVED
# Receive SYN+ACK, Send ACK
# ESTABLISHED state
def SYN_SENT_2_transition(self, recv_packet) -> (ST, pk):
assert self.state == ST.SYN_SENT
if recv_packet.get_SYN() == 1 and recv_packet.get_ACK() == 0:
self.state = ST.SYN_RCVD
send_packet = pk()
send_packet.set_ACK()
send_packet.set_th_seq(recv_packet.get_th_ack())
if len(recv_packet.get_PAYLOAD()) == 0:
send_packet.set_th_ack(recv_packet.get_th_seq() + 1)
else:
send_packet.set_th_ack(recv_packet.get_th_seq() + len(recv_packet.get_PAYLOAD()))
return self.state, send_packet
elif recv_packet.get_SYN() == 1 and recv_packet.get_ACK() == 1:
self.state = ST.ESTABLISHED
send_packet = pk()
send_packet.set_ACK()
send_packet.set_th_seq(recv_packet.get_th_ack())
if len(recv_packet.get_PAYLOAD()) == 0:
send_packet.set_th_ack(recv_packet.get_th_seq() + 1)
else:
send_packet.set_th_ack(recv_packet.get_th_seq() + len(recv_packet.get_PAYLOAD()))
return self.state, send_packet
else:
return self.state
# 超时或主动关闭引起的情况
def SYN_SENT_2_CLOSED(self) -> (ST, pk):
assert self.state == ST.SYN_SENT
self.state = ST.CLOSED
return self.state
# Receive ACK
# transitions to the ESTABLISHED state
def SYN_RCVD_2_ESTABLISHED(self, recv_packet) -> ST:
assert self.state == ST.SYN_RCVD
if recv_packet.get_ACK() == 1:
self.state = ST.ESTABLISHED
return self.state
else:
return self.state
# 超时引起的情况
# Close, Send RST
# def SYN_RCVD_2_CLOSED(self, recv_packet) -> (ST, pk):
# assert self.state == ST.SYN_RCVD
# self.state = ST.CLOSED
# send_packet = pk()
# send_packet.set_RST()
# send_packet.set_th_seq(recv_packet.get_ACK)
# if len(recv_packet.get_th_PAYLOAD()) == 0:
# send_packet.set_th_ack(recv_packet.get_th_seq() + 1)
# else:
# send_packet.set_th_ack(recv_packet.get_th_seq() + len(recv_packet.get_PAYLOAD()))
# return self.state, send_packet
# 关闭引起的情况
# Send FIN
def SYN_RCVD_2_FIN_WAIT_1(self, recv_packet) -> (ST, pk):
assert self.state == ST.SYN_RCVD
self.state = ST.FIN_WAIT_1
send_packet = pk()
send_packet.set_FIN()
send_packet.set_th_seq(recv_packet.get_ACK)
if len(recv_packet.get_th_PAYLOAD()) == 0:
send_packet.set_th_ack(recv_packet.get_th_seq() + 1)
else:
send_packet.set_th_ack(recv_packet.get_th_seq() + len(recv_packet.get_PAYLOAD()))
return self.state, send_packet
# todo 缺少了ACK和SEQ num的记录,理论上要在Establish中做记录
# 主动关闭
# Close, Send FIN
# transition to the FIN-WAIT-1 state
def ESTABLISHED_2_FIN_WAIT_1_transition(self) -> (ST, pk):
assert self.state == ST.ESTABLISHED
self.state = ST.FIN_WAIT_1
send_packet = pk()
send_packet.set_FIN()
# todo SEQ 和 ACK num 都需要改
send_packet.set_th_seq(1)
send_packet.set_th_ack(1)
return self.state, send_packet
# Basic Transmit State
# Receive FIN
# transition to the CLOSE-WAIT state.
def ESTABLISHED_2_transmit(self, recv_packet) -> (ST, pk):
assert self.state == ST.ESTABLISHED
if recv_packet.get_FIN():
self.state = ST.CLOSE_WAIT
send_packet = pk()
send_packet.set_ACK()
send_packet.set_th_seq(recv_packet.get_th_ack())
CLOSEWAIT_Seq = recv_packet.get_th_ack() + 1
if len(recv_packet.get_PAYLOAD()) == 0:
send_packet.set_th_ack(recv_packet.get_th_seq() + 1)
CLOSEWAIT_ACK = recv_packet.get_th_seq() + 1
else:
send_packet.set_th_ack(recv_packet.get_th_seq() + len(recv_packet.get_PAYLOAD()))
CLOSEWAIT_ACK = recv_packet.get_th_seq() + len(recv_packet.get_PAYLOAD())
return self.state, send_packet
else:
send_packet = pk()
send_packet.set_th_seq(recv_packet.get_th_ack())
if len(recv_packet.get_PAYLOAD()) == 0:
send_packet.set_th_ack(recv_packet.get_th_seq() + 1)
else:
send_packet.set_th_ack(recv_packet.get_th_seq() + len(recv_packet.get_PAYLOAD()))
return self.state, send_packet
# Close, Send FIN
# transitions to LAST-ACK.
def CLOSE_WAIT_2_LAST_ACK(self) -> (ST, pk):
assert self.state == ST.CLOSE_WAIT
self.state = ST.LAST_ACK
send_packet = pk()
send_packet.set_FIN()
send_packet.set_th_seq(CLOSEWAIT_Seq)
send_packet.set_th_ack(CLOSEWAIT_ACK)
return self.state, send_packet
# Receive ACK
# transitions to CLOSED
def LAST_ACK_2_CLOSED(self, recv_packet) -> (ST, pk):
assert self.state == ST.LAST_ACK
if recv_packet.get_ACK():
self.state = ST.CLOSED
return self.state
else:
return self.state
# Receive ACK for FIN
# transitions to the FIN-WAIT-2 state
# Receive FIN, Send ACK
# moves to the CLOSING state
# Receive FIN and ACK, Send ACK
# moves to the TIME_WAIT state
def FIN_WAIT_1_transition(self, recv_packet) -> (ST, pk):
assert self.state == ST.FIN_WAIT_1
if recv_packet.get_ACK() and not recv_packet.get_FIN():
self.state = ST.FIN_WAIT_2
return self.state, None
elif recv_packet.get_FIN() and not recv_packet.get_ACK():
self.state = ST.CLOSING
send_packet = pk()
send_packet.set_ACK()
send_packet.set_th_seq(recv_packet.get_ACK)
if len(recv_packet.get_th_PAYLOAD()) == 0:
send_packet.set_th_ack(recv_packet.get_th_seq() + 1)
else:
send_packet.set_th_ack(recv_packet.get_th_seq() + len(recv_packet.get_PAYLOAD()))
return self.state, send_packet
elif recv_packet.get_FIN() and recv_packet.get_ACK():
self.state = ST.TIME_WAIT
send_packet = pk()
send_packet.set_ACK()
send_packet.set_th_seq(recv_packet.get_ACK)
if len(recv_packet.get_th_PAYLOAD()) == 0:
send_packet.set_th_ack(recv_packet.get_th_seq() + 1)
else:
send_packet.set_th_ack(recv_packet.get_th_seq() + len(recv_packet.get_PAYLOAD()))
return self.state, send_packet
else:
return self.state, None
# Receive FIN, Send ACK
# moves to the TIME-WAIT state
def FIN_WAIT_2_2_TIME_WAIT(self, recv_packet) -> (ST, pk):
assert self.state == ST.FIN_WAIT_2
if recv_packet.get_FIN():
self.state = ST.TIME_WAIT
send_packet = pk()
send_packet.set_ACK()
send_packet.set_th_seq(recv_packet.get_th_ack())
if len(recv_packet.get_PAYLOAD()) == 0:
send_packet.set_th_ack(recv_packet.get_th_seq() + 1)
else:
send_packet.set_th_ack(recv_packet.get_th_seq() + len(recv_packet.get_PAYLOAD()))
return self.state, send_packet
else:
return self.state, None
# Receive ACK for FIN
# transitions to the TIME-WAIT stat
def CLOSING_2_TIME_WAIT(self, recv_packet) -> (ST, pk):
assert self.state == ST.CLOSING
if recv_packet.get_ACK():
self.state = ST.TIME_WAIT
return self.state
else:
return self.state
# After a designated wait period, device transitions to the CLOSED state.
def TIME_WAIT_2_CLOSED(self, recv_packet=None) -> (ST, pk):
assert self.state == ST.TIME_WAIT
self.state = ST.CLOSED
return self.state, None