update go-multiaddr-net dependency
License: MIT Signed-off-by: Jeromy <jeromyj@gmail.com>
Jeromy committed
Oct 11, 2015 at 10:43 UTC
67d17c642a46ee6be8647881fc431bbc2f285940
90 files changed
+4796
-3407
Godeps/Godeps.json
+17
-5
@@ -32,10 +32,26 @@
32
"ImportPath": "github.com/alecthomas/units",
33
"Rev": "6b4e7dc5e3143b85ea77909c72caf89416fc2915"
34
},
35
+ {
36
+ "ImportPath": "github.com/anacrolix/jitter",
37
+ "Rev": "2ea5c18645100745b24e9f5cfc9b3f6f7eac51ef"
38
+ },
39
+ {
40
+ "ImportPath": "github.com/anacrolix/missinggo",
41
+ "Rev": "4e1ca5963308863b56c31863f60c394a7365ec29"
42
+ },
43
+ {
44
+ "ImportPath": "github.com/anacrolix/utp",
45
+ "Rev": "0bb24de92c268452fb9106ca4fb9302442ca0dee"
46
+ },
47
{
48
"ImportPath": "github.com/beorn7/perks/quantile",
49
"Rev": "b965b613227fddccbfffe13eae360ed3fa822f8d"
50
},
51
+ {
52
+ "ImportPath": "github.com/bradfitz/iter",
53
+ "Rev": "454541ec3da2a73fc34fd049b19ee5777bf19345"
54
+ },
55
{
56
"ImportPath": "github.com/bren2010/proquint",
57
"Rev": "5958552242606512f714d2e93513b380f43f9991"
@@ -104,10 +120,6 @@
120
"ImportPath": "github.com/golang/protobuf/proto",
121
"Rev": "aece6fb931241ad332956db4f62798dfbea944b3"
122
},
107
- {
108
- "ImportPath": "github.com/h2so5/utp",
109
- "Rev": "6ca83358f5c331028feb9b97c445e9c7354967b0"
110
- },
123
{
124
"ImportPath": "github.com/hashicorp/golang-lru",
125
"Rev": "253b2dc1ca8bae42c3b5b6e53dd2eab1a7551116"
@@ -171,7 +183,7 @@
183
},
184
{
185
"ImportPath": "github.com/jbenet/go-multiaddr-net",
174
- "Rev": "6b29a00b65526d23f534813eb5bfa64dfa281e4a"
186
+ "Rev": "4a8bd8f8baf45afcf2bb385bbc17e5208d5d4c71"
187
},
188
{
189
"ImportPath": "github.com/jbenet/go-multihash",
Godeps/_workspace/src/github.com/anacrolix/jitter/jitter.go
new
+12
@@ -0,0 +1,12 @@
1
+package jitter
2
+
3
+import (
4
+ "math/rand"
5
+ "time"
6
+)
7
+
8
+func Duration(average, plusMinus time.Duration) (ret time.Duration) {
9
+ ret = average - plusMinus
10
+ ret += time.Duration(rand.Int63n(2*int64(plusMinus) + 1))
11
+ return
12
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/addr.go
new
+72
@@ -0,0 +1,72 @@
1
+package missinggo
2
+
3
+import (
4
+ "net"
5
+ "strconv"
6
+ "strings"
7
+)
8
+
9
+type HostMaybePort struct {
10
+ Host string
11
+ Port int
12
+ NoPort bool
13
+}
14
+
15
+func (me HostMaybePort) String() string {
16
+ if me.NoPort {
17
+ return me.Host
18
+ }
19
+ return net.JoinHostPort(me.Host, strconv.FormatInt(int64(me.Port), 10))
20
+}
21
+
22
+func SplitHostPort(hostport string) (ret HostMaybePort) {
23
+ host, port, err := net.SplitHostPort(hostport)
24
+ if err != nil {
25
+ if strings.Contains(err.Error(), "missing port") {
26
+ ret.Host = hostport
27
+ ret.NoPort = true
28
+ return
29
+ }
30
+ panic(err)
31
+ }
32
+ i64, err := strconv.ParseInt(port, 0, 0)
33
+ ret.Host = host
34
+ ret.Port = int(i64)
35
+ if err != nil {
36
+ ret.NoPort = true
37
+ }
38
+ return
39
+}
40
+
41
+// Extracts the port as an integer from an address string.
42
+func AddrPort(addr net.Addr) int {
43
+ switch raw := addr.(type) {
44
+ case *net.UDPAddr:
45
+ return raw.Port
46
+ default:
47
+ _, port, err := net.SplitHostPort(addr.String())
48
+ if err != nil {
49
+ panic(err)
50
+ }
51
+ i64, err := strconv.ParseInt(port, 0, 0)
52
+ if err != nil {
53
+ panic(err)
54
+ }
55
+ return int(i64)
56
+ }
57
+}
58
+
59
+func AddrIP(addr net.Addr) net.IP {
60
+ switch raw := addr.(type) {
61
+ case *net.UDPAddr:
62
+ return raw.IP
63
+ case *net.TCPAddr:
64
+ return raw.IP
65
+ default:
66
+ host, _, err := net.SplitHostPort(addr.String())
67
+ if err != nil {
68
+ panic(err)
69
+ }
70
+ return net.ParseIP(host)
71
+ }
72
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/addr_test.go
new
+17
@@ -0,0 +1,17 @@
1
+package missinggo
2
+
3
+import (
4
+ "testing"
5
+
6
+ "github.com/stretchr/testify/assert"
7
+)
8
+
9
+func TestSplitHostPort(t *testing.T) {
10
+ assert.EqualValues(t, HostMaybePort{"a", 1, false}, SplitHostPort("a:1"))
11
+ assert.EqualValues(t, HostMaybePort{"a", 0, true}, SplitHostPort("a"))
12
+}
13
+
14
+func TestHostMaybePortString(t *testing.T) {
15
+ assert.EqualValues(t, "a:1", (HostMaybePort{"a", 1, false}).String())
16
+ assert.EqualValues(t, "a", (HostMaybePort{"a", 0, true}).String())
17
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/args/args.go
new
+15
@@ -0,0 +1,15 @@
1
+package args
2
+
3
+import (
4
+ "flag"
5
+ "fmt"
6
+ "os"
7
+)
8
+
9
+func Parse() {
10
+ flag.Parse()
11
+ if flag.NArg() != 0 {
12
+ fmt.Fprintf(os.Stderr, "unexpected positional arguments\n")
13
+ os.Exit(2)
14
+ }
15
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/atime.go
new
+11
@@ -0,0 +1,11 @@
1
+package missinggo
2
+
3
+import (
4
+ "os"
5
+ "time"
6
+)
7
+
8
+// Extracts the access time from the FileInfo internals.
9
+func FileInfoAccessTime(fi os.FileInfo) time.Time {
10
+ return fileInfoAccessTime(fi)
11
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/atime_darwin.go
new
+12
@@ -0,0 +1,12 @@
1
+package missinggo
2
+
3
+import (
4
+ "os"
5
+ "syscall"
6
+ "time"
7
+)
8
+
9
+func fileInfoAccessTime(fi os.FileInfo) time.Time {
10
+ ts := fi.Sys().(*syscall.Stat_t).Atimespec
11
+ return time.Unix(int64(ts.Sec), int64(ts.Nsec))
12
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/atime_freebsd.go
new
+12
@@ -0,0 +1,12 @@
1
+package missinggo
2
+
3
+import (
4
+ "os"
5
+ "syscall"
6
+ "time"
7
+)
8
+
9
+func fileInfoAccessTime(fi os.FileInfo) time.Time {
10
+ ts := fi.Sys().(*syscall.Stat_t).Atimespec
11
+ return time.Unix(int64(ts.Sec), int64(ts.Nsec))
12
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/atime_linux.go
new
+12
@@ -0,0 +1,12 @@
1
+package missinggo
2
+
3
+import (
4
+ "os"
5
+ "syscall"
6
+ "time"
7
+)
8
+
9
+func fileInfoAccessTime(fi os.FileInfo) time.Time {
10
+ ts := fi.Sys().(*syscall.Stat_t).Atim
11
+ return time.Unix(int64(ts.Sec), int64(ts.Nsec))
12
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/atime_windows.go
new
+12
@@ -0,0 +1,12 @@
1
+package missinggo
2
+
3
+import (
4
+ "os"
5
+ "syscall"
6
+ "time"
7
+)
8
+
9
+func fileInfoAccessTime(fi os.FileInfo) time.Time {
10
+ ts := fi.Sys().(syscall.Win32FileAttributeData).LastAccessTime
11
+ return time.Unix(0, int64(ts.Nanoseconds()))
12
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/castslice.go
new
+17
@@ -0,0 +1,17 @@
1
+package missinggo
2
+
3
+import (
4
+ "reflect"
5
+
6
+ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/bradfitz/iter"
7
+)
8
+
9
+func ConvertToSliceOfEmptyInterface(slice interface{}) (ret []interface{}) {
10
+ v := reflect.ValueOf(slice)
11
+ l := v.Len()
12
+ ret = make([]interface{}, 0, l)
13
+ for i := range iter.N(v.Len()) {
14
+ ret = append(ret, v.Index(i).Interface())
15
+ }
16
+ return
17
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/cmd/go-env/main.go
new
+12
@@ -0,0 +1,12 @@
1
+package main
2
+
3
+import (
4
+ "fmt"
5
+ "os"
6
+)
7
+
8
+func main() {
9
+ for _, v := range os.Environ() {
10
+ fmt.Printf("%s\n", v)
11
+ }
12
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/cmd/nop/main.go
new
+3
@@ -0,0 +1,3 @@
1
+package main
2
+
3
+func main() {}
Godeps/_workspace/src/github.com/anacrolix/missinggo/cmd/query-escape/main.go
new
+11
@@ -0,0 +1,11 @@
1
+package main
2
+
3
+import (
4
+ "fmt"
5
+ "net/url"
6
+ "os"
7
+)
8
+
9
+func main() {
10
+ fmt.Println(url.QueryEscape(os.Args[1]))
11
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/cmd/query-unescape/main.go
new
+11
@@ -0,0 +1,11 @@
1
+package main
2
+
3
+import (
4
+ "fmt"
5
+ "net/url"
6
+ "os"
7
+)
8
+
9
+func main() {
10
+ fmt.Println(url.QueryUnescape(os.Args[1]))
11
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/copy.go
new
+32
@@ -0,0 +1,32 @@
1
+package missinggo
2
+
3
+import (
4
+ "fmt"
5
+ "reflect"
6
+)
7
+
8
+func CopyExact(dest interface{}, src interface{}) {
9
+ dV := reflect.ValueOf(dest)
10
+ sV := reflect.ValueOf(src)
11
+ if dV.Kind() == reflect.Ptr {
12
+ dV = dV.Elem()
13
+ }
14
+ if dV.Kind() == reflect.Array && !dV.CanAddr() {
15
+ panic(fmt.Sprintf("dest not addressable: %T", dest))
16
+ }
17
+ if sV.Kind() == reflect.Ptr {
18
+ sV = sV.Elem()
19
+ }
20
+ if sV.Kind() == reflect.String {
21
+ sV = sV.Convert(reflect.SliceOf(dV.Type().Elem()))
22
+ }
23
+ if !sV.IsValid() {
24
+ panic("invalid source, probably nil")
25
+ }
26
+ if dV.Len() != sV.Len() {
27
+ panic(fmt.Sprintf("dest len (%d) != src len (%d)", dV.Len(), sV.Len()))
28
+ }
29
+ if dV.Len() != reflect.Copy(dV, sV) {
30
+ panic("dammit")
31
+ }
32
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/copy_test.go
new
+89
@@ -0,0 +1,89 @@
1
+package missinggo
2
+
3
+import (
4
+ "bytes"
5
+ "strings"
6
+ "testing"
7
+)
8
+
9
+func TestCopyToArray(t *testing.T) {
10
+ var arr [3]byte
11
+ bb := []byte{1, 2, 3}
12
+ CopyExact(&arr, bb)
13
+ if !bytes.Equal(arr[:], bb) {
14
+ t.FailNow()
15
+ }
16
+}
17
+
18
+func TestCopyToSlicedArray(t *testing.T) {
19
+ var arr [5]byte
20
+ CopyExact(arr[:], "hello")
21
+ if !bytes.Equal(arr[:], []byte("hello")) {
22
+ t.FailNow()
23
+ }
24
+}
25
+
26
+func TestCopyDestNotAddr(t *testing.T) {
27
+ defer func() {
28
+ r := recover()
29
+ if r == nil {
30
+ t.FailNow()
31
+ }
32
+ t.Log(r)
33
+ }()
34
+ var arr [3]byte
35
+ CopyExact(arr, "nope")
36
+}
37
+
38
+func TestCopyLenMismatch(t *testing.T) {
39
+ defer func() {
40
+ r := recover()
41
+ if r == nil {
42
+ t.FailNow()
43
+ }
44
+ t.Log(r)
45
+ }()
46
+ CopyExact(make([]byte, 2), "abc")
47
+}
48
+
49
+func TestCopySrcString(t *testing.T) {
50
+ dest := make([]byte, 3)
51
+ CopyExact(dest, "lol")
52
+ if string(dest) != "lol" {
53
+ t.FailNow()
54
+ }
55
+ func() {
56
+ defer func() {
57
+ r := recover()
58
+ if r == nil {
59
+ t.FailNow()
60
+ }
61
+ }()
62
+ CopyExact(dest, "rofl")
63
+ }()
64
+ var arr [5]byte
65
+ CopyExact(&arr, interface{}("hello"))
66
+ if string(arr[:]) != "hello" {
67
+ t.FailNow()
68
+ }
69
+}
70
+
71
+func TestCopySrcNilInterface(t *testing.T) {
72
+ var arr [3]byte
73
+ defer func() {
74
+ r := recover().(string)
75
+ if !strings.Contains(r, "invalid source") {
76
+ t.FailNow()
77
+ }
78
+ }()
79
+ CopyExact(&arr, nil)
80
+}
81
+
82
+func TestCopySrcPtr(t *testing.T) {
83
+ var bigDst [1024]byte
84
+ var bigSrc [1024]byte = [1024]byte{'h', 'i'}
85
+ CopyExact(&bigDst, &bigSrc)
86
+ if !bytes.Equal(bigDst[:], bigSrc[:]) {
87
+ t.FailNow()
88
+ }
89
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/croak.go
new
+18
@@ -0,0 +1,18 @@
1
+package missinggo
2
+
3
+import (
4
+ "fmt"
5
+ "os"
6
+)
7
+
8
+func Unchomp(s string) string {
9
+ if len(s) > 0 && s[len(s)-1] == '\n' {
10
+ return s
11
+ }
12
+ return s + "\n"
13
+}
14
+
15
+func Fatal(msg interface{}) {
16
+ os.Stderr.WriteString(Unchomp(fmt.Sprint(msg)))
17
+ os.Exit(1)
18
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/doc.go
new
+3
@@ -0,0 +1,3 @@
1
+// Package missinggo contains miscellaneous helpers used in many of anacrolix'
2
+// projects.
3
+package missinggo
Godeps/_workspace/src/github.com/anacrolix/missinggo/expvarIndentMap.go
new
+35
@@ -0,0 +1,35 @@
1
+package missinggo
2
+
3
+import (
4
+ "bytes"
5
+ "expvar"
6
+ "fmt"
7
+)
8
+
9
+type IndentMap struct {
10
+ expvar.Map
11
+}
12
+
13
+var _ expvar.Var = &IndentMap{}
14
+
15
+func NewExpvarIndentMap(name string) *IndentMap {
16
+ v := new(IndentMap)
17
+ v.Init()
18
+ expvar.Publish(name, v)
19
+ return v
20
+}
21
+
22
+func (v *IndentMap) String() string {
23
+ var b bytes.Buffer
24
+ fmt.Fprintf(&b, "{")
25
+ first := true
26
+ v.Do(func(kv expvar.KeyValue) {
27
+ if !first {
28
+ fmt.Fprintf(&b, ",")
29
+ }
30
+ fmt.Fprintf(&b, "\n\t%q: %v", kv.Key, kv.Value)
31
+ first = false
32
+ })
33
+ fmt.Fprintf(&b, "}")
34
+ return b.String()
35
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/filecache/cache.go
new
+269
@@ -0,0 +1,269 @@
1
+package filecache
2
+
3
+import (
4
+ "errors"
5
+ "log"
6
+ "os"
7
+ "path"
8
+ "path/filepath"
9
+ "sync"
10
+ "time"
11
+
12
+ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/anacrolix/missinggo"
13
+)
14
+
15
+type Cache struct {
16
+ mu sync.Mutex
17
+ capacity int64
18
+ filled int64
19
+ items *lruItems
20
+ paths map[string]ItemInfo
21
+ root string
22
+}
23
+
24
+type CacheInfo struct {
25
+ Capacity int64
26
+ Filled int64
27
+ NumItems int
28
+}
29
+
30
+type ItemInfo struct {
31
+ Accessed time.Time
32
+ Size int64
33
+ Path string
34
+}
35
+
36
+// Calls the function for every item known to the cache. The ItemInfo should
37
+// not be modified.
38
+func (me *Cache) WalkItems(cb func(ItemInfo)) {
39
+ me.mu.Lock()
40
+ defer me.mu.Unlock()
41
+ for e := me.items.Front(); e != nil; e = e.Next() {
42
+ cb(e.Value().(ItemInfo))
43
+ }
44
+}
45
+
46
+func (me *Cache) Info() (ret CacheInfo) {
47
+ me.mu.Lock()
48
+ defer me.mu.Unlock()
49
+ ret.Capacity = me.capacity
50
+ ret.Filled = me.filled
51
+ ret.NumItems = len(me.paths)
52
+ return
53
+}
54
+
55
+func (me *Cache) SetCapacity(capacity int64) {
56
+ me.mu.Lock()
57
+ defer me.mu.Unlock()
58
+ me.capacity = capacity
59
+}
60
+
61
+func NewCache(root string) (ret *Cache, err error) {
62
+ if !filepath.IsAbs(root) {
63
+ err = errors.New("root is not an absolute filepath")
64
+ return
65
+ }
66
+ ret = &Cache{
67
+ root: root,
68
+ capacity: -1, // unlimited
69
+ }
70
+ ret.mu.Lock()
71
+ go func() {
72
+ defer ret.mu.Unlock()
73
+ ret.rescan()
74
+ }()
75
+ return
76
+}
77
+
78
+// An empty return path is an error.
79
+func sanitizePath(p string) (ret string) {
80
+ if p == "" {
81
+ return
82
+ }
83
+ ret = path.Clean("/" + p)
84
+ if ret[0] == '/' {
85
+ ret = ret[1:]
86
+ }
87
+ return
88
+}
89
+
90
+// Leaf is a descendent of root.
91
+func pruneEmptyDirs(root string, leaf string) (err error) {
92
+ rootInfo, err := os.Stat(root)
93
+ if err != nil {
94
+ return
95
+ }
96
+ for {
97
+ var leafInfo os.FileInfo
98
+ leafInfo, err = os.Stat(leaf)
99
+ if os.IsNotExist(err) {
100
+ goto parent
101
+ }
102
+ if err != nil {
103
+ return
104
+ }
105
+ if !leafInfo.IsDir() {
106
+ return
107
+ }
108
+ if os.SameFile(rootInfo, leafInfo) {
109
+ return
110
+ }
111
+ if os.Remove(leaf) != nil {
112
+ return
113
+ }
114
+ parent:
115
+ leaf = filepath.Dir(leaf)
116
+ }
117
+}
118
+
119
+func (me *Cache) Remove(path string) (err error) {
120
+ path = sanitizePath(path)
121
+ me.mu.Lock()
122
+ defer me.mu.Unlock()
123
+ err = me.remove(path)
124
+ return
125
+}
126
+
127
+var (
128
+ ErrBadPath = errors.New("bad path")
129
+ ErrIsDir = errors.New("is directory")
130
+)
131
+
132
+func (me *Cache) OpenFile(path string, flag int) (ret *File, err error) {
133
+ path = sanitizePath(path)
134
+ if path == "" {
135
+ err = ErrIsDir
136
+ return
137
+ }
138
+ f, err := os.OpenFile(me.realpath(path), flag, 0644)
139
+ if flag&os.O_CREATE != 0 && os.IsNotExist(err) {
140
+ os.MkdirAll(me.root, 0755)
141
+ os.MkdirAll(filepath.Dir(me.realpath(path)), 0755)
142
+ f, err = os.OpenFile(me.realpath(path), flag, 0644)
143
+ if err != nil {
144
+ me.pruneEmptyDirs(path)
145
+ }
146
+ }
147
+ if err != nil {
148
+ return
149
+ }
150
+ ret = &File{
151
+ c: me,
152
+ path: path,
153
+ f: f,
154
+ }
155
+ me.mu.Lock()
156
+ go func() {
157
+ defer me.mu.Unlock()
158
+ me.statItem(path, time.Now())
159
+ }()
160
+ return
161
+}
162
+
163
+func (me *Cache) rescan() {
164
+ me.filled = 0
165
+ me.items = newLRUItems()
166
+ me.paths = make(map[string]ItemInfo)
167
+ err := filepath.Walk(me.root, func(path string, info os.FileInfo, err error) error {
168
+ if os.IsNotExist(err) {
169
+ return nil
170
+ }
171
+ if err != nil {
172
+ return err
173
+ }
174
+ if info.IsDir() {
175
+ return nil
176
+ }
177
+ path, err = filepath.Rel(me.root, path)
178
+ if err != nil {
179
+ log.Print(err)
180
+ return nil
181
+ }
182
+ me.statItem(path, time.Time{})
183
+ return nil
184
+ })
185
+ if err != nil {
186
+ panic(err)
187
+ }
188
+}
189
+
190
+func (me *Cache) insertItem(i ItemInfo) {
191
+ me.items.Insert(i)
192
+}
193
+
194
+func (me *Cache) removeInfo(path string) (ret ItemInfo, ok bool) {
195
+ ret, ok = me.paths[path]
196
+ if !ok {
197
+ return
198
+ }
199
+ if !me.items.Remove(ret) {
200
+ panic(ret)
201
+ }
202
+ me.filled -= ret.Size
203
+ delete(me.paths, path)
204
+ return
205
+}
206
+
207
+// Triggers the item for path to be updated. If access is non-zero, set the
208
+// item's access time to that value, otherwise deduce it appropriately.
209
+func (me *Cache) statItem(path string, access time.Time) {
210
+ info, ok := me.removeInfo(path)
211
+ fi, err := os.Stat(me.realpath(path))
212
+ if os.IsNotExist(err) {
213
+ return
214
+ }
215
+ if err != nil {
216
+ panic(err)
217
+ }
218
+ if !ok {
219
+ info.Path = path
220
+ }
221
+ if !access.IsZero() {
222
+ info.Accessed = access
223
+ }
224
+ if info.Accessed.IsZero() {
225
+ info.Accessed = missinggo.FileInfoAccessTime(fi)
226
+ }
227
+ info.Size = fi.Size()
228
+ me.filled += info.Size
229
+ me.insertItem(info)
230
+ me.paths[path] = info
231
+}
232
+
233
+func (me *Cache) realpath(path string) string {
234
+ return filepath.Join(me.root, filepath.FromSlash(path))
235
+}
236
+
237
+func (me *Cache) TrimToCapacity() {
238
+ me.mu.Lock()
239
+ defer me.mu.Unlock()
240
+ me.trimToCapacity()
241
+}
242
+
243
+func (me *Cache) pruneEmptyDirs(path string) {
244
+ pruneEmptyDirs(me.root, me.realpath(path))
245
+}
246
+
247
+func (me *Cache) remove(path string) (err error) {
248
+ err = os.Remove(me.realpath(path))
249
+ if os.IsNotExist(err) {
250
+ err = nil
251
+ }
252
+ me.pruneEmptyDirs(path)
253
+ me.removeInfo(path)
254
+ return
255
+}
256
+
257
+func (me *Cache) trimToCapacity() {
258
+ if me.capacity < 0 {
259
+ return
260
+ }
261
+ for me.filled > me.capacity {
262
+ item := me.items.LRU()
263
+ me.remove(item.Path)
264
+ }
265
+}
266
+
267
+func (me *Cache) pathInfo(p string) ItemInfo {
268
+ return me.paths[p]
269
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/filecache/cache_test.go
new
+84
@@ -0,0 +1,84 @@
1
+package filecache
2
+
3
+import (
4
+ "io"
5
+ "io/ioutil"
6
+ "os"
7
+ "path/filepath"
8
+ "testing"
9
+
10
+ "github.com/stretchr/testify/assert"
11
+ "github.com/stretchr/testify/require"
12
+
13
+ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/anacrolix/missinggo"
14
+)
15
+
16
+func TestCache(t *testing.T) {
17
+ td, err := ioutil.TempDir("", "gotest")
18
+ if err != nil {
19
+ t.Fatal(err)
20
+ }
21
+ defer os.RemoveAll(td)
22
+ c, err := NewCache(filepath.Join(td, "cache"))
23
+ if err != nil {
24
+ t.Fatal(err)
25
+ }
26
+ assert.EqualValues(t, 0, c.Info().Filled)
27
+ c.WalkItems(func(i ItemInfo) {})
28
+ _, err = c.OpenFile("/", os.O_CREATE)
29
+ assert.NotNil(t, err)
30
+ _, err = c.OpenFile("", os.O_CREATE)
31
+ assert.NotNil(t, err)
32
+ c.WalkItems(func(i ItemInfo) {})
33
+ require.Equal(t, 0, c.Info().NumItems)
34
+ _, err = c.OpenFile("notexist", 0)
35
+ assert.True(t, os.IsNotExist(err), err)
36
+ _, err = c.OpenFile("/notexist", 0)
37
+ assert.True(t, os.IsNotExist(err), err)
38
+ _, err = c.OpenFile("/dir/notexist", 0)
39
+ assert.True(t, os.IsNotExist(err), err)
40
+ f, err := c.OpenFile("dir/blah", os.O_CREATE)
41
+ require.NoError(t, err)
42
+ defer f.Close()
43
+ c.WalkItems(func(i ItemInfo) {})
44
+ assert.True(t, missinggo.FilePathExists(filepath.Join(td, filepath.FromSlash("cache/dir/blah"))))
45
+ assert.True(t, missinggo.FilePathExists(filepath.Join(td, filepath.FromSlash("cache/dir/"))))
46
+ assert.Equal(t, 1, c.Info().NumItems)
47
+ f.Remove()
48
+ assert.False(t, missinggo.FilePathExists(filepath.Join(td, filepath.FromSlash("dir/blah"))))
49
+ assert.False(t, missinggo.FilePathExists(filepath.Join(td, filepath.FromSlash("dir/"))))
50
+ _, err = f.Read(nil)
51
+ assert.NotEqual(t, io.EOF, err)
52
+ a, err := c.OpenFile("/a", os.O_CREATE|os.O_WRONLY)
53
+ defer a.Close()
54
+ require.Nil(t, err)
55
+ b, err := c.OpenFile("b", os.O_CREATE|os.O_WRONLY)
56
+ defer b.Close()
57
+ require.Nil(t, err)
58
+ c.mu.Lock()
59
+ assert.True(t, c.pathInfo("a").Accessed.Before(c.pathInfo("b").Accessed))
60
+ c.mu.Unlock()
61
+ n, err := a.Write([]byte("hello"))
62
+ assert.Nil(t, err)
63
+ assert.EqualValues(t, 5, n)
64
+ assert.EqualValues(t, 5, c.Info().Filled)
65
+ assert.True(t, c.pathInfo("b").Accessed.Before(c.pathInfo("a").Accessed))
66
+ c.SetCapacity(5)
67
+ n, err = a.Write([]byte(" world"))
68
+ assert.NotNil(t, err)
69
+ _, err = b.Write([]byte("boom!"))
70
+ // "a" and "b" have been evicted.
71
+ assert.NotNil(t, err)
72
+ assert.EqualValues(t, 0, c.Info().Filled)
73
+ assert.EqualValues(t, 0, c.Info().NumItems)
74
+ _, err = a.Seek(0, os.SEEK_SET)
75
+ assert.NotNil(t, err)
76
+}
77
+
78
+func TestSanitizePath(t *testing.T) {
79
+ assert.Equal(t, "", sanitizePath("////"))
80
+ assert.Equal(t, "", sanitizePath("/../.."))
81
+ assert.Equal(t, "a", sanitizePath("/a//b/.."))
82
+ assert.Equal(t, "a", sanitizePath("../a"))
83
+ assert.Equal(t, "a", sanitizePath("./a"))
84
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/filecache/file.go
new
+117
@@ -0,0 +1,117 @@
1
+package filecache
2
+
3
+import (
4
+ "errors"
5
+ "math"
6
+ "os"
7
+ "sync"
8
+ "time"
9
+)
10
+
11
+type File struct {
12
+ mu sync.Mutex
13
+ c *Cache
14
+ path string
15
+ f *os.File
16
+ gone bool
17
+}
18
+
19
+func (me *File) Remove() (err error) {
20
+ return me.c.Remove(me.path)
21
+}
22
+
23
+func (me *File) Seek(offset int64, whence int) (ret int64, err error) {
24
+ ret, err = me.f.Seek(offset, whence)
25
+ return
26
+}
27
+
28
+func (me *File) maxWrite() (max int64, err error) {
29
+ if me.c.capacity < 0 {
30
+ max = math.MaxInt64
31
+ return
32
+ }
33
+ pos, err := me.Seek(0, os.SEEK_CUR)
34
+ if err != nil {
35
+ return
36
+ }
37
+ max = me.c.capacity - pos
38
+ if max < 0 {
39
+ max = 0
40
+ }
41
+ return
42
+}
43
+
44
+var (
45
+ ErrFileTooLarge = errors.New("file too large for cache")
46
+ ErrFileDisappeared = errors.New("file disappeared")
47
+)
48
+
49
+func (me *File) checkGone() {
50
+ if me.gone {
51
+ return
52
+ }
53
+ ffi, _ := me.Stat()
54
+ fsfi, _ := os.Stat(me.c.realpath(me.path))
55
+ me.gone = !os.SameFile(ffi, fsfi)
56
+}
57
+
58
+func (me *File) goneErr() error {
59
+ me.mu.Lock()
60
+ defer me.mu.Unlock()
61
+ me.checkGone()
62
+ if me.gone {
63
+ me.f.Close()
64
+ return ErrFileDisappeared
65
+ }
66
+ return nil
67
+}
68
+
69
+func (me *File) Write(b []byte) (n int, err error) {
70
+ err = me.goneErr()
71
+ if err != nil {
72
+ return
73
+ }
74
+ n, err = me.f.Write(b)
75
+ me.c.mu.Lock()
76
+ me.c.statItem(me.path, time.Now())
77
+ me.c.trimToCapacity()
78
+ me.c.mu.Unlock()
79
+ if err == nil {
80
+ err = me.goneErr()
81
+ }
82
+ return
83
+}
84
+
85
+func (me *File) Close() error {
86
+ return me.f.Close()
87
+}
88
+
89
+func (me *File) Stat() (os.FileInfo, error) {
90
+ return me.f.Stat()
91
+}
92
+
93
+func (me *File) Read(b []byte) (n int, err error) {
94
+ err = me.goneErr()
95
+ if err != nil {
96
+ return
97
+ }
98
+ defer func() {
99
+ me.c.mu.Lock()
100
+ defer me.c.mu.Unlock()
101
+ me.c.statItem(me.path, time.Now())
102
+ }()
103
+ return me.f.Read(b)
104
+}
105
+
106
+func (me *File) ReadAt(b []byte, off int64) (n int, err error) {
107
+ err = me.goneErr()
108
+ if err != nil {
109
+ return
110
+ }
111
+ defer func() {
112
+ me.c.mu.Lock()
113
+ defer me.c.mu.Unlock()
114
+ me.c.statItem(me.path, time.Now())
115
+ }()
116
+ return me.f.ReadAt(b, off)
117
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/filecache/lruitems.go
new
+94
@@ -0,0 +1,94 @@
1
+package filecache
2
+
3
+import (
4
+ "container/list"
5
+ "io"
6
+
7
+ "github.com/cznic/b"
8
+)
9
+
10
+type Iterator interface {
11
+ Next() Iterator
12
+ Value() interface{}
13
+}
14
+
15
+type listElementIterator struct {
16
+ le *list.Element
17
+}
18
+
19
+func (me listElementIterator) Next() Iterator {
20
+ e := me.le.Next()
21
+ if e == nil {
22
+ return nil
23
+ }
24
+ return listElementIterator{e}
25
+}
26
+
27
+func (me listElementIterator) Value() interface{} {
28
+ return me.le.Value
29
+}
30
+
31
+func newLRUItems() *lruItems {
32
+ return &lruItems{b.TreeNew(func(_a, _b interface{}) int {
33
+ a := _a.(ItemInfo)
34
+ b := _b.(ItemInfo)
35
+ if a.Accessed != b.Accessed {
36
+ if a.Accessed.Before(b.Accessed) {
37
+ return -1
38
+ } else {
39
+ return 1
40
+ }
41
+ }
42
+ if a.Path == b.Path {
43
+ return 0
44
+ }
45
+ if a.Path < b.Path {
46
+ return -1
47
+ }
48
+ return 1
49
+ })}
50
+}
51
+
52
+type lruItems struct {
53
+ tree *b.Tree
54
+}
55
+
56
+type bEnumeratorIterator struct {
57
+ e *b.Enumerator
58
+ v ItemInfo
59
+}
60
+
61
+func (me bEnumeratorIterator) Next() Iterator {
62
+ _, v, err := me.e.Next()
63
+ if err == io.EOF {
64
+ return nil
65
+ }
66
+ return bEnumeratorIterator{me.e, v.(ItemInfo)}
67
+}
68
+
69
+func (me bEnumeratorIterator) Value() interface{} {
70
+ return me.v
71
+}
72
+
73
+func (me *lruItems) Front() Iterator {
74
+ e, _ := me.tree.SeekFirst()
75
+ if e == nil {
76
+ return nil
77
+ }
78
+ return bEnumeratorIterator{
79
+ e: e,
80
+ }.Next()
81
+}
82
+
83
+func (me *lruItems) LRU() ItemInfo {
84
+ _, v := me.tree.First()
85
+ return v.(ItemInfo)
86
+}
87
+
88
+func (me *lruItems) Insert(ii ItemInfo) {
89
+ me.tree.Set(ii, ii)
90
+}
91
+
92
+func (me *lruItems) Remove(ii ItemInfo) bool {
93
+ return me.tree.Delete(ii)
94
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/filecache/lruitems_test.go
new
+22
@@ -0,0 +1,22 @@
1
+package filecache
2
+
3
+import (
4
+ "math/rand"
5
+ "testing"
6
+ "time"
7
+
8
+ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/bradfitz/iter"
9
+)
10
+
11
+func BenchmarkInsert(b *testing.B) {
12
+ for range iter.N(b.N) {
13
+ li := newLRUItems()
14
+ for range iter.N(10000) {
15
+ r := rand.Int63()
16
+ t := time.Unix(r/1e9, r%1e9)
17
+ li.Insert(ItemInfo{
18
+ Accessed: t,
19
+ })
20
+ }
21
+ }
22
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/httpcontentrange.go
new
+38
@@ -0,0 +1,38 @@
1
+package missinggo
2
+
3
+import (
4
+ "regexp"
5
+ "strconv"
6
+)
7
+
8
+type HTTPBytesContentRange struct {
9
+ First, Last, Length int64
10
+}
11
+
12
+var bytesContentRangeRegexp = regexp.MustCompile(`bytes[ =](\d+)-(\d+)/(\d+|\*)`)
13
+
14
+func ParseHTTPBytesContentRange(s string) (ret HTTPBytesContentRange, ok bool) {
15
+ ss := bytesContentRangeRegexp.FindStringSubmatch(s)
16
+ if ss == nil {
17
+ return
18
+ }
19
+ var err error
20
+ ret.First, err = strconv.ParseInt(ss[1], 10, 64)
21
+ if err != nil {
22
+ return
23
+ }
24
+ ret.Last, err = strconv.ParseInt(ss[2], 10, 64)
25
+ if err != nil {
26
+ return
27
+ }
28
+ if ss[3] == "*" {
29
+ ret.Length = -1
30
+ } else {
31
+ ret.Length, err = strconv.ParseInt(ss[3], 10, 64)
32
+ if err != nil {
33
+ return
34
+ }
35
+ }
36
+ ok = true
37
+ return
38
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/httpcontentrange_test.go
new
+27
@@ -0,0 +1,27 @@
1
+package missinggo
2
+
3
+import (
4
+ "testing"
5
+
6
+ "github.com/stretchr/testify/assert"
7
+)
8
+
9
+func TestParseHTTPContentRange(t *testing.T) {
10
+ for _, _case := range []struct {
11
+ h string
12
+ cr *HTTPBytesContentRange
13
+ }{
14
+ {"", nil},
15
+ {"1-2/*", nil},
16
+ {"bytes=1-2/3", &HTTPBytesContentRange{1, 2, 3}},
17
+ {"bytes=12-34/*", &HTTPBytesContentRange{12, 34, -1}},
18
+ {" bytes=12-34/*", &HTTPBytesContentRange{12, 34, -1}},
19
+ {" bytes 12-34/56", &HTTPBytesContentRange{12, 34, 56}},
20
+ } {
21
+ ret, ok := ParseHTTPBytesContentRange(_case.h)
22
+ assert.Equal(t, _case.cr != nil, ok)
23
+ if _case.cr != nil {
24
+ assert.Equal(t, *_case.cr, ret)
25
+ }
26
+ }
27
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/httpfile/httpfile.go
new
+222
@@ -0,0 +1,222 @@
1
+package httpfile
2
+
3
+import (
4
+ "bytes"
5
+ "errors"
6
+ "fmt"
7
+ "io"
8
+ "net/http"
9
+ "os"
10
+ "strconv"
11
+
12
+ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/anacrolix/missinggo"
13
+)
14
+
15
+type File struct {
16
+ off int64
17
+ r io.ReadCloser
18
+ rOff int64
19
+ length int64
20
+ url string
21
+}
22
+
23
+func OpenSectionReader(url string, off, n int64) (ret io.ReadCloser, err error) {
24
+ req, err := http.NewRequest("GET", url, nil)
25
+ if err != nil {
26
+ return
27
+ }
28
+ req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", off, off+n-1))
29
+ resp, err := http.DefaultClient.Do(req)
30
+ if err != nil {
31
+ return
32
+ }
33
+ if resp.StatusCode == http.StatusNotFound {
34
+ err = ErrNotFound
35
+ resp.Body.Close()
36
+ return
37
+ }
38
+ if resp.StatusCode != http.StatusPartialContent {
39
+ err = fmt.Errorf("bad response status: %s", resp.Status)
40
+ resp.Body.Close()
41
+ return
42
+ }
43
+ ret = resp.Body
44
+ return
45
+}
46
+
47
+func Open(url string) *File {
48
+ return &File{
49
+ url: url,
50
+ }
51
+}
52
+
53
+func (me *File) prepareReader() (err error) {
54
+ if me.r != nil && me.off != me.rOff {
55
+ me.r.Close()
56
+ me.r = nil
57
+ }
58
+ if me.r != nil {
59
+ return nil
60
+ }
61
+ req, err := http.NewRequest("GET", me.url, nil)
62
+ if err != nil {
63
+ return
64
+ }
65
+ if me.off != 0 {
66
+ req.Header.Set("Range", fmt.Sprintf("bytes=%d-", me.off))
67
+ }
68
+ resp, err := http.DefaultClient.Do(req)
69
+ if err != nil {
70
+ return
71
+ }
72
+ switch resp.StatusCode {
73
+ case http.StatusPartialContent:
74
+ cr, ok := missinggo.ParseHTTPBytesContentRange(resp.Header.Get("Content-Range"))
75
+ if !ok || cr.First != me.off {
76
+ err = errors.New("bad response")
77
+ resp.Body.Close()
78
+ return
79
+ }
80
+ me.length = cr.Length
81
+ case http.StatusOK:
82
+ if me.off != 0 {
83
+ err = errors.New("bad response")
84
+ resp.Body.Close()
85
+ return
86
+ }
87
+ if h := resp.Header.Get("Content-Length"); h != "" {
88
+ var cl uint64
89
+ cl, err = strconv.ParseUint(h, 10, 64)
90
+ if err != nil {
91
+ resp.Body.Close()
92
+ return
93
+ }
94
+ me.length = int64(cl)
95
+ }
96
+ default:
97
+ err = errors.New(resp.Status)
98
+ resp.Body.Close()
99
+ return
100
+ }
101
+ me.r = resp.Body
102
+ me.rOff = me.off
103
+ return
104
+}
105
+
106
+func (me *File) Read(b []byte) (n int, err error) {
107
+ err = me.prepareReader()
108
+ if err != nil {
109
+ return
110
+ }
111
+ n, err = me.r.Read(b)
112
+ me.off += int64(n)
113
+ me.rOff += int64(n)
114
+ return
115
+}
116
+
117
+func instanceLength(r *http.Response) (int64, error) {
118
+ switch r.StatusCode {
119
+ case http.StatusOK:
120
+ if h := r.Header.Get("Content-Length"); h != "" {
121
+ return strconv.ParseInt(h, 10, 64)
122
+ } else {
123
+ return -1, nil
124
+ }
125
+ case http.StatusPartialContent:
126
+ cr, ok := missinggo.ParseHTTPBytesContentRange(r.Header.Get("Content-Range"))
127
+ if !ok {
128
+ return -1, errors.New("bad 206 response")
129
+ }
130
+ return cr.Length, nil
131
+ default:
132
+ return -1, errors.New(r.Status)
133
+ }
134
+}
135
+
136
+func (me *File) Seek(offset int64, whence int) (ret int64, err error) {
137
+ switch whence {
138
+ case os.SEEK_SET:
139
+ ret = offset
140
+ case os.SEEK_CUR:
141
+ ret = me.off + offset
142
+ case os.SEEK_END:
143
+ if me.length < 0 {
144
+ err = errors.New("length unknown")
145
+ return
146
+ }
147
+ ret = me.length + offset
148
+ default:
149
+ err = fmt.Errorf("unhandled whence: %d", whence)
150
+ return
151
+ }
152
+ me.off = ret
153
+ return
154
+}
155
+
156
+func (me *File) Write(b []byte) (n int, err error) {
157
+ req, err := http.NewRequest("PATCH", me.url, bytes.NewReader(b))
158
+ if err != nil {
159
+ return
160
+ }
161
+ req.Header.Set("Content-Range", fmt.Sprintf("bytes=%d-", me.off))
162
+ req.ContentLength = int64(len(b))
163
+ resp, err := http.DefaultClient.Do(req)
164
+ if err != nil {
165
+ return
166
+ }
167
+ resp.Body.Close()
168
+ if resp.StatusCode != http.StatusPartialContent {
169
+ err = errors.New(resp.Status)
170
+ return
171
+ }
172
+ n = len(b)
173
+ me.off += int64(n)
174
+ return
175
+}
176
+
177
+var (
178
+ ErrNotFound = errors.New("not found")
179
+)
180
+
181
+// Returns the length of the resource in bytes.
182
+func GetLength(url string) (ret int64, err error) {
183
+ resp, err := http.Head(url)
184
+ if err != nil {
185
+ return
186
+ }
187
+ resp.Body.Close()
188
+ if resp.StatusCode == http.StatusNotFound {
189
+ err = ErrNotFound
190
+ return
191
+ }
192
+ return instanceLength(resp)
193
+}
194
+
195
+func (me *File) Close() error {
196
+ me.url = ""
197
+ if me.r != nil {
198
+ me.r.Close()
199
+ me.r = nil
200
+ }
201
+ return nil
202
+}
203
+
204
+func Delete(urlStr string) (err error) {
205
+ req, err := http.NewRequest("DELETE", urlStr, nil)
206
+ if err != nil {
207
+ return
208
+ }
209
+ resp, err := http.DefaultClient.Do(req)
210
+ if err != nil {
211
+ return
212
+ }
213
+ resp.Body.Close()
214
+ if resp.StatusCode == http.StatusNotFound {
215
+ err = ErrNotFound
216
+ return
217
+ }
218
+ if resp.StatusCode != 200 {
219
+ err = fmt.Errorf("response: %s", resp.Status)
220
+ }
221
+ return
222
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/httpgzip.go
new
+47
@@ -0,0 +1,47 @@
1
+package missinggo
2
+
3
+import (
4
+ "compress/gzip"
5
+ "io"
6
+ "net/http"
7
+ "strings"
8
+)
9
+
10
+type gzipResponseWriter struct {
11
+ io.Writer
12
+ http.ResponseWriter
13
+ haveWritten bool
14
+}
15
+
16
+func (w *gzipResponseWriter) Write(b []byte) (int, error) {
17
+ if w.haveWritten {
18
+ goto write
19
+ }
20
+ w.haveWritten = true
21
+ if w.Header().Get("Content-Type") != "" {
22
+ goto write
23
+ }
24
+ if type_ := http.DetectContentType(b); type_ != "application/octet-stream" {
25
+ w.Header().Set("Content-Type", type_)
26
+ }
27
+write:
28
+ return w.Writer.Write(b)
29
+}
30
+
31
+// Gzips response body if the request says it'll allow it.
32
+func GzipHTTPHandler(h http.Handler) http.Handler {
33
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
34
+ if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") || w.Header().Get("Content-Encoding") != "" || w.Header().Get("Vary") != "" {
35
+ h.ServeHTTP(w, r)
36
+ return
37
+ }
38
+ w.Header().Set("Content-Encoding", "gzip")
39
+ w.Header().Set("Vary", "Accept-Encoding")
40
+ gz := gzip.NewWriter(w)
41
+ defer gz.Close()
42
+ h.ServeHTTP(&gzipResponseWriter{
43
+ Writer: gz,
44
+ ResponseWriter: w,
45
+ }, r)
46
+ })
47
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/httpresponsestatus.go
new
+60
@@ -0,0 +1,60 @@
1
+package missinggo
2
+
3
+import (
4
+ "bufio"
5
+ "io"
6
+ "net"
7
+ "net/http"
8
+)
9
+
10
+// A http.ResponseWriter that tracks the status of the response. The status
11
+// code, and number of bytes written for example.
12
+type StatusResponseWriter struct {
13
+ RW http.ResponseWriter
14
+ Code int
15
+ BytesWritten int64
16
+}
17
+
18
+var _ http.ResponseWriter = &StatusResponseWriter{}
19
+
20
+func (me *StatusResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
21
+ return me.RW.(http.Hijacker).Hijack()
22
+}
23
+
24
+func (me *StatusResponseWriter) CloseNotify() <-chan bool {
25
+ return me.RW.(http.CloseNotifier).CloseNotify()
26
+}
27
+
28
+func (me *StatusResponseWriter) Flush() {
29
+ me.RW.(http.Flusher).Flush()
30
+}
31
+
32
+func (me *StatusResponseWriter) Header() http.Header {
33
+ return me.RW.Header()
34
+}
35
+
36
+func (me *StatusResponseWriter) Write(b []byte) (n int, err error) {
37
+ if me.Code == 0 {
38
+ me.Code = 200
39
+ }
40
+ n, err = me.RW.Write(b)
41
+ me.BytesWritten += int64(n)
42
+ return
43
+}
44
+
45
+func (me *StatusResponseWriter) WriteHeader(code int) {
46
+ me.RW.WriteHeader(code)
47
+ me.Code = code
48
+}
49
+
50
+type ReaderFromStatusResponseWriter struct {
51
+ StatusResponseWriter
52
+ io.ReaderFrom
53
+}
54
+
55
+func NewReaderFromStatusResponseWriter(w http.ResponseWriter) *ReaderFromStatusResponseWriter {
56
+ return &ReaderFromStatusResponseWriter{
57
+ StatusResponseWriter{RW: w},
58
+ w.(io.ReaderFrom),
59
+ }
60
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/itertools/groupby.go
new
+81
@@ -0,0 +1,81 @@
1
+package itertools
2
+
3
+type groupBy struct {
4
+ curKey interface{}
5
+ curKeyOk bool
6
+ curValue interface{}
7
+ keyFunc func(interface{}) interface{}
8
+ input Iterator
9
+ groupKey interface{}
10
+ groupKeyOk bool
11
+}
12
+
13
+type Group interface {
14
+ Iterator
15
+ Key() interface{}
16
+}
17
+
18
+type group struct {
19
+ gb *groupBy
20
+ key interface{}
21
+ first bool
22
+}
23
+
24
+func (me *group) Next() (ok bool) {
25
+ if me.first {
26
+ me.first = false
27
+ return true
28
+ }
29
+ me.gb.advance()
30
+ if !me.gb.curKeyOk || me.gb.curKey != me.key {
31
+ return
32
+ }
33
+ ok = true
34
+ return
35
+}
36
+
37
+func (me group) Value() (ret interface{}) {
38
+ ret = me.gb.curValue
39
+ return
40
+}
41
+
42
+func (me group) Key() interface{} {
43
+ return me.key
44
+}
45
+
46
+func (me *groupBy) advance() {
47
+ me.curKeyOk = me.input.Next()
48
+ if me.curKeyOk {
49
+ me.curValue = me.input.Value()
50
+ me.curKey = me.keyFunc(me.curValue)
51
+ }
52
+}
53
+
54
+func (me *groupBy) Next() (ok bool) {
55
+ for me.curKey == me.groupKey {
56
+ ok = me.input.Next()
57
+ if !ok {
58
+ return
59
+ }
60
+ me.curValue = me.input.Value()
61
+ me.curKey = me.keyFunc(me.curValue)
62
+ me.curKeyOk = true
63
+ }
64
+ me.groupKey = me.curKey
65
+ me.groupKeyOk = true
66
+ return true
67
+}
68
+
69
+func (me *groupBy) Value() (ret interface{}) {
70
+ return &group{me, me.groupKey, true}
71
+}
72
+
73
+func GroupBy(input Iterator, keyFunc func(interface{}) interface{}) Iterator {
74
+ if keyFunc == nil {
75
+ keyFunc = func(a interface{}) interface{} { return a }
76
+ }
77
+ return &groupBy{
78
+ input: input,
79
+ keyFunc: keyFunc,
80
+ }
81
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/itertools/groupby_test.go
new
+31
@@ -0,0 +1,31 @@
1
+package itertools
2
+
3
+import (
4
+ "testing"
5
+
6
+ "github.com/stretchr/testify/require"
7
+)
8
+
9
+func TestGroupByKey(t *testing.T) {
10
+ var ks []byte
11
+ gb := GroupBy(StringIterator("AAAABBBCCDAABBB"), nil)
12
+ for gb.Next() {
13
+ ks = append(ks, gb.Value().(Group).Key().(byte))
14
+ }
15
+ t.Log(ks)
16
+ require.EqualValues(t, "ABCDAB", ks)
17
+}
18
+
19
+func TestGroupByList(t *testing.T) {
20
+ var gs []string
21
+ gb := GroupBy(StringIterator("AAAABBBCCD"), nil)
22
+ for gb.Next() {
23
+ i := gb.Value().(Iterator)
24
+ var g string
25
+ for i.Next() {
26
+ g += string(i.Value().(byte))
27
+ }
28
+ gs = append(gs, g)
29
+ }
30
+ t.Log(gs)
31
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/itertools/iterator.go
new
+41
@@ -0,0 +1,41 @@
1
+package itertools
2
+
3
+import "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/anacrolix/missinggo"
4
+
5
+type Iterator interface {
6
+ Next() bool
7
+ Value() interface{}
8
+}
9
+
10
+type sliceIterator struct {
11
+ slice []interface{}
12
+ value interface{}
13
+ ok bool
14
+}
15
+
16
+func (me *sliceIterator) Next() bool {
17
+ if len(me.slice) == 0 {
18
+ return false
19
+ }
20
+ me.value = me.slice[0]
21
+ me.slice = me.slice[1:]
22
+ me.ok = true
23
+ return true
24
+}
25
+
26
+func (me *sliceIterator) Value() interface{} {
27
+ if !me.ok {
28
+ panic("no value; call Next")
29
+ }
30
+ return me.value
31
+}
32
+
33
+func SliceIterator(a []interface{}) Iterator {
34
+ return &sliceIterator{
35
+ slice: a,
36
+ }
37
+}
38
+
39
+func StringIterator(a string) Iterator {
40
+ return SliceIterator(missinggo.ConvertToSliceOfEmptyInterface(a))
41
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/itertools/iterator_test.go
new
+17
@@ -0,0 +1,17 @@
1
+package itertools
2
+
3
+import (
4
+ "testing"
5
+
6
+ "github.com/stretchr/testify/require"
7
+)
8
+
9
+func TestIterator(t *testing.T) {
10
+ const s = "AAAABBBCCDAABBB"
11
+ si := StringIterator(s)
12
+ for i := range s {
13
+ require.True(t, si.Next())
14
+ require.Equal(t, s[i], si.Value().(byte))
15
+ }
16
+ require.False(t, si.Next())
17
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/net.go
new
+26
@@ -0,0 +1,26 @@
1
+package missinggo
2
+
3
+import (
4
+ "net"
5
+)
6
+
7
+type HostPort struct {
8
+ Host string // Just the host, with no port.
9
+ Port string // May be empty if no port was given.
10
+ Err error // The error returned from net.SplitHostPort.
11
+}
12
+
13
+// Parse a "hostport" string, a concept that floats around the stdlib a lot
14
+// and is painful to work with. If no port is present, what's usually present
15
+// is just the host.
16
+func ParseHostPort(hostPort string) (ret HostPort) {
17
+ ret.Host, ret.Port, ret.Err = net.SplitHostPort(hostPort)
18
+ if ret.Err != nil {
19
+ ret.Host = hostPort
20
+ }
21
+ return
22
+}
23
+
24
+func (me *HostPort) Join() string {
25
+ return net.JoinHostPort(me.Host, me.Port)
26
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/path.go
new
+20
@@ -0,0 +1,20 @@
1
+package missinggo
2
+
3
+import (
4
+ "os"
5
+ "path"
6
+)
7
+
8
+// Splits the pathname p into Root and Ext, such that Root+Ext==p.
9
+func PathSplitExt(p string) (ret struct {
10
+ Root, Ext string
11
+}) {
12
+ ret.Ext = path.Ext(p)
13
+ ret.Root = p[:len(p)-len(ret.Ext)]
14
+ return
15
+}
16
+
17
+func FilePathExists(p string) bool {
18
+ _, err := os.Stat(p)
19
+ return err == nil
20
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/path_test.go
new
+17
@@ -0,0 +1,17 @@
1
+package missinggo
2
+
3
+import (
4
+ "fmt"
5
+)
6
+
7
+func ExamplePathSplitExt() {
8
+ fmt.Printf("%q\n", PathSplitExt(".cshrc"))
9
+ fmt.Printf("%q\n", PathSplitExt("dir/a.ext"))
10
+ fmt.Printf("%q\n", PathSplitExt("dir/.rc"))
11
+ fmt.Printf("%q\n", PathSplitExt("home/.secret/file"))
12
+ // Output:
13
+ // {"" ".cshrc"}
14
+ // {"dir/a" ".ext"}
15
+ // {"dir/" ".rc"}
16
+ // {"home/.secret/file" ""}
17
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/perf/mutex.go
new
+48
@@ -0,0 +1,48 @@
1
+package perf
2
+
3
+import (
4
+ "sync"
5
+
6
+ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/anacrolix/missinggo"
7
+)
8
+
9
+type TimedLocker struct {
10
+ L sync.Locker
11
+ Desc string
12
+}
13
+
14
+func (me *TimedLocker) Lock() {
15
+ tr := NewTimer()
16
+ me.L.Lock()
17
+ tr.Stop(me.Desc)
18
+}
19
+
20
+func (me *TimedLocker) Unlock() {
21
+ me.L.Unlock()
22
+}
23
+
24
+type TimedRWLocker struct {
25
+ RWL missinggo.RWLocker
26
+ WriteDesc string
27
+ ReadDesc string
28
+}
29
+
30
+func (me *TimedRWLocker) Lock() {
31
+ tr := NewTimer()
32
+ me.RWL.Lock()
33
+ tr.Stop(me.WriteDesc)
34
+}
35
+
36
+func (me *TimedRWLocker) Unlock() {
37
+ me.RWL.Unlock()
38
+}
39
+
40
+func (me *TimedRWLocker) RLock() {
41
+ tr := NewTimer()
42
+ me.RWL.RLock()
43
+ tr.Stop(me.ReadDesc)
44
+}
45
+
46
+func (me *TimedRWLocker) RUnlock() {
47
+ me.RWL.RUnlock()
48
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/perf/perf.go
new
+92
@@ -0,0 +1,92 @@
1
+package perf
2
+
3
+import (
4
+ "bytes"
5
+ "expvar"
6
+ "fmt"
7
+ "strconv"
8
+ "sync"
9
+ "time"
10
+
11
+ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/anacrolix/missinggo"
12
+)
13
+
14
+var (
15
+ em = missinggo.NewExpvarIndentMap("perfBuckets")
16
+ mu sync.RWMutex
17
+)
18
+
19
+type Timer struct {
20
+ started time.Time
21
+}
22
+
23
+func NewTimer() Timer {
24
+ return Timer{time.Now()}
25
+}
26
+
27
+func bucketExponent(d time.Duration) int {
28
+ e := -9
29
+ for d != 0 {
30
+ d /= 10
31
+ e++
32
+ }
33
+ return e
34
+}
35
+
36
+type buckets struct {
37
+ mu sync.Mutex
38
+ buckets []int64
39
+}
40
+
41
+func (me *buckets) Add(t time.Duration) {
42
+ e := bucketExponent(t)
43
+ me.mu.Lock()
44
+ for e+9 >= len(me.buckets) {
45
+ me.buckets = append(me.buckets, 0)
46
+ }
47
+ me.buckets[e+9]++
48
+ me.mu.Unlock()
49
+}
50
+
51
+func (me *buckets) String() string {
52
+ var b bytes.Buffer
53
+ fmt.Fprintf(&b, "{")
54
+ first := true
55
+ me.mu.Lock()
56
+ for i, count := range me.buckets {
57
+ if first {
58
+ if count == 0 {
59
+ continue
60
+ }
61
+ first = false
62
+ } else {
63
+ fmt.Fprintf(&b, ", ")
64
+ }
65
+ key := strconv.Itoa(i - 9)
66
+ fmt.Fprintf(&b, "%q: %d", key, count)
67
+ }
68
+ me.mu.Unlock()
69
+ fmt.Fprintf(&b, "}")
70
+ return b.String()
71
+}
72
+
73
+var _ expvar.Var = &buckets{}
74
+
75
+func (t *Timer) Stop(desc string) time.Duration {
76
+ d := time.Since(t.started)
77
+ mu.RLock()
78
+ _m := em.Get(desc)
79
+ mu.RUnlock()
80
+ if _m == nil {
81
+ mu.Lock()
82
+ _m = em.Get(desc)
83
+ if _m == nil {
84
+ _m = new(buckets)
85
+ em.Set(desc, _m)
86
+ }
87
+ mu.Unlock()
88
+ }
89
+ m := _m.(*buckets)
90
+ m.Add(d)
91
+ return d
92
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/perf/perf_test.go
new
+52
@@ -0,0 +1,52 @@
1
+package perf
2
+
3
+import (
4
+ "fmt"
5
+ "strconv"
6
+ "testing"
7
+ "time"
8
+
9
+ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/bradfitz/iter"
10
+ "github.com/stretchr/testify/assert"
11
+)
12
+
13
+func TestTimer(t *testing.T) {
14
+ tr := NewTimer()
15
+ tr.Stop("hiyo")
16
+ tr.Stop("hiyo")
17
+ t.Log(em.Get("hiyo").(*buckets))
18
+}
19
+
20
+func BenchmarkStopWarm(b *testing.B) {
21
+ tr := NewTimer()
22
+ for range iter.N(b.N) {
23
+ tr.Stop("a")
24
+ }
25
+}
26
+
27
+func BenchmarkStopCold(b *testing.B) {
28
+ tr := NewTimer()
29
+ for i := range iter.N(b.N) {
30
+ tr.Stop(strconv.FormatInt(int64(i), 10))
31
+ }
32
+}
33
+
34
+func TestExponent(t *testing.T) {
35
+ for _, c := range []struct {
36
+ e int
37
+ d time.Duration
38
+ }{
39
+ {-1, 10 * time.Millisecond},
40
+ {-2, 5 * time.Millisecond},
41
+ {-2, time.Millisecond},
42
+ {-3, 500 * time.Microsecond},
43
+ {-3, 100 * time.Microsecond},
44
+ } {
45
+ tr := NewTimer()
46
+ time.Sleep(c.d)
47
+ assert.Equal(t, c.e, bucketExponent(tr.Stop(fmt.Sprintf("%d", c.e))), "%s", c.d)
48
+ }
49
+ assert.Equal(t, `{"-1": 1}`, em.Get("-1").String())
50
+ assert.Equal(t, `{"-2": 2}`, em.Get("-2").String())
51
+ assert.Equal(t, `{"-3": 2}`, em.Get("-3").String())
52
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/pubsub/pubsub.go
new
+92
@@ -0,0 +1,92 @@
1
+package pubsub
2
+
3
+import (
4
+ "sync"
5
+)
6
+
7
+type PubSub struct {
8
+ mu sync.Mutex
9
+ next chan item
10
+ closed bool
11
+}
12
+
13
+type item struct {
14
+ value interface{}
15
+ next chan item
16
+}
17
+
18
+type Subscription struct {
19
+ next chan item
20
+ Values chan interface{}
21
+ mu sync.Mutex
22
+ closed chan struct{}
23
+}
24
+
25
+func NewPubSub() (ret *PubSub) {
26
+ return &PubSub{
27
+ next: make(chan item, 1),
28
+ }
29
+}
30
+
31
+func (me *PubSub) Publish(v interface{}) {
32
+ next := make(chan item, 1)
33
+ i := item{v, next}
34
+ me.mu.Lock()
35
+ me.next <- i
36
+ me.next = next
37
+ me.mu.Unlock()
38
+}
39
+
40
+func (me *Subscription) Close() {
41
+ me.mu.Lock()
42
+ defer me.mu.Unlock()
43
+ select {
44
+ case <-me.closed:
45
+ default:
46
+ close(me.closed)
47
+ }
48
+}
49
+
50
+func (me *Subscription) runner() {
51
+ defer close(me.Values)
52
+ for {
53
+ select {
54
+ case i, ok := <-me.next:
55
+ if !ok {
56
+ me.Close()
57
+ return
58
+ }
59
+ me.next <- i
60
+ me.next = i.next
61
+ select {
62
+ case me.Values <- i.value:
63
+ case <-me.closed:
64
+ return
65
+ }
66
+ case <-me.closed:
67
+ return
68
+ }
69
+ }
70
+}
71
+
72
+func (me *PubSub) Subscribe() (ret *Subscription) {
73
+ ret = &Subscription{
74
+ closed: make(chan struct{}),
75
+ Values: make(chan interface{}),
76
+ }
77
+ me.mu.Lock()
78
+ ret.next = me.next
79
+ me.mu.Unlock()
80
+ go ret.runner()
81
+ return
82
+}
83
+
84
+func (me *PubSub) Close() {
85
+ me.mu.Lock()
86
+ defer me.mu.Unlock()
87
+ if me.closed {
88
+ return
89
+ }
90
+ close(me.next)
91
+ me.closed = true
92
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/pubsub/pubsub_test.go
new
+74
@@ -0,0 +1,74 @@
1
+package pubsub
2
+
3
+import (
4
+ "sync"
5
+ "testing"
6
+
7
+ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/bradfitz/iter"
8
+ "github.com/stretchr/testify/assert"
9
+ "github.com/stretchr/testify/require"
10
+)
11
+
12
+func TestDoubleClose(t *testing.T) {
13
+ ps := NewPubSub()
14
+ ps.Close()
15
+ ps.Close()
16
+}
17
+
18
+func testBroadcast(t testing.TB, subs, vals int) {
19
+ ps := NewPubSub()
20
+ var wg sync.WaitGroup
21
+ for range iter.N(subs) {
22
+ wg.Add(1)
23
+ s := ps.Subscribe()
24
+ go func() {
25
+ defer wg.Done()
26
+ var e int
27
+ for i := range s.Values {
28
+ assert.Equal(t, e, i.(int))
29
+ e++
30
+ }
31
+ assert.Equal(t, vals, e)
32
+ }()
33
+ }
34
+ for i := range iter.N(vals) {
35
+ ps.Publish(i)
36
+ }
37
+ ps.Close()
38
+ wg.Wait()
39
+}
40
+
41
+func TestBroadcast(t *testing.T) {
42
+ testBroadcast(t, 100, 10)
43
+}
44
+
45
+func BenchmarkBroadcast(b *testing.B) {
46
+ for range iter.N(b.N) {
47
+ testBroadcast(b, 10, 1000)
48
+ }
49
+}
50
+
51
+func TestCloseSubscription(t *testing.T) {
52
+ ps := NewPubSub()
53
+ ps.Publish(1)
54
+ s := ps.Subscribe()
55
+ select {
56
+ case <-s.Values:
57
+ t.FailNow()
58
+ default:
59
+ }
60
+ ps.Publish(2)
61
+ s2 := ps.Subscribe()
62
+ ps.Publish(3)
63
+ require.Equal(t, 2, <-s.Values)
64
+ require.EqualValues(t, 3, <-s.Values)
65
+ s.Close()
66
+ _, ok := <-s.Values
67
+ require.False(t, ok)
68
+ ps.Publish(4)
69
+ ps.Close()
70
+ require.Equal(t, 3, <-s2.Values)
71
+ require.Equal(t, 4, <-s2.Values)
72
+ require.Nil(t, <-s2.Values)
73
+ s2.Close()
74
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/rle.go
new
+46
@@ -0,0 +1,46 @@
1
+package missinggo
2
+
3
+// A RunLengthEncoder counts successive duplicate elements and emits the
4
+// element and the run length when the element changes or the encoder is
5
+// flushed.
6
+type RunLengthEncoder interface {
7
+ // Add a series of identical elements to the stream.
8
+ Append(element interface{}, count uint64)
9
+ // Emit the current element and its count if non-zero without waiting for
10
+ // the element to change.
11
+ Flush()
12
+}
13
+
14
+type runLengthEncoder struct {
15
+ eachRun func(element interface{}, count uint64)
16
+ element interface{}
17
+ count uint64
18
+}
19
+
20
+// Creates a new RunLengthEncoder. eachRun is called when an element and its
21
+// count is emitted, per the RunLengthEncoder interface.
22
+func NewRunLengthEncoder(eachRun func(element interface{}, count uint64)) RunLengthEncoder {
23
+ return &runLengthEncoder{
24
+ eachRun: eachRun,
25
+ }
26
+}
27
+
28
+func (me *runLengthEncoder) Append(element interface{}, count uint64) {
29
+ if element == me.element {
30
+ me.count += count
31
+ return
32
+ }
33
+ if me.count != 0 {
34
+ me.eachRun(me.element, me.count)
35
+ }
36
+ me.count = count
37
+ me.element = element
38
+}
39
+
40
+func (me *runLengthEncoder) Flush() {
41
+ if me.count == 0 {
42
+ return
43
+ }
44
+ me.eachRun(me.element, me.count)
45
+ me.count = 0
46
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/rle_test.go
new
+20
@@ -0,0 +1,20 @@
1
+package missinggo_test
2
+
3
+import (
4
+ "fmt"
5
+
6
+ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/anacrolix/missinggo"
7
+)
8
+
9
+func ExampleNewRunLengthEncoder() {
10
+ var s string
11
+ rle := missinggo.NewRunLengthEncoder(func(e interface{}, count uint64) {
12
+ s += fmt.Sprintf("%d%c", count, e)
13
+ })
14
+ for _, e := range "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW" {
15
+ rle.Append(e, 1)
16
+ }
17
+ rle.Flush()
18
+ fmt.Println(s)
19
+ // Output: 12W1B12W3B24W1B14W
20
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/singleflight.go
new
+39
@@ -0,0 +1,39 @@
1
+package missinggo
2
+
3
+import "sync"
4
+
5
+type ongoing struct {
6
+ do sync.Mutex
7
+ users int
8
+}
9
+
10
+type SingleFlight struct {
11
+ mu sync.Mutex
12
+ ongoing map[string]*ongoing
13
+}
14
+
15
+func (me *SingleFlight) Lock(id string) {
16
+ me.mu.Lock()
17
+ on, ok := me.ongoing[id]
18
+ if !ok {
19
+ on = new(ongoing)
20
+ if me.ongoing == nil {
21
+ me.ongoing = make(map[string]*ongoing)
22
+ }
23
+ me.ongoing[id] = on
24
+ }
25
+ on.users++
26
+ me.mu.Unlock()
27
+ on.do.Lock()
28
+}
29
+
30
+func (me *SingleFlight) Unlock(id string) {
31
+ me.mu.Lock()
32
+ on := me.ongoing[id]
33
+ on.do.Unlock()
34
+ on.users--
35
+ if on.users == 0 {
36
+ delete(me.ongoing, id)
37
+ }
38
+ me.mu.Unlock()
39
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/sync.go
new
+11
@@ -0,0 +1,11 @@
1
+package missinggo
2
+
3
+import (
4
+ "sync"
5
+)
6
+
7
+type RWLocker interface {
8
+ sync.Locker
9
+ RLock()
10
+ RUnlock()
11
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/url.go
new
+30
@@ -0,0 +1,30 @@
1
+package missinggo
2
+
3
+import (
4
+ "net/http"
5
+ "net/url"
6
+)
7
+
8
+// Deep copies a URL.
9
+func CopyURL(u *url.URL) (ret *url.URL) {
10
+ ret = new(url.URL)
11
+ *ret = *u
12
+ if u.User != nil {
13
+ ret.User = new(url.Userinfo)
14
+ *ret.User = *u.User
15
+ }
16
+ return
17
+}
18
+
19
+// Reconstructs the URL that would have produced the given Request.
20
+// Request.URLs are not fully populated in http.Server handlers.
21
+func RequestedURL(r *http.Request) (ret *url.URL) {
22
+ ret = CopyURL(r.URL)
23
+ ret.Host = r.Host
24
+ if r.TLS != nil {
25
+ ret.Scheme = "https"
26
+ } else {
27
+ ret.Scheme = "http"
28
+ }
29
+ return
30
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/wolf.go
new
+51
@@ -0,0 +1,51 @@
1
+package missinggo
2
+
3
+import (
4
+ "log"
5
+ "runtime"
6
+ "sync"
7
+ "sync/atomic"
8
+)
9
+
10
+const debug = false
11
+
12
+// A Wolf represents some event that becomes less and less interesting as it
13
+// occurs. Call CryHeard to see if we should pay attention this time.
14
+type Wolf struct {
15
+ cries uint64
16
+}
17
+
18
+// Returns true less and less often. Convenient for exponentially decreasing
19
+// the amount of noise due to errors.
20
+func (me *Wolf) CryHeard() bool {
21
+ n := atomic.AddUint64(&me.cries, 1)
22
+ return n&(n-1) == 0
23
+}
24
+
25
+var (
26
+ mu sync.Mutex
27
+ wolves map[uintptr]*Wolf
28
+)
29
+
30
+// Calls CryHeard() on a Wolf that is unique to the callers program counter.
31
+// i.e. every CryHeard() expression has its own Wolf.
32
+func CryHeard() bool {
33
+ pc, file, line, ok := runtime.Caller(1)
34
+ if debug {
35
+ log.Println(pc, file, line, ok)
36
+ }
37
+ if !ok {
38
+ return true
39
+ }
40
+ mu.Lock()
41
+ if wolves == nil {
42
+ wolves = make(map[uintptr]*Wolf)
43
+ }
44
+ w, ok := wolves[pc]
45
+ if !ok {
46
+ w = new(Wolf)
47
+ wolves[pc] = w
48
+ }
49
+ mu.Unlock()
50
+ return w.CryHeard()
51
+}
Godeps/_workspace/src/github.com/anacrolix/missinggo/wolf_test.go
new
+30
@@ -0,0 +1,30 @@
1
+package missinggo
2
+
3
+import (
4
+ "testing"
5
+
6
+ "github.com/stretchr/testify/require"
7
+)
8
+
9
+func cryHeard() bool {
10
+ return CryHeard()
11
+}
12
+
13
+func TestCrySameLocation(t *testing.T) {
14
+ require.True(t, cryHeard())
15
+ require.True(t, cryHeard())
16
+ require.False(t, cryHeard())
17
+ require.True(t, cryHeard())
18
+ require.False(t, cryHeard())
19
+ require.False(t, cryHeard())
20
+ require.False(t, cryHeard())
21
+ require.True(t, cryHeard())
22
+}
23
+
24
+func TestCryDifferentLocations(t *testing.T) {
25
+ require.True(t, CryHeard())
26
+ require.True(t, CryHeard())
27
+ require.True(t, CryHeard())
28
+ require.True(t, CryHeard())
29
+ require.True(t, CryHeard())
30
+}
Godeps/_workspace/src/github.com/anacrolix/utp/LICENSE
new
+362
@@ -0,0 +1,362 @@
1
+Mozilla Public License, version 2.0
2
+
3
+1. Definitions
4
+
5
+1.1. "Contributor"
6
+
7
+ means each individual or legal entity that creates, contributes to the
8
+ creation of, or owns Covered Software.
9
+
10
+1.2. "Contributor Version"
11
+
12
+ means the combination of the Contributions of others (if any) used by a
13
+ Contributor and that particular Contributor's Contribution.
14
+
15
+1.3. "Contribution"
16
+
17
+ means Covered Software of a particular Contributor.
18
+
19
+1.4. "Covered Software"
20
+
21
+ means Source Code Form to which the initial Contributor has attached the
22
+ notice in Exhibit A, the Executable Form of such Source Code Form, and
23
+ Modifications of such Source Code Form, in each case including portions
24
+ thereof.
25
+
26
+1.5. "Incompatible With Secondary Licenses"
27
+ means
28
+
29
+ a. that the initial Contributor has attached the notice described in
30
+ Exhibit B to the Covered Software; or
31
+
32
+ b. that the Covered Software was made available under the terms of
33
+ version 1.1 or earlier of the License, but not also under the terms of
34
+ a Secondary License.
35
+
36
+1.6. "Executable Form"
37
+
38
+ means any form of the work other than Source Code Form.
39
+
40
+1.7. "Larger Work"
41
+
42
+ means a work that combines Covered Software with other material, in a
43
+ separate file or files, that is not Covered Software.
44
+
45
+1.8. "License"
46
+
47
+ means this document.
48
+
49
+1.9. "Licensable"
50
+
51
+ means having the right to grant, to the maximum extent possible, whether
52
+ at the time of the initial grant or subsequently, any and all of the
53
+ rights conveyed by this License.
54
+
55
+1.10. "Modifications"
56
+
57
+ means any of the following:
58
+
59
+ a. any file in Source Code Form that results from an addition to,
60
+ deletion from, or modification of the contents of Covered Software; or
61
+
62
+ b. any new file in Source Code Form that contains any Covered Software.
63
+
64
+1.11. "Patent Claims" of a Contributor
65
+
66
+ means any patent claim(s), including without limitation, method,
67
+ process, and apparatus claims, in any patent Licensable by such
68
+ Contributor that would be infringed, but for the grant of the License,
69
+ by the making, using, selling, offering for sale, having made, import,
70
+ or transfer of either its Contributions or its Contributor Version.
71
+
72
+1.12. "Secondary License"
73
+
74
+ means either the GNU General Public License, Version 2.0, the GNU Lesser
75
+ General Public License, Version 2.1, the GNU Affero General Public
76
+ License, Version 3.0, or any later versions of those licenses.
77
+
78
+1.13. "Source Code Form"
79
+
80
+ means the form of the work preferred for making modifications.
81
+
82
+1.14. "You" (or "Your")
83
+
84
+ means an individual or a legal entity exercising rights under this
85
+ License. For legal entities, "You" includes any entity that controls, is
86
+ controlled by, or is under common control with You. For purposes of this
87
+ definition, "control" means (a) the power, direct or indirect, to cause
88
+ the direction or management of such entity, whether by contract or
89
+ otherwise, or (b) ownership of more than fifty percent (50%) of the
90
+ outstanding shares or beneficial ownership of such entity.
91
+
92
+
93
+2. License Grants and Conditions
94
+
95
+2.1. Grants
96
+
97
+ Each Contributor hereby grants You a world-wide, royalty-free,
98
+ non-exclusive license:
99
+
100
+ a. under intellectual property rights (other than patent or trademark)
101
+ Licensable by such Contributor to use, reproduce, make available,
102
+ modify, display, perform, distribute, and otherwise exploit its
103
+ Contributions, either on an unmodified basis, with Modifications, or
104
+ as part of a Larger Work; and
105
+
106
+ b. under Patent Claims of such Contributor to make, use, sell, offer for
107
+ sale, have made, import, and otherwise transfer either its
108
+ Contributions or its Contributor Version.
109
+
110
+2.2. Effective Date
111
+
112
+ The licenses granted in Section 2.1 with respect to any Contribution
113
+ become effective for each Contribution on the date the Contributor first
114
+ distributes such Contribution.
115
+
116
+2.3. Limitations on Grant Scope
117
+
118
+ The licenses granted in this Section 2 are the only rights granted under
119
+ this License. No additional rights or licenses will be implied from the
120
+ distribution or licensing of Covered Software under this License.
121
+ Notwithstanding Section 2.1(b) above, no patent license is granted by a
122
+ Contributor:
123
+
124
+ a. for any code that a Contributor has removed from Covered Software; or
125
+
126
+ b. for infringements caused by: (i) Your and any other third party's
127
+ modifications of Covered Software, or (ii) the combination of its
128
+ Contributions with other software (except as part of its Contributor
129
+ Version); or
130
+
131
+ c. under Patent Claims infringed by Covered Software in the absence of
132
+ its Contributions.
133
+
134
+ This License does not grant any rights in the trademarks, service marks,
135
+ or logos of any Contributor (except as may be necessary to comply with
136
+ the notice requirements in Section 3.4).
137
+
138
+2.4. Subsequent Licenses
139
+
140
+ No Contributor makes additional grants as a result of Your choice to
141
+ distribute the Covered Software under a subsequent version of this
142
+ License (see Section 10.2) or under the terms of a Secondary License (if
143
+ permitted under the terms of Section 3.3).
144
+
145
+2.5. Representation
146
+
147
+ Each Contributor represents that the Contributor believes its
148
+ Contributions are its original creation(s) or it has sufficient rights to
149
+ grant the rights to its Contributions conveyed by this License.
150
+
151
+2.6. Fair Use
152
+
153
+ This License is not intended to limit any rights You have under
154
+ applicable copyright doctrines of fair use, fair dealing, or other
155
+ equivalents.
156
+
157
+2.7. Conditions
158
+
159
+ Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
160
+ Section 2.1.
161
+
162
+
163
+3. Responsibilities
164
+
165
+3.1. Distribution of Source Form
166
+
167
+ All distribution of Covered Software in Source Code Form, including any
168
+ Modifications that You create or to which You contribute, must be under
169
+ the terms of this License. You must inform recipients that the Source
170
+ Code Form of the Covered Software is governed by the terms of this
171
+ License, and how they can obtain a copy of this License. You may not
172
+ attempt to alter or restrict the recipients' rights in the Source Code
173
+ Form.
174
+
175
+3.2. Distribution of Executable Form
176
+
177
+ If You distribute Covered Software in Executable Form then:
178
+
179
+ a. such Covered Software must also be made available in Source Code Form,
180
+ as described in Section 3.1, and You must inform recipients of the
181
+ Executable Form how they can obtain a copy of such Source Code Form by
182
+ reasonable means in a timely manner, at a charge no more than the cost
183
+ of distribution to the recipient; and
184
+
185
+ b. You may distribute such Executable Form under the terms of this
186
+ License, or sublicense it under different terms, provided that the
187
+ license for the Executable Form does not attempt to limit or alter the
188
+ recipients' rights in the Source Code Form under this License.
189
+
190
+3.3. Distribution of a Larger Work
191
+
192
+ You may create and distribute a Larger Work under terms of Your choice,
193
+ provided that You also comply with the requirements of this License for
194
+ the Covered Software. If the Larger Work is a combination of Covered
195
+ Software with a work governed by one or more Secondary Licenses, and the
196
+ Covered Software is not Incompatible With Secondary Licenses, this
197
+ License permits You to additionally distribute such Covered Software
198
+ under the terms of such Secondary License(s), so that the recipient of
199
+ the Larger Work may, at their option, further distribute the Covered
200
+ Software under the terms of either this License or such Secondary
201
+ License(s).
202
+
203
+3.4. Notices
204
+
205
+ You may not remove or alter the substance of any license notices
206
+ (including copyright notices, patent notices, disclaimers of warranty, or
207
+ limitations of liability) contained within the Source Code Form of the
208
+ Covered Software, except that You may alter any license notices to the
209
+ extent required to remedy known factual inaccuracies.
210
+
211
+3.5. Application of Additional Terms
212
+
213
+ You may choose to offer, and to charge a fee for, warranty, support,
214
+ indemnity or liability obligations to one or more recipients of Covered
215
+ Software. However, You may do so only on Your own behalf, and not on
216
+ behalf of any Contributor. You must make it absolutely clear that any
217
+ such warranty, support, indemnity, or liability obligation is offered by
218
+ You alone, and You hereby agree to indemnify every Contributor for any
219
+ liability incurred by such Contributor as a result of warranty, support,
220
+ indemnity or liability terms You offer. You may include additional
221
+ disclaimers of warranty and limitations of liability specific to any
222
+ jurisdiction.
223
+
224
+4. Inability to Comply Due to Statute or Regulation
225
+
226
+ If it is impossible for You to comply with any of the terms of this License
227
+ with respect to some or all of the Covered Software due to statute,
228
+ judicial order, or regulation then You must: (a) comply with the terms of
229
+ this License to the maximum extent possible; and (b) describe the
230
+ limitations and the code they affect. Such description must be placed in a
231
+ text file included with all distributions of the Covered Software under
232
+ this License. Except to the extent prohibited by statute or regulation,
233
+ such description must be sufficiently detailed for a recipient of ordinary
234
+ skill to be able to understand it.
235
+
236
+5. Termination
237
+
238
+5.1. The rights granted under this License will terminate automatically if You
239
+ fail to comply with any of its terms. However, if You become compliant,
240
+ then the rights granted under this License from a particular Contributor
241
+ are reinstated (a) provisionally, unless and until such Contributor
242
+ explicitly and finally terminates Your grants, and (b) on an ongoing
243
+ basis, if such Contributor fails to notify You of the non-compliance by
244
+ some reasonable means prior to 60 days after You have come back into
245
+ compliance. Moreover, Your grants from a particular Contributor are
246
+ reinstated on an ongoing basis if such Contributor notifies You of the
247
+ non-compliance by some reasonable means, this is the first time You have
248
+ received notice of non-compliance with this License from such
249
+ Contributor, and You become compliant prior to 30 days after Your receipt
250
+ of the notice.
251
+
252
+5.2. If You initiate litigation against any entity by asserting a patent
253
+ infringement claim (excluding declaratory judgment actions,
254
+ counter-claims, and cross-claims) alleging that a Contributor Version
255
+ directly or indirectly infringes any patent, then the rights granted to
256
+ You by any and all Contributors for the Covered Software under Section
257
+ 2.1 of this License shall terminate.
258
+
259
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
260
+ license agreements (excluding distributors and resellers) which have been
261
+ validly granted by You or Your distributors under this License prior to
262
+ termination shall survive termination.
263
+
264
+6. Disclaimer of Warranty
265
+
266
+ Covered Software is provided under this License on an "as is" basis,
267
+ without warranty of any kind, either expressed, implied, or statutory,
268
+ including, without limitation, warranties that the Covered Software is free
269
+ of defects, merchantable, fit for a particular purpose or non-infringing.
270
+ The entire risk as to the quality and performance of the Covered Software
271
+ is with You. Should any Covered Software prove defective in any respect,
272
+ You (not any Contributor) assume the cost of any necessary servicing,
273
+ repair, or correction. This disclaimer of warranty constitutes an essential
274
+ part of this License. No use of any Covered Software is authorized under
275
+ this License except under this disclaimer.
276
+
277
+7. Limitation of Liability
278
+
279
+ Under no circumstances and under no legal theory, whether tort (including
280
+ negligence), contract, or otherwise, shall any Contributor, or anyone who
281
+ distributes Covered Software as permitted above, be liable to You for any
282
+ direct, indirect, special, incidental, or consequential damages of any
283
+ character including, without limitation, damages for lost profits, loss of
284
+ goodwill, work stoppage, computer failure or malfunction, or any and all
285
+ other commercial damages or losses, even if such party shall have been
286
+ informed of the possibility of such damages. This limitation of liability
287
+ shall not apply to liability for death or personal injury resulting from
288
+ such party's negligence to the extent applicable law prohibits such
289
+ limitation. Some jurisdictions do not allow the exclusion or limitation of
290
+ incidental or consequential damages, so this exclusion and limitation may
291
+ not apply to You.
292
+
293
+8. Litigation
294
+
295
+ Any litigation relating to this License may be brought only in the courts
296
+ of a jurisdiction where the defendant maintains its principal place of
297
+ business and such litigation shall be governed by laws of that
298
+ jurisdiction, without reference to its conflict-of-law provisions. Nothing
299
+ in this Section shall prevent a party's ability to bring cross-claims or
300
+ counter-claims.
301
+
302
+9. Miscellaneous
303
+
304
+ This License represents the complete agreement concerning the subject
305
+ matter hereof. If any provision of this License is held to be
306
+ unenforceable, such provision shall be reformed only to the extent
307
+ necessary to make it enforceable. Any law or regulation which provides that
308
+ the language of a contract shall be construed against the drafter shall not
309
+ be used to construe this License against a Contributor.
310
+
311
+
312
+10. Versions of the License
313
+
314
+10.1. New Versions
315
+
316
+ Mozilla Foundation is the license steward. Except as provided in Section
317
+ 10.3, no one other than the license steward has the right to modify or
318
+ publish new versions of this License. Each version will be given a
319
+ distinguishing version number.
320
+
321
+10.2. Effect of New Versions
322
+
323
+ You may distribute the Covered Software under the terms of the version
324
+ of the License under which You originally received the Covered Software,
325
+ or under the terms of any subsequent version published by the license
326
+ steward.
327
+
328
+10.3. Modified Versions
329
+
330
+ If you create software not governed by this License, and you want to
331
+ create a new license for such software, you may create and use a
332
+ modified version of this License if you rename the license and remove
333
+ any references to the name of the license steward (except to note that
334
+ such modified license differs from this License).
335
+
336
+10.4. Distributing Source Code Form that is Incompatible With Secondary
337
+ Licenses If You choose to distribute Source Code Form that is
338
+ Incompatible With Secondary Licenses under the terms of this version of
339
+ the License, the notice described in Exhibit B of this License must be
340
+ attached.
341
+
342
+Exhibit A - Source Code Form License Notice
343
+
344
+ This Source Code Form is subject to the
345
+ terms of the Mozilla Public License, v.
346
+ 2.0. If a copy of the MPL was not
347
+ distributed with this file, You can
348
+ obtain one at
349
+ http://mozilla.org/MPL/2.0/.
350
+
351
+If it is not possible or desirable to put the notice in a particular file,
352
+then You may include the notice in a location (such as a LICENSE file in a
353
+relevant directory) where a recipient would be likely to look for such a
354
+notice.
355
+
356
+You may add additional accurate notices of copyright ownership.
357
+
358
+Exhibit B - "Incompatible With Secondary Licenses" Notice
359
+
360
+ This Source Code Form is "Incompatible
361
+ With Secondary Licenses", as defined by
362
+ the Mozilla Public License, v. 2.0.
Godeps/_workspace/src/github.com/anacrolix/utp/README.md
new
+19
@@ -0,0 +1,19 @@
1
+# utp
2
+[](https://godoc.org/github.com/anacrolix/utp)
3
+[](https://drone.io/github.com/anacrolix/utp/latest)
4
+
5
+Package utp implements uTP, the micro transport protocol as used with Bittorrent. It opts for simplicity and reliability over strict adherence to the (poor) spec.
6
+
7
+## Supported
8
+
9
+ * Multiple uTP connections switched on a single PacketConn, including those initiated locally.
10
+ * Raw access to the PacketConn for non-uTP purposes, like sharing the PacketConn with a DHT implementation.
11
+
12
+## Implementation characteristics
13
+
14
+ * Receive window size is used to limit out of order packets received.
15
+ * There is no MTU path discovery. The minimum size is always used.
16
+ * A fixed 64 slot selective ack window is used in both sending and receiving.
17
+ * All received non-ACK packets are ACKed in response.
18
+
19
+Patches welcomed.
Godeps/_workspace/src/github.com/anacrolix/utp/cmd/ucat/ucat.go
new
+66
@@ -0,0 +1,66 @@
1
+package main
2
+
3
+import (
4
+ "flag"
5
+ "fmt"
6
+ "io"
7
+ "log"
8
+ "net"
9
+ "os"
10
+ "os/signal"
11
+
12
+ "github.com/anacrolix/envpprof"
13
+
14
+ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/anacrolix/utp"
15
+)
16
+
17
+func main() {
18
+ defer envpprof.Stop()
19
+ listen := flag.Bool("l", false, "listen")
20
+ port := flag.Int("p", 0, "port to listen on")
21
+ flag.Parse()
22
+ var (
23
+ conn net.Conn
24
+ err error
25
+ )
26
+ if *listen {
27
+ s, err := utp.NewSocket("udp", fmt.Sprintf(":%d", *port))
28
+ if err != nil {
29
+ log.Fatal(err)
30
+ }
31
+ defer s.Close()
32
+ conn, err = s.Accept()
33
+ if err != nil {
34
+ log.Fatal(err)
35
+ }
36
+ } else {
37
+ conn, err = utp.Dial(net.JoinHostPort(flag.Arg(0), flag.Arg(1)))
38
+ if err != nil {
39
+ log.Fatal(err)
40
+ }
41
+ }
42
+ defer conn.Close()
43
+ go func() {
44
+ sig := make(chan os.Signal, 1)
45
+ signal.Notify(sig, os.Interrupt)
46
+ <-sig
47
+ conn.Close()
48
+ }()
49
+ writerDone := make(chan struct{})
50
+ go func() {
51
+ defer close(writerDone)
52
+ written, err := io.Copy(conn, os.Stdin)
53
+ if err != nil {
54
+ conn.Close()
55
+ log.Fatalf("error after writing %d bytes: %s", written, err)
56
+ }
57
+ log.Printf("wrote %d bytes", written)
58
+ conn.Close()
59
+ }()
60
+ n, err := io.Copy(os.Stdout, conn)
61
+ if err != nil {
62
+ log.Fatal(err)
63
+ }
64
+ log.Printf("received %d bytes", n)
65
+ // <-writerDone
66
+}
Godeps/_workspace/src/github.com/anacrolix/utp/pingpong
new
+61
@@ -0,0 +1,61 @@
1
+# This shell script uses nc-like executables to send and receive the file at
2
+# $1, and prints the checksums. 3 such executables are
3
+# github.com/h2so5/utp/ucat, invoked as h2so5-ucat, libutp-ucat, which is the
4
+# ucat or ucat-static generated by the C++ libutp, and lastly, ./cmd/ucat from
5
+# this repository. A good file in my experiments is no more than a few 100MB,
6
+# or you'll be waiting a while.
7
+
8
+set -eu
9
+# set -x
10
+
11
+# Passed to invocations of godo for package ./cmd/ucat.
12
+#GODOFLAGS=-race
13
+
14
+#export GO_UTP_PACKET_DROP=0.1
15
+export GOPPROF=
16
+
17
+# Invokes the implementation to test against. If there's an arg, then it's
18
+# expected to listen.
19
+function other_ucat() {
20
+ if [[ $# != 0 ]]; then
21
+ libutp-ucat -l -p 4000
22
+ # h2so5-ucat -l :4000
23
+ else
24
+ libutp-ucat localhost 4000
25
+ # h2so5-ucat localhost:4000
26
+ fi
27
+}
28
+
29
+# Check what the correct result is.
30
+md5 "$1"
31
+
32
+rate() {
33
+ pv -a -W -b
34
+}
35
+
36
+echo 'utp->other_ucat'
37
+# Send from this uTP implementation to another client.
38
+other_ucat -l | rate | md5 &
39
+# sleep 1
40
+godo ${GODOFLAGS-} ./cmd/ucat localhost 4000 < "$1"
41
+wait
42
+
43
+echo 'other_ucat->utp'
44
+# Send from the other implementation, to this one.
45
+GO_UTP_LOGGING=0 GOPPROF= godo ${GODOFLAGS-} ./cmd/ucat -l -p 4000 | rate | md5 &
46
+# Never receive from h2so5's ucat without a small sleep first. Don't know why.
47
+# sleep 1
48
+other_ucat < "$1"
49
+wait
50
+
51
+echo 'libutp->libutp'
52
+libutp-ucat -l -p 4000 | rate | md5 &
53
+libutp-ucat localhost 4000 < "$1"
54
+wait
55
+
56
+echo 'utp->utp'
57
+godo ./cmd/ucat -l -p 4000 | rate | md5 &
58
+godo ./cmd/ucat localhost 4000 < "$1"
59
+wait
60
+
61
+# Now check the hashes match (yes you).
Godeps/_workspace/src/github.com/anacrolix/utp/utp.go
new
+1461
@@ -0,0 +1,1461 @@
1
+// Package utp implements uTP, the micro transport protocol as used with
2
+// Bittorrent. It opts for simplicity and reliability over strict adherence to
3
+// the (poor) spec. It allows using the underlying OS-level transport despite
4
+// dispatching uTP on top to allow for example, shared socket use with DHT.
5
+// Additionally, multiple uTP connections can share the same OS socket, to
6
+// truly realize uTP's claim to be light on system and network switching
7
+// resources.
8
+//
9
+// Socket is a wrapper of net.UDPConn, and performs dispatching of uTP packets
10
+// to attached uTP Conns. Dial and Accept is done via Socket. Conn implements
11
+// net.Conn over uTP, via aforementioned Socket.
12
+package utp
13
+
14
+import (
15
+ "encoding/binary"
16
+ "errors"
17
+ "expvar"
18
+ "fmt"
19
+ "io"
20
+ "log"
21
+ "math/rand"
22
+ "net"
23
+ "os"
24
+ "strconv"
25
+ "sync"
26
+ "time"
27
+
28
+ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/anacrolix/jitter"
29
+ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/anacrolix/missinggo"
30
+)
31
+
32
+const (
33
+ // Maximum received SYNs that haven't been accepted. If more SYNs are
34
+ // received, a pseudo randomly selected SYN is replied to with a reset to
35
+ // make room.
36
+ backlog = 50
37
+
38
+ // IPv6 min MTU is 1280, -40 for IPv6 header, and ~8 for fragment header?
39
+ minMTU = 1232
40
+ recvWindow = 0x8000 // 32KiB
41
+ // uTP header of 20, +2 for the next extension, and 8 bytes of selective
42
+ // ACK.
43
+ maxHeaderSize = 30
44
+ maxPayloadSize = minMTU - maxHeaderSize
45
+ maxRecvSize = 0x2000
46
+
47
+ // Maximum out-of-order packets to buffer.
48
+ maxUnackedInbound = 64
49
+
50
+ // If an send isn't acknowledged after this period, its connection is
51
+ // destroyed. There are resends during this period.
52
+ sendTimeout = 15 * time.Second
53
+)
54
+
55
+var (
56
+ ackSkippedResends = expvar.NewInt("utpAckSkippedResends")
57
+ // Inbound packets processed by a Conn.
58
+ deliveriesProcessed = expvar.NewInt("utpDeliveriesProcessed")
59
+ sentStatePackets = expvar.NewInt("utpSentStatePackets")
60
+ unusedReads = expvar.NewInt("utpUnusedReads")
61
+ sendBufferPool = sync.Pool{
62
+ New: func() interface{} { return make([]byte, minMTU) },
63
+ }
64
+)
65
+
66
+type deadlineCallback struct {
67
+ deadline time.Time
68
+ timer *time.Timer
69
+ callback func()
70
+ inited bool
71
+}
72
+
73
+func (me *deadlineCallback) deadlineExceeded() bool {
74
+ return !me.deadline.IsZero() && !time.Now().Before(me.deadline)
75
+}
76
+
77
+func (me *deadlineCallback) updateTimer() {
78
+ if me.timer != nil {
79
+ me.timer.Stop()
80
+ }
81
+ if me.deadline.IsZero() {
82
+ return
83
+ }
84
+ if me.callback == nil {
85
+ panic("deadline callback is nil")
86
+ }
87
+ me.timer = time.AfterFunc(me.deadline.Sub(time.Now()), me.callback)
88
+}
89
+
90
+func (me *deadlineCallback) setDeadline(t time.Time) {
91
+ me.deadline = t
92
+ me.updateTimer()
93
+}
94
+
95
+func (me *deadlineCallback) setCallback(f func()) {
96
+ me.callback = f
97
+ me.updateTimer()
98
+}
99
+
100
+type connDeadlines struct {
101
+ // mu sync.Mutex
102
+ read, write deadlineCallback
103
+}
104
+
105
+func (c *connDeadlines) SetDeadline(t time.Time) error {
106
+ c.read.setDeadline(t)
107
+ c.write.setDeadline(t)
108
+ return nil
109
+}
110
+
111
+func (c *connDeadlines) SetReadDeadline(t time.Time) error {
112
+ c.read.setDeadline(t)
113
+ return nil
114
+}
115
+
116
+func (c *connDeadlines) SetWriteDeadline(t time.Time) error {
117
+ c.write.setDeadline(t)
118
+ return nil
119
+}
120
+
121
+// Strongly-type guarantee of resolved network address.
122
+type resolvedAddrStr string
123
+
124
+// Uniquely identifies any uTP connection on top of the underlying packet
125
+// stream.
126
+type connKey struct {
127
+ remoteAddr resolvedAddrStr
128
+ connID uint16
129
+}
130
+
131
+// A Socket wraps a net.PacketConn, diverting uTP packets to its child uTP
132
+// Conns.
133
+type Socket struct {
134
+ mu sync.RWMutex
135
+ event sync.Cond
136
+ pc net.PacketConn
137
+ conns map[connKey]*Conn
138
+ backlog map[syn]struct{}
139
+ reads chan read
140
+ closing chan struct{}
141
+
142
+ unusedReads chan read
143
+ connDeadlines
144
+ // If a read error occurs on the underlying net.PacketConn, it is put
145
+ // here. This is because reading is done in its own goroutine to dispatch
146
+ // to uTP Conns.
147
+ ReadErr error
148
+}
149
+
150
+type read struct {
151
+ data []byte
152
+ from net.Addr
153
+}
154
+
155
+type syn struct {
156
+ seq_nr, conn_id uint16
157
+ addr string
158
+}
159
+
160
+const (
161
+ extensionTypeSelectiveAck = 1
162
+)
163
+
164
+type extensionField struct {
165
+ Type byte
166
+ Bytes []byte
167
+}
168
+
169
+type header struct {
170
+ Type st
171
+ Version int
172
+ ConnID uint16
173
+ Timestamp uint32
174
+ TimestampDiff uint32
175
+ WndSize uint32
176
+ SeqNr uint16
177
+ AckNr uint16
178
+ Extensions []extensionField
179
+}
180
+
181
+var (
182
+ mu sync.RWMutex
183
+ logLevel = 0
184
+ artificialPacketDropChance = 0.0
185
+)
186
+
187
+func init() {
188
+ logLevel, _ = strconv.Atoi(os.Getenv("GO_UTP_LOGGING"))
189
+ fmt.Sscanf(os.Getenv("GO_UTP_PACKET_DROP"), "%f", &artificialPacketDropChance)
190
+}
191
+
192
+var (
193
+ errClosed = errors.New("closed")
194
+ errNotImplemented = errors.New("not implemented")
195
+ errTimeout net.Error = timeoutError{"i/o timeout"}
196
+ errAckTimeout = timeoutError{"timed out waiting for ack"}
197
+)
198
+
199
+type timeoutError struct {
200
+ msg string
201
+}
202
+
203
+func (me timeoutError) Timeout() bool { return true }
204
+func (me timeoutError) Error() string { return me.msg }
205
+func (me timeoutError) Temporary() bool { return false }
206
+
207
+func unmarshalExtensions(_type byte, b []byte) (n int, ef []extensionField, err error) {
208
+ for _type != 0 {
209
+ if _type != extensionTypeSelectiveAck {
210
+ // An extension type that is not known to us. Generally we're
211
+ // unmarshalling an packet that isn't actually uTP but we don't
212
+ // yet know for sure until we try to deliver it.
213
+
214
+ // logonce.Stderr.Printf("utp extension %d", _type)
215
+ }
216
+ if len(b) < 2 || len(b) < int(b[1])+2 {
217
+ err = fmt.Errorf("buffer ends prematurely: %x", b)
218
+ return
219
+ }
220
+ ef = append(ef, extensionField{
221
+ Type: _type,
222
+ Bytes: append([]byte{}, b[2:int(b[1])+2]...),
223
+ })
224
+ _type = b[0]
225
+ n += 2 + int(b[1])
226
+ b = b[2+int(b[1]):]
227
+ }
228
+ return
229
+}
230
+
231
+var errInvalidHeader = errors.New("invalid header")
232
+
233
+func (h *header) Unmarshal(b []byte) (n int, err error) {
234
+ h.Type = st(b[0] >> 4)
235
+ h.Version = int(b[0] & 0xf)
236
+ if h.Type > stMax || h.Version != 1 {
237
+ err = errInvalidHeader
238
+ return
239
+ }
240
+ n, h.Extensions, err = unmarshalExtensions(b[1], b[20:])
241
+ if err != nil {
242
+ return
243
+ }
244
+ h.ConnID = binary.BigEndian.Uint16(b[2:4])
245
+ h.Timestamp = binary.BigEndian.Uint32(b[4:8])
246
+ h.TimestampDiff = binary.BigEndian.Uint32(b[8:12])
247
+ h.WndSize = binary.BigEndian.Uint32(b[12:16])
248
+ h.SeqNr = binary.BigEndian.Uint16(b[16:18])
249
+ h.AckNr = binary.BigEndian.Uint16(b[18:20])
250
+ n += 20
251
+ return
252
+}
253
+
254
+func (h *header) Marshal() (ret []byte) {
255
+ hLen := 20 + func() (ret int) {
256
+ for _, ext := range h.Extensions {
257
+ ret += 2 + len(ext.Bytes)
258
+ }
259
+ return
260
+ }()
261
+ ret = sendBufferPool.Get().([]byte)[:hLen:minMTU]
262
+ // ret = make([]byte, hLen, minMTU)
263
+ p := ret // Used for manipulating ret.
264
+ p[0] = byte(h.Type<<4 | 1)
265
+ binary.BigEndian.PutUint16(p[2:4], h.ConnID)
266
+ binary.BigEndian.PutUint32(p[4:8], h.Timestamp)
267
+ binary.BigEndian.PutUint32(p[8:12], h.TimestampDiff)
268
+ binary.BigEndian.PutUint32(p[12:16], h.WndSize)
269
+ binary.BigEndian.PutUint16(p[16:18], h.SeqNr)
270
+ binary.BigEndian.PutUint16(p[18:20], h.AckNr)
271
+ // Pointer to the last type field so the next extension can set it.
272
+ _type := &p[1]
273
+ // We're done with the basic header.
274
+ p = p[20:]
275
+ for _, ext := range h.Extensions {
276
+ *_type = ext.Type
277
+ // The next extension's type will go here.
278
+ _type = &p[0]
279
+ p[1] = uint8(len(ext.Bytes))
280
+ if int(p[1]) != copy(p[2:], ext.Bytes) {
281
+ panic("unexpected extension length")
282
+ }
283
+ p = p[2+len(ext.Bytes):]
284
+ }
285
+ if len(p) != 0 {
286
+ panic("header length changed")
287
+ }
288
+ return
289
+}
290
+
291
+var (
292
+ _ net.Listener = &Socket{}
293
+ _ net.PacketConn = &Socket{}
294
+)
295
+
296
+const (
297
+ csInvalid = iota
298
+ csSynSent
299
+ csConnected
300
+ csDestroy
301
+)
302
+
303
+type st int
304
+
305
+func (me st) String() string {
306
+ switch me {
307
+ case stData:
308
+ return "stData"
309
+ case stFin:
310
+ return "stFin"
311
+ case stState:
312
+ return "stState"
313
+ case stReset:
314
+ return "stReset"
315
+ case stSyn:
316
+ return "stSyn"
317
+ default:
318
+ panic(fmt.Sprintf("%d", me))
319
+ }
320
+}
321
+
322
+const (
323
+ stData st = 0
324
+ stFin = 1
325
+ stState = 2
326
+ stReset = 3
327
+ stSyn = 4
328
+
329
+ // Used for validating packet headers.
330
+ stMax = stSyn
331
+)
332
+
333
+// Conn is a uTP stream and implements net.Conn. It owned by a Socket, which
334
+// handles dispatching packets to and from Conns.
335
+type Conn struct {
336
+ mu sync.Mutex
337
+ event sync.Cond
338
+
339
+ recv_id, send_id uint16
340
+ seq_nr, ack_nr uint16
341
+ lastAck uint16
342
+ lastTimeDiff uint32
343
+ peerWndSize uint32
344
+
345
+ readBuf []byte
346
+
347
+ socket *Socket
348
+ remoteAddr net.Addr
349
+ // The uTP timestamp.
350
+ startTimestamp uint32
351
+ // When the conn was allocated.
352
+ created time.Time
353
+ // Callback to unregister Conn from a parent Socket. Should be called when
354
+ // no more packets will be handled.
355
+ detach func()
356
+
357
+ cs int
358
+ gotFin bool
359
+ sentFin bool
360
+ err error
361
+
362
+ unackedSends []*send
363
+ // Inbound payloads, the first is ack_nr+1.
364
+ inbound []recv
365
+ packetsIn chan packet
366
+ connDeadlines
367
+ latencies []time.Duration
368
+ pendingSendState bool
369
+ destroyed chan struct{}
370
+}
371
+
372
+type send struct {
373
+ acked chan struct{} // Closed with Conn lock.
374
+ payloadSize uint32
375
+ started time.Time
376
+ // This send was skipped in a selective ack.
377
+ resend func()
378
+ timedOut func()
379
+ conn *Conn
380
+
381
+ mu sync.Mutex
382
+ acksSkipped int
383
+ resendTimer *time.Timer
384
+ numResends int
385
+}
386
+
387
+func (s *send) Ack() (latency time.Duration) {
388
+ s.mu.Lock()
389
+ defer s.mu.Unlock()
390
+ s.resendTimer.Stop()
391
+ select {
392
+ case <-s.acked:
393
+ return
394
+ default:
395
+ close(s.acked)
396
+ }
397
+ latency = time.Since(s.started)
398
+ return
399
+}
400
+
401
+type recv struct {
402
+ seen bool
403
+ data []byte
404
+ Type st
405
+}
406
+
407
+var (
408
+ _ net.Conn = &Conn{}
409
+)
410
+
411
+func (c *Conn) age() time.Duration {
412
+ return time.Since(c.created)
413
+}
414
+
415
+func (c *Conn) timestamp() uint32 {
416
+ return nowTimestamp() - c.startTimestamp
417
+}
418
+
419
+func (c *Conn) connected() bool {
420
+ return c.cs == csConnected
421
+}
422
+
423
+// addr is used to create a listening UDP conn which becomes the underlying
424
+// net.PacketConn for the Socket.
425
+func NewSocket(network, addr string) (s *Socket, err error) {
426
+ s = &Socket{
427
+ backlog: make(map[syn]struct{}, backlog),
428
+ reads: make(chan read, 100),
429
+ closing: make(chan struct{}),
430
+
431
+ unusedReads: make(chan read, 100),
432
+ }
433
+ s.event.L = &s.mu
434
+ s.pc, err = net.ListenPacket(network, addr)
435
+ if err != nil {
436
+ return
437
+ }
438
+ go s.reader()
439
+ go s.dispatcher()
440
+ return
441
+}
442
+
443
+func packetDebugString(h *header, payload []byte) string {
444
+ return fmt.Sprintf("%s->%d: %q", h.Type, h.ConnID, payload)
445
+}
446
+
447
+func (s *Socket) reader() {
448
+ defer close(s.reads)
449
+ var b [maxRecvSize]byte
450
+ for {
451
+ if s.pc == nil {
452
+ break
453
+ }
454
+ n, addr, err := s.pc.ReadFrom(b[:])
455
+ if err != nil {
456
+ select {
457
+ case <-s.closing:
458
+ default:
459
+ s.ReadErr = err
460
+ }
461
+ return
462
+ }
463
+ var nilB []byte
464
+ s.reads <- read{append(nilB, b[:n:n]...), addr}
465
+ }
466
+}
467
+
468
+func (s *Socket) unusedRead(read read) {
469
+ unusedReads.Add(1)
470
+ select {
471
+ case s.unusedReads <- read:
472
+ default:
473
+ // Drop the packet.
474
+ }
475
+}
476
+
477
+func stringAddr(s string) net.Addr {
478
+ addr, err := net.ResolveUDPAddr("udp", s)
479
+ if err != nil {
480
+ panic(err)
481
+ }
482
+ return addr
483
+}
484
+
485
+func (s *Socket) pushBacklog(syn syn) {
486
+ if _, ok := s.backlog[syn]; ok {
487
+ return
488
+ }
489
+ for k := range s.backlog {
490
+ if len(s.backlog) < backlog {
491
+ break
492
+ }
493
+ delete(s.backlog, k)
494
+ // A syn is sent on the remote's recv_id, so this is where we can send
495
+ // the reset.
496
+ s.reset(stringAddr(k.addr), k.seq_nr, k.conn_id)
497
+ }
498
+ s.backlog[syn] = struct{}{}
499
+ s.event.Broadcast()
500
+}
501
+
502
+func (s *Socket) dispatcher() {
503
+ for {
504
+ select {
505
+ case read, ok := <-s.reads:
506
+ if !ok {
507
+ return
508
+ }
509
+ if len(read.data) < 20 {
510
+ s.unusedRead(read)
511
+ continue
512
+ }
513
+ s.dispatch(read)
514
+ }
515
+ }
516
+}
517
+
518
+func (s *Socket) dispatch(read read) {
519
+ b := read.data
520
+ addr := read.from
521
+ var h header
522
+ hEnd, err := h.Unmarshal(b)
523
+ if logLevel >= 1 {
524
+ log.Printf("recvd utp msg: %s", packetDebugString(&h, b[hEnd:]))
525
+ }
526
+ if err != nil || h.Type > stMax || h.Version != 1 {
527
+ s.unusedRead(read)
528
+ return
529
+ }
530
+ s.mu.RLock()
531
+ c, ok := s.conns[connKey{resolvedAddrStr(addr.String()), func() (recvID uint16) {
532
+ recvID = h.ConnID
533
+ // If a SYN is resent, its connection ID field will be one lower
534
+ // than we expect.
535
+ if h.Type == stSyn {
536
+ recvID++
537
+ }
538
+ return
539
+ }()}]
540
+ s.mu.RUnlock()
541
+ if ok {
542
+ if h.Type == stSyn {
543
+ if h.ConnID == c.send_id-2 {
544
+ // This is a SYN for connection that cannot exist locally. The
545
+ // connection the remote wants to establish here with the proposed
546
+ // recv_id, already has an existing connection that was dialled
547
+ // *out* from this socket, which is why the send_id is 1 higher,
548
+ // rather than 1 lower than the recv_id.
549
+ log.Print("resetting conflicting syn")
550
+ s.reset(addr, h.SeqNr, h.ConnID)
551
+ return
552
+ } else if h.ConnID != c.send_id {
553
+ panic("bad assumption")
554
+ }
555
+ }
556
+ c.deliver(h, b[hEnd:])
557
+ return
558
+ }
559
+ if h.Type == stSyn {
560
+ if logLevel >= 1 {
561
+ log.Printf("adding SYN to backlog")
562
+ }
563
+ syn := syn{
564
+ seq_nr: h.SeqNr,
565
+ conn_id: h.ConnID,
566
+ addr: addr.String(),
567
+ }
568
+ s.mu.Lock()
569
+ s.pushBacklog(syn)
570
+ s.mu.Unlock()
571
+ return
572
+ } else if h.Type != stReset {
573
+ // This is an unexpected packet. We'll send a reset, but also pass
574
+ // it on.
575
+ // log.Print("resetting unexpected packet")
576
+ // I don't think you can reset on the received packets ConnID if it isn't a SYN, as the send_id will differ in this case.
577
+ s.reset(addr, h.SeqNr, h.ConnID)
578
+ s.reset(addr, h.SeqNr, h.ConnID-1)
579
+ s.reset(addr, h.SeqNr, h.ConnID+1)
580
+ }
581
+ s.unusedRead(read)
582
+}
583
+
584
+// Send a reset in response to a packet with the given header.
585
+func (s *Socket) reset(addr net.Addr, ackNr, connId uint16) {
586
+ go s.writeTo((&header{
587
+ Type: stReset,
588
+ Version: 1,
589
+ ConnID: connId,
590
+ AckNr: ackNr,
591
+ }).Marshal(), addr)
592
+}
593
+
594
+// Attempt to connect to a remote uTP listener, creating a Socket just for
595
+// this connection.
596
+func Dial(addr string) (net.Conn, error) {
597
+ return DialTimeout(addr, 0)
598
+}
599
+
600
+// Same as Dial with a timeout parameter.
601
+func DialTimeout(addr string, timeout time.Duration) (nc net.Conn, err error) {
602
+ s, err := NewSocket("udp", ":0")
603
+ if err != nil {
604
+ return
605
+ }
606
+ return s.DialTimeout(addr, timeout)
607
+
608
+}
609
+
610
+// Return a recv_id that should be free. Handling the case where it isn't is
611
+// deferred to a more appropriate function.
612
+func (s *Socket) newConnID(remoteAddr resolvedAddrStr) (id uint16) {
613
+ // Rather than use math.Rand, which requires generating all the IDs up
614
+ // front and allocating a slice, we do it on the stack, generating the IDs
615
+ // only as required. To do this, we use the fact that the array is
616
+ // default-initialized. IDs that are 0, are actually their index in the
617
+ // array. IDs that are non-zero, are +1 from their intended ID.
618
+ var idsBack [0x10000]int
619
+ ids := idsBack[:]
620
+ for len(ids) != 0 {
621
+ // Pick the next ID from the untried ids.
622
+ i := rand.Intn(len(ids))
623
+ id = uint16(ids[i])
624
+ // If it's zero, then treat it as though the index i was the ID.
625
+ // Otherwise the value we get is the ID+1.
626
+ if id == 0 {
627
+ id = uint16(i)
628
+ } else {
629
+ id--
630
+ }
631
+ // Check there's no connection using this ID for its recv_id...
632
+ _, ok1 := s.conns[connKey{remoteAddr, id}]
633
+ // and if we're connecting to our own Socket, that there isn't a Conn
634
+ // already receiving on what will correspond to our send_id. Note that
635
+ // we just assume that we could be connecting to our own Socket. This
636
+ // will halve the available connection IDs to each distinct remote
637
+ // address. Presumably that's ~0x8000, down from ~0x10000.
638
+ _, ok2 := s.conns[connKey{remoteAddr, id + 1}]
639
+ _, ok4 := s.conns[connKey{remoteAddr, id - 1}]
640
+ if !ok1 && !ok2 && !ok4 {
641
+ return
642
+ }
643
+ // The set of possible IDs is shrinking. The highest one will be lost, so
644
+ // it's moved to the location of the one we just tried.
645
+ ids[i] = len(ids) // Conveniently already +1.
646
+ // And shrink.
647
+ ids = ids[:len(ids)-1]
648
+ }
649
+ return
650
+}
651
+
652
+func (c *Conn) sendPendingState() {
653
+ if !c.pendingSendState {
654
+ return
655
+ }
656
+ c.sendState()
657
+}
658
+
659
+func (s *Socket) newConn(addr net.Addr) (c *Conn) {
660
+ c = &Conn{
661
+ socket: s,
662
+ remoteAddr: addr,
663
+ startTimestamp: nowTimestamp(),
664
+ created: time.Now(),
665
+ packetsIn: make(chan packet, 100),
666
+ destroyed: make(chan struct{}),
667
+ }
668
+ c.event.L = &c.mu
669
+ c.mu.Lock()
670
+ c.connDeadlines.read.setCallback(func() {
671
+ c.mu.Lock()
672
+ c.event.Broadcast()
673
+ c.mu.Unlock()
674
+ })
675
+ c.connDeadlines.write.setCallback(func() {
676
+ c.mu.Lock()
677
+ c.event.Broadcast()
678
+ c.mu.Unlock()
679
+ })
680
+ c.mu.Unlock()
681
+ go c.deliveryProcessor()
682
+ return
683
+}
684
+
685
+func (s *Socket) Dial(addr string) (net.Conn, error) {
686
+ return s.DialTimeout(addr, 0)
687
+}
688
+
689
+func (s *Socket) DialTimeout(addr string, timeout time.Duration) (nc net.Conn, err error) {
690
+ netAddr, err := net.ResolveUDPAddr("udp", addr)
691
+ if err != nil {
692
+ return
693
+ }
694
+
695
+ s.mu.Lock()
696
+ c := s.newConn(netAddr)
697
+ c.recv_id = s.newConnID(resolvedAddrStr(netAddr.String()))
698
+ c.send_id = c.recv_id + 1
699
+ if logLevel >= 1 {
700
+ log.Printf("dial registering addr: %s", netAddr.String())
701
+ }
702
+ if !s.registerConn(c.recv_id, resolvedAddrStr(netAddr.String()), c) {
703
+ err = errors.New("couldn't register new connection")
704
+ log.Println(c.recv_id, netAddr.String())
705
+ for k, c := range s.conns {
706
+ log.Println(k, c, c.age())
707
+ }
708
+ log.Printf("that's %d connections", len(s.conns))
709
+ }
710
+ s.mu.Unlock()
711
+ if err != nil {
712
+ return
713
+ }
714
+
715
+ connErr := make(chan error, 1)
716
+ go func() {
717
+ connErr <- c.connect()
718
+ }()
719
+ var timeoutCh <-chan time.Time
720
+ if timeout != 0 {
721
+ timeoutCh = time.After(timeout)
722
+ }
723
+ select {
724
+ case err = <-connErr:
725
+ case <-timeoutCh:
726
+ c.Close()
727
+ err = errTimeout
728
+ }
729
+ if err == nil {
730
+ nc = c
731
+ }
732
+ return
733
+}
734
+
735
+func (c *Conn) wndSize() uint32 {
736
+ if len(c.inbound) > maxUnackedInbound/2 {
737
+ return 0
738
+ }
739
+ var buffered int
740
+ for _, r := range c.inbound {
741
+ buffered += len(r.data)
742
+ }
743
+ buffered += len(c.readBuf)
744
+ if buffered >= recvWindow {
745
+ return 0
746
+ }
747
+ return recvWindow - uint32(buffered)
748
+}
749
+
750
+func nowTimestamp() uint32 {
751
+ return uint32(time.Now().UnixNano() / int64(time.Microsecond))
752
+}
753
+
754
+// Send the given payload with an up to date header.
755
+func (c *Conn) send(_type st, connID uint16, payload []byte, seqNr uint16) (err error) {
756
+ // Always selectively ack the first 64 packets. Don't bother with rest for
757
+ // now.
758
+ selAck := selectiveAckBitmask(make([]byte, 8))
759
+ for i := 1; i < 65; i++ {
760
+ if len(c.inbound) <= i {
761
+ break
762
+ }
763
+ if c.inbound[i].seen {
764
+ selAck.SetBit(i - 1)
765
+ }
766
+ }
767
+ h := header{
768
+ Type: _type,
769
+ Version: 1,
770
+ ConnID: connID,
771
+ SeqNr: seqNr,
772
+ AckNr: c.ack_nr,
773
+ WndSize: c.wndSize(),
774
+ Timestamp: c.timestamp(),
775
+ TimestampDiff: c.lastTimeDiff,
776
+ // Currently always send an 8 byte selective ack.
777
+ Extensions: []extensionField{{
778
+ Type: extensionTypeSelectiveAck,
779
+ Bytes: selAck,
780
+ }},
781
+ }
782
+ p := h.Marshal()
783
+ // Extension headers are currently fixed in size.
784
+ if len(p) != maxHeaderSize {
785
+ panic("header has unexpected size")
786
+ }
787
+ p = append(p, payload...)
788
+ if logLevel >= 1 {
789
+ log.Printf("writing utp msg to %s: %s", c.remoteAddr, packetDebugString(&h, payload))
790
+ }
791
+ n1, err := c.socket.writeTo(p, c.remoteAddr)
792
+ if err != nil {
793
+ return
794
+ }
795
+ if n1 != len(p) {
796
+ panic(n1)
797
+ }
798
+ c.unpendSendState()
799
+ return
800
+}
801
+
802
+func (me *Conn) unpendSendState() {
803
+ me.pendingSendState = false
804
+}
805
+
806
+func (c *Conn) pendSendState() {
807
+ c.pendingSendState = true
808
+}
809
+
810
+func (me *Socket) writeTo(b []byte, addr net.Addr) (n int, err error) {
811
+ mu.RLock()
812
+ apdc := artificialPacketDropChance
813
+ mu.RUnlock()
814
+ if apdc != 0 {
815
+ if rand.Float64() < apdc {
816
+ n = len(b)
817
+ return
818
+ }
819
+ }
820
+ n, err = me.pc.WriteTo(b, addr)
821
+ return
822
+}
823
+
824
+func (s *send) timeoutResend() {
825
+ select {
826
+ case <-s.acked:
827
+ return
828
+ default:
829
+ }
830
+ if time.Since(s.started) >= sendTimeout {
831
+ s.timedOut()
832
+ return
833
+ }
834
+ s.conn.mu.Lock()
835
+ rt := s.conn.resendTimeout()
836
+ s.conn.mu.Unlock()
837
+ go s.resend()
838
+ s.mu.Lock()
839
+ s.numResends++
840
+ s.resendTimer.Reset(rt)
841
+ s.mu.Unlock()
842
+}
843
+
844
+func (me *Conn) writeSyn() (err error) {
845
+ if me.cs != csInvalid {
846
+ panic(me.cs)
847
+ }
848
+ _, err = me.write(stSyn, me.recv_id, nil, me.seq_nr)
849
+ return
850
+}
851
+
852
+func (c *Conn) write(_type st, connID uint16, payload []byte, seqNr uint16) (n int, err error) {
853
+ switch _type {
854
+ case stSyn, stFin, stData:
855
+ default:
856
+ panic(_type)
857
+ }
858
+ switch c.cs {
859
+ case csConnected, csSynSent, csInvalid:
860
+ default:
861
+ panic(c.cs)
862
+ }
863
+ if c.sentFin {
864
+ panic(c)
865
+ }
866
+ if len(payload) > maxPayloadSize {
867
+ payload = payload[:maxPayloadSize]
868
+ }
869
+ err = c.send(_type, connID, payload, seqNr)
870
+ if err != nil {
871
+ return
872
+ }
873
+ n = len(payload)
874
+ // Copy payload so caller to write can continue to use the buffer.
875
+ if payload != nil {
876
+ payload = append(sendBufferPool.Get().([]byte)[:0:minMTU], payload...)
877
+ }
878
+ send := &send{
879
+ acked: make(chan struct{}),
880
+ payloadSize: uint32(len(payload)),
881
+ started: time.Now(),
882
+ resend: func() {
883
+ c.mu.Lock()
884
+ err := c.send(_type, connID, payload, seqNr)
885
+ if err != nil {
886
+ log.Printf("error resending packet: %s", err)
887
+ }
888
+ c.mu.Unlock()
889
+ },
890
+ timedOut: func() {
891
+ c.mu.Lock()
892
+ c.destroy(errAckTimeout)
893
+ c.mu.Unlock()
894
+ },
895
+ conn: c,
896
+ }
897
+ send.mu.Lock()
898
+ send.resendTimer = time.AfterFunc(c.resendTimeout(), send.timeoutResend)
899
+ send.mu.Unlock()
900
+ c.unackedSends = append(c.unackedSends, send)
901
+ c.seq_nr++
902
+ return
903
+}
904
+
905
+func (c *Conn) latency() (ret time.Duration) {
906
+ if len(c.latencies) == 0 {
907
+ // Sort of the p95 of latencies?
908
+ return 200 * time.Millisecond
909
+ }
910
+ for _, l := range c.latencies {
911
+ ret += l
912
+ }
913
+ ret = (ret + time.Duration(len(c.latencies)) - 1) / time.Duration(len(c.latencies))
914
+ return
915
+}
916
+
917
+func (c *Conn) numUnackedSends() (num int) {
918
+ for _, s := range c.unackedSends {
919
+ select {
920
+ case <-s.acked:
921
+ default:
922
+ num++
923
+ }
924
+ }
925
+ return
926
+}
927
+
928
+func (c *Conn) cur_window() (window uint32) {
929
+ for _, s := range c.unackedSends {
930
+ select {
931
+ case <-s.acked:
932
+ default:
933
+ window += s.payloadSize
934
+ }
935
+ }
936
+ return
937
+}
938
+
939
+func (c *Conn) sendState() {
940
+ c.send(stState, c.send_id, nil, c.seq_nr)
941
+ sentStatePackets.Add(1)
942
+}
943
+
944
+func seqLess(a, b uint16) bool {
945
+ if b < 0x8000 {
946
+ return a < b || a >= b-0x8000
947
+ } else {
948
+ return a < b && a >= b-0x8000
949
+ }
950
+}
951
+
952
+// Ack our send with the given sequence number.
953
+func (c *Conn) ack(nr uint16) {
954
+ if !seqLess(c.lastAck, nr) {
955
+ // Already acked.
956
+ return
957
+ }
958
+ i := nr - c.lastAck - 1
959
+ if int(i) >= len(c.unackedSends) {
960
+ log.Printf("got ack ahead of syn (%x > %x)", nr, c.seq_nr-1)
961
+ return
962
+ }
963
+ latency := c.unackedSends[i].Ack()
964
+ if latency != 0 {
965
+ c.latencies = append(c.latencies, latency)
966
+ if len(c.latencies) > 10 {
967
+ c.latencies = c.latencies[len(c.latencies)-10:]
968
+ }
969
+ }
970
+ for {
971
+ if len(c.unackedSends) == 0 {
972
+ break
973
+ }
974
+ select {
975
+ case <-c.unackedSends[0].acked:
976
+ default:
977
+ // Can't trim unacked sends any further.
978
+ return
979
+ }
980
+ // Trim the front of the unacked sends.
981
+ c.unackedSends = c.unackedSends[1:]
982
+ c.lastAck++
983
+ }
984
+ c.event.Broadcast()
985
+}
986
+
987
+func (c *Conn) ackTo(nr uint16) {
988
+ if !seqLess(nr, c.seq_nr) {
989
+ return
990
+ }
991
+ for seqLess(c.lastAck, nr) {
992
+ c.ack(c.lastAck + 1)
993
+ }
994
+}
995
+
996
+type selectiveAckBitmask []byte
997
+
998
+func (me selectiveAckBitmask) NumBits() int {
999
+ return len(me) * 8
1000
+}
1001
+
1002
+func (me selectiveAckBitmask) SetBit(index int) {
1003
+ me[index/8] |= 1 << uint(index%8)
1004
+}
1005
+
1006
+func (me selectiveAckBitmask) BitIsSet(index int) bool {
1007
+ return me[index/8]>>uint(index%8)&1 == 1
1008
+}
1009
+
1010
+// Return the send state for the sequence number. Returns nil if there's no
1011
+// outstanding send for that sequence number.
1012
+func (c *Conn) seqSend(seqNr uint16) *send {
1013
+ if !seqLess(c.lastAck, seqNr) {
1014
+ // Presumably already acked.
1015
+ return nil
1016
+ }
1017
+ i := int(seqNr - c.lastAck - 1)
1018
+ if i >= len(c.unackedSends) {
1019
+ // No such send.
1020
+ return nil
1021
+ }
1022
+ return c.unackedSends[i]
1023
+}
1024
+
1025
+func (c *Conn) resendTimeout() time.Duration {
1026
+ l := c.latency()
1027
+ if l < 10*time.Millisecond {
1028
+ l = 10 * time.Millisecond
1029
+ }
1030
+ ret := jitter.Duration(3*l, l)
1031
+ // log.Print(ret)
1032
+ return ret
1033
+}
1034
+
1035
+func (c *Conn) ackSkipped(seqNr uint16) {
1036
+ send := c.seqSend(seqNr)
1037
+ if send == nil {
1038
+ return
1039
+ }
1040
+ send.mu.Lock()
1041
+ defer send.mu.Unlock()
1042
+ send.acksSkipped++
1043
+ switch send.acksSkipped {
1044
+ case 3, 60:
1045
+ ackSkippedResends.Add(1)
1046
+ go send.resend()
1047
+ send.resendTimer.Reset(c.resendTimeout())
1048
+ default:
1049
+ }
1050
+}
1051
+
1052
+type packet struct {
1053
+ h header
1054
+ payload []byte
1055
+}
1056
+
1057
+func (c *Conn) deliver(h header, payload []byte) {
1058
+ c.packetsIn <- packet{h, payload}
1059
+}
1060
+
1061
+func (c *Conn) deliveryProcessor() {
1062
+ for {
1063
+ select {
1064
+ case p := <-c.packetsIn:
1065
+ c.processDelivery(p.h, p.payload)
1066
+ timeout := time.After(500 * time.Microsecond)
1067
+ batched:
1068
+ for {
1069
+ select {
1070
+ case p := <-c.packetsIn:
1071
+ c.processDelivery(p.h, p.payload)
1072
+ case <-timeout:
1073
+ break batched
1074
+ }
1075
+ }
1076
+ c.mu.Lock()
1077
+ c.sendPendingState()
1078
+ c.mu.Unlock()
1079
+ case <-c.destroyed:
1080
+ return
1081
+ }
1082
+ }
1083
+}
1084
+
1085
+func (c *Conn) processDelivery(h header, payload []byte) {
1086
+ deliveriesProcessed.Add(1)
1087
+ c.mu.Lock()
1088
+ defer c.mu.Unlock()
1089
+ defer c.event.Broadcast()
1090
+ c.assertHeader(h)
1091
+ c.peerWndSize = h.WndSize
1092
+ c.applyAcks(h)
1093
+ if h.Timestamp == 0 {
1094
+ c.lastTimeDiff = 0
1095
+ } else {
1096
+ c.lastTimeDiff = c.timestamp() - h.Timestamp
1097
+ }
1098
+
1099
+ // We want this connection destroyed, and our peer has acked everything.
1100
+ if c.sentFin && len(c.unackedSends) == 0 {
1101
+ // log.Print("gracefully completed")
1102
+ c.destroy(nil)
1103
+ return
1104
+ }
1105
+ if h.Type == stReset {
1106
+ c.destroy(errors.New("peer reset"))
1107
+ return
1108
+ }
1109
+ if c.cs == csSynSent {
1110
+ if h.Type != stState {
1111
+ return
1112
+ }
1113
+ c.changeState(csConnected)
1114
+ c.ack_nr = h.SeqNr - 1
1115
+ return
1116
+ }
1117
+ if h.Type == stState {
1118
+ return
1119
+ }
1120
+ c.pendSendState()
1121
+ if !seqLess(c.ack_nr, h.SeqNr) {
1122
+ // Already received this packet.
1123
+ return
1124
+ }
1125
+ inboundIndex := int(h.SeqNr - c.ack_nr - 1)
1126
+ if inboundIndex < len(c.inbound) && c.inbound[inboundIndex].seen {
1127
+ // Already received this packet.
1128
+ return
1129
+ }
1130
+ // Derived from running in production:
1131
+ // grep -oP '(?<=packet out of order, index=)\d+' log | sort -n | uniq -c
1132
+ // 64 should correspond to 8 bytes of selective ack.
1133
+ if inboundIndex >= maxUnackedInbound {
1134
+ // Discard packet too far ahead.
1135
+ if missinggo.CryHeard() {
1136
+ // I can't tell if this occurs due to bad peers, or something
1137
+ // missing in the implementation.
1138
+ log.Printf("received packet from %s %d ahead of next seqnr (%x > %x)", c.remoteAddr, inboundIndex, h.SeqNr, c.ack_nr+1)
1139
+ }
1140
+ return
1141
+ }
1142
+ // Extend inbound so the new packet has a place.
1143
+ for inboundIndex >= len(c.inbound) {
1144
+ c.inbound = append(c.inbound, recv{})
1145
+ }
1146
+ c.inbound[inboundIndex] = recv{true, payload, h.Type}
1147
+ c.processInbound()
1148
+}
1149
+
1150
+func (c *Conn) applyAcks(h header) {
1151
+ c.ackTo(h.AckNr)
1152
+ for _, ext := range h.Extensions {
1153
+ switch ext.Type {
1154
+ case extensionTypeSelectiveAck:
1155
+ c.ackSkipped(h.AckNr + 1)
1156
+ bitmask := selectiveAckBitmask(ext.Bytes)
1157
+ for i := 0; i < bitmask.NumBits(); i++ {
1158
+ if bitmask.BitIsSet(i) {
1159
+ nr := h.AckNr + 2 + uint16(i)
1160
+ // log.Printf("selectively acked %d", nr)
1161
+ c.ack(nr)
1162
+ } else {
1163
+ c.ackSkipped(h.AckNr + 2 + uint16(i))
1164
+ }
1165
+ }
1166
+ }
1167
+ }
1168
+}
1169
+
1170
+func (c *Conn) assertHeader(h header) {
1171
+ if h.Type == stSyn {
1172
+ if h.ConnID != c.send_id {
1173
+ panic(fmt.Sprintf("%d != %d", h.ConnID, c.send_id))
1174
+ }
1175
+ } else {
1176
+ if h.ConnID != c.recv_id {
1177
+ panic("erroneous delivery")
1178
+ }
1179
+ }
1180
+}
1181
+
1182
+func (c *Conn) processInbound() {
1183
+ // Consume consecutive next packets.
1184
+ for !c.gotFin && len(c.inbound) > 0 && c.inbound[0].seen {
1185
+ c.ack_nr++
1186
+ p := c.inbound[0]
1187
+ c.inbound = c.inbound[1:]
1188
+ c.readBuf = append(c.readBuf, p.data...)
1189
+ if p.Type == stFin {
1190
+ c.gotFin = true
1191
+ }
1192
+ }
1193
+}
1194
+
1195
+func (c *Conn) waitAck(seq uint16) {
1196
+ send := c.seqSend(seq)
1197
+ if send == nil {
1198
+ return
1199
+ }
1200
+ c.mu.Unlock()
1201
+ defer c.mu.Lock()
1202
+ <-send.acked
1203
+ return
1204
+}
1205
+
1206
+func (c *Conn) changeState(cs int) {
1207
+ // log.Println(c, "goes", c.cs, "->", cs)
1208
+ c.cs = cs
1209
+}
1210
+
1211
+func (c *Conn) connect() error {
1212
+ c.mu.Lock()
1213
+ defer c.mu.Unlock()
1214
+ c.seq_nr = 1
1215
+ err := c.writeSyn()
1216
+ if err != nil {
1217
+ return err
1218
+ }
1219
+ c.changeState(csSynSent)
1220
+ if logLevel >= 2 {
1221
+ log.Printf("sent syn")
1222
+ }
1223
+ // c.seq_nr++
1224
+ c.waitAck(1)
1225
+ if c.err != nil {
1226
+ err = c.err
1227
+ }
1228
+ c.event.Broadcast()
1229
+ return err
1230
+}
1231
+
1232
+// Returns true if the connection was newly registered, false otherwise.
1233
+func (s *Socket) registerConn(recvID uint16, remoteAddr resolvedAddrStr, c *Conn) bool {
1234
+ if s.conns == nil {
1235
+ s.conns = make(map[connKey]*Conn)
1236
+ }
1237
+ key := connKey{remoteAddr, recvID}
1238
+ if _, ok := s.conns[key]; ok {
1239
+ return false
1240
+ }
1241
+ s.conns[key] = c
1242
+ c.detach = func() {
1243
+ s.mu.Lock()
1244
+ defer s.mu.Unlock()
1245
+ defer s.event.Broadcast()
1246
+ if s.conns[key] != c {
1247
+ panic("conn changed")
1248
+ }
1249
+ // log.Println("detached", key)
1250
+ delete(s.conns, key)
1251
+ if len(s.conns) == 0 {
1252
+ s.pc.Close()
1253
+ }
1254
+ }
1255
+ return true
1256
+}
1257
+
1258
+func (s *Socket) nextSyn() (syn syn, ok bool) {
1259
+ s.mu.Lock()
1260
+ defer s.mu.Unlock()
1261
+ for {
1262
+ for k := range s.backlog {
1263
+ syn = k
1264
+ delete(s.backlog, k)
1265
+ ok = true
1266
+ return
1267
+ }
1268
+ select {
1269
+ case <-s.closing:
1270
+ return
1271
+ default:
1272
+ }
1273
+ s.event.Wait()
1274
+ }
1275
+}
1276
+
1277
+// Accept and return a new uTP connection.
1278
+func (s *Socket) Accept() (c net.Conn, err error) {
1279
+ for {
1280
+ syn, ok := s.nextSyn()
1281
+ if !ok {
1282
+ err = errClosed
1283
+ return
1284
+ }
1285
+ s.mu.Lock()
1286
+ _c := s.newConn(stringAddr(syn.addr))
1287
+ _c.send_id = syn.conn_id
1288
+ _c.recv_id = _c.send_id + 1
1289
+ _c.seq_nr = uint16(rand.Int())
1290
+ _c.lastAck = _c.seq_nr - 1
1291
+ _c.ack_nr = syn.seq_nr
1292
+ _c.cs = csConnected
1293
+ if !s.registerConn(_c.recv_id, resolvedAddrStr(syn.addr), _c) {
1294
+ // SYN that triggered this accept duplicates existing connection.
1295
+ // Ack again in case the SYN was a resend.
1296
+ _c = s.conns[connKey{resolvedAddrStr(syn.addr), _c.recv_id}]
1297
+ if _c.send_id != syn.conn_id {
1298
+ panic(":|")
1299
+ }
1300
+ _c.sendState()
1301
+ s.mu.Unlock()
1302
+ continue
1303
+ }
1304
+ _c.sendState()
1305
+ // _c.seq_nr++
1306
+ c = _c
1307
+ s.mu.Unlock()
1308
+ return
1309
+ }
1310
+}
1311
+
1312
+// The address we're listening on for new uTP connections.
1313
+func (s *Socket) Addr() net.Addr {
1314
+ return s.pc.LocalAddr()
1315
+}
1316
+
1317
+// Marks the Socket for close. Currently this just axes the underlying OS
1318
+// socket.
1319
+func (s *Socket) Close() (err error) {
1320
+ s.mu.Lock()
1321
+ defer s.mu.Unlock()
1322
+ select {
1323
+ case <-s.closing:
1324
+ return
1325
+ default:
1326
+ }
1327
+ s.event.Broadcast()
1328
+ close(s.closing)
1329
+ if len(s.conns) == 0 {
1330
+ err = s.pc.Close()
1331
+ }
1332
+ return
1333
+}
1334
+
1335
+func (s *Socket) LocalAddr() net.Addr {
1336
+ return s.pc.LocalAddr()
1337
+}
1338
+
1339
+func (s *Socket) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
1340
+ read, ok := <-s.unusedReads
1341
+ if !ok {
1342
+ err = io.EOF
1343
+ }
1344
+ n = copy(p, read.data)
1345
+ addr = read.from
1346
+ return
1347
+}
1348
+
1349
+func (s *Socket) WriteTo(b []byte, addr net.Addr) (int, error) {
1350
+ return s.pc.WriteTo(b, addr)
1351
+}
1352
+
1353
+func (c *Conn) writeFin() (err error) {
1354
+ if c.sentFin {
1355
+ return
1356
+ }
1357
+ _, err = c.write(stFin, c.send_id, nil, c.seq_nr)
1358
+ if err != nil {
1359
+ return
1360
+ }
1361
+ c.sentFin = true
1362
+ c.event.Broadcast()
1363
+ return
1364
+}
1365
+
1366
+func (c *Conn) destroy(reason error) {
1367
+ if c.err != nil && reason != nil {
1368
+ log.Printf("duplicate destroy call: %s", reason)
1369
+ }
1370
+ if c.cs == csDestroy {
1371
+ return
1372
+ }
1373
+ close(c.destroyed)
1374
+ c.writeFin()
1375
+ c.changeState(csDestroy)
1376
+ c.err = reason
1377
+ c.event.Broadcast()
1378
+ c.detach()
1379
+ for _, s := range c.unackedSends {
1380
+ s.Ack()
1381
+ }
1382
+}
1383
+
1384
+func (c *Conn) Close() error {
1385
+ c.mu.Lock()
1386
+ defer c.mu.Unlock()
1387
+ return c.writeFin()
1388
+}
1389
+
1390
+func (c *Conn) LocalAddr() net.Addr {
1391
+ return c.socket.Addr()
1392
+}
1393
+
1394
+func (c *Conn) Read(b []byte) (n int, err error) {
1395
+ c.mu.Lock()
1396
+ defer c.mu.Unlock()
1397
+ for {
1398
+ if len(c.readBuf) != 0 {
1399
+ break
1400
+ }
1401
+ if c.cs == csDestroy || c.gotFin || c.sentFin {
1402
+ err = c.err
1403
+ if err == nil {
1404
+ err = io.EOF
1405
+ }
1406
+ return
1407
+ }
1408
+ if c.connDeadlines.read.deadlineExceeded() {
1409
+ err = errTimeout
1410
+ return
1411
+ }
1412
+ if logLevel >= 2 {
1413
+ log.Printf("nothing to read, state=%d", c.cs)
1414
+ }
1415
+ c.event.Wait()
1416
+ }
1417
+ n = copy(b, c.readBuf)
1418
+ c.readBuf = c.readBuf[n:]
1419
+
1420
+ return
1421
+}
1422
+
1423
+func (c *Conn) RemoteAddr() net.Addr {
1424
+ return c.remoteAddr
1425
+}
1426
+
1427
+func (c *Conn) String() string {
1428
+ return fmt.Sprintf("<UTPConn %s-%s (%d)>", c.LocalAddr(), c.RemoteAddr(), c.recv_id)
1429
+}
1430
+
1431
+func (c *Conn) Write(p []byte) (n int, err error) {
1432
+ c.mu.Lock()
1433
+ defer c.mu.Unlock()
1434
+ for len(p) != 0 {
1435
+ for {
1436
+ if c.sentFin {
1437
+ err = io.ErrClosedPipe
1438
+ return
1439
+ }
1440
+ // If peerWndSize is 0, we still want to send something, so don't
1441
+ // block until we exceed it.
1442
+ if c.cur_window() <= c.peerWndSize && len(c.unackedSends) < 64 && c.cs == csConnected {
1443
+ break
1444
+ }
1445
+ if c.connDeadlines.write.deadlineExceeded() {
1446
+ err = errTimeout
1447
+ return
1448
+ }
1449
+ c.event.Wait()
1450
+ }
1451
+ var n1 int
1452
+ n1, err = c.write(stData, c.send_id, p, c.seq_nr)
1453
+ if err != nil {
1454
+ return
1455
+ }
1456
+ // c.seq_nr++
1457
+ n += n1
1458
+ p = p[n1:]
1459
+ }
1460
+ return
1461
+}
Godeps/_workspace/src/github.com/anacrolix/utp/utp_test.go
new
+411
@@ -0,0 +1,411 @@
1
+package utp
2
+
3
+import (
4
+ "fmt"
5
+ "io"
6
+ "io/ioutil"
7
+ "log"
8
+ "net"
9
+ "runtime"
10
+ "sync"
11
+ "testing"
12
+ "time"
13
+
14
+ _ "github.com/anacrolix/envpprof"
15
+ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/anacrolix/missinggo"
16
+ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/bradfitz/iter"
17
+ "github.com/stretchr/testify/require"
18
+)
19
+
20
+func init() {
21
+ log.SetFlags(log.Flags() | log.Lshortfile)
22
+}
23
+
24
+func TestUTPPingPong(t *testing.T) {
25
+ defer goroutineLeakCheck(t)()
26
+ s, err := NewSocket("udp", "localhost:0")
27
+ require.NoError(t, err)
28
+ defer s.Close()
29
+ pingerClosed := make(chan struct{})
30
+ go func() {
31
+ defer close(pingerClosed)
32
+ b, err := Dial(s.Addr().String())
33
+ require.NoError(t, err)
34
+ defer b.Close()
35
+ n, err := b.Write([]byte("ping"))
36
+ require.NoError(t, err)
37
+ require.EqualValues(t, 4, n)
38
+ buf := make([]byte, 4)
39
+ b.Read(buf)
40
+ require.EqualValues(t, "pong", buf)
41
+ log.Printf("got pong")
42
+ }()
43
+ a, err := s.Accept()
44
+ require.NoError(t, err)
45
+ defer a.Close()
46
+ log.Printf("accepted %s", a)
47
+ buf := make([]byte, 42)
48
+ n, err := a.Read(buf)
49
+ require.NoError(t, err)
50
+ require.EqualValues(t, "ping", buf[:n])
51
+ log.Print("got ping")
52
+ n, err = a.Write([]byte("pong"))
53
+ require.NoError(t, err)
54
+ require.Equal(t, 4, n)
55
+ log.Print("waiting for pinger to close")
56
+ <-pingerClosed
57
+}
58
+
59
+func goroutineLeakCheck(t testing.TB) func() {
60
+ if !testing.Verbose() {
61
+ return func() {}
62
+ }
63
+ numStart := runtime.NumGoroutine()
64
+ return func() {
65
+ var numNow int
66
+ for range iter.N(1) {
67
+ numNow = runtime.NumGoroutine()
68
+ if numNow == numStart {
69
+ return
70
+ }
71
+ time.Sleep(10 * time.Millisecond)
72
+ }
73
+ // I'd print stacks, or treat this as fatal, but I think
74
+ // runtime.NumGoroutine is including system routines for which we are
75
+ // not provided the stacks, and are spawned unpredictably.
76
+ t.Logf("have %d goroutines, started with %d", numNow, numStart)
77
+ }
78
+}
79
+
80
+func TestDialTimeout(t *testing.T) {
81
+ defer goroutineLeakCheck(t)()
82
+ s, _ := NewSocket("udp", "localhost:0")
83
+ defer s.Close()
84
+ conn, err := DialTimeout(s.Addr().String(), 10*time.Millisecond)
85
+ if err == nil {
86
+ conn.Close()
87
+ t.Fatal("expected timeout")
88
+ }
89
+ t.Log(err)
90
+}
91
+
92
+func TestMinMaxHeaderType(t *testing.T) {
93
+ require.Equal(t, stSyn, stMax)
94
+}
95
+
96
+func TestUTPRawConn(t *testing.T) {
97
+ l, err := NewSocket("udp", "")
98
+ require.NoError(t, err)
99
+ defer l.Close()
100
+ go func() {
101
+ for {
102
+ _, err := l.Accept()
103
+ if err != nil {
104
+ break
105
+ }
106
+ }
107
+ }()
108
+ // Connect a UTP peer to see if the RawConn will still work.
109
+ log.Print("dialing")
110
+ utpPeer := func() net.Conn {
111
+ s, _ := NewSocket("udp", "")
112
+ defer s.Close()
113
+ ret, err := s.Dial(fmt.Sprintf("localhost:%d", missinggo.AddrPort(l.Addr())))
114
+ require.NoError(t, err)
115
+ return ret
116
+ }()
117
+ log.Print("dial returned")
118
+ if err != nil {
119
+ t.Fatalf("error dialing utp listener: %s", err)
120
+ }
121
+ defer utpPeer.Close()
122
+ peer, err := net.ListenPacket("udp", ":0")
123
+ if err != nil {
124
+ t.Fatal(err)
125
+ }
126
+ defer peer.Close()
127
+
128
+ msgsReceived := 0
129
+ const N = 5000 // How many messages to send.
130
+ readerStopped := make(chan struct{})
131
+ // The reader goroutine.
132
+ go func() {
133
+ defer close(readerStopped)
134
+ b := make([]byte, 500)
135
+ for i := 0; i < N; i++ {
136
+ n, _, err := l.ReadFrom(b)
137
+ if err != nil {
138
+ t.Fatalf("error reading from raw conn: %s", err)
139
+ }
140
+ msgsReceived++
141
+ var d int
142
+ fmt.Sscan(string(b[:n]), &d)
143
+ if d != i {
144
+ log.Printf("got wrong number: expected %d, got %d", i, d)
145
+ }
146
+ }
147
+ }()
148
+ udpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("localhost:%d", missinggo.AddrPort(l.Addr())))
149
+ if err != nil {
150
+ t.Fatal(err)
151
+ }
152
+ for i := 0; i < N; i++ {
153
+ _, err := peer.WriteTo([]byte(fmt.Sprintf("%d", i)), udpAddr)
154
+ if err != nil {
155
+ t.Fatal(err)
156
+ }
157
+ time.Sleep(time.Microsecond)
158
+ }
159
+ select {
160
+ case <-readerStopped:
161
+ case <-time.After(time.Second):
162
+ t.Fatal("reader timed out")
163
+ }
164
+ if msgsReceived != N {
165
+ t.Fatalf("messages received: %d", msgsReceived)
166
+ }
167
+}
168
+
169
+func TestConnReadDeadline(t *testing.T) {
170
+ ls, _ := NewSocket("udp", "localhost:0")
171
+ ds, _ := NewSocket("udp", "localhost:0")
172
+ dcReadErr := make(chan error)
173
+ go func() {
174
+ c, _ := ds.Dial(ls.Addr().String())
175
+ defer c.Close()
176
+ _, err := c.Read(nil)
177
+ dcReadErr <- err
178
+ }()
179
+ c, _ := ls.Accept()
180
+ dl := time.Now().Add(time.Millisecond)
181
+ c.SetReadDeadline(dl)
182
+ _, err := c.Read(nil)
183
+ require.Equal(t, errTimeout, err)
184
+ // The deadline has passed.
185
+ if !time.Now().After(dl) {
186
+ t.FailNow()
187
+ }
188
+ // Returns timeout on subsequent read.
189
+ _, err = c.Read(nil)
190
+ require.Equal(t, errTimeout, err)
191
+ // Disable the deadline.
192
+ c.SetReadDeadline(time.Time{})
193
+ readReturned := make(chan struct{})
194
+ go func() {
195
+ c.Read(nil)
196
+ close(readReturned)
197
+ }()
198
+ select {
199
+ case <-readReturned:
200
+ // Read returned but shouldn't have.
201
+ t.FailNow()
202
+ case <-time.After(time.Millisecond):
203
+ }
204
+ c.Close()
205
+ select {
206
+ case <-readReturned:
207
+ case <-time.After(time.Millisecond):
208
+ t.Fatal("read should return after Conn is closed")
209
+ }
210
+ if err := <-dcReadErr; err != io.EOF {
211
+ t.Fatalf("dial conn read returned %s", err)
212
+ }
213
+}
214
+
215
+func connectSelfLots(n int, t testing.TB) {
216
+ defer goroutineLeakCheck(t)()
217
+ s, err := NewSocket("udp", "localhost:0")
218
+ if err != nil {
219
+ t.Fatal(err)
220
+ }
221
+ go func() {
222
+ for range iter.N(n) {
223
+ c, err := s.Accept()
224
+ if err != nil {
225
+ log.Fatal(err)
226
+ }
227
+ defer c.Close()
228
+ }
229
+ }()
230
+ dialErr := make(chan error)
231
+ connCh := make(chan net.Conn)
232
+ dialSema := make(chan struct{}, backlog)
233
+ for range iter.N(n) {
234
+ go func() {
235
+ dialSema <- struct{}{}
236
+ c, err := s.Dial(s.Addr().String())
237
+ <-dialSema
238
+ if err != nil {
239
+ dialErr <- err
240
+ return
241
+ }
242
+ connCh <- c
243
+ }()
244
+ }
245
+ conns := make([]net.Conn, 0, n)
246
+ for range iter.N(n) {
247
+ select {
248
+ case c := <-connCh:
249
+ conns = append(conns, c)
250
+ case err := <-dialErr:
251
+ t.Fatal(err)
252
+ }
253
+ }
254
+ for _, c := range conns {
255
+ if c != nil {
256
+ c.Close()
257
+ }
258
+ }
259
+ s.mu.Lock()
260
+ for len(s.conns) != 0 {
261
+ // log.Print(len(s.conns))
262
+ s.event.Wait()
263
+ }
264
+ s.mu.Unlock()
265
+ s.Close()
266
+}
267
+
268
+// Connect to ourself heaps.
269
+func TestConnectSelf(t *testing.T) {
270
+ // A rough guess says that at worst, I can only have 0x10000/3 connections
271
+ // to the same socket, due to fragmentation in the assigned connection
272
+ // IDs.
273
+ connectSelfLots(0x1000, t)
274
+}
275
+
276
+func BenchmarkConnectSelf(b *testing.B) {
277
+ for range iter.N(b.N) {
278
+ connectSelfLots(2, b)
279
+ }
280
+}
281
+
282
+func BenchmarkNewCloseSocket(b *testing.B) {
283
+ for range iter.N(b.N) {
284
+ s, err := NewSocket("udp", "localhost:0")
285
+ if err != nil {
286
+ b.Fatal(err)
287
+ }
288
+ err = s.Close()
289
+ if err != nil {
290
+ b.Fatal(err)
291
+ }
292
+ }
293
+}
294
+
295
+func TestRejectDialBacklogFilled(t *testing.T) {
296
+ s, err := NewSocket("udp", "localhost:0")
297
+ if err != nil {
298
+ t.Fatal(err)
299
+ }
300
+ errChan := make(chan error, 1)
301
+ dial := func() {
302
+ _, err := s.Dial(s.Addr().String())
303
+ if err != nil {
304
+ errChan <- err
305
+ }
306
+ }
307
+ // Fill the backlog.
308
+ for range iter.N(backlog + 1) {
309
+ go dial()
310
+ }
311
+ s.mu.Lock()
312
+ for len(s.backlog) < backlog {
313
+ s.event.Wait()
314
+ }
315
+ s.mu.Unlock()
316
+ select {
317
+ case <-errChan:
318
+ t.FailNow()
319
+ default:
320
+ }
321
+ // One more connection should cause a dial attempt to get reset.
322
+ go dial()
323
+ err = <-errChan
324
+ if err.Error() != "peer reset" {
325
+ t.FailNow()
326
+ }
327
+ s.Close()
328
+}
329
+
330
+// Make sure that we can reset AfterFunc timers, so we don't have to create
331
+// brand new ones everytime they fire. Specifically for the Conn resend timer.
332
+func TestResetAfterFuncTimer(t *testing.T) {
333
+ fired := make(chan struct{})
334
+ timer := time.AfterFunc(time.Millisecond, func() {
335
+ fired <- struct{}{}
336
+ })
337
+ <-fired
338
+ if timer.Reset(time.Millisecond) {
339
+ // The timer should have expired
340
+ t.FailNow()
341
+ }
342
+ <-fired
343
+}
344
+
345
+func connPair() (initer, accepted net.Conn) {
346
+ s, err := NewSocket("udp", "localhost:0")
347
+ if err != nil {
348
+ panic(err)
349
+ }
350
+ defer s.Close()
351
+ var wg sync.WaitGroup
352
+ wg.Add(1)
353
+ go func() {
354
+ defer wg.Done()
355
+ var err error
356
+ initer, err = Dial(s.Addr().String())
357
+ if err != nil {
358
+ panic(err)
359
+ }
360
+ }()
361
+ accepted, err = s.Accept()
362
+ if err != nil {
363
+ panic(err)
364
+ }
365
+ wg.Wait()
366
+ return
367
+}
368
+
369
+// Check that peer sending FIN doesn't cause unread data to be dropped in a
370
+// receiver.
371
+func TestReadFinishedConn(t *testing.T) {
372
+ a, b := connPair()
373
+ defer a.Close()
374
+ defer b.Close()
375
+ mu.Lock()
376
+ originalAPDC := artificialPacketDropChance
377
+ artificialPacketDropChance = 1
378
+ mu.Unlock()
379
+ n, err := a.Write([]byte("hello"))
380
+ require.Equal(t, 5, n)
381
+ require.NoError(t, err)
382
+ n, err = a.Write([]byte("world"))
383
+ require.Equal(t, 5, n)
384
+ require.NoError(t, err)
385
+ mu.Lock()
386
+ artificialPacketDropChance = originalAPDC
387
+ mu.Unlock()
388
+ a.Close()
389
+ all, err := ioutil.ReadAll(b)
390
+ require.NoError(t, err)
391
+ require.EqualValues(t, "helloworld", all)
392
+}
393
+
394
+func TestCloseDetachesQuickly(t *testing.T) {
395
+ s, _ := NewSocket("udp", "localhost:0")
396
+ defer s.Close()
397
+ go func() {
398
+ a, _ := s.Dial(s.Addr().String())
399
+ log.Print("close a")
400
+ a.Close()
401
+ log.Print("closed a")
402
+ }()
403
+ b, _ := s.Accept()
404
+ b.Close()
405
+ s.mu.Lock()
406
+ for len(s.conns) != 0 {
407
+ log.Print(len(s.conns))
408
+ s.event.Wait()
409
+ }
410
+ s.mu.Unlock()
411
+}
Godeps/_workspace/src/github.com/bradfitz/iter/.gitignore
new
+1
@@ -0,0 +1 @@
1
+*~
Godeps/_workspace/src/github.com/bradfitz/iter/README.txt
new
+1
@@ -0,0 +1 @@
1
+See http://godoc.org/github.com/bradfitz/iter
Godeps/_workspace/src/github.com/bradfitz/iter/iter.go
new
+17
@@ -0,0 +1,17 @@
1
+// Package iter provides a syntantically different way to iterate over integers. That's it.
2
+package iter
3
+
4
+// N returns a slice of n 0-sized elements, suitable for ranging over.
5
+//
6
+// For example:
7
+//
8
+// for i := range iter.N(10) {
9
+// fmt.Println(i)
10
+// }
11
+//
12
+// ... will print 0 to 9, inclusive.
13
+//
14
+// It does not cause any allocations.
15
+func N(n int) []struct{} {
16
+ return make([]struct{}, n)
17
+}
Godeps/_workspace/src/github.com/bradfitz/iter/iter_test.go
new
+29
@@ -0,0 +1,29 @@
1
+package iter_test
2
+
3
+import (
4
+ "fmt"
5
+ "testing"
6
+
7
+ "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/bradfitz/iter"
8
+)
9
+
10
+func ExampleN() {
11
+ for i := range iter.N(4) {
12
+ fmt.Println(i)
13
+ }
14
+ // Output:
15
+ // 0
16
+ // 1
17
+ // 2
18
+ // 3
19
+}
20
+
21
+func TestAllocs(t *testing.T) {
22
+ var x []struct{}
23
+ allocs := testing.AllocsPerRun(500, func() {
24
+ x = iter.N(1e9)
25
+ })
26
+ if allocs > 0.1 {
27
+ t.Errorf("allocs = %v", allocs)
28
+ }
29
+}
Godeps/_workspace/src/github.com/h2so5/utp/.gitignore
deleted
-26
@@ -1,26 +0,0 @@
1
-# Compiled Object files, Static and Dynamic libs (Shared Objects)
2
-*.o
3
-*.a
4
-*.so
5
-
6
-# Folders
7
-_obj
8
-_test
9
-
10
-# Architecture specific extensions/prefixes
11
-*.[568vq]
12
-[568vq].out
13
-
14
-*.cgo1.go
15
-*.cgo2.c
16
-_cgo_defun.c
17
-_cgo_gotypes.go
18
-_cgo_export.*
19
-
20
-_testmain.go
21
-
22
-*.exe
23
-*.test
24
-*.prof
25
-
26
-_ucat_test/libutp
Godeps/_workspace/src/github.com/h2so5/utp/.travis.yml
deleted
-9
@@ -1,9 +0,0 @@
1
-language: go
2
-
3
-script:
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/LICENSE
deleted
-21
@@ -1,21 +0,0 @@
1
-The MIT License (MIT)
2
-
3
-Copyright (c) 2014 Ron Hashimoto
4
-
5
-Permission is hereby granted, free of charge, to any person obtaining a copy
6
-of this software and associated documentation files (the "Software"), to deal
7
-in the Software without restriction, including without limitation the rights
8
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
-copies of the Software, and to permit persons to whom the Software is
10
-furnished to do so, subject to the following conditions:
11
-
12
-The above copyright notice and this permission notice shall be included in all
13
-copies or substantial portions of the Software.
14
-
15
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
-SOFTWARE.
Godeps/_workspace/src/github.com/h2so5/utp/README.md
deleted
-28
@@ -1,28 +0,0 @@
1
-utp
2
-===
3
-
4
-μTP (Micro Transport Protocol) implementation
5
-
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
-## Installation
13
-
14
-```
15
-go get github.com/h2so5/utp
16
-```
17
-
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
deleted
-42
@@ -1,42 +0,0 @@
1
-package utp
2
-
3
-import "net"
4
-
5
-// Addr represents the address of a UTP end point.
6
-type Addr struct {
7
- net.Addr
8
-}
9
-
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 {
33
- case "utp":
34
- return "udp", nil
35
- case "utp4":
36
- return "udp4", nil
37
- case "utp6":
38
- return "udp6", nil
39
- default:
40
- return "", net.UnknownNetworkError(n)
41
- }
42
-}
Godeps/_workspace/src/github.com/h2so5/utp/base.go
deleted
-325
@@ -1,325 +0,0 @@
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
deleted
-308
@@ -1,308 +0,0 @@
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
deleted
-296
@@ -1,296 +0,0 @@
1
-package main
2
-
3
-import (
4
- "bytes"
5
- "crypto/md5"
6
- "flag"
7
- "fmt"
8
- "io"
9
- "log"
10
- "math/rand"
11
- "sync"
12
- "time"
13
-
14
- "github.com/davecheney/profile"
15
- "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/dustin/go-humanize"
16
- "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/h2so5/utp"
17
-)
18
-
19
-type RandReader struct{}
20
-
21
-func (r RandReader) Read(p []byte) (n int, err error) {
22
- for i := range p {
23
- p[i] = byte(rand.Int())
24
- }
25
- return len(p), nil
26
-}
27
-
28
-type ByteCounter struct {
29
- n int64
30
- mutex sync.RWMutex
31
-}
32
-
33
-func (b *ByteCounter) Write(p []byte) (n int, err error) {
34
- b.mutex.Lock()
35
- defer b.mutex.Unlock()
36
- b.n += int64(len(p))
37
- return len(p), nil
38
-}
39
-
40
-func (b *ByteCounter) Length() int64 {
41
- b.mutex.RLock()
42
- defer b.mutex.RUnlock()
43
- return b.n
44
-}
45
-
46
-var h = flag.Bool("h", false, "Human readable")
47
-
48
-func main() {
49
- var l = flag.Int("c", 10485760, "Payload length (bytes)")
50
- var s = flag.Bool("s", false, "Stream mode(Low memory usage, but Slow)")
51
- flag.Parse()
52
-
53
- defer profile.Start(profile.CPUProfile).Stop()
54
-
55
- if *h {
56
- fmt.Printf("Payload: %s\n", humanize.IBytes(uint64(*l)))
57
- } else {
58
- fmt.Printf("Payload: %d\n", *l)
59
- }
60
-
61
- c2s := c2s(int64(*l), *s)
62
- n, p := humanize.ComputeSI(c2s)
63
- if *h {
64
- fmt.Printf("C2S: %f%sbps\n", n, p)
65
- } else {
66
- fmt.Printf("C2S: %f\n", c2s)
67
- }
68
-
69
- s2c := s2c(int64(*l), *s)
70
- n, p = humanize.ComputeSI(s2c)
71
- if *h {
72
- fmt.Printf("S2C: %f%sbps\n", n, p)
73
- } else {
74
- fmt.Printf("S2C: %f\n", s2c)
75
- }
76
-
77
- avg := (c2s + s2c) / 2.0
78
- n, p = humanize.ComputeSI(avg)
79
-
80
- if *h {
81
- fmt.Printf("AVG: %f%sbps\n", n, p)
82
- } else {
83
- fmt.Printf("AVG: %f\n", avg)
84
- }
85
-}
86
-
87
-func c2s(l int64, stream bool) float64 {
88
- laddr, err := utp.ResolveAddr("utp", "127.0.0.1:0")
89
- if err != nil {
90
- log.Fatal(err)
91
- }
92
- ln, err := utp.Listen("utp", laddr)
93
- if err != nil {
94
- log.Fatal(err)
95
- }
96
-
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
- }
107
- cch <- c
108
- }()
109
-
110
- s, err := ln.Accept()
111
- if err != nil {
112
- log.Fatal(err)
113
- }
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()
125
- counter := ByteCounter{}
126
-
127
- var bps 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)
138
- }()
139
-
140
- go func() {
141
- for {
142
- select {
143
- case <-time.After(time.Second):
144
- if *h {
145
- fmt.Printf("\r <--> %s ", humanize.IBytes(uint64(counter.Length())))
146
- } else {
147
- fmt.Printf("\r <--> %d ", counter.Length())
148
- }
149
- case <-rch:
150
- fmt.Printf("\r")
151
- return
152
- }
153
- }
154
- }()
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 {
162
- var sendBuf, readBuf bytes.Buffer
163
- io.Copy(io.MultiWriter(&sendBuf, sendHash), io.LimitReader(RandReader{}, l))
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)
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)
182
- io.Copy(readHash, &readBuf)
183
- }
184
-
185
- if !bytes.Equal(sendHash.Sum(nil), readHash.Sum(nil)) {
186
- log.Fatal("Broken payload")
187
- }
188
-
189
- return bps
190
-}
191
-
192
-func s2c(l int64, stream bool) float64 {
193
- laddr, err := utp.ResolveAddr("utp", "127.0.0.1:0")
194
- if err != nil {
195
- log.Fatal(err)
196
- }
197
- ln, err := utp.Listen("utp", laddr)
198
- if err != nil {
199
- log.Fatal(err)
200
- }
201
-
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
-
209
- if err != nil {
210
- log.Fatal(err)
211
- }
212
- cch <- c
213
- }()
214
-
215
- s, err := ln.Accept()
216
- if err != nil {
217
- log.Fatal(err)
218
- }
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()
230
- counter := ByteCounter{}
231
-
232
- var bps float64
233
-
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)
244
- }()
245
-
246
- go func() {
247
- for {
248
- select {
249
- case <-time.After(time.Second):
250
- if *h {
251
- fmt.Printf("\r <--> %s ", humanize.IBytes(uint64(counter.Length())))
252
- } else {
253
- fmt.Printf("\r <--> %d ", counter.Length())
254
- }
255
- case <-rch:
256
- fmt.Printf("\r")
257
- return
258
- }
259
- }
260
- }()
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 {
268
- var sendBuf, readBuf bytes.Buffer
269
- io.Copy(io.MultiWriter(&sendBuf, sendHash), io.LimitReader(RandReader{}, l))
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)
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)
288
- io.Copy(readHash, &readBuf)
289
- }
290
-
291
- if !bytes.Equal(sendHash.Sum(nil), readHash.Sum(nil)) {
292
- log.Fatal("Broken payload")
293
- }
294
-
295
- return bps
296
-}
Godeps/_workspace/src/github.com/h2so5/utp/buffer.go
deleted
-472
@@ -1,472 +0,0 @@
1
-package utp
2
-
3
-import (
4
- "errors"
5
- "io"
6
- "math"
7
- "sync"
8
- "time"
9
-)
10
-
11
-type packetBuffer struct {
12
- root *packetBufferNode
13
- size int
14
- begin int
15
-}
16
-
17
-type packetBufferNode struct {
18
- p *packet
19
- next *packetBufferNode
20
- pushed time.Time
21
-}
22
-
23
-func newPacketBuffer(size, begin int) *packetBuffer {
24
- return &packetBuffer{
25
- size: size,
26
- begin: begin,
27
- }
28
-}
29
-
30
-func (b *packetBuffer) push(p *packet) error {
31
- if int(p.header.seq) > b.begin+b.size-1 {
32
- return errors.New("out of bounds")
33
- } else if int(p.header.seq) < b.begin {
34
- if int(p.header.seq)+math.MaxUint16 > b.begin+b.size-1 {
35
- return errors.New("out of bounds")
36
- }
37
- }
38
- if b.root == nil {
39
- b.root = &packetBufferNode{}
40
- }
41
- n := b.root
42
- i := b.begin
43
- for {
44
- if i == int(p.header.seq) {
45
- n.p = p
46
- n.pushed = time.Now()
47
- return nil
48
- } else if n.next == nil {
49
- n.next = &packetBufferNode{}
50
- }
51
- n = n.next
52
- i = (i + 1) % (math.MaxUint16 + 1)
53
- }
54
- return nil
55
-}
56
-
57
-func (b *packetBuffer) fetch(id uint16) *packet {
58
- for p := b.root; p != nil; p = p.next {
59
- if p.p != nil {
60
- if p.p.header.seq < id {
61
- p.p = nil
62
- } else if p.p.header.seq == id {
63
- r := p.p
64
- p.p = nil
65
- return r
66
- }
67
- }
68
- }
69
- return nil
70
-}
71
-
72
-func (b *packetBuffer) compact() {
73
- for b.root != nil && b.root.p == nil {
74
- b.root = b.root.next
75
- b.begin = (b.begin + 1) % (math.MaxUint16 + 1)
76
- }
77
-}
78
-
79
-func (b *packetBuffer) front() *packet {
80
- if b.root == nil || b.root.p == nil {
81
- return nil
82
- }
83
- return b.root.p
84
-}
85
-
86
-func (b *packetBuffer) frontPushedTime() (time.Time, error) {
87
- if b.root == nil || b.root.p == nil {
88
- return time.Time{}, errors.New("no first packet")
89
- }
90
- return b.root.pushed, nil
91
-}
92
-
93
-func (b *packetBuffer) fetchSequence() []*packet {
94
- var a []*packet
95
- for ; b.root != nil && b.root.p != nil; b.root = b.root.next {
96
- a = append(a, b.root.p)
97
- b.begin = (b.begin + 1) % (math.MaxUint16 + 1)
98
- }
99
- return a
100
-}
101
-
102
-func (b *packetBuffer) sequence() []*packet {
103
- var a []*packet
104
- n := b.root
105
- for ; n != nil && n.p != nil; n = n.next {
106
- a = append(a, n.p)
107
- }
108
- return a
109
-}
110
-
111
-func (b *packetBuffer) space() int {
112
- s := b.size
113
- for p := b.root; p != nil; p = p.next {
114
- s--
115
- }
116
- return s
117
-}
118
-
119
-func (b *packetBuffer) empty() bool {
120
- return b.root == nil
121
-}
122
-
123
-// test use only
124
-func (b *packetBuffer) all() []*packet {
125
- var a []*packet
126
- for p := b.root; p != nil; p = p.next {
127
- if p.p != nil {
128
- a = append(a, p.p)
129
- }
130
- }
131
- return a
132
-}
133
-
134
-func (b *packetBuffer) generateSelectiveACK() []byte {
135
- if b.empty() {
136
- return nil
137
- }
138
-
139
- var ack []byte
140
- var bit uint
141
- var octet byte
142
- for p := b.root.next; p != nil; p = p.next {
143
- if p.p != nil {
144
- octet |= (1 << bit)
145
- }
146
- bit++
147
- if bit == 8 {
148
- ack = append(ack, octet)
149
- bit = 0
150
- octet = 0
151
- }
152
- }
153
-
154
- if bit != 0 {
155
- ack = append(ack, octet)
156
- }
157
-
158
- for len(ack) > 0 && ack[len(ack)-1] == 0 {
159
- ack = ack[:len(ack)-1]
160
- }
161
-
162
- if len(ack) == 0 {
163
- return nil
164
- }
165
- return ack
166
-}
167
-
168
-func (b *packetBuffer) processSelectiveACK(ack []byte) {
169
- if b.empty() {
170
- return
171
- }
172
-
173
- p := b.root.next
174
- if p == nil {
175
- return
176
- }
177
-
178
- for _, a := range ack {
179
- for i := 0; i < 8; i++ {
180
- acked := (a & 1) != 0
181
- a >>= 1
182
- if acked {
183
- p.p = nil
184
- }
185
- p = p.next
186
- if p == nil {
187
- return
188
- }
189
- }
190
- }
191
-}
192
-
193
-type packetRingBuffer struct {
194
- b []*packet
195
- begin int
196
- s int
197
- mutex sync.RWMutex
198
- rch chan int
199
-}
200
-
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
-
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
- }
402
- }
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
- }
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
-
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
- }
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
- }
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
deleted
-178
@@ -1,178 +0,0 @@
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
deleted
-571
@@ -1,571 +0,0 @@
1
-package utp
2
-
3
-import (
4
- "math"
5
- "net"
6
- "sync"
7
- "sync/atomic"
8
- "syscall"
9
- "time"
10
-)
11
-
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
-
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
-
56
-type statistics struct {
57
- sentPackets int
58
- resentPackets int
59
- receivedPackets int
60
- receivedDuplicatedACKs int
61
- packetTimedOuts int
62
- sentSelectiveACKs int
63
- receivedSelectiveACKs int
64
- rtoSum int64
65
- rtoCount int
66
-}
67
-
68
-func newConn() *Conn {
69
- wch := make(chan []byte)
70
- c := &Conn{
71
- minRtt: math.MaxInt64,
72
- maxWindow: mss,
73
- rto: int64(60),
74
-
75
- recv: make(chan *packet),
76
- connch: make(chan int),
77
-
78
- recvbuf: newPacketBuffer(0, 0),
79
-
80
- readbuf: newByteRingBuffer(readBufferSize),
81
- writebuf: newRateLimitedBuffer(wch, mss),
82
-
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),
89
- closech: make(chan int),
90
- }
91
- return c
92
-}
93
-
94
-func (c *Conn) ok() bool { return c != nil && c.conn != nil }
95
-
96
-// Close closes the connection.
97
-func (c *Conn) Close() error {
98
- if !c.ok() {
99
- return syscall.EINVAL
100
- }
101
- if !c.isOpen() {
102
- return nil
103
- }
104
- select {
105
- case <-c.closingch:
106
- default:
107
- close(c.closingch)
108
- }
109
- select {
110
- case <-c.connch:
111
- default:
112
- return nil
113
- }
114
- <-c.closech
115
- return nil
116
-}
117
-
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
-
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
-
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
- }
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
- }
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 {
154
- case c.ackch <- 0:
155
- default:
156
- }
157
- }
158
- return l, err
159
-}
160
-
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
- }
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
- }
185
- c.deadlineMutex.RLock()
186
- d := timeToDeadline(c.wdeadline)
187
- c.deadlineMutex.RUnlock()
188
- return c.writebuf.WriteTimeout(b, d)
189
-}
190
-
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
- }
196
- err := c.SetReadDeadline(t)
197
- if err != nil {
198
- return err
199
- }
200
- return c.SetWriteDeadline(t)
201
-}
202
-
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
-
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
-
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
- }
230
- if !c.isOpen() {
231
- return errClosing
232
- }
233
- c.keepalivech <- d
234
- return nil
235
-}
236
-
237
-func (c *Conn) loop() {
238
- defer c.conn.Unregister(int32(c.rid))
239
-
240
- var resendSeq uint16
241
- var resendCont int
242
- var keepalive <-chan time.Time
243
-
244
- resend := time.NewTimer(0)
245
- resend.Stop()
246
- defer resend.Stop()
247
-
248
- for {
249
- resend.Stop()
250
- f := c.sendbuf.front()
251
- if f != nil {
252
- resend.Reset(time.Duration(c.rto) * time.Millisecond)
253
- }
254
- select {
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
- }
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() {
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
296
- } else {
297
- keepalive = time.Tick(d)
298
- }
299
- case <-keepalive:
300
- ulog.Printf(2, "Conn(%v): Send keepalive", c.LocalAddr())
301
- c.sendACK()
302
- }
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
-
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
-
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
-
356
-func (c *Conn) processPacket(p *packet) {
357
- if p.header.t == 0 {
358
- c.diff = 0
359
- } else {
360
- t := currentMicrosecond()
361
- if t > p.header.t {
362
- c.diff = t - p.header.t
363
- if c.minRtt > int64(c.diff) {
364
- c.minRtt = int64(c.diff)
365
- }
366
- }
367
- }
368
-
369
- c.baseDelay.Push(c.diff)
370
-
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 {
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)
380
- }
381
- }
382
- }
383
-
384
- s := c.sendbuf.fetch(p.header.ack)
385
- if s != nil {
386
- current := currentMicrosecond()
387
- if current > s.header.t {
388
- e := int64(current-s.header.t) / 1000
389
- if c.rtt == 0 {
390
- c.rtt = e
391
- c.rttVar = e / 2
392
- } else {
393
- d := c.rtt - e
394
- if d < 0 {
395
- d = -d
396
- }
397
- c.rttVar += (d - c.rttVar) / 4
398
- c.rtt = c.rtt - c.rtt/8 + e/8
399
- }
400
- c.rto = c.rtt + c.rttVar*4
401
- if c.rto < 60 {
402
- c.rto = 60
403
- } else if c.rto > 1000 {
404
- c.rto = 1000
405
- }
406
- c.stat.rtoSum += c.rto
407
- c.stat.rtoCount++
408
- }
409
-
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
415
- gain := 3000.0 * delayFactor * windowFactor
416
- c.maxWindow = uint32(int(c.maxWindow) + int(gain))
417
- if c.maxWindow < mtu {
418
- c.maxWindow = mtu
419
- }
420
- ulog.Printf(4, "Conn(%v): Update maxWindow: %d", c.LocalAddr(), c.maxWindow)
421
- }
422
- }
423
-
424
- c.sendbuf.compact()
425
-
426
- if c.lastAck == p.header.ack {
427
- c.dupAck++
428
- if c.dupAck >= 2 {
429
- c.stat.receivedDuplicatedACKs++
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)
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
- }
452
- c.writebuf.Reset(wnd)
453
- }
454
-
455
- if c.state == stateSynSent {
456
- c.recvbuf = newPacketBuffer(windowSize, int(p.header.seq))
457
- c.state = stateConnected
458
- close(c.connch)
459
- }
460
-
461
- case stReset:
462
- c.sendRST()
463
- c.close()
464
-
465
- default:
466
- c.recvbuf.push(p)
467
- for _, s := range c.recvbuf.fetchSequence() {
468
- c.ack = s.header.seq
469
- if s.header.typ == stData {
470
- c.readbuf.Write(s.payload)
471
- } else if s.header.typ == stFin {
472
- c.enterClosing()
473
- }
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
- }
491
- c.stat.sentPackets++
492
- c.conn.Send(ack)
493
-}
494
-
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
553
- if typ == stSyn {
554
- id = c.rid
555
- }
556
- p := &packet{}
557
- p.header.typ = typ
558
- p.header.ver = version
559
- p.header.id = id
560
- p.header.t = currentMicrosecond()
561
- p.header.diff = c.diff
562
- p.header.wnd = uint32(wnd)
563
- p.header.seq = c.seq
564
- p.header.ack = c.ack
565
- p.addr = dst
566
- if typ != stState && typ != stFin {
567
- c.seq++
568
- }
569
- p.payload = payload
570
- return p
571
-}
Godeps/_workspace/src/github.com/h2so5/utp/conn_test.go
deleted
-87
@@ -1,87 +0,0 @@
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
deleted
-102
@@ -1,102 +0,0 @@
1
-package utp
2
-
3
-import (
4
- "errors"
5
- "math"
6
- "math/rand"
7
- "net"
8
- "time"
9
-)
10
-
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
- }
25
-
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
-
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.
60
-//
61
-// The zero value for each field is equivalent to dialing without
62
-// that option. Dialing with the zero value of Dialer is therefore
63
-// equivalent to just calling the Dial function.
64
-type Dialer struct {
65
- // Timeout is the maximum amount of time a dial will wait for
66
- // a connect to complete. If Deadline is also set, it may fail
67
- // earlier.
68
- //
69
- // The default is no timeout.
70
- //
71
- // With or without a timeout, the operating system may impose
72
- // its own earlier timeout. For instance, TCP timeouts are
73
- // often around 3 minutes.
74
- Timeout time.Duration
75
-
76
- // LocalAddr is the local address to use when dialing an
77
- // address. The address must be of a compatible type for the
78
- // network being dialed.
79
- // If nil, a local address is automatically chosen.
80
- LocalAddr net.Addr
81
-}
82
-
83
-// Dial connects to the address on the named network.
84
-//
85
-// See func Dial for a description of the network and address parameters.
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
-
92
- var laddr *Addr
93
- if d.LocalAddr != nil {
94
- var ok bool
95
- laddr, ok = d.LocalAddr.(*Addr)
96
- if !ok {
97
- return nil, errors.New("Dialer.LocalAddr is not a Addr")
98
- }
99
- }
100
-
101
- return DialUTPTimeout(n, laddr, raddr, d.Timeout)
102
-}
Godeps/_workspace/src/github.com/h2so5/utp/dial_test.go
deleted
-52
@@ -1,52 +0,0 @@
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
deleted
-146
@@ -1,146 +0,0 @@
1
-package utp
2
-
3
-import (
4
- "math"
5
- "math/rand"
6
- "net"
7
- "sync"
8
- "sync/atomic"
9
- "syscall"
10
- "time"
11
-)
12
-
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
-
20
- conn *baseConn
21
- deadline time.Time
22
- deadlineMutex sync.RWMutex
23
- closed int32
24
-}
25
-
26
-func (l *Listener) ok() bool { return l != nil && l.conn != nil }
27
-
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
- }
37
- l := &Listener{
38
- RawConn: conn,
39
- conn: conn,
40
- }
41
- conn.Register(-1, nil)
42
- return l, nil
43
-}
44
-
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
-
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
- }
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
- }
64
- }
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
- }
77
-
78
- seq := rand.Intn(math.MaxUint16)
79
- rid := p.header.id + 1
80
-
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
-
95
- ulog.Printf(2, "baseConn(%v): accept #%d from %v", c.LocalAddr(), c.rid, c.raddr)
96
- return c, nil
97
-}
98
-
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
- }
104
- return l.conn.LocalAddr()
105
-}
106
-
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
- }
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
-
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
- }
130
- l.deadlineMutex.Lock()
131
- defer l.deadlineMutex.Unlock()
132
- l.deadline = t
133
- return nil
134
-}
135
-
136
-func (l *Listener) close() bool {
137
- if atomic.CompareAndSwapInt32(&l.closed, 0, 1) {
138
- l.conn.Unregister(-1)
139
- return true
140
- }
141
- return false
142
-}
143
-
144
-func (l *Listener) isOpen() bool {
145
- return atomic.LoadInt32(&l.closed) == 0
146
-}
Godeps/_workspace/src/github.com/h2so5/utp/listener_test.go
deleted
-68
@@ -1,68 +0,0 @@
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/log.go
deleted
-50
@@ -1,50 +0,0 @@
1
-package utp
2
-
3
-import (
4
- "log"
5
- "os"
6
- "strconv"
7
-)
8
-
9
-type logger struct {
10
- level int
11
-}
12
-
13
-var ulog *logger
14
-
15
-func init() {
16
- logenv := os.Getenv("GO_UTP_LOGGING")
17
-
18
- var level int
19
- if len(logenv) > 0 {
20
- l, err := strconv.Atoi(logenv)
21
- if err != nil {
22
- log.Print("warning: GO_UTP_LOGGING must be numeric")
23
- } else {
24
- level = l
25
- }
26
- }
27
-
28
- ulog = &logger{level}
29
-}
30
-
31
-func (l *logger) Print(level int, v ...interface{}) {
32
- if l.level < level {
33
- return
34
- }
35
- log.Print(v...)
36
-}
37
-
38
-func (l *logger) Printf(level int, format string, v ...interface{}) {
39
- if l.level < level {
40
- return
41
- }
42
- log.Printf(format, v...)
43
-}
44
-
45
-func (l *logger) Println(level int, v ...interface{}) {
46
- if l.level < level {
47
- return
48
- }
49
- log.Println(v...)
50
-}
Godeps/_workspace/src/github.com/h2so5/utp/packet.go
deleted
-198
@@ -1,198 +0,0 @@
1
-package utp
2
-
3
-import (
4
- "bytes"
5
- "encoding/binary"
6
- "fmt"
7
- "io"
8
- "io/ioutil"
9
- "net"
10
-)
11
-
12
-type header struct {
13
- typ, ver int
14
- id uint16
15
- t, diff, wnd uint32
16
- seq, ack uint16
17
-}
18
-
19
-type extension struct {
20
- typ int
21
- payload []byte
22
-}
23
-
24
-type packet struct {
25
- header header
26
- ext []extension
27
- payload []byte
28
- addr net.Addr
29
-}
30
-
31
-func (p *packet) MarshalBinary() ([]byte, error) {
32
- firstExt := extNone
33
- if len(p.ext) > 0 {
34
- firstExt = p.ext[0].typ
35
- }
36
- buf := new(bytes.Buffer)
37
- var beforeExt = []interface{}{
38
- // | type | ver |
39
- uint8(((byte(p.header.typ) << 4) & 0xF0) | (byte(p.header.ver) & 0xF)),
40
- // | extension |
41
- uint8(firstExt),
42
- }
43
- var afterExt = []interface{}{
44
- // | connection_id |
45
- uint16(p.header.id),
46
- // | timestamp_microseconds |
47
- uint32(p.header.t),
48
- // | timestamp_difference_microseconds |
49
- uint32(p.header.diff),
50
- // | wnd_size |
51
- uint32(p.header.wnd),
52
- // | seq_nr |
53
- uint16(p.header.seq),
54
- // | ack_nr |
55
- uint16(p.header.ack),
56
- }
57
-
58
- for _, v := range beforeExt {
59
- err := binary.Write(buf, binary.BigEndian, v)
60
- if err != nil {
61
- return nil, err
62
- }
63
- }
64
-
65
- if len(p.ext) > 0 {
66
- for i, e := range p.ext {
67
- next := extNone
68
- if i < len(p.ext)-1 {
69
- next = p.ext[i+1].typ
70
- }
71
- var ext = []interface{}{
72
- // | extension |
73
- uint8(next),
74
- // | len |
75
- uint8(len(e.payload)),
76
- }
77
- for _, v := range ext {
78
- err := binary.Write(buf, binary.BigEndian, v)
79
- if err != nil {
80
- return nil, err
81
- }
82
- }
83
- _, err := buf.Write(e.payload)
84
- if err != nil {
85
- return nil, err
86
- }
87
- }
88
- }
89
-
90
- for _, v := range afterExt {
91
- err := binary.Write(buf, binary.BigEndian, v)
92
- if err != nil {
93
- return nil, err
94
- }
95
- }
96
-
97
- _, err := buf.Write(p.payload)
98
- if err != nil {
99
- return nil, err
100
- }
101
- return buf.Bytes(), nil
102
-}
103
-
104
-func (p *packet) UnmarshalBinary(data []byte) error {
105
- p.ext = nil
106
- buf := bytes.NewReader(data)
107
- var tv, e uint8
108
-
109
- var beforeExt = []interface{}{
110
- // | type | ver |
111
- (*uint8)(&tv),
112
- // | extension |
113
- (*uint8)(&e),
114
- }
115
- for _, v := range beforeExt {
116
- err := binary.Read(buf, binary.BigEndian, v)
117
- if err != nil {
118
- return err
119
- }
120
- }
121
-
122
- for e != extNone {
123
- currentExt := int(e)
124
- var l uint8
125
- var ext = []interface{}{
126
- // | extension |
127
- (*uint8)(&e),
128
- // | len |
129
- (*uint8)(&l),
130
- }
131
- for _, v := range ext {
132
- err := binary.Read(buf, binary.BigEndian, v)
133
- if err != nil {
134
- return err
135
- }
136
- }
137
- payload := make([]byte, l)
138
- size, err := buf.Read(payload[:])
139
- if err != nil {
140
- return err
141
- }
142
- if size != len(payload) {
143
- return io.EOF
144
- }
145
- p.ext = append(p.ext, extension{typ: currentExt, payload: payload})
146
- }
147
-
148
- var afterExt = []interface{}{
149
- // | connection_id |
150
- (*uint16)(&p.header.id),
151
- // | timestamp_microseconds |
152
- (*uint32)(&p.header.t),
153
- // | timestamp_difference_microseconds |
154
- (*uint32)(&p.header.diff),
155
- // | wnd_size |
156
- (*uint32)(&p.header.wnd),
157
- // | seq_nr |
158
- (*uint16)(&p.header.seq),
159
- // | ack_nr |
160
- (*uint16)(&p.header.ack),
161
- }
162
- for _, v := range afterExt {
163
- err := binary.Read(buf, binary.BigEndian, v)
164
- if err != nil {
165
- return err
166
- }
167
- }
168
-
169
- p.header.typ = int((tv >> 4) & 0xF)
170
- p.header.ver = int(tv & 0xF)
171
-
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 {
182
- s := fmt.Sprintf("[%d ", p.header.id)
183
- switch p.header.typ {
184
- case stData:
185
- s += "ST_DATA"
186
- case stFin:
187
- s += "ST_FIN"
188
- case stState:
189
- s += "ST_STATE"
190
- case stReset:
191
- s += "ST_RESET"
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
-}
Godeps/_workspace/src/github.com/h2so5/utp/packet_test.go
deleted
-64
@@ -1,64 +0,0 @@
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/.gitignore
deleted
-3
@@ -1,3 +0,0 @@
1
-ucat
2
-random
3
-.trash/
Godeps/_workspace/src/github.com/h2so5/utp/ucat/Makefile
deleted
-34
@@ -1,34 +0,0 @@
1
-# Run tests
2
-
3
-testnames=simple
4
-tests=$(addprefix test_, $(testnames))
5
-trash=.trash/
6
-
7
-all: ucat
8
-
9
-test: clean ucat ${tests}
10
- @echo ${tests}
11
- @echo "*** tests passed ***"
12
-
13
-# not sue why this doesn't work:
14
-# test_%: test_%.sh
15
-test_simple: test_simple.sh
16
- mkdir -p ${trash}
17
- @echo "*** running $@ ***"
18
- ./$@.sh
19
-
20
-clean:
21
- @echo "*** $@ ***"
22
- -rm -r ${trash}
23
-
24
-deps: random ucat
25
-
26
-ucat:
27
- go build
28
-
29
-random:
30
- @echo "*** installing $@ ***"
31
- go get github.com/jbenet/go-random/random
32
- go build -o random github.com/jbenet/go-random/random
33
-
34
-.PHONY: clean ucat ${tests}
Godeps/_workspace/src/github.com/h2so5/utp/ucat/test_simple.sh
deleted
-49
@@ -1,49 +0,0 @@
1
-#!/bin/sh
2
-
3
-set -e # exit on error
4
-# set -v # verbose
5
-
6
-log() {
7
- echo "--> $1"
8
-}
9
-
10
-test_send() {
11
- file=$1_
12
- count=$2
13
- addr=localhost:8765
14
-
15
- # generate random data
16
- log "generating $count bytes of random data"
17
- ./random $count $RANDOM > ${file}expected
18
-
19
- # dialer sends
20
- log "sending from dialer"
21
- ./ucat -v $addr 2>&1 <${file}expected | sed "s/^/ dialer1: /" &
22
- ./ucat -v -l $addr 2>&1 >${file}actual1 | sed "s/^/listener1: /"
23
- diff ${file}expected ${file}actual1
24
- if test $? != 0; then
25
- log "sending from dialer failed. compare with:\n"
26
- log "diff ${file}expected ${file}actual1"
27
- exit 1
28
- fi
29
-
30
- # listener sends
31
- log "sending from listener"
32
- ./ucat -v -l $addr 2>&1 <${file}expected | sed "s/^/listener2: /" &
33
- ./ucat -v $addr 2>&1 >${file}actual2 | sed "s/^/ dialer2: /"
34
- diff ${file}expected ${file}actual2
35
- if test $? != 0; then
36
- log "sending from listener failed. compare with:\n"
37
- log "diff ${file}expected ${file}actual2"
38
- exit 1
39
- fi
40
-
41
- echo rm ${file}{expected,actual1,actual2}
42
- rm ${file}{expected,actual1,actual2}
43
- return 0
44
-}
45
-
46
-
47
-test_send ".trash/1KB" 1024
48
-test_send ".trash/1MB" 1048576
49
-test_send ".trash/1GB" 1073741824
Godeps/_workspace/src/github.com/h2so5/utp/ucat/ucat.go
deleted
-192
@@ -1,192 +0,0 @@
1
-// package ucat provides an implementation of netcat using the go utp package.
2
-// It is meant to exercise the utp implementation.
3
-// Usage:
4
-// ucat [<local address>] <remote address>
5
-// ucat -l <local address>
6
-//
7
-// Address format is: [host]:port
8
-//
9
-// Note that uTP's congestion control gives priority to tcp flows (web traffic),
10
-// so you could use this ucat tool to transfer massive files without hogging
11
-// all the bandwidth.
12
-package main
13
-
14
-import (
15
- "flag"
16
- "fmt"
17
- "io"
18
- "net"
19
- "os"
20
- "os/signal"
21
- "syscall"
22
-
23
- utp "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/h2so5/utp"
24
-)
25
-
26
-var verbose = false
27
-
28
-// Usage prints out the usage of this module.
29
-// Assumes flags use go stdlib flag pacakage.
30
-var Usage = func() {
31
- text := `ucat - uTP netcat in Go
32
-
33
-Usage:
34
-
35
- listen: %s [<local address>] <remote address>
36
- dial: %s -l <local address>
37
-
38
-Address format is Go's: [host]:port
39
-`
40
-
41
- fmt.Fprintf(os.Stderr, text, os.Args[0], os.Args[0])
42
- flag.PrintDefaults()
43
-}
44
-
45
-type args struct {
46
- listen bool
47
- verbose bool
48
- localAddr string
49
- remoteAddr string
50
-}
51
-
52
-func parseArgs() args {
53
- var a args
54
-
55
- // setup + parse flags
56
- flag.BoolVar(&a.listen, "listen", false, "listen for connections")
57
- flag.BoolVar(&a.listen, "l", false, "listen for connections (short)")
58
- flag.BoolVar(&a.verbose, "v", false, "verbose debugging")
59
- flag.Usage = Usage
60
- flag.Parse()
61
- osArgs := flag.Args()
62
-
63
- if len(osArgs) < 1 {
64
- exit("")
65
- }
66
-
67
- if a.listen {
68
- a.localAddr = osArgs[0]
69
- } else {
70
- if len(osArgs) > 1 {
71
- a.localAddr = osArgs[0]
72
- a.remoteAddr = osArgs[1]
73
- } else {
74
- a.remoteAddr = osArgs[0]
75
- }
76
- }
77
-
78
- return a
79
-}
80
-
81
-func main() {
82
- args := parseArgs()
83
- verbose = args.verbose
84
-
85
- var err error
86
- if args.listen {
87
- err = Listen(args.localAddr)
88
- } else {
89
- err = Dial(args.localAddr, args.remoteAddr)
90
- }
91
-
92
- if err != nil {
93
- exit("%s", err)
94
- }
95
-}
96
-
97
-func exit(format string, vals ...interface{}) {
98
- if format != "" {
99
- fmt.Fprintf(os.Stderr, "ucat error: "+format+"\n", vals...)
100
- }
101
- Usage()
102
- os.Exit(1)
103
-}
104
-
105
-func log(format string, vals ...interface{}) {
106
- if verbose {
107
- fmt.Fprintf(os.Stderr, "ucat log: "+format+"\n", vals...)
108
- }
109
-}
110
-
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
- 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
- }
122
- log("listening at %s", l.Addr())
123
-
124
- c, err := l.Accept()
125
- if err != nil {
126
- return err
127
- }
128
- log("accepted connection from %s", c.RemoteAddr())
129
-
130
- // should be able to close listener here, but utp.Listener.Close
131
- // closes all open connections.
132
- defer l.Close()
133
-
134
- netcat(c)
135
- return c.Close()
136
-}
137
-
138
-// Dial connects to a remote address and pipes all os.Stdin to the remote end.
139
-// If localAddr is set, uses it to Dial from.
140
-func Dial(localAddr, remoteAddr string) error {
141
-
142
- var laddr net.Addr
143
- var err error
144
- if localAddr != "" {
145
- laddr, err = utp.ResolveAddr("utp", localAddr)
146
- if err != nil {
147
- return fmt.Errorf("failed to resolve address %s", localAddr)
148
- }
149
- }
150
-
151
- if laddr != nil {
152
- log("dialing %s from %s", remoteAddr, laddr)
153
- } else {
154
- log("dialing %s", remoteAddr)
155
- }
156
-
157
- d := utp.Dialer{LocalAddr: laddr}
158
- c, err := d.Dial("utp", remoteAddr)
159
- if err != nil {
160
- return err
161
- }
162
- log("connected to %s", c.RemoteAddr())
163
-
164
- netcat(c)
165
- return c.Close()
166
-}
167
-
168
-func netcat(c net.Conn) {
169
- log("piping stdio to connection")
170
-
171
- done := make(chan struct{})
172
-
173
- go func() {
174
- n, _ := io.Copy(c, os.Stdin)
175
- log("sent %d bytes", n)
176
- done <- struct{}{}
177
- }()
178
- go func() {
179
- n, _ := io.Copy(os.Stdout, c)
180
- log("received %d bytes", n)
181
- done <- struct{}{}
182
- }()
183
-
184
- // wait until we exit.
185
- sigc := make(chan os.Signal, 1)
186
- signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT,
187
- syscall.SIGTERM, syscall.SIGQUIT)
188
- select {
189
- case <-done:
190
- case <-sigc:
191
- }
192
-}
Godeps/_workspace/src/github.com/h2so5/utp/utp.go
deleted
-47
@@ -1,47 +0,0 @@
1
-package utp
2
-
3
-import (
4
- "errors"
5
- "time"
6
-)
7
-
8
-const (
9
- version = 1
10
-
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{}
39
-
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/jbenet/go-multiaddr-net/Godeps/Godeps.json
+14
-2
@@ -6,8 +6,20 @@
6
],
7
"Deps": [
8
{
9
- "ImportPath": "github.com/h2so5/utp",
10
- "Rev": "5288a05e1781334589c4b8806bcfb1e69f5b5d63"
9
+ "ImportPath": "github.com/anacrolix/jitter",
10
+ "Rev": "2ea5c18645100745b24e9f5cfc9b3f6f7eac51ef"
11
+ },
12
+ {
13
+ "ImportPath": "github.com/anacrolix/missinggo",
14
+ "Rev": "4e1ca5963308863b56c31863f60c394a7365ec29"
15
+ },
16
+ {
17
+ "ImportPath": "github.com/anacrolix/utp",
18
+ "Rev": "0bb24de92c268452fb9106ca4fb9302442ca0dee"
19
+ },
20
+ {
21
+ "ImportPath": "github.com/bradfitz/iter",
22
+ "Rev": "454541ec3da2a73fc34fd049b19ee5777bf19345"
23
},
24
{
25
"ImportPath": "github.com/jbenet/go-base58",
Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net/convert.go
+6
-2
@@ -5,14 +5,18 @@ import (
5
"net"
6
"strings"
7
8
- utp "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/h2so5/utp"
8
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
9
+ utp "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net/utp"
10
)
11
12
var errIncorrectNetAddr = fmt.Errorf("incorrect network addr conversion")
13
14
// FromNetAddr converts a net.Addr type to a Multiaddr.
15
func FromNetAddr(a net.Addr) (ma.Multiaddr, error) {
16
+ if a == nil {
17
+ return nil, fmt.Errorf("nil multiaddr")
18
+ }
19
+
20
switch a.Network() {
21
case "tcp", "tcp4", "tcp6":
22
ac, ok := a.(*net.TCPAddr)
@@ -63,7 +67,7 @@ func FromNetAddr(a net.Addr) (ma.Multiaddr, error) {
67
}
68
69
// Get UDP Addr
66
- ac, ok := acc.Addr.(*net.UDPAddr)
70
+ ac, ok := acc.Child().(*net.UDPAddr)
71
if !ok {
72
return nil, errIncorrectNetAddr
73
}
Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net/convert_test.go
+3
-7
@@ -4,8 +4,8 @@ import (
4
"net"
5
"testing"
6
7
- utp "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/h2so5/utp"
7
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
8
+ mautp "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net/utp"
9
)
10
11
type GenFunc func() (ma.Multiaddr, error)
@@ -90,13 +90,9 @@ func TestFromUDP(t *testing.T) {
90
}
91
92
func TestFromUTP(t *testing.T) {
93
+ a := &net.UDPAddr{IP: net.ParseIP("10.20.30.40"), Port: 1234}
94
testConvert(t, "/ip4/10.20.30.40/udp/1234/utp", func() (ma.Multiaddr, error) {
94
- return FromNetAddr(&utp.Addr{
95
- Addr: &net.UDPAddr{
96
- IP: net.ParseIP("10.20.30.40"),
97
- Port: 1234,
98
- },
99
- })
95
+ return FromNetAddr(mautp.MakeAddr(a))
96
})
97
}
98
Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net/multiaddr/multiaddr.go
+2
-2
@@ -10,8 +10,8 @@ import (
10
manet "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
11
)
12
13
-var formats = []string{"string", "bytes", // flags
14
-"hex", "slice"}
13
+// flags
14
+var formats = []string{"string", "bytes", "hex", "slice"}
15
var format string
16
var hideLoopback bool
17
Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net/net.go
+14
-18
@@ -4,8 +4,8 @@ import (
4
"fmt"
5
"net"
6
7
- // utp "github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/h2so5/utp"
7
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
8
+ mautp "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net/utp"
9
)
10
11
// Conn is the equivalent of a net.Conn object. It is the
@@ -109,24 +109,21 @@ func (d *Dialer) Dial(remote ma.Multiaddr) (Conn, error) {
109
// ok, Dial!
110
var nconn net.Conn
111
switch rnet {
112
- case "tcp", "tcp4", "tcp6":
112
+ case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6":
113
nconn, err = d.Dialer.Dial(rnet, rnaddr)
114
if err != nil {
115
return nil, err
116
}
117
- case "udp", "udp4", "udp6":
118
- return nil, fmt.Errorf("utp is currently broken")
119
-
120
- // // construct utp dialer, with options on our net.Dialer
121
- // utpd := utp.Dialer{
122
- // Timeout: d.Dialer.Timeout,
123
- // LocalAddr: d.Dialer.LocalAddr,
124
- // }
125
- //
126
- // nconn, err = utpd.Dial(rnet, rnaddr)
127
- // if err != nil {
128
- // return nil, err
129
- // }
117
+ case "utp", "utp4", "utp6":
118
+ utpd := mautp.Dialer{
119
+ Timeout: d.Timeout,
120
+ LocalAddr: d.Dialer.LocalAddr,
121
+ }
122
+ // construct utp dialer, with options on our net.Dialer
123
+ nconn, err = utpd.Dial(rnet, rnaddr)
124
+ if err != nil {
125
+ return nil, err
126
+ }
127
}
128
129
// get local address (pre-specified or assigned within net.Conn)
@@ -229,9 +226,8 @@ func Listen(laddr ma.Multiaddr) (Listener, error) {
226
227
var nl net.Listener
228
switch lnet {
232
- case "utp":
233
- // nl, err = utp.Listen(lnet, lnaddr)
234
- return nil, fmt.Errorf("utp is currently broken")
229
+ case "utp", "utp4", "utp6":
230
+ nl, err = mautp.Listen(lnet, lnaddr)
231
default:
232
nl, err = net.Listen(lnet, lnaddr)
233
}
Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net/net_test.go
+3
-3
@@ -246,12 +246,10 @@ func TestListenAndDial(t *testing.T) {
246
}
247
248
func TestListenAndDialUTP(t *testing.T) {
249
- t.Skip("utp is broken")
250
-
249
maddr := newMultiaddr(t, "/ip4/127.0.0.1/udp/4323/utp")
250
listener, err := Listen(maddr)
251
if err != nil {
254
- t.Fatal("failed to listen")
252
+ t.Fatal("failed to listen: ", err)
253
}
254
255
var wg sync.WaitGroup
@@ -267,6 +265,8 @@ func TestListenAndDialUTP(t *testing.T) {
265
t.Fatal("local multiaddr not equal:", maddr, cB.LocalMultiaddr())
266
}
267
268
+ defer cB.Close()
269
+
270
// echo out
271
buf := make([]byte, 1024)
272
for {
Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net/utp/utp_util.go
new
+105
@@ -0,0 +1,105 @@
1
+package utp
2
+
3
+import (
4
+ "errors"
5
+ "net"
6
+ "time"
7
+
8
+ utp "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/anacrolix/utp"
9
+)
10
+
11
+type Listener struct {
12
+ *utp.Socket
13
+}
14
+
15
+type Conn struct {
16
+ net.Conn
17
+}
18
+
19
+type Addr struct {
20
+ net string
21
+ child net.Addr
22
+}
23
+
24
+func (ca *Addr) Network() string {
25
+ return ca.net
26
+}
27
+
28
+func (ca *Addr) String() string {
29
+ return ca.child.String()
30
+}
31
+
32
+func (ca *Addr) Child() net.Addr {
33
+ return ca.child
34
+}
35
+
36
+func MakeAddr(a net.Addr) net.Addr {
37
+ return &Addr{
38
+ net: "utp",
39
+ child: a,
40
+ }
41
+}
42
+
43
+func ResolveAddr(network string, host string) (net.Addr, error) {
44
+ a, err := net.ResolveUDPAddr("udp"+network[3:], host)
45
+ if err != nil {
46
+ return nil, err
47
+ }
48
+
49
+ return MakeAddr(a), nil
50
+}
51
+
52
+func (u *Conn) LocalAddr() net.Addr {
53
+ return MakeAddr(u.Conn.LocalAddr())
54
+}
55
+
56
+func (u *Conn) RemoteAddr() net.Addr {
57
+ return MakeAddr(u.Conn.RemoteAddr())
58
+}
59
+
60
+func Listen(network string, laddr string) (net.Listener, error) {
61
+ switch network {
62
+ case "utp", "utp4", "utp6":
63
+ s, err := utp.NewSocket("udp"+network[3:], laddr)
64
+ if err != nil {
65
+ return nil, err
66
+ }
67
+
68
+ return &Listener{s}, nil
69
+
70
+ default:
71
+ return nil, errors.New("unrecognized network: " + network)
72
+ }
73
+}
74
+
75
+func (u *Listener) Accept() (net.Conn, error) {
76
+ c, err := u.Socket.Accept()
77
+ if err != nil {
78
+ return nil, err
79
+ }
80
+
81
+ return &Conn{c}, nil
82
+}
83
+
84
+func (u *Listener) Addr() net.Addr {
85
+ return MakeAddr(u.Socket.Addr())
86
+}
87
+
88
+type Dialer struct {
89
+ Timeout time.Duration
90
+ LocalAddr net.Addr
91
+}
92
+
93
+func (d *Dialer) Dial(rnet string, raddr string) (net.Conn, error) {
94
+ if d.LocalAddr != nil {
95
+ s, err := utp.NewSocket(d.LocalAddr.Network(), d.LocalAddr.String())
96
+ if err != nil {
97
+ return nil, err
98
+ }
99
+
100
+ // zero timeout is the same as calling s.Dial()
101
+ return s.DialTimeout(raddr, d.Timeout)
102
+ }
103
+
104
+ return utp.DialTimeout(raddr, d.Timeout)
105
+}