@cryptotaxi247 / kubo / commits / 67d17c642

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 +[![GoDoc](https://godoc.org/github.com/anacrolix/utp?status.svg)](https://godoc.org/github.com/anacrolix/utp)
3 +[![Build Status](https://drone.io/github.com/anacrolix/utp/status.png)](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 -[![Build status](https://ci.appveyor.com/api/projects/status/j1be8y7p6nd2wqqw?svg=true&branch=master)](https://ci.appveyor.com/project/h2so5/utp)
7 -[![Build Status](https://travis-ci.org/h2so5/utp.svg?branch=master)](https://travis-ci.org/h2so5/utp)
8 -[![GoDoc](https://godoc.org/github.com/h2so5/utp?status.svg)](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 +}