This repository was archived by the owner on Jul 26, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmockiface.go
More file actions
155 lines (143 loc) · 3.54 KB
/
Copy pathmockiface.go
File metadata and controls
155 lines (143 loc) · 3.54 KB
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
package gomulticast
import (
"net"
"github.com/nitroshare/golist"
)
// MockInterface implements Interface and provides methods for sending and
// receiving packets on the interface. Only one Listener should be created
// for each MockInterface.
type MockInterface struct {
chanQueueForRead chan *Packet
chanQueueForReadRet chan any
chanReadRequest chan any
chanReadReply chan *Packet
chanWrite chan *Packet
chanWriteRet chan any
chanDequeueRequest chan any
chanDequeueReply chan *Packet
chanTest chan any
chanClose chan any
chanClosed chan any
errOnNextRead bool
}
func (m *MockInterface) run() {
defer close(m.chanClosed)
defer close(m.chanReadReply)
defer close(m.chanDequeueReply)
var (
readQueue = &golist.List[*Packet]{}
writeQueue = &golist.List[*Packet]{}
waitingForRead bool
waitingForDequeue bool
)
for {
select {
case p := <-m.chanQueueForRead:
if waitingForRead {
m.chanReadReply <- p
waitingForRead = false
} else {
readQueue.Add(p)
}
m.chanQueueForReadRet <- nil
case <-m.chanReadRequest:
e := readQueue.PopFront()
if e != nil {
m.chanReadReply <- e.Value
} else {
if m.chanTest != nil {
m.chanTest <- nil
}
waitingForRead = true
}
case p := <-m.chanWrite:
if waitingForDequeue {
m.chanDequeueReply <- p
waitingForDequeue = false
} else {
writeQueue.Add(p)
}
m.chanWriteRet <- nil
case <-m.chanDequeueRequest:
e := writeQueue.PopFront()
if e != nil {
m.chanDequeueReply <- e.Value
} else {
if m.chanTest != nil {
m.chanTest <- nil
}
waitingForDequeue = true
}
case <-m.chanClose:
return
}
}
}
// NewMockInterface initializes a new instance of MockInterface.
func NewMockInterface() *MockInterface {
m := &MockInterface{
chanQueueForRead: make(chan *Packet),
chanQueueForReadRet: make(chan any),
chanReadRequest: make(chan any),
chanReadReply: make(chan *Packet),
chanWrite: make(chan *Packet),
chanWriteRet: make(chan any),
chanDequeueRequest: make(chan any),
chanDequeueReply: make(chan *Packet),
chanClose: make(chan any),
chanClosed: make(chan any),
}
go m.run()
return m
}
func (m MockInterface) Interface() *net.Interface {
return &net.Interface{
MTU: 1500,
Name: "MockInterface",
Flags: net.FlagUp & net.FlagRunning & net.FlagMulticast,
}
}
// QueueForRead queues the provided packet for reading in a subsequent call to
// Listener.Read().
func (m *MockInterface) QueueForRead(p *Packet) {
m.chanQueueForRead <- p
<-m.chanQueueForReadRet
}
// DequeueWrite returns packets written to the Listener in order. This call
// will block until a packet is written or the connection is closed.
func (m *MockInterface) DequeueWrite() (*Packet, error) {
m.chanDequeueRequest <- nil
p, ok := <-m.chanDequeueReply
if !ok {
return nil, net.ErrClosed
}
return p, nil
}
type mockUDPConn struct {
i *MockInterface
}
func (m *mockUDPConn) ReadFrom(b []byte) (int, net.Addr, error) {
if m.i.errOnNextRead {
m.i.errOnNextRead = false
return 0, nil, net.ErrClosed
}
m.i.chanReadRequest <- nil
p, ok := <-m.i.chanReadReply
if !ok {
return 0, nil, net.ErrClosed
}
return copy(b, p.Data), p.Addr, nil
}
func (m *mockUDPConn) WriteTo(b []byte, addr net.Addr) (int, error) {
m.i.chanWrite <- &Packet{
Addr: addr,
Data: b,
}
<-m.i.chanWriteRet
return len(b), nil
}
func (m *mockUDPConn) Close() error {
close(m.i.chanClose)
<-m.i.chanClosed
return nil
}