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
|
package main
import (
"fmt"
// "log"
"github.com/insomniacslk/dhcp/dhcpv6"
)
// FSM from RFC 2131 Figure 5
type DHCP interface {
SendDiscover()
SendRequest()
}
type FSM struct {
state State
dhcp DHCP
}
type DHCPv4 struct {
}
func (f FSM) Init(d DHCP) {
fmt.Println("Init")
f.dhcp = d
f.state = stInit(f.dhcp, nil)
// go
}
func (f FSM) InputMessage() {
}
func (d DHCPv4) SendDiscover() {
}
type DHCPv6 struct {
}
func (d DHCPv6) SendDiscover() {
fmt.Println("SendDiscover")
}
func (d DHCPv6) SendRequest() {
fmt.Println("SendRequest")
}
type EventType uint8
const (
EventTypeNone EventType = 0
EventTypeMessage EventType = 1
EventTypeTimeoutT1 EventType = 2
EventTypeTimeoutT2 EventType = 3
EventTypeTimeoutLease EventType = 3
)
type Event interface {
Type() EventType
}
// type TimerType uint8
// const (
// TimerNone TimerType = 0
// TimerT1 TimerType = 1
// TimerT2 TimerType = 2
// TimerLease TimerType = 3
// )
// type EventTimeout struct {
// Event
// Timer TimerType
// }
type EventMessage struct {
Event
msg dhcpv6.Message
}
func (ev *EventMessage) Type() EventType {
return EventTypeMessage
}
func (ev *EventMessage) Msg() dhcpv6.Message {
return ev.msg
}
type State func (d DHCP, ev Event) (next State)
func stInit(d DHCP, ev Event) State {
// Send Discover
d.SendDiscover()
return stSelecting
}
func stSelecting(d DHCP, ev Event) State {
switch ev.Type() {
case EventTypeMessage:
msg := ev.(*EventMessage).Msg()
switch msg.Type() {
case dhcpv6.MessageTypeAdvertise:
// Select first offer
d.SendRequest()
return stRequesting
}
}
return stSelecting
}
func stRequesting(d DHCP, ev Event) State {
switch ev.Type() {
case EventTypeMessage:
msg := ev.(*EventMessage).Msg()
switch msg.Type() {
case dhcpv6.MessageTypeAdvertise:
// Discard
return stRequesting
case dhcpv6.MessageTypeReply:
// Record lease, set T1, T2
return stBound
case dhcpv6.MessageTypeNone: // FIXME NAK
// Send Decline
return stInit
}
}
return stRequesting
}
func stBound(d DHCP, ev Event) State {
switch ev.Type() {
case EventTypeTimeoutT1:
// Send Request
return stRenewing
case EventTypeMessage:
msg := ev.(*EventMessage).Msg()
switch msg.Type() {
case dhcpv6.MessageTypeAdvertise:
case dhcpv6.MessageTypeReply:
case dhcpv6.MessageTypeNone:
// TODO or NACK
// Send Decline
return stBound
}
}
return stBound
}
func stRenewing(d DHCP, ev Event) State {
// FIXME
switch ev.Type() {
case EventTypeTimeoutT2:
// Broadcast request?
return stRebinding
case EventTypeMessage:
msg := ev.(*EventMessage).Msg()
switch msg.Type() {
case dhcpv6.MessageTypeReply:
// Record lease, set T1, T2
return stBound
case dhcpv6.MessageTypeNone: // FIXME NAK
// HALT network
return stInit
}
}
return stRenewing
}
func stRebinding(d DHCP, ev Event) State {
switch ev.Type() {
case EventTypeTimeoutLease:
// Halt network
return stInit
case EventTypeMessage:
msg := ev.(*EventMessage).Msg()
switch msg.Type() {
case dhcpv6.MessageTypeReply:
// Record lease, set timers T1, T2
return stBound
case dhcpv6.MessageTypeNone: // FIXME NAK
// Halt network
return stInit
}
}
return stRebinding
}
|