mirror of
https://github.com/logos-messaging/go-multiaddr.git
synced 2026-01-03 21:43:06 +00:00
move deps from godep to gx
This commit is contained in:
parent
4a8bd8f8ba
commit
4d7e08bab8
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
bin/gx*
|
||||||
|
*.swp
|
||||||
17
.travis.yml
17
.travis.yml
@ -1,11 +1,20 @@
|
|||||||
|
os:
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
|
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
|
sudo: false
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.3
|
- 1.5.3
|
||||||
- release
|
|
||||||
- tip
|
install:
|
||||||
|
- make deps
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- make test
|
- make test
|
||||||
|
|
||||||
env: TEST_VERBOSE=1
|
cache:
|
||||||
|
directories:
|
||||||
|
- $GOPATH/src/gx
|
||||||
|
|||||||
43
Godeps/Godeps.json
generated
43
Godeps/Godeps.json
generated
@ -1,43 +0,0 @@
|
|||||||
{
|
|
||||||
"ImportPath": "github.com/jbenet/go-multiaddr-net",
|
|
||||||
"GoVersion": "go1.4.2",
|
|
||||||
"Packages": [
|
|
||||||
"./..."
|
|
||||||
],
|
|
||||||
"Deps": [
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/anacrolix/jitter",
|
|
||||||
"Rev": "2ea5c18645100745b24e9f5cfc9b3f6f7eac51ef"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/anacrolix/missinggo",
|
|
||||||
"Rev": "4e1ca5963308863b56c31863f60c394a7365ec29"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/anacrolix/utp",
|
|
||||||
"Rev": "0bb24de92c268452fb9106ca4fb9302442ca0dee"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/bradfitz/iter",
|
|
||||||
"Rev": "454541ec3da2a73fc34fd049b19ee5777bf19345"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/jbenet/go-base58",
|
|
||||||
"Rev": "568a28d73fd97651d3442392036a658b6976eed5"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/jbenet/go-multiaddr",
|
|
||||||
"Comment": "0.1.2-38-gc13f11b",
|
|
||||||
"Rev": "c13f11bbfe6439771f4df7bfb330f686826144e8"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "github.com/jbenet/go-multihash",
|
|
||||||
"Comment": "0.1.0-36-g87e53a9",
|
|
||||||
"Rev": "87e53a9d2875a18a7863b351d22f912545e6b3a3"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ImportPath": "golang.org/x/crypto/sha3",
|
|
||||||
"Rev": "1351f936d976c60a0a48d728281922cf63eafb8d"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
5
Godeps/Readme
generated
5
Godeps/Readme
generated
@ -1,5 +0,0 @@
|
|||||||
This directory tree is generated automatically by godep.
|
|
||||||
|
|
||||||
Please do not edit.
|
|
||||||
|
|
||||||
See https://github.com/tools/godep for more information.
|
|
||||||
2
Godeps/_workspace/.gitignore
generated
vendored
2
Godeps/_workspace/.gitignore
generated
vendored
@ -1,2 +0,0 @@
|
|||||||
/pkg
|
|
||||||
/bin
|
|
||||||
12
Godeps/_workspace/src/github.com/anacrolix/jitter/jitter.go
generated
vendored
12
Godeps/_workspace/src/github.com/anacrolix/jitter/jitter.go
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
package jitter
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Duration(average, plusMinus time.Duration) (ret time.Duration) {
|
|
||||||
ret = average - plusMinus
|
|
||||||
ret += time.Duration(rand.Int63n(2*int64(plusMinus) + 1))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
72
Godeps/_workspace/src/github.com/anacrolix/missinggo/addr.go
generated
vendored
72
Godeps/_workspace/src/github.com/anacrolix/missinggo/addr.go
generated
vendored
@ -1,72 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type HostMaybePort struct {
|
|
||||||
Host string
|
|
||||||
Port int
|
|
||||||
NoPort bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me HostMaybePort) String() string {
|
|
||||||
if me.NoPort {
|
|
||||||
return me.Host
|
|
||||||
}
|
|
||||||
return net.JoinHostPort(me.Host, strconv.FormatInt(int64(me.Port), 10))
|
|
||||||
}
|
|
||||||
|
|
||||||
func SplitHostPort(hostport string) (ret HostMaybePort) {
|
|
||||||
host, port, err := net.SplitHostPort(hostport)
|
|
||||||
if err != nil {
|
|
||||||
if strings.Contains(err.Error(), "missing port") {
|
|
||||||
ret.Host = hostport
|
|
||||||
ret.NoPort = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
i64, err := strconv.ParseInt(port, 0, 0)
|
|
||||||
ret.Host = host
|
|
||||||
ret.Port = int(i64)
|
|
||||||
if err != nil {
|
|
||||||
ret.NoPort = true
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extracts the port as an integer from an address string.
|
|
||||||
func AddrPort(addr net.Addr) int {
|
|
||||||
switch raw := addr.(type) {
|
|
||||||
case *net.UDPAddr:
|
|
||||||
return raw.Port
|
|
||||||
default:
|
|
||||||
_, port, err := net.SplitHostPort(addr.String())
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
i64, err := strconv.ParseInt(port, 0, 0)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return int(i64)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddrIP(addr net.Addr) net.IP {
|
|
||||||
switch raw := addr.(type) {
|
|
||||||
case *net.UDPAddr:
|
|
||||||
return raw.IP
|
|
||||||
case *net.TCPAddr:
|
|
||||||
return raw.IP
|
|
||||||
default:
|
|
||||||
host, _, err := net.SplitHostPort(addr.String())
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return net.ParseIP(host)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
17
Godeps/_workspace/src/github.com/anacrolix/missinggo/addr_test.go
generated
vendored
17
Godeps/_workspace/src/github.com/anacrolix/missinggo/addr_test.go
generated
vendored
@ -1,17 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSplitHostPort(t *testing.T) {
|
|
||||||
assert.EqualValues(t, HostMaybePort{"a", 1, false}, SplitHostPort("a:1"))
|
|
||||||
assert.EqualValues(t, HostMaybePort{"a", 0, true}, SplitHostPort("a"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHostMaybePortString(t *testing.T) {
|
|
||||||
assert.EqualValues(t, "a:1", (HostMaybePort{"a", 1, false}).String())
|
|
||||||
assert.EqualValues(t, "a", (HostMaybePort{"a", 0, true}).String())
|
|
||||||
}
|
|
||||||
15
Godeps/_workspace/src/github.com/anacrolix/missinggo/args/args.go
generated
vendored
15
Godeps/_workspace/src/github.com/anacrolix/missinggo/args/args.go
generated
vendored
@ -1,15 +0,0 @@
|
|||||||
package args
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Parse() {
|
|
||||||
flag.Parse()
|
|
||||||
if flag.NArg() != 0 {
|
|
||||||
fmt.Fprintf(os.Stderr, "unexpected positional arguments\n")
|
|
||||||
os.Exit(2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
11
Godeps/_workspace/src/github.com/anacrolix/missinggo/atime.go
generated
vendored
11
Godeps/_workspace/src/github.com/anacrolix/missinggo/atime.go
generated
vendored
@ -1,11 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Extracts the access time from the FileInfo internals.
|
|
||||||
func FileInfoAccessTime(fi os.FileInfo) time.Time {
|
|
||||||
return fileInfoAccessTime(fi)
|
|
||||||
}
|
|
||||||
12
Godeps/_workspace/src/github.com/anacrolix/missinggo/atime_darwin.go
generated
vendored
12
Godeps/_workspace/src/github.com/anacrolix/missinggo/atime_darwin.go
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func fileInfoAccessTime(fi os.FileInfo) time.Time {
|
|
||||||
ts := fi.Sys().(*syscall.Stat_t).Atimespec
|
|
||||||
return time.Unix(int64(ts.Sec), int64(ts.Nsec))
|
|
||||||
}
|
|
||||||
12
Godeps/_workspace/src/github.com/anacrolix/missinggo/atime_freebsd.go
generated
vendored
12
Godeps/_workspace/src/github.com/anacrolix/missinggo/atime_freebsd.go
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func fileInfoAccessTime(fi os.FileInfo) time.Time {
|
|
||||||
ts := fi.Sys().(*syscall.Stat_t).Atimespec
|
|
||||||
return time.Unix(int64(ts.Sec), int64(ts.Nsec))
|
|
||||||
}
|
|
||||||
12
Godeps/_workspace/src/github.com/anacrolix/missinggo/atime_linux.go
generated
vendored
12
Godeps/_workspace/src/github.com/anacrolix/missinggo/atime_linux.go
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func fileInfoAccessTime(fi os.FileInfo) time.Time {
|
|
||||||
ts := fi.Sys().(*syscall.Stat_t).Atim
|
|
||||||
return time.Unix(int64(ts.Sec), int64(ts.Nsec))
|
|
||||||
}
|
|
||||||
12
Godeps/_workspace/src/github.com/anacrolix/missinggo/atime_windows.go
generated
vendored
12
Godeps/_workspace/src/github.com/anacrolix/missinggo/atime_windows.go
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func fileInfoAccessTime(fi os.FileInfo) time.Time {
|
|
||||||
ts := fi.Sys().(syscall.Win32FileAttributeData).LastAccessTime
|
|
||||||
return time.Unix(0, int64(ts.Nanoseconds()))
|
|
||||||
}
|
|
||||||
17
Godeps/_workspace/src/github.com/anacrolix/missinggo/castslice.go
generated
vendored
17
Godeps/_workspace/src/github.com/anacrolix/missinggo/castslice.go
generated
vendored
@ -1,17 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
|
|
||||||
"github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/bradfitz/iter"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ConvertToSliceOfEmptyInterface(slice interface{}) (ret []interface{}) {
|
|
||||||
v := reflect.ValueOf(slice)
|
|
||||||
l := v.Len()
|
|
||||||
ret = make([]interface{}, 0, l)
|
|
||||||
for i := range iter.N(v.Len()) {
|
|
||||||
ret = append(ret, v.Index(i).Interface())
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
12
Godeps/_workspace/src/github.com/anacrolix/missinggo/cmd/go-env/main.go
generated
vendored
12
Godeps/_workspace/src/github.com/anacrolix/missinggo/cmd/go-env/main.go
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
for _, v := range os.Environ() {
|
|
||||||
fmt.Printf("%s\n", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
3
Godeps/_workspace/src/github.com/anacrolix/missinggo/cmd/nop/main.go
generated
vendored
3
Godeps/_workspace/src/github.com/anacrolix/missinggo/cmd/nop/main.go
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
func main() {}
|
|
||||||
11
Godeps/_workspace/src/github.com/anacrolix/missinggo/cmd/query-escape/main.go
generated
vendored
11
Godeps/_workspace/src/github.com/anacrolix/missinggo/cmd/query-escape/main.go
generated
vendored
@ -1,11 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Println(url.QueryEscape(os.Args[1]))
|
|
||||||
}
|
|
||||||
11
Godeps/_workspace/src/github.com/anacrolix/missinggo/cmd/query-unescape/main.go
generated
vendored
11
Godeps/_workspace/src/github.com/anacrolix/missinggo/cmd/query-unescape/main.go
generated
vendored
@ -1,11 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
fmt.Println(url.QueryUnescape(os.Args[1]))
|
|
||||||
}
|
|
||||||
32
Godeps/_workspace/src/github.com/anacrolix/missinggo/copy.go
generated
vendored
32
Godeps/_workspace/src/github.com/anacrolix/missinggo/copy.go
generated
vendored
@ -1,32 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CopyExact(dest interface{}, src interface{}) {
|
|
||||||
dV := reflect.ValueOf(dest)
|
|
||||||
sV := reflect.ValueOf(src)
|
|
||||||
if dV.Kind() == reflect.Ptr {
|
|
||||||
dV = dV.Elem()
|
|
||||||
}
|
|
||||||
if dV.Kind() == reflect.Array && !dV.CanAddr() {
|
|
||||||
panic(fmt.Sprintf("dest not addressable: %T", dest))
|
|
||||||
}
|
|
||||||
if sV.Kind() == reflect.Ptr {
|
|
||||||
sV = sV.Elem()
|
|
||||||
}
|
|
||||||
if sV.Kind() == reflect.String {
|
|
||||||
sV = sV.Convert(reflect.SliceOf(dV.Type().Elem()))
|
|
||||||
}
|
|
||||||
if !sV.IsValid() {
|
|
||||||
panic("invalid source, probably nil")
|
|
||||||
}
|
|
||||||
if dV.Len() != sV.Len() {
|
|
||||||
panic(fmt.Sprintf("dest len (%d) != src len (%d)", dV.Len(), sV.Len()))
|
|
||||||
}
|
|
||||||
if dV.Len() != reflect.Copy(dV, sV) {
|
|
||||||
panic("dammit")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
89
Godeps/_workspace/src/github.com/anacrolix/missinggo/copy_test.go
generated
vendored
89
Godeps/_workspace/src/github.com/anacrolix/missinggo/copy_test.go
generated
vendored
@ -1,89 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCopyToArray(t *testing.T) {
|
|
||||||
var arr [3]byte
|
|
||||||
bb := []byte{1, 2, 3}
|
|
||||||
CopyExact(&arr, bb)
|
|
||||||
if !bytes.Equal(arr[:], bb) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCopyToSlicedArray(t *testing.T) {
|
|
||||||
var arr [5]byte
|
|
||||||
CopyExact(arr[:], "hello")
|
|
||||||
if !bytes.Equal(arr[:], []byte("hello")) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCopyDestNotAddr(t *testing.T) {
|
|
||||||
defer func() {
|
|
||||||
r := recover()
|
|
||||||
if r == nil {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
t.Log(r)
|
|
||||||
}()
|
|
||||||
var arr [3]byte
|
|
||||||
CopyExact(arr, "nope")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCopyLenMismatch(t *testing.T) {
|
|
||||||
defer func() {
|
|
||||||
r := recover()
|
|
||||||
if r == nil {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
t.Log(r)
|
|
||||||
}()
|
|
||||||
CopyExact(make([]byte, 2), "abc")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCopySrcString(t *testing.T) {
|
|
||||||
dest := make([]byte, 3)
|
|
||||||
CopyExact(dest, "lol")
|
|
||||||
if string(dest) != "lol" {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
func() {
|
|
||||||
defer func() {
|
|
||||||
r := recover()
|
|
||||||
if r == nil {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
CopyExact(dest, "rofl")
|
|
||||||
}()
|
|
||||||
var arr [5]byte
|
|
||||||
CopyExact(&arr, interface{}("hello"))
|
|
||||||
if string(arr[:]) != "hello" {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCopySrcNilInterface(t *testing.T) {
|
|
||||||
var arr [3]byte
|
|
||||||
defer func() {
|
|
||||||
r := recover().(string)
|
|
||||||
if !strings.Contains(r, "invalid source") {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
CopyExact(&arr, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCopySrcPtr(t *testing.T) {
|
|
||||||
var bigDst [1024]byte
|
|
||||||
var bigSrc [1024]byte = [1024]byte{'h', 'i'}
|
|
||||||
CopyExact(&bigDst, &bigSrc)
|
|
||||||
if !bytes.Equal(bigDst[:], bigSrc[:]) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
18
Godeps/_workspace/src/github.com/anacrolix/missinggo/croak.go
generated
vendored
18
Godeps/_workspace/src/github.com/anacrolix/missinggo/croak.go
generated
vendored
@ -1,18 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Unchomp(s string) string {
|
|
||||||
if len(s) > 0 && s[len(s)-1] == '\n' {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
return s + "\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
func Fatal(msg interface{}) {
|
|
||||||
os.Stderr.WriteString(Unchomp(fmt.Sprint(msg)))
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
3
Godeps/_workspace/src/github.com/anacrolix/missinggo/doc.go
generated
vendored
3
Godeps/_workspace/src/github.com/anacrolix/missinggo/doc.go
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
// Package missinggo contains miscellaneous helpers used in many of anacrolix'
|
|
||||||
// projects.
|
|
||||||
package missinggo
|
|
||||||
35
Godeps/_workspace/src/github.com/anacrolix/missinggo/expvarIndentMap.go
generated
vendored
35
Godeps/_workspace/src/github.com/anacrolix/missinggo/expvarIndentMap.go
generated
vendored
@ -1,35 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"expvar"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IndentMap struct {
|
|
||||||
expvar.Map
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ expvar.Var = &IndentMap{}
|
|
||||||
|
|
||||||
func NewExpvarIndentMap(name string) *IndentMap {
|
|
||||||
v := new(IndentMap)
|
|
||||||
v.Init()
|
|
||||||
expvar.Publish(name, v)
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *IndentMap) String() string {
|
|
||||||
var b bytes.Buffer
|
|
||||||
fmt.Fprintf(&b, "{")
|
|
||||||
first := true
|
|
||||||
v.Do(func(kv expvar.KeyValue) {
|
|
||||||
if !first {
|
|
||||||
fmt.Fprintf(&b, ",")
|
|
||||||
}
|
|
||||||
fmt.Fprintf(&b, "\n\t%q: %v", kv.Key, kv.Value)
|
|
||||||
first = false
|
|
||||||
})
|
|
||||||
fmt.Fprintf(&b, "}")
|
|
||||||
return b.String()
|
|
||||||
}
|
|
||||||
269
Godeps/_workspace/src/github.com/anacrolix/missinggo/filecache/cache.go
generated
vendored
269
Godeps/_workspace/src/github.com/anacrolix/missinggo/filecache/cache.go
generated
vendored
@ -1,269 +0,0 @@
|
|||||||
package filecache
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/anacrolix/missinggo"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Cache struct {
|
|
||||||
mu sync.Mutex
|
|
||||||
capacity int64
|
|
||||||
filled int64
|
|
||||||
items *lruItems
|
|
||||||
paths map[string]ItemInfo
|
|
||||||
root string
|
|
||||||
}
|
|
||||||
|
|
||||||
type CacheInfo struct {
|
|
||||||
Capacity int64
|
|
||||||
Filled int64
|
|
||||||
NumItems int
|
|
||||||
}
|
|
||||||
|
|
||||||
type ItemInfo struct {
|
|
||||||
Accessed time.Time
|
|
||||||
Size int64
|
|
||||||
Path string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calls the function for every item known to the cache. The ItemInfo should
|
|
||||||
// not be modified.
|
|
||||||
func (me *Cache) WalkItems(cb func(ItemInfo)) {
|
|
||||||
me.mu.Lock()
|
|
||||||
defer me.mu.Unlock()
|
|
||||||
for e := me.items.Front(); e != nil; e = e.Next() {
|
|
||||||
cb(e.Value().(ItemInfo))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *Cache) Info() (ret CacheInfo) {
|
|
||||||
me.mu.Lock()
|
|
||||||
defer me.mu.Unlock()
|
|
||||||
ret.Capacity = me.capacity
|
|
||||||
ret.Filled = me.filled
|
|
||||||
ret.NumItems = len(me.paths)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *Cache) SetCapacity(capacity int64) {
|
|
||||||
me.mu.Lock()
|
|
||||||
defer me.mu.Unlock()
|
|
||||||
me.capacity = capacity
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewCache(root string) (ret *Cache, err error) {
|
|
||||||
if !filepath.IsAbs(root) {
|
|
||||||
err = errors.New("root is not an absolute filepath")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ret = &Cache{
|
|
||||||
root: root,
|
|
||||||
capacity: -1, // unlimited
|
|
||||||
}
|
|
||||||
ret.mu.Lock()
|
|
||||||
go func() {
|
|
||||||
defer ret.mu.Unlock()
|
|
||||||
ret.rescan()
|
|
||||||
}()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// An empty return path is an error.
|
|
||||||
func sanitizePath(p string) (ret string) {
|
|
||||||
if p == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ret = path.Clean("/" + p)
|
|
||||||
if ret[0] == '/' {
|
|
||||||
ret = ret[1:]
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Leaf is a descendent of root.
|
|
||||||
func pruneEmptyDirs(root string, leaf string) (err error) {
|
|
||||||
rootInfo, err := os.Stat(root)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
var leafInfo os.FileInfo
|
|
||||||
leafInfo, err = os.Stat(leaf)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
goto parent
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !leafInfo.IsDir() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if os.SameFile(rootInfo, leafInfo) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if os.Remove(leaf) != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
parent:
|
|
||||||
leaf = filepath.Dir(leaf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *Cache) Remove(path string) (err error) {
|
|
||||||
path = sanitizePath(path)
|
|
||||||
me.mu.Lock()
|
|
||||||
defer me.mu.Unlock()
|
|
||||||
err = me.remove(path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrBadPath = errors.New("bad path")
|
|
||||||
ErrIsDir = errors.New("is directory")
|
|
||||||
)
|
|
||||||
|
|
||||||
func (me *Cache) OpenFile(path string, flag int) (ret *File, err error) {
|
|
||||||
path = sanitizePath(path)
|
|
||||||
if path == "" {
|
|
||||||
err = ErrIsDir
|
|
||||||
return
|
|
||||||
}
|
|
||||||
f, err := os.OpenFile(me.realpath(path), flag, 0644)
|
|
||||||
if flag&os.O_CREATE != 0 && os.IsNotExist(err) {
|
|
||||||
os.MkdirAll(me.root, 0755)
|
|
||||||
os.MkdirAll(filepath.Dir(me.realpath(path)), 0755)
|
|
||||||
f, err = os.OpenFile(me.realpath(path), flag, 0644)
|
|
||||||
if err != nil {
|
|
||||||
me.pruneEmptyDirs(path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ret = &File{
|
|
||||||
c: me,
|
|
||||||
path: path,
|
|
||||||
f: f,
|
|
||||||
}
|
|
||||||
me.mu.Lock()
|
|
||||||
go func() {
|
|
||||||
defer me.mu.Unlock()
|
|
||||||
me.statItem(path, time.Now())
|
|
||||||
}()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *Cache) rescan() {
|
|
||||||
me.filled = 0
|
|
||||||
me.items = newLRUItems()
|
|
||||||
me.paths = make(map[string]ItemInfo)
|
|
||||||
err := filepath.Walk(me.root, func(path string, info os.FileInfo, err error) error {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if info.IsDir() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
path, err = filepath.Rel(me.root, path)
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
me.statItem(path, time.Time{})
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *Cache) insertItem(i ItemInfo) {
|
|
||||||
me.items.Insert(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *Cache) removeInfo(path string) (ret ItemInfo, ok bool) {
|
|
||||||
ret, ok = me.paths[path]
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !me.items.Remove(ret) {
|
|
||||||
panic(ret)
|
|
||||||
}
|
|
||||||
me.filled -= ret.Size
|
|
||||||
delete(me.paths, path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Triggers the item for path to be updated. If access is non-zero, set the
|
|
||||||
// item's access time to that value, otherwise deduce it appropriately.
|
|
||||||
func (me *Cache) statItem(path string, access time.Time) {
|
|
||||||
info, ok := me.removeInfo(path)
|
|
||||||
fi, err := os.Stat(me.realpath(path))
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
info.Path = path
|
|
||||||
}
|
|
||||||
if !access.IsZero() {
|
|
||||||
info.Accessed = access
|
|
||||||
}
|
|
||||||
if info.Accessed.IsZero() {
|
|
||||||
info.Accessed = missinggo.FileInfoAccessTime(fi)
|
|
||||||
}
|
|
||||||
info.Size = fi.Size()
|
|
||||||
me.filled += info.Size
|
|
||||||
me.insertItem(info)
|
|
||||||
me.paths[path] = info
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *Cache) realpath(path string) string {
|
|
||||||
return filepath.Join(me.root, filepath.FromSlash(path))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *Cache) TrimToCapacity() {
|
|
||||||
me.mu.Lock()
|
|
||||||
defer me.mu.Unlock()
|
|
||||||
me.trimToCapacity()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *Cache) pruneEmptyDirs(path string) {
|
|
||||||
pruneEmptyDirs(me.root, me.realpath(path))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *Cache) remove(path string) (err error) {
|
|
||||||
err = os.Remove(me.realpath(path))
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
err = nil
|
|
||||||
}
|
|
||||||
me.pruneEmptyDirs(path)
|
|
||||||
me.removeInfo(path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *Cache) trimToCapacity() {
|
|
||||||
if me.capacity < 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for me.filled > me.capacity {
|
|
||||||
item := me.items.LRU()
|
|
||||||
me.remove(item.Path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *Cache) pathInfo(p string) ItemInfo {
|
|
||||||
return me.paths[p]
|
|
||||||
}
|
|
||||||
84
Godeps/_workspace/src/github.com/anacrolix/missinggo/filecache/cache_test.go
generated
vendored
84
Godeps/_workspace/src/github.com/anacrolix/missinggo/filecache/cache_test.go
generated
vendored
@ -1,84 +0,0 @@
|
|||||||
package filecache
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/anacrolix/missinggo"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCache(t *testing.T) {
|
|
||||||
td, err := ioutil.TempDir("", "gotest")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(td)
|
|
||||||
c, err := NewCache(filepath.Join(td, "cache"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
assert.EqualValues(t, 0, c.Info().Filled)
|
|
||||||
c.WalkItems(func(i ItemInfo) {})
|
|
||||||
_, err = c.OpenFile("/", os.O_CREATE)
|
|
||||||
assert.NotNil(t, err)
|
|
||||||
_, err = c.OpenFile("", os.O_CREATE)
|
|
||||||
assert.NotNil(t, err)
|
|
||||||
c.WalkItems(func(i ItemInfo) {})
|
|
||||||
require.Equal(t, 0, c.Info().NumItems)
|
|
||||||
_, err = c.OpenFile("notexist", 0)
|
|
||||||
assert.True(t, os.IsNotExist(err), err)
|
|
||||||
_, err = c.OpenFile("/notexist", 0)
|
|
||||||
assert.True(t, os.IsNotExist(err), err)
|
|
||||||
_, err = c.OpenFile("/dir/notexist", 0)
|
|
||||||
assert.True(t, os.IsNotExist(err), err)
|
|
||||||
f, err := c.OpenFile("dir/blah", os.O_CREATE)
|
|
||||||
require.NoError(t, err)
|
|
||||||
defer f.Close()
|
|
||||||
c.WalkItems(func(i ItemInfo) {})
|
|
||||||
assert.True(t, missinggo.FilePathExists(filepath.Join(td, filepath.FromSlash("cache/dir/blah"))))
|
|
||||||
assert.True(t, missinggo.FilePathExists(filepath.Join(td, filepath.FromSlash("cache/dir/"))))
|
|
||||||
assert.Equal(t, 1, c.Info().NumItems)
|
|
||||||
f.Remove()
|
|
||||||
assert.False(t, missinggo.FilePathExists(filepath.Join(td, filepath.FromSlash("dir/blah"))))
|
|
||||||
assert.False(t, missinggo.FilePathExists(filepath.Join(td, filepath.FromSlash("dir/"))))
|
|
||||||
_, err = f.Read(nil)
|
|
||||||
assert.NotEqual(t, io.EOF, err)
|
|
||||||
a, err := c.OpenFile("/a", os.O_CREATE|os.O_WRONLY)
|
|
||||||
defer a.Close()
|
|
||||||
require.Nil(t, err)
|
|
||||||
b, err := c.OpenFile("b", os.O_CREATE|os.O_WRONLY)
|
|
||||||
defer b.Close()
|
|
||||||
require.Nil(t, err)
|
|
||||||
c.mu.Lock()
|
|
||||||
assert.True(t, c.pathInfo("a").Accessed.Before(c.pathInfo("b").Accessed))
|
|
||||||
c.mu.Unlock()
|
|
||||||
n, err := a.Write([]byte("hello"))
|
|
||||||
assert.Nil(t, err)
|
|
||||||
assert.EqualValues(t, 5, n)
|
|
||||||
assert.EqualValues(t, 5, c.Info().Filled)
|
|
||||||
assert.True(t, c.pathInfo("b").Accessed.Before(c.pathInfo("a").Accessed))
|
|
||||||
c.SetCapacity(5)
|
|
||||||
n, err = a.Write([]byte(" world"))
|
|
||||||
assert.NotNil(t, err)
|
|
||||||
_, err = b.Write([]byte("boom!"))
|
|
||||||
// "a" and "b" have been evicted.
|
|
||||||
assert.NotNil(t, err)
|
|
||||||
assert.EqualValues(t, 0, c.Info().Filled)
|
|
||||||
assert.EqualValues(t, 0, c.Info().NumItems)
|
|
||||||
_, err = a.Seek(0, os.SEEK_SET)
|
|
||||||
assert.NotNil(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSanitizePath(t *testing.T) {
|
|
||||||
assert.Equal(t, "", sanitizePath("////"))
|
|
||||||
assert.Equal(t, "", sanitizePath("/../.."))
|
|
||||||
assert.Equal(t, "a", sanitizePath("/a//b/.."))
|
|
||||||
assert.Equal(t, "a", sanitizePath("../a"))
|
|
||||||
assert.Equal(t, "a", sanitizePath("./a"))
|
|
||||||
}
|
|
||||||
117
Godeps/_workspace/src/github.com/anacrolix/missinggo/filecache/file.go
generated
vendored
117
Godeps/_workspace/src/github.com/anacrolix/missinggo/filecache/file.go
generated
vendored
@ -1,117 +0,0 @@
|
|||||||
package filecache
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"math"
|
|
||||||
"os"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type File struct {
|
|
||||||
mu sync.Mutex
|
|
||||||
c *Cache
|
|
||||||
path string
|
|
||||||
f *os.File
|
|
||||||
gone bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *File) Remove() (err error) {
|
|
||||||
return me.c.Remove(me.path)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *File) Seek(offset int64, whence int) (ret int64, err error) {
|
|
||||||
ret, err = me.f.Seek(offset, whence)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *File) maxWrite() (max int64, err error) {
|
|
||||||
if me.c.capacity < 0 {
|
|
||||||
max = math.MaxInt64
|
|
||||||
return
|
|
||||||
}
|
|
||||||
pos, err := me.Seek(0, os.SEEK_CUR)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
max = me.c.capacity - pos
|
|
||||||
if max < 0 {
|
|
||||||
max = 0
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrFileTooLarge = errors.New("file too large for cache")
|
|
||||||
ErrFileDisappeared = errors.New("file disappeared")
|
|
||||||
)
|
|
||||||
|
|
||||||
func (me *File) checkGone() {
|
|
||||||
if me.gone {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ffi, _ := me.Stat()
|
|
||||||
fsfi, _ := os.Stat(me.c.realpath(me.path))
|
|
||||||
me.gone = !os.SameFile(ffi, fsfi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *File) goneErr() error {
|
|
||||||
me.mu.Lock()
|
|
||||||
defer me.mu.Unlock()
|
|
||||||
me.checkGone()
|
|
||||||
if me.gone {
|
|
||||||
me.f.Close()
|
|
||||||
return ErrFileDisappeared
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *File) Write(b []byte) (n int, err error) {
|
|
||||||
err = me.goneErr()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
n, err = me.f.Write(b)
|
|
||||||
me.c.mu.Lock()
|
|
||||||
me.c.statItem(me.path, time.Now())
|
|
||||||
me.c.trimToCapacity()
|
|
||||||
me.c.mu.Unlock()
|
|
||||||
if err == nil {
|
|
||||||
err = me.goneErr()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *File) Close() error {
|
|
||||||
return me.f.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *File) Stat() (os.FileInfo, error) {
|
|
||||||
return me.f.Stat()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *File) Read(b []byte) (n int, err error) {
|
|
||||||
err = me.goneErr()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
me.c.mu.Lock()
|
|
||||||
defer me.c.mu.Unlock()
|
|
||||||
me.c.statItem(me.path, time.Now())
|
|
||||||
}()
|
|
||||||
return me.f.Read(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *File) ReadAt(b []byte, off int64) (n int, err error) {
|
|
||||||
err = me.goneErr()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
me.c.mu.Lock()
|
|
||||||
defer me.c.mu.Unlock()
|
|
||||||
me.c.statItem(me.path, time.Now())
|
|
||||||
}()
|
|
||||||
return me.f.ReadAt(b, off)
|
|
||||||
}
|
|
||||||
94
Godeps/_workspace/src/github.com/anacrolix/missinggo/filecache/lruitems.go
generated
vendored
94
Godeps/_workspace/src/github.com/anacrolix/missinggo/filecache/lruitems.go
generated
vendored
@ -1,94 +0,0 @@
|
|||||||
package filecache
|
|
||||||
|
|
||||||
import (
|
|
||||||
"container/list"
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/cznic/b"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Iterator interface {
|
|
||||||
Next() Iterator
|
|
||||||
Value() interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type listElementIterator struct {
|
|
||||||
le *list.Element
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me listElementIterator) Next() Iterator {
|
|
||||||
e := me.le.Next()
|
|
||||||
if e == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return listElementIterator{e}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me listElementIterator) Value() interface{} {
|
|
||||||
return me.le.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
func newLRUItems() *lruItems {
|
|
||||||
return &lruItems{b.TreeNew(func(_a, _b interface{}) int {
|
|
||||||
a := _a.(ItemInfo)
|
|
||||||
b := _b.(ItemInfo)
|
|
||||||
if a.Accessed != b.Accessed {
|
|
||||||
if a.Accessed.Before(b.Accessed) {
|
|
||||||
return -1
|
|
||||||
} else {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if a.Path == b.Path {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if a.Path < b.Path {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
return 1
|
|
||||||
})}
|
|
||||||
}
|
|
||||||
|
|
||||||
type lruItems struct {
|
|
||||||
tree *b.Tree
|
|
||||||
}
|
|
||||||
|
|
||||||
type bEnumeratorIterator struct {
|
|
||||||
e *b.Enumerator
|
|
||||||
v ItemInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me bEnumeratorIterator) Next() Iterator {
|
|
||||||
_, v, err := me.e.Next()
|
|
||||||
if err == io.EOF {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return bEnumeratorIterator{me.e, v.(ItemInfo)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me bEnumeratorIterator) Value() interface{} {
|
|
||||||
return me.v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *lruItems) Front() Iterator {
|
|
||||||
e, _ := me.tree.SeekFirst()
|
|
||||||
if e == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return bEnumeratorIterator{
|
|
||||||
e: e,
|
|
||||||
}.Next()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *lruItems) LRU() ItemInfo {
|
|
||||||
_, v := me.tree.First()
|
|
||||||
return v.(ItemInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *lruItems) Insert(ii ItemInfo) {
|
|
||||||
me.tree.Set(ii, ii)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *lruItems) Remove(ii ItemInfo) bool {
|
|
||||||
return me.tree.Delete(ii)
|
|
||||||
}
|
|
||||||
22
Godeps/_workspace/src/github.com/anacrolix/missinggo/filecache/lruitems_test.go
generated
vendored
22
Godeps/_workspace/src/github.com/anacrolix/missinggo/filecache/lruitems_test.go
generated
vendored
@ -1,22 +0,0 @@
|
|||||||
package filecache
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/bradfitz/iter"
|
|
||||||
)
|
|
||||||
|
|
||||||
func BenchmarkInsert(b *testing.B) {
|
|
||||||
for _ = range iter.N(b.N) {
|
|
||||||
li := newLRUItems()
|
|
||||||
for _ = range iter.N(10000) {
|
|
||||||
r := rand.Int63()
|
|
||||||
t := time.Unix(r/1e9, r%1e9)
|
|
||||||
li.Insert(ItemInfo{
|
|
||||||
Accessed: t,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
38
Godeps/_workspace/src/github.com/anacrolix/missinggo/httpcontentrange.go
generated
vendored
38
Godeps/_workspace/src/github.com/anacrolix/missinggo/httpcontentrange.go
generated
vendored
@ -1,38 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
type HTTPBytesContentRange struct {
|
|
||||||
First, Last, Length int64
|
|
||||||
}
|
|
||||||
|
|
||||||
var bytesContentRangeRegexp = regexp.MustCompile(`bytes[ =](\d+)-(\d+)/(\d+|\*)`)
|
|
||||||
|
|
||||||
func ParseHTTPBytesContentRange(s string) (ret HTTPBytesContentRange, ok bool) {
|
|
||||||
ss := bytesContentRangeRegexp.FindStringSubmatch(s)
|
|
||||||
if ss == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
ret.First, err = strconv.ParseInt(ss[1], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ret.Last, err = strconv.ParseInt(ss[2], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if ss[3] == "*" {
|
|
||||||
ret.Length = -1
|
|
||||||
} else {
|
|
||||||
ret.Length, err = strconv.ParseInt(ss[3], 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ok = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
27
Godeps/_workspace/src/github.com/anacrolix/missinggo/httpcontentrange_test.go
generated
vendored
27
Godeps/_workspace/src/github.com/anacrolix/missinggo/httpcontentrange_test.go
generated
vendored
@ -1,27 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestParseHTTPContentRange(t *testing.T) {
|
|
||||||
for _, _case := range []struct {
|
|
||||||
h string
|
|
||||||
cr *HTTPBytesContentRange
|
|
||||||
}{
|
|
||||||
{"", nil},
|
|
||||||
{"1-2/*", nil},
|
|
||||||
{"bytes=1-2/3", &HTTPBytesContentRange{1, 2, 3}},
|
|
||||||
{"bytes=12-34/*", &HTTPBytesContentRange{12, 34, -1}},
|
|
||||||
{" bytes=12-34/*", &HTTPBytesContentRange{12, 34, -1}},
|
|
||||||
{" bytes 12-34/56", &HTTPBytesContentRange{12, 34, 56}},
|
|
||||||
} {
|
|
||||||
ret, ok := ParseHTTPBytesContentRange(_case.h)
|
|
||||||
assert.Equal(t, _case.cr != nil, ok)
|
|
||||||
if _case.cr != nil {
|
|
||||||
assert.Equal(t, *_case.cr, ret)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
222
Godeps/_workspace/src/github.com/anacrolix/missinggo/httpfile/httpfile.go
generated
vendored
222
Godeps/_workspace/src/github.com/anacrolix/missinggo/httpfile/httpfile.go
generated
vendored
@ -1,222 +0,0 @@
|
|||||||
package httpfile
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/anacrolix/missinggo"
|
|
||||||
)
|
|
||||||
|
|
||||||
type File struct {
|
|
||||||
off int64
|
|
||||||
r io.ReadCloser
|
|
||||||
rOff int64
|
|
||||||
length int64
|
|
||||||
url string
|
|
||||||
}
|
|
||||||
|
|
||||||
func OpenSectionReader(url string, off, n int64) (ret io.ReadCloser, err error) {
|
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", off, off+n-1))
|
|
||||||
resp, err := http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if resp.StatusCode == http.StatusNotFound {
|
|
||||||
err = ErrNotFound
|
|
||||||
resp.Body.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if resp.StatusCode != http.StatusPartialContent {
|
|
||||||
err = fmt.Errorf("bad response status: %s", resp.Status)
|
|
||||||
resp.Body.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ret = resp.Body
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func Open(url string) *File {
|
|
||||||
return &File{
|
|
||||||
url: url,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *File) prepareReader() (err error) {
|
|
||||||
if me.r != nil && me.off != me.rOff {
|
|
||||||
me.r.Close()
|
|
||||||
me.r = nil
|
|
||||||
}
|
|
||||||
if me.r != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
req, err := http.NewRequest("GET", me.url, nil)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if me.off != 0 {
|
|
||||||
req.Header.Set("Range", fmt.Sprintf("bytes=%d-", me.off))
|
|
||||||
}
|
|
||||||
resp, err := http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch resp.StatusCode {
|
|
||||||
case http.StatusPartialContent:
|
|
||||||
cr, ok := missinggo.ParseHTTPBytesContentRange(resp.Header.Get("Content-Range"))
|
|
||||||
if !ok || cr.First != me.off {
|
|
||||||
err = errors.New("bad response")
|
|
||||||
resp.Body.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
me.length = cr.Length
|
|
||||||
case http.StatusOK:
|
|
||||||
if me.off != 0 {
|
|
||||||
err = errors.New("bad response")
|
|
||||||
resp.Body.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if h := resp.Header.Get("Content-Length"); h != "" {
|
|
||||||
var cl uint64
|
|
||||||
cl, err = strconv.ParseUint(h, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
resp.Body.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
me.length = int64(cl)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
err = errors.New(resp.Status)
|
|
||||||
resp.Body.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
me.r = resp.Body
|
|
||||||
me.rOff = me.off
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *File) Read(b []byte) (n int, err error) {
|
|
||||||
err = me.prepareReader()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
n, err = me.r.Read(b)
|
|
||||||
me.off += int64(n)
|
|
||||||
me.rOff += int64(n)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func instanceLength(r *http.Response) (int64, error) {
|
|
||||||
switch r.StatusCode {
|
|
||||||
case http.StatusOK:
|
|
||||||
if h := r.Header.Get("Content-Length"); h != "" {
|
|
||||||
return strconv.ParseInt(h, 10, 64)
|
|
||||||
} else {
|
|
||||||
return -1, nil
|
|
||||||
}
|
|
||||||
case http.StatusPartialContent:
|
|
||||||
cr, ok := missinggo.ParseHTTPBytesContentRange(r.Header.Get("Content-Range"))
|
|
||||||
if !ok {
|
|
||||||
return -1, errors.New("bad 206 response")
|
|
||||||
}
|
|
||||||
return cr.Length, nil
|
|
||||||
default:
|
|
||||||
return -1, errors.New(r.Status)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *File) Seek(offset int64, whence int) (ret int64, err error) {
|
|
||||||
switch whence {
|
|
||||||
case os.SEEK_SET:
|
|
||||||
ret = offset
|
|
||||||
case os.SEEK_CUR:
|
|
||||||
ret = me.off + offset
|
|
||||||
case os.SEEK_END:
|
|
||||||
if me.length < 0 {
|
|
||||||
err = errors.New("length unknown")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ret = me.length + offset
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("unhandled whence: %d", whence)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
me.off = ret
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *File) Write(b []byte) (n int, err error) {
|
|
||||||
req, err := http.NewRequest("PATCH", me.url, bytes.NewReader(b))
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
req.Header.Set("Content-Range", fmt.Sprintf("bytes=%d-", me.off))
|
|
||||||
req.ContentLength = int64(len(b))
|
|
||||||
resp, err := http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp.Body.Close()
|
|
||||||
if resp.StatusCode != http.StatusPartialContent {
|
|
||||||
err = errors.New(resp.Status)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
n = len(b)
|
|
||||||
me.off += int64(n)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrNotFound = errors.New("not found")
|
|
||||||
)
|
|
||||||
|
|
||||||
// Returns the length of the resource in bytes.
|
|
||||||
func GetLength(url string) (ret int64, err error) {
|
|
||||||
resp, err := http.Head(url)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp.Body.Close()
|
|
||||||
if resp.StatusCode == http.StatusNotFound {
|
|
||||||
err = ErrNotFound
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return instanceLength(resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *File) Close() error {
|
|
||||||
me.url = ""
|
|
||||||
if me.r != nil {
|
|
||||||
me.r.Close()
|
|
||||||
me.r = nil
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Delete(urlStr string) (err error) {
|
|
||||||
req, err := http.NewRequest("DELETE", urlStr, nil)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp, err := http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp.Body.Close()
|
|
||||||
if resp.StatusCode == http.StatusNotFound {
|
|
||||||
err = ErrNotFound
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if resp.StatusCode != 200 {
|
|
||||||
err = fmt.Errorf("response: %s", resp.Status)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
47
Godeps/_workspace/src/github.com/anacrolix/missinggo/httpgzip.go
generated
vendored
47
Godeps/_workspace/src/github.com/anacrolix/missinggo/httpgzip.go
generated
vendored
@ -1,47 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"compress/gzip"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
type gzipResponseWriter struct {
|
|
||||||
io.Writer
|
|
||||||
http.ResponseWriter
|
|
||||||
haveWritten bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *gzipResponseWriter) Write(b []byte) (int, error) {
|
|
||||||
if w.haveWritten {
|
|
||||||
goto write
|
|
||||||
}
|
|
||||||
w.haveWritten = true
|
|
||||||
if w.Header().Get("Content-Type") != "" {
|
|
||||||
goto write
|
|
||||||
}
|
|
||||||
if type_ := http.DetectContentType(b); type_ != "application/octet-stream" {
|
|
||||||
w.Header().Set("Content-Type", type_)
|
|
||||||
}
|
|
||||||
write:
|
|
||||||
return w.Writer.Write(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gzips response body if the request says it'll allow it.
|
|
||||||
func GzipHTTPHandler(h http.Handler) http.Handler {
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") || w.Header().Get("Content-Encoding") != "" || w.Header().Get("Vary") != "" {
|
|
||||||
h.ServeHTTP(w, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Header().Set("Content-Encoding", "gzip")
|
|
||||||
w.Header().Set("Vary", "Accept-Encoding")
|
|
||||||
gz := gzip.NewWriter(w)
|
|
||||||
defer gz.Close()
|
|
||||||
h.ServeHTTP(&gzipResponseWriter{
|
|
||||||
Writer: gz,
|
|
||||||
ResponseWriter: w,
|
|
||||||
}, r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
60
Godeps/_workspace/src/github.com/anacrolix/missinggo/httpresponsestatus.go
generated
vendored
60
Godeps/_workspace/src/github.com/anacrolix/missinggo/httpresponsestatus.go
generated
vendored
@ -1,60 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"io"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A http.ResponseWriter that tracks the status of the response. The status
|
|
||||||
// code, and number of bytes written for example.
|
|
||||||
type StatusResponseWriter struct {
|
|
||||||
RW http.ResponseWriter
|
|
||||||
Code int
|
|
||||||
BytesWritten int64
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ http.ResponseWriter = &StatusResponseWriter{}
|
|
||||||
|
|
||||||
func (me *StatusResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
|
||||||
return me.RW.(http.Hijacker).Hijack()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *StatusResponseWriter) CloseNotify() <-chan bool {
|
|
||||||
return me.RW.(http.CloseNotifier).CloseNotify()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *StatusResponseWriter) Flush() {
|
|
||||||
me.RW.(http.Flusher).Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *StatusResponseWriter) Header() http.Header {
|
|
||||||
return me.RW.Header()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *StatusResponseWriter) Write(b []byte) (n int, err error) {
|
|
||||||
if me.Code == 0 {
|
|
||||||
me.Code = 200
|
|
||||||
}
|
|
||||||
n, err = me.RW.Write(b)
|
|
||||||
me.BytesWritten += int64(n)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *StatusResponseWriter) WriteHeader(code int) {
|
|
||||||
me.RW.WriteHeader(code)
|
|
||||||
me.Code = code
|
|
||||||
}
|
|
||||||
|
|
||||||
type ReaderFromStatusResponseWriter struct {
|
|
||||||
StatusResponseWriter
|
|
||||||
io.ReaderFrom
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewReaderFromStatusResponseWriter(w http.ResponseWriter) *ReaderFromStatusResponseWriter {
|
|
||||||
return &ReaderFromStatusResponseWriter{
|
|
||||||
StatusResponseWriter{RW: w},
|
|
||||||
w.(io.ReaderFrom),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
81
Godeps/_workspace/src/github.com/anacrolix/missinggo/itertools/groupby.go
generated
vendored
81
Godeps/_workspace/src/github.com/anacrolix/missinggo/itertools/groupby.go
generated
vendored
@ -1,81 +0,0 @@
|
|||||||
package itertools
|
|
||||||
|
|
||||||
type groupBy struct {
|
|
||||||
curKey interface{}
|
|
||||||
curKeyOk bool
|
|
||||||
curValue interface{}
|
|
||||||
keyFunc func(interface{}) interface{}
|
|
||||||
input Iterator
|
|
||||||
groupKey interface{}
|
|
||||||
groupKeyOk bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type Group interface {
|
|
||||||
Iterator
|
|
||||||
Key() interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type group struct {
|
|
||||||
gb *groupBy
|
|
||||||
key interface{}
|
|
||||||
first bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *group) Next() (ok bool) {
|
|
||||||
if me.first {
|
|
||||||
me.first = false
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
me.gb.advance()
|
|
||||||
if !me.gb.curKeyOk || me.gb.curKey != me.key {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ok = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me group) Value() (ret interface{}) {
|
|
||||||
ret = me.gb.curValue
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me group) Key() interface{} {
|
|
||||||
return me.key
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *groupBy) advance() {
|
|
||||||
me.curKeyOk = me.input.Next()
|
|
||||||
if me.curKeyOk {
|
|
||||||
me.curValue = me.input.Value()
|
|
||||||
me.curKey = me.keyFunc(me.curValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *groupBy) Next() (ok bool) {
|
|
||||||
for me.curKey == me.groupKey {
|
|
||||||
ok = me.input.Next()
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
me.curValue = me.input.Value()
|
|
||||||
me.curKey = me.keyFunc(me.curValue)
|
|
||||||
me.curKeyOk = true
|
|
||||||
}
|
|
||||||
me.groupKey = me.curKey
|
|
||||||
me.groupKeyOk = true
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *groupBy) Value() (ret interface{}) {
|
|
||||||
return &group{me, me.groupKey, true}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GroupBy(input Iterator, keyFunc func(interface{}) interface{}) Iterator {
|
|
||||||
if keyFunc == nil {
|
|
||||||
keyFunc = func(a interface{}) interface{} { return a }
|
|
||||||
}
|
|
||||||
return &groupBy{
|
|
||||||
input: input,
|
|
||||||
keyFunc: keyFunc,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
31
Godeps/_workspace/src/github.com/anacrolix/missinggo/itertools/groupby_test.go
generated
vendored
31
Godeps/_workspace/src/github.com/anacrolix/missinggo/itertools/groupby_test.go
generated
vendored
@ -1,31 +0,0 @@
|
|||||||
package itertools
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGroupByKey(t *testing.T) {
|
|
||||||
var ks []byte
|
|
||||||
gb := GroupBy(StringIterator("AAAABBBCCDAABBB"), nil)
|
|
||||||
for gb.Next() {
|
|
||||||
ks = append(ks, gb.Value().(Group).Key().(byte))
|
|
||||||
}
|
|
||||||
t.Log(ks)
|
|
||||||
require.EqualValues(t, "ABCDAB", ks)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGroupByList(t *testing.T) {
|
|
||||||
var gs []string
|
|
||||||
gb := GroupBy(StringIterator("AAAABBBCCD"), nil)
|
|
||||||
for gb.Next() {
|
|
||||||
i := gb.Value().(Iterator)
|
|
||||||
var g string
|
|
||||||
for i.Next() {
|
|
||||||
g += string(i.Value().(byte))
|
|
||||||
}
|
|
||||||
gs = append(gs, g)
|
|
||||||
}
|
|
||||||
t.Log(gs)
|
|
||||||
}
|
|
||||||
41
Godeps/_workspace/src/github.com/anacrolix/missinggo/itertools/iterator.go
generated
vendored
41
Godeps/_workspace/src/github.com/anacrolix/missinggo/itertools/iterator.go
generated
vendored
@ -1,41 +0,0 @@
|
|||||||
package itertools
|
|
||||||
|
|
||||||
import "github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/anacrolix/missinggo"
|
|
||||||
|
|
||||||
type Iterator interface {
|
|
||||||
Next() bool
|
|
||||||
Value() interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type sliceIterator struct {
|
|
||||||
slice []interface{}
|
|
||||||
value interface{}
|
|
||||||
ok bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *sliceIterator) Next() bool {
|
|
||||||
if len(me.slice) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
me.value = me.slice[0]
|
|
||||||
me.slice = me.slice[1:]
|
|
||||||
me.ok = true
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *sliceIterator) Value() interface{} {
|
|
||||||
if !me.ok {
|
|
||||||
panic("no value; call Next")
|
|
||||||
}
|
|
||||||
return me.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func SliceIterator(a []interface{}) Iterator {
|
|
||||||
return &sliceIterator{
|
|
||||||
slice: a,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func StringIterator(a string) Iterator {
|
|
||||||
return SliceIterator(missinggo.ConvertToSliceOfEmptyInterface(a))
|
|
||||||
}
|
|
||||||
17
Godeps/_workspace/src/github.com/anacrolix/missinggo/itertools/iterator_test.go
generated
vendored
17
Godeps/_workspace/src/github.com/anacrolix/missinggo/itertools/iterator_test.go
generated
vendored
@ -1,17 +0,0 @@
|
|||||||
package itertools
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestIterator(t *testing.T) {
|
|
||||||
const s = "AAAABBBCCDAABBB"
|
|
||||||
si := StringIterator(s)
|
|
||||||
for i := range s {
|
|
||||||
require.True(t, si.Next())
|
|
||||||
require.Equal(t, s[i], si.Value().(byte))
|
|
||||||
}
|
|
||||||
require.False(t, si.Next())
|
|
||||||
}
|
|
||||||
26
Godeps/_workspace/src/github.com/anacrolix/missinggo/net.go
generated
vendored
26
Godeps/_workspace/src/github.com/anacrolix/missinggo/net.go
generated
vendored
@ -1,26 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
type HostPort struct {
|
|
||||||
Host string // Just the host, with no port.
|
|
||||||
Port string // May be empty if no port was given.
|
|
||||||
Err error // The error returned from net.SplitHostPort.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse a "hostport" string, a concept that floats around the stdlib a lot
|
|
||||||
// and is painful to work with. If no port is present, what's usually present
|
|
||||||
// is just the host.
|
|
||||||
func ParseHostPort(hostPort string) (ret HostPort) {
|
|
||||||
ret.Host, ret.Port, ret.Err = net.SplitHostPort(hostPort)
|
|
||||||
if ret.Err != nil {
|
|
||||||
ret.Host = hostPort
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *HostPort) Join() string {
|
|
||||||
return net.JoinHostPort(me.Host, me.Port)
|
|
||||||
}
|
|
||||||
20
Godeps/_workspace/src/github.com/anacrolix/missinggo/path.go
generated
vendored
20
Godeps/_workspace/src/github.com/anacrolix/missinggo/path.go
generated
vendored
@ -1,20 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Splits the pathname p into Root and Ext, such that Root+Ext==p.
|
|
||||||
func PathSplitExt(p string) (ret struct {
|
|
||||||
Root, Ext string
|
|
||||||
}) {
|
|
||||||
ret.Ext = path.Ext(p)
|
|
||||||
ret.Root = p[:len(p)-len(ret.Ext)]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func FilePathExists(p string) bool {
|
|
||||||
_, err := os.Stat(p)
|
|
||||||
return err == nil
|
|
||||||
}
|
|
||||||
17
Godeps/_workspace/src/github.com/anacrolix/missinggo/path_test.go
generated
vendored
17
Godeps/_workspace/src/github.com/anacrolix/missinggo/path_test.go
generated
vendored
@ -1,17 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExamplePathSplitExt() {
|
|
||||||
fmt.Printf("%q\n", PathSplitExt(".cshrc"))
|
|
||||||
fmt.Printf("%q\n", PathSplitExt("dir/a.ext"))
|
|
||||||
fmt.Printf("%q\n", PathSplitExt("dir/.rc"))
|
|
||||||
fmt.Printf("%q\n", PathSplitExt("home/.secret/file"))
|
|
||||||
// Output:
|
|
||||||
// {"" ".cshrc"}
|
|
||||||
// {"dir/a" ".ext"}
|
|
||||||
// {"dir/" ".rc"}
|
|
||||||
// {"home/.secret/file" ""}
|
|
||||||
}
|
|
||||||
48
Godeps/_workspace/src/github.com/anacrolix/missinggo/perf/mutex.go
generated
vendored
48
Godeps/_workspace/src/github.com/anacrolix/missinggo/perf/mutex.go
generated
vendored
@ -1,48 +0,0 @@
|
|||||||
package perf
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/anacrolix/missinggo"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TimedLocker struct {
|
|
||||||
L sync.Locker
|
|
||||||
Desc string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *TimedLocker) Lock() {
|
|
||||||
tr := NewTimer()
|
|
||||||
me.L.Lock()
|
|
||||||
tr.Stop(me.Desc)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *TimedLocker) Unlock() {
|
|
||||||
me.L.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
type TimedRWLocker struct {
|
|
||||||
RWL missinggo.RWLocker
|
|
||||||
WriteDesc string
|
|
||||||
ReadDesc string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *TimedRWLocker) Lock() {
|
|
||||||
tr := NewTimer()
|
|
||||||
me.RWL.Lock()
|
|
||||||
tr.Stop(me.WriteDesc)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *TimedRWLocker) Unlock() {
|
|
||||||
me.RWL.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *TimedRWLocker) RLock() {
|
|
||||||
tr := NewTimer()
|
|
||||||
me.RWL.RLock()
|
|
||||||
tr.Stop(me.ReadDesc)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *TimedRWLocker) RUnlock() {
|
|
||||||
me.RWL.RUnlock()
|
|
||||||
}
|
|
||||||
92
Godeps/_workspace/src/github.com/anacrolix/missinggo/perf/perf.go
generated
vendored
92
Godeps/_workspace/src/github.com/anacrolix/missinggo/perf/perf.go
generated
vendored
@ -1,92 +0,0 @@
|
|||||||
package perf
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"expvar"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/anacrolix/missinggo"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
em = missinggo.NewExpvarIndentMap("perfBuckets")
|
|
||||||
mu sync.RWMutex
|
|
||||||
)
|
|
||||||
|
|
||||||
type Timer struct {
|
|
||||||
started time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewTimer() Timer {
|
|
||||||
return Timer{time.Now()}
|
|
||||||
}
|
|
||||||
|
|
||||||
func bucketExponent(d time.Duration) int {
|
|
||||||
e := -9
|
|
||||||
for d != 0 {
|
|
||||||
d /= 10
|
|
||||||
e++
|
|
||||||
}
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
|
|
||||||
type buckets struct {
|
|
||||||
mu sync.Mutex
|
|
||||||
buckets []int64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *buckets) Add(t time.Duration) {
|
|
||||||
e := bucketExponent(t)
|
|
||||||
me.mu.Lock()
|
|
||||||
for e+9 >= len(me.buckets) {
|
|
||||||
me.buckets = append(me.buckets, 0)
|
|
||||||
}
|
|
||||||
me.buckets[e+9]++
|
|
||||||
me.mu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *buckets) String() string {
|
|
||||||
var b bytes.Buffer
|
|
||||||
fmt.Fprintf(&b, "{")
|
|
||||||
first := true
|
|
||||||
me.mu.Lock()
|
|
||||||
for i, count := range me.buckets {
|
|
||||||
if first {
|
|
||||||
if count == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
first = false
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(&b, ", ")
|
|
||||||
}
|
|
||||||
key := strconv.Itoa(i - 9)
|
|
||||||
fmt.Fprintf(&b, "%q: %d", key, count)
|
|
||||||
}
|
|
||||||
me.mu.Unlock()
|
|
||||||
fmt.Fprintf(&b, "}")
|
|
||||||
return b.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ expvar.Var = &buckets{}
|
|
||||||
|
|
||||||
func (t *Timer) Stop(desc string) time.Duration {
|
|
||||||
d := time.Since(t.started)
|
|
||||||
mu.RLock()
|
|
||||||
_m := em.Get(desc)
|
|
||||||
mu.RUnlock()
|
|
||||||
if _m == nil {
|
|
||||||
mu.Lock()
|
|
||||||
_m = em.Get(desc)
|
|
||||||
if _m == nil {
|
|
||||||
_m = new(buckets)
|
|
||||||
em.Set(desc, _m)
|
|
||||||
}
|
|
||||||
mu.Unlock()
|
|
||||||
}
|
|
||||||
m := _m.(*buckets)
|
|
||||||
m.Add(d)
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
52
Godeps/_workspace/src/github.com/anacrolix/missinggo/perf/perf_test.go
generated
vendored
52
Godeps/_workspace/src/github.com/anacrolix/missinggo/perf/perf_test.go
generated
vendored
@ -1,52 +0,0 @@
|
|||||||
package perf
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/bradfitz/iter"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestTimer(t *testing.T) {
|
|
||||||
tr := NewTimer()
|
|
||||||
tr.Stop("hiyo")
|
|
||||||
tr.Stop("hiyo")
|
|
||||||
t.Log(em.Get("hiyo").(*buckets))
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkStopWarm(b *testing.B) {
|
|
||||||
tr := NewTimer()
|
|
||||||
for _ = range iter.N(b.N) {
|
|
||||||
tr.Stop("a")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkStopCold(b *testing.B) {
|
|
||||||
tr := NewTimer()
|
|
||||||
for i := range iter.N(b.N) {
|
|
||||||
tr.Stop(strconv.FormatInt(int64(i), 10))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExponent(t *testing.T) {
|
|
||||||
for _, c := range []struct {
|
|
||||||
e int
|
|
||||||
d time.Duration
|
|
||||||
}{
|
|
||||||
{-1, 10 * time.Millisecond},
|
|
||||||
{-2, 5 * time.Millisecond},
|
|
||||||
{-2, time.Millisecond},
|
|
||||||
{-3, 500 * time.Microsecond},
|
|
||||||
{-3, 100 * time.Microsecond},
|
|
||||||
} {
|
|
||||||
tr := NewTimer()
|
|
||||||
time.Sleep(c.d)
|
|
||||||
assert.Equal(t, c.e, bucketExponent(tr.Stop(fmt.Sprintf("%d", c.e))), "%s", c.d)
|
|
||||||
}
|
|
||||||
assert.Equal(t, `{"-1": 1}`, em.Get("-1").String())
|
|
||||||
assert.Equal(t, `{"-2": 2}`, em.Get("-2").String())
|
|
||||||
assert.Equal(t, `{"-3": 2}`, em.Get("-3").String())
|
|
||||||
}
|
|
||||||
92
Godeps/_workspace/src/github.com/anacrolix/missinggo/pubsub/pubsub.go
generated
vendored
92
Godeps/_workspace/src/github.com/anacrolix/missinggo/pubsub/pubsub.go
generated
vendored
@ -1,92 +0,0 @@
|
|||||||
package pubsub
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
type PubSub struct {
|
|
||||||
mu sync.Mutex
|
|
||||||
next chan item
|
|
||||||
closed bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type item struct {
|
|
||||||
value interface{}
|
|
||||||
next chan item
|
|
||||||
}
|
|
||||||
|
|
||||||
type Subscription struct {
|
|
||||||
next chan item
|
|
||||||
Values chan interface{}
|
|
||||||
mu sync.Mutex
|
|
||||||
closed chan struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewPubSub() (ret *PubSub) {
|
|
||||||
return &PubSub{
|
|
||||||
next: make(chan item, 1),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *PubSub) Publish(v interface{}) {
|
|
||||||
next := make(chan item, 1)
|
|
||||||
i := item{v, next}
|
|
||||||
me.mu.Lock()
|
|
||||||
me.next <- i
|
|
||||||
me.next = next
|
|
||||||
me.mu.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *Subscription) Close() {
|
|
||||||
me.mu.Lock()
|
|
||||||
defer me.mu.Unlock()
|
|
||||||
select {
|
|
||||||
case <-me.closed:
|
|
||||||
default:
|
|
||||||
close(me.closed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *Subscription) runner() {
|
|
||||||
defer close(me.Values)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case i, ok := <-me.next:
|
|
||||||
if !ok {
|
|
||||||
me.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
me.next <- i
|
|
||||||
me.next = i.next
|
|
||||||
select {
|
|
||||||
case me.Values <- i.value:
|
|
||||||
case <-me.closed:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case <-me.closed:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *PubSub) Subscribe() (ret *Subscription) {
|
|
||||||
ret = &Subscription{
|
|
||||||
closed: make(chan struct{}),
|
|
||||||
Values: make(chan interface{}),
|
|
||||||
}
|
|
||||||
me.mu.Lock()
|
|
||||||
ret.next = me.next
|
|
||||||
me.mu.Unlock()
|
|
||||||
go ret.runner()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *PubSub) Close() {
|
|
||||||
me.mu.Lock()
|
|
||||||
defer me.mu.Unlock()
|
|
||||||
if me.closed {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
close(me.next)
|
|
||||||
me.closed = true
|
|
||||||
}
|
|
||||||
74
Godeps/_workspace/src/github.com/anacrolix/missinggo/pubsub/pubsub_test.go
generated
vendored
74
Godeps/_workspace/src/github.com/anacrolix/missinggo/pubsub/pubsub_test.go
generated
vendored
@ -1,74 +0,0 @@
|
|||||||
package pubsub
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/bradfitz/iter"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDoubleClose(t *testing.T) {
|
|
||||||
ps := NewPubSub()
|
|
||||||
ps.Close()
|
|
||||||
ps.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func testBroadcast(t testing.TB, subs, vals int) {
|
|
||||||
ps := NewPubSub()
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
for _ = range iter.N(subs) {
|
|
||||||
wg.Add(1)
|
|
||||||
s := ps.Subscribe()
|
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
var e int
|
|
||||||
for i := range s.Values {
|
|
||||||
assert.Equal(t, e, i.(int))
|
|
||||||
e++
|
|
||||||
}
|
|
||||||
assert.Equal(t, vals, e)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
for i := range iter.N(vals) {
|
|
||||||
ps.Publish(i)
|
|
||||||
}
|
|
||||||
ps.Close()
|
|
||||||
wg.Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBroadcast(t *testing.T) {
|
|
||||||
testBroadcast(t, 100, 10)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkBroadcast(b *testing.B) {
|
|
||||||
for _ = range iter.N(b.N) {
|
|
||||||
testBroadcast(b, 10, 1000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCloseSubscription(t *testing.T) {
|
|
||||||
ps := NewPubSub()
|
|
||||||
ps.Publish(1)
|
|
||||||
s := ps.Subscribe()
|
|
||||||
select {
|
|
||||||
case <-s.Values:
|
|
||||||
t.FailNow()
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
ps.Publish(2)
|
|
||||||
s2 := ps.Subscribe()
|
|
||||||
ps.Publish(3)
|
|
||||||
require.Equal(t, 2, <-s.Values)
|
|
||||||
require.EqualValues(t, 3, <-s.Values)
|
|
||||||
s.Close()
|
|
||||||
_, ok := <-s.Values
|
|
||||||
require.False(t, ok)
|
|
||||||
ps.Publish(4)
|
|
||||||
ps.Close()
|
|
||||||
require.Equal(t, 3, <-s2.Values)
|
|
||||||
require.Equal(t, 4, <-s2.Values)
|
|
||||||
require.Nil(t, <-s2.Values)
|
|
||||||
s2.Close()
|
|
||||||
}
|
|
||||||
46
Godeps/_workspace/src/github.com/anacrolix/missinggo/rle.go
generated
vendored
46
Godeps/_workspace/src/github.com/anacrolix/missinggo/rle.go
generated
vendored
@ -1,46 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
// A RunLengthEncoder counts successive duplicate elements and emits the
|
|
||||||
// element and the run length when the element changes or the encoder is
|
|
||||||
// flushed.
|
|
||||||
type RunLengthEncoder interface {
|
|
||||||
// Add a series of identical elements to the stream.
|
|
||||||
Append(element interface{}, count uint64)
|
|
||||||
// Emit the current element and its count if non-zero without waiting for
|
|
||||||
// the element to change.
|
|
||||||
Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
type runLengthEncoder struct {
|
|
||||||
eachRun func(element interface{}, count uint64)
|
|
||||||
element interface{}
|
|
||||||
count uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates a new RunLengthEncoder. eachRun is called when an element and its
|
|
||||||
// count is emitted, per the RunLengthEncoder interface.
|
|
||||||
func NewRunLengthEncoder(eachRun func(element interface{}, count uint64)) RunLengthEncoder {
|
|
||||||
return &runLengthEncoder{
|
|
||||||
eachRun: eachRun,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *runLengthEncoder) Append(element interface{}, count uint64) {
|
|
||||||
if element == me.element {
|
|
||||||
me.count += count
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if me.count != 0 {
|
|
||||||
me.eachRun(me.element, me.count)
|
|
||||||
}
|
|
||||||
me.count = count
|
|
||||||
me.element = element
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *runLengthEncoder) Flush() {
|
|
||||||
if me.count == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
me.eachRun(me.element, me.count)
|
|
||||||
me.count = 0
|
|
||||||
}
|
|
||||||
20
Godeps/_workspace/src/github.com/anacrolix/missinggo/rle_test.go
generated
vendored
20
Godeps/_workspace/src/github.com/anacrolix/missinggo/rle_test.go
generated
vendored
@ -1,20 +0,0 @@
|
|||||||
package missinggo_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/anacrolix/missinggo"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExampleNewRunLengthEncoder() {
|
|
||||||
var s string
|
|
||||||
rle := missinggo.NewRunLengthEncoder(func(e interface{}, count uint64) {
|
|
||||||
s += fmt.Sprintf("%d%c", count, e)
|
|
||||||
})
|
|
||||||
for _, e := range "WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWBWWWWWWWWWWWWWW" {
|
|
||||||
rle.Append(e, 1)
|
|
||||||
}
|
|
||||||
rle.Flush()
|
|
||||||
fmt.Println(s)
|
|
||||||
// Output: 12W1B12W3B24W1B14W
|
|
||||||
}
|
|
||||||
39
Godeps/_workspace/src/github.com/anacrolix/missinggo/singleflight.go
generated
vendored
39
Godeps/_workspace/src/github.com/anacrolix/missinggo/singleflight.go
generated
vendored
@ -1,39 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import "sync"
|
|
||||||
|
|
||||||
type ongoing struct {
|
|
||||||
do sync.Mutex
|
|
||||||
users int
|
|
||||||
}
|
|
||||||
|
|
||||||
type SingleFlight struct {
|
|
||||||
mu sync.Mutex
|
|
||||||
ongoing map[string]*ongoing
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *SingleFlight) Lock(id string) {
|
|
||||||
me.mu.Lock()
|
|
||||||
on, ok := me.ongoing[id]
|
|
||||||
if !ok {
|
|
||||||
on = new(ongoing)
|
|
||||||
if me.ongoing == nil {
|
|
||||||
me.ongoing = make(map[string]*ongoing)
|
|
||||||
}
|
|
||||||
me.ongoing[id] = on
|
|
||||||
}
|
|
||||||
on.users++
|
|
||||||
me.mu.Unlock()
|
|
||||||
on.do.Lock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (me *SingleFlight) Unlock(id string) {
|
|
||||||
me.mu.Lock()
|
|
||||||
on := me.ongoing[id]
|
|
||||||
on.do.Unlock()
|
|
||||||
on.users--
|
|
||||||
if on.users == 0 {
|
|
||||||
delete(me.ongoing, id)
|
|
||||||
}
|
|
||||||
me.mu.Unlock()
|
|
||||||
}
|
|
||||||
11
Godeps/_workspace/src/github.com/anacrolix/missinggo/sync.go
generated
vendored
11
Godeps/_workspace/src/github.com/anacrolix/missinggo/sync.go
generated
vendored
@ -1,11 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
type RWLocker interface {
|
|
||||||
sync.Locker
|
|
||||||
RLock()
|
|
||||||
RUnlock()
|
|
||||||
}
|
|
||||||
30
Godeps/_workspace/src/github.com/anacrolix/missinggo/url.go
generated
vendored
30
Godeps/_workspace/src/github.com/anacrolix/missinggo/url.go
generated
vendored
@ -1,30 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Deep copies a URL.
|
|
||||||
func CopyURL(u *url.URL) (ret *url.URL) {
|
|
||||||
ret = new(url.URL)
|
|
||||||
*ret = *u
|
|
||||||
if u.User != nil {
|
|
||||||
ret.User = new(url.Userinfo)
|
|
||||||
*ret.User = *u.User
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reconstructs the URL that would have produced the given Request.
|
|
||||||
// Request.URLs are not fully populated in http.Server handlers.
|
|
||||||
func RequestedURL(r *http.Request) (ret *url.URL) {
|
|
||||||
ret = CopyURL(r.URL)
|
|
||||||
ret.Host = r.Host
|
|
||||||
if r.TLS != nil {
|
|
||||||
ret.Scheme = "https"
|
|
||||||
} else {
|
|
||||||
ret.Scheme = "http"
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
51
Godeps/_workspace/src/github.com/anacrolix/missinggo/wolf.go
generated
vendored
51
Godeps/_workspace/src/github.com/anacrolix/missinggo/wolf.go
generated
vendored
@ -1,51 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
)
|
|
||||||
|
|
||||||
const debug = false
|
|
||||||
|
|
||||||
// A Wolf represents some event that becomes less and less interesting as it
|
|
||||||
// occurs. Call CryHeard to see if we should pay attention this time.
|
|
||||||
type Wolf struct {
|
|
||||||
cries uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns true less and less often. Convenient for exponentially decreasing
|
|
||||||
// the amount of noise due to errors.
|
|
||||||
func (me *Wolf) CryHeard() bool {
|
|
||||||
n := atomic.AddUint64(&me.cries, 1)
|
|
||||||
return n&(n-1) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
mu sync.Mutex
|
|
||||||
wolves map[uintptr]*Wolf
|
|
||||||
)
|
|
||||||
|
|
||||||
// Calls CryHeard() on a Wolf that is unique to the callers program counter.
|
|
||||||
// i.e. every CryHeard() expression has its own Wolf.
|
|
||||||
func CryHeard() bool {
|
|
||||||
pc, file, line, ok := runtime.Caller(1)
|
|
||||||
if debug {
|
|
||||||
log.Println(pc, file, line, ok)
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
mu.Lock()
|
|
||||||
if wolves == nil {
|
|
||||||
wolves = make(map[uintptr]*Wolf)
|
|
||||||
}
|
|
||||||
w, ok := wolves[pc]
|
|
||||||
if !ok {
|
|
||||||
w = new(Wolf)
|
|
||||||
wolves[pc] = w
|
|
||||||
}
|
|
||||||
mu.Unlock()
|
|
||||||
return w.CryHeard()
|
|
||||||
}
|
|
||||||
30
Godeps/_workspace/src/github.com/anacrolix/missinggo/wolf_test.go
generated
vendored
30
Godeps/_workspace/src/github.com/anacrolix/missinggo/wolf_test.go
generated
vendored
@ -1,30 +0,0 @@
|
|||||||
package missinggo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func cryHeard() bool {
|
|
||||||
return CryHeard()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCrySameLocation(t *testing.T) {
|
|
||||||
require.True(t, cryHeard())
|
|
||||||
require.True(t, cryHeard())
|
|
||||||
require.False(t, cryHeard())
|
|
||||||
require.True(t, cryHeard())
|
|
||||||
require.False(t, cryHeard())
|
|
||||||
require.False(t, cryHeard())
|
|
||||||
require.False(t, cryHeard())
|
|
||||||
require.True(t, cryHeard())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCryDifferentLocations(t *testing.T) {
|
|
||||||
require.True(t, CryHeard())
|
|
||||||
require.True(t, CryHeard())
|
|
||||||
require.True(t, CryHeard())
|
|
||||||
require.True(t, CryHeard())
|
|
||||||
require.True(t, CryHeard())
|
|
||||||
}
|
|
||||||
BIN
Godeps/_workspace/src/github.com/anacrolix/utp/.utp.go.swp
generated
vendored
BIN
Godeps/_workspace/src/github.com/anacrolix/utp/.utp.go.swp
generated
vendored
Binary file not shown.
362
Godeps/_workspace/src/github.com/anacrolix/utp/LICENSE
generated
vendored
362
Godeps/_workspace/src/github.com/anacrolix/utp/LICENSE
generated
vendored
@ -1,362 +0,0 @@
|
|||||||
Mozilla Public License, version 2.0
|
|
||||||
|
|
||||||
1. Definitions
|
|
||||||
|
|
||||||
1.1. "Contributor"
|
|
||||||
|
|
||||||
means each individual or legal entity that creates, contributes to the
|
|
||||||
creation of, or owns Covered Software.
|
|
||||||
|
|
||||||
1.2. "Contributor Version"
|
|
||||||
|
|
||||||
means the combination of the Contributions of others (if any) used by a
|
|
||||||
Contributor and that particular Contributor's Contribution.
|
|
||||||
|
|
||||||
1.3. "Contribution"
|
|
||||||
|
|
||||||
means Covered Software of a particular Contributor.
|
|
||||||
|
|
||||||
1.4. "Covered Software"
|
|
||||||
|
|
||||||
means Source Code Form to which the initial Contributor has attached the
|
|
||||||
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
|
||||||
Modifications of such Source Code Form, in each case including portions
|
|
||||||
thereof.
|
|
||||||
|
|
||||||
1.5. "Incompatible With Secondary Licenses"
|
|
||||||
means
|
|
||||||
|
|
||||||
a. that the initial Contributor has attached the notice described in
|
|
||||||
Exhibit B to the Covered Software; or
|
|
||||||
|
|
||||||
b. that the Covered Software was made available under the terms of
|
|
||||||
version 1.1 or earlier of the License, but not also under the terms of
|
|
||||||
a Secondary License.
|
|
||||||
|
|
||||||
1.6. "Executable Form"
|
|
||||||
|
|
||||||
means any form of the work other than Source Code Form.
|
|
||||||
|
|
||||||
1.7. "Larger Work"
|
|
||||||
|
|
||||||
means a work that combines Covered Software with other material, in a
|
|
||||||
separate file or files, that is not Covered Software.
|
|
||||||
|
|
||||||
1.8. "License"
|
|
||||||
|
|
||||||
means this document.
|
|
||||||
|
|
||||||
1.9. "Licensable"
|
|
||||||
|
|
||||||
means having the right to grant, to the maximum extent possible, whether
|
|
||||||
at the time of the initial grant or subsequently, any and all of the
|
|
||||||
rights conveyed by this License.
|
|
||||||
|
|
||||||
1.10. "Modifications"
|
|
||||||
|
|
||||||
means any of the following:
|
|
||||||
|
|
||||||
a. any file in Source Code Form that results from an addition to,
|
|
||||||
deletion from, or modification of the contents of Covered Software; or
|
|
||||||
|
|
||||||
b. any new file in Source Code Form that contains any Covered Software.
|
|
||||||
|
|
||||||
1.11. "Patent Claims" of a Contributor
|
|
||||||
|
|
||||||
means any patent claim(s), including without limitation, method,
|
|
||||||
process, and apparatus claims, in any patent Licensable by such
|
|
||||||
Contributor that would be infringed, but for the grant of the License,
|
|
||||||
by the making, using, selling, offering for sale, having made, import,
|
|
||||||
or transfer of either its Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
1.12. "Secondary License"
|
|
||||||
|
|
||||||
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
|
||||||
General Public License, Version 2.1, the GNU Affero General Public
|
|
||||||
License, Version 3.0, or any later versions of those licenses.
|
|
||||||
|
|
||||||
1.13. "Source Code Form"
|
|
||||||
|
|
||||||
means the form of the work preferred for making modifications.
|
|
||||||
|
|
||||||
1.14. "You" (or "Your")
|
|
||||||
|
|
||||||
means an individual or a legal entity exercising rights under this
|
|
||||||
License. For legal entities, "You" includes any entity that controls, is
|
|
||||||
controlled by, or is under common control with You. For purposes of this
|
|
||||||
definition, "control" means (a) the power, direct or indirect, to cause
|
|
||||||
the direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
|
||||||
outstanding shares or beneficial ownership of such entity.
|
|
||||||
|
|
||||||
|
|
||||||
2. License Grants and Conditions
|
|
||||||
|
|
||||||
2.1. Grants
|
|
||||||
|
|
||||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
|
||||||
non-exclusive license:
|
|
||||||
|
|
||||||
a. under intellectual property rights (other than patent or trademark)
|
|
||||||
Licensable by such Contributor to use, reproduce, make available,
|
|
||||||
modify, display, perform, distribute, and otherwise exploit its
|
|
||||||
Contributions, either on an unmodified basis, with Modifications, or
|
|
||||||
as part of a Larger Work; and
|
|
||||||
|
|
||||||
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
|
||||||
sale, have made, import, and otherwise transfer either its
|
|
||||||
Contributions or its Contributor Version.
|
|
||||||
|
|
||||||
2.2. Effective Date
|
|
||||||
|
|
||||||
The licenses granted in Section 2.1 with respect to any Contribution
|
|
||||||
become effective for each Contribution on the date the Contributor first
|
|
||||||
distributes such Contribution.
|
|
||||||
|
|
||||||
2.3. Limitations on Grant Scope
|
|
||||||
|
|
||||||
The licenses granted in this Section 2 are the only rights granted under
|
|
||||||
this License. No additional rights or licenses will be implied from the
|
|
||||||
distribution or licensing of Covered Software under this License.
|
|
||||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
|
||||||
Contributor:
|
|
||||||
|
|
||||||
a. for any code that a Contributor has removed from Covered Software; or
|
|
||||||
|
|
||||||
b. for infringements caused by: (i) Your and any other third party's
|
|
||||||
modifications of Covered Software, or (ii) the combination of its
|
|
||||||
Contributions with other software (except as part of its Contributor
|
|
||||||
Version); or
|
|
||||||
|
|
||||||
c. under Patent Claims infringed by Covered Software in the absence of
|
|
||||||
its Contributions.
|
|
||||||
|
|
||||||
This License does not grant any rights in the trademarks, service marks,
|
|
||||||
or logos of any Contributor (except as may be necessary to comply with
|
|
||||||
the notice requirements in Section 3.4).
|
|
||||||
|
|
||||||
2.4. Subsequent Licenses
|
|
||||||
|
|
||||||
No Contributor makes additional grants as a result of Your choice to
|
|
||||||
distribute the Covered Software under a subsequent version of this
|
|
||||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
|
||||||
permitted under the terms of Section 3.3).
|
|
||||||
|
|
||||||
2.5. Representation
|
|
||||||
|
|
||||||
Each Contributor represents that the Contributor believes its
|
|
||||||
Contributions are its original creation(s) or it has sufficient rights to
|
|
||||||
grant the rights to its Contributions conveyed by this License.
|
|
||||||
|
|
||||||
2.6. Fair Use
|
|
||||||
|
|
||||||
This License is not intended to limit any rights You have under
|
|
||||||
applicable copyright doctrines of fair use, fair dealing, or other
|
|
||||||
equivalents.
|
|
||||||
|
|
||||||
2.7. Conditions
|
|
||||||
|
|
||||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
|
||||||
Section 2.1.
|
|
||||||
|
|
||||||
|
|
||||||
3. Responsibilities
|
|
||||||
|
|
||||||
3.1. Distribution of Source Form
|
|
||||||
|
|
||||||
All distribution of Covered Software in Source Code Form, including any
|
|
||||||
Modifications that You create or to which You contribute, must be under
|
|
||||||
the terms of this License. You must inform recipients that the Source
|
|
||||||
Code Form of the Covered Software is governed by the terms of this
|
|
||||||
License, and how they can obtain a copy of this License. You may not
|
|
||||||
attempt to alter or restrict the recipients' rights in the Source Code
|
|
||||||
Form.
|
|
||||||
|
|
||||||
3.2. Distribution of Executable Form
|
|
||||||
|
|
||||||
If You distribute Covered Software in Executable Form then:
|
|
||||||
|
|
||||||
a. such Covered Software must also be made available in Source Code Form,
|
|
||||||
as described in Section 3.1, and You must inform recipients of the
|
|
||||||
Executable Form how they can obtain a copy of such Source Code Form by
|
|
||||||
reasonable means in a timely manner, at a charge no more than the cost
|
|
||||||
of distribution to the recipient; and
|
|
||||||
|
|
||||||
b. You may distribute such Executable Form under the terms of this
|
|
||||||
License, or sublicense it under different terms, provided that the
|
|
||||||
license for the Executable Form does not attempt to limit or alter the
|
|
||||||
recipients' rights in the Source Code Form under this License.
|
|
||||||
|
|
||||||
3.3. Distribution of a Larger Work
|
|
||||||
|
|
||||||
You may create and distribute a Larger Work under terms of Your choice,
|
|
||||||
provided that You also comply with the requirements of this License for
|
|
||||||
the Covered Software. If the Larger Work is a combination of Covered
|
|
||||||
Software with a work governed by one or more Secondary Licenses, and the
|
|
||||||
Covered Software is not Incompatible With Secondary Licenses, this
|
|
||||||
License permits You to additionally distribute such Covered Software
|
|
||||||
under the terms of such Secondary License(s), so that the recipient of
|
|
||||||
the Larger Work may, at their option, further distribute the Covered
|
|
||||||
Software under the terms of either this License or such Secondary
|
|
||||||
License(s).
|
|
||||||
|
|
||||||
3.4. Notices
|
|
||||||
|
|
||||||
You may not remove or alter the substance of any license notices
|
|
||||||
(including copyright notices, patent notices, disclaimers of warranty, or
|
|
||||||
limitations of liability) contained within the Source Code Form of the
|
|
||||||
Covered Software, except that You may alter any license notices to the
|
|
||||||
extent required to remedy known factual inaccuracies.
|
|
||||||
|
|
||||||
3.5. Application of Additional Terms
|
|
||||||
|
|
||||||
You may choose to offer, and to charge a fee for, warranty, support,
|
|
||||||
indemnity or liability obligations to one or more recipients of Covered
|
|
||||||
Software. However, You may do so only on Your own behalf, and not on
|
|
||||||
behalf of any Contributor. You must make it absolutely clear that any
|
|
||||||
such warranty, support, indemnity, or liability obligation is offered by
|
|
||||||
You alone, and You hereby agree to indemnify every Contributor for any
|
|
||||||
liability incurred by such Contributor as a result of warranty, support,
|
|
||||||
indemnity or liability terms You offer. You may include additional
|
|
||||||
disclaimers of warranty and limitations of liability specific to any
|
|
||||||
jurisdiction.
|
|
||||||
|
|
||||||
4. Inability to Comply Due to Statute or Regulation
|
|
||||||
|
|
||||||
If it is impossible for You to comply with any of the terms of this License
|
|
||||||
with respect to some or all of the Covered Software due to statute,
|
|
||||||
judicial order, or regulation then You must: (a) comply with the terms of
|
|
||||||
this License to the maximum extent possible; and (b) describe the
|
|
||||||
limitations and the code they affect. Such description must be placed in a
|
|
||||||
text file included with all distributions of the Covered Software under
|
|
||||||
this License. Except to the extent prohibited by statute or regulation,
|
|
||||||
such description must be sufficiently detailed for a recipient of ordinary
|
|
||||||
skill to be able to understand it.
|
|
||||||
|
|
||||||
5. Termination
|
|
||||||
|
|
||||||
5.1. The rights granted under this License will terminate automatically if You
|
|
||||||
fail to comply with any of its terms. However, if You become compliant,
|
|
||||||
then the rights granted under this License from a particular Contributor
|
|
||||||
are reinstated (a) provisionally, unless and until such Contributor
|
|
||||||
explicitly and finally terminates Your grants, and (b) on an ongoing
|
|
||||||
basis, if such Contributor fails to notify You of the non-compliance by
|
|
||||||
some reasonable means prior to 60 days after You have come back into
|
|
||||||
compliance. Moreover, Your grants from a particular Contributor are
|
|
||||||
reinstated on an ongoing basis if such Contributor notifies You of the
|
|
||||||
non-compliance by some reasonable means, this is the first time You have
|
|
||||||
received notice of non-compliance with this License from such
|
|
||||||
Contributor, and You become compliant prior to 30 days after Your receipt
|
|
||||||
of the notice.
|
|
||||||
|
|
||||||
5.2. If You initiate litigation against any entity by asserting a patent
|
|
||||||
infringement claim (excluding declaratory judgment actions,
|
|
||||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
|
||||||
directly or indirectly infringes any patent, then the rights granted to
|
|
||||||
You by any and all Contributors for the Covered Software under Section
|
|
||||||
2.1 of this License shall terminate.
|
|
||||||
|
|
||||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
|
||||||
license agreements (excluding distributors and resellers) which have been
|
|
||||||
validly granted by You or Your distributors under this License prior to
|
|
||||||
termination shall survive termination.
|
|
||||||
|
|
||||||
6. Disclaimer of Warranty
|
|
||||||
|
|
||||||
Covered Software is provided under this License on an "as is" basis,
|
|
||||||
without warranty of any kind, either expressed, implied, or statutory,
|
|
||||||
including, without limitation, warranties that the Covered Software is free
|
|
||||||
of defects, merchantable, fit for a particular purpose or non-infringing.
|
|
||||||
The entire risk as to the quality and performance of the Covered Software
|
|
||||||
is with You. Should any Covered Software prove defective in any respect,
|
|
||||||
You (not any Contributor) assume the cost of any necessary servicing,
|
|
||||||
repair, or correction. This disclaimer of warranty constitutes an essential
|
|
||||||
part of this License. No use of any Covered Software is authorized under
|
|
||||||
this License except under this disclaimer.
|
|
||||||
|
|
||||||
7. Limitation of Liability
|
|
||||||
|
|
||||||
Under no circumstances and under no legal theory, whether tort (including
|
|
||||||
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
|
||||||
distributes Covered Software as permitted above, be liable to You for any
|
|
||||||
direct, indirect, special, incidental, or consequential damages of any
|
|
||||||
character including, without limitation, damages for lost profits, loss of
|
|
||||||
goodwill, work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses, even if such party shall have been
|
|
||||||
informed of the possibility of such damages. This limitation of liability
|
|
||||||
shall not apply to liability for death or personal injury resulting from
|
|
||||||
such party's negligence to the extent applicable law prohibits such
|
|
||||||
limitation. Some jurisdictions do not allow the exclusion or limitation of
|
|
||||||
incidental or consequential damages, so this exclusion and limitation may
|
|
||||||
not apply to You.
|
|
||||||
|
|
||||||
8. Litigation
|
|
||||||
|
|
||||||
Any litigation relating to this License may be brought only in the courts
|
|
||||||
of a jurisdiction where the defendant maintains its principal place of
|
|
||||||
business and such litigation shall be governed by laws of that
|
|
||||||
jurisdiction, without reference to its conflict-of-law provisions. Nothing
|
|
||||||
in this Section shall prevent a party's ability to bring cross-claims or
|
|
||||||
counter-claims.
|
|
||||||
|
|
||||||
9. Miscellaneous
|
|
||||||
|
|
||||||
This License represents the complete agreement concerning the subject
|
|
||||||
matter hereof. If any provision of this License is held to be
|
|
||||||
unenforceable, such provision shall be reformed only to the extent
|
|
||||||
necessary to make it enforceable. Any law or regulation which provides that
|
|
||||||
the language of a contract shall be construed against the drafter shall not
|
|
||||||
be used to construe this License against a Contributor.
|
|
||||||
|
|
||||||
|
|
||||||
10. Versions of the License
|
|
||||||
|
|
||||||
10.1. New Versions
|
|
||||||
|
|
||||||
Mozilla Foundation is the license steward. Except as provided in Section
|
|
||||||
10.3, no one other than the license steward has the right to modify or
|
|
||||||
publish new versions of this License. Each version will be given a
|
|
||||||
distinguishing version number.
|
|
||||||
|
|
||||||
10.2. Effect of New Versions
|
|
||||||
|
|
||||||
You may distribute the Covered Software under the terms of the version
|
|
||||||
of the License under which You originally received the Covered Software,
|
|
||||||
or under the terms of any subsequent version published by the license
|
|
||||||
steward.
|
|
||||||
|
|
||||||
10.3. Modified Versions
|
|
||||||
|
|
||||||
If you create software not governed by this License, and you want to
|
|
||||||
create a new license for such software, you may create and use a
|
|
||||||
modified version of this License if you rename the license and remove
|
|
||||||
any references to the name of the license steward (except to note that
|
|
||||||
such modified license differs from this License).
|
|
||||||
|
|
||||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
|
||||||
Licenses If You choose to distribute Source Code Form that is
|
|
||||||
Incompatible With Secondary Licenses under the terms of this version of
|
|
||||||
the License, the notice described in Exhibit B of this License must be
|
|
||||||
attached.
|
|
||||||
|
|
||||||
Exhibit A - Source Code Form License Notice
|
|
||||||
|
|
||||||
This Source Code Form is subject to the
|
|
||||||
terms of the Mozilla Public License, v.
|
|
||||||
2.0. If a copy of the MPL was not
|
|
||||||
distributed with this file, You can
|
|
||||||
obtain one at
|
|
||||||
http://mozilla.org/MPL/2.0/.
|
|
||||||
|
|
||||||
If it is not possible or desirable to put the notice in a particular file,
|
|
||||||
then You may include the notice in a location (such as a LICENSE file in a
|
|
||||||
relevant directory) where a recipient would be likely to look for such a
|
|
||||||
notice.
|
|
||||||
|
|
||||||
You may add additional accurate notices of copyright ownership.
|
|
||||||
|
|
||||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
|
||||||
|
|
||||||
This Source Code Form is "Incompatible
|
|
||||||
With Secondary Licenses", as defined by
|
|
||||||
the Mozilla Public License, v. 2.0.
|
|
||||||
19
Godeps/_workspace/src/github.com/anacrolix/utp/README.md
generated
vendored
19
Godeps/_workspace/src/github.com/anacrolix/utp/README.md
generated
vendored
@ -1,19 +0,0 @@
|
|||||||
# utp
|
|
||||||
[](https://godoc.org/github.com/anacrolix/utp)
|
|
||||||
[](https://drone.io/github.com/anacrolix/utp/latest)
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## Supported
|
|
||||||
|
|
||||||
* Multiple uTP connections switched on a single PacketConn, including those initiated locally.
|
|
||||||
* Raw access to the PacketConn for non-uTP purposes, like sharing the PacketConn with a DHT implementation.
|
|
||||||
|
|
||||||
## Implementation characteristics
|
|
||||||
|
|
||||||
* Receive window size is used to limit out of order packets received.
|
|
||||||
* There is no MTU path discovery. The minimum size is always used.
|
|
||||||
* A fixed 64 slot selective ack window is used in both sending and receiving.
|
|
||||||
* All received non-ACK packets are ACKed in response.
|
|
||||||
|
|
||||||
Patches welcomed.
|
|
||||||
66
Godeps/_workspace/src/github.com/anacrolix/utp/cmd/ucat/ucat.go
generated
vendored
66
Godeps/_workspace/src/github.com/anacrolix/utp/cmd/ucat/ucat.go
generated
vendored
@ -1,66 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
|
|
||||||
"github.com/anacrolix/envpprof"
|
|
||||||
|
|
||||||
"github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/anacrolix/utp"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
defer envpprof.Stop()
|
|
||||||
listen := flag.Bool("l", false, "listen")
|
|
||||||
port := flag.Int("p", 0, "port to listen on")
|
|
||||||
flag.Parse()
|
|
||||||
var (
|
|
||||||
conn net.Conn
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
if *listen {
|
|
||||||
s, err := utp.NewSocket("udp", fmt.Sprintf(":%d", *port))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer s.Close()
|
|
||||||
conn, err = s.Accept()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
conn, err = utp.Dial(net.JoinHostPort(flag.Arg(0), flag.Arg(1)))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
go func() {
|
|
||||||
sig := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(sig, os.Interrupt)
|
|
||||||
<-sig
|
|
||||||
conn.Close()
|
|
||||||
}()
|
|
||||||
writerDone := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
defer close(writerDone)
|
|
||||||
written, err := io.Copy(conn, os.Stdin)
|
|
||||||
if err != nil {
|
|
||||||
conn.Close()
|
|
||||||
log.Fatalf("error after writing %d bytes: %s", written, err)
|
|
||||||
}
|
|
||||||
log.Printf("wrote %d bytes", written)
|
|
||||||
conn.Close()
|
|
||||||
}()
|
|
||||||
n, err := io.Copy(os.Stdout, conn)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
log.Printf("received %d bytes", n)
|
|
||||||
// <-writerDone
|
|
||||||
}
|
|
||||||
61
Godeps/_workspace/src/github.com/anacrolix/utp/pingpong
generated
vendored
61
Godeps/_workspace/src/github.com/anacrolix/utp/pingpong
generated
vendored
@ -1,61 +0,0 @@
|
|||||||
# This shell script uses nc-like executables to send and receive the file at
|
|
||||||
# $1, and prints the checksums. 3 such executables are
|
|
||||||
# github.com/h2so5/utp/ucat, invoked as h2so5-ucat, libutp-ucat, which is the
|
|
||||||
# ucat or ucat-static generated by the C++ libutp, and lastly, ./cmd/ucat from
|
|
||||||
# this repository. A good file in my experiments is no more than a few 100MB,
|
|
||||||
# or you'll be waiting a while.
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
# set -x
|
|
||||||
|
|
||||||
# Passed to invocations of godo for package ./cmd/ucat.
|
|
||||||
#GODOFLAGS=-race
|
|
||||||
|
|
||||||
#export GO_UTP_PACKET_DROP=0.1
|
|
||||||
export GOPPROF=
|
|
||||||
|
|
||||||
# Invokes the implementation to test against. If there's an arg, then it's
|
|
||||||
# expected to listen.
|
|
||||||
function other_ucat() {
|
|
||||||
if [[ $# != 0 ]]; then
|
|
||||||
libutp-ucat -l -p 4000
|
|
||||||
# h2so5-ucat -l :4000
|
|
||||||
else
|
|
||||||
libutp-ucat localhost 4000
|
|
||||||
# h2so5-ucat localhost:4000
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check what the correct result is.
|
|
||||||
md5 "$1"
|
|
||||||
|
|
||||||
rate() {
|
|
||||||
pv -a -W -b
|
|
||||||
}
|
|
||||||
|
|
||||||
echo 'utp->other_ucat'
|
|
||||||
# Send from this uTP implementation to another client.
|
|
||||||
other_ucat -l | rate | md5 &
|
|
||||||
# sleep 1
|
|
||||||
godo ${GODOFLAGS-} ./cmd/ucat localhost 4000 < "$1"
|
|
||||||
wait
|
|
||||||
|
|
||||||
echo 'other_ucat->utp'
|
|
||||||
# Send from the other implementation, to this one.
|
|
||||||
GO_UTP_LOGGING=0 GOPPROF= godo ${GODOFLAGS-} ./cmd/ucat -l -p 4000 | rate | md5 &
|
|
||||||
# Never receive from h2so5's ucat without a small sleep first. Don't know why.
|
|
||||||
# sleep 1
|
|
||||||
other_ucat < "$1"
|
|
||||||
wait
|
|
||||||
|
|
||||||
echo 'libutp->libutp'
|
|
||||||
libutp-ucat -l -p 4000 | rate | md5 &
|
|
||||||
libutp-ucat localhost 4000 < "$1"
|
|
||||||
wait
|
|
||||||
|
|
||||||
echo 'utp->utp'
|
|
||||||
godo ./cmd/ucat -l -p 4000 | rate | md5 &
|
|
||||||
godo ./cmd/ucat localhost 4000 < "$1"
|
|
||||||
wait
|
|
||||||
|
|
||||||
# Now check the hashes match (yes you).
|
|
||||||
1461
Godeps/_workspace/src/github.com/anacrolix/utp/utp.go
generated
vendored
1461
Godeps/_workspace/src/github.com/anacrolix/utp/utp.go
generated
vendored
File diff suppressed because it is too large
Load Diff
411
Godeps/_workspace/src/github.com/anacrolix/utp/utp_test.go
generated
vendored
411
Godeps/_workspace/src/github.com/anacrolix/utp/utp_test.go
generated
vendored
@ -1,411 +0,0 @@
|
|||||||
package utp
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
_ "github.com/anacrolix/envpprof"
|
|
||||||
"github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/anacrolix/missinggo"
|
|
||||||
"github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/bradfitz/iter"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
log.SetFlags(log.Flags() | log.Lshortfile)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUTPPingPong(t *testing.T) {
|
|
||||||
defer goroutineLeakCheck(t)()
|
|
||||||
s, err := NewSocket("udp", "localhost:0")
|
|
||||||
require.NoError(t, err)
|
|
||||||
defer s.Close()
|
|
||||||
pingerClosed := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
defer close(pingerClosed)
|
|
||||||
b, err := Dial(s.Addr().String())
|
|
||||||
require.NoError(t, err)
|
|
||||||
defer b.Close()
|
|
||||||
n, err := b.Write([]byte("ping"))
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.EqualValues(t, 4, n)
|
|
||||||
buf := make([]byte, 4)
|
|
||||||
b.Read(buf)
|
|
||||||
require.EqualValues(t, "pong", buf)
|
|
||||||
log.Printf("got pong")
|
|
||||||
}()
|
|
||||||
a, err := s.Accept()
|
|
||||||
require.NoError(t, err)
|
|
||||||
defer a.Close()
|
|
||||||
log.Printf("accepted %s", a)
|
|
||||||
buf := make([]byte, 42)
|
|
||||||
n, err := a.Read(buf)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.EqualValues(t, "ping", buf[:n])
|
|
||||||
log.Print("got ping")
|
|
||||||
n, err = a.Write([]byte("pong"))
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, 4, n)
|
|
||||||
log.Print("waiting for pinger to close")
|
|
||||||
<-pingerClosed
|
|
||||||
}
|
|
||||||
|
|
||||||
func goroutineLeakCheck(t testing.TB) func() {
|
|
||||||
if !testing.Verbose() {
|
|
||||||
return func() {}
|
|
||||||
}
|
|
||||||
numStart := runtime.NumGoroutine()
|
|
||||||
return func() {
|
|
||||||
var numNow int
|
|
||||||
for _ = range iter.N(1) {
|
|
||||||
numNow = runtime.NumGoroutine()
|
|
||||||
if numNow == numStart {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
|
||||||
}
|
|
||||||
// I'd print stacks, or treat this as fatal, but I think
|
|
||||||
// runtime.NumGoroutine is including system routines for which we are
|
|
||||||
// not provided the stacks, and are spawned unpredictably.
|
|
||||||
t.Logf("have %d goroutines, started with %d", numNow, numStart)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDialTimeout(t *testing.T) {
|
|
||||||
defer goroutineLeakCheck(t)()
|
|
||||||
s, _ := NewSocket("udp", "localhost:0")
|
|
||||||
defer s.Close()
|
|
||||||
conn, err := DialTimeout(s.Addr().String(), 10*time.Millisecond)
|
|
||||||
if err == nil {
|
|
||||||
conn.Close()
|
|
||||||
t.Fatal("expected timeout")
|
|
||||||
}
|
|
||||||
t.Log(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMinMaxHeaderType(t *testing.T) {
|
|
||||||
require.Equal(t, stSyn, stMax)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUTPRawConn(t *testing.T) {
|
|
||||||
l, err := NewSocket("udp", "")
|
|
||||||
require.NoError(t, err)
|
|
||||||
defer l.Close()
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
_, err := l.Accept()
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
// Connect a UTP peer to see if the RawConn will still work.
|
|
||||||
log.Print("dialing")
|
|
||||||
utpPeer := func() net.Conn {
|
|
||||||
s, _ := NewSocket("udp", "")
|
|
||||||
defer s.Close()
|
|
||||||
ret, err := s.Dial(fmt.Sprintf("localhost:%d", missinggo.AddrPort(l.Addr())))
|
|
||||||
require.NoError(t, err)
|
|
||||||
return ret
|
|
||||||
}()
|
|
||||||
log.Print("dial returned")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("error dialing utp listener: %s", err)
|
|
||||||
}
|
|
||||||
defer utpPeer.Close()
|
|
||||||
peer, err := net.ListenPacket("udp", ":0")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer peer.Close()
|
|
||||||
|
|
||||||
msgsReceived := 0
|
|
||||||
const N = 5000 // How many messages to send.
|
|
||||||
readerStopped := make(chan struct{})
|
|
||||||
// The reader goroutine.
|
|
||||||
go func() {
|
|
||||||
defer close(readerStopped)
|
|
||||||
b := make([]byte, 500)
|
|
||||||
for i := 0; i < N; i++ {
|
|
||||||
n, _, err := l.ReadFrom(b)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("error reading from raw conn: %s", err)
|
|
||||||
}
|
|
||||||
msgsReceived++
|
|
||||||
var d int
|
|
||||||
fmt.Sscan(string(b[:n]), &d)
|
|
||||||
if d != i {
|
|
||||||
log.Printf("got wrong number: expected %d, got %d", i, d)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
udpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("localhost:%d", missinggo.AddrPort(l.Addr())))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
for i := 0; i < N; i++ {
|
|
||||||
_, err := peer.WriteTo([]byte(fmt.Sprintf("%d", i)), udpAddr)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
time.Sleep(time.Microsecond)
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-readerStopped:
|
|
||||||
case <-time.After(time.Second):
|
|
||||||
t.Fatal("reader timed out")
|
|
||||||
}
|
|
||||||
if msgsReceived != N {
|
|
||||||
t.Fatalf("messages received: %d", msgsReceived)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConnReadDeadline(t *testing.T) {
|
|
||||||
ls, _ := NewSocket("udp", "localhost:0")
|
|
||||||
ds, _ := NewSocket("udp", "localhost:0")
|
|
||||||
dcReadErr := make(chan error)
|
|
||||||
go func() {
|
|
||||||
c, _ := ds.Dial(ls.Addr().String())
|
|
||||||
defer c.Close()
|
|
||||||
_, err := c.Read(nil)
|
|
||||||
dcReadErr <- err
|
|
||||||
}()
|
|
||||||
c, _ := ls.Accept()
|
|
||||||
dl := time.Now().Add(time.Millisecond)
|
|
||||||
c.SetReadDeadline(dl)
|
|
||||||
_, err := c.Read(nil)
|
|
||||||
require.Equal(t, errTimeout, err)
|
|
||||||
// The deadline has passed.
|
|
||||||
if !time.Now().After(dl) {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
// Returns timeout on subsequent read.
|
|
||||||
_, err = c.Read(nil)
|
|
||||||
require.Equal(t, errTimeout, err)
|
|
||||||
// Disable the deadline.
|
|
||||||
c.SetReadDeadline(time.Time{})
|
|
||||||
readReturned := make(chan struct{})
|
|
||||||
go func() {
|
|
||||||
c.Read(nil)
|
|
||||||
close(readReturned)
|
|
||||||
}()
|
|
||||||
select {
|
|
||||||
case <-readReturned:
|
|
||||||
// Read returned but shouldn't have.
|
|
||||||
t.FailNow()
|
|
||||||
case <-time.After(time.Millisecond):
|
|
||||||
}
|
|
||||||
c.Close()
|
|
||||||
select {
|
|
||||||
case <-readReturned:
|
|
||||||
case <-time.After(time.Millisecond):
|
|
||||||
t.Fatal("read should return after Conn is closed")
|
|
||||||
}
|
|
||||||
if err := <-dcReadErr; err != io.EOF {
|
|
||||||
t.Fatalf("dial conn read returned %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func connectSelfLots(n int, t testing.TB) {
|
|
||||||
defer goroutineLeakCheck(t)()
|
|
||||||
s, err := NewSocket("udp", "localhost:0")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
for _ = range iter.N(n) {
|
|
||||||
c, err := s.Accept()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer c.Close()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
dialErr := make(chan error)
|
|
||||||
connCh := make(chan net.Conn)
|
|
||||||
dialSema := make(chan struct{}, backlog)
|
|
||||||
for _ = range iter.N(n) {
|
|
||||||
go func() {
|
|
||||||
dialSema <- struct{}{}
|
|
||||||
c, err := s.Dial(s.Addr().String())
|
|
||||||
<-dialSema
|
|
||||||
if err != nil {
|
|
||||||
dialErr <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
connCh <- c
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
conns := make([]net.Conn, 0, n)
|
|
||||||
for _ = range iter.N(n) {
|
|
||||||
select {
|
|
||||||
case c := <-connCh:
|
|
||||||
conns = append(conns, c)
|
|
||||||
case err := <-dialErr:
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, c := range conns {
|
|
||||||
if c != nil {
|
|
||||||
c.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.mu.Lock()
|
|
||||||
for len(s.conns) != 0 {
|
|
||||||
// log.Print(len(s.conns))
|
|
||||||
s.event.Wait()
|
|
||||||
}
|
|
||||||
s.mu.Unlock()
|
|
||||||
s.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect to ourself heaps.
|
|
||||||
func TestConnectSelf(t *testing.T) {
|
|
||||||
// A rough guess says that at worst, I can only have 0x10000/3 connections
|
|
||||||
// to the same socket, due to fragmentation in the assigned connection
|
|
||||||
// IDs.
|
|
||||||
connectSelfLots(0x1000, t)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkConnectSelf(b *testing.B) {
|
|
||||||
for _ = range iter.N(b.N) {
|
|
||||||
connectSelfLots(2, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkNewCloseSocket(b *testing.B) {
|
|
||||||
for _ = range iter.N(b.N) {
|
|
||||||
s, err := NewSocket("udp", "localhost:0")
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
err = s.Close()
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRejectDialBacklogFilled(t *testing.T) {
|
|
||||||
s, err := NewSocket("udp", "localhost:0")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
errChan := make(chan error, 1)
|
|
||||||
dial := func() {
|
|
||||||
_, err := s.Dial(s.Addr().String())
|
|
||||||
if err != nil {
|
|
||||||
errChan <- err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Fill the backlog.
|
|
||||||
for _ = range iter.N(backlog + 1) {
|
|
||||||
go dial()
|
|
||||||
}
|
|
||||||
s.mu.Lock()
|
|
||||||
for len(s.backlog) < backlog {
|
|
||||||
s.event.Wait()
|
|
||||||
}
|
|
||||||
s.mu.Unlock()
|
|
||||||
select {
|
|
||||||
case <-errChan:
|
|
||||||
t.FailNow()
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
// One more connection should cause a dial attempt to get reset.
|
|
||||||
go dial()
|
|
||||||
err = <-errChan
|
|
||||||
if err.Error() != "peer reset" {
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
s.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure that we can reset AfterFunc timers, so we don't have to create
|
|
||||||
// brand new ones everytime they fire. Specifically for the Conn resend timer.
|
|
||||||
func TestResetAfterFuncTimer(t *testing.T) {
|
|
||||||
fired := make(chan struct{})
|
|
||||||
timer := time.AfterFunc(time.Millisecond, func() {
|
|
||||||
fired <- struct{}{}
|
|
||||||
})
|
|
||||||
<-fired
|
|
||||||
if timer.Reset(time.Millisecond) {
|
|
||||||
// The timer should have expired
|
|
||||||
t.FailNow()
|
|
||||||
}
|
|
||||||
<-fired
|
|
||||||
}
|
|
||||||
|
|
||||||
func connPair() (initer, accepted net.Conn) {
|
|
||||||
s, err := NewSocket("udp", "localhost:0")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer s.Close()
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
wg.Add(1)
|
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
var err error
|
|
||||||
initer, err = Dial(s.Addr().String())
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
accepted, err = s.Accept()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that peer sending FIN doesn't cause unread data to be dropped in a
|
|
||||||
// receiver.
|
|
||||||
func TestReadFinishedConn(t *testing.T) {
|
|
||||||
a, b := connPair()
|
|
||||||
defer a.Close()
|
|
||||||
defer b.Close()
|
|
||||||
mu.Lock()
|
|
||||||
originalAPDC := artificialPacketDropChance
|
|
||||||
artificialPacketDropChance = 1
|
|
||||||
mu.Unlock()
|
|
||||||
n, err := a.Write([]byte("hello"))
|
|
||||||
require.Equal(t, 5, n)
|
|
||||||
require.NoError(t, err)
|
|
||||||
n, err = a.Write([]byte("world"))
|
|
||||||
require.Equal(t, 5, n)
|
|
||||||
require.NoError(t, err)
|
|
||||||
mu.Lock()
|
|
||||||
artificialPacketDropChance = originalAPDC
|
|
||||||
mu.Unlock()
|
|
||||||
a.Close()
|
|
||||||
all, err := ioutil.ReadAll(b)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.EqualValues(t, "helloworld", all)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCloseDetachesQuickly(t *testing.T) {
|
|
||||||
s, _ := NewSocket("udp", "localhost:0")
|
|
||||||
defer s.Close()
|
|
||||||
go func() {
|
|
||||||
a, _ := s.Dial(s.Addr().String())
|
|
||||||
log.Print("close a")
|
|
||||||
a.Close()
|
|
||||||
log.Print("closed a")
|
|
||||||
}()
|
|
||||||
b, _ := s.Accept()
|
|
||||||
b.Close()
|
|
||||||
s.mu.Lock()
|
|
||||||
for len(s.conns) != 0 {
|
|
||||||
log.Print(len(s.conns))
|
|
||||||
s.event.Wait()
|
|
||||||
}
|
|
||||||
s.mu.Unlock()
|
|
||||||
}
|
|
||||||
1
Godeps/_workspace/src/github.com/bradfitz/iter/.gitignore
generated
vendored
1
Godeps/_workspace/src/github.com/bradfitz/iter/.gitignore
generated
vendored
@ -1 +0,0 @@
|
|||||||
*~
|
|
||||||
1
Godeps/_workspace/src/github.com/bradfitz/iter/README.txt
generated
vendored
1
Godeps/_workspace/src/github.com/bradfitz/iter/README.txt
generated
vendored
@ -1 +0,0 @@
|
|||||||
See http://godoc.org/github.com/bradfitz/iter
|
|
||||||
17
Godeps/_workspace/src/github.com/bradfitz/iter/iter.go
generated
vendored
17
Godeps/_workspace/src/github.com/bradfitz/iter/iter.go
generated
vendored
@ -1,17 +0,0 @@
|
|||||||
// Package iter provides a syntantically different way to iterate over integers. That's it.
|
|
||||||
package iter
|
|
||||||
|
|
||||||
// N returns a slice of n 0-sized elements, suitable for ranging over.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
//
|
|
||||||
// for i := range iter.N(10) {
|
|
||||||
// fmt.Println(i)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// ... will print 0 to 9, inclusive.
|
|
||||||
//
|
|
||||||
// It does not cause any allocations.
|
|
||||||
func N(n int) []struct{} {
|
|
||||||
return make([]struct{}, n)
|
|
||||||
}
|
|
||||||
29
Godeps/_workspace/src/github.com/bradfitz/iter/iter_test.go
generated
vendored
29
Godeps/_workspace/src/github.com/bradfitz/iter/iter_test.go
generated
vendored
@ -1,29 +0,0 @@
|
|||||||
package iter_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/bradfitz/iter"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ExampleN() {
|
|
||||||
for i := range iter.N(4) {
|
|
||||||
fmt.Println(i)
|
|
||||||
}
|
|
||||||
// Output:
|
|
||||||
// 0
|
|
||||||
// 1
|
|
||||||
// 2
|
|
||||||
// 3
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAllocs(t *testing.T) {
|
|
||||||
var x []struct{}
|
|
||||||
allocs := testing.AllocsPerRun(500, func() {
|
|
||||||
x = iter.N(1e9)
|
|
||||||
})
|
|
||||||
if allocs > 0.1 {
|
|
||||||
t.Errorf("allocs = %v", allocs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
13
Godeps/_workspace/src/github.com/jbenet/go-base58/LICENSE
generated
vendored
13
Godeps/_workspace/src/github.com/jbenet/go-base58/LICENSE
generated
vendored
@ -1,13 +0,0 @@
|
|||||||
Copyright (c) 2013 Conformal Systems LLC.
|
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software for any
|
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
|
||||||
copyright notice and this permission notice appear in all copies.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
66
Godeps/_workspace/src/github.com/jbenet/go-base58/README.md
generated
vendored
66
Godeps/_workspace/src/github.com/jbenet/go-base58/README.md
generated
vendored
@ -1,66 +0,0 @@
|
|||||||
# go-base58
|
|
||||||
|
|
||||||
I extracted this package from https://github.com/conformal/btcutil to provide a simple base58 package that
|
|
||||||
- defaults to base58-check (btc)
|
|
||||||
- and allows using different alphabets.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
b58 "github.com/jbenet/go-base58"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
buf := []byte{255, 254, 253, 252}
|
|
||||||
fmt.Printf("buffer: %v\n", buf)
|
|
||||||
|
|
||||||
str := b58.Encode(buf)
|
|
||||||
fmt.Printf("encoded: %s\n", str)
|
|
||||||
|
|
||||||
buf2 := b58.Decode(str)
|
|
||||||
fmt.Printf("decoded: %v\n", buf2)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Another alphabet
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
b58 "github.com/jbenet/go-base58"
|
|
||||||
)
|
|
||||||
|
|
||||||
const BogusAlphabet = "ZYXWVUTSRQPNMLKJHGFEDCBAzyxwvutsrqponmkjihgfedcba987654321"
|
|
||||||
|
|
||||||
|
|
||||||
func encdec(alphabet string) {
|
|
||||||
fmt.Printf("using: %s\n", alphabet)
|
|
||||||
|
|
||||||
buf := []byte{255, 254, 253, 252}
|
|
||||||
fmt.Printf("buffer: %v\n", buf)
|
|
||||||
|
|
||||||
str := b58.EncodeAlphabet(buf, alphabet)
|
|
||||||
fmt.Printf("encoded: %s\n", str)
|
|
||||||
|
|
||||||
buf2 := b58.DecodeAlphabet(str, alphabet)
|
|
||||||
fmt.Printf("decoded: %v\n\n", buf2)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
encdec(b58.BTCAlphabet)
|
|
||||||
encdec(b58.FlickrAlphabet)
|
|
||||||
encdec(BogusAlphabet)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
Package base58 (and the original btcutil) are licensed under the ISC License.
|
|
||||||
90
Godeps/_workspace/src/github.com/jbenet/go-base58/base58.go
generated
vendored
90
Godeps/_workspace/src/github.com/jbenet/go-base58/base58.go
generated
vendored
@ -1,90 +0,0 @@
|
|||||||
// Copyright (c) 2013-2014 Conformal Systems LLC.
|
|
||||||
// Use of this source code is governed by an ISC
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
// Modified by Juan Benet (juan@benet.ai)
|
|
||||||
|
|
||||||
package base58
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/big"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// alphabet is the modified base58 alphabet used by Bitcoin.
|
|
||||||
const BTCAlphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
|
|
||||||
const FlickrAlphabet = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
|
|
||||||
|
|
||||||
var bigRadix = big.NewInt(58)
|
|
||||||
var bigZero = big.NewInt(0)
|
|
||||||
|
|
||||||
// Decode decodes a modified base58 string to a byte slice, using BTCAlphabet
|
|
||||||
func Decode(b string) []byte {
|
|
||||||
return DecodeAlphabet(b, BTCAlphabet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode encodes a byte slice to a modified base58 string, using BTCAlphabet
|
|
||||||
func Encode(b []byte) string {
|
|
||||||
return EncodeAlphabet(b, BTCAlphabet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecodeAlphabet decodes a modified base58 string to a byte slice, using alphabet.
|
|
||||||
func DecodeAlphabet(b, alphabet string) []byte {
|
|
||||||
answer := big.NewInt(0)
|
|
||||||
j := big.NewInt(1)
|
|
||||||
|
|
||||||
for i := len(b) - 1; i >= 0; i-- {
|
|
||||||
tmp := strings.IndexAny(alphabet, string(b[i]))
|
|
||||||
if tmp == -1 {
|
|
||||||
return []byte("")
|
|
||||||
}
|
|
||||||
idx := big.NewInt(int64(tmp))
|
|
||||||
tmp1 := big.NewInt(0)
|
|
||||||
tmp1.Mul(j, idx)
|
|
||||||
|
|
||||||
answer.Add(answer, tmp1)
|
|
||||||
j.Mul(j, bigRadix)
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpval := answer.Bytes()
|
|
||||||
|
|
||||||
var numZeros int
|
|
||||||
for numZeros = 0; numZeros < len(b); numZeros++ {
|
|
||||||
if b[numZeros] != alphabet[0] {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
flen := numZeros + len(tmpval)
|
|
||||||
val := make([]byte, flen, flen)
|
|
||||||
copy(val[numZeros:], tmpval)
|
|
||||||
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode encodes a byte slice to a modified base58 string, using alphabet
|
|
||||||
func EncodeAlphabet(b []byte, alphabet string) string {
|
|
||||||
x := new(big.Int)
|
|
||||||
x.SetBytes(b)
|
|
||||||
|
|
||||||
answer := make([]byte, 0, len(b)*136/100)
|
|
||||||
for x.Cmp(bigZero) > 0 {
|
|
||||||
mod := new(big.Int)
|
|
||||||
x.DivMod(x, bigRadix, mod)
|
|
||||||
answer = append(answer, alphabet[mod.Int64()])
|
|
||||||
}
|
|
||||||
|
|
||||||
// leading zero bytes
|
|
||||||
for _, i := range b {
|
|
||||||
if i != 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
answer = append(answer, alphabet[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
// reverse
|
|
||||||
alen := len(answer)
|
|
||||||
for i := 0; i < alen/2; i++ {
|
|
||||||
answer[i], answer[alen-1-i] = answer[alen-1-i], answer[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(answer)
|
|
||||||
}
|
|
||||||
96
Godeps/_workspace/src/github.com/jbenet/go-base58/base58_test.go
generated
vendored
96
Godeps/_workspace/src/github.com/jbenet/go-base58/base58_test.go
generated
vendored
@ -1,96 +0,0 @@
|
|||||||
// Copyright (c) 2013-2014 Conformal Systems LLC.
|
|
||||||
// Use of this source code is governed by an ISC
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package base58
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var stringTests = []struct {
|
|
||||||
in string
|
|
||||||
out string
|
|
||||||
}{
|
|
||||||
{"", ""},
|
|
||||||
{" ", "Z"},
|
|
||||||
{"-", "n"},
|
|
||||||
{"0", "q"},
|
|
||||||
{"1", "r"},
|
|
||||||
{"-1", "4SU"},
|
|
||||||
{"11", "4k8"},
|
|
||||||
{"abc", "ZiCa"},
|
|
||||||
{"1234598760", "3mJr7AoUXx2Wqd"},
|
|
||||||
{"abcdefghijklmnopqrstuvwxyz", "3yxU3u1igY8WkgtjK92fbJQCd4BZiiT1v25f"},
|
|
||||||
{"00000000000000000000000000000000000000000000000000000000000000", "3sN2THZeE9Eh9eYrwkvZqNstbHGvrxSAM7gXUXvyFQP8XvQLUqNCS27icwUeDT7ckHm4FUHM2mTVh1vbLmk7y"},
|
|
||||||
}
|
|
||||||
|
|
||||||
var invalidStringTests = []struct {
|
|
||||||
in string
|
|
||||||
out string
|
|
||||||
}{
|
|
||||||
{"0", ""},
|
|
||||||
{"O", ""},
|
|
||||||
{"I", ""},
|
|
||||||
{"l", ""},
|
|
||||||
{"3mJr0", ""},
|
|
||||||
{"O3yxU", ""},
|
|
||||||
{"3sNI", ""},
|
|
||||||
{"4kl8", ""},
|
|
||||||
{"0OIl", ""},
|
|
||||||
{"!@#$%^&*()-_=+~`", ""},
|
|
||||||
}
|
|
||||||
|
|
||||||
var hexTests = []struct {
|
|
||||||
in string
|
|
||||||
out string
|
|
||||||
}{
|
|
||||||
{"61", "2g"},
|
|
||||||
{"626262", "a3gV"},
|
|
||||||
{"636363", "aPEr"},
|
|
||||||
{"73696d706c792061206c6f6e6720737472696e67", "2cFupjhnEsSn59qHXstmK2ffpLv2"},
|
|
||||||
{"00eb15231dfceb60925886b67d065299925915aeb172c06647", "1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L"},
|
|
||||||
{"516b6fcd0f", "ABnLTmg"},
|
|
||||||
{"bf4f89001e670274dd", "3SEo3LWLoPntC"},
|
|
||||||
{"572e4794", "3EFU7m"},
|
|
||||||
{"ecac89cad93923c02321", "EJDM8drfXA6uyA"},
|
|
||||||
{"10c8511e", "Rt5zm"},
|
|
||||||
{"00000000000000000000", "1111111111"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBase58(t *testing.T) {
|
|
||||||
// Base58Encode tests
|
|
||||||
for x, test := range stringTests {
|
|
||||||
tmp := []byte(test.in)
|
|
||||||
if res := Encode(tmp); res != test.out {
|
|
||||||
t.Errorf("Base58Encode test #%d failed: got: %s want: %s",
|
|
||||||
x, res, test.out)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base58Decode tests
|
|
||||||
for x, test := range hexTests {
|
|
||||||
b, err := hex.DecodeString(test.in)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("hex.DecodeString failed failed #%d: got: %s", x, test.in)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if res := Decode(test.out); bytes.Equal(res, b) != true {
|
|
||||||
t.Errorf("Base58Decode test #%d failed: got: %q want: %q",
|
|
||||||
x, res, test.in)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base58Decode with invalid input
|
|
||||||
for x, test := range invalidStringTests {
|
|
||||||
if res := Decode(test.in); string(res) != test.out {
|
|
||||||
t.Errorf("Base58Decode invalidString test #%d failed: got: %q want: %q",
|
|
||||||
x, res, test.out)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
20
Godeps/_workspace/src/github.com/jbenet/go-base58/doc.go
generated
vendored
20
Godeps/_workspace/src/github.com/jbenet/go-base58/doc.go
generated
vendored
@ -1,20 +0,0 @@
|
|||||||
// Copyright (c) 2013-2014 Conformal Systems LLC.
|
|
||||||
// Use of this source code is governed by an ISC
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
/*
|
|
||||||
Package base58 provides base58-check encoding.
|
|
||||||
The alphabet is modifyiable for
|
|
||||||
|
|
||||||
Base58 Usage
|
|
||||||
|
|
||||||
To decode a base58 string:
|
|
||||||
|
|
||||||
rawData := base58.Base58Decode(encodedData)
|
|
||||||
|
|
||||||
Similarly, to encode the same data:
|
|
||||||
|
|
||||||
encodedData := base58.Base58Encode(rawData)
|
|
||||||
|
|
||||||
*/
|
|
||||||
package base58
|
|
||||||
9
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/.travis.yml
generated
vendored
9
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/.travis.yml
generated
vendored
@ -1,9 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.3
|
|
||||||
- release
|
|
||||||
- tip
|
|
||||||
|
|
||||||
script:
|
|
||||||
- go test -race -cpu=5 -v ./...
|
|
||||||
21
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/LICENSE
generated
vendored
21
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/LICENSE
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2014 Juan Batiz-Benet
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
58
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/README.md
generated
vendored
58
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/README.md
generated
vendored
@ -1,58 +0,0 @@
|
|||||||
# go-multiaddr
|
|
||||||
|
|
||||||
[multiaddr](https://github.com/jbenet/multiaddr) implementation in Go.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
### Simple
|
|
||||||
|
|
||||||
```go
|
|
||||||
import ma "github.com/jbenet/go-multiaddr"
|
|
||||||
|
|
||||||
// construct from a string (err signals parse failure)
|
|
||||||
m1, err := ma.NewMultiaddr("/ip4/127.0.0.1/udp/1234")
|
|
||||||
|
|
||||||
// construct from bytes (err signals parse failure)
|
|
||||||
m2, err := ma.NewMultiaddrBytes(m1.Bytes())
|
|
||||||
|
|
||||||
// true
|
|
||||||
strings.Equal(m1.String(), "/ip4/127.0.0.1/udp/1234")
|
|
||||||
strings.Equal(m1.String(), m2.String())
|
|
||||||
bytes.Equal(m1.Bytes(), m2.Bytes())
|
|
||||||
m1.Equal(m2)
|
|
||||||
m2.Equal(m1)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Protocols
|
|
||||||
|
|
||||||
```go
|
|
||||||
// get the multiaddr protocol description objects
|
|
||||||
addr.Protocols()
|
|
||||||
// []Protocol{
|
|
||||||
// Protocol{ Code: 4, Name: 'ip4', Size: 32},
|
|
||||||
// Protocol{ Code: 17, Name: 'udp', Size: 16},
|
|
||||||
// }
|
|
||||||
```
|
|
||||||
|
|
||||||
### En/decapsulate
|
|
||||||
|
|
||||||
```go
|
|
||||||
m.Encapsulate(ma.NewMultiaddr("/sctp/5678"))
|
|
||||||
// <Multiaddr /ip4/127.0.0.1/udp/1234/sctp/5678>
|
|
||||||
m.Decapsulate(ma.NewMultiaddr("/udp")) // up to + inc last occurrence of subaddr
|
|
||||||
// <Multiaddr /ip4/127.0.0.1>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Tunneling
|
|
||||||
|
|
||||||
Multiaddr allows expressing tunnels very nicely.
|
|
||||||
|
|
||||||
```js
|
|
||||||
printer, _ := ma.NewMultiaddr("/ip4/192.168.0.13/tcp/80")
|
|
||||||
proxy, _ := ma.NewMultiaddr("/ip4/10.20.30.40/tcp/443")
|
|
||||||
printerOverProxy := proxy.Encapsulate(printer)
|
|
||||||
// /ip4/10.20.30.40/tcp/443/ip4/192.168.0.13/tcp/80
|
|
||||||
|
|
||||||
proxyAgain := printerOverProxy.Decapsulate(printer)
|
|
||||||
// /ip4/10.20.30.40/tcp/443
|
|
||||||
```
|
|
||||||
209
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/codec.go
generated
vendored
209
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/codec.go
generated
vendored
@ -1,209 +0,0 @@
|
|||||||
package multiaddr
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
mh "github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/jbenet/go-multihash"
|
|
||||||
)
|
|
||||||
|
|
||||||
func stringToBytes(s string) ([]byte, error) {
|
|
||||||
|
|
||||||
// consume trailing slashes
|
|
||||||
s = strings.TrimRight(s, "/")
|
|
||||||
|
|
||||||
b := []byte{}
|
|
||||||
sp := strings.Split(s, "/")
|
|
||||||
|
|
||||||
if sp[0] != "" {
|
|
||||||
return nil, fmt.Errorf("invalid multiaddr, must begin with /")
|
|
||||||
}
|
|
||||||
|
|
||||||
// consume first empty elem
|
|
||||||
sp = sp[1:]
|
|
||||||
|
|
||||||
for len(sp) > 0 {
|
|
||||||
p := ProtocolWithName(sp[0])
|
|
||||||
if p.Code == 0 {
|
|
||||||
return nil, fmt.Errorf("no protocol with name %s", sp[0])
|
|
||||||
}
|
|
||||||
b = append(b, CodeToVarint(p.Code)...)
|
|
||||||
sp = sp[1:]
|
|
||||||
|
|
||||||
if p.Size == 0 { // no length.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(sp) < 1 {
|
|
||||||
return nil, fmt.Errorf("protocol requires address, none given: %s", p.Name)
|
|
||||||
}
|
|
||||||
a, err := addressStringToBytes(p, sp[0])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to parse %s: %s %s", p.Name, sp[0], err)
|
|
||||||
}
|
|
||||||
b = append(b, a...)
|
|
||||||
sp = sp[1:]
|
|
||||||
}
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func bytesToString(b []byte) (ret string, err error) {
|
|
||||||
// panic handler, in case we try accessing bytes incorrectly.
|
|
||||||
defer func() {
|
|
||||||
if e := recover(); e != nil {
|
|
||||||
ret = ""
|
|
||||||
switch e := e.(type) {
|
|
||||||
case error:
|
|
||||||
err = e
|
|
||||||
case string:
|
|
||||||
err = errors.New(e)
|
|
||||||
default:
|
|
||||||
err = fmt.Errorf("%v", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
s := ""
|
|
||||||
|
|
||||||
for len(b) > 0 {
|
|
||||||
|
|
||||||
code, n := ReadVarintCode(b)
|
|
||||||
b = b[n:]
|
|
||||||
p := ProtocolWithCode(code)
|
|
||||||
if p.Code == 0 {
|
|
||||||
return "", fmt.Errorf("no protocol with code %d", code)
|
|
||||||
}
|
|
||||||
s += "/" + p.Name
|
|
||||||
|
|
||||||
if p.Size == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
size := sizeForAddr(p, b)
|
|
||||||
a, err := addressBytesToString(p, b[:size])
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
if len(a) > 0 {
|
|
||||||
s += "/" + a
|
|
||||||
}
|
|
||||||
b = b[size:]
|
|
||||||
}
|
|
||||||
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func sizeForAddr(p Protocol, b []byte) int {
|
|
||||||
switch {
|
|
||||||
case p.Size > 0:
|
|
||||||
return (p.Size / 8)
|
|
||||||
case p.Size == 0:
|
|
||||||
return 0
|
|
||||||
default:
|
|
||||||
size, n := ReadVarintCode(b)
|
|
||||||
return size + n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func bytesSplit(b []byte) (ret [][]byte, err error) {
|
|
||||||
// panic handler, in case we try accessing bytes incorrectly.
|
|
||||||
defer func() {
|
|
||||||
if e := recover(); e != nil {
|
|
||||||
ret = [][]byte{}
|
|
||||||
err = e.(error)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
ret = [][]byte{}
|
|
||||||
for len(b) > 0 {
|
|
||||||
code, n := ReadVarintCode(b)
|
|
||||||
p := ProtocolWithCode(code)
|
|
||||||
if p.Code == 0 {
|
|
||||||
return [][]byte{}, fmt.Errorf("no protocol with code %d", b[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
size := sizeForAddr(p, b[n:])
|
|
||||||
length := n + size
|
|
||||||
ret = append(ret, b[:length])
|
|
||||||
b = b[length:]
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func addressStringToBytes(p Protocol, s string) ([]byte, error) {
|
|
||||||
switch p.Code {
|
|
||||||
|
|
||||||
case P_IP4: // ipv4
|
|
||||||
i := net.ParseIP(s).To4()
|
|
||||||
if i == nil {
|
|
||||||
return nil, fmt.Errorf("failed to parse ip4 addr: %s", s)
|
|
||||||
}
|
|
||||||
return i, nil
|
|
||||||
|
|
||||||
case P_IP6: // ipv6
|
|
||||||
i := net.ParseIP(s).To16()
|
|
||||||
if i == nil {
|
|
||||||
return nil, fmt.Errorf("failed to parse ip6 addr: %s", s)
|
|
||||||
}
|
|
||||||
return i, nil
|
|
||||||
|
|
||||||
// tcp udp dccp sctp
|
|
||||||
case P_TCP, P_UDP, P_DCCP, P_SCTP:
|
|
||||||
i, err := strconv.Atoi(s)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to parse %s addr: %s", p.Name, err)
|
|
||||||
}
|
|
||||||
if i >= 65536 {
|
|
||||||
return nil, fmt.Errorf("failed to parse %s addr: %s", p.Name, "greater than 65536")
|
|
||||||
}
|
|
||||||
b := make([]byte, 2)
|
|
||||||
binary.BigEndian.PutUint16(b, uint16(i))
|
|
||||||
return b, nil
|
|
||||||
|
|
||||||
case P_IPFS: // ipfs
|
|
||||||
// the address is a varint prefixed multihash string representation
|
|
||||||
m, err := mh.FromB58String(s)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to parse ipfs addr: %s %s", s, err)
|
|
||||||
}
|
|
||||||
size := CodeToVarint(len(m))
|
|
||||||
b := append(size, m...)
|
|
||||||
return b, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return []byte{}, fmt.Errorf("failed to parse %s addr: unknown", p.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
func addressBytesToString(p Protocol, b []byte) (string, error) {
|
|
||||||
switch p.Code {
|
|
||||||
|
|
||||||
// ipv4,6
|
|
||||||
case P_IP4, P_IP6:
|
|
||||||
return net.IP(b).String(), nil
|
|
||||||
|
|
||||||
// tcp udp dccp sctp
|
|
||||||
case P_TCP, P_UDP, P_DCCP, P_SCTP:
|
|
||||||
i := binary.BigEndian.Uint16(b)
|
|
||||||
return strconv.Itoa(int(i)), nil
|
|
||||||
|
|
||||||
case P_IPFS: // ipfs
|
|
||||||
// the address is a varint-prefixed multihash string representation
|
|
||||||
size, n := ReadVarintCode(b)
|
|
||||||
b = b[n:]
|
|
||||||
if len(b) != size {
|
|
||||||
panic("inconsistent lengths")
|
|
||||||
}
|
|
||||||
m, err := mh.Cast(b)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return m.B58String(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", fmt.Errorf("unknown protocol")
|
|
||||||
}
|
|
||||||
36
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/doc.go
generated
vendored
36
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/doc.go
generated
vendored
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
Package multiaddr provides an implementation of the Multiaddr network
|
|
||||||
address format. Multiaddr emphasizes explicitness, self-description, and
|
|
||||||
portability. It allows applications to treat addresses as opaque tokens,
|
|
||||||
and to avoid making assumptions about the address representation (e.g. length).
|
|
||||||
Learn more at https://github.com/jbenet/multiaddr
|
|
||||||
|
|
||||||
Basic Use:
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"strings"
|
|
||||||
ma "github.com/jbenet/go-multiaddr"
|
|
||||||
)
|
|
||||||
|
|
||||||
// construct from a string (err signals parse failure)
|
|
||||||
m1, err := ma.NewMultiaddr("/ip4/127.0.0.1/udp/1234")
|
|
||||||
|
|
||||||
// construct from bytes (err signals parse failure)
|
|
||||||
m2, err := ma.NewMultiaddrBytes(m1.Bytes())
|
|
||||||
|
|
||||||
// true
|
|
||||||
strings.Equal(m1.String(), "/ip4/127.0.0.1/udp/1234")
|
|
||||||
strings.Equal(m1.String(), m2.String())
|
|
||||||
bytes.Equal(m1.Bytes(), m2.Bytes())
|
|
||||||
m1.Equal(m2)
|
|
||||||
m2.Equal(m1)
|
|
||||||
|
|
||||||
// tunneling (en/decap)
|
|
||||||
printer, _ := ma.NewMultiaddr("/ip4/192.168.0.13/tcp/80")
|
|
||||||
proxy, _ := ma.NewMultiaddr("/ip4/10.20.30.40/tcp/443")
|
|
||||||
printerOverProxy := proxy.Encapsulate(printer)
|
|
||||||
proxyAgain := printerOverProxy.Decapsulate(printer)
|
|
||||||
|
|
||||||
*/
|
|
||||||
package multiaddr
|
|
||||||
42
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/interface.go
generated
vendored
42
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/interface.go
generated
vendored
@ -1,42 +0,0 @@
|
|||||||
package multiaddr
|
|
||||||
|
|
||||||
/*
|
|
||||||
Multiaddr is a cross-protocol, cross-platform format for representing
|
|
||||||
internet addresses. It emphasizes explicitness and self-description.
|
|
||||||
Learn more here: https://github.com/jbenet/multiaddr
|
|
||||||
|
|
||||||
Multiaddrs have both a binary and string representation.
|
|
||||||
|
|
||||||
import ma "github.com/jbenet/go-multiaddr"
|
|
||||||
|
|
||||||
addr, err := ma.NewMultiaddr("/ip4/1.2.3.4/tcp/80")
|
|
||||||
// err non-nil when parsing failed.
|
|
||||||
|
|
||||||
*/
|
|
||||||
type Multiaddr interface {
|
|
||||||
// Equal returns whether two Multiaddrs are exactly equal
|
|
||||||
Equal(Multiaddr) bool
|
|
||||||
|
|
||||||
// Bytes returns the []byte representation of this Multiaddr
|
|
||||||
Bytes() []byte
|
|
||||||
|
|
||||||
// String returns the string representation of this Multiaddr
|
|
||||||
// (may panic if internal state is corrupted)
|
|
||||||
String() string
|
|
||||||
|
|
||||||
// Protocols returns the list of Protocols this Multiaddr includes
|
|
||||||
// will panic if protocol code incorrect (and bytes accessed incorrectly)
|
|
||||||
Protocols() []Protocol
|
|
||||||
|
|
||||||
// Encapsulate wraps this Multiaddr around another. For example:
|
|
||||||
//
|
|
||||||
// /ip4/1.2.3.4 encapsulate /tcp/80 = /ip4/1.2.3.4/tcp/80
|
|
||||||
//
|
|
||||||
Encapsulate(Multiaddr) Multiaddr
|
|
||||||
|
|
||||||
// Decapsultate removes a Multiaddr wrapping. For example:
|
|
||||||
//
|
|
||||||
// /ip4/1.2.3.4/tcp/80 decapsulate /ip4/1.2.3.4 = /tcp/80
|
|
||||||
//
|
|
||||||
Decapsulate(Multiaddr) Multiaddr
|
|
||||||
}
|
|
||||||
115
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr.go
generated
vendored
115
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr.go
generated
vendored
@ -1,115 +0,0 @@
|
|||||||
package multiaddr
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// multiaddr is the data structure representing a Multiaddr
|
|
||||||
type multiaddr struct {
|
|
||||||
bytes []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMultiaddr parses and validates an input string, returning a *Multiaddr
|
|
||||||
func NewMultiaddr(s string) (Multiaddr, error) {
|
|
||||||
b, err := stringToBytes(s)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &multiaddr{bytes: b}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMultiaddrBytes initializes a Multiaddr from a byte representation.
|
|
||||||
// It validates it as an input string.
|
|
||||||
func NewMultiaddrBytes(b []byte) (Multiaddr, error) {
|
|
||||||
s, err := bytesToString(b)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return NewMultiaddr(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Equal tests whether two multiaddrs are equal
|
|
||||||
func (m *multiaddr) Equal(m2 Multiaddr) bool {
|
|
||||||
return bytes.Equal(m.bytes, m2.Bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bytes returns the []byte representation of this Multiaddr
|
|
||||||
func (m *multiaddr) Bytes() []byte {
|
|
||||||
// consider returning copy to prevent changing underneath us?
|
|
||||||
cpy := make([]byte, len(m.bytes))
|
|
||||||
copy(cpy, m.bytes)
|
|
||||||
return cpy
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the string representation of a Multiaddr
|
|
||||||
func (m *multiaddr) String() string {
|
|
||||||
s, err := bytesToString(m.bytes)
|
|
||||||
if err != nil {
|
|
||||||
panic("multiaddr failed to convert back to string. corrupted?")
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// Protocols returns the list of protocols this Multiaddr has.
|
|
||||||
// will panic in case we access bytes incorrectly.
|
|
||||||
func (m *multiaddr) Protocols() []Protocol {
|
|
||||||
|
|
||||||
// panic handler, in case we try accessing bytes incorrectly.
|
|
||||||
defer func() {
|
|
||||||
if e := recover(); e != nil {
|
|
||||||
err := e.(error)
|
|
||||||
panic("Multiaddr.Protocols error: " + err.Error())
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
size := 0
|
|
||||||
ps := []Protocol{}
|
|
||||||
b := m.bytes[:]
|
|
||||||
for len(b) > 0 {
|
|
||||||
code, n := ReadVarintCode(b)
|
|
||||||
p := ProtocolWithCode(code)
|
|
||||||
if p.Code == 0 {
|
|
||||||
// this is a panic (and not returning err) because this should've been
|
|
||||||
// caught on constructing the Multiaddr
|
|
||||||
panic(fmt.Errorf("no protocol with code %d", b[0]))
|
|
||||||
}
|
|
||||||
ps = append(ps, p)
|
|
||||||
b = b[n:]
|
|
||||||
|
|
||||||
size = sizeForAddr(p, b)
|
|
||||||
b = b[size:]
|
|
||||||
}
|
|
||||||
return ps
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encapsulate wraps a given Multiaddr, returning the resulting joined Multiaddr
|
|
||||||
func (m *multiaddr) Encapsulate(o Multiaddr) Multiaddr {
|
|
||||||
mb := m.bytes
|
|
||||||
ob := o.Bytes()
|
|
||||||
|
|
||||||
b := make([]byte, len(mb)+len(ob))
|
|
||||||
copy(b, mb)
|
|
||||||
copy(b[len(mb):], ob)
|
|
||||||
return &multiaddr{bytes: b}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decapsulate unwraps Multiaddr up until the given Multiaddr is found.
|
|
||||||
func (m *multiaddr) Decapsulate(o Multiaddr) Multiaddr {
|
|
||||||
s1 := m.String()
|
|
||||||
s2 := o.String()
|
|
||||||
i := strings.LastIndex(s1, s2)
|
|
||||||
if i < 0 {
|
|
||||||
// if multiaddr not contained, returns a copy.
|
|
||||||
cpy := make([]byte, len(m.bytes))
|
|
||||||
copy(cpy, m.bytes)
|
|
||||||
return &multiaddr{bytes: cpy}
|
|
||||||
}
|
|
||||||
|
|
||||||
ma, err := NewMultiaddr(s1[:i])
|
|
||||||
if err != nil {
|
|
||||||
panic("Multiaddr.Decapsulate incorrect byte boundaries.")
|
|
||||||
}
|
|
||||||
return ma
|
|
||||||
}
|
|
||||||
294
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr_test.go
generated
vendored
294
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr_test.go
generated
vendored
@ -1,294 +0,0 @@
|
|||||||
package multiaddr
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func newMultiaddr(t *testing.T, a string) Multiaddr {
|
|
||||||
m, err := NewMultiaddr(a)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConstructFails(t *testing.T) {
|
|
||||||
cases := []string{
|
|
||||||
"/ip4",
|
|
||||||
"/ip4/::1",
|
|
||||||
"/ip4/fdpsofodsajfdoisa",
|
|
||||||
"/ip6",
|
|
||||||
"/udp",
|
|
||||||
"/tcp",
|
|
||||||
"/sctp",
|
|
||||||
"/udp/65536",
|
|
||||||
"/tcp/65536",
|
|
||||||
"/udp/1234/sctp",
|
|
||||||
"/udp/1234/udt/1234",
|
|
||||||
"/udp/1234/utp/1234",
|
|
||||||
"/ip4/127.0.0.1/udp/jfodsajfidosajfoidsa",
|
|
||||||
"/ip4/127.0.0.1/udp",
|
|
||||||
"/ip4/127.0.0.1/tcp/jfodsajfidosajfoidsa",
|
|
||||||
"/ip4/127.0.0.1/tcp",
|
|
||||||
"/ip4/127.0.0.1/ipfs",
|
|
||||||
"/ip4/127.0.0.1/ipfs/tcp",
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, a := range cases {
|
|
||||||
if _, err := NewMultiaddr(a); err == nil {
|
|
||||||
t.Errorf("should have failed: %s - %s", a, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConstructSucceeds(t *testing.T) {
|
|
||||||
cases := []string{
|
|
||||||
"/ip4/1.2.3.4",
|
|
||||||
"/ip4/0.0.0.0",
|
|
||||||
"/ip6/::1",
|
|
||||||
"/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21",
|
|
||||||
"/udp/0",
|
|
||||||
"/tcp/0",
|
|
||||||
"/sctp/0",
|
|
||||||
"/udp/1234",
|
|
||||||
"/tcp/1234",
|
|
||||||
"/sctp/1234",
|
|
||||||
"/udp/65535",
|
|
||||||
"/tcp/65535",
|
|
||||||
"/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
|
||||||
"/udp/1234/sctp/1234",
|
|
||||||
"/udp/1234/udt",
|
|
||||||
"/udp/1234/utp",
|
|
||||||
"/tcp/1234/http",
|
|
||||||
"/tcp/1234/https",
|
|
||||||
"/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
|
|
||||||
"/ip4/127.0.0.1/udp/1234",
|
|
||||||
"/ip4/127.0.0.1/udp/0",
|
|
||||||
"/ip4/127.0.0.1/tcp/1234",
|
|
||||||
"/ip4/127.0.0.1/tcp/1234/",
|
|
||||||
"/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
|
|
||||||
"/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, a := range cases {
|
|
||||||
if _, err := NewMultiaddr(a); err != nil {
|
|
||||||
t.Errorf("should have succeeded: %s -- %s", a, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEqual(t *testing.T) {
|
|
||||||
m1 := newMultiaddr(t, "/ip4/127.0.0.1/udp/1234")
|
|
||||||
m2 := newMultiaddr(t, "/ip4/127.0.0.1/tcp/1234")
|
|
||||||
m3 := newMultiaddr(t, "/ip4/127.0.0.1/tcp/1234")
|
|
||||||
m4 := newMultiaddr(t, "/ip4/127.0.0.1/tcp/1234/")
|
|
||||||
|
|
||||||
if m1.Equal(m2) {
|
|
||||||
t.Error("should not be equal")
|
|
||||||
}
|
|
||||||
|
|
||||||
if m2.Equal(m1) {
|
|
||||||
t.Error("should not be equal")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !m2.Equal(m3) {
|
|
||||||
t.Error("should be equal")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !m3.Equal(m2) {
|
|
||||||
t.Error("should be equal")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !m1.Equal(m1) {
|
|
||||||
t.Error("should be equal")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !m2.Equal(m4) {
|
|
||||||
t.Error("should be equal")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !m4.Equal(m3) {
|
|
||||||
t.Error("should be equal")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStringToBytes(t *testing.T) {
|
|
||||||
|
|
||||||
testString := func(s string, h string) {
|
|
||||||
b1, err := hex.DecodeString(h)
|
|
||||||
if err != nil {
|
|
||||||
t.Error("failed to decode hex", h)
|
|
||||||
}
|
|
||||||
|
|
||||||
b2, err := stringToBytes(s)
|
|
||||||
if err != nil {
|
|
||||||
t.Error("failed to convert", s)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(b1, b2) {
|
|
||||||
t.Error("failed to convert", s, "to", b1, "got", b2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
testString("/ip4/127.0.0.1/udp/1234", "047f0000011104d2")
|
|
||||||
testString("/ip4/127.0.0.1/tcp/4321", "047f0000010610e1")
|
|
||||||
testString("/ip4/127.0.0.1/udp/1234/ip4/127.0.0.1/tcp/4321", "047f0000011104d2047f0000010610e1")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBytesToString(t *testing.T) {
|
|
||||||
|
|
||||||
testString := func(s1 string, h string) {
|
|
||||||
b, err := hex.DecodeString(h)
|
|
||||||
if err != nil {
|
|
||||||
t.Error("failed to decode hex", h)
|
|
||||||
}
|
|
||||||
|
|
||||||
s2, err := bytesToString(b)
|
|
||||||
if err != nil {
|
|
||||||
t.Error("failed to convert", b)
|
|
||||||
}
|
|
||||||
|
|
||||||
if s1 != s2 {
|
|
||||||
t.Error("failed to convert", b, "to", s1, "got", s2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
testString("/ip4/127.0.0.1/udp/1234", "047f0000011104d2")
|
|
||||||
testString("/ip4/127.0.0.1/tcp/4321", "047f0000010610e1")
|
|
||||||
testString("/ip4/127.0.0.1/udp/1234/ip4/127.0.0.1/tcp/4321", "047f0000011104d2047f0000010610e1")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBytesSplitAndJoin(t *testing.T) {
|
|
||||||
|
|
||||||
testString := func(s string, res []string) {
|
|
||||||
m, err := NewMultiaddr(s)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("failed to convert", s, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
split := Split(m)
|
|
||||||
if len(split) != len(res) {
|
|
||||||
t.Error("not enough split components", split)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, a := range split {
|
|
||||||
if a.String() != res[i] {
|
|
||||||
t.Errorf("split component failed: %s != %s", a, res[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
joined := Join(split...)
|
|
||||||
if !m.Equal(joined) {
|
|
||||||
t.Errorf("joined components failed: %s != %s", m, joined)
|
|
||||||
}
|
|
||||||
|
|
||||||
// modifying underlying bytes is fine.
|
|
||||||
m2 := m.(*multiaddr)
|
|
||||||
for i := range m2.bytes {
|
|
||||||
m2.bytes[i] = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, a := range split {
|
|
||||||
if a.String() != res[i] {
|
|
||||||
t.Errorf("split component failed: %s != %s", a, res[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
testString("/ip4/1.2.3.4/udp/1234", []string{"/ip4/1.2.3.4", "/udp/1234"})
|
|
||||||
testString("/ip4/1.2.3.4/tcp/1/ip4/2.3.4.5/udp/2",
|
|
||||||
[]string{"/ip4/1.2.3.4", "/tcp/1", "/ip4/2.3.4.5", "/udp/2"})
|
|
||||||
testString("/ip4/1.2.3.4/utp/ip4/2.3.4.5/udp/2/udt",
|
|
||||||
[]string{"/ip4/1.2.3.4", "/utp", "/ip4/2.3.4.5", "/udp/2", "/udt"})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestProtocols(t *testing.T) {
|
|
||||||
m, err := NewMultiaddr("/ip4/127.0.0.1/udp/1234")
|
|
||||||
if err != nil {
|
|
||||||
t.Error("failed to construct", "/ip4/127.0.0.1/udp/1234")
|
|
||||||
}
|
|
||||||
|
|
||||||
ps := m.Protocols()
|
|
||||||
if ps[0].Code != ProtocolWithName("ip4").Code {
|
|
||||||
t.Error(ps[0], ProtocolWithName("ip4"))
|
|
||||||
t.Error("failed to get ip4 protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
if ps[1].Code != ProtocolWithName("udp").Code {
|
|
||||||
t.Error(ps[1], ProtocolWithName("udp"))
|
|
||||||
t.Error("failed to get udp protocol")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestProtocolsWithString(t *testing.T) {
|
|
||||||
pwn := ProtocolWithName
|
|
||||||
good := map[string][]Protocol{
|
|
||||||
"/ip4": []Protocol{pwn("ip4")},
|
|
||||||
"/ip4/tcp": []Protocol{pwn("ip4"), pwn("tcp")},
|
|
||||||
"ip4/tcp/udp/ip6": []Protocol{pwn("ip4"), pwn("tcp"), pwn("udp"), pwn("ip6")},
|
|
||||||
"////////ip4/tcp": []Protocol{pwn("ip4"), pwn("tcp")},
|
|
||||||
"ip4/udp/////////": []Protocol{pwn("ip4"), pwn("udp")},
|
|
||||||
"////////ip4/tcp////////": []Protocol{pwn("ip4"), pwn("tcp")},
|
|
||||||
}
|
|
||||||
|
|
||||||
for s, ps1 := range good {
|
|
||||||
ps2, err := ProtocolsWithString(s)
|
|
||||||
if err != nil {
|
|
||||||
t.Error("ProtocolsWithString(%s) should have succeeded", s)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, ps1p := range ps1 {
|
|
||||||
ps2p := ps2[i]
|
|
||||||
if ps1p.Code != ps2p.Code {
|
|
||||||
t.Errorf("mismatch: %s != %s, %s", ps1p.Name, ps2p.Name, s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bad := []string{
|
|
||||||
"dsijafd", // bogus proto
|
|
||||||
"/ip4/tcp/fidosafoidsa", // bogus proto
|
|
||||||
"////////ip4/tcp/21432141/////////", // bogus proto
|
|
||||||
"////////ip4///////tcp/////////", // empty protos in between
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, s := range bad {
|
|
||||||
if _, err := ProtocolsWithString(s); err == nil {
|
|
||||||
t.Error("ProtocolsWithString(%s) should have failed", s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEncapsulate(t *testing.T) {
|
|
||||||
m, err := NewMultiaddr("/ip4/127.0.0.1/udp/1234")
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
m2, err := NewMultiaddr("/udp/5678")
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
b := m.Encapsulate(m2)
|
|
||||||
if s := b.String(); s != "/ip4/127.0.0.1/udp/1234/udp/5678" {
|
|
||||||
t.Error("encapsulate /ip4/127.0.0.1/udp/1234/udp/5678 failed.", s)
|
|
||||||
}
|
|
||||||
|
|
||||||
m3, _ := NewMultiaddr("/udp/5678")
|
|
||||||
c := b.Decapsulate(m3)
|
|
||||||
if s := c.String(); s != "/ip4/127.0.0.1/udp/1234" {
|
|
||||||
t.Error("decapsulate /udp failed.", "/ip4/127.0.0.1/udp/1234", s)
|
|
||||||
}
|
|
||||||
|
|
||||||
m4, _ := NewMultiaddr("/ip4/127.0.0.1")
|
|
||||||
d := c.Decapsulate(m4)
|
|
||||||
if s := d.String(); s != "" {
|
|
||||||
t.Error("decapsulate /ip4 failed.", "/", s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
12
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.csv
generated
vendored
12
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.csv
generated
vendored
@ -1,12 +0,0 @@
|
|||||||
code size name
|
|
||||||
4 32 ip4
|
|
||||||
6 16 tcp
|
|
||||||
17 16 udp
|
|
||||||
33 16 dccp
|
|
||||||
41 128 ip6
|
|
||||||
132 16 sctp
|
|
||||||
301 0 udt
|
|
||||||
302 0 utp
|
|
||||||
421 V ipfs
|
|
||||||
480 0 http
|
|
||||||
443 0 https
|
|
||||||
|
116
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.go
generated
vendored
116
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.go
generated
vendored
@ -1,116 +0,0 @@
|
|||||||
package multiaddr
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Protocol is a Multiaddr protocol description structure.
|
|
||||||
type Protocol struct {
|
|
||||||
Code int
|
|
||||||
Size int // a size of -1 indicates a length-prefixed variable size
|
|
||||||
Name string
|
|
||||||
VCode []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// replicating table here to:
|
|
||||||
// 1. avoid parsing the csv
|
|
||||||
// 2. ensuring errors in the csv don't screw up code.
|
|
||||||
// 3. changing a number has to happen in two places.
|
|
||||||
const (
|
|
||||||
P_IP4 = 4
|
|
||||||
P_TCP = 6
|
|
||||||
P_UDP = 17
|
|
||||||
P_DCCP = 33
|
|
||||||
P_IP6 = 41
|
|
||||||
P_SCTP = 132
|
|
||||||
P_UTP = 301
|
|
||||||
P_UDT = 302
|
|
||||||
P_IPFS = 421
|
|
||||||
P_HTTP = 480
|
|
||||||
P_HTTPS = 443
|
|
||||||
)
|
|
||||||
|
|
||||||
// These are special sizes
|
|
||||||
const (
|
|
||||||
LengthPrefixedVarSize = -1
|
|
||||||
)
|
|
||||||
|
|
||||||
// Protocols is the list of multiaddr protocols supported by this module.
|
|
||||||
var Protocols = []Protocol{
|
|
||||||
Protocol{P_IP4, 32, "ip4", CodeToVarint(P_IP4)},
|
|
||||||
Protocol{P_TCP, 16, "tcp", CodeToVarint(P_TCP)},
|
|
||||||
Protocol{P_UDP, 16, "udp", CodeToVarint(P_UDP)},
|
|
||||||
Protocol{P_DCCP, 16, "dccp", CodeToVarint(P_DCCP)},
|
|
||||||
Protocol{P_IP6, 128, "ip6", CodeToVarint(P_IP6)},
|
|
||||||
// these require varint:
|
|
||||||
Protocol{P_SCTP, 16, "sctp", CodeToVarint(P_SCTP)},
|
|
||||||
Protocol{P_UTP, 0, "utp", CodeToVarint(P_UTP)},
|
|
||||||
Protocol{P_UDT, 0, "udt", CodeToVarint(P_UDT)},
|
|
||||||
Protocol{P_HTTP, 0, "http", CodeToVarint(P_HTTP)},
|
|
||||||
Protocol{P_HTTPS, 0, "https", CodeToVarint(P_HTTPS)},
|
|
||||||
Protocol{P_IPFS, LengthPrefixedVarSize, "ipfs", CodeToVarint(P_IPFS)},
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProtocolWithName returns the Protocol description with given string name.
|
|
||||||
func ProtocolWithName(s string) Protocol {
|
|
||||||
for _, p := range Protocols {
|
|
||||||
if p.Name == s {
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Protocol{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProtocolWithCode returns the Protocol description with given protocol code.
|
|
||||||
func ProtocolWithCode(c int) Protocol {
|
|
||||||
for _, p := range Protocols {
|
|
||||||
if p.Code == c {
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Protocol{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProtocolsWithString returns a slice of protocols matching given string.
|
|
||||||
func ProtocolsWithString(s string) ([]Protocol, error) {
|
|
||||||
s = strings.Trim(s, "/")
|
|
||||||
sp := strings.Split(s, "/")
|
|
||||||
if len(sp) == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
t := make([]Protocol, len(sp))
|
|
||||||
for i, name := range sp {
|
|
||||||
p := ProtocolWithName(name)
|
|
||||||
if p.Code == 0 {
|
|
||||||
return nil, fmt.Errorf("no protocol with name: %s", name)
|
|
||||||
}
|
|
||||||
t[i] = p
|
|
||||||
}
|
|
||||||
return t, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CodeToVarint converts an integer to a varint-encoded []byte
|
|
||||||
func CodeToVarint(num int) []byte {
|
|
||||||
buf := make([]byte, (num/7)+1) // varint package is uint64
|
|
||||||
n := binary.PutUvarint(buf, uint64(num))
|
|
||||||
return buf[:n]
|
|
||||||
}
|
|
||||||
|
|
||||||
// VarintToCode converts a varint-encoded []byte to an integer protocol code
|
|
||||||
func VarintToCode(buf []byte) int {
|
|
||||||
num, _ := ReadVarintCode(buf)
|
|
||||||
return num
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadVarintCode reads a varint code from the beginning of buf.
|
|
||||||
// returns the code, and the number of bytes read.
|
|
||||||
func ReadVarintCode(buf []byte) (int, int) {
|
|
||||||
num, n := binary.Uvarint(buf)
|
|
||||||
if n < 0 {
|
|
||||||
panic("varints larger than uint64 not yet supported")
|
|
||||||
}
|
|
||||||
return int(num), n
|
|
||||||
}
|
|
||||||
56
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/util.go
generated
vendored
56
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/util.go
generated
vendored
@ -1,56 +0,0 @@
|
|||||||
package multiaddr
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// Split returns the sub-address portions of a multiaddr.
|
|
||||||
func Split(m Multiaddr) []Multiaddr {
|
|
||||||
split, err := bytesSplit(m.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("invalid multiaddr %s", m.String()))
|
|
||||||
}
|
|
||||||
|
|
||||||
addrs := make([]Multiaddr, len(split))
|
|
||||||
for i, addr := range split {
|
|
||||||
addrs[i] = &multiaddr{bytes: addr}
|
|
||||||
}
|
|
||||||
return addrs
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join returns a combination of addresses.
|
|
||||||
func Join(ms ...Multiaddr) Multiaddr {
|
|
||||||
|
|
||||||
length := 0
|
|
||||||
bs := make([][]byte, len(ms))
|
|
||||||
for i, m := range ms {
|
|
||||||
bs[i] = m.Bytes()
|
|
||||||
length += len(bs[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
bidx := 0
|
|
||||||
b := make([]byte, length)
|
|
||||||
for _, mb := range bs {
|
|
||||||
for i := range mb {
|
|
||||||
b[bidx] = mb[i]
|
|
||||||
bidx++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &multiaddr{bytes: b}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cast re-casts a byte slice as a multiaddr. will panic if it fails to parse.
|
|
||||||
func Cast(b []byte) Multiaddr {
|
|
||||||
_, err := bytesToString(b)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("multiaddr failed to parse: %s", err))
|
|
||||||
}
|
|
||||||
return &multiaddr{bytes: b}
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringCast like Cast, but parses a string. Will also panic if it fails to parse.
|
|
||||||
func StringCast(s string) Multiaddr {
|
|
||||||
m, err := NewMultiaddr(s)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("multiaddr failed to parse: %s", err))
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
11
Godeps/_workspace/src/github.com/jbenet/go-multihash/.travis.yml
generated
vendored
11
Godeps/_workspace/src/github.com/jbenet/go-multihash/.travis.yml
generated
vendored
@ -1,11 +0,0 @@
|
|||||||
language: go
|
|
||||||
|
|
||||||
go:
|
|
||||||
- 1.3
|
|
||||||
- release
|
|
||||||
- tip
|
|
||||||
|
|
||||||
script:
|
|
||||||
- make test
|
|
||||||
|
|
||||||
env: TEST_VERBOSE=1
|
|
||||||
21
Godeps/_workspace/src/github.com/jbenet/go-multihash/LICENSE
generated
vendored
21
Godeps/_workspace/src/github.com/jbenet/go-multihash/LICENSE
generated
vendored
@ -1,21 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2014 Juan Batiz-Benet
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
11
Godeps/_workspace/src/github.com/jbenet/go-multihash/Makefile
generated
vendored
11
Godeps/_workspace/src/github.com/jbenet/go-multihash/Makefile
generated
vendored
@ -1,11 +0,0 @@
|
|||||||
test: go_test other_tests
|
|
||||||
|
|
||||||
other_tests:
|
|
||||||
cd test && make test
|
|
||||||
|
|
||||||
go_test: go_deps
|
|
||||||
go test -race -cpu=5 -v ./...
|
|
||||||
|
|
||||||
go_deps:
|
|
||||||
go get golang.org/x/crypto/sha3
|
|
||||||
go get github.com/jbenet/go-base58
|
|
||||||
45
Godeps/_workspace/src/github.com/jbenet/go-multihash/README.md
generated
vendored
45
Godeps/_workspace/src/github.com/jbenet/go-multihash/README.md
generated
vendored
@ -1,45 +0,0 @@
|
|||||||
# go-multihash
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
[multihash](//github.com/jbenet/multihash) implementation in Go.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
```go
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"github.com/jbenet/go-multihash"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// ignores errors for simplicity.
|
|
||||||
// don't do that at home.
|
|
||||||
|
|
||||||
buf, _ := hex.DecodeString("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33")
|
|
||||||
mhbuf, _ := multihash.EncodeName(buf, "sha1");
|
|
||||||
mhhex := hex.EncodeToString(mhbuf)
|
|
||||||
fmt.Printf("hex: %v\n", mhhex);
|
|
||||||
|
|
||||||
o, _ := multihash.Decode(mhbuf);
|
|
||||||
mhhex = hex.EncodeToString(o.Digest);
|
|
||||||
fmt.Printf("obj: %v 0x%x %d %s\n", o.Name, o.Code, o.Length, mhhex);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Run [test/foo.go](test/foo.go)
|
|
||||||
|
|
||||||
```
|
|
||||||
> cd test/
|
|
||||||
> go build
|
|
||||||
> ./test
|
|
||||||
hex: 11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33
|
|
||||||
obj: sha1 0x11 20 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
MIT
|
|
||||||
79
Godeps/_workspace/src/github.com/jbenet/go-multihash/io.go
generated
vendored
79
Godeps/_workspace/src/github.com/jbenet/go-multihash/io.go
generated
vendored
@ -1,79 +0,0 @@
|
|||||||
package multihash
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Reader is an io.Reader wrapper that exposes a function
|
|
||||||
// to read a whole multihash, parse it, and return it.
|
|
||||||
type Reader interface {
|
|
||||||
io.Reader
|
|
||||||
|
|
||||||
ReadMultihash() (Multihash, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Writer is an io.Writer wrapper that exposes a function
|
|
||||||
// to write a whole multihash.
|
|
||||||
type Writer interface {
|
|
||||||
io.Writer
|
|
||||||
|
|
||||||
WriteMultihash(Multihash) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewReader wraps an io.Reader with a multihash.Reader
|
|
||||||
func NewReader(r io.Reader) Reader {
|
|
||||||
return &mhReader{r}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewWriter wraps an io.Writer with a multihash.Writer
|
|
||||||
func NewWriter(w io.Writer) Writer {
|
|
||||||
return &mhWriter{w}
|
|
||||||
}
|
|
||||||
|
|
||||||
type mhReader struct {
|
|
||||||
r io.Reader
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *mhReader) Read(buf []byte) (n int, err error) {
|
|
||||||
return r.r.Read(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *mhReader) ReadMultihash() (Multihash, error) {
|
|
||||||
mhhdr := make([]byte, 2)
|
|
||||||
if _, err := io.ReadFull(r.r, mhhdr); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// first byte is the algo, the second is the length.
|
|
||||||
|
|
||||||
// (varints someday...)
|
|
||||||
length := uint(mhhdr[1])
|
|
||||||
|
|
||||||
if length > 127 {
|
|
||||||
return nil, fmt.Errorf("varints not yet supported (length is %d)", length)
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := make([]byte, length+2)
|
|
||||||
buf[0] = mhhdr[0]
|
|
||||||
buf[1] = mhhdr[1]
|
|
||||||
|
|
||||||
if _, err := io.ReadFull(r.r, buf[2:]); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return Cast(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
type mhWriter struct {
|
|
||||||
w io.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *mhWriter) Write(buf []byte) (n int, err error) {
|
|
||||||
return w.w.Write(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *mhWriter) WriteMultihash(m Multihash) error {
|
|
||||||
_, err := w.w.Write([]byte(m))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
69
Godeps/_workspace/src/github.com/jbenet/go-multihash/io_test.go
generated
vendored
69
Godeps/_workspace/src/github.com/jbenet/go-multihash/io_test.go
generated
vendored
@ -1,69 +0,0 @@
|
|||||||
package multihash
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestReader(t *testing.T) {
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
m, err := tc.Multihash()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
buf.Write([]byte(m))
|
|
||||||
}
|
|
||||||
|
|
||||||
r := NewReader(&buf)
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
h, err := tc.Multihash()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
h2, err := r.ReadMultihash()
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(h, h2) {
|
|
||||||
t.Error("h and h2 should be equal")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWriter(t *testing.T) {
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
w := NewWriter(&buf)
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
m, err := tc.Multihash()
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := w.WriteMultihash(m); err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
buf2 := make([]byte, len(m))
|
|
||||||
if _, err := io.ReadFull(&buf, buf2); err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(m, buf2) {
|
|
||||||
t.Error("m and buf2 should be equal")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
188
Godeps/_workspace/src/github.com/jbenet/go-multihash/multihash.go
generated
vendored
188
Godeps/_workspace/src/github.com/jbenet/go-multihash/multihash.go
generated
vendored
@ -1,188 +0,0 @@
|
|||||||
package multihash
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
b58 "github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/jbenet/go-base58"
|
|
||||||
)
|
|
||||||
|
|
||||||
// errors
|
|
||||||
var (
|
|
||||||
ErrUnknownCode = errors.New("unknown multihash code")
|
|
||||||
ErrTooShort = errors.New("multihash too short. must be > 3 bytes")
|
|
||||||
ErrTooLong = errors.New("multihash too long. must be < 129 bytes")
|
|
||||||
ErrLenNotSupported = errors.New("multihash does not yet support digests longer than 127 bytes")
|
|
||||||
)
|
|
||||||
|
|
||||||
// ErrInconsistentLen is returned when a decoded multihash has an inconsistent length
|
|
||||||
type ErrInconsistentLen struct {
|
|
||||||
dm *DecodedMultihash
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e ErrInconsistentLen) Error() string {
|
|
||||||
return fmt.Sprintf("multihash length inconsistent: %v", e.dm)
|
|
||||||
}
|
|
||||||
|
|
||||||
// constants
|
|
||||||
const (
|
|
||||||
SHA1 = 0x11
|
|
||||||
SHA2_256 = 0x12
|
|
||||||
SHA2_512 = 0x13
|
|
||||||
SHA3 = 0x14
|
|
||||||
BLAKE2B = 0x40
|
|
||||||
BLAKE2S = 0x41
|
|
||||||
)
|
|
||||||
|
|
||||||
// Names maps the name of a hash to the code
|
|
||||||
var Names = map[string]int{
|
|
||||||
"sha1": SHA1,
|
|
||||||
"sha2-256": SHA2_256,
|
|
||||||
"sha2-512": SHA2_512,
|
|
||||||
"sha3": SHA3,
|
|
||||||
"blake2b": BLAKE2B,
|
|
||||||
"blake2s": BLAKE2S,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Codes maps a hash code to it's name
|
|
||||||
var Codes = map[int]string{
|
|
||||||
SHA1: "sha1",
|
|
||||||
SHA2_256: "sha2-256",
|
|
||||||
SHA2_512: "sha2-512",
|
|
||||||
SHA3: "sha3",
|
|
||||||
BLAKE2B: "blake2b",
|
|
||||||
BLAKE2S: "blake2s",
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultLengths maps a hash code to it's default length
|
|
||||||
var DefaultLengths = map[int]int{
|
|
||||||
SHA1: 20,
|
|
||||||
SHA2_256: 32,
|
|
||||||
SHA2_512: 64,
|
|
||||||
SHA3: 64,
|
|
||||||
BLAKE2B: 64,
|
|
||||||
BLAKE2S: 32,
|
|
||||||
}
|
|
||||||
|
|
||||||
type DecodedMultihash struct {
|
|
||||||
Code int
|
|
||||||
Name string
|
|
||||||
Length int
|
|
||||||
Digest []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
type Multihash []byte
|
|
||||||
|
|
||||||
func (m *Multihash) HexString() string {
|
|
||||||
return hex.EncodeToString([]byte(*m))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Multihash) String() string {
|
|
||||||
return m.HexString()
|
|
||||||
}
|
|
||||||
|
|
||||||
func FromHexString(s string) (Multihash, error) {
|
|
||||||
b, err := hex.DecodeString(s)
|
|
||||||
if err != nil {
|
|
||||||
return Multihash{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return Cast(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m Multihash) B58String() string {
|
|
||||||
return b58.Encode([]byte(m))
|
|
||||||
}
|
|
||||||
|
|
||||||
func FromB58String(s string) (m Multihash, err error) {
|
|
||||||
// panic handler, in case we try accessing bytes incorrectly.
|
|
||||||
defer func() {
|
|
||||||
if e := recover(); e != nil {
|
|
||||||
m = Multihash{}
|
|
||||||
err = e.(error)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
//b58 smells like it can panic...
|
|
||||||
b := b58.Decode(s)
|
|
||||||
return Cast(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Cast(buf []byte) (Multihash, error) {
|
|
||||||
dm, err := Decode(buf)
|
|
||||||
if err != nil {
|
|
||||||
return Multihash{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !ValidCode(dm.Code) {
|
|
||||||
return Multihash{}, ErrUnknownCode
|
|
||||||
}
|
|
||||||
|
|
||||||
return Multihash(buf), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a hash from the given Multihash.
|
|
||||||
func Decode(buf []byte) (*DecodedMultihash, error) {
|
|
||||||
|
|
||||||
if len(buf) < 3 {
|
|
||||||
return nil, ErrTooShort
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(buf) > 129 {
|
|
||||||
return nil, ErrTooLong
|
|
||||||
}
|
|
||||||
|
|
||||||
dm := &DecodedMultihash{
|
|
||||||
Code: int(uint8(buf[0])),
|
|
||||||
Name: Codes[int(uint8(buf[0]))],
|
|
||||||
Length: int(uint8(buf[1])),
|
|
||||||
Digest: buf[2:],
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(dm.Digest) != dm.Length {
|
|
||||||
return nil, ErrInconsistentLen{dm}
|
|
||||||
}
|
|
||||||
|
|
||||||
return dm, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encode a hash digest along with the specified function code.
|
|
||||||
// Note: the length is derived from the length of the digest itself.
|
|
||||||
func Encode(buf []byte, code int) ([]byte, error) {
|
|
||||||
|
|
||||||
if !ValidCode(code) {
|
|
||||||
return nil, ErrUnknownCode
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(buf) > 127 {
|
|
||||||
return nil, ErrLenNotSupported
|
|
||||||
}
|
|
||||||
|
|
||||||
pre := make([]byte, 2)
|
|
||||||
pre[0] = byte(uint8(code))
|
|
||||||
pre[1] = byte(uint8(len(buf)))
|
|
||||||
return append(pre, buf...), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func EncodeName(buf []byte, name string) ([]byte, error) {
|
|
||||||
return Encode(buf, Names[name])
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidCode checks whether a multihash code is valid.
|
|
||||||
func ValidCode(code int) bool {
|
|
||||||
if AppCode(code) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := Codes[code]; ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// AppCode checks whether a multihash code is part of the App range.
|
|
||||||
func AppCode(code int) bool {
|
|
||||||
return code >= 0 && code < 0x10
|
|
||||||
}
|
|
||||||
1
Godeps/_workspace/src/github.com/jbenet/go-multihash/multihash/.gitignore
generated
vendored
1
Godeps/_workspace/src/github.com/jbenet/go-multihash/multihash/.gitignore
generated
vendored
@ -1 +0,0 @@
|
|||||||
multihash
|
|
||||||
116
Godeps/_workspace/src/github.com/jbenet/go-multihash/multihash/README.md
generated
vendored
116
Godeps/_workspace/src/github.com/jbenet/go-multihash/multihash/README.md
generated
vendored
@ -1,116 +0,0 @@
|
|||||||
# multihash tool
|
|
||||||
|
|
||||||
The `multihash` tool uses `go-multihash` to hash things much like `shasum`.
|
|
||||||
|
|
||||||
Warning: this is a **multihash** tool! Its digests follow the [multihash](https://github.com/jbenet/multihash) format.
|
|
||||||
|
|
||||||
### Install
|
|
||||||
|
|
||||||
```
|
|
||||||
go get github.com/jbenet/go-multihash/multihash
|
|
||||||
```
|
|
||||||
|
|
||||||
### Usage
|
|
||||||
|
|
||||||
```sh
|
|
||||||
> multihash -h
|
|
||||||
usage: ./multihash [options] [FILE]
|
|
||||||
Print or check multihash checksums.
|
|
||||||
With no FILE, or when FILE is -, read standard input.
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-a="sha2-256": one of: sha1, sha2-256, sha2-512, sha3 (shorthand)
|
|
||||||
-algorithm="sha2-256": one of: sha1, sha2-256, sha2-512, sha3
|
|
||||||
-c="": check checksum matches (shorthand)
|
|
||||||
-check="": check checksum matches
|
|
||||||
-e="base58": one of: raw, hex, base58, base64 (shorthand)
|
|
||||||
-encoding="base58": one of: raw, hex, base58, base64
|
|
||||||
-l=-1: checksums length in bits (truncate). -1 is default (shorthand)
|
|
||||||
-length=-1: checksums length in bits (truncate). -1 is default
|
|
||||||
```
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
#### Input
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# from stdin
|
|
||||||
> multihash < main.go
|
|
||||||
QmRZxt2b1FVZPNqd8hsiykDL3TdBDeTSPX9Kv46HmX4Gx8
|
|
||||||
|
|
||||||
# from file
|
|
||||||
> ./multihash main.go
|
|
||||||
QmRZxt2b1FVZPNqd8hsiykDL3TdBDeTSPX9Kv46HmX4Gx8
|
|
||||||
|
|
||||||
# from stdin "filename"
|
|
||||||
> multihash - < main.go
|
|
||||||
QmRZxt2b1FVZPNqd8hsiykDL3TdBDeTSPX9Kv46HmX4Gx8
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Algorithms
|
|
||||||
|
|
||||||
```sh
|
|
||||||
> multihash -a ?
|
|
||||||
error: algorithm '?' not one of: sha1, sha2-256, sha2-512, sha3
|
|
||||||
|
|
||||||
> multihash -a sha1 < main.go
|
|
||||||
5drkbcqJUo6fZVvcZJeVEVWAgndvLm
|
|
||||||
|
|
||||||
> multihash -a sha2-256 < main.go
|
|
||||||
QmcK3s36goo9v2HYcfTrDKKwxaxmJJ59etodQQFYsL5T5N
|
|
||||||
|
|
||||||
> multihash -a sha2-512 < main.go
|
|
||||||
8VuDcW4CooyPQA8Cc4eYpwjhyDJZqu5m5ZMDFzWULYsVS8d119JaGeNWsZbZ2ZG2kPtbrMx31MidokCigaD65yUPAs
|
|
||||||
|
|
||||||
> multihash -a sha3 < main.go
|
|
||||||
8tWDCTfAX24DYmzNixTj2ARJkqwRG736VHx5aJppmqRjhW9QT1EuTgKUmu9Pmunzq292jzPKxb2VxSsTXmjFY1HD3B
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Encodings
|
|
||||||
|
|
||||||
```sh
|
|
||||||
> multihash -e raw < main.go
|
|
||||||
Ϛ<><CF9A><EFBFBD><EFBFBD><EFBFBD>I<EFBFBD>5 S<><53>WG><3E><><EFBFBD>_<EFBFBD><5F>]g<><67><EFBFBD><EFBFBD><EFBFBD>u
|
|
||||||
|
|
||||||
> multihash -e hex < main.go
|
|
||||||
1220cf9aa2b8a38b9b49d135095390059a57473e97aceb5fcae25d67a8b6feb58275
|
|
||||||
|
|
||||||
> multihash -e base64 < main.go
|
|
||||||
EiDPmqK4o4ubSdE1CVOQBZpXRz6XrOtfyuJdZ6i2/rWCdQ==
|
|
||||||
|
|
||||||
> multihash -e base58 < main.go
|
|
||||||
Qmf1QjEXDmqBm7RqHKqFGNUyhzUjnX7cmgKMrGzzPceZDQ
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Digest Length
|
|
||||||
|
|
||||||
```sh
|
|
||||||
# we're outputing hex (good byte alignment) to show the codes changing
|
|
||||||
# notice the multihash code (first 2 chars) differs!
|
|
||||||
> multihash -e hex -a sha2-256 -l 256 < main.go
|
|
||||||
1220cf9aa2b8a38b9b49d135095390059a57473e97aceb5fcae25d67a8b6feb58275
|
|
||||||
> multihash -e hex -a sha2-512 -l 256 < main.go
|
|
||||||
132047a4b6c629f5545f529b0ff461dc09119969f3593186277a1cc7a8ea3560a6f1
|
|
||||||
> multihash -e hex -a sha3 -l 256 < main.go
|
|
||||||
14206b9222a1a47939e665261bd2b5573e55e7988675223adde73c1011066ad66335
|
|
||||||
|
|
||||||
# notice the multihash length (next 2 chars) differs!
|
|
||||||
> multihash -e hex -a sha2-256 -l 256 < main.go
|
|
||||||
1220cf9aa2b8a38b9b49d135095390059a57473e97aceb5fcae25d67a8b6feb58275
|
|
||||||
> multihash -e hex -a sha2-256 -l 200 < main.go
|
|
||||||
1219cf9aa2b8a38b9b49d135095390059a57473e97aceb5fcae25d
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Verify Checksum
|
|
||||||
|
|
||||||
```sh
|
|
||||||
> multihash -c QmRZxt2b1FVZPNqd8hsiykDL3TdBDeTSPX9Kv46HmX4Gx8 < main.go
|
|
||||||
OK checksums match (-q for no output)
|
|
||||||
|
|
||||||
> multihash -c QmcKaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa < main.go
|
|
||||||
error: computed checksum did not match (-q for no output)
|
|
||||||
|
|
||||||
# works with other arguments too
|
|
||||||
> multihash -e hex -l 128 -c "12102ffc284a1e82bf51e567c75b2ae6edb9" < main.go
|
|
||||||
OK checksums match (-q for no output)
|
|
||||||
```
|
|
||||||
40
Godeps/_workspace/src/github.com/jbenet/go-multihash/multihash/coding.go
generated
vendored
40
Godeps/_workspace/src/github.com/jbenet/go-multihash/multihash/coding.go
generated
vendored
@ -1,40 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
base58 "github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/jbenet/go-base58"
|
|
||||||
mh "github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/jbenet/go-multihash"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Decode(encoding, digest string) (mh.Multihash, error) {
|
|
||||||
switch encoding {
|
|
||||||
case "raw":
|
|
||||||
return mh.Cast([]byte(digest))
|
|
||||||
case "hex":
|
|
||||||
return hex.DecodeString(digest)
|
|
||||||
case "base58":
|
|
||||||
return base58.Decode(digest), nil
|
|
||||||
case "base64":
|
|
||||||
return base64.StdEncoding.DecodeString(digest)
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unknown encoding: %s", encoding)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Encode(encoding string, hash mh.Multihash) (string, error) {
|
|
||||||
switch encoding {
|
|
||||||
case "raw":
|
|
||||||
return string(hash), nil
|
|
||||||
case "hex":
|
|
||||||
return hex.EncodeToString(hash), nil
|
|
||||||
case "base58":
|
|
||||||
return base58.Encode(hash), nil
|
|
||||||
case "base64":
|
|
||||||
return base64.StdEncoding.EncodeToString(hash), nil
|
|
||||||
default:
|
|
||||||
return "", fmt.Errorf("unknown encoding: %s", encoding)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
208
Godeps/_workspace/src/github.com/jbenet/go-multihash/multihash/main.go
generated
vendored
208
Godeps/_workspace/src/github.com/jbenet/go-multihash/multihash/main.go
generated
vendored
@ -1,208 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
mh "github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/jbenet/go-multihash"
|
|
||||||
)
|
|
||||||
|
|
||||||
var usage = `usage: %s [options] [FILE]
|
|
||||||
Print or check multihash checksums.
|
|
||||||
With no FILE, or when FILE is -, read standard input.
|
|
||||||
|
|
||||||
Options:
|
|
||||||
`
|
|
||||||
|
|
||||||
// flags
|
|
||||||
var encodings = []string{"raw", "hex", "base58", "base64"}
|
|
||||||
var algorithms = []string{"sha1", "sha2-256", "sha2-512", "sha3"}
|
|
||||||
var encoding string
|
|
||||||
var algorithm string
|
|
||||||
var algorithmCode int
|
|
||||||
var length int
|
|
||||||
var checkRaw string
|
|
||||||
var checkMh mh.Multihash
|
|
||||||
var inputFilename string
|
|
||||||
var quiet bool
|
|
||||||
|
|
||||||
// joined names
|
|
||||||
var algoStr string
|
|
||||||
var encStr string
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
flag.Usage = func() {
|
|
||||||
fmt.Fprintf(os.Stderr, usage, os.Args[0])
|
|
||||||
flag.PrintDefaults()
|
|
||||||
}
|
|
||||||
|
|
||||||
algoStr = "one of: " + strings.Join(algorithms, ", ")
|
|
||||||
flag.StringVar(&algorithm, "algorithm", "sha2-256", algoStr)
|
|
||||||
flag.StringVar(&algorithm, "a", "sha2-256", algoStr+" (shorthand)")
|
|
||||||
|
|
||||||
encStr = "one of: " + strings.Join(encodings, ", ")
|
|
||||||
flag.StringVar(&encoding, "encoding", "base58", encStr)
|
|
||||||
flag.StringVar(&encoding, "e", "base58", encStr+" (shorthand)")
|
|
||||||
|
|
||||||
checkStr := "check checksum matches"
|
|
||||||
flag.StringVar(&checkRaw, "check", "", checkStr)
|
|
||||||
flag.StringVar(&checkRaw, "c", "", checkStr+" (shorthand)")
|
|
||||||
|
|
||||||
lengthStr := "checksums length in bits (truncate). -1 is default"
|
|
||||||
flag.IntVar(&length, "length", -1, lengthStr)
|
|
||||||
flag.IntVar(&length, "l", -1, lengthStr+" (shorthand)")
|
|
||||||
|
|
||||||
quietStr := "quiet output (no newline on checksum, no error text)"
|
|
||||||
flag.BoolVar(&quiet, "quiet", false, quietStr)
|
|
||||||
flag.BoolVar(&quiet, "q", false, quietStr+" (shorthand)")
|
|
||||||
}
|
|
||||||
|
|
||||||
func strIn(a string, set []string) bool {
|
|
||||||
for _, s := range set {
|
|
||||||
if s == a {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseFlags() error {
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
if !strIn(algorithm, algorithms) {
|
|
||||||
return fmt.Errorf("algorithm '%s' not %s", algorithm, algoStr)
|
|
||||||
}
|
|
||||||
var found bool
|
|
||||||
algorithmCode, found = mh.Names[algorithm]
|
|
||||||
if !found {
|
|
||||||
return fmt.Errorf("algorithm '%s' not found (lib error, pls report).")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !strIn(encoding, encodings) {
|
|
||||||
return fmt.Errorf("encoding '%s' not %s", encoding, encStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
if checkRaw != "" {
|
|
||||||
var err error
|
|
||||||
checkMh, err = Decode(encoding, checkRaw)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("fail to decode check '%s': %s", checkRaw, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if length >= 0 {
|
|
||||||
if length%8 != 0 {
|
|
||||||
return fmt.Errorf("length must be multiple of 8")
|
|
||||||
}
|
|
||||||
length = length / 8
|
|
||||||
|
|
||||||
if length > mh.DefaultLengths[algorithmCode] {
|
|
||||||
length = mh.DefaultLengths[algorithmCode]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getInput() (io.ReadCloser, error) {
|
|
||||||
args := flag.Args()
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case len(args) < 1:
|
|
||||||
inputFilename = "-"
|
|
||||||
return os.Stdin, nil
|
|
||||||
case args[0] == "-":
|
|
||||||
inputFilename = "-"
|
|
||||||
return os.Stdin, nil
|
|
||||||
default:
|
|
||||||
inputFilename = args[0]
|
|
||||||
f, err := os.Open(args[0])
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to open '%s': %s", args[0], err)
|
|
||||||
}
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func check(h1 mh.Multihash, r io.Reader) error {
|
|
||||||
h2, err := hash(r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(h1, h2) {
|
|
||||||
if quiet {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("computed checksum did not match (-q for no output)")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !quiet {
|
|
||||||
fmt.Println("OK checksums match (-q for no output)")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func hash(r io.Reader) (mh.Multihash, error) {
|
|
||||||
b, err := ioutil.ReadAll(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return mh.Sum(b, algorithmCode, length)
|
|
||||||
}
|
|
||||||
|
|
||||||
func printHash(r io.Reader) error {
|
|
||||||
h, err := hash(r)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
s, err := Encode(encoding, h)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if quiet {
|
|
||||||
fmt.Print(s)
|
|
||||||
} else {
|
|
||||||
fmt.Println(s)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
checkErr := func(err error) {
|
|
||||||
if err != nil {
|
|
||||||
die("error: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err := parseFlags()
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
inp, err := getInput()
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
if checkMh != nil {
|
|
||||||
err = check(checkMh, inp)
|
|
||||||
checkErr(err)
|
|
||||||
} else {
|
|
||||||
err = printHash(inp)
|
|
||||||
checkErr(err)
|
|
||||||
}
|
|
||||||
inp.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func die(v ...interface{}) {
|
|
||||||
if !quiet {
|
|
||||||
fmt.Fprint(os.Stderr, v...)
|
|
||||||
fmt.Fprint(os.Stderr, "\n")
|
|
||||||
}
|
|
||||||
// flag.Usage()
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
270
Godeps/_workspace/src/github.com/jbenet/go-multihash/multihash_test.go
generated
vendored
270
Godeps/_workspace/src/github.com/jbenet/go-multihash/multihash_test.go
generated
vendored
@ -1,270 +0,0 @@
|
|||||||
package multihash
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
// maybe silly, but makes it so changing
|
|
||||||
// the table accidentally has to happen twice.
|
|
||||||
var tCodes = map[int]string{
|
|
||||||
0x11: "sha1",
|
|
||||||
0x12: "sha2-256",
|
|
||||||
0x13: "sha2-512",
|
|
||||||
0x14: "sha3",
|
|
||||||
0x40: "blake2b",
|
|
||||||
0x41: "blake2s",
|
|
||||||
}
|
|
||||||
|
|
||||||
type TestCase struct {
|
|
||||||
hex string
|
|
||||||
code int
|
|
||||||
name string
|
|
||||||
}
|
|
||||||
|
|
||||||
var testCases = []TestCase{
|
|
||||||
TestCase{"0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33", 0x11, "sha1"},
|
|
||||||
TestCase{"0beec7b5", 0x11, "sha1"},
|
|
||||||
TestCase{"2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae", 0x12, "sha2-256"},
|
|
||||||
TestCase{"2c26b46b", 0x12, "sha2-256"},
|
|
||||||
TestCase{"0beec7b5ea3f0fdbc9", 0x40, "blake2b"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func (tc TestCase) Multihash() (Multihash, error) {
|
|
||||||
ob, err := hex.DecodeString(tc.hex)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
b := make([]byte, 2+len(ob))
|
|
||||||
b[0] = byte(uint8(tc.code))
|
|
||||||
b[1] = byte(uint8(len(ob)))
|
|
||||||
copy(b[2:], ob)
|
|
||||||
return Cast(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEncode(t *testing.T) {
|
|
||||||
for _, tc := range testCases {
|
|
||||||
ob, err := hex.DecodeString(tc.hex)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
pre := make([]byte, 2)
|
|
||||||
pre[0] = byte(uint8(tc.code))
|
|
||||||
pre[1] = byte(uint8(len(ob)))
|
|
||||||
nb := append(pre, ob...)
|
|
||||||
|
|
||||||
encC, err := Encode(ob, tc.code)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(encC, nb) {
|
|
||||||
t.Error("encoded byte mismatch: ", encC, nb)
|
|
||||||
}
|
|
||||||
|
|
||||||
encN, err := EncodeName(ob, tc.name)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(encN, nb) {
|
|
||||||
t.Error("encoded byte mismatch: ", encN, nb)
|
|
||||||
}
|
|
||||||
|
|
||||||
h, err := tc.Multihash()
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
if !bytes.Equal(h, nb) {
|
|
||||||
t.Error("Multihash func mismatch.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleEncodeName() {
|
|
||||||
// ignores errors for simplicity - don't do that at home.
|
|
||||||
buf, _ := hex.DecodeString("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33")
|
|
||||||
mhbuf, _ := EncodeName(buf, "sha1")
|
|
||||||
mhhex := hex.EncodeToString(mhbuf)
|
|
||||||
fmt.Printf("hex: %v\n", mhhex)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// hex: 11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDecode(t *testing.T) {
|
|
||||||
for _, tc := range testCases {
|
|
||||||
ob, err := hex.DecodeString(tc.hex)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
pre := make([]byte, 2)
|
|
||||||
pre[0] = byte(uint8(tc.code))
|
|
||||||
pre[1] = byte(uint8(len(ob)))
|
|
||||||
nb := append(pre, ob...)
|
|
||||||
|
|
||||||
dec, err := Decode(nb)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if dec.Code != tc.code {
|
|
||||||
t.Error("decoded code mismatch: ", dec.Code, tc.code)
|
|
||||||
}
|
|
||||||
|
|
||||||
if dec.Name != tc.name {
|
|
||||||
t.Error("decoded name mismatch: ", dec.Name, tc.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if dec.Length != len(ob) {
|
|
||||||
t.Error("decoded length mismatch: ", dec.Length, len(ob))
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(dec.Digest, ob) {
|
|
||||||
t.Error("decoded byte mismatch: ", dec.Digest, ob)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTable(t *testing.T) {
|
|
||||||
for k, v := range tCodes {
|
|
||||||
if Codes[k] != v {
|
|
||||||
t.Error("Table mismatch: ", Codes[k], v)
|
|
||||||
}
|
|
||||||
if Names[v] != k {
|
|
||||||
t.Error("Table mismatch: ", Names[v], k)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleDecode() {
|
|
||||||
// ignores errors for simplicity - don't do that at home.
|
|
||||||
buf, _ := hex.DecodeString("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33")
|
|
||||||
mhbuf, _ := EncodeName(buf, "sha1")
|
|
||||||
o, _ := Decode(mhbuf)
|
|
||||||
mhhex := hex.EncodeToString(o.Digest)
|
|
||||||
fmt.Printf("obj: %v 0x%x %d %s\n", o.Name, o.Code, o.Length, mhhex)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// obj: sha1 0x11 20 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValidCode(t *testing.T) {
|
|
||||||
for i := 0; i < 0xff; i++ {
|
|
||||||
_, ok := tCodes[i]
|
|
||||||
b := AppCode(i) || ok
|
|
||||||
|
|
||||||
if ValidCode(i) != b {
|
|
||||||
t.Error("ValidCode incorrect for: ", i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestAppCode(t *testing.T) {
|
|
||||||
for i := 0; i < 0xff; i++ {
|
|
||||||
b := i >= 0 && i < 0x10
|
|
||||||
if AppCode(i) != b {
|
|
||||||
t.Error("AppCode incorrect for: ", i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCast(t *testing.T) {
|
|
||||||
for _, tc := range testCases {
|
|
||||||
ob, err := hex.DecodeString(tc.hex)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
pre := make([]byte, 2)
|
|
||||||
pre[0] = byte(uint8(tc.code))
|
|
||||||
pre[1] = byte(uint8(len(ob)))
|
|
||||||
nb := append(pre, ob...)
|
|
||||||
|
|
||||||
if _, err := Cast(nb); err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err = Cast(ob); err == nil {
|
|
||||||
t.Error("cast failed to detect non-multihash")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHex(t *testing.T) {
|
|
||||||
for _, tc := range testCases {
|
|
||||||
ob, err := hex.DecodeString(tc.hex)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
pre := make([]byte, 2)
|
|
||||||
pre[0] = byte(uint8(tc.code))
|
|
||||||
pre[1] = byte(uint8(len(ob)))
|
|
||||||
nb := append(pre, ob...)
|
|
||||||
|
|
||||||
hs := hex.EncodeToString(nb)
|
|
||||||
mh, err := FromHexString(hs)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(mh, nb) {
|
|
||||||
t.Error("FromHexString failed", nb, mh)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if mh.HexString() != hs {
|
|
||||||
t.Error("Multihash.HexString failed", hs, mh.HexString)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkEncode(b *testing.B) {
|
|
||||||
tc := testCases[0]
|
|
||||||
ob, err := hex.DecodeString(tc.hex)
|
|
||||||
if err != nil {
|
|
||||||
b.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
Encode(ob, tc.code)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkDecode(b *testing.B) {
|
|
||||||
tc := testCases[0]
|
|
||||||
ob, err := hex.DecodeString(tc.hex)
|
|
||||||
if err != nil {
|
|
||||||
b.Error(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pre := make([]byte, 2)
|
|
||||||
pre[0] = byte(uint8(tc.code))
|
|
||||||
pre[1] = byte(uint8(len(ob)))
|
|
||||||
nb := append(pre, ob...)
|
|
||||||
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
Decode(nb)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
72
Godeps/_workspace/src/github.com/jbenet/go-multihash/sum.go
generated
vendored
72
Godeps/_workspace/src/github.com/jbenet/go-multihash/sum.go
generated
vendored
@ -1,72 +0,0 @@
|
|||||||
package multihash
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/sha1"
|
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/sha512"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
sha3 "github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/golang.org/x/crypto/sha3"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ErrSumNotSupported = errors.New("Function not implemented. Complain to lib maintainer.")
|
|
||||||
|
|
||||||
func Sum(data []byte, code int, length int) (Multihash, error) {
|
|
||||||
m := Multihash{}
|
|
||||||
err := error(nil)
|
|
||||||
if !ValidCode(code) {
|
|
||||||
return m, fmt.Errorf("invalid multihash code %d", code)
|
|
||||||
}
|
|
||||||
|
|
||||||
var d []byte
|
|
||||||
switch code {
|
|
||||||
case SHA1:
|
|
||||||
d = sumSHA1(data)
|
|
||||||
case SHA2_256:
|
|
||||||
d = sumSHA256(data)
|
|
||||||
case SHA2_512:
|
|
||||||
d = sumSHA512(data)
|
|
||||||
case SHA3:
|
|
||||||
d, err = sumSHA3(data)
|
|
||||||
default:
|
|
||||||
return m, ErrSumNotSupported
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return m, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if length < 0 {
|
|
||||||
var ok bool
|
|
||||||
length, ok = DefaultLengths[code]
|
|
||||||
if !ok {
|
|
||||||
return m, fmt.Errorf("no default length for code %d", code)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Encode(d[0:length], code)
|
|
||||||
}
|
|
||||||
|
|
||||||
func sumSHA1(data []byte) []byte {
|
|
||||||
a := sha1.Sum(data)
|
|
||||||
return a[0:20]
|
|
||||||
}
|
|
||||||
|
|
||||||
func sumSHA256(data []byte) []byte {
|
|
||||||
a := sha256.Sum256(data)
|
|
||||||
return a[0:32]
|
|
||||||
}
|
|
||||||
|
|
||||||
func sumSHA512(data []byte) []byte {
|
|
||||||
a := sha512.Sum512(data)
|
|
||||||
return a[0:64]
|
|
||||||
}
|
|
||||||
|
|
||||||
func sumSHA3(data []byte) ([]byte, error) {
|
|
||||||
h := sha3.New512()
|
|
||||||
if _, err := h.Write(data); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return h.Sum(nil), nil
|
|
||||||
}
|
|
||||||
66
Godeps/_workspace/src/github.com/jbenet/go-multihash/sum_test.go
generated
vendored
66
Godeps/_workspace/src/github.com/jbenet/go-multihash/sum_test.go
generated
vendored
@ -1,66 +0,0 @@
|
|||||||
package multihash
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SumTestCase struct {
|
|
||||||
code int
|
|
||||||
length int
|
|
||||||
input string
|
|
||||||
hex string
|
|
||||||
}
|
|
||||||
|
|
||||||
var sumTestCases = []SumTestCase{
|
|
||||||
SumTestCase{SHA1, -1, "foo", "11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33"},
|
|
||||||
SumTestCase{SHA1, 10, "foo", "110a0beec7b5ea3f0fdbc95d"},
|
|
||||||
SumTestCase{SHA2_256, -1, "foo", "12202c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"},
|
|
||||||
SumTestCase{SHA2_256, 16, "foo", "12102c26b46b68ffc68ff99b453c1d304134"},
|
|
||||||
SumTestCase{SHA2_512, -1, "foo", "1340f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc6638326e282c41be5e4254d8820772c5518a2c5a8c0c7f7eda19594a7eb539453e1ed7"},
|
|
||||||
SumTestCase{SHA2_512, 32, "foo", "1320f7fbba6e0636f890e56fbbf3283e524c6fa3204ae298382d624741d0dc663832"},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSum(t *testing.T) {
|
|
||||||
|
|
||||||
for _, tc := range sumTestCases {
|
|
||||||
|
|
||||||
m1, err := FromHexString(tc.hex)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
m2, err := Sum([]byte(tc.input), tc.code, tc.length)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(tc.code, "sum failed.", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(m1, m2) {
|
|
||||||
t.Error(tc.code, "sum failed.", m1, m2)
|
|
||||||
}
|
|
||||||
|
|
||||||
s1 := m1.HexString()
|
|
||||||
if s1 != tc.hex {
|
|
||||||
t.Error("hex strings not the same")
|
|
||||||
}
|
|
||||||
|
|
||||||
s2 := m1.B58String()
|
|
||||||
m3, err := FromB58String(s2)
|
|
||||||
if err != nil {
|
|
||||||
t.Error("failed to decode b58")
|
|
||||||
} else if !bytes.Equal(m3, m1) {
|
|
||||||
t.Error("b58 failing bytes")
|
|
||||||
} else if s2 != m3.B58String() {
|
|
||||||
t.Error("b58 failing string")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkSum(b *testing.B) {
|
|
||||||
tc := sumTestCases[0]
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
Sum([]byte(tc.input), tc.code, tc.length)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1
Godeps/_workspace/src/github.com/jbenet/go-multihash/test/.gitignore
generated
vendored
1
Godeps/_workspace/src/github.com/jbenet/go-multihash/test/.gitignore
generated
vendored
@ -1 +0,0 @@
|
|||||||
bin/multihash
|
|
||||||
25
Godeps/_workspace/src/github.com/jbenet/go-multihash/test/Makefile
generated
vendored
25
Godeps/_workspace/src/github.com/jbenet/go-multihash/test/Makefile
generated
vendored
@ -1,25 +0,0 @@
|
|||||||
BINS = bin/multihash
|
|
||||||
MULTIHASH_ROOT = ../
|
|
||||||
MULTIHASH_CMD = ../multihash
|
|
||||||
|
|
||||||
all: deps
|
|
||||||
|
|
||||||
deps: bins
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm $(BINS)
|
|
||||||
|
|
||||||
bins: $(BINS)
|
|
||||||
|
|
||||||
bin/multihash: $(MULTIHASH_ROOT)/**/*.go
|
|
||||||
go build -o bin/multihash $(MULTIHASH_CMD)
|
|
||||||
|
|
||||||
test: test_expensive
|
|
||||||
|
|
||||||
test_expensive:
|
|
||||||
cd sharness && make TEST_EXPENSIVE=1
|
|
||||||
|
|
||||||
test_cheap:
|
|
||||||
cd sharness && make
|
|
||||||
|
|
||||||
.PHONY: all clean
|
|
||||||
3
Godeps/_workspace/src/github.com/jbenet/go-multihash/test/sharness/.gitignore
generated
vendored
3
Godeps/_workspace/src/github.com/jbenet/go-multihash/test/sharness/.gitignore
generated
vendored
@ -1,3 +0,0 @@
|
|||||||
lib/sharness/
|
|
||||||
test-results/
|
|
||||||
trash directory.*.sh/
|
|
||||||
37
Godeps/_workspace/src/github.com/jbenet/go-multihash/test/sharness/Makefile
generated
vendored
37
Godeps/_workspace/src/github.com/jbenet/go-multihash/test/sharness/Makefile
generated
vendored
@ -1,37 +0,0 @@
|
|||||||
# Run tests
|
|
||||||
#
|
|
||||||
# Copyright (c) 2014 Christian Couder
|
|
||||||
# MIT Licensed; see the LICENSE file in this repository.
|
|
||||||
#
|
|
||||||
|
|
||||||
# NOTE: run with TEST_VERBOSE=1 for verbose sharness tests.
|
|
||||||
|
|
||||||
T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
|
|
||||||
BINS = bin/multihash
|
|
||||||
SHARNESS = lib/sharness/sharness.sh
|
|
||||||
|
|
||||||
all: clean deps $(T) aggregate
|
|
||||||
|
|
||||||
clean:
|
|
||||||
@echo "*** $@ ***"
|
|
||||||
-rm -rf test-results
|
|
||||||
|
|
||||||
$(T):
|
|
||||||
@echo "*** $@ ***"
|
|
||||||
./$@
|
|
||||||
|
|
||||||
aggregate:
|
|
||||||
@echo "*** $@ ***"
|
|
||||||
lib/test-aggregate-results.sh
|
|
||||||
|
|
||||||
deps: $(SHARNESS) $(BINS)
|
|
||||||
|
|
||||||
$(SHARNESS):
|
|
||||||
@echo "*** installing $@ ***"
|
|
||||||
lib/install-sharness.sh
|
|
||||||
|
|
||||||
bin/%:
|
|
||||||
@echo "*** installing $@ ***"
|
|
||||||
cd .. && make $@
|
|
||||||
|
|
||||||
.PHONY: all clean $(T) aggregate
|
|
||||||
1
Godeps/_workspace/src/github.com/jbenet/go-multihash/test/sharness/bin
generated
vendored
1
Godeps/_workspace/src/github.com/jbenet/go-multihash/test/sharness/bin
generated
vendored
@ -1 +0,0 @@
|
|||||||
../bin
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# install sharness.sh
|
|
||||||
#
|
|
||||||
# Copyright (c) 2014 Juan Batiz-Benet
|
|
||||||
# MIT Licensed; see the LICENSE file in this repository.
|
|
||||||
#
|
|
||||||
|
|
||||||
# settings
|
|
||||||
version=50229a79ba22b2f13ccd82451d86570fecbd194c
|
|
||||||
urlprefix=https://github.com/mlafeldt/sharness.git
|
|
||||||
clonedir=lib
|
|
||||||
sharnessdir=sharness
|
|
||||||
|
|
||||||
die() {
|
|
||||||
echo >&2 "$@"
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
mkdir -p "$clonedir" || die "Could not create '$clonedir' directory"
|
|
||||||
cd "$clonedir" || die "Could not cd into '$clonedir' directory"
|
|
||||||
|
|
||||||
git clone "$urlprefix" || die "Could not clone '$urlprefix'"
|
|
||||||
cd "$sharnessdir" || die "Could not cd into '$sharnessdir' directory"
|
|
||||||
git checkout "$version" || die "Could not checkout '$version'"
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user