godep: update h2so5/utp
the godep tool is toying with me...
Henry committed
Apr 28, 2015 at 13:40 UTC
9ff03782ee891a7f36841469872d689d9598a615
20 files changed
+1962
-1597
Godeps/Godeps.json
+1
-1
@@ -96,7 +96,7 @@
96
},
97
{
98
"ImportPath": "github.com/h2so5/utp",
99
- "Rev": "654d875bb65e96729678180215cf080fe2810371"
99
+ "Rev": "6ca83358f5c331028feb9b97c445e9c7354967b0"
100
},
101
{
102
"ImportPath": "github.com/hashicorp/go.net/ipv4",
Godeps/_workspace/src/github.com/h2so5/utp/.travis.yml
+3
-1
@@ -1,7 +1,9 @@
1
language: go
2
3
script:
4
- - GO_UTP_LOGGING=2 go test -v -bench .
4
+ - GO_UTP_LOGGING=2 go test -v
5
+ - GOMAXPROCS=4 GO_UTP_LOGGING=2 go test -v
6
- go test -v -race
7
- GO_UTP_LOGGING=2 go run benchmark/main.go -h
8
+ - GOMAXPROCS=4 GO_UTP_LOGGING=2 go run benchmark/main.go -h
9
- GO_UTP_LOGGING=2 cd _ucat_test; make test
Godeps/_workspace/src/github.com/h2so5/utp/README.md
+12
-41
@@ -3,55 +3,26 @@ utp
3
4
μTP (Micro Transport Protocol) implementation
5
6
-[](https://ci.appveyor.com/project/h2so5/utp)
7
-[](https://travis-ci.org/h2so5/utp)
6
+[](https://ci.appveyor.com/project/h2so5/utp)
7
+[](https://travis-ci.org/h2so5/utp)
8
[](http://godoc.org/github.com/h2so5/utp)
9
10
http://www.bittorrent.org/beps/bep_0029.html
11
12
-**warning: This is a buggy alpha version.**
13
-
14
-## Benchmark History
15
-
16
-[]()
17
-
12
## Installation
13
14
```
15
go get github.com/h2so5/utp
16
```
17
24
-## Example
25
-
26
-Echo server
27
-
28
-```go
29
-package main
30
-
31
-import (
32
- "time"
33
-
34
- "github.com/h2so5/utp"
35
-)
36
-
37
-func main() {
38
- ln, _ := utp.Listen("utp", ":11000")
39
- defer ln.Close()
40
-
41
- conn, _ := ln.AcceptUTP()
42
- conn.SetKeepAlive(time.Minute)
43
- defer conn.Close()
44
-
45
- for {
46
- var buf [1024]byte
47
- l, err := conn.Read(buf[:])
48
- if err != nil {
49
- break
50
- }
51
- _, err = conn.Write(buf[:l])
52
- if err != nil {
53
- break
54
- }
55
- }
56
-}
18
+## Debug Log
19
+
20
+Use GO_UTP_LOGGING to show debug logs.
21
+
22
+```
23
+GO_UTP_LOGGING=0 go test <- default, no logging
24
+GO_UTP_LOGGING=1 go test
25
+GO_UTP_LOGGING=2 go test
26
+GO_UTP_LOGGING=3 go test
27
+GO_UTP_LOGGING=4 go test <- most verbose
28
```
Godeps/_workspace/src/github.com/h2so5/utp/addr.go
+22
-14
@@ -2,11 +2,31 @@ package utp
2
3
import "net"
4
5
-type UTPAddr struct {
5
+// Addr represents the address of a UTP end point.
6
+type Addr struct {
7
net.Addr
8
}
9
9
-func (a UTPAddr) Network() string { return "utp" }
10
+// Network returns the address's network name, "utp".
11
+func (a Addr) Network() string { return "utp" }
12
+
13
+// ResolveAddr parses addr as a UTP address of the form "host:port"
14
+// or "[ipv6-host%zone]:port" and resolves a pair of domain name and
15
+// port name on the network net, which must be "utp", "utp4" or
16
+// "utp6". A literal address or host name for IPv6 must be enclosed
17
+// in square brackets, as in "[::1]:80", "[ipv6-host]:http" or
18
+// "[ipv6-host%zone]:80".
19
+func ResolveAddr(n, addr string) (*Addr, error) {
20
+ udpnet, err := utp2udp(n)
21
+ if err != nil {
22
+ return nil, err
23
+ }
24
+ udp, err := net.ResolveUDPAddr(udpnet, addr)
25
+ if err != nil {
26
+ return nil, err
27
+ }
28
+ return &Addr{Addr: udp}, nil
29
+}
30
31
func utp2udp(n string) (string, error) {
32
switch n {
@@ -20,15 +40,3 @@ func utp2udp(n string) (string, error) {
40
return "", net.UnknownNetworkError(n)
41
}
42
}
23
-
24
-func ResolveUTPAddr(n, addr string) (*UTPAddr, error) {
25
- udpnet, err := utp2udp(n)
26
- if err != nil {
27
- return nil, err
28
- }
29
- udp, err := net.ResolveUDPAddr(udpnet, addr)
30
- if err != nil {
31
- return nil, err
32
- }
33
- return &UTPAddr{Addr: udp}, nil
34
-}
Godeps/_workspace/src/github.com/h2so5/utp/base.go
new
+325
@@ -0,0 +1,325 @@
1
+package utp
2
+
3
+import (
4
+ "errors"
5
+ "net"
6
+ "sync"
7
+ "sync/atomic"
8
+ "syscall"
9
+ "time"
10
+)
11
+
12
+var baseConnMap = make(map[string]*baseConn)
13
+var baseConnMutex sync.Mutex
14
+
15
+type packetHandler struct {
16
+ send chan<- *packet
17
+ closed chan int
18
+}
19
+
20
+type baseConn struct {
21
+ addr string
22
+ conn net.PacketConn
23
+ synPackets *packetRingBuffer
24
+ outOfBandPackets *packetRingBuffer
25
+
26
+ handlers map[uint16]*packetHandler
27
+ handlerMutex sync.RWMutex
28
+ ref int32
29
+ refMutex sync.RWMutex
30
+
31
+ rdeadline time.Time
32
+ wdeadline time.Time
33
+
34
+ softClosed int32
35
+ closed int32
36
+}
37
+
38
+func newBaseConn(n string, addr *Addr) (*baseConn, error) {
39
+ udpnet, err := utp2udp(n)
40
+ if err != nil {
41
+ return nil, err
42
+ }
43
+ var s string
44
+ if addr != nil {
45
+ s = addr.String()
46
+ } else {
47
+ s = ":0"
48
+ }
49
+ conn, err := net.ListenPacket(udpnet, s)
50
+ if err != nil {
51
+ return nil, err
52
+ }
53
+ c := &baseConn{
54
+ conn: conn,
55
+ synPackets: newPacketRingBuffer(packetBufferSize),
56
+ outOfBandPackets: newPacketRingBuffer(packetBufferSize),
57
+ handlers: make(map[uint16]*packetHandler),
58
+ }
59
+ c.Register(-1, nil)
60
+ go c.recvLoop()
61
+ return c, nil
62
+}
63
+
64
+func getSharedBaseConn(n string, addr *Addr) (*baseConn, error) {
65
+ baseConnMutex.Lock()
66
+ defer baseConnMutex.Unlock()
67
+ var s string
68
+ if addr != nil {
69
+ s = addr.String()
70
+ } else {
71
+ s = ":0"
72
+ }
73
+ if c, ok := baseConnMap[s]; ok {
74
+ return c, nil
75
+ }
76
+ c, err := newBaseConn(n, addr)
77
+ if err != nil {
78
+ return nil, err
79
+ }
80
+ c.addr = s
81
+ baseConnMap[s] = c
82
+ go c.recvLoop()
83
+ return c, nil
84
+}
85
+
86
+func (c *baseConn) ok() bool { return c != nil && c.conn != nil }
87
+
88
+func (c *baseConn) LocalAddr() net.Addr {
89
+ if !c.ok() {
90
+ return nil
91
+ }
92
+ return &Addr{Addr: c.conn.LocalAddr()}
93
+}
94
+
95
+func (c *baseConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
96
+ if !c.ok() {
97
+ return 0, nil, syscall.EINVAL
98
+ }
99
+ if !c.isOpen() {
100
+ return 0, nil, &net.OpError{
101
+ Op: "read",
102
+ Net: c.LocalAddr().Network(),
103
+ Addr: c.LocalAddr(),
104
+ Err: errClosing,
105
+ }
106
+ }
107
+ var d time.Duration
108
+ if !c.rdeadline.IsZero() {
109
+ d = c.rdeadline.Sub(time.Now())
110
+ if d < 0 {
111
+ d = 0
112
+ }
113
+ }
114
+ p, err := c.outOfBandPackets.popOne(d)
115
+ if err != nil {
116
+ return 0, nil, &net.OpError{
117
+ Op: "read",
118
+ Net: c.LocalAddr().Network(),
119
+ Addr: c.LocalAddr(),
120
+ Err: err,
121
+ }
122
+ }
123
+ return copy(b, p.payload), p.addr, nil
124
+}
125
+
126
+func (c *baseConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
127
+ if !c.ok() {
128
+ return 0, syscall.EINVAL
129
+ }
130
+ if !c.isOpen() {
131
+ return 0, &net.OpError{
132
+ Op: "write",
133
+ Net: c.LocalAddr().Network(),
134
+ Addr: c.LocalAddr(),
135
+ Err: errClosing,
136
+ }
137
+ }
138
+ return c.conn.WriteTo(b, addr)
139
+}
140
+
141
+func (c *baseConn) Close() error {
142
+ if !c.ok() {
143
+ return syscall.EINVAL
144
+ }
145
+ if c.isOpen() && atomic.CompareAndSwapInt32(&c.softClosed, 0, 1) {
146
+ c.Unregister(-1)
147
+ } else {
148
+ return &net.OpError{
149
+ Op: "close",
150
+ Net: c.LocalAddr().Network(),
151
+ Addr: c.LocalAddr(),
152
+ Err: errClosing,
153
+ }
154
+ }
155
+ return nil
156
+}
157
+
158
+func (c *baseConn) SetDeadline(t time.Time) error {
159
+ if !c.ok() {
160
+ return syscall.EINVAL
161
+ }
162
+ err := c.SetReadDeadline(t)
163
+ if err != nil {
164
+ return err
165
+ }
166
+ return c.SetWriteDeadline(t)
167
+}
168
+
169
+func (c *baseConn) SetReadDeadline(t time.Time) error {
170
+ if !c.ok() {
171
+ return syscall.EINVAL
172
+ }
173
+ c.rdeadline = t
174
+ return nil
175
+}
176
+
177
+func (c *baseConn) SetWriteDeadline(t time.Time) error {
178
+ if !c.ok() {
179
+ return syscall.EINVAL
180
+ }
181
+ c.wdeadline = t
182
+ return nil
183
+}
184
+
185
+func (c *baseConn) recvLoop() {
186
+ var buf [maxUdpPayload]byte
187
+ for {
188
+ l, addr, err := c.conn.ReadFrom(buf[:])
189
+ if err != nil {
190
+ ulog.Printf(3, "baseConn(%v): %v", c.LocalAddr(), err)
191
+ return
192
+ }
193
+ p, err := c.decodePacket(buf[:l])
194
+ if err != nil {
195
+ ulog.Printf(3, "baseConn(%v): RECV out-of-band packet (len: %d) from %v", c.LocalAddr(), l, addr)
196
+ c.outOfBandPackets.push(&packet{payload: append([]byte{}, buf[:l]...), addr: addr})
197
+ } else {
198
+ p.addr = addr
199
+ ulog.Printf(3, "baseConn(%v): RECV: %v from %v", c.LocalAddr(), p, addr)
200
+ if p.header.typ == stSyn {
201
+ // ignore duplicated syns
202
+ if !c.exists(p.header.id + 1) {
203
+ c.synPackets.push(p)
204
+ }
205
+ } else {
206
+ c.processPacket(p)
207
+ }
208
+ }
209
+ }
210
+}
211
+
212
+func (c *baseConn) decodePacket(b []byte) (*packet, error) {
213
+ var p packet
214
+ err := p.UnmarshalBinary(b)
215
+ if err != nil {
216
+ return nil, err
217
+ }
218
+ if p.header.ver != version {
219
+ return nil, errors.New("unsupported utp version")
220
+ }
221
+ return &p, nil
222
+}
223
+
224
+func (c *baseConn) exists(id uint16) bool {
225
+ c.handlerMutex.RLock()
226
+ defer c.handlerMutex.RUnlock()
227
+ return c.handlers[id] != nil
228
+}
229
+
230
+func (c *baseConn) processPacket(p *packet) {
231
+ c.handlerMutex.RLock()
232
+ h, ok := c.handlers[p.header.id]
233
+ c.handlerMutex.RUnlock()
234
+ if ok {
235
+ select {
236
+ case <-h.closed:
237
+ case h.send <- p:
238
+ }
239
+ }
240
+}
241
+
242
+func (c *baseConn) Register(id int32, f chan<- *packet) {
243
+ if id < 0 {
244
+ c.refMutex.Lock()
245
+ c.ref++
246
+ c.refMutex.Unlock()
247
+ } else {
248
+ if f == nil {
249
+ panic("nil handler not allowed")
250
+ }
251
+ c.handlerMutex.Lock()
252
+ _, ok := c.handlers[uint16(id)]
253
+ c.handlerMutex.Unlock()
254
+ if !ok {
255
+ c.refMutex.Lock()
256
+ c.ref++
257
+ c.refMutex.Unlock()
258
+ c.handlerMutex.Lock()
259
+ c.handlers[uint16(id)] = &packetHandler{
260
+ send: f,
261
+ closed: make(chan int),
262
+ }
263
+ c.handlerMutex.Unlock()
264
+ ulog.Printf(2, "baseConn(%v): register #%d (ref: %d)", c.LocalAddr(), id, c.ref)
265
+ }
266
+ }
267
+}
268
+
269
+func (c *baseConn) Unregister(id int32) {
270
+ if id < 0 {
271
+ c.refMutex.Lock()
272
+ c.ref--
273
+ c.refMutex.Unlock()
274
+ } else {
275
+ c.handlerMutex.Lock()
276
+ f, ok := c.handlers[uint16(id)]
277
+ c.handlerMutex.Unlock()
278
+ if ok {
279
+ c.handlerMutex.Lock()
280
+ close(f.closed)
281
+ delete(c.handlers, uint16(id))
282
+ c.handlerMutex.Unlock()
283
+ c.refMutex.Lock()
284
+ c.ref--
285
+ c.refMutex.Unlock()
286
+ }
287
+ }
288
+ c.refMutex.Lock()
289
+ r := c.ref
290
+ c.refMutex.Unlock()
291
+ if r <= 0 {
292
+ baseConnMutex.Lock()
293
+ defer baseConnMutex.Unlock()
294
+ c.close()
295
+ delete(baseConnMap, c.addr)
296
+ ulog.Printf(2, "baseConn(%v): unregister #%d (ref: %d)", c.LocalAddr(), id, c.ref)
297
+ }
298
+}
299
+
300
+func (c *baseConn) close() {
301
+ if atomic.CompareAndSwapInt32(&c.closed, 0, 1) {
302
+ c.conn.Close()
303
+ }
304
+}
305
+
306
+func (c *baseConn) isOpen() bool {
307
+ return atomic.LoadInt32(&c.closed) == 0
308
+}
309
+
310
+func (c *baseConn) Send(p *packet) {
311
+ b, err := p.MarshalBinary()
312
+ if err != nil {
313
+ panic(err)
314
+ }
315
+ ulog.Printf(3, "baseConn(%v): SEND: %v to %v", c.LocalAddr(), p, p.addr)
316
+ _, err = c.conn.WriteTo(b, p.addr)
317
+ if err != nil {
318
+ ulog.Printf(3, "%v", err)
319
+ panic(err)
320
+ }
321
+}
322
+
323
+func (c *baseConn) RecvSyn(timeout time.Duration) (*packet, error) {
324
+ return c.synPackets.popOne(timeout)
325
+}
Godeps/_workspace/src/github.com/h2so5/utp/base_test.go
new
+308
@@ -0,0 +1,308 @@
1
+package utp
2
+
3
+import (
4
+ "bytes"
5
+ "net"
6
+ "sync"
7
+ "testing"
8
+ "time"
9
+)
10
+
11
+func TestSharedConnRecvPacket(t *testing.T) {
12
+ addr, err := ResolveAddr("utp", "127.0.0.1:0")
13
+ if err != nil {
14
+ t.Fatal(err)
15
+ }
16
+
17
+ c, err := getSharedBaseConn("utp", addr)
18
+ if err != nil {
19
+ t.Fatal(err)
20
+ }
21
+ defer c.Close()
22
+
23
+ uaddr, err := net.ResolveUDPAddr("udp", c.LocalAddr().String())
24
+ if err != nil {
25
+ t.Fatal(err)
26
+ }
27
+
28
+ uc, err := net.DialUDP("udp", nil, uaddr)
29
+ if err != nil {
30
+ t.Fatal(err)
31
+ }
32
+ defer uc.Close()
33
+
34
+ ch := make(chan *packet)
35
+ c.Register(5, ch)
36
+
37
+ for i := 0; i < 100; i++ {
38
+ p := &packet{header: header{typ: stData, ver: version, id: 5}}
39
+ payload, err := p.MarshalBinary()
40
+ if err != nil {
41
+ t.Fatal(err)
42
+ }
43
+ go func() {
44
+ uc.Write(payload)
45
+ }()
46
+ <-ch
47
+ }
48
+
49
+ c.Unregister(5)
50
+}
51
+
52
+func TestSharedConnSendPacket(t *testing.T) {
53
+ addr, err := ResolveAddr("utp", "127.0.0.1:0")
54
+ if err != nil {
55
+ t.Fatal(err)
56
+ }
57
+
58
+ c, err := getSharedBaseConn("utp", addr)
59
+ if err != nil {
60
+ t.Fatal(err)
61
+ }
62
+ defer c.Close()
63
+
64
+ uaddr, err := net.ResolveUDPAddr("udp", c.LocalAddr().String())
65
+ if err != nil {
66
+ t.Fatal(err)
67
+ }
68
+
69
+ uc, err := net.DialUDP("udp", nil, uaddr)
70
+ if err != nil {
71
+ t.Fatal(err)
72
+ }
73
+ defer uc.Close()
74
+
75
+ for i := 0; i < 100; i++ {
76
+ addr, err := net.ResolveUDPAddr("udp", uc.LocalAddr().String())
77
+ if err != nil {
78
+ t.Fatal(err)
79
+ }
80
+ p := &packet{header: header{typ: stData, ver: version, id: 5}, addr: addr}
81
+ payload, err := p.MarshalBinary()
82
+ if err != nil {
83
+ t.Fatal(err)
84
+ }
85
+
86
+ c.Send(p)
87
+
88
+ var b [256]byte
89
+ l, err := uc.Read(b[:])
90
+ if err != nil {
91
+ t.Fatal(err)
92
+ }
93
+
94
+ if !bytes.Equal(b[:l], payload) {
95
+ t.Errorf("expected packet of %v; got %v", payload, b[:l])
96
+ }
97
+ }
98
+}
99
+
100
+func TestSharedConnRecvSyn(t *testing.T) {
101
+ addr, err := ResolveAddr("utp", "127.0.0.1:0")
102
+ if err != nil {
103
+ t.Fatal(err)
104
+ }
105
+
106
+ c, err := getSharedBaseConn("utp", addr)
107
+ if err != nil {
108
+ t.Fatal(err)
109
+ }
110
+ defer c.Close()
111
+
112
+ uaddr, err := net.ResolveUDPAddr("udp", c.LocalAddr().String())
113
+ if err != nil {
114
+ t.Fatal(err)
115
+ }
116
+
117
+ uc, err := net.DialUDP("udp", nil, uaddr)
118
+ if err != nil {
119
+ t.Fatal(err)
120
+ }
121
+ defer uc.Close()
122
+
123
+ for i := 0; i < 100; i++ {
124
+ p := &packet{header: header{typ: stSyn, ver: version}}
125
+ payload, err := p.MarshalBinary()
126
+ if err != nil {
127
+ t.Fatal(err)
128
+ }
129
+ go func() {
130
+ uc.Write(payload)
131
+ }()
132
+ p, err = c.RecvSyn(time.Duration(0))
133
+ if err != nil {
134
+ t.Fatal(err)
135
+ }
136
+ if p == nil {
137
+ t.Errorf("packet must not be nil")
138
+ }
139
+ }
140
+}
141
+
142
+func TestSharedConnRecvOutOfBound(t *testing.T) {
143
+ addr, err := ResolveAddr("utp", "127.0.0.1:0")
144
+ if err != nil {
145
+ t.Fatal(err)
146
+ }
147
+
148
+ c, err := getSharedBaseConn("utp", addr)
149
+ if err != nil {
150
+ t.Fatal(err)
151
+ }
152
+ defer c.Close()
153
+
154
+ uaddr, err := net.ResolveUDPAddr("udp", c.LocalAddr().String())
155
+ if err != nil {
156
+ t.Fatal(err)
157
+ }
158
+
159
+ uc, err := net.DialUDP("udp", nil, uaddr)
160
+ if err != nil {
161
+ t.Fatal(err)
162
+ }
163
+ defer uc.Close()
164
+
165
+ for i := 0; i < 100; i++ {
166
+ payload := []byte("Hello")
167
+ go func() {
168
+ uc.Write(payload)
169
+ }()
170
+ var b [256]byte
171
+ l, _, err := c.ReadFrom(b[:])
172
+ if err != nil {
173
+ t.Fatal(err)
174
+ }
175
+ if !bytes.Equal(payload, b[:l]) {
176
+ t.Errorf("expected packet of %v; got %v", payload, b[:l])
177
+ }
178
+ }
179
+}
180
+
181
+func TestSharedConnSendOutOfBound(t *testing.T) {
182
+ addr, err := ResolveAddr("utp", "127.0.0.1:0")
183
+ if err != nil {
184
+ t.Fatal(err)
185
+ }
186
+
187
+ c, err := getSharedBaseConn("utp", addr)
188
+ if err != nil {
189
+ t.Fatal(err)
190
+ }
191
+ defer c.Close()
192
+
193
+ uaddr, err := net.ResolveUDPAddr("udp", c.LocalAddr().String())
194
+ if err != nil {
195
+ t.Fatal(err)
196
+ }
197
+
198
+ uc, err := net.DialUDP("udp", nil, uaddr)
199
+ if err != nil {
200
+ t.Fatal(err)
201
+ }
202
+ defer uc.Close()
203
+
204
+ for i := 0; i < 100; i++ {
205
+ addr, err := net.ResolveUDPAddr("udp", uc.LocalAddr().String())
206
+ if err != nil {
207
+ t.Fatal(err)
208
+ }
209
+ payload := []byte("Hello")
210
+ _, err = c.WriteTo(payload, addr)
211
+ if err != nil {
212
+ t.Fatal(err)
213
+ }
214
+
215
+ var b [256]byte
216
+ l, err := uc.Read(b[:])
217
+ if err != nil {
218
+ t.Fatal(err)
219
+ }
220
+
221
+ if !bytes.Equal(payload, b[:l]) {
222
+ t.Errorf("expected packet of %v; got %v", payload, b[:l])
223
+ }
224
+ }
225
+}
226
+
227
+func TestSharedConnReferenceCount(t *testing.T) {
228
+ addr, err := ResolveAddr("utp", "127.0.0.1:0")
229
+ if err != nil {
230
+ t.Fatal(err)
231
+ }
232
+
233
+ c, err := getSharedBaseConn("utp", addr)
234
+ if err != nil {
235
+ t.Fatal(err)
236
+ }
237
+ defer c.Close()
238
+
239
+ var w sync.WaitGroup
240
+
241
+ c.Register(-1, nil)
242
+
243
+ for i := 0; i < 5; i++ {
244
+ w.Add(1)
245
+ go func(i int) {
246
+ defer w.Done()
247
+ c.Register(int32(i), make(chan *packet))
248
+ }(i)
249
+ }
250
+
251
+ w.Wait()
252
+ for i := 0; i < 5; i++ {
253
+ w.Add(1)
254
+ go func(i int) {
255
+ defer w.Done()
256
+ c.Unregister(int32(i))
257
+ }(i)
258
+ }
259
+
260
+ w.Wait()
261
+ c.Unregister(-1)
262
+ c.Close()
263
+
264
+ c = baseConnMap[addr.String()]
265
+ if c != nil {
266
+ t.Errorf("baseConn should be released", c.ref)
267
+ }
268
+}
269
+
270
+func TestSharedConnClose(t *testing.T) {
271
+ addr, err := ResolveAddr("utp", "127.0.0.1:0")
272
+ if err != nil {
273
+ t.Fatal(err)
274
+ }
275
+
276
+ c, err := getSharedBaseConn("utp", addr)
277
+ if err != nil {
278
+ t.Fatal(err)
279
+ }
280
+ defer c.Close()
281
+
282
+ for i := 0; i < 5; i++ {
283
+ c.Close()
284
+ }
285
+
286
+ var b [256]byte
287
+ _, _, err = c.ReadFrom(b[:])
288
+ if err == nil {
289
+ t.Fatal("ReadFrom should fail")
290
+ }
291
+
292
+ uaddr, err := net.ResolveUDPAddr("udp", c.LocalAddr().String())
293
+ if err != nil {
294
+ t.Fatal(err)
295
+ }
296
+
297
+ uc, err := net.DialUDP("udp", nil, uaddr)
298
+ if err != nil {
299
+ t.Fatal(err)
300
+ }
301
+ defer uc.Close()
302
+
303
+ payload := []byte("Hello")
304
+ _, err = c.WriteTo(payload, uc.LocalAddr())
305
+ if err == nil {
306
+ t.Fatal("WriteTo should fail")
307
+ }
308
+}
Godeps/_workspace/src/github.com/h2so5/utp/benchmark/main.go
+46
-26
@@ -85,25 +85,27 @@ func main() {
85
}
86
87
func c2s(l int64, stream bool) float64 {
88
- ln, err := utp.Listen("utp", "127.0.0.1:0")
88
+ laddr, err := utp.ResolveAddr("utp", "127.0.0.1:0")
89
if err != nil {
90
log.Fatal(err)
91
}
92
-
93
- raddr, err := utp.ResolveUTPAddr("utp", ln.Addr().String())
92
+ ln, err := utp.Listen("utp", laddr)
93
if err != nil {
94
log.Fatal(err)
95
}
96
98
- c, err := utp.DialUTPTimeout("utp", nil, raddr, 1000*time.Millisecond)
99
- if err != nil {
100
- log.Fatal(err)
101
- }
102
- defer c.Close()
97
+ cch := make(chan *utp.Conn)
98
+ go func() {
99
+ c, err := utp.DialUTPTimeout("utp", nil, ln.Addr().(*utp.Addr), 1000*time.Millisecond)
100
+ if err != nil {
101
+ log.Fatal(err)
102
+ }
103
104
- if err != nil {
105
- log.Fatal(err)
106
- }
104
+ if err != nil {
105
+ log.Fatal(err)
106
+ }
107
+ cch <- c
108
+ }()
109
110
s, err := ln.Accept()
111
if err != nil {
@@ -112,7 +114,11 @@ func c2s(l int64, stream bool) float64 {
114
defer s.Close()
115
ln.Close()
116
117
+ c := <-cch
118
+ defer c.Close()
119
+
120
rch := make(chan int)
121
+ wch := make(chan int)
122
123
sendHash := md5.New()
124
readHash := md5.New()
@@ -122,12 +128,13 @@ func c2s(l int64, stream bool) float64 {
128
if stream {
129
go func() {
130
defer c.Close()
131
+ defer close(wch)
132
io.Copy(io.MultiWriter(c, sendHash, &counter), io.LimitReader(RandReader{}, l))
133
}()
134
135
go func() {
136
+ defer close(rch)
137
io.Copy(readHash, s)
130
- close(rch)
138
}()
139
140
go func() {
@@ -148,6 +155,7 @@ func c2s(l int64, stream bool) float64 {
155
156
start := time.Now()
157
<-rch
158
+ <-wch
159
bps = float64(l*8) / (float64(time.Now().Sub(start)) / float64(time.Second))
160
161
} else {
@@ -156,16 +164,18 @@ func c2s(l int64, stream bool) float64 {
164
165
go func() {
166
defer c.Close()
167
+ defer close(wch)
168
io.Copy(c, &sendBuf)
169
}()
170
171
go func() {
172
+ defer close(rch)
173
io.Copy(&readBuf, s)
164
- rch <- 0
174
}()
175
176
start := time.Now()
177
<-rch
178
+ <-wch
179
bps = float64(l*8) / (float64(time.Now().Sub(start)) / float64(time.Second))
180
181
io.Copy(sendHash, &sendBuf)
@@ -180,25 +190,27 @@ func c2s(l int64, stream bool) float64 {
190
}
191
192
func s2c(l int64, stream bool) float64 {
183
- ln, err := utp.Listen("utp", "127.0.0.1:0")
193
+ laddr, err := utp.ResolveAddr("utp", "127.0.0.1:0")
194
if err != nil {
195
log.Fatal(err)
196
}
187
-
188
- raddr, err := utp.ResolveUTPAddr("utp", ln.Addr().String())
197
+ ln, err := utp.Listen("utp", laddr)
198
if err != nil {
199
log.Fatal(err)
200
}
201
193
- c, err := utp.DialUTPTimeout("utp", nil, raddr, 1000*time.Millisecond)
194
- if err != nil {
195
- log.Fatal(err)
196
- }
197
- defer c.Close()
202
+ cch := make(chan *utp.Conn)
203
+ go func() {
204
+ c, err := utp.DialUTPTimeout("utp", nil, ln.Addr().(*utp.Addr), 1000*time.Millisecond)
205
+ if err != nil {
206
+ log.Fatal(err)
207
+ }
208
199
- if err != nil {
200
- log.Fatal(err)
201
- }
209
+ if err != nil {
210
+ log.Fatal(err)
211
+ }
212
+ cch <- c
213
+ }()
214
215
s, err := ln.Accept()
216
if err != nil {
@@ -207,7 +219,11 @@ func s2c(l int64, stream bool) float64 {
219
defer s.Close()
220
ln.Close()
221
222
+ c := <-cch
223
+ defer c.Close()
224
+
225
rch := make(chan int)
226
+ wch := make(chan int)
227
228
sendHash := md5.New()
229
readHash := md5.New()
@@ -218,12 +234,13 @@ func s2c(l int64, stream bool) float64 {
234
if stream {
235
go func() {
236
defer s.Close()
237
+ defer close(wch)
238
io.Copy(io.MultiWriter(s, sendHash, &counter), io.LimitReader(RandReader{}, l))
239
}()
240
241
go func() {
242
+ defer close(rch)
243
io.Copy(readHash, c)
226
- close(rch)
244
}()
245
246
go func() {
@@ -244,6 +261,7 @@ func s2c(l int64, stream bool) float64 {
261
262
start := time.Now()
263
<-rch
264
+ <-wch
265
bps = float64(l*8) / (float64(time.Now().Sub(start)) / float64(time.Second))
266
267
} else {
@@ -252,16 +270,18 @@ func s2c(l int64, stream bool) float64 {
270
271
go func() {
272
defer s.Close()
273
+ defer close(wch)
274
io.Copy(s, &sendBuf)
275
}()
276
277
go func() {
278
+ defer close(rch)
279
io.Copy(&readBuf, c)
260
- rch <- 0
280
}()
281
282
start := time.Now()
283
<-rch
284
+ <-wch
285
bps = float64(l*8) / (float64(time.Now().Sub(start)) / float64(time.Second))
286
287
io.Copy(sendHash, &sendBuf)
Godeps/_workspace/src/github.com/h2so5/utp/buffer.go
+272
-30
@@ -2,7 +2,9 @@ package utp
2
3
import (
4
"errors"
5
+ "io"
6
"math"
7
+ "sync"
8
"time"
9
)
10
@@ -74,7 +76,7 @@ func (b *packetBuffer) compact() {
76
}
77
}
78
77
-func (b *packetBuffer) first() *packet {
79
+func (b *packetBuffer) front() *packet {
80
if b.root == nil || b.root.p == nil {
81
return nil
82
}
@@ -157,6 +159,9 @@ func (b *packetBuffer) generateSelectiveACK() []byte {
159
ack = ack[:len(ack)-1]
160
}
161
162
+ if len(ack) == 0 {
163
+ return nil
164
+ }
165
return ack
166
}
167
@@ -185,46 +190,283 @@ func (b *packetBuffer) processSelectiveACK(ack []byte) {
190
}
191
}
192
188
-type timedBuffer struct {
189
- d time.Duration
190
- root *timedBufferNode
193
+type packetRingBuffer struct {
194
+ b []*packet
195
+ begin int
196
+ s int
197
+ mutex sync.RWMutex
198
+ rch chan int
199
}
200
193
-type timedBufferNode struct {
194
- val float64
195
- next *timedBufferNode
196
- pushed time.Time
201
+func newPacketRingBuffer(s int) *packetRingBuffer {
202
+ return &packetRingBuffer{
203
+ b: make([]*packet, s),
204
+ rch: make(chan int),
205
+ }
206
+}
207
+
208
+func (b *packetRingBuffer) size() int {
209
+ b.mutex.RLock()
210
+ defer b.mutex.RUnlock()
211
+ return b.s
212
+}
213
+
214
+func (b *packetRingBuffer) empty() bool {
215
+ return b.size() == 0
216
+}
217
+
218
+func (b *packetRingBuffer) push(p *packet) {
219
+ b.mutex.Lock()
220
+ defer b.mutex.Unlock()
221
+ b.b[(b.begin+b.s)%len(b.b)] = p
222
+ if b.s < len(b.b) {
223
+ b.s++
224
+ } else {
225
+ b.begin = (b.begin + 1) % len(b.b)
226
+ }
227
+ select {
228
+ case b.rch <- 0:
229
+ default:
230
+ }
231
+}
232
+
233
+func (b *packetRingBuffer) pop() *packet {
234
+ if b.empty() {
235
+ return nil
236
+ }
237
+ b.mutex.Lock()
238
+ defer b.mutex.Unlock()
239
+ p := b.b[b.begin]
240
+ b.begin = (b.begin + 1) % len(b.b)
241
+ b.s--
242
+ return p
243
+}
244
+
245
+func (b *packetRingBuffer) popOne(timeout time.Duration) (*packet, error) {
246
+ t := time.NewTimer(timeout)
247
+ defer t.Stop()
248
+ if timeout == 0 {
249
+ t.Stop()
250
+ }
251
+ if b.empty() {
252
+ select {
253
+ case <-b.rch:
254
+ case <-t.C:
255
+ return nil, errTimeout
256
+ }
257
+ }
258
+ return b.pop(), nil
259
+}
260
+
261
+type byteRingBuffer struct {
262
+ b []byte
263
+ begin int
264
+ s int
265
+ mutex sync.RWMutex
266
+ rch chan int
267
+ closech chan int
268
+ closechMutex sync.Mutex
269
+}
270
+
271
+func newByteRingBuffer(s int) *byteRingBuffer {
272
+ return &byteRingBuffer{
273
+ b: make([]byte, s),
274
+ rch: make(chan int),
275
+ closech: make(chan int),
276
+ }
277
}
278
199
-func (b *timedBuffer) push(val float64) {
200
- var before *timedBufferNode
201
- for n := b.root; n != nil; n = n.next {
202
- if time.Now().Sub(n.pushed) >= b.d {
203
- if before != nil {
204
- before.next = nil
205
- } else {
206
- b.root = nil
279
+func (r *byteRingBuffer) size() int {
280
+ r.mutex.RLock()
281
+ defer r.mutex.RUnlock()
282
+ return r.s
283
+}
284
+
285
+func (r *byteRingBuffer) space() int {
286
+ r.mutex.RLock()
287
+ defer r.mutex.RUnlock()
288
+ return len(r.b) - r.s
289
+}
290
+
291
+func (r *byteRingBuffer) empty() bool {
292
+ return r.size() == 0
293
+}
294
+
295
+func (r *byteRingBuffer) Write(b []byte) (int, error) {
296
+ r.mutex.Lock()
297
+ defer r.mutex.Unlock()
298
+
299
+ for len(b) > 0 {
300
+ end := (r.begin + r.s) % len(r.b)
301
+ n := copy(r.b[end:], b)
302
+ b = b[n:]
303
+
304
+ s := r.s + n
305
+ if s > len(r.b) {
306
+ r.begin = (r.begin + s - len(r.b)) % len(r.b)
307
+ r.s = len(r.b)
308
+ } else {
309
+ r.s += n
310
+ }
311
+ }
312
+ select {
313
+ case r.rch <- 0:
314
+ case <-r.closech:
315
+ return 0, io.EOF
316
+ default:
317
+ }
318
+ return len(b), nil
319
+}
320
+
321
+func (r *byteRingBuffer) ReadTimeout(b []byte, timeout time.Duration) (int, error) {
322
+ t := time.NewTimer(timeout)
323
+ defer t.Stop()
324
+ if timeout == 0 {
325
+ t.Stop()
326
+ }
327
+ if r.empty() {
328
+ select {
329
+ case <-r.rch:
330
+ case <-t.C:
331
+ return 0, errTimeout
332
+ case <-r.closech:
333
+ return 0, io.EOF
334
+ }
335
+ }
336
+ l := r.size()
337
+ if l > len(b) {
338
+ l = len(b)
339
+ }
340
+ r.mutex.Lock()
341
+ defer r.mutex.Unlock()
342
+ if r.begin+l > len(r.b) {
343
+ n := copy(b, r.b[r.begin:])
344
+ n = copy(b[n:], r.b[:])
345
+ r.begin = n
346
+ } else {
347
+ copy(b, r.b[r.begin:r.begin+l])
348
+ r.begin = (r.begin + l) % len(r.b)
349
+ }
350
+ r.s -= l
351
+ return l, nil
352
+}
353
+
354
+func (r *byteRingBuffer) Close() error {
355
+ r.closechMutex.Lock()
356
+ defer r.closechMutex.Unlock()
357
+ select {
358
+ case <-r.closech:
359
+ return errClosing
360
+ default:
361
+ close(r.closech)
362
+ }
363
+ return nil
364
+}
365
+
366
+type rateLimitedBuffer struct {
367
+ wch chan<- []byte
368
+ closech chan int
369
+ closechMutex sync.Mutex
370
+ size uint32
371
+ sizech chan uint32
372
+ sizeMutex sync.Mutex
373
+}
374
+
375
+func newRateLimitedBuffer(ch chan<- []byte, size uint32) *rateLimitedBuffer {
376
+ return &rateLimitedBuffer{
377
+ wch: ch,
378
+ closech: make(chan int),
379
+ size: size,
380
+ sizech: make(chan uint32),
381
+ }
382
+}
383
+
384
+func (r *rateLimitedBuffer) WriteTimeout(b []byte, timeout time.Duration) (int, error) {
385
+ t := time.NewTimer(timeout)
386
+ defer t.Stop()
387
+ if timeout == 0 {
388
+ t.Stop()
389
+ }
390
+
391
+ for wrote := uint32(0); wrote < uint32(len(b)); {
392
+ r.sizeMutex.Lock()
393
+ s := r.size
394
+ r.sizeMutex.Unlock()
395
+ if s == 0 {
396
+ select {
397
+ case ns := <-r.sizech:
398
+ s = ns
399
+ case <-r.closech:
400
+ return 0, errClosing
401
}
208
- break
402
}
210
- before = n
403
+ if s > uint32(len(b))-wrote {
404
+ s = uint32(len(b)) - wrote
405
+ }
406
+ select {
407
+ case r.wch <- append([]byte{}, b[wrote:wrote+s]...):
408
+ wrote += s
409
+ r.sizeMutex.Lock()
410
+ r.size -= uint32(s)
411
+ r.sizeMutex.Unlock()
412
+ case <-r.closech:
413
+ return 0, errClosing
414
+ case <-t.C:
415
+ return 0, errTimeout
416
+ }
417
}
212
- b.root = &timedBufferNode{
213
- val: val,
214
- next: b.root,
215
- pushed: time.Now(),
418
+
419
+ return len(b), nil
420
+}
421
+
422
+func (r *rateLimitedBuffer) Reset(size uint32) {
423
+ r.sizeMutex.Lock()
424
+ defer r.sizeMutex.Unlock()
425
+ r.size = size
426
+ select {
427
+ case r.sizech <- size:
428
+ default:
429
}
430
}
431
219
-func (b *timedBuffer) min() float64 {
220
- if b.root == nil {
221
- return 0
432
+func (r *rateLimitedBuffer) Close() error {
433
+ r.closechMutex.Lock()
434
+ defer r.closechMutex.Unlock()
435
+ select {
436
+ case <-r.closech:
437
+ return errClosing
438
+ default:
439
+ close(r.closech)
440
}
223
- min := b.root.val
224
- for n := b.root; n != nil; n = n.next {
225
- if min > n.val {
226
- min = n.val
441
+ return nil
442
+}
443
+
444
+type baseDelayBuffer struct {
445
+ b [6]uint32
446
+ last int
447
+ min uint32
448
+}
449
+
450
+func (b *baseDelayBuffer) Push(val uint32) {
451
+ t := time.Now()
452
+ i := t.Second()/20 + (t.Minute()%2)*3
453
+ if b.last == i {
454
+ if b.b[i] > val {
455
+ b.b[i] = val
456
}
457
+ } else {
458
+ b.b[i] = val
459
+ b.last = i
460
}
229
- return min
461
+ min := val
462
+ for _, v := range b.b {
463
+ if v > 0 && min > v {
464
+ min = v
465
+ }
466
+ }
467
+ b.min = min
468
+}
469
+
470
+func (b *baseDelayBuffer) Min() uint32 {
471
+ return b.min
472
}
Godeps/_workspace/src/github.com/h2so5/utp/buffer_test.go
new
+178
@@ -0,0 +1,178 @@
1
+package utp
2
+
3
+import (
4
+ "bytes"
5
+ "math"
6
+ "testing"
7
+ "time"
8
+)
9
+
10
+func TestPacketBuffer(t *testing.T) {
11
+ size := 12
12
+ b := newPacketBuffer(12, 1)
13
+
14
+ if b.space() != size {
15
+ t.Errorf("expected space == %d; got %d", size, b.space())
16
+ }
17
+
18
+ for i := 1; i <= size; i++ {
19
+ b.push(&packet{header: header{seq: uint16(i)}})
20
+ }
21
+
22
+ if b.space() != 0 {
23
+ t.Errorf("expected space == 0; got %d", b.space())
24
+ }
25
+
26
+ a := []byte{255, 7}
27
+ ack := b.generateSelectiveACK()
28
+ if !bytes.Equal(a, ack) {
29
+ t.Errorf("expected ack == %v; got %v", a, ack)
30
+ }
31
+
32
+ err := b.push(&packet{header: header{seq: 15}})
33
+ if err == nil {
34
+ t.Fatal("push should fail")
35
+ }
36
+
37
+ all := b.all()
38
+ if len(all) != size {
39
+ t.Errorf("expected %d packets sequence; got %d", size, len(all))
40
+ }
41
+
42
+ f := b.fetch(6)
43
+ if f == nil {
44
+ t.Fatal("fetch should not fail")
45
+ }
46
+
47
+ b.compact()
48
+
49
+ err = b.push(&packet{header: header{seq: 15}})
50
+ if err != nil {
51
+ t.Fatal(err)
52
+ }
53
+
54
+ err = b.push(&packet{header: header{seq: 17}})
55
+ if err != nil {
56
+ t.Fatal(err)
57
+ }
58
+
59
+ for i := 7; i <= size; i++ {
60
+ f := b.fetch(uint16(i))
61
+ if f == nil {
62
+ t.Fatal("fetch should not fail")
63
+ }
64
+ }
65
+
66
+ a = []byte{128, 2}
67
+ ack = b.generateSelectiveACK()
68
+ if !bytes.Equal(a, ack) {
69
+ t.Errorf("expected ack == %v; got %v", a, ack)
70
+ }
71
+
72
+ all = b.all()
73
+ if len(all) != 2 {
74
+ t.Errorf("expected 2 packets sequence; got %d", len(all))
75
+ }
76
+
77
+ b.compact()
78
+ if b.space() != 9 {
79
+ t.Errorf("expected space == 9; got %d", b.space())
80
+ }
81
+
82
+ ack = b.generateSelectiveACK()
83
+ b.processSelectiveACK(ack)
84
+
85
+ all = b.all()
86
+ if len(all) != 1 {
87
+ t.Errorf("expected size == 1; got %d", len(all))
88
+ }
89
+}
90
+
91
+func TestPacketBufferBoundary(t *testing.T) {
92
+ begin := math.MaxUint16 - 3
93
+ b := newPacketBuffer(12, begin)
94
+ for i := begin; i != 5; i = (i + 1) % (math.MaxUint16 + 1) {
95
+ err := b.push(&packet{header: header{seq: uint16(i)}})
96
+ if err != nil {
97
+ t.Fatal(err)
98
+ }
99
+ }
100
+}
101
+
102
+func TestPacketRingBuffer(t *testing.T) {
103
+ b := newPacketRingBuffer(5)
104
+ for i := 0; i < 7; i++ {
105
+ b.push(&packet{header: header{seq: uint16(i)}})
106
+ }
107
+
108
+ if b.size() != 5 {
109
+ t.Errorf("expected size == 5; got %d", b.size())
110
+ }
111
+
112
+ p := b.pop()
113
+ if p.header.seq != 2 {
114
+ t.Errorf("expected header.seq == 2; got %d", p.header.seq)
115
+ }
116
+
117
+ if b.size() != 4 {
118
+ t.Errorf("expected size == 4; got %d", b.size())
119
+ }
120
+
121
+ for b.pop() != nil {
122
+ }
123
+
124
+ if !b.empty() {
125
+ t.Errorf("buffer must be empty")
126
+ }
127
+
128
+ go func() {
129
+ for i := 0; i < 5; i++ {
130
+ b.push(&packet{header: header{seq: uint16(i)}})
131
+ }
132
+ }()
133
+
134
+ p, err := b.popOne(time.Second)
135
+ if err != nil {
136
+ t.Fatal(err)
137
+ }
138
+
139
+ if p.header.seq != 0 {
140
+ t.Errorf("expected header.seq == 0; got %d", p.header.seq)
141
+ }
142
+}
143
+
144
+func TestByteRingBuffer(t *testing.T) {
145
+
146
+ b := newByteRingBuffer(5)
147
+ for i := 0; i < 100; i++ {
148
+ b.Write([]byte{byte(i)})
149
+ }
150
+
151
+ var buf [10]byte
152
+ l, err := b.ReadTimeout(buf[:], 0)
153
+ if err != nil {
154
+ t.Fatal(err)
155
+ }
156
+
157
+ e := []byte{95, 96, 97, 98, 99}
158
+ if !bytes.Equal(buf[:l], e) {
159
+ t.Errorf("expected payload of %v; got %v", e, buf[:l])
160
+ }
161
+
162
+ e2 := []byte("abcdefghijklmnopqrstuvwxyz")
163
+ go func() {
164
+ _, err := b.Write(e2)
165
+ if err != nil {
166
+ t.Fatal(err)
167
+ }
168
+ }()
169
+
170
+ l, err = b.ReadTimeout(buf[:], 0)
171
+ if err != nil {
172
+ t.Fatal(err)
173
+ }
174
+
175
+ if !bytes.Equal(buf[:l], e2[len(e2)-5:]) {
176
+ t.Errorf("expected payload of %v; got %v", e2[len(e2)-5:], buf[:l])
177
+ }
178
+}
Godeps/_workspace/src/github.com/h2so5/utp/conn.go
+329
-519
@@ -1,48 +1,55 @@
1
package utp
2
3
import (
4
- "bytes"
5
- "errors"
6
- "io"
4
"math"
8
- "math/rand"
5
"net"
6
+ "sync"
7
+ "sync/atomic"
8
"syscall"
9
"time"
10
)
11
14
-type UTPConn struct {
15
- conn net.PacketConn
16
- raddr net.Addr
17
- rid, sid, seq, ack, lastAck uint16
18
- rtt, rttVar, minRtt, rto, dupAck int64
19
- diff, maxWindow uint32
20
- rdeadline, wdeadline time.Time
21
-
22
- state state
23
- lastTimedOut time.Time
24
-
25
- outch chan *outgoingPacket
26
- outchch chan int
27
- sendch chan *outgoingPacket
28
- sendchch chan int
29
- recvch chan *packet
30
- recvchch chan int
31
- readch chan []byte
32
- readchch chan int
33
- winch chan uint32
34
- quitch chan int
35
- activech chan int
36
- connch chan error
37
- finch chan int
38
- closech chan<- uint16
39
- eofid uint16
40
- keepalivech chan time.Duration
12
+// Conn is an implementation of the Conn interface for UTP network
13
+// connections.
14
+type Conn struct {
15
+ conn *baseConn
16
+ raddr net.Addr
17
+ rid, sid, seq, ack, lastAck uint16
18
+ rtt, rttVar, minRtt, rto int64
19
+ dupAck int
20
+ diff, maxWindow uint32
21
+
22
+ state int
23
+ closed int32
24
42
- readbuf bytes.Buffer
25
recvbuf *packetBuffer
26
sendbuf *packetBuffer
27
28
+ readbuf *byteRingBuffer
29
+ writebuf *rateLimitedBuffer
30
+
31
+ baseDelay baseDelayBuffer
32
+
33
+ writech chan []byte
34
+ ackch chan int
35
+ synch chan int
36
+
37
+ rdeadline time.Time
38
+ wdeadline time.Time
39
+ deadlineMutex sync.RWMutex
40
+
41
+ recv chan *packet
42
+
43
+ closing bool
44
+ closingch chan int
45
+
46
+ keepalivech chan time.Duration
47
+
48
+ connch chan int
49
+
50
+ closech chan int
51
+ closechMutex sync.Mutex
52
+
53
stat statistics
54
}
55
@@ -54,351 +61,235 @@ type statistics struct {
61
packetTimedOuts int
62
sentSelectiveACKs int
63
receivedSelectiveACKs int
57
-
58
- rtoSum int
59
- rtoCount int
64
+ rtoSum int64
65
+ rtoCount int
66
}
67
62
-func dial(n string, laddr, raddr *UTPAddr, timeout time.Duration) (*UTPConn, error) {
63
- udpnet, err := utp2udp(n)
64
- if err != nil {
65
- return nil, err
66
- }
67
-
68
- // TODO extract
69
- if laddr == nil {
70
- addr, err := net.ResolveUDPAddr(udpnet, ":0")
71
- if err != nil {
72
- return nil, err
73
- }
74
- laddr = &UTPAddr{Addr: addr}
75
- }
76
-
77
- conn, err := net.ListenPacket(udpnet, laddr.Addr.String())
78
- if err != nil {
79
- return nil, err
80
- }
81
-
82
- id := uint16(rand.Intn(math.MaxUint16))
83
-
84
- c := newUTPConn()
85
- c.conn = conn
86
- c.raddr = raddr.Addr
87
- c.rid = id
88
- c.sid = id + 1
89
- c.seq = 1
90
- c.state = state_syn_sent
91
- c.sendbuf = newPacketBuffer(window_size, 1)
92
-
93
- go c.recv()
94
- go c.loop()
95
-
96
- select {
97
- case c.sendch <- &outgoingPacket{st_syn, nil, nil}:
98
- case <-c.sendchch:
99
- return nil, errors.New("use of closed network connection")
100
- }
68
+func newConn() *Conn {
69
+ wch := make(chan []byte)
70
+ c := &Conn{
71
+ minRtt: math.MaxInt64,
72
+ maxWindow: mss,
73
+ rto: int64(60),
74
102
- var t <-chan time.Time
103
- if timeout != 0 {
104
- t = time.After(timeout)
105
- }
75
+ recv: make(chan *packet),
76
+ connch: make(chan int),
77
107
- select {
108
- case err := <-c.connch:
109
- if err != nil {
110
- c.closed()
111
- return nil, err
112
- }
113
- ulog.Printf(1, "Conn(%v): Connected", c.LocalAddr())
114
- return c, nil
115
- case <-t:
116
- c.quitch <- 0
117
- return nil, &timeoutError{}
118
- }
119
-}
78
+ recvbuf: newPacketBuffer(0, 0),
79
121
-func newUTPConn() *UTPConn {
122
- rto := 60
80
+ readbuf: newByteRingBuffer(readBufferSize),
81
+ writebuf: newRateLimitedBuffer(wch, mss),
82
124
- return &UTPConn{
125
- minRtt: math.MaxInt64,
126
- maxWindow: mtu,
127
- rto: int64(rto),
128
-
129
- outch: make(chan *outgoingPacket, 1),
130
- outchch: make(chan int),
131
- sendch: make(chan *outgoingPacket, 1),
132
- sendchch: make(chan int),
133
- recvch: make(chan *packet, 2),
134
- recvchch: make(chan int),
135
- winch: make(chan uint32, 1),
136
- quitch: make(chan int),
137
- activech: make(chan int),
138
- readch: make(chan []byte, 1),
139
- readchch: make(chan int),
140
- connch: make(chan error, 1),
141
- finch: make(chan int, 1),
83
+ writech: wch,
84
+ ackch: make(chan int),
85
+ synch: make(chan int),
86
87
+ closingch: make(chan int),
88
keepalivech: make(chan time.Duration),
144
-
145
- stat: statistics{
146
- rtoSum: rto,
147
- rtoCount: 1,
148
- },
89
+ closech: make(chan int),
90
}
91
+ return c
92
}
93
152
-func (c *UTPConn) ok() bool { return c != nil && c.conn != nil }
94
+func (c *Conn) ok() bool { return c != nil && c.conn != nil }
95
154
-func (c *UTPConn) Close() error {
96
+// Close closes the connection.
97
+func (c *Conn) Close() error {
98
if !c.ok() {
99
return syscall.EINVAL
100
}
158
-
101
+ if !c.isOpen() {
102
+ return nil
103
+ }
104
select {
160
- case <-c.activech:
105
+ case <-c.closingch:
106
default:
162
- c.quitch <- 0
163
- ulog.Printf(2, "Conn(%v): Wait for close", c.LocalAddr())
164
- <-c.finch
107
+ close(c.closingch)
108
}
166
-
109
+ select {
110
+ case <-c.connch:
111
+ default:
112
+ return nil
113
+ }
114
+ <-c.closech
115
return nil
116
}
117
170
-func (c *UTPConn) LocalAddr() net.Addr {
171
- return &UTPAddr{Addr: c.conn.LocalAddr()}
118
+// LocalAddr returns the local network address.
119
+func (c *Conn) LocalAddr() net.Addr {
120
+ if !c.ok() {
121
+ return nil
122
+ }
123
+ return c.conn.LocalAddr()
124
}
125
174
-func (c *UTPConn) RemoteAddr() net.Addr {
175
- return &UTPAddr{Addr: c.raddr}
126
+// RemoteAddr returns the remote network address.
127
+func (c *Conn) RemoteAddr() net.Addr {
128
+ if !c.ok() {
129
+ return nil
130
+ }
131
+ return c.raddr
132
}
133
178
-func (c *UTPConn) Read(b []byte) (int, error) {
134
+// Read implements the Conn Read method.
135
+func (c *Conn) Read(b []byte) (int, error) {
136
if !c.ok() {
137
return 0, syscall.EINVAL
138
}
182
-
183
- if c.readbuf.Len() == 0 {
184
- var timeout <-chan time.Time
185
- if !c.rdeadline.IsZero() {
186
- timeout = time.After(c.rdeadline.Sub(time.Now()))
139
+ if !c.isOpen() {
140
+ return 0, &net.OpError{
141
+ Op: "read",
142
+ Net: c.LocalAddr().Network(),
143
+ Addr: c.LocalAddr(),
144
+ Err: errClosing,
145
}
188
-
146
+ }
147
+ s := c.readbuf.space()
148
+ c.deadlineMutex.RLock()
149
+ d := timeToDeadline(c.rdeadline)
150
+ c.deadlineMutex.RUnlock()
151
+ l, err := c.readbuf.ReadTimeout(b, d)
152
+ if s < mss && c.readbuf.space() > 0 {
153
select {
190
- case b := <-c.readch:
191
- if b == nil {
192
- return 0, io.EOF
193
- }
194
- _, err := c.readbuf.Write(b)
195
- if err != nil {
196
- return 0, err
197
- }
198
- case <-c.readchch:
199
- loop:
200
- for {
201
- select {
202
- case b := <-c.readch:
203
- _, err := c.readbuf.Write(b)
204
- if err != nil {
205
- return 0, err
206
- }
207
- default:
208
- break loop
209
- }
210
- }
211
- if c.readbuf.Len() == 0 {
212
- return 0, io.EOF
213
- }
214
- case <-timeout:
215
- return 0, &timeoutError{}
154
+ case c.ackch <- 0:
155
+ default:
156
}
157
}
218
- return c.readbuf.Read(b)
158
+ return l, err
159
}
160
221
-func (c *UTPConn) Write(b []byte) (int, error) {
161
+func timeToDeadline(deadline time.Time) (d time.Duration) {
162
+ if deadline.IsZero() {
163
+ return
164
+ }
165
+ d = deadline.Sub(time.Now())
166
+ if d < 0 {
167
+ d = 0
168
+ }
169
+ return
170
+}
171
+
172
+// Write implements the Conn Write method.
173
+func (c *Conn) Write(b []byte) (int, error) {
174
if !c.ok() {
175
return 0, syscall.EINVAL
176
}
225
-
226
- var wrote uint64
227
- for {
228
- l := uint64(len(b)) - wrote
229
- if l > mss {
230
- l = mss
231
- }
232
- select {
233
- case c.outch <- &outgoingPacket{st_data, nil, b[wrote : wrote+l]}:
234
- case <-c.outchch:
235
- return 0, errors.New("use of closed network connection")
236
- }
237
-
238
- wrote += l
239
- ulog.Printf(4, "Conn(%v): Write %d/%d bytes", c.LocalAddr(), wrote, len(b))
240
- if l < mss {
241
- break
177
+ if !c.isOpen() {
178
+ return 0, &net.OpError{
179
+ Op: "write",
180
+ Net: c.LocalAddr().Network(),
181
+ Addr: c.LocalAddr(),
182
+ Err: errClosing,
183
}
184
}
244
-
245
- return len(b), nil
185
+ c.deadlineMutex.RLock()
186
+ d := timeToDeadline(c.wdeadline)
187
+ c.deadlineMutex.RUnlock()
188
+ return c.writebuf.WriteTimeout(b, d)
189
}
190
248
-func (c *UTPConn) SetDeadline(t time.Time) error {
191
+// SetDeadline implements the Conn SetDeadline method.
192
+func (c *Conn) SetDeadline(t time.Time) error {
193
if !c.ok() {
194
return syscall.EINVAL
195
}
252
- if err := c.SetReadDeadline(t); err != nil {
253
- return err
254
- }
255
- if err := c.SetWriteDeadline(t); err != nil {
196
+ err := c.SetReadDeadline(t)
197
+ if err != nil {
198
return err
199
}
258
- return nil
200
+ return c.SetWriteDeadline(t)
201
}
202
261
-func (c *UTPConn) SetReadDeadline(t time.Time) error {
203
+// SetReadDeadline implements the Conn SetReadDeadline method.
204
+func (c *Conn) SetReadDeadline(t time.Time) error {
205
if !c.ok() {
206
return syscall.EINVAL
207
}
208
+ c.deadlineMutex.Lock()
209
+ defer c.deadlineMutex.Unlock()
210
c.rdeadline = t
211
return nil
212
}
213
269
-func (c *UTPConn) SetWriteDeadline(t time.Time) error {
214
+// SetWriteDeadline implements the Conn SetWriteDeadline method.
215
+func (c *Conn) SetWriteDeadline(t time.Time) error {
216
if !c.ok() {
217
return syscall.EINVAL
218
}
219
+ c.deadlineMutex.Lock()
220
+ defer c.deadlineMutex.Unlock()
221
c.wdeadline = t
222
return nil
223
}
224
277
-func (c *UTPConn) SetKeepAlive(d time.Duration) error {
225
+// SetKeepAlive sets the keepalive interval associated with the connection.
226
+func (c *Conn) SetKeepAlive(d time.Duration) error {
227
if !c.ok() {
228
return syscall.EINVAL
229
}
281
- select {
282
- case <-c.activech:
283
- default:
284
- c.keepalivech <- d
230
+ if !c.isOpen() {
231
+ return errClosing
232
}
233
+ c.keepalivech <- d
234
return nil
235
}
236
289
-func readPacket(data []byte) (*packet, error) {
290
- p := globalPool.get()
291
- err := p.UnmarshalBinary(data)
292
- if err != nil {
293
- return nil, err
294
- }
295
- if p.header.ver != version {
296
- return nil, errors.New("unsupported header version")
297
- }
298
- return p, nil
299
-}
300
-
301
-func (c *UTPConn) recv() {
302
- for {
303
- var buf [mtu]byte
304
- len, addr, err := c.conn.ReadFrom(buf[:])
305
- if err != nil {
306
- return
307
- }
308
- if addr.String() != c.raddr.String() {
309
- continue
310
- }
311
- p, err := readPacket(buf[:len])
312
- if err == nil {
313
- select {
314
- case c.recvch <- p:
315
- case <-c.recvchch:
316
- return
317
- }
318
- }
319
- }
320
-}
237
+func (c *Conn) loop() {
238
+ defer c.conn.Unregister(int32(c.rid))
239
322
-func (c *UTPConn) loop() {
323
- var recvExit, sendExit bool
324
- var lastReceived time.Time
240
+ var resendSeq uint16
241
+ var resendCont int
242
var keepalive <-chan time.Time
243
327
- go func() {
328
- var window uint32 = window_size * mtu
329
- for {
330
- if window >= mtu {
331
- select {
332
- case b := <-c.outch:
333
- select {
334
- case c.sendch <- b:
335
- window -= mtu
336
- case <-c.sendchch:
337
- return
338
- }
339
- case <-c.outchch:
340
- return
341
- case w := <-c.winch:
342
- window = w
343
- }
344
- } else {
345
- window = <-c.winch
346
- }
347
- }
348
- }()
244
+ resend := time.NewTimer(0)
245
+ resend.Stop()
246
+ defer resend.Stop()
247
248
for {
351
- select {
352
- case <-c.sendchch:
353
- sendExit = true
354
- default:
249
+ resend.Stop()
250
+ f := c.sendbuf.front()
251
+ if f != nil {
252
+ resend.Reset(time.Duration(c.rto) * time.Millisecond)
253
}
254
select {
357
- case <-c.recvchch:
358
- recvExit = true
359
- default:
360
- }
361
- select {
362
- case p := <-c.recvch:
363
- ack := c.processPacket(p)
364
- lastReceived = time.Now()
365
- if ack {
366
- out := &outgoingPacket{st_state, nil, nil}
367
- selack := c.sendbuf.generateSelectiveACK()
368
- if len(selack) > 0 {
369
- out.ext = []extension{
370
- extension{
371
- typ: ext_selective_ack,
372
- payload: selack,
373
- },
374
- }
375
- c.stat.sentSelectiveACKs++
255
+ case <-c.ackch:
256
+ c.sendACK()
257
+ case <-c.synch:
258
+ c.sendSYN()
259
+ case p := <-c.recv:
260
+ c.stat.receivedPackets++
261
+ c.processPacket(p)
262
+ case b := <-c.writech:
263
+ c.sendDATA(b)
264
+ case <-c.closingch:
265
+ c.enterClosing()
266
+ case <-resend.C:
267
+ if f != nil {
268
+ if resendSeq == f.header.seq {
269
+ resendCont++
270
+ } else {
271
+ resendCont = 0
272
+ resendSeq = f.header.seq
273
}
377
- c.sendPacket(out)
378
- }
379
-
380
- case b := <-c.sendch:
381
- c.sendPacket(b)
382
-
383
- case <-time.After(time.Duration(c.rto) * time.Millisecond):
384
- if !c.state.active && time.Now().Sub(lastReceived) > reset_timeout {
385
- ulog.Printf(2, "Conn(%v): Connection timed out", c.LocalAddr())
386
- c.sendPacket(&outgoingPacket{st_reset, nil, nil})
387
- c.close()
388
- } else {
389
- t, err := c.sendbuf.frontPushedTime()
390
- if err == nil && c.lastTimedOut != t && time.Now().Sub(t) > time.Duration(c.rto)*time.Millisecond {
391
- c.lastTimedOut = t
392
- c.stat.packetTimedOuts++
274
+ c.stat.packetTimedOuts++
275
+ if resendCont > maxRetry {
276
+ c.sendRST()
277
+ c.close()
278
+ } else {
279
c.maxWindow /= 2
280
if c.maxWindow < mtu {
281
c.maxWindow = mtu
282
}
283
for _, p := range c.sendbuf.sequence() {
398
- c.resendPacket(p)
284
+ c.resend(p)
285
}
286
}
287
}
288
+ case <-c.closech:
289
+ c.readbuf.Close()
290
+ c.state = stateClosed
291
+ atomic.StoreInt32(&c.closed, 1)
292
+ return
293
case d := <-c.keepalivech:
294
if d <= 0 {
295
keepalive = nil
@@ -407,56 +298,62 @@ func (c *UTPConn) loop() {
298
}
299
case <-keepalive:
300
ulog.Printf(2, "Conn(%v): Send keepalive", c.LocalAddr())
410
- c.sendPacket(&outgoingPacket{st_state, nil, nil})
411
-
412
- case <-c.quitch:
413
- if c.state.exit != nil {
414
- c.state.exit(c)
415
- }
301
+ c.sendACK()
302
}
417
- if recvExit && sendExit {
418
- return
303
+ if c.closing {
304
+ c.tryFIN()
305
+ if c.state == stateSynSent || c.state == stateFinSent || (c.recvbuf.empty() && c.sendbuf.empty()) {
306
+ c.close()
307
+ }
308
}
309
}
310
}
311
423
-func (c *UTPConn) sendPacket(b *outgoingPacket) {
424
- p := c.makePacket(b)
425
- bin, err := p.MarshalBinary()
426
- if err == nil {
427
- ulog.Printf(3, "SEND %v -> %v: %v", c.conn.LocalAddr(), c.raddr, p.String())
428
- c.stat.sentPackets++
429
- _, err = c.conn.WriteTo(bin, c.raddr)
430
- if err != nil {
431
- return
432
- }
433
- if b.typ != st_state {
434
- c.sendbuf.push(p)
435
- } else {
436
- globalPool.put(p)
312
+func (c *Conn) tryFIN() {
313
+ if c.state != stateFinSent {
314
+ if c.sendFIN() == nil {
315
+ c.writebuf.Close()
316
+ c.state = stateFinSent
317
}
318
}
319
}
320
441
-func (c *UTPConn) resendPacket(p *packet) {
442
- bin, err := p.MarshalBinary()
443
- if err == nil {
444
- ulog.Printf(3, "RESEND %v -> %v: %v", c.conn.LocalAddr(), c.raddr, p.String())
445
- c.stat.resentPackets++
446
- _, err = c.conn.WriteTo(bin, c.raddr)
447
- if err != nil {
448
- return
449
- }
321
+func (c *Conn) enterClosing() {
322
+ if !c.closing {
323
+ c.closing = true
324
}
325
}
326
327
+func (c *Conn) close() {
328
+ c.closechMutex.Lock()
329
+ defer c.closechMutex.Unlock()
330
+ select {
331
+ case <-c.closech:
332
+ default:
333
+ close(c.closech)
334
+ }
335
+ ulog.Printf(1, "Conn(%v): closed", c.LocalAddr())
336
+ ulog.Printf(1, "Conn(%v): * SentPackets: %d", c.LocalAddr(), c.stat.sentPackets)
337
+ ulog.Printf(1, "Conn(%v): * ResentPackets: %d", c.LocalAddr(), c.stat.resentPackets)
338
+ ulog.Printf(1, "Conn(%v): * ReceivedPackets: %d", c.LocalAddr(), c.stat.receivedPackets)
339
+ ulog.Printf(1, "Conn(%v): * ReceivedDuplicatedACKs: %d", c.LocalAddr(), c.stat.receivedDuplicatedACKs)
340
+ ulog.Printf(1, "Conn(%v): * PacketTimedOuts: %d", c.LocalAddr(), c.stat.packetTimedOuts)
341
+ ulog.Printf(1, "Conn(%v): * SentSelectiveACKs: %d", c.LocalAddr(), c.stat.sentSelectiveACKs)
342
+ ulog.Printf(1, "Conn(%v): * ReceivedSelectiveACKs: %d", c.LocalAddr(), c.stat.receivedSelectiveACKs)
343
+ if c.stat.rtoCount > 0 {
344
+ ulog.Printf(1, "Conn(%v): * AverageRTO: %d", c.LocalAddr(), c.stat.rtoSum/int64(c.stat.rtoCount))
345
+ }
346
+}
347
+
348
+func (c *Conn) isOpen() bool {
349
+ return atomic.LoadInt32(&c.closed) == 0
350
+}
351
+
352
func currentMicrosecond() uint32 {
353
return uint32(time.Now().Nanosecond() / 1000)
354
}
355
457
-func (c *UTPConn) processPacket(p *packet) bool {
458
- var ack bool
459
-
356
+func (c *Conn) processPacket(p *packet) {
357
if p.header.t == 0 {
358
c.diff = 0
359
} else {
@@ -469,15 +366,14 @@ func (c *UTPConn) processPacket(p *packet) bool {
366
}
367
}
368
472
- ulog.Printf(3, "RECV %v -> %v: %v", c.raddr, c.conn.LocalAddr(), p.String())
473
- c.stat.receivedPackets++
369
+ c.baseDelay.Push(c.diff)
370
475
- if p.header.typ == st_state {
476
-
477
- f := c.sendbuf.first()
371
+ switch p.header.typ {
372
+ case stState:
373
+ f := c.sendbuf.front()
374
if f != nil && p.header.ack == f.header.seq {
375
for _, e := range p.ext {
480
- if e.typ == ext_selective_ack {
376
+ if e.typ == extSelectiveAck {
377
ulog.Printf(3, "Conn(%v): Receive Selective ACK", c.LocalAddr())
378
c.stat.receivedSelectiveACKs++
379
c.sendbuf.processSelectiveACK(e.payload)
@@ -507,12 +403,12 @@ func (c *UTPConn) processPacket(p *packet) bool {
403
} else if c.rto > 1000 {
404
c.rto = 1000
405
}
510
- c.stat.rtoSum += int(c.rto)
406
+ c.stat.rtoSum += c.rto
407
c.stat.rtoCount++
408
}
409
514
- if c.diff != 0 {
515
- ourDelay := float64(c.diff)
410
+ ourDelay := float64(c.diff - c.baseDelay.Min())
411
+ if ourDelay != 0.0 {
412
offTarget := 100000.0 - ourDelay
413
windowFactor := float64(mtu) / float64(c.maxWindow)
414
delayFactor := offTarget / 100000.0
@@ -523,85 +419,142 @@ func (c *UTPConn) processPacket(p *packet) bool {
419
}
420
ulog.Printf(4, "Conn(%v): Update maxWindow: %d", c.LocalAddr(), c.maxWindow)
421
}
526
- globalPool.put(s)
422
}
423
+
424
c.sendbuf.compact()
425
+
426
if c.lastAck == p.header.ack {
427
c.dupAck++
428
if c.dupAck >= 2 {
532
- ulog.Printf(3, "Conn(%v): Receive 3 duplicated acks: %d", c.LocalAddr(), p.header.ack)
429
c.stat.receivedDuplicatedACKs++
534
- p := c.sendbuf.first()
430
+ ulog.Printf(3, "Conn(%v): Receive 3 duplicated acks: %d", c.LocalAddr(), p.header.ack)
431
+ p := c.sendbuf.front()
432
if p != nil {
433
c.maxWindow /= 2
434
if c.maxWindow < mtu {
435
c.maxWindow = mtu
436
}
437
ulog.Printf(4, "Conn(%v): Update maxWindow: %d", c.LocalAddr(), c.maxWindow)
541
- c.resendPacket(p)
438
+ c.resend(p)
439
}
440
c.dupAck = 0
441
}
442
} else {
443
c.dupAck = 0
444
}
445
+
446
c.lastAck = p.header.ack
447
if p.header.ack == c.seq-1 {
448
wnd := p.header.wnd
449
if wnd > c.maxWindow {
450
wnd = c.maxWindow
451
}
554
- ulog.Printf(4, "Conn(%v): Reset window: %d", c.LocalAddr(), wnd)
555
- go func() {
556
- c.winch <- wnd
557
- }()
452
+ c.writebuf.Reset(wnd)
453
}
559
- if c.state.state != nil {
560
- c.state.state(c, p)
454
+
455
+ if c.state == stateSynSent {
456
+ c.recvbuf = newPacketBuffer(windowSize, int(p.header.seq))
457
+ c.state = stateConnected
458
+ close(c.connch)
459
}
562
- globalPool.put(p)
563
- } else if p.header.typ == st_reset {
564
- globalPool.put(p)
460
+
461
+ case stReset:
462
+ c.sendRST()
463
c.close()
566
- } else {
567
- if c.recvbuf == nil {
568
- return false
569
- }
570
- ack = true
464
+
465
+ default:
466
c.recvbuf.push(p)
467
for _, s := range c.recvbuf.fetchSequence() {
468
c.ack = s.header.seq
574
- switch s.header.typ {
575
- case st_data:
576
- if c.state.data != nil {
577
- c.state.data(c, s)
578
- }
579
- case st_fin:
580
- if c.state.fin != nil {
581
- c.state.fin(c, s)
582
- }
583
- case st_state:
584
- if c.state.state != nil {
585
- c.state.state(c, s)
586
- }
469
+ if s.header.typ == stData {
470
+ c.readbuf.Write(s.payload)
471
+ } else if s.header.typ == stFin {
472
+ c.enterClosing()
473
}
588
- globalPool.put(s)
474
+ }
475
+ c.sendACK()
476
+ }
477
+}
478
+
479
+func (c *Conn) sendACK() {
480
+ ack := c.makePacket(stState, nil, c.raddr)
481
+ selack := c.sendbuf.generateSelectiveACK()
482
+ if selack != nil {
483
+ c.stat.sentSelectiveACKs++
484
+ ack.ext = []extension{
485
+ extension{
486
+ typ: extSelectiveAck,
487
+ payload: selack,
488
+ },
489
}
490
}
591
- return ack
491
+ c.stat.sentPackets++
492
+ c.conn.Send(ack)
493
}
494
594
-func (c *UTPConn) makePacket(b *outgoingPacket) *packet {
595
- wnd := window_size * mtu
495
+func (c *Conn) sendSYN() {
496
+ syn := c.makePacket(stSyn, nil, c.raddr)
497
+ err := c.sendbuf.push(syn)
498
+ if err != nil {
499
+ ulog.Printf(2, "Conn(%v): buffer error: %v", c.LocalAddr(), err)
500
+ return
501
+ }
502
+ c.stat.sentPackets++
503
+ c.conn.Send(syn)
504
+}
505
+
506
+func (c *Conn) sendFIN() error {
507
+ fin := c.makePacket(stFin, nil, c.raddr)
508
+ err := c.sendbuf.push(fin)
509
+ if err != nil {
510
+ ulog.Printf(2, "Conn(%v): buffer error: %v", c.LocalAddr(), err)
511
+ return err
512
+ }
513
+ c.stat.sentPackets++
514
+ c.conn.Send(fin)
515
+ return nil
516
+}
517
+
518
+func (c *Conn) sendRST() {
519
+ rst := c.makePacket(stReset, nil, c.raddr)
520
+ c.stat.sentPackets++
521
+ c.conn.Send(rst)
522
+}
523
+
524
+func (c *Conn) sendDATA(b []byte) {
525
+ for i := 0; i <= len(b)/mss; i++ {
526
+ l := len(b) - i*mss
527
+ if l > mss {
528
+ l = mss
529
+ }
530
+ data := c.makePacket(stData, b[i*mss:i*mss+l], c.raddr)
531
+ c.sendbuf.push(data)
532
+ c.stat.sentPackets++
533
+ c.conn.Send(data)
534
+ }
535
+}
536
+
537
+func (c *Conn) resend(p *packet) {
538
+ c.stat.resentPackets++
539
+ c.conn.Send(p)
540
+ ulog.Printf(3, "Conn(%v): RESEND: %s", c.LocalAddr(), p.String())
541
+}
542
+
543
+func (c *Conn) makePacket(typ int, payload []byte, dst net.Addr) *packet {
544
+ wnd := windowSize * mtu
545
if c.recvbuf != nil {
546
wnd = c.recvbuf.space() * mtu
547
}
548
+ s := c.readbuf.space()
549
+ if wnd > s {
550
+ wnd = s
551
+ }
552
id := c.sid
600
- if b.typ == st_syn {
553
+ if typ == stSyn {
554
id = c.rid
555
}
603
- p := globalPool.get()
604
- p.header.typ = b.typ
556
+ p := &packet{}
557
+ p.header.typ = typ
558
p.header.ver = version
559
p.header.id = id
560
p.header.t = currentMicrosecond()
@@ -609,153 +562,10 @@ func (c *UTPConn) makePacket(b *outgoingPacket) *packet {
562
p.header.wnd = uint32(wnd)
563
p.header.seq = c.seq
564
p.header.ack = c.ack
612
- if b.typ == st_fin {
613
- c.eofid = c.seq
614
- }
615
- if !(b.typ == st_state && len(b.payload) == 0) {
565
+ p.addr = dst
566
+ if typ != stState && typ != stFin {
567
c.seq++
568
}
618
- p.payload = p.payload[:len(b.payload)]
619
- copy(p.payload, b.payload)
569
+ p.payload = payload
570
return p
571
}
622
-
623
-func (c *UTPConn) close() {
624
- if !c.state.closed {
625
- close(c.outchch)
626
- close(c.readchch)
627
- close(c.sendchch)
628
- close(c.recvchch)
629
- close(c.activech)
630
- close(c.finch)
631
- c.closed()
632
-
633
- // Accepted connection
634
- if c.closech != nil {
635
- c.closech <- c.sid
636
- } else {
637
- c.conn.Close()
638
- }
639
-
640
- ulog.Printf(1, "Conn(%v): Closed", c.LocalAddr())
641
- ulog.Printf(1, "Conn(%v): * SentPackets: %d", c.LocalAddr(), c.stat.sentPackets)
642
- ulog.Printf(1, "Conn(%v): * ResentPackets: %d", c.LocalAddr(), c.stat.resentPackets)
643
- ulog.Printf(1, "Conn(%v): * ReceivedPackets: %d", c.LocalAddr(), c.stat.receivedPackets)
644
- ulog.Printf(1, "Conn(%v): * ReceivedDuplicatedACKs: %d", c.LocalAddr(), c.stat.receivedDuplicatedACKs)
645
- ulog.Printf(1, "Conn(%v): * PacketTimedOuts: %d", c.LocalAddr(), c.stat.packetTimedOuts)
646
- ulog.Printf(1, "Conn(%v): * SentSelectiveACKs: %d", c.LocalAddr(), c.stat.sentSelectiveACKs)
647
- ulog.Printf(1, "Conn(%v): * ReceivedSelectiveACKs: %d", c.LocalAddr(), c.stat.receivedSelectiveACKs)
648
- ulog.Printf(1, "Conn(%v): * AverageRTO: %d", c.LocalAddr(), c.stat.rtoSum/c.stat.rtoCount)
649
- }
650
-}
651
-
652
-func (c *UTPConn) closed() {
653
- ulog.Printf(2, "Conn(%v): Change state: CLOSED", c.LocalAddr())
654
- c.state = state_closed
655
-}
656
-
657
-func (c *UTPConn) closing() {
658
- ulog.Printf(2, "Conn(%v): Change state: CLOSING", c.LocalAddr())
659
- c.state = state_closing
660
-}
661
-
662
-func (c *UTPConn) syn_sent() {
663
- ulog.Printf(2, "Conn(%v): Change state: SYN_SENT", c.LocalAddr())
664
- c.state = state_syn_sent
665
-}
666
-
667
-func (c *UTPConn) connected() {
668
- ulog.Printf(2, "Conn(%v): Change state: CONNECTED", c.LocalAddr())
669
- c.state = state_connected
670
-}
671
-
672
-func (c *UTPConn) fin_sent() {
673
- ulog.Printf(2, "Conn(%v): Change state: FIN_SENT", c.LocalAddr())
674
- c.state = state_fin_sent
675
-}
676
-
677
-type state struct {
678
- data func(c *UTPConn, p *packet)
679
- fin func(c *UTPConn, p *packet)
680
- state func(c *UTPConn, p *packet)
681
- exit func(c *UTPConn)
682
- active bool
683
- closed bool
684
-}
685
-
686
-var state_closed state = state{
687
- closed: true,
688
-}
689
-
690
-var state_closing state = state{
691
- data: func(c *UTPConn, p *packet) {
692
- select {
693
- case c.readch <- append([]byte(nil), p.payload...):
694
- case <-c.readchch:
695
- }
696
- if c.recvbuf.empty() && c.sendbuf.empty() {
697
- c.close()
698
- }
699
- },
700
- state: func(c *UTPConn, p *packet) {
701
- if c.recvbuf.empty() && c.sendbuf.empty() {
702
- c.close()
703
- }
704
- },
705
-}
706
-
707
-var state_syn_sent state = state{
708
- state: func(c *UTPConn, p *packet) {
709
- c.recvbuf = newPacketBuffer(window_size, int(p.header.seq))
710
- c.connected()
711
- c.connch <- nil
712
- },
713
- exit: func(c *UTPConn) {
714
- go func() {
715
- select {
716
- case c.outch <- &outgoingPacket{st_fin, nil, nil}:
717
- case <-c.outchch:
718
- }
719
- }()
720
- c.fin_sent()
721
- },
722
- active: true,
723
-}
724
-
725
-var state_connected state = state{
726
- data: func(c *UTPConn, p *packet) {
727
- select {
728
- case c.readch <- append([]byte(nil), p.payload...):
729
- case <-c.readchch:
730
- }
731
- },
732
- fin: func(c *UTPConn, p *packet) {
733
- if c.recvbuf.empty() && c.sendbuf.empty() {
734
- c.close()
735
- } else {
736
- c.closing()
737
- }
738
- },
739
- exit: func(c *UTPConn) {
740
- go func() {
741
- select {
742
- case c.outch <- &outgoingPacket{st_fin, nil, nil}:
743
- case <-c.outchch:
744
- }
745
- }()
746
- c.fin_sent()
747
- },
748
- active: true,
749
-}
750
-
751
-var state_fin_sent state = state{
752
- state: func(c *UTPConn, p *packet) {
753
- if p.header.ack == c.eofid {
754
- if c.recvbuf.empty() && c.sendbuf.empty() {
755
- c.close()
756
- } else {
757
- c.closing()
758
- }
759
- }
760
- },
761
-}
Godeps/_workspace/src/github.com/h2so5/utp/conn_test.go
new
+87
@@ -0,0 +1,87 @@
1
+package utp
2
+
3
+import (
4
+ "bytes"
5
+ "testing"
6
+)
7
+
8
+func TestReadWrite(t *testing.T) {
9
+ addr, err := ResolveAddr("utp", "127.0.0.1:0")
10
+ if err != nil {
11
+ t.Fatal(err)
12
+ }
13
+
14
+ l, err := Listen("utp", addr)
15
+ if err != nil {
16
+ t.Fatal(err)
17
+ }
18
+ defer l.Close()
19
+
20
+ payload := []byte("abcdefgh")
21
+
22
+ ch := make(chan int)
23
+ go func() {
24
+ c, err := l.Accept()
25
+ if err != nil {
26
+ t.Fatal(err)
27
+ }
28
+ defer c.Close()
29
+
30
+ var buf [256]byte
31
+ length, err := c.Read(buf[:])
32
+ if err != nil {
33
+ t.Fatal(err)
34
+ }
35
+ if !bytes.Equal(payload, buf[:length]) {
36
+ t.Errorf("expected payload of %v; got %v", payload, buf[:length])
37
+ }
38
+
39
+ ch <- 0
40
+ }()
41
+
42
+ c, err := DialUTP("utp", nil, l.Addr().(*Addr))
43
+ if err != nil {
44
+ t.Fatal(err)
45
+ }
46
+ defer c.Close()
47
+
48
+ _, err = c.Write(payload)
49
+ if err != nil {
50
+ t.Fatal(err)
51
+ }
52
+
53
+ <-ch
54
+}
55
+
56
+func TestClose(t *testing.T) {
57
+ addr, err := ResolveAddr("utp", "127.0.0.1:0")
58
+ if err != nil {
59
+ t.Fatal(err)
60
+ }
61
+
62
+ l, err := Listen("utp", addr)
63
+ if err != nil {
64
+ t.Fatal(err)
65
+ }
66
+ defer l.Close()
67
+
68
+ go func() {
69
+ c, err := l.Accept()
70
+ if err != nil {
71
+ t.Fatal(err)
72
+ }
73
+ c.Close()
74
+ }()
75
+
76
+ c, err := DialUTP("utp", nil, l.Addr().(*Addr))
77
+ if err != nil {
78
+ t.Fatal(err)
79
+ }
80
+ defer c.Close()
81
+
82
+ var b [128]byte
83
+ _, err = c.Read(b[:])
84
+ if err == nil {
85
+ t.Fatal("Read should fail")
86
+ }
87
+}
Godeps/_workspace/src/github.com/h2so5/utp/dial.go
+48
-14
@@ -2,24 +2,58 @@ package utp
2
3
import (
4
"errors"
5
+ "math"
6
+ "math/rand"
7
"net"
8
"time"
9
)
10
9
-func Dial(n, addr string) (*UTPConn, error) {
10
- raddr, err := ResolveUTPAddr(n, addr)
11
+// DialUTP connects to the remote address raddr on the network net,
12
+// which must be "utp", "utp4", or "utp6". If laddr is not nil, it is
13
+// used as the local address for the connection.
14
+func DialUTP(n string, laddr, raddr *Addr) (*Conn, error) {
15
+ return DialUTPTimeout(n, laddr, raddr, 0)
16
+}
17
+
18
+// DialUTPTimeout acts like Dial but takes a timeout.
19
+// The timeout includes name resolution, if required.
20
+func DialUTPTimeout(n string, laddr, raddr *Addr, timeout time.Duration) (*Conn, error) {
21
+ conn, err := getSharedBaseConn(n, laddr)
22
if err != nil {
23
return nil, err
24
}
14
- return DialUTP(n, nil, raddr)
15
-}
25
17
-func DialUTP(n string, laddr, raddr *UTPAddr) (*UTPConn, error) {
18
- return dial(n, laddr, raddr, 0)
19
-}
26
+ id := uint16(rand.Intn(math.MaxUint16))
27
+ c := newConn()
28
+ c.conn = conn
29
+ c.raddr = raddr.Addr
30
+ c.rid = id
31
+ c.sid = id + 1
32
+ c.seq = 1
33
+ c.state = stateSynSent
34
+ c.sendbuf = newPacketBuffer(windowSize*2, 1)
35
+ c.conn.Register(int32(c.rid), c.recv)
36
+ go c.loop()
37
+ c.synch <- 0
38
21
-func DialUTPTimeout(n string, laddr, raddr *UTPAddr, timeout time.Duration) (*UTPConn, error) {
22
- return dial(n, laddr, raddr, timeout)
39
+ t := time.NewTimer(timeout)
40
+ defer t.Stop()
41
+ if timeout == 0 {
42
+ t.Stop()
43
+ }
44
+
45
+ select {
46
+ case <-c.connch:
47
+ case <-t.C:
48
+ c.Close()
49
+ return nil, &net.OpError{
50
+ Op: "dial",
51
+ Net: c.LocalAddr().Network(),
52
+ Addr: c.LocalAddr(),
53
+ Err: errTimeout,
54
+ }
55
+ }
56
+ return c, nil
57
}
58
59
// A Dialer contains options for connecting to an address.
@@ -49,18 +83,18 @@ type Dialer struct {
83
// Dial connects to the address on the named network.
84
//
85
// See func Dial for a description of the network and address parameters.
52
-func (d *Dialer) Dial(n, addr string) (*UTPConn, error) {
53
- raddr, err := ResolveUTPAddr(n, addr)
86
+func (d *Dialer) Dial(n, addr string) (*Conn, error) {
87
+ raddr, err := ResolveAddr(n, addr)
88
if err != nil {
89
return nil, err
90
}
91
58
- var laddr *UTPAddr
92
+ var laddr *Addr
93
if d.LocalAddr != nil {
94
var ok bool
61
- laddr, ok = d.LocalAddr.(*UTPAddr)
95
+ laddr, ok = d.LocalAddr.(*Addr)
96
if !ok {
63
- return nil, errors.New("Dialer.LocalAddr is not a UTPAddr")
97
+ return nil, errors.New("Dialer.LocalAddr is not a Addr")
98
}
99
}
100
Godeps/_workspace/src/github.com/h2so5/utp/dial_test.go
new
+52
@@ -0,0 +1,52 @@
1
+package utp
2
+
3
+import (
4
+ "testing"
5
+ "time"
6
+)
7
+
8
+func TestDial(t *testing.T) {
9
+ addr, err := ResolveAddr("utp", "127.0.0.1:0")
10
+ if err != nil {
11
+ t.Fatal(err)
12
+ }
13
+
14
+ l, err := Listen("utp", addr)
15
+ if err != nil {
16
+ t.Fatal(err)
17
+ }
18
+ defer l.Close()
19
+
20
+ ch := make(chan struct{})
21
+ go func() {
22
+ l.Accept()
23
+ close(ch)
24
+ }()
25
+
26
+ c, err := DialUTP("utp", nil, l.Addr().(*Addr))
27
+ if err != nil {
28
+ t.Fatal(err)
29
+ }
30
+ defer c.Close()
31
+
32
+ <-ch
33
+}
34
+
35
+func TestDialFastTimeout(t *testing.T) {
36
+ addr, err := ResolveAddr("utp", "127.0.0.1:0")
37
+ if err != nil {
38
+ t.Fatal(err)
39
+ }
40
+
41
+ l, err := Listen("utp", addr)
42
+ if err != nil {
43
+ t.Fatal(err)
44
+ }
45
+ defer l.Close()
46
+ _, err = (&Dialer{
47
+ Timeout: time.Nanosecond,
48
+ }).Dial("utp", l.Addr().String())
49
+ if err == nil {
50
+ t.Fatal("expected an error")
51
+ }
52
+}
Godeps/_workspace/src/github.com/h2so5/utp/listener.go
+91
-274
@@ -1,329 +1,146 @@
1
package utp
2
3
import (
4
- "errors"
4
"math"
5
"math/rand"
6
"net"
7
+ "sync"
8
+ "sync/atomic"
9
"syscall"
10
"time"
11
)
12
12
-type UTPListener struct {
13
+// Listener is a UTP network listener. Clients should typically
14
+// use variables of type Listener instead of assuming UTP.
15
+type Listener struct {
16
// RawConn represents an out-of-band connection.
17
// This allows a single socket to handle multiple protocols.
18
RawConn net.PacketConn
19
17
- conn net.PacketConn
18
- conns map[uint16]*UTPConn
19
- accept chan (*UTPConn)
20
- err chan (error)
21
- lasterr error
22
- deadline time.Time
23
- closech chan int
24
- connch chan uint16
25
- closed bool
20
+ conn *baseConn
21
+ deadline time.Time
22
+ deadlineMutex sync.RWMutex
23
+ closed int32
24
}
25
28
-func Listen(n, laddr string) (*UTPListener, error) {
29
- addr, err := ResolveUTPAddr(n, laddr)
30
- if err != nil {
31
- return nil, err
32
- }
33
- return ListenUTP(n, addr)
34
-}
26
+func (l *Listener) ok() bool { return l != nil && l.conn != nil }
27
36
-func ListenUTP(n string, laddr *UTPAddr) (*UTPListener, error) {
37
- udpnet, err := utp2udp(n)
38
- if err != nil {
39
- return nil, err
40
- }
41
- conn, err := listenPacket(udpnet, laddr.Addr.String())
28
+// Listen announces on the UTP address laddr and returns a UTP
29
+// listener. Net must be "utp", "utp4", or "utp6". If laddr has a
30
+// port of 0, ListenUTP will choose an available port. The caller can
31
+// use the Addr method of Listener to retrieve the chosen address.
32
+func Listen(n string, laddr *Addr) (*Listener, error) {
33
+ conn, err := newBaseConn(n, laddr)
34
if err != nil {
35
return nil, err
36
}
45
-
46
- l := UTPListener{
47
- RawConn: newRawConn(conn),
37
+ l := &Listener{
38
+ RawConn: conn,
39
conn: conn,
49
- conns: make(map[uint16]*UTPConn),
50
- accept: make(chan (*UTPConn), 10),
51
- err: make(chan (error), 1),
52
- closech: make(chan int),
53
- connch: make(chan uint16),
54
- lasterr: nil,
40
}
56
-
57
- l.listen()
58
- return &l, nil
41
+ conn.Register(-1, nil)
42
+ return l, nil
43
}
44
61
-type incoming struct {
62
- p *packet
63
- addr net.Addr
64
-}
65
-
66
-func (l *UTPListener) listen() {
67
- inch := make(chan incoming)
68
- raw := l.RawConn.(*rawConn)
69
-
70
- // reads udp packets
71
- go func() {
72
- for {
73
- var buf [mtu]byte
74
- len, addr, err := l.conn.ReadFrom(buf[:])
75
- if err != nil {
76
- l.err <- err
77
- return
78
- }
79
- p, err := readPacket(buf[:len])
80
- if err == nil {
81
- inch <- incoming{p, addr}
82
- } else {
83
- select {
84
- case <-raw.closed:
85
- default:
86
- i := rawIncoming{b: buf[:len], addr: addr}
87
- select {
88
- case raw.in <- i:
89
- default:
90
- // discard the oldest packet
91
- <-raw.in
92
- raw.in <- i
93
- }
94
- }
95
- }
96
- }
97
- }()
98
-
99
- go func() {
100
- for {
101
- select {
102
- case i := <-inch:
103
- l.processPacket(i.p, i.addr)
104
- case <-l.closech:
105
- ulog.Printf(2, "Listener(%v): Stop listening", l.conn.LocalAddr())
106
- close(l.accept)
107
- l.closed = true
108
- case id := <-l.connch:
109
- if _, ok := l.conns[id]; !ok {
110
- delete(l.conns, id+1)
111
- ulog.Printf(2, "Listener(%v): Connection closed #%d (alive: %d)", l.conn.LocalAddr(), id, len(l.conns))
112
- if l.closed && len(l.conns) == 0 {
113
- ulog.Printf(2, "Listener(%v): All accepted connections are closed", l.conn.LocalAddr())
114
- l.conn.Close()
115
- ulog.Printf(1, "Listener(%v): Closed", l.conn.LocalAddr())
116
- return
117
- }
118
- }
119
- }
120
- }
121
- }()
122
-
123
- ulog.Printf(1, "Listener(%v): Start listening", l.conn.LocalAddr())
124
-}
125
-
126
-func listenPacket(n, addr string) (net.PacketConn, error) {
127
- if n == "mem" {
128
- return nil, errors.New("TODO implement in-memory packet connection")
129
- }
130
- return net.ListenPacket(n, addr)
131
-}
132
-
133
-func (l *UTPListener) processPacket(p *packet, addr net.Addr) {
134
- switch p.header.typ {
135
- case st_data, st_fin, st_state, st_reset:
136
- if c, ok := l.conns[p.header.id]; ok {
137
- select {
138
- case c.recvch <- p:
139
- case <-c.recvchch:
140
- }
141
- }
142
- case st_syn:
143
- if l.closed {
144
- return
145
- }
146
- sid := p.header.id + 1
147
- if _, ok := l.conns[p.header.id]; !ok {
148
- seq := rand.Intn(math.MaxUint16)
149
-
150
- c := newUTPConn()
151
- c.conn = l.conn
152
- c.raddr = addr
153
- c.rid = p.header.id + 1
154
- c.sid = p.header.id
155
- c.seq = uint16(seq)
156
- c.ack = p.header.seq
157
- c.diff = currentMicrosecond() - p.header.t
158
- c.state = state_connected
159
- c.closech = l.connch
160
- c.recvbuf = newPacketBuffer(window_size, int(p.header.seq))
161
- c.sendbuf = newPacketBuffer(window_size, seq)
162
-
163
- go c.loop()
164
- select {
165
- case c.recvch <- p:
166
- case <-c.recvchch:
167
- }
168
-
169
- l.conns[sid] = c
170
- ulog.Printf(2, "Listener(%v): New incoming connection #%d from %v (alive: %d)", l.conn.LocalAddr(), sid, addr, len(l.conns))
171
-
172
- l.accept <- c
173
- }
174
- }
175
-}
176
-
177
-func (l *UTPListener) Accept() (net.Conn, error) {
45
+// Accept implements the Accept method in the Listener interface; it
46
+// waits for the next call and returns a generic Conn.
47
+func (l *Listener) Accept() (net.Conn, error) {
48
return l.AcceptUTP()
49
}
50
181
-func (l *UTPListener) AcceptUTP() (*UTPConn, error) {
182
- if l == nil || l.conn == nil {
51
+// AcceptUTP accepts the next incoming call and returns the new
52
+// connection.
53
+func (l *Listener) AcceptUTP() (*Conn, error) {
54
+ if !l.ok() {
55
return nil, syscall.EINVAL
56
}
185
- if l.lasterr != nil {
186
- return nil, l.lasterr
187
- }
188
- var timeout <-chan time.Time
189
- if !l.deadline.IsZero() {
190
- timeout = time.After(l.deadline.Sub(time.Now()))
191
- }
192
- select {
193
- case conn := <-l.accept:
194
- if conn == nil {
195
- return nil, errors.New("use of closed network connection")
57
+ if !l.isOpen() {
58
+ return nil, &net.OpError{
59
+ Op: "accept",
60
+ Net: l.conn.LocalAddr().Network(),
61
+ Addr: l.conn.LocalAddr(),
62
+ Err: errClosing,
63
}
197
- return conn, nil
198
- case err := <-l.err:
199
- l.lasterr = err
200
- return nil, err
201
- case <-timeout:
202
- return nil, &timeoutError{}
203
- }
204
-}
205
-
206
-func (l *UTPListener) Addr() net.Addr {
207
- return &UTPAddr{Addr: l.conn.LocalAddr()}
208
-}
209
-
210
-func (l *UTPListener) Close() error {
211
- if l == nil || l.conn == nil {
212
- return syscall.EINVAL
64
}
214
- l.closech <- 0
215
- l.RawConn.Close()
216
- return nil
217
-}
218
-
219
-func (l *UTPListener) SetDeadline(t time.Time) error {
220
- if l == nil || l.conn == nil {
221
- return syscall.EINVAL
65
+ l.deadlineMutex.RLock()
66
+ d := timeToDeadline(l.deadline)
67
+ l.deadlineMutex.RUnlock()
68
+ p, err := l.conn.RecvSyn(d)
69
+ if err != nil {
70
+ return nil, &net.OpError{
71
+ Op: "accept",
72
+ Net: l.conn.LocalAddr().Network(),
73
+ Addr: l.conn.LocalAddr(),
74
+ Err: errClosing,
75
+ }
76
}
223
- l.deadline = t
224
- return nil
225
-}
77
227
-type rawIncoming struct {
228
- b []byte
229
- addr net.Addr
230
-}
78
+ seq := rand.Intn(math.MaxUint16)
79
+ rid := p.header.id + 1
80
232
-type rawConn struct {
233
- conn net.PacketConn
234
- rdeadline, wdeadline time.Time
235
- in chan rawIncoming
236
- closed chan int
237
-}
81
+ c := newConn()
82
+ c.state = stateConnected
83
+ c.conn = l.conn
84
+ c.raddr = p.addr
85
+ c.rid = p.header.id + 1
86
+ c.sid = p.header.id
87
+ c.seq = uint16(seq)
88
+ c.ack = p.header.seq
89
+ c.recvbuf = newPacketBuffer(windowSize, int(p.header.seq))
90
+ c.sendbuf = newPacketBuffer(windowSize*2, seq)
91
+ l.conn.Register(int32(rid), c.recv)
92
+ go c.loop()
93
+ c.recv <- p
94
239
-func newRawConn(conn net.PacketConn) *rawConn {
240
- return &rawConn{
241
- conn: conn,
242
- in: make(chan rawIncoming, 100),
243
- closed: make(chan int),
244
- }
95
+ ulog.Printf(2, "baseConn(%v): accept #%d from %v", c.LocalAddr(), c.rid, c.raddr)
96
+ return c, nil
97
}
98
247
-func (c *rawConn) ok() bool { return c != nil && c.conn != nil }
248
-
249
-func (c *rawConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
250
- if !c.ok() {
251
- return 0, nil, syscall.EINVAL
252
- }
253
- select {
254
- case <-c.closed:
255
- return 0, nil, errors.New("use of closed network connection")
256
- default:
257
- }
258
- var timeout <-chan time.Time
259
- if !c.rdeadline.IsZero() {
260
- timeout = time.After(c.rdeadline.Sub(time.Now()))
261
- }
262
- select {
263
- case r := <-c.in:
264
- return copy(b, r.b), r.addr, nil
265
- case <-timeout:
266
- return 0, nil, &timeoutError{}
267
- }
268
-}
269
-
270
-func (c *rawConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
271
- if !c.ok() {
272
- return 0, syscall.EINVAL
273
- }
274
- select {
275
- case <-c.closed:
276
- return 0, errors.New("use of closed network connection")
277
- default:
99
+// Addr returns the listener's network address, a *Addr.
100
+func (l *Listener) Addr() net.Addr {
101
+ if !l.ok() {
102
+ return nil
103
}
279
- return c.conn.WriteTo(b, addr)
104
+ return l.conn.LocalAddr()
105
}
106
282
-func (c *rawConn) Close() error {
283
- if !c.ok() {
107
+// Close stops listening on the UTP address.
108
+// Already Accepted connections are not closed.
109
+func (l *Listener) Close() error {
110
+ if !l.ok() {
111
return syscall.EINVAL
112
}
286
- select {
287
- case <-c.closed:
288
- return errors.New("use of closed network connection")
289
- default:
290
- close(c.closed)
113
+ if !l.close() {
114
+ return &net.OpError{
115
+ Op: "close",
116
+ Net: l.conn.LocalAddr().Network(),
117
+ Addr: l.conn.LocalAddr(),
118
+ Err: errClosing,
119
+ }
120
}
121
return nil
122
}
123
295
-func (c *rawConn) LocalAddr() net.Addr {
296
- if !c.ok() {
297
- return nil
298
- }
299
- return c.conn.LocalAddr()
300
-}
301
-
302
-func (c *rawConn) SetDeadline(t time.Time) error {
303
- if !c.ok() {
124
+// SetDeadline sets the deadline associated with the listener.
125
+// A zero time value disables the deadline.
126
+func (l *Listener) SetDeadline(t time.Time) error {
127
+ if !l.ok() {
128
return syscall.EINVAL
129
}
306
- if err := c.SetReadDeadline(t); err != nil {
307
- return err
308
- }
309
- if err := c.SetWriteDeadline(t); err != nil {
310
- return err
311
- }
130
+ l.deadlineMutex.Lock()
131
+ defer l.deadlineMutex.Unlock()
132
+ l.deadline = t
133
return nil
134
}
135
315
-func (c *rawConn) SetReadDeadline(t time.Time) error {
316
- if !c.ok() {
317
- return syscall.EINVAL
136
+func (l *Listener) close() bool {
137
+ if atomic.CompareAndSwapInt32(&l.closed, 0, 1) {
138
+ l.conn.Unregister(-1)
139
+ return true
140
}
319
- c.rdeadline = t
320
- return nil
141
+ return false
142
}
143
323
-func (c *rawConn) SetWriteDeadline(t time.Time) error {
324
- if !c.ok() {
325
- return syscall.EINVAL
326
- }
327
- c.wdeadline = t
328
- return nil
144
+func (l *Listener) isOpen() bool {
145
+ return atomic.LoadInt32(&l.closed) == 0
146
}
Godeps/_workspace/src/github.com/h2so5/utp/listener_test.go
new
+68
@@ -0,0 +1,68 @@
1
+package utp
2
+
3
+import (
4
+ "net"
5
+ "testing"
6
+)
7
+
8
+func TestListenerAccept(t *testing.T) {
9
+ addr, err := ResolveAddr("utp", "127.0.0.1:0")
10
+ if err != nil {
11
+ t.Fatal(err)
12
+ }
13
+
14
+ l, err := Listen("utp", addr)
15
+ if err != nil {
16
+ t.Fatal(err)
17
+ }
18
+ defer l.Close()
19
+
20
+ uaddr, err := net.ResolveUDPAddr("udp", l.Addr().String())
21
+ if err != nil {
22
+ t.Fatal(err)
23
+ }
24
+
25
+ uc, err := net.DialUDP("udp", nil, uaddr)
26
+ if err != nil {
27
+ t.Fatal(err)
28
+ }
29
+ defer uc.Close()
30
+
31
+ for i := 0; i < 1; i++ {
32
+ p := &packet{header: header{typ: stSyn, ver: version, id: uint16(i)}}
33
+ payload, err := p.MarshalBinary()
34
+ if err != nil {
35
+ t.Fatal(err)
36
+ }
37
+ go func() {
38
+ uc.Write(payload)
39
+ }()
40
+
41
+ a, err := l.Accept()
42
+ if err != nil {
43
+ t.Fatal(err)
44
+ }
45
+ a.Close()
46
+ }
47
+}
48
+
49
+func TestListenerClose(t *testing.T) {
50
+ addr, err := ResolveAddr("utp", ":0")
51
+ if err != nil {
52
+ t.Fatal(err)
53
+ }
54
+
55
+ l, err := Listen("utp", addr)
56
+ if err != nil {
57
+ t.Fatal(err)
58
+ }
59
+
60
+ for i := 0; i < 5; i++ {
61
+ l.Close()
62
+ }
63
+
64
+ _, err = l.Accept()
65
+ if err == nil {
66
+ t.Fatal("Accept should fail")
67
+ }
68
+}
Godeps/_workspace/src/github.com/h2so5/utp/packet.go
+16
-58
@@ -5,7 +5,8 @@ import (
5
"encoding/binary"
6
"fmt"
7
"io"
8
- "sync"
8
+ "io/ioutil"
9
+ "net"
10
)
11
12
type header struct {
@@ -24,16 +25,11 @@ type packet struct {
25
header header
26
ext []extension
27
payload []byte
27
-}
28
-
29
-type outgoingPacket struct {
30
- typ int
31
- ext []extension
32
- payload []byte
28
+ addr net.Addr
29
}
30
31
func (p *packet) MarshalBinary() ([]byte, error) {
36
- firstExt := ext_none
32
+ firstExt := extNone
33
if len(p.ext) > 0 {
34
firstExt = p.ext[0].typ
35
}
@@ -68,7 +64,7 @@ func (p *packet) MarshalBinary() ([]byte, error) {
64
65
if len(p.ext) > 0 {
66
for i, e := range p.ext {
71
- next := ext_none
67
+ next := extNone
68
if i < len(p.ext)-1 {
69
next = p.ext[i+1].typ
70
}
@@ -123,7 +119,7 @@ func (p *packet) UnmarshalBinary(data []byte) error {
119
}
120
}
121
126
- for e != ext_none {
122
+ for e != extNone {
123
currentExt := int(e)
124
var l uint8
125
var ext = []interface{}{
@@ -173,68 +169,30 @@ func (p *packet) UnmarshalBinary(data []byte) error {
169
p.header.typ = int((tv >> 4) & 0xF)
170
p.header.ver = int(tv & 0xF)
171
176
- l := buf.Len()
177
- if l > 0 {
178
- p.payload = p.payload[:l]
179
- _, err := buf.Read(p.payload[:])
180
- if err != nil {
181
- return err
182
- }
172
+ data, err := ioutil.ReadAll(buf)
173
+ if err != nil {
174
+ return err
175
}
176
+ p.payload = data
177
178
return nil
179
}
180
181
func (p packet) String() string {
189
- var s string = fmt.Sprintf("[%d ", p.header.id)
182
+ s := fmt.Sprintf("[%d ", p.header.id)
183
switch p.header.typ {
191
- case st_data:
184
+ case stData:
185
s += "ST_DATA"
193
- case st_fin:
186
+ case stFin:
187
s += "ST_FIN"
195
- case st_state:
188
+ case stState:
189
s += "ST_STATE"
197
- case st_reset:
190
+ case stReset:
191
s += "ST_RESET"
199
- case st_syn:
192
+ case stSyn:
193
s += "ST_SYN"
194
}
195
s += fmt.Sprintf(" seq:%d ack:%d len:%d", p.header.seq, p.header.ack, len(p.payload))
196
s += "]"
197
return s
198
}
206
-
207
-var globalPool packetPool
208
-
209
-type packetPool struct {
210
- root *packetPoolNode
211
- mutex sync.Mutex
212
-}
213
-
214
-type packetPoolNode struct {
215
- p *packet
216
- next *packetPoolNode
217
-}
218
-
219
-func (o *packetPool) get() *packet {
220
- o.mutex.Lock()
221
- defer o.mutex.Unlock()
222
- r := o.root
223
- if r != nil {
224
- o.root = o.root.next
225
- return r.p
226
- } else {
227
- return &packet{
228
- payload: make([]byte, 0, mss),
229
- }
230
- }
231
-}
232
-
233
-func (o *packetPool) put(p *packet) {
234
- o.mutex.Lock()
235
- defer o.mutex.Unlock()
236
- o.root = &packetPoolNode{
237
- p: p,
238
- next: o.root,
239
- }
240
-}
Godeps/_workspace/src/github.com/h2so5/utp/packet_test.go
new
+64
@@ -0,0 +1,64 @@
1
+package utp
2
+
3
+import (
4
+ "io"
5
+ "reflect"
6
+ "testing"
7
+)
8
+
9
+func TestPacketBinary(t *testing.T) {
10
+ h := header{
11
+ typ: stFin,
12
+ ver: version,
13
+ id: 100,
14
+ t: 50000,
15
+ diff: 10000,
16
+ wnd: 65535,
17
+ seq: 100,
18
+ ack: 200,
19
+ }
20
+
21
+ e := []extension{
22
+ extension{
23
+ typ: extSelectiveAck,
24
+ payload: []byte{0, 1, 0, 1},
25
+ },
26
+ extension{
27
+ typ: extSelectiveAck,
28
+ payload: []byte{100, 0, 200, 0},
29
+ },
30
+ }
31
+
32
+ p := packet{
33
+ header: h,
34
+ ext: e,
35
+ payload: []byte("abcdefg"),
36
+ }
37
+
38
+ b, err := p.MarshalBinary()
39
+ if err != nil {
40
+ t.Fatal(err)
41
+ }
42
+
43
+ p2 := packet{payload: make([]byte, 0, mss)}
44
+ err = p2.UnmarshalBinary(b)
45
+ if err != nil {
46
+ t.Fatal(err)
47
+ }
48
+
49
+ if !reflect.DeepEqual(p, p2) {
50
+ t.Errorf("expected packet of %v; got %v", p, p2)
51
+ }
52
+}
53
+
54
+func TestUnmarshalShortPacket(t *testing.T) {
55
+ b := make([]byte, 18)
56
+ p := packet{}
57
+ err := p.UnmarshalBinary(b)
58
+
59
+ if err == nil {
60
+ t.Fatal("UnmarshalBinary should fail")
61
+ } else if err != io.EOF {
62
+ t.Fatal(err)
63
+ }
64
+}
Godeps/_workspace/src/github.com/h2so5/utp/ucat/ucat.go
+6
-2
@@ -111,7 +111,11 @@ func log(format string, vals ...interface{}) {
111
// Listen listens and accepts one incoming uTP connection on a given port,
112
// and pipes all incoming data to os.Stdout.
113
func Listen(localAddr string) error {
114
- l, err := utp.Listen("utp", localAddr)
114
+ laddr, err := utp.ResolveAddr("utp", localAddr)
115
+ if err != nil {
116
+ return fmt.Errorf("failed to resolve address %s", localAddr)
117
+ }
118
+ l, err := utp.Listen("utp", laddr)
119
if err != nil {
120
return err
121
}
@@ -138,7 +142,7 @@ func Dial(localAddr, remoteAddr string) error {
142
var laddr net.Addr
143
var err error
144
if localAddr != "" {
141
- laddr, err = utp.ResolveUTPAddr("utp", localAddr)
145
+ laddr, err = utp.ResolveAddr("utp", localAddr)
146
if err != nil {
147
return fmt.Errorf("failed to resolve address %s", localAddr)
148
}
Godeps/_workspace/src/github.com/h2so5/utp/utp.go
+34
-16
@@ -1,25 +1,38 @@
1
package utp
2
3
-import "time"
3
+import (
4
+ "errors"
5
+ "time"
6
+)
7
8
const (
9
version = 1
10
8
- st_data = 0
9
- st_fin = 1
10
- st_state = 2
11
- st_reset = 3
12
- st_syn = 4
13
-
14
- ext_none = 0
15
- ext_selective_ack = 1
16
-
17
- header_size = 20
18
- mtu = 3200
19
- mss = mtu - header_size
20
- window_size = 100
21
-
22
- reset_timeout = time.Second
11
+ stData = 0
12
+ stFin = 1
13
+ stState = 2
14
+ stReset = 3
15
+ stSyn = 4
16
+
17
+ stateClosed = iota
18
+ stateClosing
19
+ stateSynSent
20
+ stateConnected
21
+ stateFinSent
22
+
23
+ extNone = 0
24
+ extSelectiveAck = 1
25
+
26
+ headerSize = 20
27
+ mtu = 3200
28
+ mss = mtu - headerSize
29
+ windowSize = 100
30
+ packetBufferSize = 256
31
+ readBufferSize = 1048576
32
+ maxRetry = 3
33
+
34
+ maxUdpPayload = 65507
35
+ resetTimeout = time.Second
36
)
37
38
type timeoutError struct{}
@@ -27,3 +40,8 @@ type timeoutError struct{}
40
func (e *timeoutError) Error() string { return "i/o timeout" }
41
func (e *timeoutError) Timeout() bool { return true }
42
func (e *timeoutError) Temporary() bool { return true }
43
+
44
+var (
45
+ errTimeout error = &timeoutError{}
46
+ errClosing = errors.New("use of closed network connection")
47
+)
Godeps/_workspace/src/github.com/h2so5/utp/utp_test.go
deleted
-601
@@ -1,601 +0,0 @@
1
-package utp
2
-
3
-import (
4
- "bytes"
5
- "io"
6
- "io/ioutil"
7
- "math"
8
- "math/rand"
9
- "net"
10
- "reflect"
11
- "testing"
12
- "time"
13
-)
14
-
15
-func init() {
16
- rand.Seed(time.Now().Unix())
17
-}
18
-
19
-func TestReadWrite(t *testing.T) {
20
- ln, err := Listen("utp", "127.0.0.1:0")
21
- if err != nil {
22
- t.Fatal(err)
23
- }
24
-
25
- raddr, err := ResolveUTPAddr("utp", ln.Addr().String())
26
- if err != nil {
27
- t.Fatal(err)
28
- }
29
-
30
- c, err := DialUTPTimeout("utp", nil, raddr, 1000*time.Millisecond)
31
- if err != nil {
32
- t.Fatal(err)
33
- }
34
- defer c.Close()
35
-
36
- err = ln.SetDeadline(time.Now().Add(1000 * time.Millisecond))
37
- if err != nil {
38
- t.Fatal(err)
39
- }
40
-
41
- s, err := ln.Accept()
42
- if err != nil {
43
- t.Fatal(err)
44
- }
45
- ln.Close()
46
-
47
- payload := []byte("Hello!")
48
- _, err = c.Write(payload)
49
- if err != nil {
50
- t.Fatal(err)
51
- }
52
-
53
- err = s.SetDeadline(time.Now().Add(1000 * time.Millisecond))
54
- if err != nil {
55
- t.Fatal(err)
56
- }
57
-
58
- var buf [256]byte
59
- l, err := s.Read(buf[:])
60
- if err != nil {
61
- t.Fatal(err)
62
- }
63
-
64
- if !bytes.Equal(payload, buf[:l]) {
65
- t.Errorf("expected payload of %v; got %v", payload, buf[:l])
66
- }
67
-
68
- payload2 := []byte("World!")
69
- _, err = s.Write(payload2)
70
- if err != nil {
71
- t.Fatal(err)
72
- }
73
-
74
- err = c.SetDeadline(time.Now().Add(1000 * time.Millisecond))
75
- if err != nil {
76
- t.Fatal(err)
77
- }
78
-
79
- l, err = c.Read(buf[:])
80
- if err != nil {
81
- t.Fatal(err)
82
- }
83
-
84
- if !bytes.Equal(payload2, buf[:l]) {
85
- t.Errorf("expected payload of %v; got %v", payload2, buf[:l])
86
- }
87
-}
88
-
89
-func TestRawReadWrite(t *testing.T) {
90
- ln, err := Listen("utp", "127.0.0.1:0")
91
- if err != nil {
92
- t.Fatal(err)
93
- }
94
- defer ln.Close()
95
-
96
- raddr, err := net.ResolveUDPAddr("udp", ln.Addr().String())
97
- if err != nil {
98
- t.Fatal(err)
99
- }
100
-
101
- c, err := net.DialUDP("udp", nil, raddr)
102
- if err != nil {
103
- t.Fatal(err)
104
- }
105
- defer c.Close()
106
-
107
- payload := []byte("Hello!")
108
- _, err = c.Write(payload)
109
- if err != nil {
110
- t.Fatal(err)
111
- }
112
-
113
- var buf [256]byte
114
- n, addr, err := ln.RawConn.ReadFrom(buf[:])
115
- if !bytes.Equal(payload, buf[:n]) {
116
- t.Errorf("expected payload of %v; got %v", payload, buf[:n])
117
- }
118
- if addr.String() != c.LocalAddr().String() {
119
- t.Errorf("expected addr of %v; got %v", c.LocalAddr(), addr.String())
120
- }
121
-}
122
-
123
-func TestLongReadWriteC2S(t *testing.T) {
124
- ln, err := Listen("utp", "127.0.0.1:0")
125
- if err != nil {
126
- t.Fatal(err)
127
- }
128
-
129
- raddr, err := ResolveUTPAddr("utp", ln.Addr().String())
130
- if err != nil {
131
- t.Fatal(err)
132
- }
133
-
134
- c, err := DialUTPTimeout("utp", nil, raddr, 1000*time.Millisecond)
135
- if err != nil {
136
- t.Fatal(err)
137
- }
138
- defer c.Close()
139
-
140
- err = ln.SetDeadline(time.Now().Add(1000 * time.Millisecond))
141
- if err != nil {
142
- t.Fatal(err)
143
- }
144
-
145
- s, err := ln.Accept()
146
- if err != nil {
147
- t.Fatal(err)
148
- }
149
- defer s.Close()
150
- ln.Close()
151
-
152
- var payload [10485760]byte
153
- for i := range payload {
154
- payload[i] = byte(rand.Int())
155
- }
156
-
157
- rch := make(chan []byte)
158
- ech := make(chan error, 2)
159
-
160
- go func() {
161
- defer c.Close()
162
- _, err := c.Write(payload[:])
163
- if err != nil {
164
- ech <- err
165
- }
166
- }()
167
-
168
- go func() {
169
- b, err := ioutil.ReadAll(s)
170
- if err != nil {
171
- ech <- err
172
- rch <- nil
173
- } else {
174
- ech <- nil
175
- rch <- b
176
- }
177
- }()
178
-
179
- err = <-ech
180
- if err != nil {
181
- t.Fatal(err)
182
- }
183
-
184
- r := <-rch
185
- if r == nil {
186
- return
187
- }
188
-
189
- if !bytes.Equal(r, payload[:]) {
190
- t.Errorf("expected payload of %d; got %d", len(payload[:]), len(r))
191
- }
192
-}
193
-
194
-func TestLongReadWriteS2C(t *testing.T) {
195
- ln, err := Listen("utp", "127.0.0.1:0")
196
- if err != nil {
197
- t.Fatal(err)
198
- }
199
-
200
- raddr, err := ResolveUTPAddr("utp", ln.Addr().String())
201
- if err != nil {
202
- t.Fatal(err)
203
- }
204
-
205
- c, err := DialUTPTimeout("utp", nil, raddr, 1000*time.Millisecond)
206
- if err != nil {
207
- t.Fatal(err)
208
- }
209
- defer c.Close()
210
-
211
- err = ln.SetDeadline(time.Now().Add(1000 * time.Millisecond))
212
- if err != nil {
213
- t.Fatal(err)
214
- }
215
-
216
- s, err := ln.Accept()
217
- if err != nil {
218
- t.Fatal(err)
219
- }
220
- defer s.Close()
221
- ln.Close()
222
-
223
- var payload [10485760]byte
224
- for i := range payload {
225
- payload[i] = byte(rand.Int())
226
- }
227
-
228
- rch := make(chan []byte)
229
- ech := make(chan error, 2)
230
-
231
- go func() {
232
- defer s.Close()
233
- _, err := s.Write(payload[:])
234
- if err != nil {
235
- ech <- err
236
- }
237
- }()
238
-
239
- go func() {
240
- b, err := ioutil.ReadAll(c)
241
- if err != nil {
242
- ech <- err
243
- rch <- nil
244
- } else {
245
- ech <- nil
246
- rch <- b
247
- }
248
- }()
249
-
250
- err = <-ech
251
- if err != nil {
252
- t.Fatal(err)
253
- }
254
-
255
- r := <-rch
256
- if r == nil {
257
- return
258
- }
259
-
260
- if !bytes.Equal(r, payload[:]) {
261
- t.Errorf("expected payload of %d; got %d", len(payload[:]), len(r))
262
- }
263
-}
264
-
265
-func TestAccept(t *testing.T) {
266
- ln, err := Listen("utp", "127.0.0.1:0")
267
- if err != nil {
268
- t.Fatal(err)
269
- }
270
- defer ln.Close()
271
-
272
- c, err := DialUTPTimeout("utp", nil, ln.Addr().(*UTPAddr), 200*time.Millisecond)
273
- if err != nil {
274
- t.Fatal(err)
275
- }
276
- defer c.Close()
277
-
278
- err = ln.SetDeadline(time.Now().Add(100 * time.Millisecond))
279
- _, err = ln.Accept()
280
- if err != nil {
281
- t.Fatal(err)
282
- }
283
-}
284
-
285
-func TestAcceptDeadline(t *testing.T) {
286
- ln, err := Listen("utp", "127.0.0.1:0")
287
- if err != nil {
288
- t.Fatal(err)
289
- }
290
- defer ln.Close()
291
- err = ln.SetDeadline(time.Now().Add(time.Millisecond))
292
- _, err = ln.Accept()
293
- if err == nil {
294
- t.Fatal("Accept should failed")
295
- }
296
-}
297
-
298
-func TestAcceptClosedListener(t *testing.T) {
299
- ln, err := Listen("utp", "127.0.0.1:0")
300
- if err != nil {
301
- t.Fatal(err)
302
- }
303
- err = ln.Close()
304
- if err != nil {
305
- t.Fatal(err)
306
- }
307
- _, err = ln.Accept()
308
- if err == nil {
309
- t.Fatal("Accept should failed")
310
- }
311
- _, err = ln.Accept()
312
- if err == nil {
313
- t.Fatal("Accept should failed")
314
- }
315
-}
316
-
317
-func TestDialer(t *testing.T) {
318
- ln, err := Listen("utp", "127.0.0.1:0")
319
- if err != nil {
320
- t.Fatal(err)
321
- }
322
- defer ln.Close()
323
-
324
- d := Dialer{}
325
- c, err := d.Dial("utp", ln.Addr().String())
326
- if err != nil {
327
- t.Fatal(err)
328
- }
329
- defer c.Close()
330
-}
331
-
332
-func TestDialerAddrs(t *testing.T) {
333
- ln, err := Listen("utp", "127.0.0.1:0")
334
- if err != nil {
335
- t.Fatal(err)
336
- }
337
- defer ln.Close()
338
-
339
- laddr, err := ResolveUTPAddr("utp", "127.0.0.1:45678")
340
- if err != nil {
341
- t.Fatal(err)
342
- }
343
-
344
- d := Dialer{LocalAddr: laddr}
345
- c1, err := d.Dial("utp", ln.Addr().String())
346
- if err != nil {
347
- t.Fatal(err)
348
- }
349
- defer c1.Close()
350
-
351
- c2, err := ln.Accept()
352
- if err != nil {
353
- t.Fatal(err)
354
- }
355
- defer c2.Close()
356
-
357
- eq := func(a, b net.Addr) bool {
358
- return a.String() == b.String()
359
- }
360
-
361
- if !eq(d.LocalAddr, c2.RemoteAddr()) {
362
- t.Fatal("dialer.LocalAddr not equal to c2.RemoteAddr ")
363
- }
364
- if !eq(c1.LocalAddr(), c2.RemoteAddr()) {
365
- t.Fatal("c1.LocalAddr not equal to c2.RemoteAddr ")
366
- }
367
- if !eq(c2.LocalAddr(), c1.RemoteAddr()) {
368
- t.Fatal("c2.LocalAddr not equal to c1.RemoteAddr ")
369
- }
370
-}
371
-
372
-func TestDialerTimeout(t *testing.T) {
373
- timeout := time.Millisecond * 200
374
- d := Dialer{Timeout: timeout}
375
- done := make(chan struct{})
376
-
377
- go func() {
378
- _, err := d.Dial("utp", "127.0.0.1:34567")
379
- if err == nil {
380
- t.Fatal("should not connect")
381
- }
382
- done <- struct{}{}
383
- }()
384
-
385
- select {
386
- case <-time.After(timeout * 2):
387
- t.Fatal("should have ended already")
388
- case <-done:
389
- }
390
-}
391
-
392
-func TestPacketBinary(t *testing.T) {
393
- h := header{
394
- typ: st_fin,
395
- ver: version,
396
- id: 100,
397
- t: 50000,
398
- diff: 10000,
399
- wnd: 65535,
400
- seq: 100,
401
- ack: 200,
402
- }
403
-
404
- e := []extension{
405
- extension{
406
- typ: ext_selective_ack,
407
- payload: []byte{0, 1, 0, 1},
408
- },
409
- extension{
410
- typ: ext_selective_ack,
411
- payload: []byte{100, 0, 200, 0},
412
- },
413
- }
414
-
415
- p := packet{
416
- header: h,
417
- ext: e,
418
- payload: []byte("abcdefg"),
419
- }
420
-
421
- b, err := p.MarshalBinary()
422
- if err != nil {
423
- t.Fatal(err)
424
- }
425
-
426
- p2 := packet{payload: make([]byte, 0, mss)}
427
- err = p2.UnmarshalBinary(b)
428
- if err != nil {
429
- t.Fatal(err)
430
- }
431
-
432
- if !reflect.DeepEqual(p, p2) {
433
- t.Errorf("expected packet of %v; got %v", p, p2)
434
- }
435
-}
436
-
437
-func TestUnmarshalShortPacket(t *testing.T) {
438
- b := make([]byte, 18)
439
- p := packet{}
440
- err := p.UnmarshalBinary(b)
441
-
442
- if err == nil {
443
- t.Fatal("UnmarshalBinary should fail")
444
- } else if err != io.EOF {
445
- t.Fatal(err)
446
- }
447
-}
448
-
449
-func TestWriteOnClosedChannel(t *testing.T) {
450
- ln, err := Listen("utp", "127.0.0.1:0")
451
- if err != nil {
452
- t.Fatal(err)
453
- }
454
- defer ln.Close()
455
-
456
- c, err := DialUTPTimeout("utp", nil, ln.Addr().(*UTPAddr), 200*time.Millisecond)
457
- if err != nil {
458
- t.Fatal(err)
459
- }
460
-
461
- go func() {
462
- for {
463
- _, err := c.Write([]byte{100})
464
- if err != nil {
465
- return
466
- }
467
- }
468
- }()
469
-
470
- c.Close()
471
-}
472
-
473
-func TestReadOnClosedChannel(t *testing.T) {
474
- ln, err := Listen("utp", "127.0.0.1:0")
475
- if err != nil {
476
- t.Fatal(err)
477
- }
478
- defer ln.Close()
479
-
480
- c, err := DialUTPTimeout("utp", nil, ln.Addr().(*UTPAddr), 200*time.Millisecond)
481
- if err != nil {
482
- t.Fatal(err)
483
- }
484
-
485
- go func() {
486
- for {
487
- var buf [16]byte
488
- _, err := c.Read(buf[:])
489
- if err != nil {
490
- return
491
- }
492
- }
493
- }()
494
-
495
- c.Close()
496
-}
497
-
498
-func TestPacketBuffer(t *testing.T) {
499
- size := 12
500
- b := newPacketBuffer(12, 1)
501
-
502
- if b.space() != size {
503
- t.Errorf("expected space == %d; got %d", size, b.space())
504
- }
505
-
506
- for i := 1; i <= size; i++ {
507
- b.push(&packet{header: header{seq: uint16(i)}})
508
- }
509
-
510
- if b.space() != 0 {
511
- t.Errorf("expected space == 0; got %d", b.space())
512
- }
513
-
514
- a := []byte{255, 7}
515
- ack := b.generateSelectiveACK()
516
- if !bytes.Equal(a, ack) {
517
- t.Errorf("expected ack == %v; got %v", a, ack)
518
- }
519
-
520
- err := b.push(&packet{header: header{seq: 15}})
521
- if err == nil {
522
- t.Fatal("push should fail")
523
- }
524
-
525
- all := b.all()
526
- if len(all) != size {
527
- t.Errorf("expected %d packets sequence; got %d", size, len(all))
528
- }
529
-
530
- f := b.fetch(6)
531
- if f == nil {
532
- t.Fatal("fetch should not fail")
533
- }
534
-
535
- b.compact()
536
-
537
- err = b.push(&packet{header: header{seq: 15}})
538
- if err != nil {
539
- t.Fatal(err)
540
- }
541
-
542
- err = b.push(&packet{header: header{seq: 17}})
543
- if err != nil {
544
- t.Fatal(err)
545
- }
546
-
547
- for i := 7; i <= size; i++ {
548
- f := b.fetch(uint16(i))
549
- if f == nil {
550
- t.Fatal("fetch should not fail")
551
- }
552
- }
553
-
554
- a = []byte{128, 2}
555
- ack = b.generateSelectiveACK()
556
- if !bytes.Equal(a, ack) {
557
- t.Errorf("expected ack == %v; got %v", a, ack)
558
- }
559
-
560
- all = b.all()
561
- if len(all) != 2 {
562
- t.Errorf("expected 2 packets sequence; got %d", len(all))
563
- }
564
-
565
- b.compact()
566
- if b.space() != 9 {
567
- t.Errorf("expected space == 9; got %d", b.space())
568
- }
569
-
570
- ack = b.generateSelectiveACK()
571
- b.processSelectiveACK(ack)
572
-
573
- all = b.all()
574
- if len(all) != 1 {
575
- t.Errorf("expected size == 1; got %d", len(all))
576
- }
577
-}
578
-
579
-func TestPacketBufferBoundary(t *testing.T) {
580
- begin := math.MaxUint16 - 3
581
- b := newPacketBuffer(12, begin)
582
- for i := begin; i != 5; i = (i + 1) % (math.MaxUint16 + 1) {
583
- err := b.push(&packet{header: header{seq: uint16(i)}})
584
- if err != nil {
585
- t.Fatal(err)
586
- }
587
- }
588
-}
589
-
590
-func TestTimedBufferNode(t *testing.T) {
591
- b := timedBuffer{d: time.Millisecond * 100}
592
- b.push(100)
593
- b.push(200)
594
- time.Sleep(time.Millisecond * 200)
595
- b.push(300)
596
- b.push(400)
597
- m := b.min()
598
- if m != 300 {
599
- t.Errorf("expected min == 300; got %d", m)
600
- }
601
-}