├── .gitignore ├── Dockerfile ├── GeoIP.dat ├── Godeps ├── Godeps.json ├── Readme └── _workspace │ ├── .gitignore │ └── src │ ├── github.com │ ├── oschwald │ │ └── maxminddb-golang │ │ │ ├── .gitmodules │ │ │ ├── .travis.yml │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── appveyor.yml │ │ │ ├── decoder.go │ │ │ ├── decoder_test.go │ │ │ ├── example_test.go │ │ │ ├── key_appengine.go │ │ │ ├── key_other.go │ │ │ ├── mmap_unix.go │ │ │ ├── mmap_windows.go │ │ │ ├── reader.go │ │ │ ├── reader_appengine.go │ │ │ ├── reader_other.go │ │ │ ├── reader_test.go │ │ │ ├── traverse.go │ │ │ ├── traverse_test.go │ │ │ ├── verifier.go │ │ │ └── verifier_test.go │ └── vikstrous │ │ └── gotox │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── README.md │ │ ├── breaking_ideas.md │ │ ├── circle.yml │ │ ├── constants.go │ │ ├── dht │ │ ├── constants.go │ │ ├── dht.go_not │ │ ├── dht_integration_test.go_not │ │ ├── identity.go │ │ ├── local_transport.go │ │ ├── protocol.go │ │ ├── protocol_test.go │ │ ├── transport.go │ │ ├── transport_test.go │ │ └── util.go │ │ ├── qtox.pcapng │ │ ├── test.sh │ │ ├── tox.go │ │ ├── tox_test.go │ │ └── utils │ │ └── dhttest │ │ └── dhttest.go_not │ └── golang.org │ └── x │ ├── crypto │ ├── curve25519 │ │ ├── const_amd64.s │ │ ├── cswap_amd64.s │ │ ├── curve25519.go │ │ ├── curve25519_test.go │ │ ├── doc.go │ │ ├── freeze_amd64.s │ │ ├── ladderstep_amd64.s │ │ ├── mont25519_amd64.go │ │ ├── mul_amd64.s │ │ └── square_amd64.s │ ├── nacl │ │ ├── box │ │ │ ├── box.go │ │ │ └── box_test.go │ │ └── secretbox │ │ │ ├── secretbox.go │ │ │ └── secretbox_test.go │ ├── poly1305 │ │ ├── const_amd64.s │ │ ├── poly1305.go │ │ ├── poly1305_amd64.s │ │ ├── poly1305_arm.s │ │ ├── poly1305_test.go │ │ ├── sum_amd64.go │ │ ├── sum_arm.go │ │ └── sum_ref.go │ └── salsa20 │ │ └── salsa │ │ ├── hsalsa20.go │ │ ├── salsa2020_amd64.s │ │ ├── salsa208.go │ │ ├── salsa20_amd64.go │ │ ├── salsa20_ref.go │ │ └── salsa_test.go │ └── net │ └── websocket │ ├── client.go │ ├── exampledial_test.go │ ├── examplehandler_test.go │ ├── hybi.go │ ├── hybi_test.go │ ├── server.go │ ├── websocket.go │ └── websocket_test.go ├── LICENSE ├── Makefile ├── README.md ├── crawler └── crawler.go ├── data └── .gitkeep ├── main ├── crawl │ └── crawl.go └── server │ └── main.go ├── screenshot.png ├── screenshot2.png └── server ├── index.html ├── lib ├── d3.min.js ├── jquery-2.1.4.min.js └── topojson.v1.min.js ├── main.css ├── main.js └── old.js /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | data/ 3 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.5.1 2 | 3 | WORKDIR /go/src/github.com/vikstrous/tox-crawler 4 | ADD . /go/src/github.com/vikstrous/tox-crawler 5 | RUN GOPATH=/go/src/github.com/vikstrous/tox-crawler/Godeps/_workspace:/go go install ./... 6 | 7 | CMD ["server"] 8 | -------------------------------------------------------------------------------- /GeoIP.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vikstrous/tox-crawler/6ee847d4bf250060a43c5241127e90dfd5914659/GeoIP.dat -------------------------------------------------------------------------------- /Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "github.com/vikstrous/tox-crawler", 3 | "GoVersion": "go1.5.1", 4 | "Packages": [ 5 | "./..." 6 | ], 7 | "Deps": [ 8 | { 9 | "ImportPath": "github.com/oschwald/maxminddb-golang", 10 | "Comment": "v0.2.0-36-gb4a9635", 11 | "Rev": "b4a963502ba01ab44940ee21d5539bd65c726924" 12 | }, 13 | { 14 | "ImportPath": "github.com/vikstrous/gotox", 15 | "Rev": "54885321a1eb7dc319e013898a8245f92ee556cb" 16 | }, 17 | { 18 | "ImportPath": "golang.org/x/crypto/curve25519", 19 | "Rev": "aedad9a179ec1ea11b7064c57cbc6dc30d7724ec" 20 | }, 21 | { 22 | "ImportPath": "golang.org/x/crypto/nacl/box", 23 | "Rev": "aedad9a179ec1ea11b7064c57cbc6dc30d7724ec" 24 | }, 25 | { 26 | "ImportPath": "golang.org/x/crypto/nacl/secretbox", 27 | "Rev": "aedad9a179ec1ea11b7064c57cbc6dc30d7724ec" 28 | }, 29 | { 30 | "ImportPath": "golang.org/x/crypto/poly1305", 31 | "Rev": "aedad9a179ec1ea11b7064c57cbc6dc30d7724ec" 32 | }, 33 | { 34 | "ImportPath": "golang.org/x/crypto/salsa20/salsa", 35 | "Rev": "aedad9a179ec1ea11b7064c57cbc6dc30d7724ec" 36 | }, 37 | { 38 | "ImportPath": "golang.org/x/net/websocket", 39 | "Rev": "d8f3c68ddd4bb686ca3bd70e49bbc64b80c78144" 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /Godeps/Readme: -------------------------------------------------------------------------------- 1 | This directory tree is generated automatically by godep. 2 | 3 | Please do not edit. 4 | 5 | See https://github.com/tools/godep for more information. 6 | -------------------------------------------------------------------------------- /Godeps/_workspace/.gitignore: -------------------------------------------------------------------------------- 1 | /pkg 2 | /bin 3 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "test-data"] 2 | path = test-data 3 | url = git://github.com/maxmind/MaxMind-DB.git 4 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.1 5 | - 1.2 6 | - 1.3 7 | - 1.4 8 | - 1.5 9 | - release 10 | - tip 11 | 12 | install: 13 | - go get gopkg.in/check.v1 14 | 15 | script: 16 | - go test 17 | - go test -tags appengine 18 | 19 | sudo: false 20 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Gregory J. Oschwald 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 8 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 9 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 10 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 11 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 12 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 13 | PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/README.md: -------------------------------------------------------------------------------- 1 | # MaxMind DB Reader for Go # 2 | 3 | [![Build Status](https://travis-ci.org/oschwald/maxminddb-golang.png?branch=master)](https://travis-ci.org/oschwald/maxminddb-golang) 4 | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/4j2f9oep8nnfrmov/branch/master?svg=true)](https://ci.appveyor.com/project/oschwald/maxminddb-golang/branch/master) 5 | [![GoDoc](https://godoc.org/github.com/oschwald/maxminddb-golang?status.png)](https://godoc.org/github.com/oschwald/maxminddb-golang) 6 | 7 | 8 | This is a Go reader for the MaxMind DB format. This can be used to read 9 | [GeoLite2](http://dev.maxmind.com/geoip/geoip2/geolite2/) and 10 | [GeoIP2](http://www.maxmind.com/en/geolocation_landing) databases. 11 | 12 | This is not an official MaxMind API. 13 | 14 | ## Installation ## 15 | 16 | ``` 17 | go get github.com/oschwald/maxminddb-golang 18 | ``` 19 | 20 | ## Usage ## 21 | 22 | [See GoDoc](http://godoc.org/github.com/oschwald/maxminddb-golang) for 23 | documentation and examples. 24 | 25 | ## Examples ## 26 | 27 | See [GoDoc](http://godoc.org/github.com/oschwald/maxminddb-golang) or 28 | `example_test.go` for examples. 29 | 30 | ## Contributing ## 31 | 32 | Contributions welcome! Please fork the repository and open a pull request 33 | with your changes. 34 | 35 | ## License ## 36 | 37 | This is free software, licensed under the ISC License. 38 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | 3 | os: Windows Server 2012 R2 4 | 5 | clone_folder: c:\gopath\src\github.com\oschwald\maxminddb-golang 6 | 7 | environment: 8 | GOPATH: c:\gopath 9 | 10 | install: 11 | - echo %PATH% 12 | - echo %GOPATH% 13 | - git submodule update --init --recursive 14 | - go version 15 | - go env 16 | - go get -v -t ./... 17 | 18 | build_script: 19 | - go test -v ./... 20 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/decoder_test.go: -------------------------------------------------------------------------------- 1 | package maxminddb 2 | 3 | import ( 4 | "encoding/hex" 5 | "io/ioutil" 6 | "math/big" 7 | "reflect" 8 | "strings" 9 | "testing" 10 | ) 11 | 12 | func TestBool(t *testing.T) { 13 | bools := map[string]interface{}{ 14 | "0007": false, 15 | "0107": true, 16 | } 17 | 18 | validateDecoding(t, bools) 19 | } 20 | 21 | func TestDouble(t *testing.T) { 22 | doubles := map[string]interface{}{ 23 | "680000000000000000": 0.0, 24 | "683FE0000000000000": 0.5, 25 | "68400921FB54442EEA": 3.14159265359, 26 | "68405EC00000000000": 123.0, 27 | "6841D000000007F8F4": 1073741824.12457, 28 | "68BFE0000000000000": -0.5, 29 | "68C00921FB54442EEA": -3.14159265359, 30 | "68C1D000000007F8F4": -1073741824.12457, 31 | } 32 | validateDecoding(t, doubles) 33 | } 34 | 35 | func TestFloat(t *testing.T) { 36 | floats := map[string]interface{}{ 37 | "040800000000": float32(0.0), 38 | "04083F800000": float32(1.0), 39 | "04083F8CCCCD": float32(1.1), 40 | "04084048F5C3": float32(3.14), 41 | "0408461C3FF6": float32(9999.99), 42 | "0408BF800000": float32(-1.0), 43 | "0408BF8CCCCD": float32(-1.1), 44 | "0408C048F5C3": -float32(3.14), 45 | "0408C61C3FF6": float32(-9999.99), 46 | } 47 | validateDecoding(t, floats) 48 | } 49 | 50 | func TestInt32(t *testing.T) { 51 | int32 := map[string]interface{}{ 52 | "0001": 0, 53 | "0401ffffffff": -1, 54 | "0101ff": 255, 55 | "0401ffffff01": -255, 56 | "020101f4": 500, 57 | "0401fffffe0c": -500, 58 | "0201ffff": 65535, 59 | "0401ffff0001": -65535, 60 | "0301ffffff": 16777215, 61 | "0401ff000001": -16777215, 62 | "04017fffffff": 2147483647, 63 | "040180000001": -2147483647, 64 | } 65 | validateDecoding(t, int32) 66 | } 67 | 68 | func TestMap(t *testing.T) { 69 | maps := map[string]interface{}{ 70 | "e0": map[string]interface{}{}, 71 | "e142656e43466f6f": map[string]interface{}{"en": "Foo"}, 72 | "e242656e43466f6f427a6843e4baba": map[string]interface{}{"en": "Foo", "zh": "人"}, 73 | "e1446e616d65e242656e43466f6f427a6843e4baba": map[string]interface{}{"name": map[string]interface{}{"en": "Foo", "zh": "人"}}, 74 | "e1496c616e677561676573020442656e427a68": map[string]interface{}{"languages": []interface{}{"en", "zh"}}, 75 | } 76 | validateDecoding(t, maps) 77 | } 78 | 79 | func TestSlice(t *testing.T) { 80 | slice := map[string]interface{}{ 81 | "0004": []interface{}{}, 82 | "010443466f6f": []interface{}{"Foo"}, 83 | "020443466f6f43e4baba": []interface{}{"Foo", "人"}, 84 | } 85 | validateDecoding(t, slice) 86 | } 87 | 88 | var testStrings = makeTestStrings() 89 | 90 | func makeTestStrings() map[string]interface{} { 91 | str := map[string]interface{}{ 92 | "40": "", 93 | "4131": "1", 94 | "43E4BABA": "人", 95 | "5b313233343536373839303132333435363738393031323334353637": "123456789012345678901234567", 96 | "5c31323334353637383930313233343536373839303132333435363738": "1234567890123456789012345678", 97 | "5d003132333435363738393031323334353637383930313233343536373839": "12345678901234567890123456789", 98 | "5d01313233343536373839303132333435363738393031323334353637383930": "123456789012345678901234567890", 99 | } 100 | 101 | for k, v := range map[string]int{"5e00d7": 500, "5e06b3": 2000, "5f001053": 70000} { 102 | key := k + strings.Repeat("78", v) 103 | str[key] = strings.Repeat("x", v) 104 | } 105 | 106 | return str 107 | } 108 | 109 | func TestString(t *testing.T) { 110 | validateDecoding(t, testStrings) 111 | } 112 | 113 | func TestByte(t *testing.T) { 114 | b := make(map[string]interface{}) 115 | for key, val := range testStrings { 116 | oldCtrl, _ := hex.DecodeString(key[0:2]) 117 | newCtrl := []byte{oldCtrl[0] ^ 0xc0} 118 | key = strings.Replace(key, hex.EncodeToString(oldCtrl), hex.EncodeToString(newCtrl), 1) 119 | b[key] = []byte(val.(string)) 120 | } 121 | 122 | validateDecoding(t, b) 123 | } 124 | 125 | func TestUint16(t *testing.T) { 126 | uint16 := map[string]interface{}{ 127 | "a0": uint64(0), 128 | "a1ff": uint64(255), 129 | "a201f4": uint64(500), 130 | "a22a78": uint64(10872), 131 | "a2ffff": uint64(65535), 132 | } 133 | validateDecoding(t, uint16) 134 | } 135 | 136 | func TestUint32(t *testing.T) { 137 | uint32 := map[string]interface{}{ 138 | "c0": uint64(0), 139 | "c1ff": uint64(255), 140 | "c201f4": uint64(500), 141 | "c22a78": uint64(10872), 142 | "c2ffff": uint64(65535), 143 | "c3ffffff": uint64(16777215), 144 | "c4ffffffff": uint64(4294967295), 145 | } 146 | validateDecoding(t, uint32) 147 | } 148 | 149 | func TestUint64(t *testing.T) { 150 | ctrlByte := "02" 151 | bits := uint64(64) 152 | 153 | uints := map[string]interface{}{ 154 | "00" + ctrlByte: uint64(0), 155 | "02" + ctrlByte + "01f4": uint64(500), 156 | "02" + ctrlByte + "2a78": uint64(10872), 157 | } 158 | for i := uint64(0); i <= bits/8; i++ { 159 | expected := uint64((1 << (8 * i)) - 1) 160 | 161 | input := hex.EncodeToString([]byte{byte(i)}) + ctrlByte + strings.Repeat("ff", int(i)) 162 | uints[input] = expected 163 | } 164 | 165 | validateDecoding(t, uints) 166 | } 167 | 168 | // Dedup with above somehow 169 | func TestUint128(t *testing.T) { 170 | ctrlByte := "03" 171 | bits := uint(128) 172 | 173 | uints := map[string]interface{}{ 174 | "00" + ctrlByte: big.NewInt(0), 175 | "02" + ctrlByte + "01f4": big.NewInt(500), 176 | "02" + ctrlByte + "2a78": big.NewInt(10872), 177 | } 178 | for i := uint(1); i <= bits/8; i++ { 179 | expected := powBigInt(big.NewInt(2), 8*i) 180 | expected = expected.Sub(expected, big.NewInt(1)) 181 | input := hex.EncodeToString([]byte{byte(i)}) + ctrlByte + strings.Repeat("ff", int(i)) 182 | 183 | uints[input] = expected 184 | } 185 | 186 | validateDecoding(t, uints) 187 | } 188 | 189 | // No pow or bit shifting for big int, apparently :-( 190 | // This is _not_ meant to be a comprehensive power function 191 | func powBigInt(bi *big.Int, pow uint) *big.Int { 192 | newInt := big.NewInt(1) 193 | for i := uint(0); i < pow; i++ { 194 | newInt.Mul(newInt, bi) 195 | } 196 | return newInt 197 | } 198 | 199 | func validateDecoding(t *testing.T, tests map[string]interface{}) { 200 | for inputStr, expected := range tests { 201 | inputBytes, _ := hex.DecodeString(inputStr) 202 | d := decoder{inputBytes} 203 | 204 | var result interface{} 205 | _, err := d.decode(0, reflect.ValueOf(&result)) 206 | if err != nil { 207 | t.Error(err) 208 | } 209 | if !reflect.DeepEqual(result, expected) { 210 | // A big case statement would produce nicer errors 211 | t.Errorf("Output was incorrect: %s %s", inputStr, expected) 212 | } 213 | } 214 | } 215 | 216 | func TestPointers(t *testing.T) { 217 | bytes, err := ioutil.ReadFile("test-data/test-data/maps-with-pointers.raw") 218 | if err != nil { 219 | t.Error(err) 220 | } 221 | d := decoder{bytes} 222 | 223 | expected := map[uint]map[string]string{ 224 | 0: {"long_key": "long_value1"}, 225 | 22: {"long_key": "long_value2"}, 226 | 37: {"long_key2": "long_value1"}, 227 | 50: {"long_key2": "long_value2"}, 228 | 55: {"long_key": "long_value1"}, 229 | 57: {"long_key2": "long_value2"}, 230 | } 231 | 232 | for offset, expectedValue := range expected { 233 | var actual map[string]string 234 | _, err := d.decode(offset, reflect.ValueOf(&actual)) 235 | if err != nil { 236 | t.Error(err) 237 | } 238 | if !reflect.DeepEqual(actual, expectedValue) { 239 | t.Errorf("Decode for pointer at %d failed", offset) 240 | } 241 | } 242 | 243 | } 244 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/example_test.go: -------------------------------------------------------------------------------- 1 | package maxminddb_test 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net" 7 | 8 | "github.com/oschwald/maxminddb-golang" 9 | ) 10 | 11 | type onlyCountry struct { 12 | Country struct { 13 | ISOCode string `maxminddb:"iso_code"` 14 | } `maxminddb:"country"` 15 | } 16 | 17 | // This example shows how to decode to a struct 18 | func ExampleReader_Lookup_struct() { 19 | db, err := maxminddb.Open("test-data/test-data/GeoIP2-City-Test.mmdb") 20 | if err != nil { 21 | log.Fatal(err) 22 | } 23 | defer db.Close() 24 | 25 | ip := net.ParseIP("81.2.69.142") 26 | 27 | var record onlyCountry // Or any appropriate struct 28 | err = db.Lookup(ip, &record) 29 | if err != nil { 30 | log.Fatal(err) 31 | } 32 | fmt.Print(record.Country.ISOCode) 33 | // Output: 34 | // GB 35 | } 36 | 37 | // This example demonstrates how to decode to an interface{} 38 | func ExampleReader_Lookup_interface() { 39 | db, err := maxminddb.Open("test-data/test-data/GeoIP2-City-Test.mmdb") 40 | if err != nil { 41 | log.Fatal(err) 42 | } 43 | defer db.Close() 44 | 45 | ip := net.ParseIP("81.2.69.142") 46 | 47 | var record interface{} 48 | err = db.Lookup(ip, &record) 49 | if err != nil { 50 | log.Fatal(err) 51 | } 52 | fmt.Printf("%v", record) 53 | } 54 | 55 | // This example demonstrates how to iterate over all networks in the 56 | // database 57 | func ExampleReader_Networks() { 58 | db, err := maxminddb.Open("test-data/test-data/GeoIP2-Connection-Type-Test.mmdb") 59 | if err != nil { 60 | log.Fatal(err) 61 | } 62 | defer db.Close() 63 | 64 | record := struct { 65 | Domain string `maxminddb:"connection_type"` 66 | }{} 67 | 68 | networks := db.Networks() 69 | for networks.Next() { 70 | subnet, err := networks.Network(&record) 71 | if err != nil { 72 | log.Fatal(err) 73 | } 74 | fmt.Printf("%s: %s\n", subnet.String(), record.Domain) 75 | } 76 | if networks.Err() != nil { 77 | log.Fatal(networks.Err()) 78 | } 79 | // Output: 80 | // ::100:0/120: Dialup 81 | // ::100:100/120: Cable/DSL 82 | // ::100:200/119: Dialup 83 | // ::100:400/118: Dialup 84 | // ::100:800/117: Dialup 85 | // ::100:1000/116: Dialup 86 | // ::100:2000/115: Dialup 87 | // ::100:4000/114: Dialup 88 | // ::100:8000/113: Dialup 89 | // ::50d6:0/116: Cellular 90 | // ::6001:0/112: Cable/DSL 91 | // ::600a:0/111: Cable/DSL 92 | // ::6045:0/112: Cable/DSL 93 | // ::605e:0/111: Cable/DSL 94 | // ::6c60:0/107: Cellular 95 | // ::af10:c700/120: Dialup 96 | // ::bb9c:8a00/120: Cable/DSL 97 | // ::c9f3:c800/120: Corporate 98 | // ::cfb3:3000/116: Cellular 99 | // 1.0.0.0/24: Dialup 100 | // 1.0.1.0/24: Cable/DSL 101 | // 1.0.2.0/23: Dialup 102 | // 1.0.4.0/22: Dialup 103 | // 1.0.8.0/21: Dialup 104 | // 1.0.16.0/20: Dialup 105 | // 1.0.32.0/19: Dialup 106 | // 1.0.64.0/18: Dialup 107 | // 1.0.128.0/17: Dialup 108 | // 80.214.0.0/20: Cellular 109 | // 96.1.0.0/16: Cable/DSL 110 | // 96.10.0.0/15: Cable/DSL 111 | // 96.69.0.0/16: Cable/DSL 112 | // 96.94.0.0/15: Cable/DSL 113 | // 108.96.0.0/11: Cellular 114 | // 175.16.199.0/24: Dialup 115 | // 187.156.138.0/24: Cable/DSL 116 | // 201.243.200.0/24: Corporate 117 | // 207.179.48.0/20: Cellular 118 | // 2001:0:100::/56: Dialup 119 | // 2001:0:100:100::/56: Cable/DSL 120 | // 2001:0:100:200::/55: Dialup 121 | // 2001:0:100:400::/54: Dialup 122 | // 2001:0:100:800::/53: Dialup 123 | // 2001:0:100:1000::/52: Dialup 124 | // 2001:0:100:2000::/51: Dialup 125 | // 2001:0:100:4000::/50: Dialup 126 | // 2001:0:100:8000::/49: Dialup 127 | // 2001:0:50d6::/52: Cellular 128 | // 2001:0:6001::/48: Cable/DSL 129 | // 2001:0:600a::/47: Cable/DSL 130 | // 2001:0:6045::/48: Cable/DSL 131 | // 2001:0:605e::/47: Cable/DSL 132 | // 2001:0:6c60::/43: Cellular 133 | // 2001:0:af10:c700::/56: Dialup 134 | // 2001:0:bb9c:8a00::/56: Cable/DSL 135 | // 2001:0:c9f3:c800::/56: Corporate 136 | // 2001:0:cfb3:3000::/52: Cellular 137 | // 2002:100::/40: Dialup 138 | // 2002:100:100::/40: Cable/DSL 139 | // 2002:100:200::/39: Dialup 140 | // 2002:100:400::/38: Dialup 141 | // 2002:100:800::/37: Dialup 142 | // 2002:100:1000::/36: Dialup 143 | // 2002:100:2000::/35: Dialup 144 | // 2002:100:4000::/34: Dialup 145 | // 2002:100:8000::/33: Dialup 146 | // 2002:50d6::/36: Cellular 147 | // 2002:6001::/32: Cable/DSL 148 | // 2002:600a::/31: Cable/DSL 149 | // 2002:6045::/32: Cable/DSL 150 | // 2002:605e::/31: Cable/DSL 151 | // 2002:6c60::/27: Cellular 152 | // 2002:af10:c700::/40: Dialup 153 | // 2002:bb9c:8a00::/40: Cable/DSL 154 | // 2002:c9f3:c800::/40: Corporate 155 | // 2002:cfb3:3000::/36: Cellular 156 | // 2003::/24: Cable/DSL 157 | 158 | } 159 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/key_appengine.go: -------------------------------------------------------------------------------- 1 | // +build appengine 2 | 3 | package maxminddb 4 | 5 | func (d *decoder) decodeStructKey(offset uint) (string, uint, error) { 6 | return d.decodeKeyString(offset) 7 | } 8 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/key_other.go: -------------------------------------------------------------------------------- 1 | // +build !appengine 2 | 3 | package maxminddb 4 | 5 | import ( 6 | "fmt" 7 | "reflect" 8 | "unsafe" 9 | ) 10 | 11 | // decodeStructKey returns a string which points into the database. Don't keep 12 | // it around. 13 | func (d *decoder) decodeStructKey(offset uint) (string, uint, error) { 14 | typeNum, size, newOffset := d.decodeCtrlData(offset) 15 | switch typeNum { 16 | case _Pointer: 17 | pointer, ptrOffset := d.decodePointer(size, newOffset) 18 | s, _, err := d.decodeStructKey(pointer) 19 | return s, ptrOffset, err 20 | case _String: 21 | var s string 22 | val := (*reflect.StringHeader)(unsafe.Pointer(&s)) 23 | val.Data = uintptr(unsafe.Pointer(&d.buffer[newOffset])) 24 | val.Len = int(size) 25 | return s, newOffset + size, nil 26 | default: 27 | return "", 0, fmt.Errorf("unexpected type when decoding structkey: %v", typeNum) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/mmap_unix.go: -------------------------------------------------------------------------------- 1 | // +build !windows,!appengine 2 | 3 | package maxminddb 4 | 5 | import ( 6 | "syscall" 7 | ) 8 | 9 | func mmap(fd int, length int) (data []byte, err error) { 10 | return syscall.Mmap(fd, 0, length, syscall.PROT_READ, syscall.MAP_SHARED) 11 | } 12 | 13 | func munmap(b []byte) (err error) { 14 | return syscall.Munmap(b) 15 | } 16 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/mmap_windows.go: -------------------------------------------------------------------------------- 1 | package maxminddb 2 | 3 | // Windows support largely borrowed from mmap-go. 4 | // 5 | // Copyright 2011 Evan Shaw. All rights reserved. 6 | // Use of this source code is governed by a BSD-style 7 | // license that can be found in the LICENSE file. 8 | 9 | import ( 10 | "errors" 11 | "os" 12 | "reflect" 13 | "sync" 14 | "syscall" 15 | "unsafe" 16 | ) 17 | 18 | type memoryMap []byte 19 | 20 | // Windows 21 | var handleLock sync.Mutex 22 | var handleMap = map[uintptr]syscall.Handle{} 23 | 24 | func mmap(fd int, length int) (data []byte, err error) { 25 | h, errno := syscall.CreateFileMapping(syscall.Handle(fd), nil, 26 | uint32(syscall.PAGE_READONLY), 0, uint32(length), nil) 27 | if h == 0 { 28 | return nil, os.NewSyscallError("CreateFileMapping", errno) 29 | } 30 | 31 | addr, errno := syscall.MapViewOfFile(h, uint32(syscall.FILE_MAP_READ), 0, 32 | 0, uintptr(length)) 33 | if addr == 0 { 34 | return nil, os.NewSyscallError("MapViewOfFile", errno) 35 | } 36 | handleLock.Lock() 37 | handleMap[addr] = h 38 | handleLock.Unlock() 39 | 40 | m := memoryMap{} 41 | dh := m.header() 42 | dh.Data = addr 43 | dh.Len = length 44 | dh.Cap = dh.Len 45 | 46 | return m, nil 47 | } 48 | 49 | func (m *memoryMap) header() *reflect.SliceHeader { 50 | return (*reflect.SliceHeader)(unsafe.Pointer(m)) 51 | } 52 | 53 | func flush(addr, len uintptr) error { 54 | errno := syscall.FlushViewOfFile(addr, len) 55 | return os.NewSyscallError("FlushViewOfFile", errno) 56 | } 57 | 58 | func munmap(b []byte) (err error) { 59 | m := memoryMap(b) 60 | dh := m.header() 61 | 62 | addr := dh.Data 63 | length := uintptr(dh.Len) 64 | 65 | flush(addr, length) 66 | err = syscall.UnmapViewOfFile(addr) 67 | if err != nil { 68 | return err 69 | } 70 | 71 | handleLock.Lock() 72 | defer handleLock.Unlock() 73 | handle, ok := handleMap[addr] 74 | if !ok { 75 | // should be impossible; we would've errored above 76 | return errors.New("unknown base address") 77 | } 78 | delete(handleMap, addr) 79 | 80 | e := syscall.CloseHandle(syscall.Handle(handle)) 81 | return os.NewSyscallError("CloseHandle", e) 82 | } 83 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/reader.go: -------------------------------------------------------------------------------- 1 | package maxminddb 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "fmt" 7 | "net" 8 | "reflect" 9 | ) 10 | 11 | const dataSectionSeparatorSize = 16 12 | 13 | var metadataStartMarker = []byte("\xAB\xCD\xEFMaxMind.com") 14 | 15 | // Reader holds the data corresponding to the MaxMind DB file. Its only public 16 | // field is Metadata, which contains the metadata from the MaxMind DB file. 17 | type Reader struct { 18 | hasMappedFile bool 19 | buffer []byte 20 | decoder decoder 21 | Metadata Metadata 22 | ipv4Start uint 23 | } 24 | 25 | // Metadata holds the metadata decoded from the MaxMind DB file. In particular 26 | // in has the format version, the build time as Unix epoch time, the database 27 | // type and description, the IP version supported, and a slice of the natural 28 | // languages included. 29 | type Metadata struct { 30 | BinaryFormatMajorVersion uint `maxminddb:"binary_format_major_version"` 31 | BinaryFormatMinorVersion uint `maxminddb:"binary_format_minor_version"` 32 | BuildEpoch uint `maxminddb:"build_epoch"` 33 | DatabaseType string `maxminddb:"database_type"` 34 | Description map[string]string `maxminddb:"description"` 35 | IPVersion uint `maxminddb:"ip_version"` 36 | Languages []string `maxminddb:"languages"` 37 | NodeCount uint `maxminddb:"node_count"` 38 | RecordSize uint `maxminddb:"record_size"` 39 | } 40 | 41 | // FromBytes takes a byte slice corresponding to a MaxMind DB file and returns 42 | // a Reader structure or an error. 43 | func FromBytes(buffer []byte) (*Reader, error) { 44 | metadataStart := bytes.LastIndex(buffer, metadataStartMarker) 45 | 46 | if metadataStart == -1 { 47 | return nil, fmt.Errorf("error opening database file: invalid MaxMind DB file") 48 | } 49 | 50 | metadataStart += len(metadataStartMarker) 51 | metadataDecoder := decoder{buffer[metadataStart:]} 52 | 53 | var metadata Metadata 54 | 55 | rvMetdata := reflect.ValueOf(&metadata) 56 | _, err := metadataDecoder.decode(0, rvMetdata) 57 | if err != nil { 58 | return nil, err 59 | } 60 | 61 | searchTreeSize := metadata.NodeCount * metadata.RecordSize / 4 62 | decoder := decoder{ 63 | buffer[searchTreeSize+dataSectionSeparatorSize : metadataStart-len(metadataStartMarker)], 64 | } 65 | 66 | reader := &Reader{ 67 | buffer: buffer, 68 | decoder: decoder, 69 | Metadata: metadata, 70 | ipv4Start: 0, 71 | } 72 | 73 | reader.ipv4Start, err = reader.startNode() 74 | 75 | return reader, err 76 | } 77 | 78 | func (r *Reader) startNode() (uint, error) { 79 | if r.Metadata.IPVersion != 6 { 80 | return 0, nil 81 | } 82 | 83 | nodeCount := r.Metadata.NodeCount 84 | 85 | node := uint(0) 86 | var err error 87 | for i := 0; i < 96 && node < nodeCount; i++ { 88 | node, err = r.readNode(node, 0) 89 | if err != nil { 90 | return 0, err 91 | } 92 | } 93 | return node, err 94 | } 95 | 96 | // Lookup takes an IP address as a net.IP structure and a pointer to the 97 | // result value to decode into. The result value pointed to must be a data 98 | // value that corresponds to a record in the database. This may include a 99 | // struct representation of the data, a map capable of holding the data or an 100 | // empty interface{} value. 101 | // 102 | // If result is a pointer to a struct, the struct need not include a field 103 | // for every value that may be in the database. If a field is not present in 104 | // the structure, the decoder will not decode that field, reducing the time 105 | // required to decode the record. 106 | // 107 | // Currently the decoder expect most data types to correspond exactly (e.g., 108 | // a uint64 database type must be decoded into a uint64 Go type). In the 109 | // future, this may be made more flexible. 110 | func (r *Reader) Lookup(ipAddress net.IP, result interface{}) error { 111 | if ipAddress == nil { 112 | return errors.New("ipAddress passed to Lookup cannot be nil") 113 | } 114 | 115 | ipV4Address := ipAddress.To4() 116 | if ipV4Address != nil { 117 | ipAddress = ipV4Address 118 | } 119 | if len(ipAddress) == 16 && r.Metadata.IPVersion == 4 { 120 | return fmt.Errorf("error looking up '%s': you attempted to look up an IPv6 address in an IPv4-only database", ipAddress.String()) 121 | } 122 | 123 | pointer, err := r.findAddressInTree(ipAddress) 124 | 125 | if pointer == 0 { 126 | return err 127 | } 128 | 129 | return r.retrieveData(pointer, result) 130 | } 131 | 132 | func (r *Reader) findAddressInTree(ipAddress net.IP) (uint, error) { 133 | 134 | bitCount := uint(len(ipAddress) * 8) 135 | 136 | var node uint 137 | if bitCount == 32 { 138 | node = r.ipv4Start 139 | } 140 | 141 | nodeCount := r.Metadata.NodeCount 142 | 143 | for i := uint(0); i < bitCount && node < nodeCount; i++ { 144 | bit := uint(1) & (uint(ipAddress[i>>3]) >> (7 - (i % 8))) 145 | 146 | var err error 147 | node, err = r.readNode(node, bit) 148 | if err != nil { 149 | return 0, err 150 | } 151 | } 152 | if node == nodeCount { 153 | // Record is empty 154 | return 0, nil 155 | } else if node > nodeCount { 156 | return node, nil 157 | } 158 | 159 | return 0, errors.New("invalid node in search tree") 160 | } 161 | 162 | func (r *Reader) readNode(nodeNumber uint, index uint) (uint, error) { 163 | RecordSize := r.Metadata.RecordSize 164 | 165 | baseOffset := nodeNumber * RecordSize / 4 166 | 167 | var nodeBytes []byte 168 | var prefix uint64 169 | switch RecordSize { 170 | case 24: 171 | offset := baseOffset + index*3 172 | nodeBytes = r.buffer[offset : offset+3] 173 | case 28: 174 | prefix = uint64(r.buffer[baseOffset+3]) 175 | if index != 0 { 176 | prefix &= 0x0F 177 | } else { 178 | prefix = (0xF0 & prefix) >> 4 179 | } 180 | offset := baseOffset + index*4 181 | nodeBytes = r.buffer[offset : offset+3] 182 | case 32: 183 | offset := baseOffset + index*4 184 | nodeBytes = r.buffer[offset : offset+4] 185 | default: 186 | return 0, fmt.Errorf("unknown record size: %d", RecordSize) 187 | } 188 | return uint(uintFromBytes(prefix, nodeBytes)), nil 189 | } 190 | 191 | func (r *Reader) retrieveData(pointer uint, result interface{}) error { 192 | rv := reflect.ValueOf(result) 193 | if rv.Kind() != reflect.Ptr || rv.IsNil() { 194 | return errors.New("result param must be a pointer") 195 | } 196 | 197 | offset, err := r.resolveDataPointer(pointer) 198 | if err != nil { 199 | return err 200 | } 201 | 202 | _, err = r.decoder.decode(offset, rv) 203 | return err 204 | } 205 | 206 | func (r *Reader) resolveDataPointer(pointer uint) (uint, error) { 207 | nodeCount := r.Metadata.NodeCount 208 | 209 | resolved := pointer - nodeCount - dataSectionSeparatorSize 210 | 211 | if resolved > uint(len(r.buffer)) { 212 | return 0, errors.New("the MaxMind DB file's search tree is corrupt") 213 | } 214 | 215 | return resolved, nil 216 | } 217 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/reader_appengine.go: -------------------------------------------------------------------------------- 1 | // +build appengine 2 | 3 | package maxminddb 4 | 5 | import "io/ioutil" 6 | 7 | // Open takes a string path to a MaxMind DB file and returns a Reader 8 | // structure or an error. The database file is opened using a memory map, 9 | // except on Google App Engine where mmap is not supported; there the database 10 | // is loaded into memory. Use the Close method on the Reader object to return 11 | // the resources to the system. 12 | func Open(file string) (*Reader, error) { 13 | bytes, err := ioutil.ReadFile(file) 14 | if err != nil { 15 | return nil, err 16 | } 17 | 18 | return FromBytes(bytes) 19 | } 20 | 21 | // Close unmaps the database file from virtual memory and returns the 22 | // resources to the system. If called on a Reader opened using FromBytes 23 | // or Open on Google App Engine, this method does nothing. 24 | func (r *Reader) Close() error { 25 | return nil 26 | } 27 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/reader_other.go: -------------------------------------------------------------------------------- 1 | // +build !appengine 2 | 3 | package maxminddb 4 | 5 | import "os" 6 | 7 | // Open takes a string path to a MaxMind DB file and returns a Reader 8 | // structure or an error. The database file is opened using a memory map, 9 | // except on Google App Engine where mmap is not supported; there the database 10 | // is loaded into memory. Use the Close method on the Reader object to return 11 | // the resources to the system. 12 | func Open(file string) (*Reader, error) { 13 | mapFile, err := os.Open(file) 14 | if err != nil { 15 | return nil, err 16 | } 17 | defer func() { 18 | if rerr := mapFile.Close(); rerr != nil { 19 | err = rerr 20 | } 21 | }() 22 | 23 | stats, err := mapFile.Stat() 24 | if err != nil { 25 | return nil, err 26 | } 27 | 28 | fileSize := int(stats.Size()) 29 | mmap, err := mmap(int(mapFile.Fd()), fileSize) 30 | if err != nil { 31 | return nil, err 32 | } 33 | 34 | reader, err := FromBytes(mmap) 35 | if err != nil { 36 | if err2 := munmap(mmap); err2 != nil { 37 | // failing to unmap the file is probably the more severe error 38 | return nil, err2 39 | } 40 | return nil, err 41 | } 42 | 43 | reader.hasMappedFile = true 44 | return reader, err 45 | } 46 | 47 | // Close unmaps the database file from virtual memory and returns the 48 | // resources to the system. If called on a Reader opened using FromBytes 49 | // or Open on Google App Engine, this method does nothing. 50 | func (r *Reader) Close() (err error) { 51 | if r.hasMappedFile { 52 | err = munmap(r.buffer) 53 | r.hasMappedFile = false 54 | } 55 | return err 56 | } 57 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/traverse.go: -------------------------------------------------------------------------------- 1 | package maxminddb 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | ) 7 | 8 | // Internal structure used to keep track of nodes we still need to visit. 9 | type netNode struct { 10 | ip net.IP 11 | bit uint 12 | pointer uint 13 | } 14 | 15 | // Networks represents a set of subnets that we are iterating over. 16 | type Networks struct { 17 | reader *Reader 18 | nodes []netNode // Nodes we still have to visit. 19 | lastNode netNode 20 | err error 21 | } 22 | 23 | // Networks returns an iterator that can be used to traverse all networks in 24 | // the database. 25 | // 26 | // Please note that a MaxMind DB may map IPv4 networks into several locations 27 | // in in an IPv6 database. This iterator will iterate over all of these 28 | // locations separately. 29 | func (r *Reader) Networks() *Networks { 30 | s := 4 31 | if r.Metadata.IPVersion == 6 { 32 | s = 16 33 | } 34 | return &Networks{ 35 | reader: r, 36 | nodes: []netNode{ 37 | netNode{ 38 | ip: make(net.IP, s), 39 | }, 40 | }, 41 | } 42 | } 43 | 44 | // Next prepares the next network for reading with the Network method. It 45 | // returns true if there is another network to be processed and false if there 46 | // are no more networks or if there is an error. 47 | func (n *Networks) Next() bool { 48 | for len(n.nodes) > 0 { 49 | node := n.nodes[len(n.nodes)-1] 50 | n.nodes = n.nodes[:len(n.nodes)-1] 51 | 52 | for { 53 | if node.pointer < n.reader.Metadata.NodeCount { 54 | ipRight := make(net.IP, len(node.ip)) 55 | copy(ipRight, node.ip) 56 | if len(ipRight) <= int(node.bit>>3) { 57 | n.err = fmt.Errorf( 58 | "invalid search tree at %v/%v", ipRight, node.bit) 59 | return false 60 | } 61 | ipRight[node.bit>>3] |= 1 << uint(7-(node.bit%8)) 62 | 63 | rightPointer, err := n.reader.readNode(node.pointer, 1) 64 | if err != nil { 65 | n.err = err 66 | return false 67 | } 68 | 69 | node.bit++ 70 | n.nodes = append(n.nodes, netNode{ 71 | pointer: rightPointer, 72 | ip: ipRight, 73 | bit: node.bit, 74 | }) 75 | 76 | node.pointer, err = n.reader.readNode(node.pointer, 0) 77 | if err != nil { 78 | n.err = err 79 | return false 80 | } 81 | 82 | } else if node.pointer > n.reader.Metadata.NodeCount { 83 | n.lastNode = node 84 | return true 85 | } else { 86 | break 87 | } 88 | } 89 | } 90 | 91 | return false 92 | } 93 | 94 | // Network returns the current network or an error if there is a problem 95 | // decoding the data for the network. It takes a pointer to a result value to 96 | // decode the network's data into. 97 | func (n *Networks) Network(result interface{}) (*net.IPNet, error) { 98 | if err := n.reader.retrieveData(n.lastNode.pointer, result); err != nil { 99 | return nil, err 100 | } 101 | 102 | return &net.IPNet{ 103 | IP: n.lastNode.ip, 104 | Mask: net.CIDRMask(int(n.lastNode.bit), len(n.lastNode.ip)*8), 105 | }, nil 106 | } 107 | 108 | // Err returns an error, if any, that was encountered during iteration. 109 | func (n *Networks) Err() error { 110 | return n.err 111 | } 112 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/traverse_test.go: -------------------------------------------------------------------------------- 1 | package maxminddb 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestNetworks(t *testing.T) { 9 | for _, recordSize := range []uint{24, 28, 32} { 10 | for _, ipVersion := range []uint{4, 6} { 11 | fileName := fmt.Sprintf("test-data/test-data/MaxMind-DB-test-ipv%d-%d.mmdb", ipVersion, recordSize) 12 | reader, err := Open(fileName) 13 | if err != nil { 14 | t.Fatalf("unexpected error while opening database: %v", err) 15 | } 16 | defer reader.Close() 17 | 18 | n := reader.Networks() 19 | for n.Next() { 20 | record := struct { 21 | IP string `maxminddb:"ip"` 22 | }{} 23 | network, err := n.Network(&record) 24 | if err != nil { 25 | t.Fatal(err) 26 | } 27 | 28 | if record.IP != network.IP.String() { 29 | t.Fatalf("expected %s got %s", record.IP, network.IP.String()) 30 | } 31 | } 32 | if n.Err() != nil { 33 | t.Fatal(n.Err()) 34 | } 35 | } 36 | } 37 | } 38 | 39 | func TestNetworksWithInvalidSearchTree(t *testing.T) { 40 | reader, err := Open("test-data/test-data/MaxMind-DB-test-broken-search-tree-24.mmdb") 41 | if err != nil { 42 | t.Fatalf("unexpected error while opening database: %v", err) 43 | } 44 | defer reader.Close() 45 | 46 | n := reader.Networks() 47 | for n.Next() { 48 | var record interface{} 49 | _, err := n.Network(&record) 50 | if err != nil { 51 | t.Fatal(err) 52 | } 53 | } 54 | if n.Err() == nil { 55 | t.Fatal("no error received when traversing an broken search tree") 56 | } else if n.Err().Error() != "invalid search tree at 128.128.128.128/32" { 57 | t.Error(n.Err()) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/verifier.go: -------------------------------------------------------------------------------- 1 | package maxminddb 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | type verifier struct { 9 | reader *Reader 10 | } 11 | 12 | // Verify checks that the database is valid. It validates the search tree, 13 | // the data section, and the metadata section. This verifier is stricter than 14 | // the specification and may return errors on databases that are readable. 15 | func (r *Reader) Verify() error { 16 | v := verifier{r} 17 | if err := v.verifyMetadata(); err != nil { 18 | return err 19 | } 20 | 21 | return v.verifyDatabase() 22 | } 23 | 24 | func (v *verifier) verifyMetadata() error { 25 | metadata := v.reader.Metadata 26 | 27 | if metadata.BinaryFormatMajorVersion != 2 { 28 | return testError( 29 | "binary_format_major_version", 30 | 2, 31 | metadata.BinaryFormatMajorVersion, 32 | ) 33 | } 34 | 35 | if metadata.BinaryFormatMinorVersion != 0 { 36 | return testError( 37 | "binary_format_minor_version", 38 | 0, 39 | metadata.BinaryFormatMinorVersion, 40 | ) 41 | } 42 | 43 | if metadata.DatabaseType == "" { 44 | return testError( 45 | "database_type", 46 | "non-empty string", 47 | metadata.DatabaseType, 48 | ) 49 | } 50 | 51 | if len(metadata.Description) == 0 { 52 | return testError( 53 | "description", 54 | "non-empty slice", 55 | metadata.Description, 56 | ) 57 | } 58 | 59 | if metadata.IPVersion != 4 && metadata.IPVersion != 6 { 60 | return testError( 61 | "ip_version", 62 | "4 or 6", 63 | metadata.IPVersion, 64 | ) 65 | } 66 | 67 | if metadata.RecordSize != 24 && 68 | metadata.RecordSize != 28 && 69 | metadata.RecordSize != 32 { 70 | return testError( 71 | "record_size", 72 | "24, 28, or 32", 73 | metadata.RecordSize, 74 | ) 75 | } 76 | 77 | if metadata.NodeCount == 0 { 78 | return testError( 79 | "node_count", 80 | "positive integer", 81 | metadata.NodeCount, 82 | ) 83 | } 84 | return nil 85 | } 86 | 87 | func (v *verifier) verifyDatabase() error { 88 | offsets, err := v.verifySearchTree() 89 | if err != nil { 90 | return err 91 | } 92 | 93 | if err := v.verifyDataSectionSeparator(); err != nil { 94 | return err 95 | } 96 | 97 | return v.verifyDataSection(offsets) 98 | } 99 | 100 | func (v *verifier) verifySearchTree() (map[uint]bool, error) { 101 | offsets := make(map[uint]bool) 102 | 103 | it := v.reader.Networks() 104 | for it.Next() { 105 | offset, err := v.reader.resolveDataPointer(it.lastNode.pointer) 106 | if err != nil { 107 | return nil, err 108 | } 109 | offsets[offset] = true 110 | } 111 | if err := it.Err(); err != nil { 112 | return nil, err 113 | } 114 | return offsets, nil 115 | } 116 | 117 | func (v *verifier) verifyDataSectionSeparator() error { 118 | separatorStart := v.reader.Metadata.NodeCount * v.reader.Metadata.RecordSize / 4 119 | 120 | separator := v.reader.buffer[separatorStart : separatorStart+dataSectionSeparatorSize] 121 | 122 | for _, b := range separator { 123 | if b != 0 { 124 | return fmt.Errorf("unexpected byte in data separator: %v", separator) 125 | } 126 | } 127 | return nil 128 | } 129 | 130 | func (v *verifier) verifyDataSection(offsets map[uint]bool) error { 131 | pointerCount := len(offsets) 132 | 133 | decoder := v.reader.decoder 134 | 135 | var offset uint 136 | bufferLen := uint(len(decoder.buffer)) 137 | for offset < bufferLen { 138 | var data interface{} 139 | rv := reflect.ValueOf(&data) 140 | newOffset, err := decoder.decode(offset, rv) 141 | if err != nil { 142 | return fmt.Errorf("received decoding error (%v) at offset of %v", err, offset) 143 | } 144 | if newOffset <= offset { 145 | return fmt.Errorf("data section offset unexpectedly went from %v to %v", offset, newOffset) 146 | } 147 | 148 | pointer := offset 149 | 150 | if _, ok := offsets[pointer]; ok { 151 | delete(offsets, pointer) 152 | } else { 153 | return fmt.Errorf("found data (%v) at %v that the search tree does not point to", data, pointer) 154 | } 155 | 156 | offset = newOffset 157 | } 158 | 159 | if offset != bufferLen { 160 | return fmt.Errorf( 161 | "unexpected data at the end of the data section (last offset: %v, end: %v)", 162 | offset, 163 | bufferLen, 164 | ) 165 | } 166 | 167 | if len(offsets) != 0 { 168 | return fmt.Errorf( 169 | "found %v pointers (of %v) in the search tree that we did not see in the data section", 170 | len(offsets), 171 | pointerCount, 172 | ) 173 | } 174 | return nil 175 | } 176 | 177 | func testError( 178 | field string, 179 | expected interface{}, 180 | actual interface{}, 181 | ) error { 182 | return fmt.Errorf( 183 | "%v - Expected: %v Actual: %v", 184 | field, 185 | expected, 186 | actual, 187 | ) 188 | } 189 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/oschwald/maxminddb-golang/verifier_test.go: -------------------------------------------------------------------------------- 1 | package maxminddb 2 | 3 | import "testing" 4 | 5 | func TestVerifyOnGoodDatabases(t *testing.T) { 6 | databases := []string{ 7 | "test-data/test-data/GeoIP2-Anonymous-IP-Test.mmdb", 8 | "test-data/test-data/GeoIP2-City-Test.mmdb", 9 | "test-data/test-data/GeoIP2-Connection-Type-Test.mmdb", 10 | "test-data/test-data/GeoIP2-Country-Test.mmdb", 11 | "test-data/test-data/GeoIP2-Domain-Test.mmdb", 12 | "test-data/test-data/GeoIP2-ISP-Test.mmdb", 13 | "test-data/test-data/GeoIP2-Precision-City-Test.mmdb", 14 | "test-data/test-data/MaxMind-DB-no-ipv4-search-tree.mmdb", 15 | "test-data/test-data/MaxMind-DB-string-value-entries.mmdb", 16 | "test-data/test-data/MaxMind-DB-test-decoder.mmdb", 17 | "test-data/test-data/MaxMind-DB-test-ipv4-24.mmdb", 18 | "test-data/test-data/MaxMind-DB-test-ipv4-28.mmdb", 19 | "test-data/test-data/MaxMind-DB-test-ipv4-32.mmdb", 20 | "test-data/test-data/MaxMind-DB-test-ipv6-24.mmdb", 21 | "test-data/test-data/MaxMind-DB-test-ipv6-28.mmdb", 22 | "test-data/test-data/MaxMind-DB-test-ipv6-32.mmdb", 23 | "test-data/test-data/MaxMind-DB-test-mixed-24.mmdb", 24 | "test-data/test-data/MaxMind-DB-test-mixed-28.mmdb", 25 | "test-data/test-data/MaxMind-DB-test-mixed-32.mmdb", 26 | "test-data/test-data/MaxMind-DB-test-nested.mmdb", 27 | } 28 | 29 | for _, database := range databases { 30 | reader, err := Open(database) 31 | if err != nil { 32 | t.Error(err) 33 | } 34 | if err = reader.Verify(); err != nil { 35 | t.Errorf("Received error (%v) when verifying %v", err, database) 36 | } 37 | } 38 | } 39 | 40 | func TestVerifyOnBrokenDatabases(t *testing.T) { 41 | databases := []string{ 42 | "test-data/test-data/GeoIP2-City-Test-Broken-Double-Format.mmdb", 43 | "test-data/test-data/MaxMind-DB-test-broken-pointers-24.mmdb", 44 | "test-data/test-data/MaxMind-DB-test-broken-search-tree-24.mmdb", 45 | } 46 | 47 | for _, database := range databases { 48 | reader, err := Open(database) 49 | if err != nil { 50 | t.Error(err) 51 | } 52 | err = reader.Verify() 53 | if err == nil { 54 | t.Errorf( 55 | "Did not receive expected error when verifying %v", 56 | database, 57 | ) 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | 26 | *.swp 27 | coverage.out 28 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/Makefile: -------------------------------------------------------------------------------- 1 | GO15VENDOREXPERIMENT=1 2 | 3 | .PHONY: test utils bin/dhttest bin/scan 4 | 5 | all: utils 6 | 7 | test: 8 | go test -v ./... 9 | 10 | #utils: bin/scan 11 | #bin/dhttest 12 | 13 | #bin/dhttest: dht/ utils/dhttest 14 | # go install ./utils/dhttest/ 15 | 16 | #bin/scan: dht/ utils/scan 17 | # go install ./utils/scan/ 18 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/README.md: -------------------------------------------------------------------------------- 1 | [![Circle CI](https://circleci.com/gh/vikstrous/gotox.svg?style=shield)](https://circleci.com/gh/vikstrous/gotox) [![Coverage Status](https://coveralls.io/repos/vikstrous/gotox/badge.svg?branch=master&service=github)](https://coveralls.io/github/vikstrous/gotox?branch=master) 2 | 3 | # gotox 4 | 5 | A re-implementation of tuxcore in Go. WIP. 6 | 7 | TODO: 8 | 9 | * [ ] complete TODO list 10 | * [ ] DHT packet seralizers 11 | * [x] Ping/Pong 12 | * [x] GetNodes 13 | * [x] SendNodes 14 | * ... 15 | * ... 16 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/breaking_ideas.md: -------------------------------------------------------------------------------- 1 | 1. Send many spoofed getNodes requests? 2 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/circle.yml: -------------------------------------------------------------------------------- 1 | test: 2 | pre: 3 | - go get github.com/axw/gocov/gocov 4 | - go get github.com/mattn/goveralls 5 | - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi 6 | override: 7 | - ./test.sh 8 | post: 9 | - /home/ubuntu/.go_workspace/bin/goveralls -coverprofile=coverage.out -service=circle-ci -repotoken=$COVERALLS_TOKEN 10 | - go tool cover -html=coverage.out -o $CIRCLE_ARTIFACTS/coverage.html 11 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/constants.go: -------------------------------------------------------------------------------- 1 | package gotox 2 | 3 | const ( 4 | UserStatusNone = iota 5 | UserStatusAway 6 | UserStatusBusy 7 | ) 8 | 9 | const PingIDSize = 8 10 | const SendbackDataSize = 8 11 | const NonceSize = 24 12 | const SymmetricKeySize = 32 13 | const PublicKeySize = 32 14 | const PrivateKeySize = 32 15 | const MaxCloseClients = 32 16 | 17 | // Tox addresses are in the format 18 | // * [Public Key (TOX_PUBLIC_KEY_SIZE bytes)][nospam (4 bytes)][checksum (2 bytes)]. 19 | const AddressSize = PublicKeySize + 4 + 2 20 | const MaxNameLength = 128 21 | const MaxStatusMessageLength = 1007 22 | const MaxFriendRequestLength = 1016 23 | const MaxMessageLength = 1372 24 | const MaxCustomPacketLength = 1373 25 | const HashLength = 32 26 | const FileIDLength = 32 27 | const MaxFilenameLength = 255 28 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/dht/constants.go: -------------------------------------------------------------------------------- 1 | package dht 2 | 3 | import ( 4 | "github.com/vikstrous/gotox" 5 | ) 6 | 7 | type DHTID [gotox.PublicKeySize]byte 8 | 9 | const fakeFriendNumber = 4 10 | 11 | const maxUDPPacketSize = 2048 12 | 13 | // http://lxr.free-electrons.com/source/include/linux/socket.h 14 | // TODO: get these from the source 15 | const AF_INET byte = 2 16 | const AF_INET6 byte = 10 17 | const TCP_INET byte = 130 18 | const TCP_INET6 byte = 138 19 | 20 | // message type, ip, port, public key 21 | const packedNodeSizeIPv4 = 1 + 4 + 2 + gotox.PublicKeySize 22 | const packedNodeSizeIPv6 = 1 + 16 + 2 + gotox.PublicKeySize 23 | 24 | var packedNodeSize = map[byte]uint{ 25 | AF_INET: packedNodeSizeIPv4, 26 | AF_INET6: packedNodeSizeIPv6, 27 | TCP_INET: packedNodeSizeIPv4, 28 | TCP_INET6: packedNodeSizeIPv6, 29 | } 30 | 31 | const netPacketPing uint8 = 0 /* Ping request packet ID. */ 32 | const netPacketPong uint8 = 1 /* Ping response packet ID. */ 33 | // Node == DHTPeer 34 | const netPacketGetNodes uint8 = 2 /* Get nodes request packet ID. */ 35 | // AKA SendNodesIPv6 36 | const netPacketGetNodesReply uint8 = 4 /* Send nodes response packet ID for other addresses. */ 37 | const netPacketCookieRequest uint8 = 24 /* Cookie request packet */ 38 | const netPacketCookieResponse uint8 = 25 /* Cookie response packet */ 39 | const netPacketCryptoHs uint8 = 26 /* Crypto handshake packet */ 40 | const netPacketCryptoData uint8 = 27 /* Crypto data packet */ 41 | const netPacketCrypto uint8 = 32 /* Encrypted data packet ID. */ 42 | const netPacketLanDiscovery uint8 = 33 /* LAN discovery packet ID. */ 43 | 44 | /* See: docs/Prevent_Tracking.txt and onion.{c, h} */ 45 | const netPacketOnionSendInitial uint8 = 128 46 | const netPacketOnionSend1 uint8 = 129 47 | const netPacketOnionSend2 uint8 = 130 48 | 49 | const netPacketAnnounceRequest uint8 = 131 50 | const netPacketAnnounceResponse uint8 = 132 51 | const netPacketOnionDataRequest uint8 = 133 52 | const netPacketOnionDataResponse uint8 = 134 53 | 54 | const netPacketOnionRecv3 uint8 = 140 55 | const netPacketOnionRecv2 uint8 = 141 56 | const netPacketOnionRecv1 uint8 = 142 57 | 58 | /* Only used for bootstrap nodes */ 59 | const bootstrapInfoPacketId = 240 60 | 61 | const toxPortrangeFrom = 33445 62 | const toxPortrangeTo = 33545 63 | const toxPortDefault = toxPortrangeFrom 64 | 65 | /* TCP related */ 66 | //const tcpOnionFamily = (afInet6 + 1) 67 | //const tcpInet = (afInet6 + 2) 68 | //const tcpInet6 = (afInet6 + 3) 69 | //const tcpFamily = (afInet6 + 4) 70 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/dht/dht_integration_test.go_not: -------------------------------------------------------------------------------- 1 | // +build integration 2 | 3 | package dht 4 | 5 | import ( 6 | "net" 7 | //"reflect" 8 | "testing" 9 | "time" 10 | ) 11 | 12 | func TestBootstrap(t *testing.T) { 13 | dht, err := New() 14 | if err != nil { 15 | t.Fatalf("Failed to create server %s.", err) 16 | } 17 | go dht.Serve() 18 | defer dht.Stop() 19 | 20 | dht.AddFriend(&qToxPublicKey) 21 | 22 | node := Node{ 23 | Addr: net.UDPAddr{ 24 | IP: net.ParseIP("::1"), 25 | Port: 33445, 26 | }, 27 | PublicKey: qToxPublicKey, 28 | } 29 | dht.Bootstrap(node) 30 | 31 | //ping 32 | data, err := dht.PackPingPong(true, 1, &node.PublicKey) 33 | if err != nil { 34 | t.Errorf("error %s", err) 35 | } 36 | err = dht.Send(data, &node.Addr) 37 | if err != nil { 38 | t.Errorf("error %s", err) 39 | } 40 | 41 | // getnodes 42 | data, err = dht.PackGetNodes(&DhtServerList[0].PublicKey, qToxPublicKey) 43 | if err != nil { 44 | t.Errorf("error %s", err) 45 | } 46 | err = dht.Send(data, &DhtServerList[0].Addr) 47 | if err != nil { 48 | t.Errorf("error %s", err) 49 | } 50 | 51 | time.Sleep(time.Second) 52 | //<-dht.request 53 | } 54 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/dht/identity.go: -------------------------------------------------------------------------------- 1 | package dht 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | 7 | "golang.org/x/crypto/nacl/box" 8 | 9 | "github.com/vikstrous/gotox" 10 | ) 11 | 12 | type Identity struct { 13 | SymmetricKey [gotox.SymmetricKeySize]byte // used for encrypting cookies? 14 | PublicKey [gotox.PublicKeySize]byte 15 | PrivateKey [gotox.PrivateKeySize]byte 16 | } 17 | 18 | func GenerateIdentity() (*Identity, error) { 19 | // generate identity key 20 | publicKey, privateKey, err := box.GenerateKey(rand.Reader) 21 | if err != nil { 22 | return nil, err 23 | } 24 | // generate "secret" key for dht - used for cookies? 25 | // XXX: this should probably be unique on every start 26 | symmetricKey := [gotox.SymmetricKeySize]byte{} 27 | _, err = rand.Read(symmetricKey[:]) 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | id := Identity{ 33 | PublicKey: *publicKey, 34 | PrivateKey: *privateKey, 35 | SymmetricKey: symmetricKey, 36 | } 37 | return &id, nil 38 | } 39 | 40 | func (id *Identity) EncryptPacket(plain *PlainPacket, publicKey *[gotox.PublicKeySize]byte) (*EncryptedPacket, error) { 41 | encrypted := EncryptedPacket{ 42 | Kind: plain.Payload.Kind(), 43 | Sender: plain.Sender, 44 | } 45 | // binary encode the data 46 | payload, err := plain.Payload.MarshalBinary() 47 | if err != nil { 48 | return nil, err 49 | } 50 | // encrypt payload into encrypted.Payload 51 | nonce, cyphertext, err := id.Encrypt(payload, publicKey) 52 | if err != nil { 53 | return nil, err 54 | } 55 | encrypted.Nonce = nonce 56 | encrypted.Payload = cyphertext 57 | return &encrypted, nil 58 | } 59 | 60 | // TODO: cache the shared key 61 | func (id *Identity) Encrypt(plain []byte, publicKey *[gotox.PublicKeySize]byte) (*[gotox.NonceSize]byte, []byte, error) { 62 | nonce := [gotox.NonceSize]byte{} 63 | // generate and write nonce 64 | _, err := rand.Read(nonce[:]) 65 | if err != nil { 66 | return nil, nil, err 67 | } 68 | encrypted := box.Seal(nil, plain, &nonce, publicKey, &id.PrivateKey) 69 | return &nonce, encrypted, nil 70 | } 71 | 72 | func (id *Identity) DecryptPacket(encrypted *EncryptedPacket) (*PlainPacket, error) { 73 | plain := PlainPacket{ 74 | Sender: encrypted.Sender, 75 | } 76 | switch encrypted.Kind { 77 | case netPacketPing: 78 | plain.Payload = &PingPong{} 79 | case netPacketPong: 80 | plain.Payload = &PingPong{} 81 | case netPacketGetNodes: 82 | plain.Payload = &GetNodes{} 83 | case netPacketGetNodesReply: 84 | plain.Payload = &GetNodesReply{} 85 | default: 86 | return nil, fmt.Errorf("Unknown packet type %d.", encrypted.Kind) 87 | } 88 | 89 | plainPayload, success := box.Open(nil, encrypted.Payload, encrypted.Nonce, encrypted.Sender, &id.PrivateKey) 90 | if !success { 91 | return nil, fmt.Errorf("Failed to decrypt.") 92 | } 93 | 94 | // decrypt payload 95 | err := plain.Payload.UnmarshalBinary(plainPayload) 96 | if err != nil { 97 | return nil, err 98 | } 99 | 100 | return &plain, nil 101 | } 102 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/dht/local_transport.go: -------------------------------------------------------------------------------- 1 | package dht 2 | 3 | import ( 4 | "log" 5 | "net" 6 | ) 7 | 8 | type LocalTransport struct { 9 | ChOut *chan []byte 10 | ChIn *chan []byte 11 | ChStop chan struct{} 12 | Identity *Identity 13 | ReceiveFunc ReceiveFunc 14 | dataChan chan TransportMessage 15 | } 16 | 17 | func NewLocalTransport(id *Identity) (*LocalTransport, error) { 18 | chIn := make(chan []byte, 100) 19 | return &LocalTransport{ 20 | ChIn: &chIn, 21 | Identity: id, 22 | ChStop: make(chan struct{}), 23 | dataChan: make(chan TransportMessage, 100), 24 | }, nil 25 | } 26 | 27 | func (t *LocalTransport) DataChan() chan TransportMessage { 28 | return t.dataChan 29 | } 30 | 31 | func (t *LocalTransport) Send(payload Payload, dest *DHTPeer) error { 32 | plainPacket := PlainPacket{ 33 | Sender: &t.Identity.PublicKey, 34 | Payload: payload, 35 | } 36 | 37 | encryptedPacket, err := t.Identity.EncryptPacket(&plainPacket, &dest.PublicKey) 38 | if err != nil { 39 | return err 40 | } 41 | 42 | data, err := encryptedPacket.MarshalBinary() 43 | if err != nil { 44 | return err 45 | } 46 | 47 | *t.ChOut <- data 48 | 49 | return nil 50 | } 51 | 52 | func (t *LocalTransport) Listen() { 53 | listenLoop: 54 | for { 55 | select { 56 | case data := <-*t.ChIn: 57 | var encryptedPacket EncryptedPacket 58 | err := encryptedPacket.UnmarshalBinary(data) 59 | if err != nil { 60 | log.Printf("error receiving: %v", err) 61 | continue 62 | } 63 | plainPacket, err := t.Identity.DecryptPacket(&encryptedPacket) 64 | if err != nil { 65 | log.Printf("error receiving: %v", err) 66 | continue 67 | } 68 | t.dataChan <- TransportMessage{*plainPacket, net.UDPAddr{}} 69 | case <-t.ChStop: 70 | break listenLoop 71 | } 72 | } 73 | close(t.dataChan) 74 | return 75 | } 76 | 77 | func (t *LocalTransport) Stop() { 78 | close(t.ChStop) 79 | } 80 | 81 | func (t *LocalTransport) RegisterReceiver(receiver ReceiveFunc) { 82 | t.ReceiveFunc = receiver 83 | } 84 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/dht/protocol.go: -------------------------------------------------------------------------------- 1 | package dht 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "encoding/hex" 7 | "encoding/json" 8 | "fmt" 9 | "net" 10 | 11 | "github.com/vikstrous/gotox" 12 | ) 13 | 14 | var DhtServerList []DHTPeer 15 | 16 | type DHTPeer struct { 17 | PublicKey [gotox.PublicKeySize]byte 18 | Addr net.UDPAddr 19 | } 20 | 21 | func init() { 22 | serverListJSON := `[ 23 | { 24 | "Name":"sonfOfRa", 25 | "PublicKey":"04119E835DF3E78BACF0F84235B300546AF8B936F035185E2A8E9E0A67C8924F", 26 | "Addr":{"IP":"144.76.60.215","Port":33445} 27 | }, 28 | { 29 | "Name":"sta1", 30 | "PublicKey":"A09162D68618E742FFBCA1C2C70385E6679604B2D80EA6E84AD0996A1AC8A074", 31 | "Addr":{"IP":"23.226.230.47","Port":33445} 32 | }, 33 | { 34 | "Name":"Munrek", 35 | "PublicKey":"E398A69646B8CEACA9F0B84F553726C1C49270558C57DF5F3C368F05A7D71354", 36 | "Addr":{"IP":"195.154.119.113","Port":33445} 37 | }, 38 | { 39 | "Name":"nurupo", 40 | "PublicKey":"F404ABAA1C99A9D37D61AB54898F56793E1DEF8BD46B1038B9D822E8460FAB67", 41 | "Addr":{"IP":"192.210.149.121","Port":33445} 42 | }, 43 | { 44 | "Name":"Impyy", 45 | "PublicKey":"788236D34978D1D5BD822F0A5BEBD2C53C64CC31CD3149350EE27D4D9A2F9B6B", 46 | "Addr":{"IP":"178.62.250.138","Port":33445} 47 | }, 48 | { 49 | "Name":"Manolis", 50 | "PublicKey":"461FA3776EF0FA655F1A05477DF1B3B614F7D6B124F7DB1DD4FE3C08B03B640F", 51 | "Addr":{"IP":"130.133.110.14","Port":33445} 52 | }, 53 | { 54 | "Name":"noisykeyboard", 55 | "PublicKey":"5918AC3C06955962A75AD7DF4F80A5D7C34F7DB9E1498D2E0495DE35B3FE8A57", 56 | "Addr":{"IP":"104.167.101.29","Port":33445} 57 | }, 58 | { 59 | "Name":"Busindre", 60 | "PublicKey":"A179B09749AC826FF01F37A9613F6B57118AE014D4196A0E1105A98F93A54702", 61 | "Addr":{"IP":"205.185.116.116","Port":33445} 62 | }, 63 | { 64 | "Name":"Busindre", 65 | "PublicKey":"1D5A5F2F5D6233058BF0259B09622FB40B482E4FA0931EB8FD3AB8E7BF7DAF6F", 66 | "Addr":{"IP":"198.98.51.198","Port":33445} 67 | }, 68 | { 69 | "Name":"ray65536", 70 | "PublicKey":"8E7D0B859922EF569298B4D261A8CCB5FEA14FB91ED412A7603A585A25698832", 71 | "Addr":{"IP":"108.61.165.198","Port":33445} 72 | }, 73 | { 74 | "Name":"Kr9r0x", 75 | "PublicKey":"C4CEB8C7AC607C6B374E2E782B3C00EA3A63B80D4910B8649CCACDD19F260819", 76 | "Addr":{"IP":"212.71.252.109","Port":33445} 77 | }, 78 | { 79 | "Name":"fluke571", 80 | "PublicKey":"3CEE1F054081E7A011234883BC4FC39F661A55B73637A5AC293DDF1251D9432B", 81 | "Addr":{"IP":"194.249.212.109","Port":33445} 82 | }, 83 | { 84 | "Name":"MAH69K", 85 | "PublicKey":"DA4E4ED4B697F2E9B000EEFE3A34B554ACD3F45F5C96EAEA2516DD7FF9AF7B43", 86 | "Addr":{"IP":"185.25.116.107","Port":33445} 87 | }, 88 | { 89 | "Name":"WIeschie", 90 | "PublicKey":"6A4D0607A296838434A6A7DDF99F50EF9D60A2C510BBF31FE538A25CB6B4652F", 91 | "Addr":{"IP":"192.99.168.140","Port":33445} 92 | } 93 | ]` 94 | 95 | json.Unmarshal([]byte(serverListJSON), &DhtServerList) 96 | } 97 | 98 | func (n *DHTPeer) UnmarshalJSON(data []byte) error { 99 | tmp := struct { 100 | Name string 101 | PublicKey string 102 | Addr net.UDPAddr 103 | }{} 104 | err := json.Unmarshal([]byte(data), &tmp) 105 | if err != nil { 106 | return err 107 | } 108 | publicKey, err := hex.DecodeString(tmp.PublicKey) 109 | if err != nil { 110 | return err 111 | } 112 | copy(n.PublicKey[:], publicKey) 113 | n.Addr = tmp.Addr 114 | return nil 115 | } 116 | 117 | type GetNodes struct { 118 | RequestedNodeID *[gotox.PublicKeySize]byte 119 | RequestID uint64 120 | } 121 | 122 | type GetNodesReply struct { 123 | Nodes []DHTPeer 124 | SendbackData uint64 125 | } 126 | 127 | type EncryptedPacket struct { 128 | Kind uint8 129 | Sender *[gotox.PublicKeySize]byte 130 | Nonce *[gotox.NonceSize]byte 131 | Payload []byte 132 | } 133 | 134 | type Payload interface { 135 | Kind() uint8 136 | MarshalBinary() (data []byte, err error) 137 | UnmarshalBinary(data []byte) error 138 | } 139 | 140 | type PlainPacket struct { 141 | Sender *[gotox.PublicKeySize]byte 142 | Payload Payload 143 | } 144 | 145 | type PingPong struct { 146 | IsPing bool 147 | RequestID uint64 148 | } 149 | 150 | // packedNodeSizeIp6 151 | // 1 + 32 + 24 + 1 + n*(32+1+16+2) + 8 + overhead 152 | // 153 | // [byte with value: 04] 154 | // [char array (client node_id), length=32 bytes] 155 | // [random 24 byte nonce] 156 | // [Encrypted with the nonce and private key of the sender: 157 | // [uint8_t number of nodes in this packet] 158 | // [Nodes in node format, length=?? * (number of nodes (maximum of 4 nodes)) bytes] 159 | // [Sendback data, length=8 bytes] 160 | // ] 161 | 162 | //[char array (node_id), length=32 bytes] 163 | //[uint8_t family (2 == IPv4, 10 == IPv6, 130 == TCP IPv4, 138 == TCP IPv6)] 164 | //[ip (in network byte order), length=4 bytes if ipv4, 16 bytes if ipv6] 165 | //[port (in network byte order), length=2 bytes] 166 | 167 | func (sn *GetNodesReply) MarshalBinary() ([]byte, error) { 168 | buf := new(bytes.Buffer) 169 | if len(sn.Nodes) > 4 { 170 | return nil, fmt.Errorf("Attempt to send too many nodes in reply: %d", len(sn.Nodes)) 171 | } 172 | 173 | // number 174 | err := binary.Write(buf, binary.BigEndian, uint8(len(sn.Nodes))) 175 | if err != nil { 176 | return nil, err 177 | } 178 | 179 | // nodes 180 | for _, node := range sn.Nodes { 181 | nodeBytes, err := node.MarshalBinary() 182 | if err != nil { 183 | return nil, err 184 | } 185 | 186 | _, err = buf.Write(nodeBytes) 187 | if err != nil { 188 | return nil, err 189 | } 190 | } 191 | 192 | // sendback data 193 | err = binary.Write(buf, binary.BigEndian, sn.SendbackData) 194 | if err != nil { 195 | return nil, err 196 | } 197 | return buf.Bytes(), err 198 | } 199 | 200 | func (sn *GetNodesReply) Kind() uint8 { 201 | return netPacketGetNodesReply 202 | } 203 | 204 | func (sn *GetNodesReply) UnmarshalBinary(data []byte) error { 205 | //log.Printf("GetNodesReply data %v %d", data, len(data)) 206 | // number of nodes 207 | numNodes := uint8(len(sn.Nodes)) 208 | binary.Read(bytes.NewReader(data), binary.BigEndian, &numNodes) 209 | 210 | // nodes 211 | sn.Nodes = make([]DHTPeer, numNodes) 212 | offset := 1 213 | for n := uint8(0); n < numNodes; n++ { 214 | var nodeSize int 215 | if data[offset] == AF_INET || data[offset] == TCP_INET { 216 | nodeSize = packedNodeSizeIPv4 217 | } else if data[offset] == AF_INET6 || data[offset] == TCP_INET6 { 218 | nodeSize = packedNodeSizeIPv6 219 | } else { 220 | return fmt.Errorf("Unknown ip type %d", data[offset]) 221 | } 222 | err := sn.Nodes[n].UnmarshalBinary(data[offset : offset+nodeSize]) 223 | if err != nil { 224 | return err 225 | } 226 | offset += nodeSize 227 | } 228 | 229 | if len(data) != offset+8 { 230 | return fmt.Errorf("Wrong length packet decrypted! Expected %d, got %d.", offset+8, len(data)) 231 | } 232 | 233 | // sendback data 234 | return binary.Read(bytes.NewReader(data[offset:]), binary.BigEndian, &sn.SendbackData) 235 | } 236 | 237 | func (n *DHTPeer) MarshalBinary() ([]byte, error) { 238 | // TODO: support TCP 239 | buf := new(bytes.Buffer) 240 | var err error 241 | if ipv4 := n.Addr.IP.To4(); ipv4 != nil { 242 | // family 1 byte 243 | err = binary.Write(buf, binary.BigEndian, AF_INET) 244 | if err != nil { 245 | return nil, err 246 | } 247 | // address 4 bytes 248 | _, err = buf.Write(ipv4) 249 | if err != nil { 250 | return nil, err 251 | } 252 | } else if ipv6 := n.Addr.IP.To16(); ipv6 != nil { 253 | // family 1 byte 254 | err = binary.Write(buf, binary.BigEndian, AF_INET6) 255 | if err != nil { 256 | return nil, err 257 | } 258 | // address 16 bytes 259 | _, err = buf.Write(ipv6) 260 | if err != nil { 261 | return nil, err 262 | } 263 | } else { 264 | return nil, fmt.Errorf("Invalid node address for node %v", n) 265 | } 266 | // port 2 bytes 267 | err = binary.Write(buf, binary.BigEndian, uint16(n.Addr.Port)) 268 | if err != nil { 269 | return nil, err 270 | } 271 | // public key 32 bytes 272 | _, err = buf.Write(n.PublicKey[:]) 273 | if err != nil { 274 | return nil, err 275 | } 276 | return buf.Bytes(), nil 277 | } 278 | 279 | func (n *DHTPeer) UnmarshalBinary(data []byte) error { 280 | if len(data) != packedNodeSizeIPv4 && len(data) != packedNodeSizeIPv6 { 281 | return fmt.Errorf("Wrong size data for node %d", len(data)) 282 | } 283 | 284 | //log.Printf("parsing %v %d", data, len(data)) 285 | // ip type 286 | ipType := data[0] 287 | 288 | // confirm ip type 289 | var ipSize int 290 | if ipType == AF_INET || ipType == TCP_INET { 291 | ipSize = net.IPv4len 292 | n.Addr.IP = net.IPv4(data[1], data[2], data[3], data[4]) 293 | } else if ipType == AF_INET6 || ipType == TCP_INET6 { 294 | ipSize = net.IPv6len 295 | n.Addr.IP = data[1 : ipSize+1] 296 | } else { 297 | return fmt.Errorf("Unknown ip type %d", ipType) 298 | } 299 | 300 | // port 301 | var port uint16 302 | err := binary.Read(bytes.NewReader(data[1+ipSize:]), binary.BigEndian, &port) 303 | if err != nil { 304 | return err 305 | } 306 | n.Addr.Port = int(port) 307 | 308 | // public key 309 | copy(n.PublicKey[:], data[1+ipSize+2:]) 310 | return nil 311 | } 312 | 313 | func (p *EncryptedPacket) UnmarshalBinary(data []byte) error { 314 | if len(data) < 1+gotox.PublicKeySize+gotox.NonceSize { 315 | return fmt.Errorf("Packet too small to be valid %d", len(data)) 316 | } 317 | p.Kind = uint8(data[0]) 318 | p.Sender = new([gotox.PublicKeySize]byte) 319 | copy(p.Sender[:], data[1:1+gotox.PublicKeySize]) 320 | p.Nonce = new([gotox.NonceSize]byte) 321 | copy(p.Nonce[:], data[1+gotox.PublicKeySize:1+gotox.PublicKeySize+gotox.NonceSize]) 322 | p.Payload = data[1+gotox.PublicKeySize+gotox.NonceSize:] 323 | return nil 324 | } 325 | 326 | func (p *EncryptedPacket) MarshalBinary() ([]byte, error) { 327 | buf := new(bytes.Buffer) 328 | 329 | // 1 byte message type 330 | err := binary.Write(buf, binary.BigEndian, p.Kind) 331 | if err != nil { 332 | return nil, err 333 | } 334 | 335 | // 32 byte public key 336 | _, err = buf.Write(p.Sender[:]) 337 | if err != nil { 338 | return nil, err 339 | } 340 | 341 | // write the nonce 342 | _, err = buf.Write(p.Nonce[:]) 343 | if err != nil { 344 | return nil, err 345 | } 346 | 347 | // write the encrypted message 348 | _, err = buf.Write(p.Payload) 349 | if err != nil { 350 | return nil, err 351 | } 352 | 353 | return buf.Bytes(), nil 354 | } 355 | 356 | func (p *PingPong) MarshalBinary() ([]byte, error) { 357 | data := new(bytes.Buffer) 358 | var kind uint8 359 | if p.IsPing { 360 | kind = netPacketPing 361 | } else { 362 | kind = netPacketPong 363 | } 364 | // request or respense 365 | err := binary.Write(data, binary.BigEndian, kind) 366 | if err != nil { 367 | return nil, err 368 | } 369 | // pind id 370 | err = binary.Write(data, binary.BigEndian, p.RequestID) 371 | if err != nil { 372 | return nil, err 373 | } 374 | // finalize message to be encrypted 375 | return data.Bytes(), nil 376 | } 377 | 378 | func (p *PingPong) Kind() uint8 { 379 | if p.IsPing { 380 | return netPacketPing 381 | } else { 382 | return netPacketPong 383 | } 384 | } 385 | 386 | func (p *PingPong) UnmarshalBinary(data []byte) error { 387 | if len(data) < 1+8 { 388 | return fmt.Errorf("Wrong size data for ping %d.", len(data)) 389 | } 390 | if data[0] == netPacketPing { 391 | p.IsPing = true 392 | } else if data[0] == netPacketPong { 393 | p.IsPing = false 394 | } else { 395 | return fmt.Errorf("Unknown ping type %d.", data[0]) 396 | } 397 | return binary.Read(bytes.NewReader(data[1:]), binary.BigEndian, &p.RequestID) 398 | } 399 | 400 | func (sn *GetNodes) MarshalBinary() ([]byte, error) { 401 | buf := new(bytes.Buffer) 402 | // node id 403 | _, err := buf.Write(sn.RequestedNodeID[:]) 404 | if err != nil { 405 | return nil, err 406 | } 407 | // sendback data 408 | err = binary.Write(buf, binary.BigEndian, sn.RequestID) 409 | if err != nil { 410 | return nil, err 411 | } 412 | // finalize message to be encrypted 413 | return buf.Bytes(), nil 414 | } 415 | 416 | func (sn *GetNodes) Kind() uint8 { 417 | return netPacketGetNodes 418 | } 419 | 420 | func (sn *GetNodes) UnmarshalBinary(data []byte) error { 421 | //TODO: check length 422 | sn.RequestedNodeID = new([gotox.PublicKeySize]byte) 423 | copy(sn.RequestedNodeID[:], data[:gotox.PublicKeySize]) 424 | return binary.Read(bytes.NewReader(data[gotox.PublicKeySize:gotox.PublicKeySize+gotox.SendbackDataSize]), binary.BigEndian, &sn.RequestID) 425 | } 426 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/dht/protocol_test.go: -------------------------------------------------------------------------------- 1 | package dht 2 | 3 | import ( 4 | //"encoding/hex" 5 | "net" 6 | "reflect" 7 | "testing" 8 | 9 | //"github.com/vikstrous/gotox" 10 | //"golang.org/x/crypto/nacl/box" 11 | ) 12 | 13 | var TestIdentity *Identity 14 | var Addr4 net.UDPAddr 15 | var Addr6 net.UDPAddr 16 | 17 | func init() { 18 | TestIdentity, _ = GenerateIdentity() 19 | Addr6.IP = net.ParseIP("::1") 20 | Addr6.Port = 1337 21 | Addr4.IP = net.ParseIP("127.0.0.1") 22 | Addr4.Port = 1337 23 | } 24 | 25 | func testEncryptDecrypt(t *testing.T, id *Identity, pp *PlainPacket) { 26 | ep, err := id.EncryptPacket(pp, &id.PublicKey) 27 | if err != nil { 28 | t.Fatalf("Failed to encrypt. %s", err) 29 | } 30 | data, err := ep.MarshalBinary() 31 | if err != nil { 32 | t.Fatalf("Failed to marshal encrypted data. %s", err) 33 | } 34 | ep2 := &EncryptedPacket{} 35 | err = ep2.UnmarshalBinary(data) 36 | if err != nil { 37 | t.Fatalf("Failed to unmarshal encrypted data. %s", err) 38 | } 39 | pp2, err := id.DecryptPacket(ep2) 40 | if err != nil { 41 | t.Fatalf("Failed to decrypt encrypted packet. %s", err) 42 | } 43 | if !reflect.DeepEqual(pp2, pp) { 44 | t.Fatalf("Mismatch after decryption.\n %v\n from %v\n VS\n %v\n from %v\n", pp.Payload, pp.Sender, pp2.Payload, pp2.Sender) 45 | } 46 | } 47 | 48 | func TestPing(t *testing.T) { 49 | pp := &PlainPacket{Sender: &TestIdentity.PublicKey, Payload: &PingPong{true, 1}} 50 | testEncryptDecrypt(t, TestIdentity, pp) 51 | } 52 | 53 | func TestPong(t *testing.T) { 54 | pp := &PlainPacket{Sender: &TestIdentity.PublicKey, Payload: &PingPong{false, 2}} 55 | testEncryptDecrypt(t, TestIdentity, pp) 56 | } 57 | 58 | func TestGetNodes(t *testing.T) { 59 | pp := &PlainPacket{Sender: &TestIdentity.PublicKey, Payload: &GetNodes{&TestIdentity.PublicKey, 3}} 60 | testEncryptDecrypt(t, TestIdentity, pp) 61 | 62 | } 63 | 64 | func TestGetNodesReply1(t *testing.T) { 65 | pp := &PlainPacket{Sender: &TestIdentity.PublicKey, Payload: &GetNodesReply{[]DHTPeer{{TestIdentity.PublicKey, Addr4}}, 4}} 66 | testEncryptDecrypt(t, TestIdentity, pp) 67 | } 68 | 69 | func TestGetNodesReply2(t *testing.T) { 70 | pp := &PlainPacket{Sender: &TestIdentity.PublicKey, Payload: &GetNodesReply{[]DHTPeer{{TestIdentity.PublicKey, Addr4}, {TestIdentity.PublicKey, Addr6}}, 5}} 71 | testEncryptDecrypt(t, TestIdentity, pp) 72 | } 73 | func TestGetNodesReply5(t *testing.T) { 74 | node := DHTPeer{TestIdentity.PublicKey, Addr4} 75 | pp := &PlainPacket{Sender: &TestIdentity.PublicKey, Payload: &GetNodesReply{[]DHTPeer{ 76 | node, 77 | node, 78 | node, 79 | node, 80 | node}, 81 | 5}} 82 | _, err := TestIdentity.EncryptPacket(pp, &TestIdentity.PublicKey) 83 | if err == nil { 84 | t.Fatalf("Should not have succeed in encrypting with too many nodes in GetNodes.") 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/dht/transport.go: -------------------------------------------------------------------------------- 1 | package dht 2 | 3 | import ( 4 | "log" 5 | "net" 6 | "time" 7 | ) 8 | 9 | // return true to terminate the listener 10 | type ReceiveFunc func(*PlainPacket, *net.UDPAddr) bool 11 | 12 | type TransportMessage struct { 13 | Packet PlainPacket 14 | Addr net.UDPAddr 15 | } 16 | 17 | type Transport interface { 18 | Send(payload Payload, dest *DHTPeer) error 19 | Listen() 20 | Stop() 21 | DataChan() chan TransportMessage 22 | } 23 | 24 | type UDPTransport struct { 25 | Server net.UDPConn 26 | Identity *Identity 27 | dataChan chan TransportMessage 28 | ChStop chan struct{} 29 | } 30 | 31 | func NewUDPTransport(id *Identity) (*UDPTransport, error) { 32 | listener, err := net.ListenUDP("udp", nil) 33 | if err != nil { 34 | return nil, err 35 | } 36 | 37 | return &UDPTransport{ 38 | Server: *listener, 39 | Identity: id, 40 | ChStop: make(chan struct{}), 41 | dataChan: make(chan TransportMessage, 100), 42 | }, nil 43 | } 44 | 45 | func (t *UDPTransport) DataChan() chan TransportMessage { 46 | return t.dataChan 47 | } 48 | 49 | func (t *UDPTransport) Send(payload Payload, dest *DHTPeer) error { 50 | plainPacket := PlainPacket{ 51 | Sender: &t.Identity.PublicKey, 52 | Payload: payload, 53 | } 54 | 55 | encryptedPacket, err := t.Identity.EncryptPacket(&plainPacket, &dest.PublicKey) 56 | if err != nil { 57 | return err 58 | } 59 | 60 | data, err := encryptedPacket.MarshalBinary() 61 | if err != nil { 62 | return err 63 | } 64 | 65 | t.Server.SetDeadline(time.Now().Add(time.Second)) 66 | _, _, err = t.Server.WriteMsgUDP(data, nil, &dest.Addr) 67 | return err 68 | } 69 | 70 | func (t *UDPTransport) Stop() { 71 | close(t.ChStop) 72 | } 73 | 74 | func (t *UDPTransport) Listen() { 75 | listenLoop: 76 | for { 77 | select { 78 | case <-t.ChStop: 79 | break listenLoop 80 | default: 81 | buffer := make([]byte, 2048) 82 | // TODO: can we make this buffer smaller? 83 | oob := make([]byte, 2048) 84 | // n, oobn, flags, addr, err 85 | t.Server.SetDeadline(time.Now().Add(time.Second)) 86 | buffer_length, _, _, addr, err := t.Server.ReadMsgUDP(buffer, oob) 87 | if err != nil { 88 | if opErr, ok := err.(*net.OpError); ok && opErr.Timeout() { 89 | continue 90 | } 91 | log.Println(err) 92 | break listenLoop 93 | } 94 | 95 | if buffer_length >= 1 { 96 | var encryptedPacket EncryptedPacket 97 | err := encryptedPacket.UnmarshalBinary(buffer[:buffer_length]) 98 | if err != nil { 99 | log.Printf("error receiving: %v", err) 100 | continue 101 | } 102 | plainPacket, err := t.Identity.DecryptPacket(&encryptedPacket) 103 | if err != nil { 104 | log.Printf("error receiving: %v", err) 105 | continue 106 | } 107 | t.dataChan <- TransportMessage{*plainPacket, *addr} 108 | } else { 109 | log.Printf("Received empty message???") 110 | continue 111 | } 112 | } 113 | } 114 | close(t.dataChan) 115 | return 116 | } 117 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/dht/transport_test.go: -------------------------------------------------------------------------------- 1 | package dht 2 | 3 | import "testing" 4 | 5 | func TestReceive(t *testing.T) { 6 | id1, err := GenerateIdentity() 7 | if err != nil { 8 | t.Fatal(err) 9 | return 10 | } 11 | transport1, err := NewLocalTransport(id1) 12 | if err != nil { 13 | t.Fatal(err) 14 | return 15 | } 16 | id2, err := GenerateIdentity() 17 | if err != nil { 18 | t.Fatal(err) 19 | return 20 | } 21 | transport2, err := NewLocalTransport(id2) 22 | if err != nil { 23 | t.Fatal(err) 24 | return 25 | } 26 | 27 | // pipe the output of transport2 into the input of transport1 28 | transport2.ChOut = transport1.ChIn 29 | transport2.Send(&PingPong{IsPing: true, RequestID: 3}, &DHTPeer{PublicKey: id1.PublicKey}) 30 | 31 | // process the message 32 | go transport1.Listen() 33 | 34 | // register the receiver before we send 35 | message := <-transport1.DataChan() 36 | switch payload := message.Packet.Payload.(type) { 37 | case *PingPong: 38 | if payload.IsPing != true { 39 | t.Fatalf("Was not ping: %b", payload.IsPing) 40 | } 41 | if payload.RequestID != 3 { 42 | t.Fatalf("Wrong pingID: %d", payload.RequestID) 43 | } 44 | default: 45 | t.Fatalf("Internal error. Failed to handle payload of parsed packet. %d\n", message.Packet) 46 | //t.Fatalf("Internal error. Failed to handle payload of parsed packet. %d\n", message.Packet.Payload.Kind()) 47 | } 48 | 49 | transport1.Stop() 50 | _, ok := <-transport1.DataChan() 51 | if ok { 52 | t.Fatalf("transport1 channel not closed correctly?") 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/dht/util.go: -------------------------------------------------------------------------------- 1 | package dht 2 | 3 | import ( 4 | "net" 5 | ) 6 | 7 | func addrEq(addr1, addr2 net.UDPAddr) bool { 8 | if !addr1.IP.Equal(addr2.IP) { 9 | return false 10 | } 11 | if addr1.Port != addr2.Port { 12 | return false 13 | } 14 | return true 15 | } 16 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/qtox.pcapng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vikstrous/tox-crawler/6ee847d4bf250060a43c5241127e90dfd5914659/Godeps/_workspace/src/github.com/vikstrous/gotox/qtox.pcapng -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | OUT=coverage.out 3 | TMP=profile.out 4 | 5 | echo "mode: atomic" > $OUT 6 | for Dir in $(find ./* -maxdepth 10 -type d ); 7 | do 8 | if ls $Dir/*.go &> /dev/null; 9 | then 10 | returnval=`go test -race -coverprofile=profile.out $Dir` 11 | echo ${returnval} 12 | if [[ ${returnval} != *FAIL* ]] 13 | then 14 | if [ -f $TMP ] 15 | then 16 | cat $TMP | grep -v "mode: atomic" >> $OUT 17 | fi 18 | else 19 | exit 1 20 | fi 21 | fi 22 | done 23 | 24 | rm -rf $TMP 25 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/tox.go: -------------------------------------------------------------------------------- 1 | package gotox 2 | 3 | import ( 4 | //"github.com/vikstrous/gotox" 5 | ) 6 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/tox_test.go: -------------------------------------------------------------------------------- 1 | package gotox 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestConstants(t *testing.T) { 8 | if UserStatusNone != 0 { 9 | t.Errorf("derp") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/github.com/vikstrous/gotox/utils/dhttest/dhttest.go_not: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/hex" 5 | "fmt" 6 | 7 | "github.com/vikstrous/gotox" 8 | "github.com/vikstrous/gotox/dht" 9 | ) 10 | 11 | var publicKey = [gotox.PublicKeySize]byte{} 12 | 13 | func init() { 14 | publicKeySlice, _ := hex.DecodeString("A4D28D52D4116A02147ECE6C6299DA3F5524DEBA043B067CF7D5BF2E09064032353CFD14B519") 15 | copy(publicKey[:], publicKeySlice) 16 | } 17 | 18 | func main() { 19 | dhtServer, err := dht.New() 20 | if err != nil { 21 | fmt.Printf("Failed to create server %s.\n", err) 22 | return 23 | } 24 | go dhtServer.Serve() 25 | defer dhtServer.Stop() 26 | 27 | dhtServer.AddFriend(&publicKey) 28 | dhtServer.AddFriend(&dht.DhtServerList[0].PublicKey) 29 | 30 | dhtServer.Bootstrap(dht.DhtServerList[0]) 31 | 32 | data, err := dhtServer.PackPingPong(true, 1, &dht.DhtServerList[0].PublicKey) 33 | err = dhtServer.Send(data, &dht.DhtServerList[0].Addr) 34 | if err != nil { 35 | fmt.Printf("error %s\n", err) 36 | return 37 | } 38 | 39 | <-dhtServer.Request 40 | } 41 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/curve25519/const_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This code was translated into a form compatible with 6a from the public 6 | // domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html 7 | 8 | // +build amd64,!gccgo,!appengine 9 | 10 | DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF 11 | GLOBL ·REDMASK51(SB), 8, $8 12 | 13 | DATA ·_121666_213(SB)/8, $996687872 14 | GLOBL ·_121666_213(SB), 8, $8 15 | 16 | DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA 17 | GLOBL ·_2P0(SB), 8, $8 18 | 19 | DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE 20 | GLOBL ·_2P1234(SB), 8, $8 21 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/curve25519/cswap_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This code was translated into a form compatible with 6a from the public 6 | // domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html 7 | 8 | // +build amd64,!gccgo,!appengine 9 | 10 | // func cswap(inout *[5]uint64, v uint64) 11 | TEXT ·cswap(SB),7,$0 12 | MOVQ inout+0(FP),DI 13 | MOVQ v+8(FP),SI 14 | 15 | CMPQ SI,$1 16 | MOVQ 0(DI),SI 17 | MOVQ 80(DI),DX 18 | MOVQ 8(DI),CX 19 | MOVQ 88(DI),R8 20 | MOVQ SI,R9 21 | CMOVQEQ DX,SI 22 | CMOVQEQ R9,DX 23 | MOVQ CX,R9 24 | CMOVQEQ R8,CX 25 | CMOVQEQ R9,R8 26 | MOVQ SI,0(DI) 27 | MOVQ DX,80(DI) 28 | MOVQ CX,8(DI) 29 | MOVQ R8,88(DI) 30 | MOVQ 16(DI),SI 31 | MOVQ 96(DI),DX 32 | MOVQ 24(DI),CX 33 | MOVQ 104(DI),R8 34 | MOVQ SI,R9 35 | CMOVQEQ DX,SI 36 | CMOVQEQ R9,DX 37 | MOVQ CX,R9 38 | CMOVQEQ R8,CX 39 | CMOVQEQ R9,R8 40 | MOVQ SI,16(DI) 41 | MOVQ DX,96(DI) 42 | MOVQ CX,24(DI) 43 | MOVQ R8,104(DI) 44 | MOVQ 32(DI),SI 45 | MOVQ 112(DI),DX 46 | MOVQ 40(DI),CX 47 | MOVQ 120(DI),R8 48 | MOVQ SI,R9 49 | CMOVQEQ DX,SI 50 | CMOVQEQ R9,DX 51 | MOVQ CX,R9 52 | CMOVQEQ R8,CX 53 | CMOVQEQ R9,R8 54 | MOVQ SI,32(DI) 55 | MOVQ DX,112(DI) 56 | MOVQ CX,40(DI) 57 | MOVQ R8,120(DI) 58 | MOVQ 48(DI),SI 59 | MOVQ 128(DI),DX 60 | MOVQ 56(DI),CX 61 | MOVQ 136(DI),R8 62 | MOVQ SI,R9 63 | CMOVQEQ DX,SI 64 | CMOVQEQ R9,DX 65 | MOVQ CX,R9 66 | CMOVQEQ R8,CX 67 | CMOVQEQ R9,R8 68 | MOVQ SI,48(DI) 69 | MOVQ DX,128(DI) 70 | MOVQ CX,56(DI) 71 | MOVQ R8,136(DI) 72 | MOVQ 64(DI),SI 73 | MOVQ 144(DI),DX 74 | MOVQ 72(DI),CX 75 | MOVQ 152(DI),R8 76 | MOVQ SI,R9 77 | CMOVQEQ DX,SI 78 | CMOVQEQ R9,DX 79 | MOVQ CX,R9 80 | CMOVQEQ R8,CX 81 | CMOVQEQ R9,R8 82 | MOVQ SI,64(DI) 83 | MOVQ DX,144(DI) 84 | MOVQ CX,72(DI) 85 | MOVQ R8,152(DI) 86 | MOVQ DI,AX 87 | MOVQ SI,DX 88 | RET 89 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/curve25519/curve25519_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package curve25519 6 | 7 | import ( 8 | "fmt" 9 | "testing" 10 | ) 11 | 12 | const expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a" 13 | 14 | func TestBaseScalarMult(t *testing.T) { 15 | var a, b [32]byte 16 | in := &a 17 | out := &b 18 | a[0] = 1 19 | 20 | for i := 0; i < 200; i++ { 21 | ScalarBaseMult(out, in) 22 | in, out = out, in 23 | } 24 | 25 | result := fmt.Sprintf("%x", in[:]) 26 | if result != expectedHex { 27 | t.Errorf("incorrect result: got %s, want %s", result, expectedHex) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/curve25519/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package curve25519 provides an implementation of scalar multiplication on 6 | // the elliptic curve known as curve25519. See http://cr.yp.to/ecdh.html 7 | package curve25519 8 | 9 | // basePoint is the x coordinate of the generator of the curve. 10 | var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 11 | 12 | // ScalarMult sets dst to the product in*base where dst and base are the x 13 | // coordinates of group points and all values are in little-endian form. 14 | func ScalarMult(dst, in, base *[32]byte) { 15 | scalarMult(dst, in, base) 16 | } 17 | 18 | // ScalarBaseMult sets dst to the product in*base where dst and base are the x 19 | // coordinates of group points, base is the standard generator and all values 20 | // are in little-endian form. 21 | func ScalarBaseMult(dst, in *[32]byte) { 22 | ScalarMult(dst, in, &basePoint) 23 | } 24 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/curve25519/freeze_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This code was translated into a form compatible with 6a from the public 6 | // domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html 7 | 8 | // +build amd64,!gccgo,!appengine 9 | 10 | // func freeze(inout *[5]uint64) 11 | TEXT ·freeze(SB),7,$96-8 12 | MOVQ inout+0(FP), DI 13 | 14 | MOVQ SP,R11 15 | MOVQ $31,CX 16 | NOTQ CX 17 | ANDQ CX,SP 18 | ADDQ $32,SP 19 | 20 | MOVQ R11,0(SP) 21 | MOVQ R12,8(SP) 22 | MOVQ R13,16(SP) 23 | MOVQ R14,24(SP) 24 | MOVQ R15,32(SP) 25 | MOVQ BX,40(SP) 26 | MOVQ BP,48(SP) 27 | MOVQ 0(DI),SI 28 | MOVQ 8(DI),DX 29 | MOVQ 16(DI),CX 30 | MOVQ 24(DI),R8 31 | MOVQ 32(DI),R9 32 | MOVQ ·REDMASK51(SB),AX 33 | MOVQ AX,R10 34 | SUBQ $18,R10 35 | MOVQ $3,R11 36 | REDUCELOOP: 37 | MOVQ SI,R12 38 | SHRQ $51,R12 39 | ANDQ AX,SI 40 | ADDQ R12,DX 41 | MOVQ DX,R12 42 | SHRQ $51,R12 43 | ANDQ AX,DX 44 | ADDQ R12,CX 45 | MOVQ CX,R12 46 | SHRQ $51,R12 47 | ANDQ AX,CX 48 | ADDQ R12,R8 49 | MOVQ R8,R12 50 | SHRQ $51,R12 51 | ANDQ AX,R8 52 | ADDQ R12,R9 53 | MOVQ R9,R12 54 | SHRQ $51,R12 55 | ANDQ AX,R9 56 | IMUL3Q $19,R12,R12 57 | ADDQ R12,SI 58 | SUBQ $1,R11 59 | JA REDUCELOOP 60 | MOVQ $1,R12 61 | CMPQ R10,SI 62 | CMOVQLT R11,R12 63 | CMPQ AX,DX 64 | CMOVQNE R11,R12 65 | CMPQ AX,CX 66 | CMOVQNE R11,R12 67 | CMPQ AX,R8 68 | CMOVQNE R11,R12 69 | CMPQ AX,R9 70 | CMOVQNE R11,R12 71 | NEGQ R12 72 | ANDQ R12,AX 73 | ANDQ R12,R10 74 | SUBQ R10,SI 75 | SUBQ AX,DX 76 | SUBQ AX,CX 77 | SUBQ AX,R8 78 | SUBQ AX,R9 79 | MOVQ SI,0(DI) 80 | MOVQ DX,8(DI) 81 | MOVQ CX,16(DI) 82 | MOVQ R8,24(DI) 83 | MOVQ R9,32(DI) 84 | MOVQ 0(SP),R11 85 | MOVQ 8(SP),R12 86 | MOVQ 16(SP),R13 87 | MOVQ 24(SP),R14 88 | MOVQ 32(SP),R15 89 | MOVQ 40(SP),BX 90 | MOVQ 48(SP),BP 91 | MOVQ R11,SP 92 | MOVQ DI,AX 93 | MOVQ SI,DX 94 | RET 95 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/curve25519/mont25519_amd64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build amd64,!gccgo,!appengine 6 | 7 | package curve25519 8 | 9 | // These functions are implemented in the .s files. The names of the functions 10 | // in the rest of the file are also taken from the SUPERCOP sources to help 11 | // people following along. 12 | 13 | //go:noescape 14 | 15 | func cswap(inout *[5]uint64, v uint64) 16 | 17 | //go:noescape 18 | 19 | func ladderstep(inout *[5][5]uint64) 20 | 21 | //go:noescape 22 | 23 | func freeze(inout *[5]uint64) 24 | 25 | //go:noescape 26 | 27 | func mul(dest, a, b *[5]uint64) 28 | 29 | //go:noescape 30 | 31 | func square(out, in *[5]uint64) 32 | 33 | // mladder uses a Montgomery ladder to calculate (xr/zr) *= s. 34 | func mladder(xr, zr *[5]uint64, s *[32]byte) { 35 | var work [5][5]uint64 36 | 37 | work[0] = *xr 38 | setint(&work[1], 1) 39 | setint(&work[2], 0) 40 | work[3] = *xr 41 | setint(&work[4], 1) 42 | 43 | j := uint(6) 44 | var prevbit byte 45 | 46 | for i := 31; i >= 0; i-- { 47 | for j < 8 { 48 | bit := ((*s)[i] >> j) & 1 49 | swap := bit ^ prevbit 50 | prevbit = bit 51 | cswap(&work[1], uint64(swap)) 52 | ladderstep(&work) 53 | j-- 54 | } 55 | j = 7 56 | } 57 | 58 | *xr = work[1] 59 | *zr = work[2] 60 | } 61 | 62 | func scalarMult(out, in, base *[32]byte) { 63 | var e [32]byte 64 | copy(e[:], (*in)[:]) 65 | e[0] &= 248 66 | e[31] &= 127 67 | e[31] |= 64 68 | 69 | var t, z [5]uint64 70 | unpack(&t, base) 71 | mladder(&t, &z, &e) 72 | invert(&z, &z) 73 | mul(&t, &t, &z) 74 | pack(out, &t) 75 | } 76 | 77 | func setint(r *[5]uint64, v uint64) { 78 | r[0] = v 79 | r[1] = 0 80 | r[2] = 0 81 | r[3] = 0 82 | r[4] = 0 83 | } 84 | 85 | // unpack sets r = x where r consists of 5, 51-bit limbs in little-endian 86 | // order. 87 | func unpack(r *[5]uint64, x *[32]byte) { 88 | r[0] = uint64(x[0]) | 89 | uint64(x[1])<<8 | 90 | uint64(x[2])<<16 | 91 | uint64(x[3])<<24 | 92 | uint64(x[4])<<32 | 93 | uint64(x[5])<<40 | 94 | uint64(x[6]&7)<<48 95 | 96 | r[1] = uint64(x[6])>>3 | 97 | uint64(x[7])<<5 | 98 | uint64(x[8])<<13 | 99 | uint64(x[9])<<21 | 100 | uint64(x[10])<<29 | 101 | uint64(x[11])<<37 | 102 | uint64(x[12]&63)<<45 103 | 104 | r[2] = uint64(x[12])>>6 | 105 | uint64(x[13])<<2 | 106 | uint64(x[14])<<10 | 107 | uint64(x[15])<<18 | 108 | uint64(x[16])<<26 | 109 | uint64(x[17])<<34 | 110 | uint64(x[18])<<42 | 111 | uint64(x[19]&1)<<50 112 | 113 | r[3] = uint64(x[19])>>1 | 114 | uint64(x[20])<<7 | 115 | uint64(x[21])<<15 | 116 | uint64(x[22])<<23 | 117 | uint64(x[23])<<31 | 118 | uint64(x[24])<<39 | 119 | uint64(x[25]&15)<<47 120 | 121 | r[4] = uint64(x[25])>>4 | 122 | uint64(x[26])<<4 | 123 | uint64(x[27])<<12 | 124 | uint64(x[28])<<20 | 125 | uint64(x[29])<<28 | 126 | uint64(x[30])<<36 | 127 | uint64(x[31]&127)<<44 128 | } 129 | 130 | // pack sets out = x where out is the usual, little-endian form of the 5, 131 | // 51-bit limbs in x. 132 | func pack(out *[32]byte, x *[5]uint64) { 133 | t := *x 134 | freeze(&t) 135 | 136 | out[0] = byte(t[0]) 137 | out[1] = byte(t[0] >> 8) 138 | out[2] = byte(t[0] >> 16) 139 | out[3] = byte(t[0] >> 24) 140 | out[4] = byte(t[0] >> 32) 141 | out[5] = byte(t[0] >> 40) 142 | out[6] = byte(t[0] >> 48) 143 | 144 | out[6] ^= byte(t[1]<<3) & 0xf8 145 | out[7] = byte(t[1] >> 5) 146 | out[8] = byte(t[1] >> 13) 147 | out[9] = byte(t[1] >> 21) 148 | out[10] = byte(t[1] >> 29) 149 | out[11] = byte(t[1] >> 37) 150 | out[12] = byte(t[1] >> 45) 151 | 152 | out[12] ^= byte(t[2]<<6) & 0xc0 153 | out[13] = byte(t[2] >> 2) 154 | out[14] = byte(t[2] >> 10) 155 | out[15] = byte(t[2] >> 18) 156 | out[16] = byte(t[2] >> 26) 157 | out[17] = byte(t[2] >> 34) 158 | out[18] = byte(t[2] >> 42) 159 | out[19] = byte(t[2] >> 50) 160 | 161 | out[19] ^= byte(t[3]<<1) & 0xfe 162 | out[20] = byte(t[3] >> 7) 163 | out[21] = byte(t[3] >> 15) 164 | out[22] = byte(t[3] >> 23) 165 | out[23] = byte(t[3] >> 31) 166 | out[24] = byte(t[3] >> 39) 167 | out[25] = byte(t[3] >> 47) 168 | 169 | out[25] ^= byte(t[4]<<4) & 0xf0 170 | out[26] = byte(t[4] >> 4) 171 | out[27] = byte(t[4] >> 12) 172 | out[28] = byte(t[4] >> 20) 173 | out[29] = byte(t[4] >> 28) 174 | out[30] = byte(t[4] >> 36) 175 | out[31] = byte(t[4] >> 44) 176 | } 177 | 178 | // invert calculates r = x^-1 mod p using Fermat's little theorem. 179 | func invert(r *[5]uint64, x *[5]uint64) { 180 | var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t [5]uint64 181 | 182 | square(&z2, x) /* 2 */ 183 | square(&t, &z2) /* 4 */ 184 | square(&t, &t) /* 8 */ 185 | mul(&z9, &t, x) /* 9 */ 186 | mul(&z11, &z9, &z2) /* 11 */ 187 | square(&t, &z11) /* 22 */ 188 | mul(&z2_5_0, &t, &z9) /* 2^5 - 2^0 = 31 */ 189 | 190 | square(&t, &z2_5_0) /* 2^6 - 2^1 */ 191 | for i := 1; i < 5; i++ { /* 2^20 - 2^10 */ 192 | square(&t, &t) 193 | } 194 | mul(&z2_10_0, &t, &z2_5_0) /* 2^10 - 2^0 */ 195 | 196 | square(&t, &z2_10_0) /* 2^11 - 2^1 */ 197 | for i := 1; i < 10; i++ { /* 2^20 - 2^10 */ 198 | square(&t, &t) 199 | } 200 | mul(&z2_20_0, &t, &z2_10_0) /* 2^20 - 2^0 */ 201 | 202 | square(&t, &z2_20_0) /* 2^21 - 2^1 */ 203 | for i := 1; i < 20; i++ { /* 2^40 - 2^20 */ 204 | square(&t, &t) 205 | } 206 | mul(&t, &t, &z2_20_0) /* 2^40 - 2^0 */ 207 | 208 | square(&t, &t) /* 2^41 - 2^1 */ 209 | for i := 1; i < 10; i++ { /* 2^50 - 2^10 */ 210 | square(&t, &t) 211 | } 212 | mul(&z2_50_0, &t, &z2_10_0) /* 2^50 - 2^0 */ 213 | 214 | square(&t, &z2_50_0) /* 2^51 - 2^1 */ 215 | for i := 1; i < 50; i++ { /* 2^100 - 2^50 */ 216 | square(&t, &t) 217 | } 218 | mul(&z2_100_0, &t, &z2_50_0) /* 2^100 - 2^0 */ 219 | 220 | square(&t, &z2_100_0) /* 2^101 - 2^1 */ 221 | for i := 1; i < 100; i++ { /* 2^200 - 2^100 */ 222 | square(&t, &t) 223 | } 224 | mul(&t, &t, &z2_100_0) /* 2^200 - 2^0 */ 225 | 226 | square(&t, &t) /* 2^201 - 2^1 */ 227 | for i := 1; i < 50; i++ { /* 2^250 - 2^50 */ 228 | square(&t, &t) 229 | } 230 | mul(&t, &t, &z2_50_0) /* 2^250 - 2^0 */ 231 | 232 | square(&t, &t) /* 2^251 - 2^1 */ 233 | square(&t, &t) /* 2^252 - 2^2 */ 234 | square(&t, &t) /* 2^253 - 2^3 */ 235 | 236 | square(&t, &t) /* 2^254 - 2^4 */ 237 | 238 | square(&t, &t) /* 2^255 - 2^5 */ 239 | mul(r, &t, &z11) /* 2^255 - 21 */ 240 | } 241 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/curve25519/mul_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This code was translated into a form compatible with 6a from the public 6 | // domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html 7 | 8 | // +build amd64,!gccgo,!appengine 9 | 10 | // func mul(dest, a, b *[5]uint64) 11 | TEXT ·mul(SB),0,$128-24 12 | MOVQ dest+0(FP), DI 13 | MOVQ a+8(FP), SI 14 | MOVQ b+16(FP), DX 15 | 16 | MOVQ SP,R11 17 | MOVQ $31,CX 18 | NOTQ CX 19 | ANDQ CX,SP 20 | ADDQ $32,SP 21 | 22 | MOVQ R11,0(SP) 23 | MOVQ R12,8(SP) 24 | MOVQ R13,16(SP) 25 | MOVQ R14,24(SP) 26 | MOVQ R15,32(SP) 27 | MOVQ BX,40(SP) 28 | MOVQ BP,48(SP) 29 | MOVQ DI,56(SP) 30 | MOVQ DX,CX 31 | MOVQ 24(SI),DX 32 | IMUL3Q $19,DX,AX 33 | MOVQ AX,64(SP) 34 | MULQ 16(CX) 35 | MOVQ AX,R8 36 | MOVQ DX,R9 37 | MOVQ 32(SI),DX 38 | IMUL3Q $19,DX,AX 39 | MOVQ AX,72(SP) 40 | MULQ 8(CX) 41 | ADDQ AX,R8 42 | ADCQ DX,R9 43 | MOVQ 0(SI),AX 44 | MULQ 0(CX) 45 | ADDQ AX,R8 46 | ADCQ DX,R9 47 | MOVQ 0(SI),AX 48 | MULQ 8(CX) 49 | MOVQ AX,R10 50 | MOVQ DX,R11 51 | MOVQ 0(SI),AX 52 | MULQ 16(CX) 53 | MOVQ AX,R12 54 | MOVQ DX,R13 55 | MOVQ 0(SI),AX 56 | MULQ 24(CX) 57 | MOVQ AX,R14 58 | MOVQ DX,R15 59 | MOVQ 0(SI),AX 60 | MULQ 32(CX) 61 | MOVQ AX,BX 62 | MOVQ DX,BP 63 | MOVQ 8(SI),AX 64 | MULQ 0(CX) 65 | ADDQ AX,R10 66 | ADCQ DX,R11 67 | MOVQ 8(SI),AX 68 | MULQ 8(CX) 69 | ADDQ AX,R12 70 | ADCQ DX,R13 71 | MOVQ 8(SI),AX 72 | MULQ 16(CX) 73 | ADDQ AX,R14 74 | ADCQ DX,R15 75 | MOVQ 8(SI),AX 76 | MULQ 24(CX) 77 | ADDQ AX,BX 78 | ADCQ DX,BP 79 | MOVQ 8(SI),DX 80 | IMUL3Q $19,DX,AX 81 | MULQ 32(CX) 82 | ADDQ AX,R8 83 | ADCQ DX,R9 84 | MOVQ 16(SI),AX 85 | MULQ 0(CX) 86 | ADDQ AX,R12 87 | ADCQ DX,R13 88 | MOVQ 16(SI),AX 89 | MULQ 8(CX) 90 | ADDQ AX,R14 91 | ADCQ DX,R15 92 | MOVQ 16(SI),AX 93 | MULQ 16(CX) 94 | ADDQ AX,BX 95 | ADCQ DX,BP 96 | MOVQ 16(SI),DX 97 | IMUL3Q $19,DX,AX 98 | MULQ 24(CX) 99 | ADDQ AX,R8 100 | ADCQ DX,R9 101 | MOVQ 16(SI),DX 102 | IMUL3Q $19,DX,AX 103 | MULQ 32(CX) 104 | ADDQ AX,R10 105 | ADCQ DX,R11 106 | MOVQ 24(SI),AX 107 | MULQ 0(CX) 108 | ADDQ AX,R14 109 | ADCQ DX,R15 110 | MOVQ 24(SI),AX 111 | MULQ 8(CX) 112 | ADDQ AX,BX 113 | ADCQ DX,BP 114 | MOVQ 64(SP),AX 115 | MULQ 24(CX) 116 | ADDQ AX,R10 117 | ADCQ DX,R11 118 | MOVQ 64(SP),AX 119 | MULQ 32(CX) 120 | ADDQ AX,R12 121 | ADCQ DX,R13 122 | MOVQ 32(SI),AX 123 | MULQ 0(CX) 124 | ADDQ AX,BX 125 | ADCQ DX,BP 126 | MOVQ 72(SP),AX 127 | MULQ 16(CX) 128 | ADDQ AX,R10 129 | ADCQ DX,R11 130 | MOVQ 72(SP),AX 131 | MULQ 24(CX) 132 | ADDQ AX,R12 133 | ADCQ DX,R13 134 | MOVQ 72(SP),AX 135 | MULQ 32(CX) 136 | ADDQ AX,R14 137 | ADCQ DX,R15 138 | MOVQ ·REDMASK51(SB),SI 139 | SHLQ $13,R9:R8 140 | ANDQ SI,R8 141 | SHLQ $13,R11:R10 142 | ANDQ SI,R10 143 | ADDQ R9,R10 144 | SHLQ $13,R13:R12 145 | ANDQ SI,R12 146 | ADDQ R11,R12 147 | SHLQ $13,R15:R14 148 | ANDQ SI,R14 149 | ADDQ R13,R14 150 | SHLQ $13,BP:BX 151 | ANDQ SI,BX 152 | ADDQ R15,BX 153 | IMUL3Q $19,BP,DX 154 | ADDQ DX,R8 155 | MOVQ R8,DX 156 | SHRQ $51,DX 157 | ADDQ R10,DX 158 | MOVQ DX,CX 159 | SHRQ $51,DX 160 | ANDQ SI,R8 161 | ADDQ R12,DX 162 | MOVQ DX,R9 163 | SHRQ $51,DX 164 | ANDQ SI,CX 165 | ADDQ R14,DX 166 | MOVQ DX,AX 167 | SHRQ $51,DX 168 | ANDQ SI,R9 169 | ADDQ BX,DX 170 | MOVQ DX,R10 171 | SHRQ $51,DX 172 | ANDQ SI,AX 173 | IMUL3Q $19,DX,DX 174 | ADDQ DX,R8 175 | ANDQ SI,R10 176 | MOVQ R8,0(DI) 177 | MOVQ CX,8(DI) 178 | MOVQ R9,16(DI) 179 | MOVQ AX,24(DI) 180 | MOVQ R10,32(DI) 181 | MOVQ 0(SP),R11 182 | MOVQ 8(SP),R12 183 | MOVQ 16(SP),R13 184 | MOVQ 24(SP),R14 185 | MOVQ 32(SP),R15 186 | MOVQ 40(SP),BX 187 | MOVQ 48(SP),BP 188 | MOVQ R11,SP 189 | MOVQ DI,AX 190 | MOVQ SI,DX 191 | RET 192 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/curve25519/square_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This code was translated into a form compatible with 6a from the public 6 | // domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html 7 | 8 | // +build amd64,!gccgo,!appengine 9 | 10 | // func square(out, in *[5]uint64) 11 | TEXT ·square(SB),7,$96-16 12 | MOVQ out+0(FP), DI 13 | MOVQ in+8(FP), SI 14 | 15 | MOVQ SP,R11 16 | MOVQ $31,CX 17 | NOTQ CX 18 | ANDQ CX,SP 19 | ADDQ $32, SP 20 | 21 | MOVQ R11,0(SP) 22 | MOVQ R12,8(SP) 23 | MOVQ R13,16(SP) 24 | MOVQ R14,24(SP) 25 | MOVQ R15,32(SP) 26 | MOVQ BX,40(SP) 27 | MOVQ BP,48(SP) 28 | MOVQ 0(SI),AX 29 | MULQ 0(SI) 30 | MOVQ AX,CX 31 | MOVQ DX,R8 32 | MOVQ 0(SI),AX 33 | SHLQ $1,AX 34 | MULQ 8(SI) 35 | MOVQ AX,R9 36 | MOVQ DX,R10 37 | MOVQ 0(SI),AX 38 | SHLQ $1,AX 39 | MULQ 16(SI) 40 | MOVQ AX,R11 41 | MOVQ DX,R12 42 | MOVQ 0(SI),AX 43 | SHLQ $1,AX 44 | MULQ 24(SI) 45 | MOVQ AX,R13 46 | MOVQ DX,R14 47 | MOVQ 0(SI),AX 48 | SHLQ $1,AX 49 | MULQ 32(SI) 50 | MOVQ AX,R15 51 | MOVQ DX,BX 52 | MOVQ 8(SI),AX 53 | MULQ 8(SI) 54 | ADDQ AX,R11 55 | ADCQ DX,R12 56 | MOVQ 8(SI),AX 57 | SHLQ $1,AX 58 | MULQ 16(SI) 59 | ADDQ AX,R13 60 | ADCQ DX,R14 61 | MOVQ 8(SI),AX 62 | SHLQ $1,AX 63 | MULQ 24(SI) 64 | ADDQ AX,R15 65 | ADCQ DX,BX 66 | MOVQ 8(SI),DX 67 | IMUL3Q $38,DX,AX 68 | MULQ 32(SI) 69 | ADDQ AX,CX 70 | ADCQ DX,R8 71 | MOVQ 16(SI),AX 72 | MULQ 16(SI) 73 | ADDQ AX,R15 74 | ADCQ DX,BX 75 | MOVQ 16(SI),DX 76 | IMUL3Q $38,DX,AX 77 | MULQ 24(SI) 78 | ADDQ AX,CX 79 | ADCQ DX,R8 80 | MOVQ 16(SI),DX 81 | IMUL3Q $38,DX,AX 82 | MULQ 32(SI) 83 | ADDQ AX,R9 84 | ADCQ DX,R10 85 | MOVQ 24(SI),DX 86 | IMUL3Q $19,DX,AX 87 | MULQ 24(SI) 88 | ADDQ AX,R9 89 | ADCQ DX,R10 90 | MOVQ 24(SI),DX 91 | IMUL3Q $38,DX,AX 92 | MULQ 32(SI) 93 | ADDQ AX,R11 94 | ADCQ DX,R12 95 | MOVQ 32(SI),DX 96 | IMUL3Q $19,DX,AX 97 | MULQ 32(SI) 98 | ADDQ AX,R13 99 | ADCQ DX,R14 100 | MOVQ ·REDMASK51(SB),SI 101 | SHLQ $13,R8:CX 102 | ANDQ SI,CX 103 | SHLQ $13,R10:R9 104 | ANDQ SI,R9 105 | ADDQ R8,R9 106 | SHLQ $13,R12:R11 107 | ANDQ SI,R11 108 | ADDQ R10,R11 109 | SHLQ $13,R14:R13 110 | ANDQ SI,R13 111 | ADDQ R12,R13 112 | SHLQ $13,BX:R15 113 | ANDQ SI,R15 114 | ADDQ R14,R15 115 | IMUL3Q $19,BX,DX 116 | ADDQ DX,CX 117 | MOVQ CX,DX 118 | SHRQ $51,DX 119 | ADDQ R9,DX 120 | ANDQ SI,CX 121 | MOVQ DX,R8 122 | SHRQ $51,DX 123 | ADDQ R11,DX 124 | ANDQ SI,R8 125 | MOVQ DX,R9 126 | SHRQ $51,DX 127 | ADDQ R13,DX 128 | ANDQ SI,R9 129 | MOVQ DX,AX 130 | SHRQ $51,DX 131 | ADDQ R15,DX 132 | ANDQ SI,AX 133 | MOVQ DX,R10 134 | SHRQ $51,DX 135 | IMUL3Q $19,DX,DX 136 | ADDQ DX,CX 137 | ANDQ SI,R10 138 | MOVQ CX,0(DI) 139 | MOVQ R8,8(DI) 140 | MOVQ R9,16(DI) 141 | MOVQ AX,24(DI) 142 | MOVQ R10,32(DI) 143 | MOVQ 0(SP),R11 144 | MOVQ 8(SP),R12 145 | MOVQ 16(SP),R13 146 | MOVQ 24(SP),R14 147 | MOVQ 32(SP),R15 148 | MOVQ 40(SP),BX 149 | MOVQ 48(SP),BP 150 | MOVQ R11,SP 151 | MOVQ DI,AX 152 | MOVQ SI,DX 153 | RET 154 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package box authenticates and encrypts messages using public-key cryptography. 7 | 8 | Box uses Curve25519, XSalsa20 and Poly1305 to encrypt and authenticate 9 | messages. The length of messages is not hidden. 10 | 11 | It is the caller's responsibility to ensure the uniqueness of nonces—for 12 | example, by using nonce 1 for the first message, nonce 2 for the second 13 | message, etc. Nonces are long enough that randomly generated nonces have 14 | negligible risk of collision. 15 | 16 | This package is interoperable with NaCl: http://nacl.cr.yp.to/box.html. 17 | */ 18 | package box 19 | 20 | import ( 21 | "golang.org/x/crypto/curve25519" 22 | "golang.org/x/crypto/nacl/secretbox" 23 | "golang.org/x/crypto/salsa20/salsa" 24 | "io" 25 | ) 26 | 27 | // Overhead is the number of bytes of overhead when boxing a message. 28 | const Overhead = secretbox.Overhead 29 | 30 | // GenerateKey generates a new public/private key pair suitable for use with 31 | // Seal and Open. 32 | func GenerateKey(rand io.Reader) (publicKey, privateKey *[32]byte, err error) { 33 | publicKey = new([32]byte) 34 | privateKey = new([32]byte) 35 | _, err = io.ReadFull(rand, privateKey[:]) 36 | if err != nil { 37 | publicKey = nil 38 | privateKey = nil 39 | return 40 | } 41 | 42 | curve25519.ScalarBaseMult(publicKey, privateKey) 43 | return 44 | } 45 | 46 | var zeros [16]byte 47 | 48 | // Precompute calculates the shared key between peersPublicKey and privateKey 49 | // and writes it to sharedKey. The shared key can be used with 50 | // OpenAfterPrecomputation and SealAfterPrecomputation to speed up processing 51 | // when using the same pair of keys repeatedly. 52 | func Precompute(sharedKey, peersPublicKey, privateKey *[32]byte) { 53 | curve25519.ScalarMult(sharedKey, privateKey, peersPublicKey) 54 | salsa.HSalsa20(sharedKey, &zeros, sharedKey, &salsa.Sigma) 55 | } 56 | 57 | // Seal appends an encrypted and authenticated copy of message to out, which 58 | // will be Overhead bytes longer than the original and must not overlap. The 59 | // nonce must be unique for each distinct message for a given pair of keys. 60 | func Seal(out, message []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) []byte { 61 | var sharedKey [32]byte 62 | Precompute(&sharedKey, peersPublicKey, privateKey) 63 | return secretbox.Seal(out, message, nonce, &sharedKey) 64 | } 65 | 66 | // SealAfterPrecomputation performs the same actions as Seal, but takes a 67 | // shared key as generated by Precompute. 68 | func SealAfterPrecomputation(out, message []byte, nonce *[24]byte, sharedKey *[32]byte) []byte { 69 | return secretbox.Seal(out, message, nonce, sharedKey) 70 | } 71 | 72 | // Open authenticates and decrypts a box produced by Seal and appends the 73 | // message to out, which must not overlap box. The output will be Overhead 74 | // bytes smaller than box. 75 | func Open(out, box []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) ([]byte, bool) { 76 | var sharedKey [32]byte 77 | Precompute(&sharedKey, peersPublicKey, privateKey) 78 | return secretbox.Open(out, box, nonce, &sharedKey) 79 | } 80 | 81 | // OpenAfterPrecomputation performs the same actions as Open, but takes a 82 | // shared key as generated by Precompute. 83 | func OpenAfterPrecomputation(out, box []byte, nonce *[24]byte, sharedKey *[32]byte) ([]byte, bool) { 84 | return secretbox.Open(out, box, nonce, sharedKey) 85 | } 86 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/nacl/box/box_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package box 6 | 7 | import ( 8 | "bytes" 9 | "crypto/rand" 10 | "encoding/hex" 11 | "testing" 12 | 13 | "golang.org/x/crypto/curve25519" 14 | ) 15 | 16 | func TestSealOpen(t *testing.T) { 17 | publicKey1, privateKey1, _ := GenerateKey(rand.Reader) 18 | publicKey2, privateKey2, _ := GenerateKey(rand.Reader) 19 | 20 | if *privateKey1 == *privateKey2 { 21 | t.Fatalf("private keys are equal!") 22 | } 23 | if *publicKey1 == *publicKey2 { 24 | t.Fatalf("public keys are equal!") 25 | } 26 | message := []byte("test message") 27 | var nonce [24]byte 28 | 29 | box := Seal(nil, message, &nonce, publicKey1, privateKey2) 30 | opened, ok := Open(nil, box, &nonce, publicKey2, privateKey1) 31 | if !ok { 32 | t.Fatalf("failed to open box") 33 | } 34 | 35 | if !bytes.Equal(opened, message) { 36 | t.Fatalf("got %x, want %x", opened, message) 37 | } 38 | 39 | for i := range box { 40 | box[i] ^= 0x40 41 | _, ok := Open(nil, box, &nonce, publicKey2, privateKey1) 42 | if ok { 43 | t.Fatalf("opened box with byte %d corrupted", i) 44 | } 45 | box[i] ^= 0x40 46 | } 47 | } 48 | 49 | func TestBox(t *testing.T) { 50 | var privateKey1, privateKey2 [32]byte 51 | for i := range privateKey1[:] { 52 | privateKey1[i] = 1 53 | } 54 | for i := range privateKey2[:] { 55 | privateKey2[i] = 2 56 | } 57 | 58 | var publicKey1 [32]byte 59 | curve25519.ScalarBaseMult(&publicKey1, &privateKey1) 60 | var message [64]byte 61 | for i := range message[:] { 62 | message[i] = 3 63 | } 64 | 65 | var nonce [24]byte 66 | for i := range nonce[:] { 67 | nonce[i] = 4 68 | } 69 | 70 | box := Seal(nil, message[:], &nonce, &publicKey1, &privateKey2) 71 | 72 | // expected was generated using the C implementation of NaCl. 73 | expected, _ := hex.DecodeString("78ea30b19d2341ebbdba54180f821eec265cf86312549bea8a37652a8bb94f07b78a73ed1708085e6ddd0e943bbdeb8755079a37eb31d86163ce241164a47629c0539f330b4914cd135b3855bc2a2dfc") 74 | 75 | if !bytes.Equal(box, expected) { 76 | t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox/secretbox.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package secretbox encrypts and authenticates small messages. 7 | 8 | Secretbox uses XSalsa20 and Poly1305 to encrypt and authenticate messages with 9 | secret-key cryptography. The length of messages is not hidden. 10 | 11 | It is the caller's responsibility to ensure the uniqueness of nonces—for 12 | example, by using nonce 1 for the first message, nonce 2 for the second 13 | message, etc. Nonces are long enough that randomly generated nonces have 14 | negligible risk of collision. 15 | 16 | This package is interoperable with NaCl: http://nacl.cr.yp.to/secretbox.html. 17 | */ 18 | package secretbox 19 | 20 | import ( 21 | "golang.org/x/crypto/poly1305" 22 | "golang.org/x/crypto/salsa20/salsa" 23 | ) 24 | 25 | // Overhead is the number of bytes of overhead when boxing a message. 26 | const Overhead = poly1305.TagSize 27 | 28 | // setup produces a sub-key and Salsa20 counter given a nonce and key. 29 | func setup(subKey *[32]byte, counter *[16]byte, nonce *[24]byte, key *[32]byte) { 30 | // We use XSalsa20 for encryption so first we need to generate a 31 | // key and nonce with HSalsa20. 32 | var hNonce [16]byte 33 | copy(hNonce[:], nonce[:]) 34 | salsa.HSalsa20(subKey, &hNonce, key, &salsa.Sigma) 35 | 36 | // The final 8 bytes of the original nonce form the new nonce. 37 | copy(counter[:], nonce[16:]) 38 | } 39 | 40 | // sliceForAppend takes a slice and a requested number of bytes. It returns a 41 | // slice with the contents of the given slice followed by that many bytes and a 42 | // second slice that aliases into it and contains only the extra bytes. If the 43 | // original slice has sufficient capacity then no allocation is performed. 44 | func sliceForAppend(in []byte, n int) (head, tail []byte) { 45 | if total := len(in) + n; cap(in) >= total { 46 | head = in[:total] 47 | } else { 48 | head = make([]byte, total) 49 | copy(head, in) 50 | } 51 | tail = head[len(in):] 52 | return 53 | } 54 | 55 | // Seal appends an encrypted and authenticated copy of message to out, which 56 | // must not overlap message. The key and nonce pair must be unique for each 57 | // distinct message and the output will be Overhead bytes longer than message. 58 | func Seal(out, message []byte, nonce *[24]byte, key *[32]byte) []byte { 59 | var subKey [32]byte 60 | var counter [16]byte 61 | setup(&subKey, &counter, nonce, key) 62 | 63 | // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since 64 | // Salsa20 works with 64-byte blocks, we also generate 32 bytes of 65 | // keystream as a side effect. 66 | var firstBlock [64]byte 67 | salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey) 68 | 69 | var poly1305Key [32]byte 70 | copy(poly1305Key[:], firstBlock[:]) 71 | 72 | ret, out := sliceForAppend(out, len(message)+poly1305.TagSize) 73 | 74 | // We XOR up to 32 bytes of message with the keystream generated from 75 | // the first block. 76 | firstMessageBlock := message 77 | if len(firstMessageBlock) > 32 { 78 | firstMessageBlock = firstMessageBlock[:32] 79 | } 80 | 81 | tagOut := out 82 | out = out[poly1305.TagSize:] 83 | for i, x := range firstMessageBlock { 84 | out[i] = firstBlock[32+i] ^ x 85 | } 86 | message = message[len(firstMessageBlock):] 87 | ciphertext := out 88 | out = out[len(firstMessageBlock):] 89 | 90 | // Now encrypt the rest. 91 | counter[8] = 1 92 | salsa.XORKeyStream(out, message, &counter, &subKey) 93 | 94 | var tag [poly1305.TagSize]byte 95 | poly1305.Sum(&tag, ciphertext, &poly1305Key) 96 | copy(tagOut, tag[:]) 97 | 98 | return ret 99 | } 100 | 101 | // Open authenticates and decrypts a box produced by Seal and appends the 102 | // message to out, which must not overlap box. The output will be Overhead 103 | // bytes smaller than box. 104 | func Open(out []byte, box []byte, nonce *[24]byte, key *[32]byte) ([]byte, bool) { 105 | if len(box) < Overhead { 106 | return nil, false 107 | } 108 | 109 | var subKey [32]byte 110 | var counter [16]byte 111 | setup(&subKey, &counter, nonce, key) 112 | 113 | // The Poly1305 key is generated by encrypting 32 bytes of zeros. Since 114 | // Salsa20 works with 64-byte blocks, we also generate 32 bytes of 115 | // keystream as a side effect. 116 | var firstBlock [64]byte 117 | salsa.XORKeyStream(firstBlock[:], firstBlock[:], &counter, &subKey) 118 | 119 | var poly1305Key [32]byte 120 | copy(poly1305Key[:], firstBlock[:]) 121 | var tag [poly1305.TagSize]byte 122 | copy(tag[:], box) 123 | 124 | if !poly1305.Verify(&tag, box[poly1305.TagSize:], &poly1305Key) { 125 | return nil, false 126 | } 127 | 128 | ret, out := sliceForAppend(out, len(box)-Overhead) 129 | 130 | // We XOR up to 32 bytes of box with the keystream generated from 131 | // the first block. 132 | box = box[Overhead:] 133 | firstMessageBlock := box 134 | if len(firstMessageBlock) > 32 { 135 | firstMessageBlock = firstMessageBlock[:32] 136 | } 137 | for i, x := range firstMessageBlock { 138 | out[i] = firstBlock[32+i] ^ x 139 | } 140 | 141 | box = box[len(firstMessageBlock):] 142 | out = out[len(firstMessageBlock):] 143 | 144 | // Now decrypt the rest. 145 | counter[8] = 1 146 | salsa.XORKeyStream(out, box, &counter, &subKey) 147 | 148 | return ret, true 149 | } 150 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/nacl/secretbox/secretbox_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package secretbox 6 | 7 | import ( 8 | "bytes" 9 | "crypto/rand" 10 | "encoding/hex" 11 | "testing" 12 | ) 13 | 14 | func TestSealOpen(t *testing.T) { 15 | var key [32]byte 16 | var nonce [24]byte 17 | 18 | rand.Reader.Read(key[:]) 19 | rand.Reader.Read(nonce[:]) 20 | 21 | var box, opened []byte 22 | 23 | for msgLen := 0; msgLen < 128; msgLen += 17 { 24 | message := make([]byte, msgLen) 25 | rand.Reader.Read(message) 26 | 27 | box = Seal(box[:0], message, &nonce, &key) 28 | var ok bool 29 | opened, ok = Open(opened[:0], box, &nonce, &key) 30 | if !ok { 31 | t.Errorf("%d: failed to open box", msgLen) 32 | continue 33 | } 34 | 35 | if !bytes.Equal(opened, message) { 36 | t.Errorf("%d: got %x, expected %x", msgLen, opened, message) 37 | continue 38 | } 39 | } 40 | 41 | for i := range box { 42 | box[i] ^= 0x20 43 | _, ok := Open(opened[:0], box, &nonce, &key) 44 | if ok { 45 | t.Errorf("box was opened after corrupting byte %d", i) 46 | } 47 | box[i] ^= 0x20 48 | } 49 | } 50 | 51 | func TestSecretBox(t *testing.T) { 52 | var key [32]byte 53 | var nonce [24]byte 54 | var message [64]byte 55 | 56 | for i := range key[:] { 57 | key[i] = 1 58 | } 59 | for i := range nonce[:] { 60 | nonce[i] = 2 61 | } 62 | for i := range message[:] { 63 | message[i] = 3 64 | } 65 | 66 | box := Seal(nil, message[:], &nonce, &key) 67 | // expected was generated using the C implementation of NaCl. 68 | expected, _ := hex.DecodeString("8442bc313f4626f1359e3b50122b6ce6fe66ddfe7d39d14e637eb4fd5b45beadab55198df6ab5368439792a23c87db70acb6156dc5ef957ac04f6276cf6093b84be77ff0849cc33e34b7254d5a8f65ad") 69 | 70 | if !bytes.Equal(box, expected) { 71 | t.Fatalf("box didn't match, got\n%x\n, expected\n%x", box, expected) 72 | } 73 | } 74 | 75 | func TestAppend(t *testing.T) { 76 | var key [32]byte 77 | var nonce [24]byte 78 | var message [8]byte 79 | 80 | out := make([]byte, 4) 81 | box := Seal(out, message[:], &nonce, &key) 82 | if !bytes.Equal(box[:4], out[:4]) { 83 | t.Fatalf("Seal didn't correctly append") 84 | } 85 | 86 | out = make([]byte, 4, 100) 87 | box = Seal(out, message[:], &nonce, &key) 88 | if !bytes.Equal(box[:4], out[:4]) { 89 | t.Fatalf("Seal didn't correctly append with sufficient capacity.") 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/poly1305/const_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This code was translated into a form compatible with 6a from the public 6 | // domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html 7 | 8 | // +build amd64,!gccgo,!appengine 9 | 10 | DATA ·SCALE(SB)/8, $0x37F4000000000000 11 | GLOBL ·SCALE(SB), 8, $8 12 | DATA ·TWO32(SB)/8, $0x41F0000000000000 13 | GLOBL ·TWO32(SB), 8, $8 14 | DATA ·TWO64(SB)/8, $0x43F0000000000000 15 | GLOBL ·TWO64(SB), 8, $8 16 | DATA ·TWO96(SB)/8, $0x45F0000000000000 17 | GLOBL ·TWO96(SB), 8, $8 18 | DATA ·ALPHA32(SB)/8, $0x45E8000000000000 19 | GLOBL ·ALPHA32(SB), 8, $8 20 | DATA ·ALPHA64(SB)/8, $0x47E8000000000000 21 | GLOBL ·ALPHA64(SB), 8, $8 22 | DATA ·ALPHA96(SB)/8, $0x49E8000000000000 23 | GLOBL ·ALPHA96(SB), 8, $8 24 | DATA ·ALPHA130(SB)/8, $0x4C08000000000000 25 | GLOBL ·ALPHA130(SB), 8, $8 26 | DATA ·DOFFSET0(SB)/8, $0x4330000000000000 27 | GLOBL ·DOFFSET0(SB), 8, $8 28 | DATA ·DOFFSET1(SB)/8, $0x4530000000000000 29 | GLOBL ·DOFFSET1(SB), 8, $8 30 | DATA ·DOFFSET2(SB)/8, $0x4730000000000000 31 | GLOBL ·DOFFSET2(SB), 8, $8 32 | DATA ·DOFFSET3(SB)/8, $0x4930000000000000 33 | GLOBL ·DOFFSET3(SB), 8, $8 34 | DATA ·DOFFSET3MINUSTWO128(SB)/8, $0x492FFFFE00000000 35 | GLOBL ·DOFFSET3MINUSTWO128(SB), 8, $8 36 | DATA ·HOFFSET0(SB)/8, $0x43300001FFFFFFFB 37 | GLOBL ·HOFFSET0(SB), 8, $8 38 | DATA ·HOFFSET1(SB)/8, $0x45300001FFFFFFFE 39 | GLOBL ·HOFFSET1(SB), 8, $8 40 | DATA ·HOFFSET2(SB)/8, $0x47300001FFFFFFFE 41 | GLOBL ·HOFFSET2(SB), 8, $8 42 | DATA ·HOFFSET3(SB)/8, $0x49300003FFFFFFFE 43 | GLOBL ·HOFFSET3(SB), 8, $8 44 | DATA ·ROUNDING(SB)/2, $0x137f 45 | GLOBL ·ROUNDING(SB), 8, $2 46 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/poly1305/poly1305.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package poly1305 implements Poly1305 one-time message authentication code as specified in http://cr.yp.to/mac/poly1305-20050329.pdf. 7 | 8 | Poly1305 is a fast, one-time authentication function. It is infeasible for an 9 | attacker to generate an authenticator for a message without the key. However, a 10 | key must only be used for a single message. Authenticating two different 11 | messages with the same key allows an attacker to forge authenticators for other 12 | messages with the same key. 13 | 14 | Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was 15 | used with a fixed key in order to generate one-time keys from an nonce. 16 | However, in this package AES isn't used and the one-time key is specified 17 | directly. 18 | */ 19 | package poly1305 20 | 21 | import "crypto/subtle" 22 | 23 | // TagSize is the size, in bytes, of a poly1305 authenticator. 24 | const TagSize = 16 25 | 26 | // Verify returns true if mac is a valid authenticator for m with the given 27 | // key. 28 | func Verify(mac *[16]byte, m []byte, key *[32]byte) bool { 29 | var tmp [16]byte 30 | Sum(&tmp, m, key) 31 | return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1 32 | } 33 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/poly1305/poly1305_amd64.s: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This code was translated into a form compatible with 6a from the public 6 | // domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html 7 | 8 | // +build amd64,!gccgo,!appengine 9 | 10 | // func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key) 11 | TEXT ·poly1305(SB),0,$224-32 12 | MOVQ out+0(FP),DI 13 | MOVQ m+8(FP),SI 14 | MOVQ mlen+16(FP),DX 15 | MOVQ key+24(FP),CX 16 | 17 | MOVQ SP,R11 18 | MOVQ $31,R9 19 | NOTQ R9 20 | ANDQ R9,SP 21 | ADDQ $32,SP 22 | 23 | MOVQ R11,32(SP) 24 | MOVQ R12,40(SP) 25 | MOVQ R13,48(SP) 26 | MOVQ R14,56(SP) 27 | MOVQ R15,64(SP) 28 | MOVQ BX,72(SP) 29 | MOVQ BP,80(SP) 30 | FLDCW ·ROUNDING(SB) 31 | MOVL 0(CX),R8 32 | MOVL 4(CX),R9 33 | MOVL 8(CX),AX 34 | MOVL 12(CX),R10 35 | MOVQ DI,88(SP) 36 | MOVQ CX,96(SP) 37 | MOVL $0X43300000,108(SP) 38 | MOVL $0X45300000,116(SP) 39 | MOVL $0X47300000,124(SP) 40 | MOVL $0X49300000,132(SP) 41 | ANDL $0X0FFFFFFF,R8 42 | ANDL $0X0FFFFFFC,R9 43 | ANDL $0X0FFFFFFC,AX 44 | ANDL $0X0FFFFFFC,R10 45 | MOVL R8,104(SP) 46 | MOVL R9,112(SP) 47 | MOVL AX,120(SP) 48 | MOVL R10,128(SP) 49 | FMOVD 104(SP), F0 50 | FSUBD ·DOFFSET0(SB), F0 51 | FMOVD 112(SP), F0 52 | FSUBD ·DOFFSET1(SB), F0 53 | FMOVD 120(SP), F0 54 | FSUBD ·DOFFSET2(SB), F0 55 | FMOVD 128(SP), F0 56 | FSUBD ·DOFFSET3(SB), F0 57 | FXCHD F0, F3 58 | FMOVDP F0, 136(SP) 59 | FXCHD F0, F1 60 | FMOVD F0, 144(SP) 61 | FMULD ·SCALE(SB), F0 62 | FMOVDP F0, 152(SP) 63 | FMOVD F0, 160(SP) 64 | FMULD ·SCALE(SB), F0 65 | FMOVDP F0, 168(SP) 66 | FMOVD F0, 176(SP) 67 | FMULD ·SCALE(SB), F0 68 | FMOVDP F0, 184(SP) 69 | FLDZ 70 | FLDZ 71 | FLDZ 72 | FLDZ 73 | CMPQ DX,$16 74 | JB ADDATMOST15BYTES 75 | INITIALATLEAST16BYTES: 76 | MOVL 12(SI),DI 77 | MOVL 8(SI),CX 78 | MOVL 4(SI),R8 79 | MOVL 0(SI),R9 80 | MOVL DI,128(SP) 81 | MOVL CX,120(SP) 82 | MOVL R8,112(SP) 83 | MOVL R9,104(SP) 84 | ADDQ $16,SI 85 | SUBQ $16,DX 86 | FXCHD F0, F3 87 | FADDD 128(SP), F0 88 | FSUBD ·DOFFSET3MINUSTWO128(SB), F0 89 | FXCHD F0, F1 90 | FADDD 112(SP), F0 91 | FSUBD ·DOFFSET1(SB), F0 92 | FXCHD F0, F2 93 | FADDD 120(SP), F0 94 | FSUBD ·DOFFSET2(SB), F0 95 | FXCHD F0, F3 96 | FADDD 104(SP), F0 97 | FSUBD ·DOFFSET0(SB), F0 98 | CMPQ DX,$16 99 | JB MULTIPLYADDATMOST15BYTES 100 | MULTIPLYADDATLEAST16BYTES: 101 | MOVL 12(SI),DI 102 | MOVL 8(SI),CX 103 | MOVL 4(SI),R8 104 | MOVL 0(SI),R9 105 | MOVL DI,128(SP) 106 | MOVL CX,120(SP) 107 | MOVL R8,112(SP) 108 | MOVL R9,104(SP) 109 | ADDQ $16,SI 110 | SUBQ $16,DX 111 | FMOVD ·ALPHA130(SB), F0 112 | FADDD F2,F0 113 | FSUBD ·ALPHA130(SB), F0 114 | FSUBD F0,F2 115 | FMULD ·SCALE(SB), F0 116 | FMOVD ·ALPHA32(SB), F0 117 | FADDD F2,F0 118 | FSUBD ·ALPHA32(SB), F0 119 | FSUBD F0,F2 120 | FXCHD F0, F2 121 | FADDDP F0,F1 122 | FMOVD ·ALPHA64(SB), F0 123 | FADDD F4,F0 124 | FSUBD ·ALPHA64(SB), F0 125 | FSUBD F0,F4 126 | FMOVD ·ALPHA96(SB), F0 127 | FADDD F6,F0 128 | FSUBD ·ALPHA96(SB), F0 129 | FSUBD F0,F6 130 | FXCHD F0, F6 131 | FADDDP F0,F1 132 | FXCHD F0, F3 133 | FADDDP F0,F5 134 | FXCHD F0, F3 135 | FADDDP F0,F1 136 | FMOVD 176(SP), F0 137 | FMULD F3,F0 138 | FMOVD 160(SP), F0 139 | FMULD F4,F0 140 | FMOVD 144(SP), F0 141 | FMULD F5,F0 142 | FMOVD 136(SP), F0 143 | FMULDP F0,F6 144 | FMOVD 160(SP), F0 145 | FMULD F4,F0 146 | FADDDP F0,F3 147 | FMOVD 144(SP), F0 148 | FMULD F4,F0 149 | FADDDP F0,F2 150 | FMOVD 136(SP), F0 151 | FMULD F4,F0 152 | FADDDP F0,F1 153 | FMOVD 184(SP), F0 154 | FMULDP F0,F4 155 | FXCHD F0, F3 156 | FADDDP F0,F5 157 | FMOVD 144(SP), F0 158 | FMULD F4,F0 159 | FADDDP F0,F2 160 | FMOVD 136(SP), F0 161 | FMULD F4,F0 162 | FADDDP F0,F1 163 | FMOVD 184(SP), F0 164 | FMULD F4,F0 165 | FADDDP F0,F3 166 | FMOVD 168(SP), F0 167 | FMULDP F0,F4 168 | FXCHD F0, F3 169 | FADDDP F0,F4 170 | FMOVD 136(SP), F0 171 | FMULD F5,F0 172 | FADDDP F0,F1 173 | FXCHD F0, F3 174 | FMOVD 184(SP), F0 175 | FMULD F5,F0 176 | FADDDP F0,F3 177 | FXCHD F0, F1 178 | FMOVD 168(SP), F0 179 | FMULD F5,F0 180 | FADDDP F0,F1 181 | FMOVD 152(SP), F0 182 | FMULDP F0,F5 183 | FXCHD F0, F4 184 | FADDDP F0,F1 185 | CMPQ DX,$16 186 | FXCHD F0, F2 187 | FMOVD 128(SP), F0 188 | FSUBD ·DOFFSET3MINUSTWO128(SB), F0 189 | FADDDP F0,F1 190 | FXCHD F0, F1 191 | FMOVD 120(SP), F0 192 | FSUBD ·DOFFSET2(SB), F0 193 | FADDDP F0,F1 194 | FXCHD F0, F3 195 | FMOVD 112(SP), F0 196 | FSUBD ·DOFFSET1(SB), F0 197 | FADDDP F0,F1 198 | FXCHD F0, F2 199 | FMOVD 104(SP), F0 200 | FSUBD ·DOFFSET0(SB), F0 201 | FADDDP F0,F1 202 | JAE MULTIPLYADDATLEAST16BYTES 203 | MULTIPLYADDATMOST15BYTES: 204 | FMOVD ·ALPHA130(SB), F0 205 | FADDD F2,F0 206 | FSUBD ·ALPHA130(SB), F0 207 | FSUBD F0,F2 208 | FMULD ·SCALE(SB), F0 209 | FMOVD ·ALPHA32(SB), F0 210 | FADDD F2,F0 211 | FSUBD ·ALPHA32(SB), F0 212 | FSUBD F0,F2 213 | FMOVD ·ALPHA64(SB), F0 214 | FADDD F5,F0 215 | FSUBD ·ALPHA64(SB), F0 216 | FSUBD F0,F5 217 | FMOVD ·ALPHA96(SB), F0 218 | FADDD F7,F0 219 | FSUBD ·ALPHA96(SB), F0 220 | FSUBD F0,F7 221 | FXCHD F0, F7 222 | FADDDP F0,F1 223 | FXCHD F0, F5 224 | FADDDP F0,F1 225 | FXCHD F0, F3 226 | FADDDP F0,F5 227 | FADDDP F0,F1 228 | FMOVD 176(SP), F0 229 | FMULD F1,F0 230 | FMOVD 160(SP), F0 231 | FMULD F2,F0 232 | FMOVD 144(SP), F0 233 | FMULD F3,F0 234 | FMOVD 136(SP), F0 235 | FMULDP F0,F4 236 | FMOVD 160(SP), F0 237 | FMULD F5,F0 238 | FADDDP F0,F3 239 | FMOVD 144(SP), F0 240 | FMULD F5,F0 241 | FADDDP F0,F2 242 | FMOVD 136(SP), F0 243 | FMULD F5,F0 244 | FADDDP F0,F1 245 | FMOVD 184(SP), F0 246 | FMULDP F0,F5 247 | FXCHD F0, F4 248 | FADDDP F0,F3 249 | FMOVD 144(SP), F0 250 | FMULD F5,F0 251 | FADDDP F0,F2 252 | FMOVD 136(SP), F0 253 | FMULD F5,F0 254 | FADDDP F0,F1 255 | FMOVD 184(SP), F0 256 | FMULD F5,F0 257 | FADDDP F0,F4 258 | FMOVD 168(SP), F0 259 | FMULDP F0,F5 260 | FXCHD F0, F4 261 | FADDDP F0,F2 262 | FMOVD 136(SP), F0 263 | FMULD F5,F0 264 | FADDDP F0,F1 265 | FMOVD 184(SP), F0 266 | FMULD F5,F0 267 | FADDDP F0,F4 268 | FMOVD 168(SP), F0 269 | FMULD F5,F0 270 | FADDDP F0,F3 271 | FMOVD 152(SP), F0 272 | FMULDP F0,F5 273 | FXCHD F0, F4 274 | FADDDP F0,F1 275 | ADDATMOST15BYTES: 276 | CMPQ DX,$0 277 | JE NOMOREBYTES 278 | MOVL $0,0(SP) 279 | MOVL $0, 4 (SP) 280 | MOVL $0, 8 (SP) 281 | MOVL $0, 12 (SP) 282 | LEAQ 0(SP),DI 283 | MOVQ DX,CX 284 | REP; MOVSB 285 | MOVB $1,0(DI) 286 | MOVL 12 (SP),DI 287 | MOVL 8 (SP),SI 288 | MOVL 4 (SP),DX 289 | MOVL 0(SP),CX 290 | MOVL DI,128(SP) 291 | MOVL SI,120(SP) 292 | MOVL DX,112(SP) 293 | MOVL CX,104(SP) 294 | FXCHD F0, F3 295 | FADDD 128(SP), F0 296 | FSUBD ·DOFFSET3(SB), F0 297 | FXCHD F0, F2 298 | FADDD 120(SP), F0 299 | FSUBD ·DOFFSET2(SB), F0 300 | FXCHD F0, F1 301 | FADDD 112(SP), F0 302 | FSUBD ·DOFFSET1(SB), F0 303 | FXCHD F0, F3 304 | FADDD 104(SP), F0 305 | FSUBD ·DOFFSET0(SB), F0 306 | FMOVD ·ALPHA130(SB), F0 307 | FADDD F3,F0 308 | FSUBD ·ALPHA130(SB), F0 309 | FSUBD F0,F3 310 | FMULD ·SCALE(SB), F0 311 | FMOVD ·ALPHA32(SB), F0 312 | FADDD F2,F0 313 | FSUBD ·ALPHA32(SB), F0 314 | FSUBD F0,F2 315 | FMOVD ·ALPHA64(SB), F0 316 | FADDD F6,F0 317 | FSUBD ·ALPHA64(SB), F0 318 | FSUBD F0,F6 319 | FMOVD ·ALPHA96(SB), F0 320 | FADDD F5,F0 321 | FSUBD ·ALPHA96(SB), F0 322 | FSUBD F0,F5 323 | FXCHD F0, F4 324 | FADDDP F0,F3 325 | FXCHD F0, F6 326 | FADDDP F0,F1 327 | FXCHD F0, F3 328 | FADDDP F0,F5 329 | FXCHD F0, F3 330 | FADDDP F0,F1 331 | FMOVD 176(SP), F0 332 | FMULD F3,F0 333 | FMOVD 160(SP), F0 334 | FMULD F4,F0 335 | FMOVD 144(SP), F0 336 | FMULD F5,F0 337 | FMOVD 136(SP), F0 338 | FMULDP F0,F6 339 | FMOVD 160(SP), F0 340 | FMULD F5,F0 341 | FADDDP F0,F3 342 | FMOVD 144(SP), F0 343 | FMULD F5,F0 344 | FADDDP F0,F2 345 | FMOVD 136(SP), F0 346 | FMULD F5,F0 347 | FADDDP F0,F1 348 | FMOVD 184(SP), F0 349 | FMULDP F0,F5 350 | FXCHD F0, F4 351 | FADDDP F0,F5 352 | FMOVD 144(SP), F0 353 | FMULD F6,F0 354 | FADDDP F0,F2 355 | FMOVD 136(SP), F0 356 | FMULD F6,F0 357 | FADDDP F0,F1 358 | FMOVD 184(SP), F0 359 | FMULD F6,F0 360 | FADDDP F0,F4 361 | FMOVD 168(SP), F0 362 | FMULDP F0,F6 363 | FXCHD F0, F5 364 | FADDDP F0,F4 365 | FMOVD 136(SP), F0 366 | FMULD F2,F0 367 | FADDDP F0,F1 368 | FMOVD 184(SP), F0 369 | FMULD F2,F0 370 | FADDDP F0,F5 371 | FMOVD 168(SP), F0 372 | FMULD F2,F0 373 | FADDDP F0,F3 374 | FMOVD 152(SP), F0 375 | FMULDP F0,F2 376 | FXCHD F0, F1 377 | FADDDP F0,F3 378 | FXCHD F0, F3 379 | FXCHD F0, F2 380 | NOMOREBYTES: 381 | MOVL $0,R10 382 | FMOVD ·ALPHA130(SB), F0 383 | FADDD F4,F0 384 | FSUBD ·ALPHA130(SB), F0 385 | FSUBD F0,F4 386 | FMULD ·SCALE(SB), F0 387 | FMOVD ·ALPHA32(SB), F0 388 | FADDD F2,F0 389 | FSUBD ·ALPHA32(SB), F0 390 | FSUBD F0,F2 391 | FMOVD ·ALPHA64(SB), F0 392 | FADDD F4,F0 393 | FSUBD ·ALPHA64(SB), F0 394 | FSUBD F0,F4 395 | FMOVD ·ALPHA96(SB), F0 396 | FADDD F6,F0 397 | FSUBD ·ALPHA96(SB), F0 398 | FXCHD F0, F6 399 | FSUBD F6,F0 400 | FXCHD F0, F4 401 | FADDDP F0,F3 402 | FXCHD F0, F4 403 | FADDDP F0,F1 404 | FXCHD F0, F2 405 | FADDDP F0,F3 406 | FXCHD F0, F4 407 | FADDDP F0,F3 408 | FXCHD F0, F3 409 | FADDD ·HOFFSET0(SB), F0 410 | FXCHD F0, F3 411 | FADDD ·HOFFSET1(SB), F0 412 | FXCHD F0, F1 413 | FADDD ·HOFFSET2(SB), F0 414 | FXCHD F0, F2 415 | FADDD ·HOFFSET3(SB), F0 416 | FXCHD F0, F3 417 | FMOVDP F0, 104(SP) 418 | FMOVDP F0, 112(SP) 419 | FMOVDP F0, 120(SP) 420 | FMOVDP F0, 128(SP) 421 | MOVL 108(SP),DI 422 | ANDL $63,DI 423 | MOVL 116(SP),SI 424 | ANDL $63,SI 425 | MOVL 124(SP),DX 426 | ANDL $63,DX 427 | MOVL 132(SP),CX 428 | ANDL $63,CX 429 | MOVL 112(SP),R8 430 | ADDL DI,R8 431 | MOVQ R8,112(SP) 432 | MOVL 120(SP),DI 433 | ADCL SI,DI 434 | MOVQ DI,120(SP) 435 | MOVL 128(SP),DI 436 | ADCL DX,DI 437 | MOVQ DI,128(SP) 438 | MOVL R10,DI 439 | ADCL CX,DI 440 | MOVQ DI,136(SP) 441 | MOVQ $5,DI 442 | MOVL 104(SP),SI 443 | ADDL SI,DI 444 | MOVQ DI,104(SP) 445 | MOVL R10,DI 446 | MOVQ 112(SP),DX 447 | ADCL DX,DI 448 | MOVQ DI,112(SP) 449 | MOVL R10,DI 450 | MOVQ 120(SP),CX 451 | ADCL CX,DI 452 | MOVQ DI,120(SP) 453 | MOVL R10,DI 454 | MOVQ 128(SP),R8 455 | ADCL R8,DI 456 | MOVQ DI,128(SP) 457 | MOVQ $0XFFFFFFFC,DI 458 | MOVQ 136(SP),R9 459 | ADCL R9,DI 460 | SARL $16,DI 461 | MOVQ DI,R9 462 | XORL $0XFFFFFFFF,R9 463 | ANDQ DI,SI 464 | MOVQ 104(SP),AX 465 | ANDQ R9,AX 466 | ORQ AX,SI 467 | ANDQ DI,DX 468 | MOVQ 112(SP),AX 469 | ANDQ R9,AX 470 | ORQ AX,DX 471 | ANDQ DI,CX 472 | MOVQ 120(SP),AX 473 | ANDQ R9,AX 474 | ORQ AX,CX 475 | ANDQ DI,R8 476 | MOVQ 128(SP),DI 477 | ANDQ R9,DI 478 | ORQ DI,R8 479 | MOVQ 88(SP),DI 480 | MOVQ 96(SP),R9 481 | ADDL 16(R9),SI 482 | ADCL 20(R9),DX 483 | ADCL 24(R9),CX 484 | ADCL 28(R9),R8 485 | MOVL SI,0(DI) 486 | MOVL DX,4(DI) 487 | MOVL CX,8(DI) 488 | MOVL R8,12(DI) 489 | MOVQ 32(SP),R11 490 | MOVQ 40(SP),R12 491 | MOVQ 48(SP),R13 492 | MOVQ 56(SP),R14 493 | MOVQ 64(SP),R15 494 | MOVQ 72(SP),BX 495 | MOVQ 80(SP),BP 496 | MOVQ R11,SP 497 | RET 498 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/poly1305/poly1305_arm.s: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This code was translated into a form compatible with 5a from the public 6 | // domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305. 7 | 8 | // +build arm,!gccgo,!appengine 9 | 10 | DATA poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff 11 | DATA poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03 12 | DATA poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff 13 | DATA poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff 14 | DATA poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff 15 | GLOBL poly1305_init_constants_armv6<>(SB), 8, $20 16 | 17 | // Warning: the linker may use R11 to synthesize certain instructions. Please 18 | // take care and verify that no synthetic instructions use it. 19 | 20 | TEXT poly1305_init_ext_armv6<>(SB),4,$-4 21 | MOVM.DB.W [R4-R11], (R13) 22 | MOVM.IA.W (R1), [R2-R5] 23 | MOVW $poly1305_init_constants_armv6<>(SB), R7 24 | MOVW R2, R8 25 | MOVW R2>>26, R9 26 | MOVW R3>>20, g 27 | MOVW R4>>14, R11 28 | MOVW R5>>8, R12 29 | ORR R3<<6, R9, R9 30 | ORR R4<<12, g, g 31 | ORR R5<<18, R11, R11 32 | MOVM.IA (R7), [R2-R6] 33 | AND R8, R2, R2 34 | AND R9, R3, R3 35 | AND g, R4, R4 36 | AND R11, R5, R5 37 | AND R12, R6, R6 38 | MOVM.IA.W [R2-R6], (R0) 39 | EOR R2, R2, R2 40 | EOR R3, R3, R3 41 | EOR R4, R4, R4 42 | EOR R5, R5, R5 43 | EOR R6, R6, R6 44 | MOVM.IA.W [R2-R6], (R0) 45 | MOVM.IA.W (R1), [R2-R5] 46 | MOVM.IA [R2-R6], (R0) 47 | MOVM.IA.W (R13), [R4-R11] 48 | RET 49 | 50 | #define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \ 51 | MOVBU (offset+0)(Rsrc), Rtmp; \ 52 | MOVBU Rtmp, (offset+0)(Rdst); \ 53 | MOVBU (offset+1)(Rsrc), Rtmp; \ 54 | MOVBU Rtmp, (offset+1)(Rdst); \ 55 | MOVBU (offset+2)(Rsrc), Rtmp; \ 56 | MOVBU Rtmp, (offset+2)(Rdst); \ 57 | MOVBU (offset+3)(Rsrc), Rtmp; \ 58 | MOVBU Rtmp, (offset+3)(Rdst) 59 | 60 | TEXT poly1305_blocks_armv6<>(SB),4,$-4 61 | MOVM.DB.W [R4, R5, R6, R7, R8, R9, g, R11, R14], (R13) 62 | SUB $128, R13 63 | MOVW R0, 36(R13) 64 | MOVW R1, 40(R13) 65 | MOVW R2, 44(R13) 66 | MOVW R1, R14 67 | MOVW R2, R12 68 | MOVW 56(R0), R8 69 | WORD $0xe1180008 // TST R8, R8 not working see issue 5921 70 | EOR R6, R6, R6 71 | MOVW.EQ $(1<<24), R6 72 | MOVW R6, 32(R13) 73 | ADD $64, R13, g 74 | MOVM.IA (R0), [R0-R9] 75 | MOVM.IA [R0-R4], (g) 76 | CMP $16, R12 77 | BLO poly1305_blocks_armv6_done 78 | poly1305_blocks_armv6_mainloop: 79 | WORD $0xe31e0003 // TST R14, #3 not working see issue 5921 80 | BEQ poly1305_blocks_armv6_mainloop_aligned 81 | ADD $48, R13, g 82 | MOVW_UNALIGNED(R14, g, R0, 0) 83 | MOVW_UNALIGNED(R14, g, R0, 4) 84 | MOVW_UNALIGNED(R14, g, R0, 8) 85 | MOVW_UNALIGNED(R14, g, R0, 12) 86 | MOVM.IA (g), [R0-R3] 87 | ADD $16, R14 88 | B poly1305_blocks_armv6_mainloop_loaded 89 | poly1305_blocks_armv6_mainloop_aligned: 90 | MOVM.IA.W (R14), [R0-R3] 91 | poly1305_blocks_armv6_mainloop_loaded: 92 | MOVW R0>>26, g 93 | MOVW R1>>20, R11 94 | MOVW R2>>14, R12 95 | MOVW R14, 40(R13) 96 | MOVW R3>>8, R4 97 | ORR R1<<6, g, g 98 | ORR R2<<12, R11, R11 99 | ORR R3<<18, R12, R12 100 | BIC $0xfc000000, R0, R0 101 | BIC $0xfc000000, g, g 102 | MOVW 32(R13), R3 103 | BIC $0xfc000000, R11, R11 104 | BIC $0xfc000000, R12, R12 105 | ADD R0, R5, R5 106 | ADD g, R6, R6 107 | ORR R3, R4, R4 108 | ADD R11, R7, R7 109 | ADD $64, R13, R14 110 | ADD R12, R8, R8 111 | ADD R4, R9, R9 112 | MOVM.IA (R14), [R0-R4] 113 | MULLU R4, R5, (R11, g) 114 | MULLU R3, R5, (R14, R12) 115 | MULALU R3, R6, (R11, g) 116 | MULALU R2, R6, (R14, R12) 117 | MULALU R2, R7, (R11, g) 118 | MULALU R1, R7, (R14, R12) 119 | ADD R4<<2, R4, R4 120 | ADD R3<<2, R3, R3 121 | MULALU R1, R8, (R11, g) 122 | MULALU R0, R8, (R14, R12) 123 | MULALU R0, R9, (R11, g) 124 | MULALU R4, R9, (R14, R12) 125 | MOVW g, 24(R13) 126 | MOVW R11, 28(R13) 127 | MOVW R12, 16(R13) 128 | MOVW R14, 20(R13) 129 | MULLU R2, R5, (R11, g) 130 | MULLU R1, R5, (R14, R12) 131 | MULALU R1, R6, (R11, g) 132 | MULALU R0, R6, (R14, R12) 133 | MULALU R0, R7, (R11, g) 134 | MULALU R4, R7, (R14, R12) 135 | ADD R2<<2, R2, R2 136 | ADD R1<<2, R1, R1 137 | MULALU R4, R8, (R11, g) 138 | MULALU R3, R8, (R14, R12) 139 | MULALU R3, R9, (R11, g) 140 | MULALU R2, R9, (R14, R12) 141 | MOVW g, 8(R13) 142 | MOVW R11, 12(R13) 143 | MOVW R12, 0(R13) 144 | MOVW R14, w+4(SP) 145 | MULLU R0, R5, (R11, g) 146 | MULALU R4, R6, (R11, g) 147 | MULALU R3, R7, (R11, g) 148 | MULALU R2, R8, (R11, g) 149 | MULALU R1, R9, (R11, g) 150 | MOVM.IA (R13), [R0-R7] 151 | MOVW g>>26, R12 152 | MOVW R4>>26, R14 153 | ORR R11<<6, R12, R12 154 | ORR R5<<6, R14, R14 155 | BIC $0xfc000000, g, g 156 | BIC $0xfc000000, R4, R4 157 | ADD.S R12, R0, R0 158 | ADC $0, R1, R1 159 | ADD.S R14, R6, R6 160 | ADC $0, R7, R7 161 | MOVW R0>>26, R12 162 | MOVW R6>>26, R14 163 | ORR R1<<6, R12, R12 164 | ORR R7<<6, R14, R14 165 | BIC $0xfc000000, R0, R0 166 | BIC $0xfc000000, R6, R6 167 | ADD R14<<2, R14, R14 168 | ADD.S R12, R2, R2 169 | ADC $0, R3, R3 170 | ADD R14, g, g 171 | MOVW R2>>26, R12 172 | MOVW g>>26, R14 173 | ORR R3<<6, R12, R12 174 | BIC $0xfc000000, g, R5 175 | BIC $0xfc000000, R2, R7 176 | ADD R12, R4, R4 177 | ADD R14, R0, R0 178 | MOVW R4>>26, R12 179 | BIC $0xfc000000, R4, R8 180 | ADD R12, R6, R9 181 | MOVW w+44(SP), R12 182 | MOVW w+40(SP), R14 183 | MOVW R0, R6 184 | CMP $32, R12 185 | SUB $16, R12, R12 186 | MOVW R12, 44(R13) 187 | BHS poly1305_blocks_armv6_mainloop 188 | poly1305_blocks_armv6_done: 189 | MOVW 36(R13), R12 190 | MOVW R5, 20(R12) 191 | MOVW R6, 24(R12) 192 | MOVW R7, 28(R12) 193 | MOVW R8, 32(R12) 194 | MOVW R9, 36(R12) 195 | ADD $128, R13, R13 196 | MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, g, R11, R14] 197 | RET 198 | 199 | #define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \ 200 | MOVBU.P 1(Rsrc), Rtmp; \ 201 | MOVBU.P Rtmp, 1(Rdst); \ 202 | MOVBU.P 1(Rsrc), Rtmp; \ 203 | MOVBU.P Rtmp, 1(Rdst) 204 | 205 | #define MOVWP_UNALIGNED(Rsrc, Rdst, Rtmp) \ 206 | MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \ 207 | MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) 208 | 209 | TEXT poly1305_finish_ext_armv6<>(SB),4,$-4 210 | MOVM.DB.W [R4, R5, R6, R7, R8, R9, g, R11, R14], (R13) 211 | SUB $16, R13, R13 212 | MOVW R0, R5 213 | MOVW R1, R6 214 | MOVW R2, R7 215 | MOVW R3, R8 216 | AND.S R2, R2, R2 217 | BEQ poly1305_finish_ext_armv6_noremaining 218 | EOR R0, R0 219 | MOVW R13, R9 220 | MOVW R0, 0(R13) 221 | MOVW R0, 4(R13) 222 | MOVW R0, 8(R13) 223 | MOVW R0, 12(R13) 224 | WORD $0xe3110003 // TST R1, #3 not working see issue 5921 225 | BEQ poly1305_finish_ext_armv6_aligned 226 | WORD $0xe3120008 // TST R2, #8 not working see issue 5921 227 | BEQ poly1305_finish_ext_armv6_skip8 228 | MOVWP_UNALIGNED(R1, R9, g) 229 | MOVWP_UNALIGNED(R1, R9, g) 230 | poly1305_finish_ext_armv6_skip8: 231 | WORD $0xe3120004 // TST $4, R2 not working see issue 5921 232 | BEQ poly1305_finish_ext_armv6_skip4 233 | MOVWP_UNALIGNED(R1, R9, g) 234 | poly1305_finish_ext_armv6_skip4: 235 | WORD $0xe3120002 // TST $2, R2 not working see issue 5921 236 | BEQ poly1305_finish_ext_armv6_skip2 237 | MOVHUP_UNALIGNED(R1, R9, g) 238 | B poly1305_finish_ext_armv6_skip2 239 | poly1305_finish_ext_armv6_aligned: 240 | WORD $0xe3120008 // TST R2, #8 not working see issue 5921 241 | BEQ poly1305_finish_ext_armv6_skip8_aligned 242 | MOVM.IA.W (R1), [g-R11] 243 | MOVM.IA.W [g-R11], (R9) 244 | poly1305_finish_ext_armv6_skip8_aligned: 245 | WORD $0xe3120004 // TST $4, R2 not working see issue 5921 246 | BEQ poly1305_finish_ext_armv6_skip4_aligned 247 | MOVW.P 4(R1), g 248 | MOVW.P g, 4(R9) 249 | poly1305_finish_ext_armv6_skip4_aligned: 250 | WORD $0xe3120002 // TST $2, R2 not working see issue 5921 251 | BEQ poly1305_finish_ext_armv6_skip2 252 | MOVHU.P 2(R1), g 253 | MOVH.P g, 2(R9) 254 | poly1305_finish_ext_armv6_skip2: 255 | WORD $0xe3120001 // TST $1, R2 not working see issue 5921 256 | BEQ poly1305_finish_ext_armv6_skip1 257 | MOVBU.P 1(R1), g 258 | MOVBU.P g, 1(R9) 259 | poly1305_finish_ext_armv6_skip1: 260 | MOVW $1, R11 261 | MOVBU R11, 0(R9) 262 | MOVW R11, 56(R5) 263 | MOVW R5, R0 264 | MOVW R13, R1 265 | MOVW $16, R2 266 | BL poly1305_blocks_armv6<>(SB) 267 | poly1305_finish_ext_armv6_noremaining: 268 | MOVW 20(R5), R0 269 | MOVW 24(R5), R1 270 | MOVW 28(R5), R2 271 | MOVW 32(R5), R3 272 | MOVW 36(R5), R4 273 | MOVW R4>>26, R12 274 | BIC $0xfc000000, R4, R4 275 | ADD R12<<2, R12, R12 276 | ADD R12, R0, R0 277 | MOVW R0>>26, R12 278 | BIC $0xfc000000, R0, R0 279 | ADD R12, R1, R1 280 | MOVW R1>>26, R12 281 | BIC $0xfc000000, R1, R1 282 | ADD R12, R2, R2 283 | MOVW R2>>26, R12 284 | BIC $0xfc000000, R2, R2 285 | ADD R12, R3, R3 286 | MOVW R3>>26, R12 287 | BIC $0xfc000000, R3, R3 288 | ADD R12, R4, R4 289 | ADD $5, R0, R6 290 | MOVW R6>>26, R12 291 | BIC $0xfc000000, R6, R6 292 | ADD R12, R1, R7 293 | MOVW R7>>26, R12 294 | BIC $0xfc000000, R7, R7 295 | ADD R12, R2, g 296 | MOVW g>>26, R12 297 | BIC $0xfc000000, g, g 298 | ADD R12, R3, R11 299 | MOVW $-(1<<26), R12 300 | ADD R11>>26, R12, R12 301 | BIC $0xfc000000, R11, R11 302 | ADD R12, R4, R14 303 | MOVW R14>>31, R12 304 | SUB $1, R12 305 | AND R12, R6, R6 306 | AND R12, R7, R7 307 | AND R12, g, g 308 | AND R12, R11, R11 309 | AND R12, R14, R14 310 | MVN R12, R12 311 | AND R12, R0, R0 312 | AND R12, R1, R1 313 | AND R12, R2, R2 314 | AND R12, R3, R3 315 | AND R12, R4, R4 316 | ORR R6, R0, R0 317 | ORR R7, R1, R1 318 | ORR g, R2, R2 319 | ORR R11, R3, R3 320 | ORR R14, R4, R4 321 | ORR R1<<26, R0, R0 322 | MOVW R1>>6, R1 323 | ORR R2<<20, R1, R1 324 | MOVW R2>>12, R2 325 | ORR R3<<14, R2, R2 326 | MOVW R3>>18, R3 327 | ORR R4<<8, R3, R3 328 | MOVW 40(R5), R6 329 | MOVW 44(R5), R7 330 | MOVW 48(R5), g 331 | MOVW 52(R5), R11 332 | ADD.S R6, R0, R0 333 | ADC.S R7, R1, R1 334 | ADC.S g, R2, R2 335 | ADC.S R11, R3, R3 336 | MOVM.IA [R0-R3], (R8) 337 | MOVW R5, R12 338 | EOR R0, R0, R0 339 | EOR R1, R1, R1 340 | EOR R2, R2, R2 341 | EOR R3, R3, R3 342 | EOR R4, R4, R4 343 | EOR R5, R5, R5 344 | EOR R6, R6, R6 345 | EOR R7, R7, R7 346 | MOVM.IA.W [R0-R7], (R12) 347 | MOVM.IA [R0-R7], (R12) 348 | ADD $16, R13, R13 349 | MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, g, R11, R14] 350 | RET 351 | 352 | // func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key) 353 | TEXT ·poly1305_auth_armv6(SB),0,$280-16 354 | MOVW out+0(FP), R4 355 | MOVW m+4(FP), R5 356 | MOVW mlen+8(FP), R6 357 | MOVW key+12(FP), R7 358 | 359 | MOVW R13, R8 360 | BIC $63, R13 361 | SUB $64, R13, R13 362 | MOVW R13, R0 363 | MOVW R7, R1 364 | BL poly1305_init_ext_armv6<>(SB) 365 | BIC.S $15, R6, R2 366 | BEQ poly1305_auth_armv6_noblocks 367 | MOVW R13, R0 368 | MOVW R5, R1 369 | ADD R2, R5, R5 370 | SUB R2, R6, R6 371 | BL poly1305_blocks_armv6<>(SB) 372 | poly1305_auth_armv6_noblocks: 373 | MOVW R13, R0 374 | MOVW R5, R1 375 | MOVW R6, R2 376 | MOVW R4, R3 377 | BL poly1305_finish_ext_armv6<>(SB) 378 | MOVW R8, R13 379 | RET 380 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/poly1305/poly1305_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package poly1305 6 | 7 | import ( 8 | "bytes" 9 | "testing" 10 | "unsafe" 11 | ) 12 | 13 | var testData = []struct { 14 | in, k, correct []byte 15 | }{ 16 | { 17 | []byte("Hello world!"), 18 | []byte("this is 32-byte key for Poly1305"), 19 | []byte{0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0}, 20 | }, 21 | { 22 | make([]byte, 32), 23 | []byte("this is 32-byte key for Poly1305"), 24 | []byte{0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07}, 25 | }, 26 | { 27 | make([]byte, 2007), 28 | []byte("this is 32-byte key for Poly1305"), 29 | []byte{0xda, 0x84, 0xbc, 0xab, 0x02, 0x67, 0x6c, 0x38, 0xcd, 0xb0, 0x15, 0x60, 0x42, 0x74, 0xc2, 0xaa}, 30 | }, 31 | { 32 | make([]byte, 2007), 33 | make([]byte, 32), 34 | make([]byte, 16), 35 | }, 36 | } 37 | 38 | func testSum(t *testing.T, unaligned bool) { 39 | var out [16]byte 40 | var key [32]byte 41 | 42 | for i, v := range testData { 43 | in := v.in 44 | if unaligned { 45 | in = unalignBytes(in) 46 | } 47 | copy(key[:], v.k) 48 | Sum(&out, in, &key) 49 | if !bytes.Equal(out[:], v.correct) { 50 | t.Errorf("%d: expected %x, got %x", i, v.correct, out[:]) 51 | } 52 | } 53 | } 54 | 55 | func TestSum(t *testing.T) { testSum(t, false) } 56 | func TestSumUnaligned(t *testing.T) { testSum(t, true) } 57 | 58 | func benchmark(b *testing.B, size int, unaligned bool) { 59 | var out [16]byte 60 | var key [32]byte 61 | in := make([]byte, size) 62 | if unaligned { 63 | in = unalignBytes(in) 64 | } 65 | b.SetBytes(int64(len(in))) 66 | b.ResetTimer() 67 | for i := 0; i < b.N; i++ { 68 | Sum(&out, in, &key) 69 | } 70 | } 71 | 72 | func Benchmark64(b *testing.B) { benchmark(b, 64, false) } 73 | func Benchmark1K(b *testing.B) { benchmark(b, 1024, false) } 74 | func Benchmark64Unaligned(b *testing.B) { benchmark(b, 64, true) } 75 | func Benchmark1KUnaligned(b *testing.B) { benchmark(b, 1024, true) } 76 | 77 | func unalignBytes(in []byte) []byte { 78 | out := make([]byte, len(in)+1) 79 | if uintptr(unsafe.Pointer(&out[0]))&(unsafe.Alignof(uint32(0))-1) == 0 { 80 | out = out[1:] 81 | } else { 82 | out = out[:len(in)] 83 | } 84 | copy(out, in) 85 | return out 86 | } 87 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/poly1305/sum_amd64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build amd64,!gccgo,!appengine 6 | 7 | package poly1305 8 | 9 | // This function is implemented in poly1305_amd64.s 10 | 11 | //go:noescape 12 | 13 | func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]byte) 14 | 15 | // Sum generates an authenticator for m using a one-time key and puts the 16 | // 16-byte result into out. Authenticating two different messages with the same 17 | // key allows an attacker to forge messages at will. 18 | func Sum(out *[16]byte, m []byte, key *[32]byte) { 19 | var mPtr *byte 20 | if len(m) > 0 { 21 | mPtr = &m[0] 22 | } 23 | poly1305(out, mPtr, uint64(len(m)), key) 24 | } 25 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/poly1305/sum_arm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build arm,!gccgo,!appengine 6 | 7 | package poly1305 8 | 9 | // This function is implemented in poly1305_arm.s 10 | 11 | //go:noescape 12 | 13 | func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte) 14 | 15 | // Sum generates an authenticator for m using a one-time key and puts the 16 | // 16-byte result into out. Authenticating two different messages with the same 17 | // key allows an attacker to forge messages at will. 18 | func Sum(out *[16]byte, m []byte, key *[32]byte) { 19 | var mPtr *byte 20 | if len(m) > 0 { 21 | mPtr = &m[0] 22 | } 23 | poly1305_auth_armv6(out, mPtr, uint32(len(m)), key) 24 | } 25 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/hsalsa20.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package salsa provides low-level access to functions in the Salsa family. 6 | package salsa 7 | 8 | // Sigma is the Salsa20 constant for 256-bit keys. 9 | var Sigma = [16]byte{'e', 'x', 'p', 'a', 'n', 'd', ' ', '3', '2', '-', 'b', 'y', 't', 'e', ' ', 'k'} 10 | 11 | // HSalsa20 applies the HSalsa20 core function to a 16-byte input in, 32-byte 12 | // key k, and 16-byte constant c, and puts the result into the 32-byte array 13 | // out. 14 | func HSalsa20(out *[32]byte, in *[16]byte, k *[32]byte, c *[16]byte) { 15 | x0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24 16 | x1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24 17 | x2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24 18 | x3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24 19 | x4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24 20 | x5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24 21 | x6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 22 | x7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 23 | x8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 24 | x9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 25 | x10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24 26 | x11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24 27 | x12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24 28 | x13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24 29 | x14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24 30 | x15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24 31 | 32 | for i := 0; i < 20; i += 2 { 33 | u := x0 + x12 34 | x4 ^= u<<7 | u>>(32-7) 35 | u = x4 + x0 36 | x8 ^= u<<9 | u>>(32-9) 37 | u = x8 + x4 38 | x12 ^= u<<13 | u>>(32-13) 39 | u = x12 + x8 40 | x0 ^= u<<18 | u>>(32-18) 41 | 42 | u = x5 + x1 43 | x9 ^= u<<7 | u>>(32-7) 44 | u = x9 + x5 45 | x13 ^= u<<9 | u>>(32-9) 46 | u = x13 + x9 47 | x1 ^= u<<13 | u>>(32-13) 48 | u = x1 + x13 49 | x5 ^= u<<18 | u>>(32-18) 50 | 51 | u = x10 + x6 52 | x14 ^= u<<7 | u>>(32-7) 53 | u = x14 + x10 54 | x2 ^= u<<9 | u>>(32-9) 55 | u = x2 + x14 56 | x6 ^= u<<13 | u>>(32-13) 57 | u = x6 + x2 58 | x10 ^= u<<18 | u>>(32-18) 59 | 60 | u = x15 + x11 61 | x3 ^= u<<7 | u>>(32-7) 62 | u = x3 + x15 63 | x7 ^= u<<9 | u>>(32-9) 64 | u = x7 + x3 65 | x11 ^= u<<13 | u>>(32-13) 66 | u = x11 + x7 67 | x15 ^= u<<18 | u>>(32-18) 68 | 69 | u = x0 + x3 70 | x1 ^= u<<7 | u>>(32-7) 71 | u = x1 + x0 72 | x2 ^= u<<9 | u>>(32-9) 73 | u = x2 + x1 74 | x3 ^= u<<13 | u>>(32-13) 75 | u = x3 + x2 76 | x0 ^= u<<18 | u>>(32-18) 77 | 78 | u = x5 + x4 79 | x6 ^= u<<7 | u>>(32-7) 80 | u = x6 + x5 81 | x7 ^= u<<9 | u>>(32-9) 82 | u = x7 + x6 83 | x4 ^= u<<13 | u>>(32-13) 84 | u = x4 + x7 85 | x5 ^= u<<18 | u>>(32-18) 86 | 87 | u = x10 + x9 88 | x11 ^= u<<7 | u>>(32-7) 89 | u = x11 + x10 90 | x8 ^= u<<9 | u>>(32-9) 91 | u = x8 + x11 92 | x9 ^= u<<13 | u>>(32-13) 93 | u = x9 + x8 94 | x10 ^= u<<18 | u>>(32-18) 95 | 96 | u = x15 + x14 97 | x12 ^= u<<7 | u>>(32-7) 98 | u = x12 + x15 99 | x13 ^= u<<9 | u>>(32-9) 100 | u = x13 + x12 101 | x14 ^= u<<13 | u>>(32-13) 102 | u = x14 + x13 103 | x15 ^= u<<18 | u>>(32-18) 104 | } 105 | out[0] = byte(x0) 106 | out[1] = byte(x0 >> 8) 107 | out[2] = byte(x0 >> 16) 108 | out[3] = byte(x0 >> 24) 109 | 110 | out[4] = byte(x5) 111 | out[5] = byte(x5 >> 8) 112 | out[6] = byte(x5 >> 16) 113 | out[7] = byte(x5 >> 24) 114 | 115 | out[8] = byte(x10) 116 | out[9] = byte(x10 >> 8) 117 | out[10] = byte(x10 >> 16) 118 | out[11] = byte(x10 >> 24) 119 | 120 | out[12] = byte(x15) 121 | out[13] = byte(x15 >> 8) 122 | out[14] = byte(x15 >> 16) 123 | out[15] = byte(x15 >> 24) 124 | 125 | out[16] = byte(x6) 126 | out[17] = byte(x6 >> 8) 127 | out[18] = byte(x6 >> 16) 128 | out[19] = byte(x6 >> 24) 129 | 130 | out[20] = byte(x7) 131 | out[21] = byte(x7 >> 8) 132 | out[22] = byte(x7 >> 16) 133 | out[23] = byte(x7 >> 24) 134 | 135 | out[24] = byte(x8) 136 | out[25] = byte(x8 >> 8) 137 | out[26] = byte(x8 >> 16) 138 | out[27] = byte(x8 >> 24) 139 | 140 | out[28] = byte(x9) 141 | out[29] = byte(x9 >> 8) 142 | out[30] = byte(x9 >> 16) 143 | out[31] = byte(x9 >> 24) 144 | } 145 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa208.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package salsa 6 | 7 | // Core208 applies the Salsa20/8 core function to the 64-byte array in and puts 8 | // the result into the 64-byte array out. The input and output may be the same array. 9 | func Core208(out *[64]byte, in *[64]byte) { 10 | j0 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 11 | j1 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 12 | j2 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 13 | j3 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 14 | j4 := uint32(in[16]) | uint32(in[17])<<8 | uint32(in[18])<<16 | uint32(in[19])<<24 15 | j5 := uint32(in[20]) | uint32(in[21])<<8 | uint32(in[22])<<16 | uint32(in[23])<<24 16 | j6 := uint32(in[24]) | uint32(in[25])<<8 | uint32(in[26])<<16 | uint32(in[27])<<24 17 | j7 := uint32(in[28]) | uint32(in[29])<<8 | uint32(in[30])<<16 | uint32(in[31])<<24 18 | j8 := uint32(in[32]) | uint32(in[33])<<8 | uint32(in[34])<<16 | uint32(in[35])<<24 19 | j9 := uint32(in[36]) | uint32(in[37])<<8 | uint32(in[38])<<16 | uint32(in[39])<<24 20 | j10 := uint32(in[40]) | uint32(in[41])<<8 | uint32(in[42])<<16 | uint32(in[43])<<24 21 | j11 := uint32(in[44]) | uint32(in[45])<<8 | uint32(in[46])<<16 | uint32(in[47])<<24 22 | j12 := uint32(in[48]) | uint32(in[49])<<8 | uint32(in[50])<<16 | uint32(in[51])<<24 23 | j13 := uint32(in[52]) | uint32(in[53])<<8 | uint32(in[54])<<16 | uint32(in[55])<<24 24 | j14 := uint32(in[56]) | uint32(in[57])<<8 | uint32(in[58])<<16 | uint32(in[59])<<24 25 | j15 := uint32(in[60]) | uint32(in[61])<<8 | uint32(in[62])<<16 | uint32(in[63])<<24 26 | 27 | x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8 28 | x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15 29 | 30 | for i := 0; i < 8; i += 2 { 31 | u := x0 + x12 32 | x4 ^= u<<7 | u>>(32-7) 33 | u = x4 + x0 34 | x8 ^= u<<9 | u>>(32-9) 35 | u = x8 + x4 36 | x12 ^= u<<13 | u>>(32-13) 37 | u = x12 + x8 38 | x0 ^= u<<18 | u>>(32-18) 39 | 40 | u = x5 + x1 41 | x9 ^= u<<7 | u>>(32-7) 42 | u = x9 + x5 43 | x13 ^= u<<9 | u>>(32-9) 44 | u = x13 + x9 45 | x1 ^= u<<13 | u>>(32-13) 46 | u = x1 + x13 47 | x5 ^= u<<18 | u>>(32-18) 48 | 49 | u = x10 + x6 50 | x14 ^= u<<7 | u>>(32-7) 51 | u = x14 + x10 52 | x2 ^= u<<9 | u>>(32-9) 53 | u = x2 + x14 54 | x6 ^= u<<13 | u>>(32-13) 55 | u = x6 + x2 56 | x10 ^= u<<18 | u>>(32-18) 57 | 58 | u = x15 + x11 59 | x3 ^= u<<7 | u>>(32-7) 60 | u = x3 + x15 61 | x7 ^= u<<9 | u>>(32-9) 62 | u = x7 + x3 63 | x11 ^= u<<13 | u>>(32-13) 64 | u = x11 + x7 65 | x15 ^= u<<18 | u>>(32-18) 66 | 67 | u = x0 + x3 68 | x1 ^= u<<7 | u>>(32-7) 69 | u = x1 + x0 70 | x2 ^= u<<9 | u>>(32-9) 71 | u = x2 + x1 72 | x3 ^= u<<13 | u>>(32-13) 73 | u = x3 + x2 74 | x0 ^= u<<18 | u>>(32-18) 75 | 76 | u = x5 + x4 77 | x6 ^= u<<7 | u>>(32-7) 78 | u = x6 + x5 79 | x7 ^= u<<9 | u>>(32-9) 80 | u = x7 + x6 81 | x4 ^= u<<13 | u>>(32-13) 82 | u = x4 + x7 83 | x5 ^= u<<18 | u>>(32-18) 84 | 85 | u = x10 + x9 86 | x11 ^= u<<7 | u>>(32-7) 87 | u = x11 + x10 88 | x8 ^= u<<9 | u>>(32-9) 89 | u = x8 + x11 90 | x9 ^= u<<13 | u>>(32-13) 91 | u = x9 + x8 92 | x10 ^= u<<18 | u>>(32-18) 93 | 94 | u = x15 + x14 95 | x12 ^= u<<7 | u>>(32-7) 96 | u = x12 + x15 97 | x13 ^= u<<9 | u>>(32-9) 98 | u = x13 + x12 99 | x14 ^= u<<13 | u>>(32-13) 100 | u = x14 + x13 101 | x15 ^= u<<18 | u>>(32-18) 102 | } 103 | x0 += j0 104 | x1 += j1 105 | x2 += j2 106 | x3 += j3 107 | x4 += j4 108 | x5 += j5 109 | x6 += j6 110 | x7 += j7 111 | x8 += j8 112 | x9 += j9 113 | x10 += j10 114 | x11 += j11 115 | x12 += j12 116 | x13 += j13 117 | x14 += j14 118 | x15 += j15 119 | 120 | out[0] = byte(x0) 121 | out[1] = byte(x0 >> 8) 122 | out[2] = byte(x0 >> 16) 123 | out[3] = byte(x0 >> 24) 124 | 125 | out[4] = byte(x1) 126 | out[5] = byte(x1 >> 8) 127 | out[6] = byte(x1 >> 16) 128 | out[7] = byte(x1 >> 24) 129 | 130 | out[8] = byte(x2) 131 | out[9] = byte(x2 >> 8) 132 | out[10] = byte(x2 >> 16) 133 | out[11] = byte(x2 >> 24) 134 | 135 | out[12] = byte(x3) 136 | out[13] = byte(x3 >> 8) 137 | out[14] = byte(x3 >> 16) 138 | out[15] = byte(x3 >> 24) 139 | 140 | out[16] = byte(x4) 141 | out[17] = byte(x4 >> 8) 142 | out[18] = byte(x4 >> 16) 143 | out[19] = byte(x4 >> 24) 144 | 145 | out[20] = byte(x5) 146 | out[21] = byte(x5 >> 8) 147 | out[22] = byte(x5 >> 16) 148 | out[23] = byte(x5 >> 24) 149 | 150 | out[24] = byte(x6) 151 | out[25] = byte(x6 >> 8) 152 | out[26] = byte(x6 >> 16) 153 | out[27] = byte(x6 >> 24) 154 | 155 | out[28] = byte(x7) 156 | out[29] = byte(x7 >> 8) 157 | out[30] = byte(x7 >> 16) 158 | out[31] = byte(x7 >> 24) 159 | 160 | out[32] = byte(x8) 161 | out[33] = byte(x8 >> 8) 162 | out[34] = byte(x8 >> 16) 163 | out[35] = byte(x8 >> 24) 164 | 165 | out[36] = byte(x9) 166 | out[37] = byte(x9 >> 8) 167 | out[38] = byte(x9 >> 16) 168 | out[39] = byte(x9 >> 24) 169 | 170 | out[40] = byte(x10) 171 | out[41] = byte(x10 >> 8) 172 | out[42] = byte(x10 >> 16) 173 | out[43] = byte(x10 >> 24) 174 | 175 | out[44] = byte(x11) 176 | out[45] = byte(x11 >> 8) 177 | out[46] = byte(x11 >> 16) 178 | out[47] = byte(x11 >> 24) 179 | 180 | out[48] = byte(x12) 181 | out[49] = byte(x12 >> 8) 182 | out[50] = byte(x12 >> 16) 183 | out[51] = byte(x12 >> 24) 184 | 185 | out[52] = byte(x13) 186 | out[53] = byte(x13 >> 8) 187 | out[54] = byte(x13 >> 16) 188 | out[55] = byte(x13 >> 24) 189 | 190 | out[56] = byte(x14) 191 | out[57] = byte(x14 >> 8) 192 | out[58] = byte(x14 >> 16) 193 | out[59] = byte(x14 >> 24) 194 | 195 | out[60] = byte(x15) 196 | out[61] = byte(x15 >> 8) 197 | out[62] = byte(x15 >> 16) 198 | out[63] = byte(x15 >> 24) 199 | } 200 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa20_amd64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build amd64,!appengine,!gccgo 6 | 7 | package salsa 8 | 9 | // This function is implemented in salsa2020_amd64.s. 10 | 11 | //go:noescape 12 | 13 | func salsa2020XORKeyStream(out, in *byte, n uint64, nonce, key *byte) 14 | 15 | // XORKeyStream crypts bytes from in to out using the given key and counters. 16 | // In and out may be the same slice but otherwise should not overlap. Counter 17 | // contains the raw salsa20 counter bytes (both nonce and block counter). 18 | func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { 19 | if len(in) == 0 { 20 | return 21 | } 22 | salsa2020XORKeyStream(&out[0], &in[0], uint64(len(in)), &counter[0], &key[0]) 23 | } 24 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa20_ref.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !amd64 appengine gccgo 6 | 7 | package salsa 8 | 9 | const rounds = 20 10 | 11 | // core applies the Salsa20 core function to 16-byte input in, 32-byte key k, 12 | // and 16-byte constant c, and puts the result into 64-byte array out. 13 | func core(out *[64]byte, in *[16]byte, k *[32]byte, c *[16]byte) { 14 | j0 := uint32(c[0]) | uint32(c[1])<<8 | uint32(c[2])<<16 | uint32(c[3])<<24 15 | j1 := uint32(k[0]) | uint32(k[1])<<8 | uint32(k[2])<<16 | uint32(k[3])<<24 16 | j2 := uint32(k[4]) | uint32(k[5])<<8 | uint32(k[6])<<16 | uint32(k[7])<<24 17 | j3 := uint32(k[8]) | uint32(k[9])<<8 | uint32(k[10])<<16 | uint32(k[11])<<24 18 | j4 := uint32(k[12]) | uint32(k[13])<<8 | uint32(k[14])<<16 | uint32(k[15])<<24 19 | j5 := uint32(c[4]) | uint32(c[5])<<8 | uint32(c[6])<<16 | uint32(c[7])<<24 20 | j6 := uint32(in[0]) | uint32(in[1])<<8 | uint32(in[2])<<16 | uint32(in[3])<<24 21 | j7 := uint32(in[4]) | uint32(in[5])<<8 | uint32(in[6])<<16 | uint32(in[7])<<24 22 | j8 := uint32(in[8]) | uint32(in[9])<<8 | uint32(in[10])<<16 | uint32(in[11])<<24 23 | j9 := uint32(in[12]) | uint32(in[13])<<8 | uint32(in[14])<<16 | uint32(in[15])<<24 24 | j10 := uint32(c[8]) | uint32(c[9])<<8 | uint32(c[10])<<16 | uint32(c[11])<<24 25 | j11 := uint32(k[16]) | uint32(k[17])<<8 | uint32(k[18])<<16 | uint32(k[19])<<24 26 | j12 := uint32(k[20]) | uint32(k[21])<<8 | uint32(k[22])<<16 | uint32(k[23])<<24 27 | j13 := uint32(k[24]) | uint32(k[25])<<8 | uint32(k[26])<<16 | uint32(k[27])<<24 28 | j14 := uint32(k[28]) | uint32(k[29])<<8 | uint32(k[30])<<16 | uint32(k[31])<<24 29 | j15 := uint32(c[12]) | uint32(c[13])<<8 | uint32(c[14])<<16 | uint32(c[15])<<24 30 | 31 | x0, x1, x2, x3, x4, x5, x6, x7, x8 := j0, j1, j2, j3, j4, j5, j6, j7, j8 32 | x9, x10, x11, x12, x13, x14, x15 := j9, j10, j11, j12, j13, j14, j15 33 | 34 | for i := 0; i < rounds; i += 2 { 35 | u := x0 + x12 36 | x4 ^= u<<7 | u>>(32-7) 37 | u = x4 + x0 38 | x8 ^= u<<9 | u>>(32-9) 39 | u = x8 + x4 40 | x12 ^= u<<13 | u>>(32-13) 41 | u = x12 + x8 42 | x0 ^= u<<18 | u>>(32-18) 43 | 44 | u = x5 + x1 45 | x9 ^= u<<7 | u>>(32-7) 46 | u = x9 + x5 47 | x13 ^= u<<9 | u>>(32-9) 48 | u = x13 + x9 49 | x1 ^= u<<13 | u>>(32-13) 50 | u = x1 + x13 51 | x5 ^= u<<18 | u>>(32-18) 52 | 53 | u = x10 + x6 54 | x14 ^= u<<7 | u>>(32-7) 55 | u = x14 + x10 56 | x2 ^= u<<9 | u>>(32-9) 57 | u = x2 + x14 58 | x6 ^= u<<13 | u>>(32-13) 59 | u = x6 + x2 60 | x10 ^= u<<18 | u>>(32-18) 61 | 62 | u = x15 + x11 63 | x3 ^= u<<7 | u>>(32-7) 64 | u = x3 + x15 65 | x7 ^= u<<9 | u>>(32-9) 66 | u = x7 + x3 67 | x11 ^= u<<13 | u>>(32-13) 68 | u = x11 + x7 69 | x15 ^= u<<18 | u>>(32-18) 70 | 71 | u = x0 + x3 72 | x1 ^= u<<7 | u>>(32-7) 73 | u = x1 + x0 74 | x2 ^= u<<9 | u>>(32-9) 75 | u = x2 + x1 76 | x3 ^= u<<13 | u>>(32-13) 77 | u = x3 + x2 78 | x0 ^= u<<18 | u>>(32-18) 79 | 80 | u = x5 + x4 81 | x6 ^= u<<7 | u>>(32-7) 82 | u = x6 + x5 83 | x7 ^= u<<9 | u>>(32-9) 84 | u = x7 + x6 85 | x4 ^= u<<13 | u>>(32-13) 86 | u = x4 + x7 87 | x5 ^= u<<18 | u>>(32-18) 88 | 89 | u = x10 + x9 90 | x11 ^= u<<7 | u>>(32-7) 91 | u = x11 + x10 92 | x8 ^= u<<9 | u>>(32-9) 93 | u = x8 + x11 94 | x9 ^= u<<13 | u>>(32-13) 95 | u = x9 + x8 96 | x10 ^= u<<18 | u>>(32-18) 97 | 98 | u = x15 + x14 99 | x12 ^= u<<7 | u>>(32-7) 100 | u = x12 + x15 101 | x13 ^= u<<9 | u>>(32-9) 102 | u = x13 + x12 103 | x14 ^= u<<13 | u>>(32-13) 104 | u = x14 + x13 105 | x15 ^= u<<18 | u>>(32-18) 106 | } 107 | x0 += j0 108 | x1 += j1 109 | x2 += j2 110 | x3 += j3 111 | x4 += j4 112 | x5 += j5 113 | x6 += j6 114 | x7 += j7 115 | x8 += j8 116 | x9 += j9 117 | x10 += j10 118 | x11 += j11 119 | x12 += j12 120 | x13 += j13 121 | x14 += j14 122 | x15 += j15 123 | 124 | out[0] = byte(x0) 125 | out[1] = byte(x0 >> 8) 126 | out[2] = byte(x0 >> 16) 127 | out[3] = byte(x0 >> 24) 128 | 129 | out[4] = byte(x1) 130 | out[5] = byte(x1 >> 8) 131 | out[6] = byte(x1 >> 16) 132 | out[7] = byte(x1 >> 24) 133 | 134 | out[8] = byte(x2) 135 | out[9] = byte(x2 >> 8) 136 | out[10] = byte(x2 >> 16) 137 | out[11] = byte(x2 >> 24) 138 | 139 | out[12] = byte(x3) 140 | out[13] = byte(x3 >> 8) 141 | out[14] = byte(x3 >> 16) 142 | out[15] = byte(x3 >> 24) 143 | 144 | out[16] = byte(x4) 145 | out[17] = byte(x4 >> 8) 146 | out[18] = byte(x4 >> 16) 147 | out[19] = byte(x4 >> 24) 148 | 149 | out[20] = byte(x5) 150 | out[21] = byte(x5 >> 8) 151 | out[22] = byte(x5 >> 16) 152 | out[23] = byte(x5 >> 24) 153 | 154 | out[24] = byte(x6) 155 | out[25] = byte(x6 >> 8) 156 | out[26] = byte(x6 >> 16) 157 | out[27] = byte(x6 >> 24) 158 | 159 | out[28] = byte(x7) 160 | out[29] = byte(x7 >> 8) 161 | out[30] = byte(x7 >> 16) 162 | out[31] = byte(x7 >> 24) 163 | 164 | out[32] = byte(x8) 165 | out[33] = byte(x8 >> 8) 166 | out[34] = byte(x8 >> 16) 167 | out[35] = byte(x8 >> 24) 168 | 169 | out[36] = byte(x9) 170 | out[37] = byte(x9 >> 8) 171 | out[38] = byte(x9 >> 16) 172 | out[39] = byte(x9 >> 24) 173 | 174 | out[40] = byte(x10) 175 | out[41] = byte(x10 >> 8) 176 | out[42] = byte(x10 >> 16) 177 | out[43] = byte(x10 >> 24) 178 | 179 | out[44] = byte(x11) 180 | out[45] = byte(x11 >> 8) 181 | out[46] = byte(x11 >> 16) 182 | out[47] = byte(x11 >> 24) 183 | 184 | out[48] = byte(x12) 185 | out[49] = byte(x12 >> 8) 186 | out[50] = byte(x12 >> 16) 187 | out[51] = byte(x12 >> 24) 188 | 189 | out[52] = byte(x13) 190 | out[53] = byte(x13 >> 8) 191 | out[54] = byte(x13 >> 16) 192 | out[55] = byte(x13 >> 24) 193 | 194 | out[56] = byte(x14) 195 | out[57] = byte(x14 >> 8) 196 | out[58] = byte(x14 >> 16) 197 | out[59] = byte(x14 >> 24) 198 | 199 | out[60] = byte(x15) 200 | out[61] = byte(x15 >> 8) 201 | out[62] = byte(x15 >> 16) 202 | out[63] = byte(x15 >> 24) 203 | } 204 | 205 | // XORKeyStream crypts bytes from in to out using the given key and counters. 206 | // In and out may be the same slice but otherwise should not overlap. Counter 207 | // contains the raw salsa20 counter bytes (both nonce and block counter). 208 | func XORKeyStream(out, in []byte, counter *[16]byte, key *[32]byte) { 209 | var block [64]byte 210 | var counterCopy [16]byte 211 | copy(counterCopy[:], counter[:]) 212 | 213 | for len(in) >= 64 { 214 | core(&block, &counterCopy, key, &Sigma) 215 | for i, x := range block { 216 | out[i] = in[i] ^ x 217 | } 218 | u := uint32(1) 219 | for i := 8; i < 16; i++ { 220 | u += uint32(counterCopy[i]) 221 | counterCopy[i] = byte(u) 222 | u >>= 8 223 | } 224 | in = in[64:] 225 | out = out[64:] 226 | } 227 | 228 | if len(in) > 0 { 229 | core(&block, &counterCopy, key, &Sigma) 230 | for i, v := range in { 231 | out[i] = v ^ block[i] 232 | } 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/crypto/salsa20/salsa/salsa_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package salsa 6 | 7 | import "testing" 8 | 9 | func TestCore208(t *testing.T) { 10 | in := [64]byte{ 11 | 0x7e, 0x87, 0x9a, 0x21, 0x4f, 0x3e, 0xc9, 0x86, 12 | 0x7c, 0xa9, 0x40, 0xe6, 0x41, 0x71, 0x8f, 0x26, 13 | 0xba, 0xee, 0x55, 0x5b, 0x8c, 0x61, 0xc1, 0xb5, 14 | 0x0d, 0xf8, 0x46, 0x11, 0x6d, 0xcd, 0x3b, 0x1d, 15 | 0xee, 0x24, 0xf3, 0x19, 0xdf, 0x9b, 0x3d, 0x85, 16 | 0x14, 0x12, 0x1e, 0x4b, 0x5a, 0xc5, 0xaa, 0x32, 17 | 0x76, 0x02, 0x1d, 0x29, 0x09, 0xc7, 0x48, 0x29, 18 | 0xed, 0xeb, 0xc6, 0x8d, 0xb8, 0xb8, 0xc2, 0x5e} 19 | 20 | out := [64]byte{ 21 | 0xa4, 0x1f, 0x85, 0x9c, 0x66, 0x08, 0xcc, 0x99, 22 | 0x3b, 0x81, 0xca, 0xcb, 0x02, 0x0c, 0xef, 0x05, 23 | 0x04, 0x4b, 0x21, 0x81, 0xa2, 0xfd, 0x33, 0x7d, 24 | 0xfd, 0x7b, 0x1c, 0x63, 0x96, 0x68, 0x2f, 0x29, 25 | 0xb4, 0x39, 0x31, 0x68, 0xe3, 0xc9, 0xe6, 0xbc, 26 | 0xfe, 0x6b, 0xc5, 0xb7, 0xa0, 0x6d, 0x96, 0xba, 27 | 0xe4, 0x24, 0xcc, 0x10, 0x2c, 0x91, 0x74, 0x5c, 28 | 0x24, 0xad, 0x67, 0x3d, 0xc7, 0x61, 0x8f, 0x81, 29 | } 30 | 31 | Core208(&in, &in) 32 | if in != out { 33 | t.Errorf("expected %x, got %x", out, in) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/net/websocket/client.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "bufio" 9 | "crypto/tls" 10 | "io" 11 | "net" 12 | "net/http" 13 | "net/url" 14 | ) 15 | 16 | // DialError is an error that occurs while dialling a websocket server. 17 | type DialError struct { 18 | *Config 19 | Err error 20 | } 21 | 22 | func (e *DialError) Error() string { 23 | return "websocket.Dial " + e.Config.Location.String() + ": " + e.Err.Error() 24 | } 25 | 26 | // NewConfig creates a new WebSocket config for client connection. 27 | func NewConfig(server, origin string) (config *Config, err error) { 28 | config = new(Config) 29 | config.Version = ProtocolVersionHybi13 30 | config.Location, err = url.ParseRequestURI(server) 31 | if err != nil { 32 | return 33 | } 34 | config.Origin, err = url.ParseRequestURI(origin) 35 | if err != nil { 36 | return 37 | } 38 | config.Header = http.Header(make(map[string][]string)) 39 | return 40 | } 41 | 42 | // NewClient creates a new WebSocket client connection over rwc. 43 | func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err error) { 44 | br := bufio.NewReader(rwc) 45 | bw := bufio.NewWriter(rwc) 46 | err = hybiClientHandshake(config, br, bw) 47 | if err != nil { 48 | return 49 | } 50 | buf := bufio.NewReadWriter(br, bw) 51 | ws = newHybiClientConn(config, buf, rwc) 52 | return 53 | } 54 | 55 | // Dial opens a new client connection to a WebSocket. 56 | func Dial(url_, protocol, origin string) (ws *Conn, err error) { 57 | config, err := NewConfig(url_, origin) 58 | if err != nil { 59 | return nil, err 60 | } 61 | if protocol != "" { 62 | config.Protocol = []string{protocol} 63 | } 64 | return DialConfig(config) 65 | } 66 | 67 | var portMap = map[string]string{ 68 | "ws": "80", 69 | "wss": "443", 70 | } 71 | 72 | func parseAuthority(location *url.URL) string { 73 | if _, ok := portMap[location.Scheme]; ok { 74 | if _, _, err := net.SplitHostPort(location.Host); err != nil { 75 | return net.JoinHostPort(location.Host, portMap[location.Scheme]) 76 | } 77 | } 78 | return location.Host 79 | } 80 | 81 | // DialConfig opens a new client connection to a WebSocket with a config. 82 | func DialConfig(config *Config) (ws *Conn, err error) { 83 | var client net.Conn 84 | if config.Location == nil { 85 | return nil, &DialError{config, ErrBadWebSocketLocation} 86 | } 87 | if config.Origin == nil { 88 | return nil, &DialError{config, ErrBadWebSocketOrigin} 89 | } 90 | switch config.Location.Scheme { 91 | case "ws": 92 | client, err = net.Dial("tcp", parseAuthority(config.Location)) 93 | 94 | case "wss": 95 | client, err = tls.Dial("tcp", parseAuthority(config.Location), config.TlsConfig) 96 | 97 | default: 98 | err = ErrBadScheme 99 | } 100 | if err != nil { 101 | goto Error 102 | } 103 | 104 | ws, err = NewClient(config, client) 105 | if err != nil { 106 | client.Close() 107 | goto Error 108 | } 109 | return 110 | 111 | Error: 112 | return nil, &DialError{config, err} 113 | } 114 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/net/websocket/exampledial_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket_test 6 | 7 | import ( 8 | "fmt" 9 | "log" 10 | 11 | "golang.org/x/net/websocket" 12 | ) 13 | 14 | // This example demonstrates a trivial client. 15 | func ExampleDial() { 16 | origin := "http://localhost/" 17 | url := "ws://localhost:12345/ws" 18 | ws, err := websocket.Dial(url, "", origin) 19 | if err != nil { 20 | log.Fatal(err) 21 | } 22 | if _, err := ws.Write([]byte("hello, world!\n")); err != nil { 23 | log.Fatal(err) 24 | } 25 | var msg = make([]byte, 512) 26 | var n int 27 | if n, err = ws.Read(msg); err != nil { 28 | log.Fatal(err) 29 | } 30 | fmt.Printf("Received: %s.\n", msg[:n]) 31 | } 32 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/net/websocket/examplehandler_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket_test 6 | 7 | import ( 8 | "io" 9 | "net/http" 10 | 11 | "golang.org/x/net/websocket" 12 | ) 13 | 14 | // Echo the data received on the WebSocket. 15 | func EchoServer(ws *websocket.Conn) { 16 | io.Copy(ws, ws) 17 | } 18 | 19 | // This example demonstrates a trivial echo server. 20 | func ExampleHandler() { 21 | http.Handle("/echo", websocket.Handler(EchoServer)) 22 | err := http.ListenAndServe(":12345", nil) 23 | if err != nil { 24 | panic("ListenAndServe: " + err.Error()) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/net/websocket/server.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "bufio" 9 | "fmt" 10 | "io" 11 | "net/http" 12 | ) 13 | 14 | func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Request, config *Config, handshake func(*Config, *http.Request) error) (conn *Conn, err error) { 15 | var hs serverHandshaker = &hybiServerHandshaker{Config: config} 16 | code, err := hs.ReadHandshake(buf.Reader, req) 17 | if err == ErrBadWebSocketVersion { 18 | fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code)) 19 | fmt.Fprintf(buf, "Sec-WebSocket-Version: %s\r\n", SupportedProtocolVersion) 20 | buf.WriteString("\r\n") 21 | buf.WriteString(err.Error()) 22 | buf.Flush() 23 | return 24 | } 25 | if err != nil { 26 | fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code)) 27 | buf.WriteString("\r\n") 28 | buf.WriteString(err.Error()) 29 | buf.Flush() 30 | return 31 | } 32 | if handshake != nil { 33 | err = handshake(config, req) 34 | if err != nil { 35 | code = http.StatusForbidden 36 | fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code)) 37 | buf.WriteString("\r\n") 38 | buf.Flush() 39 | return 40 | } 41 | } 42 | err = hs.AcceptHandshake(buf.Writer) 43 | if err != nil { 44 | code = http.StatusBadRequest 45 | fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code)) 46 | buf.WriteString("\r\n") 47 | buf.Flush() 48 | return 49 | } 50 | conn = hs.NewServerConn(buf, rwc, req) 51 | return 52 | } 53 | 54 | // Server represents a server of a WebSocket. 55 | type Server struct { 56 | // Config is a WebSocket configuration for new WebSocket connection. 57 | Config 58 | 59 | // Handshake is an optional function in WebSocket handshake. 60 | // For example, you can check, or don't check Origin header. 61 | // Another example, you can select config.Protocol. 62 | Handshake func(*Config, *http.Request) error 63 | 64 | // Handler handles a WebSocket connection. 65 | Handler 66 | } 67 | 68 | // ServeHTTP implements the http.Handler interface for a WebSocket 69 | func (s Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { 70 | s.serveWebSocket(w, req) 71 | } 72 | 73 | func (s Server) serveWebSocket(w http.ResponseWriter, req *http.Request) { 74 | rwc, buf, err := w.(http.Hijacker).Hijack() 75 | if err != nil { 76 | panic("Hijack failed: " + err.Error()) 77 | } 78 | // The server should abort the WebSocket connection if it finds 79 | // the client did not send a handshake that matches with protocol 80 | // specification. 81 | defer rwc.Close() 82 | conn, err := newServerConn(rwc, buf, req, &s.Config, s.Handshake) 83 | if err != nil { 84 | return 85 | } 86 | if conn == nil { 87 | panic("unexpected nil conn") 88 | } 89 | s.Handler(conn) 90 | } 91 | 92 | // Handler is a simple interface to a WebSocket browser client. 93 | // It checks if Origin header is valid URL by default. 94 | // You might want to verify websocket.Conn.Config().Origin in the func. 95 | // If you use Server instead of Handler, you could call websocket.Origin and 96 | // check the origin in your Handshake func. So, if you want to accept 97 | // non-browser clients, which do not send an Origin header, set a 98 | // Server.Handshake that does not check the origin. 99 | type Handler func(*Conn) 100 | 101 | func checkOrigin(config *Config, req *http.Request) (err error) { 102 | config.Origin, err = Origin(config, req) 103 | if err == nil && config.Origin == nil { 104 | return fmt.Errorf("null origin") 105 | } 106 | return err 107 | } 108 | 109 | // ServeHTTP implements the http.Handler interface for a WebSocket 110 | func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { 111 | s := Server{Handler: h, Handshake: checkOrigin} 112 | s.serveWebSocket(w, req) 113 | } 114 | -------------------------------------------------------------------------------- /Godeps/_workspace/src/golang.org/x/net/websocket/websocket.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package websocket implements a client and server for the WebSocket protocol 6 | // as specified in RFC 6455. 7 | package websocket 8 | 9 | import ( 10 | "bufio" 11 | "crypto/tls" 12 | "encoding/json" 13 | "errors" 14 | "io" 15 | "io/ioutil" 16 | "net" 17 | "net/http" 18 | "net/url" 19 | "sync" 20 | "time" 21 | ) 22 | 23 | const ( 24 | ProtocolVersionHybi13 = 13 25 | ProtocolVersionHybi = ProtocolVersionHybi13 26 | SupportedProtocolVersion = "13" 27 | 28 | ContinuationFrame = 0 29 | TextFrame = 1 30 | BinaryFrame = 2 31 | CloseFrame = 8 32 | PingFrame = 9 33 | PongFrame = 10 34 | UnknownFrame = 255 35 | ) 36 | 37 | // ProtocolError represents WebSocket protocol errors. 38 | type ProtocolError struct { 39 | ErrorString string 40 | } 41 | 42 | func (err *ProtocolError) Error() string { return err.ErrorString } 43 | 44 | var ( 45 | ErrBadProtocolVersion = &ProtocolError{"bad protocol version"} 46 | ErrBadScheme = &ProtocolError{"bad scheme"} 47 | ErrBadStatus = &ProtocolError{"bad status"} 48 | ErrBadUpgrade = &ProtocolError{"missing or bad upgrade"} 49 | ErrBadWebSocketOrigin = &ProtocolError{"missing or bad WebSocket-Origin"} 50 | ErrBadWebSocketLocation = &ProtocolError{"missing or bad WebSocket-Location"} 51 | ErrBadWebSocketProtocol = &ProtocolError{"missing or bad WebSocket-Protocol"} 52 | ErrBadWebSocketVersion = &ProtocolError{"missing or bad WebSocket Version"} 53 | ErrChallengeResponse = &ProtocolError{"mismatch challenge/response"} 54 | ErrBadFrame = &ProtocolError{"bad frame"} 55 | ErrBadFrameBoundary = &ProtocolError{"not on frame boundary"} 56 | ErrNotWebSocket = &ProtocolError{"not websocket protocol"} 57 | ErrBadRequestMethod = &ProtocolError{"bad method"} 58 | ErrNotSupported = &ProtocolError{"not supported"} 59 | ) 60 | 61 | // Addr is an implementation of net.Addr for WebSocket. 62 | type Addr struct { 63 | *url.URL 64 | } 65 | 66 | // Network returns the network type for a WebSocket, "websocket". 67 | func (addr *Addr) Network() string { return "websocket" } 68 | 69 | // Config is a WebSocket configuration 70 | type Config struct { 71 | // A WebSocket server address. 72 | Location *url.URL 73 | 74 | // A Websocket client origin. 75 | Origin *url.URL 76 | 77 | // WebSocket subprotocols. 78 | Protocol []string 79 | 80 | // WebSocket protocol version. 81 | Version int 82 | 83 | // TLS config for secure WebSocket (wss). 84 | TlsConfig *tls.Config 85 | 86 | // Additional header fields to be sent in WebSocket opening handshake. 87 | Header http.Header 88 | 89 | handshakeData map[string]string 90 | } 91 | 92 | // serverHandshaker is an interface to handle WebSocket server side handshake. 93 | type serverHandshaker interface { 94 | // ReadHandshake reads handshake request message from client. 95 | // Returns http response code and error if any. 96 | ReadHandshake(buf *bufio.Reader, req *http.Request) (code int, err error) 97 | 98 | // AcceptHandshake accepts the client handshake request and sends 99 | // handshake response back to client. 100 | AcceptHandshake(buf *bufio.Writer) (err error) 101 | 102 | // NewServerConn creates a new WebSocket connection. 103 | NewServerConn(buf *bufio.ReadWriter, rwc io.ReadWriteCloser, request *http.Request) (conn *Conn) 104 | } 105 | 106 | // frameReader is an interface to read a WebSocket frame. 107 | type frameReader interface { 108 | // Reader is to read payload of the frame. 109 | io.Reader 110 | 111 | // PayloadType returns payload type. 112 | PayloadType() byte 113 | 114 | // HeaderReader returns a reader to read header of the frame. 115 | HeaderReader() io.Reader 116 | 117 | // TrailerReader returns a reader to read trailer of the frame. 118 | // If it returns nil, there is no trailer in the frame. 119 | TrailerReader() io.Reader 120 | 121 | // Len returns total length of the frame, including header and trailer. 122 | Len() int 123 | } 124 | 125 | // frameReaderFactory is an interface to creates new frame reader. 126 | type frameReaderFactory interface { 127 | NewFrameReader() (r frameReader, err error) 128 | } 129 | 130 | // frameWriter is an interface to write a WebSocket frame. 131 | type frameWriter interface { 132 | // Writer is to write payload of the frame. 133 | io.WriteCloser 134 | } 135 | 136 | // frameWriterFactory is an interface to create new frame writer. 137 | type frameWriterFactory interface { 138 | NewFrameWriter(payloadType byte) (w frameWriter, err error) 139 | } 140 | 141 | type frameHandler interface { 142 | HandleFrame(frame frameReader) (r frameReader, err error) 143 | WriteClose(status int) (err error) 144 | } 145 | 146 | // Conn represents a WebSocket connection. 147 | type Conn struct { 148 | config *Config 149 | request *http.Request 150 | 151 | buf *bufio.ReadWriter 152 | rwc io.ReadWriteCloser 153 | 154 | rio sync.Mutex 155 | frameReaderFactory 156 | frameReader 157 | 158 | wio sync.Mutex 159 | frameWriterFactory 160 | 161 | frameHandler 162 | PayloadType byte 163 | defaultCloseStatus int 164 | } 165 | 166 | // Read implements the io.Reader interface: 167 | // it reads data of a frame from the WebSocket connection. 168 | // if msg is not large enough for the frame data, it fills the msg and next Read 169 | // will read the rest of the frame data. 170 | // it reads Text frame or Binary frame. 171 | func (ws *Conn) Read(msg []byte) (n int, err error) { 172 | ws.rio.Lock() 173 | defer ws.rio.Unlock() 174 | again: 175 | if ws.frameReader == nil { 176 | frame, err := ws.frameReaderFactory.NewFrameReader() 177 | if err != nil { 178 | return 0, err 179 | } 180 | ws.frameReader, err = ws.frameHandler.HandleFrame(frame) 181 | if err != nil { 182 | return 0, err 183 | } 184 | if ws.frameReader == nil { 185 | goto again 186 | } 187 | } 188 | n, err = ws.frameReader.Read(msg) 189 | if err == io.EOF { 190 | if trailer := ws.frameReader.TrailerReader(); trailer != nil { 191 | io.Copy(ioutil.Discard, trailer) 192 | } 193 | ws.frameReader = nil 194 | goto again 195 | } 196 | return n, err 197 | } 198 | 199 | // Write implements the io.Writer interface: 200 | // it writes data as a frame to the WebSocket connection. 201 | func (ws *Conn) Write(msg []byte) (n int, err error) { 202 | ws.wio.Lock() 203 | defer ws.wio.Unlock() 204 | w, err := ws.frameWriterFactory.NewFrameWriter(ws.PayloadType) 205 | if err != nil { 206 | return 0, err 207 | } 208 | n, err = w.Write(msg) 209 | w.Close() 210 | if err != nil { 211 | return n, err 212 | } 213 | return n, err 214 | } 215 | 216 | // Close implements the io.Closer interface. 217 | func (ws *Conn) Close() error { 218 | err := ws.frameHandler.WriteClose(ws.defaultCloseStatus) 219 | err1 := ws.rwc.Close() 220 | if err != nil { 221 | return err 222 | } 223 | return err1 224 | } 225 | 226 | func (ws *Conn) IsClientConn() bool { return ws.request == nil } 227 | func (ws *Conn) IsServerConn() bool { return ws.request != nil } 228 | 229 | // LocalAddr returns the WebSocket Origin for the connection for client, or 230 | // the WebSocket location for server. 231 | func (ws *Conn) LocalAddr() net.Addr { 232 | if ws.IsClientConn() { 233 | return &Addr{ws.config.Origin} 234 | } 235 | return &Addr{ws.config.Location} 236 | } 237 | 238 | // RemoteAddr returns the WebSocket location for the connection for client, or 239 | // the Websocket Origin for server. 240 | func (ws *Conn) RemoteAddr() net.Addr { 241 | if ws.IsClientConn() { 242 | return &Addr{ws.config.Location} 243 | } 244 | return &Addr{ws.config.Origin} 245 | } 246 | 247 | var errSetDeadline = errors.New("websocket: cannot set deadline: not using a net.Conn") 248 | 249 | // SetDeadline sets the connection's network read & write deadlines. 250 | func (ws *Conn) SetDeadline(t time.Time) error { 251 | if conn, ok := ws.rwc.(net.Conn); ok { 252 | return conn.SetDeadline(t) 253 | } 254 | return errSetDeadline 255 | } 256 | 257 | // SetReadDeadline sets the connection's network read deadline. 258 | func (ws *Conn) SetReadDeadline(t time.Time) error { 259 | if conn, ok := ws.rwc.(net.Conn); ok { 260 | return conn.SetReadDeadline(t) 261 | } 262 | return errSetDeadline 263 | } 264 | 265 | // SetWriteDeadline sets the connection's network write deadline. 266 | func (ws *Conn) SetWriteDeadline(t time.Time) error { 267 | if conn, ok := ws.rwc.(net.Conn); ok { 268 | return conn.SetWriteDeadline(t) 269 | } 270 | return errSetDeadline 271 | } 272 | 273 | // Config returns the WebSocket config. 274 | func (ws *Conn) Config() *Config { return ws.config } 275 | 276 | // Request returns the http request upgraded to the WebSocket. 277 | // It is nil for client side. 278 | func (ws *Conn) Request() *http.Request { return ws.request } 279 | 280 | // Codec represents a symmetric pair of functions that implement a codec. 281 | type Codec struct { 282 | Marshal func(v interface{}) (data []byte, payloadType byte, err error) 283 | Unmarshal func(data []byte, payloadType byte, v interface{}) (err error) 284 | } 285 | 286 | // Send sends v marshaled by cd.Marshal as single frame to ws. 287 | func (cd Codec) Send(ws *Conn, v interface{}) (err error) { 288 | data, payloadType, err := cd.Marshal(v) 289 | if err != nil { 290 | return err 291 | } 292 | ws.wio.Lock() 293 | defer ws.wio.Unlock() 294 | w, err := ws.frameWriterFactory.NewFrameWriter(payloadType) 295 | if err != nil { 296 | return err 297 | } 298 | _, err = w.Write(data) 299 | w.Close() 300 | return err 301 | } 302 | 303 | // Receive receives single frame from ws, unmarshaled by cd.Unmarshal and stores in v. 304 | func (cd Codec) Receive(ws *Conn, v interface{}) (err error) { 305 | ws.rio.Lock() 306 | defer ws.rio.Unlock() 307 | if ws.frameReader != nil { 308 | _, err = io.Copy(ioutil.Discard, ws.frameReader) 309 | if err != nil { 310 | return err 311 | } 312 | ws.frameReader = nil 313 | } 314 | again: 315 | frame, err := ws.frameReaderFactory.NewFrameReader() 316 | if err != nil { 317 | return err 318 | } 319 | frame, err = ws.frameHandler.HandleFrame(frame) 320 | if err != nil { 321 | return err 322 | } 323 | if frame == nil { 324 | goto again 325 | } 326 | payloadType := frame.PayloadType() 327 | data, err := ioutil.ReadAll(frame) 328 | if err != nil { 329 | return err 330 | } 331 | return cd.Unmarshal(data, payloadType, v) 332 | } 333 | 334 | func marshal(v interface{}) (msg []byte, payloadType byte, err error) { 335 | switch data := v.(type) { 336 | case string: 337 | return []byte(data), TextFrame, nil 338 | case []byte: 339 | return data, BinaryFrame, nil 340 | } 341 | return nil, UnknownFrame, ErrNotSupported 342 | } 343 | 344 | func unmarshal(msg []byte, payloadType byte, v interface{}) (err error) { 345 | switch data := v.(type) { 346 | case *string: 347 | *data = string(msg) 348 | return nil 349 | case *[]byte: 350 | *data = msg 351 | return nil 352 | } 353 | return ErrNotSupported 354 | } 355 | 356 | /* 357 | Message is a codec to send/receive text/binary data in a frame on WebSocket connection. 358 | To send/receive text frame, use string type. 359 | To send/receive binary frame, use []byte type. 360 | 361 | Trivial usage: 362 | 363 | import "websocket" 364 | 365 | // receive text frame 366 | var message string 367 | websocket.Message.Receive(ws, &message) 368 | 369 | // send text frame 370 | message = "hello" 371 | websocket.Message.Send(ws, message) 372 | 373 | // receive binary frame 374 | var data []byte 375 | websocket.Message.Receive(ws, &data) 376 | 377 | // send binary frame 378 | data = []byte{0, 1, 2} 379 | websocket.Message.Send(ws, data) 380 | 381 | */ 382 | var Message = Codec{marshal, unmarshal} 383 | 384 | func jsonMarshal(v interface{}) (msg []byte, payloadType byte, err error) { 385 | msg, err = json.Marshal(v) 386 | return msg, TextFrame, err 387 | } 388 | 389 | func jsonUnmarshal(msg []byte, payloadType byte, v interface{}) (err error) { 390 | return json.Unmarshal(msg, v) 391 | } 392 | 393 | /* 394 | JSON is a codec to send/receive JSON data in a frame from a WebSocket connection. 395 | 396 | Trivial usage: 397 | 398 | import "websocket" 399 | 400 | type T struct { 401 | Msg string 402 | Count int 403 | } 404 | 405 | // receive JSON type T 406 | var data T 407 | websocket.JSON.Receive(ws, &data) 408 | 409 | // send JSON type T 410 | websocket.JSON.Send(ws, data) 411 | */ 412 | var JSON = Codec{jsonMarshal, jsonUnmarshal} 413 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | MAKEFILE_DIR=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) 2 | 3 | all: run 4 | 5 | build: 6 | docker build -t tox-crawler $(MAKEFILE_DIR) 7 | 8 | ifeq ($(BIND_ASSETS), 1) 9 | ASSETS_MOUNT=-v $(MAKEFILE_DIR)/server:/go/src/github.com/vikstrous/tox-crawler/server 10 | else 11 | ASSETS_MOUNT= 12 | endif 13 | 14 | run: build 15 | docker run --rm $(ASSETS_MOUNT) -v $(MAKEFILE_DIR)/data:/go/src/github.com/vikstrous/tox-crawler/data -p 80:7071 tox-crawler 16 | 17 | daemon: build 18 | docker run --name tox-crawler -d -p 80:7071 --restart always -v $(MAKEFILE_DIR)/data:/go/src/github.com/vikstrous/tox-crawler/data tox-crawler 19 | 20 | publish: 21 | docker build -t vikstrous/tox-crawler $(MAKEFILE_DIR) 22 | docker push vikstrous/tox-crawler 23 | 24 | deploy: 25 | ssh root@tox.viktorstanchev.com docker pull vikstrous/tox-crawler '&&' docker rm -f tox-crawler '&&' docker run --name tox-crawler -d -p 80:7071 --restart always -v /root/data:/go/src/github.com/vikstrous/tox-crawler/data vikstrous/tox-crawler 26 | 27 | .PHONY: all build run push 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tox Crawler 2 | 3 | This project is a crawler of the tox network. It's built in Go using the [gotox](https://github.com/vikstrous/gotox) library. 4 | 5 | To deploy: 6 | 7 | ``` 8 | docker run --name tox-crawler -d -p 80:7071 --restart always -v $(pwd)/data:/go/src/github.com/vikstrous/tox-crawler/data vikstrous/tox-crawler 9 | ``` 10 | 11 | Example of a graphs it can produce right now: 12 | 13 | ![screenshot](https://raw.githubusercontent.com/vikstrous/tox-crawler/master/screenshot.png) 14 | 15 | ![screenshot](https://raw.githubusercontent.com/vikstrous/tox-crawler/master/screenshot2.png) 16 | -------------------------------------------------------------------------------- /crawler/crawler.go: -------------------------------------------------------------------------------- 1 | package crawler 2 | 3 | import ( 4 | "crypto/rand" 5 | "fmt" 6 | "log" 7 | "math" 8 | "sync" 9 | "time" 10 | 11 | "github.com/vikstrous/gotox" 12 | "github.com/vikstrous/gotox/dht" 13 | ) 14 | 15 | type PeerInfo struct { 16 | dht.DHTPeer 17 | NumRequests int 18 | } 19 | 20 | // Crawler implements receive 21 | type Crawler struct { 22 | dht.Transport 23 | // this holds all nodes discovered 24 | AllPeersMutex sync.Mutex 25 | AllPeers map[[gotox.PublicKeySize]byte]PeerInfo 26 | doneChan chan struct{} 27 | } 28 | 29 | func New() (*Crawler, error) { 30 | id, err := dht.GenerateIdentity() 31 | if err != nil { 32 | return nil, err 33 | } 34 | transport, err := dht.NewUDPTransport(id) 35 | if err != nil { 36 | return nil, err 37 | } 38 | s := Crawler{ 39 | Transport: transport, 40 | AllPeers: make(map[[gotox.PublicKeySize]byte]PeerInfo), 41 | doneChan: make(chan struct{}), 42 | } 43 | 44 | go s.Receive() 45 | 46 | go s.pingerTask() 47 | 48 | return &s, nil 49 | } 50 | 51 | func (s *Crawler) Wait() { 52 | <-s.doneChan 53 | } 54 | 55 | func (s *Crawler) Crawl() []dht.DHTPeer { 56 | go s.Listen() 57 | s.Wait() 58 | peers := []dht.DHTPeer{} 59 | for _, peerInfo := range s.AllPeers { 60 | peers = append(peers, peerInfo.DHTPeer) 61 | } 62 | return peers 63 | } 64 | 65 | func (s *Crawler) pingerTask() { 66 | for { 67 | // XXX: figure out the "right" interval for this 68 | numPeers := len(s.AllPeers) 69 | duration := time.Duration(uint64(math.Log(float64(numPeers)))) * 200 70 | s.AllPeersMutex.Lock() 71 | done := true 72 | for _, neighbour := range s.AllPeers { 73 | // crawl only ipv4 74 | if neighbour.Addr.IP.To4() != nil && neighbour.NumRequests < 10 { 75 | done = false 76 | err := s.Transport.Send(&dht.GetNodes{ 77 | RequestedNodeID: &neighbour.PublicKey, 78 | }, &neighbour.DHTPeer) 79 | if err != nil { 80 | log.Println(err) 81 | } 82 | randomPK := [gotox.PublicKeySize]byte{} 83 | rand.Read(randomPK[:]) 84 | err = s.Transport.Send(&dht.GetNodes{ 85 | RequestedNodeID: &randomPK, 86 | }, &neighbour.DHTPeer) 87 | if err != nil { 88 | log.Println(err) 89 | } 90 | neighbour.NumRequests++ 91 | s.AllPeers[neighbour.PublicKey] = neighbour 92 | } 93 | } 94 | s.AllPeersMutex.Unlock() 95 | time.Sleep(duration * time.Millisecond) 96 | if numPeers == 0 { 97 | for _, server := range dht.DhtServerList { 98 | err := s.Send(&dht.GetNodes{ 99 | RequestedNodeID: &server.PublicKey, 100 | }, &server) 101 | if err != nil { 102 | fmt.Printf("error contacting bootstap node %v %s\n", server, err) 103 | } 104 | } 105 | time.Sleep(time.Second) 106 | } else { 107 | if done { 108 | s.Transport.Stop() 109 | close(s.doneChan) 110 | return 111 | } 112 | } 113 | } 114 | } 115 | 116 | func (s *Crawler) Receive() { 117 | for { 118 | message, ok := <-s.Transport.DataChan() 119 | if !ok { 120 | return 121 | } 122 | switch payload := message.Packet.Payload.(type) { 123 | case *dht.GetNodesReply: 124 | // There are only 4 replies 125 | s.AllPeersMutex.Lock() 126 | for _, node := range payload.Nodes { 127 | peer, found := s.AllPeers[node.PublicKey] 128 | // prefer ipv4 129 | if !found { 130 | s.AllPeers[node.PublicKey] = PeerInfo{DHTPeer: dht.DHTPeer{node.PublicKey, node.Addr}} 131 | } else { 132 | if peer.Addr.IP.To4() == nil && node.Addr.IP.To4() != nil { 133 | s.AllPeers[node.PublicKey] = PeerInfo{DHTPeer: dht.DHTPeer{node.PublicKey, node.Addr}} 134 | } 135 | } 136 | } 137 | s.AllPeersMutex.Unlock() 138 | default: 139 | //fmt.Printf("Internal error. Failed to handle payload of parsed packet. %d\n", pp.Payload.Kind()) 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vikstrous/tox-crawler/6ee847d4bf250060a43c5241127e90dfd5914659/data/.gitkeep -------------------------------------------------------------------------------- /main/crawl/crawl.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/vikstrous/tox-crawler/crawler" 7 | ) 8 | 9 | func main() { 10 | crawl, err := crawler.New() 11 | if err != nil { 12 | fmt.Printf("Failed to create server %s.\n", err) 13 | return 14 | } 15 | 16 | peers := crawl.Crawl() 17 | 18 | fmt.Printf("total: %d\n", len(peers)) 19 | } 20 | -------------------------------------------------------------------------------- /main/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "log" 8 | "net" 9 | "net/http" 10 | "sync" 11 | "time" 12 | 13 | "github.com/oschwald/maxminddb-golang" 14 | "github.com/vikstrous/gotox/dht" 15 | "github.com/vikstrous/tox-crawler/crawler" 16 | "golang.org/x/net/websocket" 17 | ) 18 | 19 | const DataFile = "data/data.json" 20 | const CountryCountsFile = "data/peers.json" 21 | const GeoIPFile = "./GeoIP.dat" 22 | const MaxDatapoints = 14000 23 | 24 | type Result struct { 25 | Time time.Time `json:"time"` 26 | Number int `json:"number"` 27 | } 28 | 29 | type Stats struct { 30 | NumbersList []Result `json:"numbers_list"` 31 | CountryCounts map[string]int `json:"country_counts"` 32 | } 33 | 34 | type Crawler struct { 35 | Mut sync.Mutex 36 | Results []Result 37 | ChMut sync.Mutex 38 | ChResults []chan struct{} 39 | GeoIP *maxminddb.Reader 40 | Counts map[string]int 41 | } 42 | 43 | func NewCrawler() *Crawler { 44 | return &Crawler{} 45 | } 46 | 47 | func (c *Crawler) OneCrawl() []dht.DHTPeer { 48 | crawl, err := crawler.New() 49 | if err != nil { 50 | fmt.Printf("Failed to create server %s.\n", err) 51 | return nil 52 | } 53 | 54 | return crawl.Crawl() 55 | } 56 | 57 | type mmCountry struct { 58 | Country struct { 59 | Names map[string]string `maxminddb:"names"` 60 | } `maxminddb:"country"` 61 | } 62 | 63 | func (c *Crawler) SaveState() { 64 | content, err := json.Marshal(c.Results) 65 | if err != nil { 66 | log.Printf("Error building json: %s", err) 67 | } 68 | log.Printf("Saving data...") 69 | err = ioutil.WriteFile(DataFile, content, 0644) 70 | if err != nil { 71 | log.Printf("Error writing data: %s", err) 72 | } 73 | log.Printf("Saved data...") 74 | content, err = json.Marshal(c.Counts) 75 | if err != nil { 76 | log.Printf("Error building json: %s", err) 77 | } 78 | log.Printf("Saving country counts...") 79 | err = ioutil.WriteFile(CountryCountsFile, content, 0644) 80 | if err != nil { 81 | log.Printf("Error writing data: %s", err) 82 | } 83 | log.Printf("Saved country counts...") 84 | } 85 | 86 | func (c *Crawler) Crawl() { 87 | for { 88 | log.Printf("Crawling...") 89 | peers := c.OneCrawl() 90 | numNodes := len(peers) 91 | log.Printf("Found %d nodes", numNodes) 92 | 93 | // if we have a geoip database, use it 94 | counts := map[string]int{} 95 | if c.GeoIP != nil { 96 | for _, peer := range peers { 97 | var record mmCountry 98 | err := c.GeoIP.Lookup(peer.Addr.IP, &record) 99 | if err != nil { 100 | log.Printf("Error reading from geoip database: %s", err) 101 | } 102 | counts[record.Country.Names["en"]] += 1 103 | } 104 | } 105 | 106 | c.Mut.Lock() 107 | // update graph 108 | c.Results = append(c.Results, Result{time.Now(), numNodes}) 109 | if len(c.Results) > MaxDatapoints { 110 | c.Results = c.Results[1:] 111 | } 112 | c.Counts = counts 113 | 114 | c.SaveState() 115 | c.Mut.Unlock() 116 | 117 | // notify listeners that we added a new entry 118 | c.ChMut.Lock() 119 | log.Printf("Notifying %d websocket clients", len(c.ChResults)) 120 | for _, ch := range c.ChResults { 121 | close(ch) 122 | } 123 | c.ChResults = [](chan struct{}){} 124 | c.ChMut.Unlock() 125 | 126 | // slow down our crawling interval to avoid using too much bandwidth 127 | log.Printf("Taking a nap until next interval") 128 | time.Sleep(5 * time.Minute) 129 | } 130 | } 131 | 132 | func (c *Crawler) statsHandler(ws *websocket.Conn) { 133 | c.Mut.Lock() 134 | json.NewEncoder(ws).Encode(Stats{c.Results, c.Counts}) 135 | c.Mut.Unlock() 136 | 137 | // if a message we receive exceeds 2000 bytes, it'll be broken up and could 138 | // trigger more than one reply 139 | buf := make([]byte, 2000) 140 | 141 | ch := make(chan struct{}) 142 | c.ChMut.Lock() 143 | c.ChResults = append(c.ChResults, ch) 144 | c.ChMut.Unlock() 145 | 146 | for { 147 | select { 148 | case <-ch: 149 | // if we have data, send it 150 | c.Mut.Lock() 151 | json.NewEncoder(ws).Encode(Stats{c.Results, c.Counts}) 152 | c.Mut.Unlock() 153 | 154 | ch = make(chan struct{}) 155 | c.ChMut.Lock() 156 | c.ChResults = append(c.ChResults, ch) 157 | c.ChMut.Unlock() 158 | default: 159 | // else, keep waiting; process messages from the user 160 | ws.SetReadDeadline(time.Now().Add(time.Second)) 161 | // if we receive any data, 162 | _, err := ws.Read(buf) 163 | if err == nil { 164 | // if we have data, send it 165 | c.Mut.Lock() 166 | json.NewEncoder(ws).Encode(Stats{c.Results, c.Counts}) 167 | c.Mut.Unlock() 168 | } else if opErr, ok := err.(*net.OpError); !ok || !opErr.Timeout() { 169 | // non-timeout network error -> close the connection 170 | ws.Close() 171 | return 172 | } 173 | } 174 | } 175 | } 176 | 177 | func main() { 178 | 179 | c := NewCrawler() 180 | content, err := ioutil.ReadFile(CountryCountsFile) 181 | if err != nil { 182 | c.Counts = map[string]int{} 183 | } else { 184 | err = json.Unmarshal(content, &c.Counts) 185 | if err != nil { 186 | panic("Failed to load country stats: " + err.Error()) 187 | } else { 188 | log.Printf("Loaded info on %d countries", len(c.Counts)) 189 | } 190 | } 191 | content, err = ioutil.ReadFile(DataFile) 192 | if err != nil { 193 | c.Results = make([]Result, 0, MaxDatapoints) 194 | } else { 195 | err = json.Unmarshal(content, &c.Results) 196 | if err != nil { 197 | panic("Failed to load data: " + err.Error()) 198 | } else { 199 | log.Printf("Loaded %d results", len(c.Results)) 200 | } 201 | } 202 | 203 | gi, err := maxminddb.Open("GeoIP.dat") 204 | if err != nil { 205 | fmt.Printf("Could not open GeoIP database. Running in mapless mode.\n") 206 | } 207 | defer gi.Close() 208 | c.GeoIP = gi 209 | 210 | go c.Crawl() 211 | 212 | http.Handle("/stats", websocket.Handler(c.statsHandler)) 213 | http.Handle("/", http.FileServer(http.Dir("server"))) 214 | err = http.ListenAndServe(":7071", nil) 215 | if err != nil { 216 | panic("ListenAndServe: " + err.Error()) 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vikstrous/tox-crawler/6ee847d4bf250060a43c5241127e90dfd5914659/screenshot.png -------------------------------------------------------------------------------- /screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vikstrous/tox-crawler/6ee847d4bf250060a43c5241127e90dfd5914659/screenshot2.png -------------------------------------------------------------------------------- /server/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Tox Crawler 6 | 7 | 8 | 9 |

Tox Crawler

10 |

This project crawls the Tox network every 5 minutes or so and graphs the number of nodes over time.

11 |

Source code: https://github.com/vikstrous/tox-crawler

12 |

The graph is automatically refreshed when new data arrives using websockets. The server is configured to collect 14000 data points before it starts discarding data. This is about a megabyte per refresh (every 5 minutes). The crawler is tracking only ipv4 nodes right now. We count each tox id as one node even if we receive multiple addresses for it. If the same address hosts more than one tox id, we count them as separate.

13 |
14 |
15 |
16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /server/lib/topojson.v1.min.js: -------------------------------------------------------------------------------- 1 | topojson=function(){function t(t,e){function n(e){var n=t.arcs[e],r=n[0],o=[0,0];return n.forEach(function(t){o[0]+=t[0],o[1]+=t[1]}),[r,o]}var r={},o={},a={};e.forEach(function(t){var e=n(t);(r[e[0]]||(r[e[0]]=[])).push(t),(r[e[1]]||(r[e[1]]=[])).push(~t)}),e.forEach(function(t){var e,r,i=n(t),u=i[0],c=i[1];if(e=a[u])if(delete a[e.end],e.push(t),e.end=c,r=o[c]){delete o[r.start];var s=r===e?e:e.concat(r);o[s.start=e.start]=a[s.end=r.end]=s}else if(r=a[c]){delete o[r.start],delete a[r.end];var s=e.concat(r.map(function(t){return~t}).reverse());o[s.start=e.start]=a[s.end=r.start]=s}else o[e.start]=a[e.end]=e;else if(e=o[c])if(delete o[e.start],e.unshift(t),e.start=u,r=a[u]){delete a[r.end];var f=r===e?e:r.concat(e);o[f.start=r.start]=a[f.end=e.end]=f}else if(r=o[u]){delete o[r.start],delete a[r.end];var f=r.map(function(t){return~t}).reverse().concat(e);o[f.start=r.end]=a[f.end=e.end]=f}else o[e.start]=a[e.end]=e;else if(e=o[u])if(delete o[e.start],e.unshift(~t),e.start=c,r=a[c]){delete a[r.end];var f=r===e?e:r.concat(e);o[f.start=r.start]=a[f.end=e.end]=f}else if(r=o[c]){delete o[r.start],delete a[r.end];var f=r.map(function(t){return~t}).reverse().concat(e);o[f.start=r.end]=a[f.end=e.end]=f}else o[e.start]=a[e.end]=e;else if(e=a[c])if(delete a[e.end],e.push(~t),e.end=u,r=a[u]){delete o[r.start];var s=r===e?e:e.concat(r);o[s.start=e.start]=a[s.end=r.end]=s}else if(r=o[u]){delete o[r.start],delete a[r.end];var s=e.concat(r.map(function(t){return~t}).reverse());o[s.start=e.start]=a[s.end=r.start]=s}else o[e.start]=a[e.end]=e;else e=[t],o[e.start=u]=a[e.end=c]=e});var i=[];for(var u in a)i.push(a[u]);return i}function e(e,n,r){function a(t){0>t&&(t=~t),(l[t]||(l[t]=[])).push(f)}function i(t){t.forEach(a)}function u(t){t.forEach(i)}function c(t){t.type==="GeometryCollection"?t.geometries.forEach(c):t.type in d&&(f=t,d[t.type](t.arcs))}var s=[];if(arguments.length>1){var f,l=[],d={LineString:i,MultiLineString:u,Polygon:u,MultiPolygon:function(t){t.forEach(u)}};c(n),l.forEach(arguments.length<3?function(t,e){s.push(e)}:function(t,e){r(t[0],t[t.length-1])&&s.push(e)})}else for(var p=0,h=e.arcs.length;h>p;++p)s.push(p);return o(e,{type:"MultiLineString",arcs:t(e,s)})}function n(t,e){return e.type==="GeometryCollection"?{type:"FeatureCollection",features:e.geometries.map(function(e){return r(t,e)})}:r(t,e)}function r(t,e){var n={type:"Feature",id:e.id,properties:e.properties||{},geometry:o(t,e)};return e.id==null&&delete n.id,n}function o(t,e){function n(t,e){e.length&&e.pop();for(var n,r=h[0>t?~t:t],o=0,i=r.length,u=0,c=0;i>o;++o)e.push([(u+=(n=r[o])[0])*f+d,(c+=n[1])*l+p]);0>t&&a(e,i)}function r(t){return[t[0]*f+d,t[1]*l+p]}function o(t){for(var e=[],r=0,o=t.length;o>r;++r)n(t[r],e);return e.length<2&&e.push(e[0]),e}function i(t){for(var e=o(t);e.length<4;)e.push(e[0]);return e}function u(t){return t.map(i)}function c(t){var e=t.type;return"GeometryCollection"===e?{type:e,geometries:t.geometries.map(c)}:e in v?{type:e,coordinates:v[e](t)}:null}var s=t.transform,f=s.scale[0],l=s.scale[1],d=s.translate[0],p=s.translate[1],h=t.arcs,v={Point:function(t){return r(t.coordinates)},MultiPoint:function(t){return t.coordinates.map(r)},LineString:function(t){return o(t.arcs)},MultiLineString:function(t){return t.arcs.map(o)},Polygon:function(t){return u(t.arcs)},MultiPolygon:function(t){return t.arcs.map(u)}};return c(e)}function a(t,e){for(var n,r=t.length,o=r-e;o<--r;)n=t[o],t[o++]=t[r],t[r]=n}function i(t,e){for(var n=0,r=t.length;r>n;){var o=n+r>>>1;t[o]t&&(t=~t);var n=o[t]||(o[t]=[]);n[e]||(n.forEach(function(t){var n,r;r=i(n=a[e],t),n[r]!==t&&n.splice(r,0,t),r=i(n=a[t],e),n[r]!==e&&n.splice(r,0,e)}),n[e]=e)})}function n(t,n){t.forEach(function(t){e(t,n)})}function r(t,e){t.type==="GeometryCollection"?t.geometries.forEach(function(t){r(t,e)}):t.type in u&&u[t.type](t.arcs,e)}var o=[],a=t.map(function(){return[]}),u={LineString:e,MultiLineString:n,Polygon:n,MultiPolygon:function(t,e){t.forEach(function(t){n(t,e)})}};return t.forEach(r),a}return{version:"1.1.2",mesh:e,feature:n,neighbors:u}}(); -------------------------------------------------------------------------------- /server/main.css: -------------------------------------------------------------------------------- 1 | 2 | body { 3 | font: 20px sans-serif; 4 | } 5 | svg { 6 | font: 14px sans-serif; 7 | } 8 | 9 | .axis path, 10 | .axis line { 11 | fill: none; 12 | stroke: #000; 13 | shape-rendering: crispEdges; 14 | } 15 | 16 | .x.axis path { 17 | display: none; 18 | } 19 | 20 | .line { 21 | fill: none; 22 | stroke: steelblue; 23 | stroke-width: 1.5px; 24 | } 25 | 26 | .country:hover{ 27 | stroke: #fff; 28 | stroke-width: 1.5px; 29 | } 30 | .text{ 31 | font-size:10px; 32 | text-transform:capitalize; 33 | } 34 | #container { 35 | height:100%; 36 | background: #F0F8FF; 37 | } 38 | .hidden { 39 | display: none; 40 | } 41 | div.tooltip { 42 | color: #222; 43 | background: #fff; 44 | padding: .5em; 45 | text-shadow: #f5f5f5 0 1px 0; 46 | border-radius: 2px; 47 | box-shadow: 0px 0px 2px 0px #a6a6a6; 48 | opacity: 0.9; 49 | position: absolute; 50 | } 51 | -------------------------------------------------------------------------------- /server/main.js: -------------------------------------------------------------------------------- 1 | var redraw; 2 | (function() { 3 | d3.select(window).on("resize", throttle); 4 | 5 | var zoom = d3.behavior.zoom() 6 | .scaleExtent([1, 9]) 7 | .on("zoom", move); 8 | 9 | var width = document.getElementById('container').offsetWidth; 10 | var height = width / 2; 11 | 12 | var topo, projection, path, svg2, g; 13 | 14 | var tooltip = d3.select("#container").append("div").attr("class", "tooltip hidden"); 15 | 16 | setup(width, height); 17 | 18 | function setup(width, height) { 19 | projection = d3.geo.mercator() 20 | .translate([(width / 2), (height / 2)]) 21 | .scale(width / 2 / Math.PI); 22 | 23 | path = d3.geo.path().projection(projection); 24 | 25 | svg2 = d3.select("#container").append("svg") 26 | .attr("width", width) 27 | .attr("height", height) 28 | .call(zoom) 29 | .append("g"); 30 | 31 | g = svg2.append("g"); 32 | } 33 | 34 | d3.json("data/world-topo-min.json", function(error, world) { 35 | var countries = topojson.feature(world, world.objects.countries).features; 36 | topo = countries; 37 | draw(topo); 38 | }); 39 | 40 | function draw(topo) { 41 | var country = g.selectAll(".country").data(topo); 42 | 43 | country.enter().insert("path") 44 | .attr("class", "country") 45 | .attr("d", path) 46 | .attr("id", function(d, i) { 47 | return d.id; 48 | }) 49 | .style("fill", function(d, i) { 50 | return country_color(d.properties.name); 51 | }); 52 | 53 | //offsets for tooltips 54 | var offsetL = document.getElementById('container').offsetLeft + 20; 55 | var offsetT = document.getElementById('container').offsetTop + 10; 56 | 57 | //tooltips 58 | country 59 | .on("mousemove", function(d, i) { 60 | var mouse = d3.mouse(svg2.node()).map(function(d) { 61 | return parseInt(d); 62 | }); 63 | 64 | tooltip.classed("hidden", false) 65 | .attr("style", "left:" + (mouse[0] + offsetL) + "px;top:" + (mouse[1] + offsetT) + "px") 66 | .html( 67 | name_correction(d.properties.name) + ": " + get_count(d.properties.name) 68 | ); 69 | 70 | }) 71 | .on("mouseout", function(d, i) { 72 | tooltip.classed("hidden", true); 73 | }); 74 | } 75 | 76 | redraw = function() { 77 | width = document.getElementById('container').offsetWidth; 78 | height = width / 2; 79 | d3.select('#container svg').remove(); 80 | setup(width, height); 81 | draw(topo); 82 | } 83 | 84 | function move() { 85 | var t = d3.event.translate; 86 | var s = d3.event.scale; 87 | zscale = s; 88 | var h = height / 4; 89 | 90 | 91 | t[0] = Math.min( 92 | (width / height) * (s - 1), 93 | Math.max(width * (1 - s), t[0]) 94 | ); 95 | 96 | t[1] = Math.min( 97 | h * (s - 1) + h * s, 98 | Math.max(height * (1 - s) - h * s, t[1]) 99 | ); 100 | 101 | zoom.translate(t); 102 | g.attr("transform", "translate(" + t + ")scale(" + s + ")"); 103 | 104 | //adjust the country hover stroke width based on zoom level 105 | d3.selectAll(".country").style("stroke-width", 1.5 / s); 106 | 107 | } 108 | 109 | })(); 110 | 111 | var throttleTimer; 112 | 113 | function throttle() { 114 | window.clearTimeout(throttleTimer); 115 | throttleTimer = window.setTimeout(function() { 116 | redraw(); 117 | render_graph(); 118 | }, 200); 119 | } 120 | 121 | // handles values up to 255 122 | function to_hex(value){ 123 | value = Math.floor(value); 124 | var upper = Math.floor(value / 16); 125 | var lower = value % 16; 126 | return hex[upper] + hex[lower]; 127 | } 128 | 129 | function country_color(name) { 130 | var count = get_count(name); 131 | if (country_counts_max) { 132 | var percent = count / country_counts_max; 133 | // give the space a bit of an exponential curve 134 | percent = Math.log(Math.floor(percent * 1023) + 1) / Math.log(2) / 10 135 | var blue = Math.floor(percent * 255); 136 | var green = Math.floor(blue)/2; 137 | return '#00' + to_hex(green) + to_hex(blue); 138 | } else { 139 | return '#000000'; 140 | } 141 | } 142 | 143 | function get_count(name) { 144 | name = name_correction(name); 145 | if (country_counts && country_counts[name]) { 146 | return country_counts[name]; 147 | } 148 | return 0; 149 | } 150 | function name_correction(name) { 151 | name = name.split(',')[0]; 152 | if (name_corrections[name] !== undefined) { 153 | return name_corrections[name] 154 | } 155 | return name 156 | } 157 | var name_corrections = { 158 | 'Russian Federation': 'Russia', 159 | 'Korea': 'Republic of Korea', 160 | 'Lithuania': 'Republic of Lithuania', 161 | 'Moldova': 'Republic of Moldova', 162 | 'Slovakia': 'Slovak Republic', 163 | 'Viet Nam': 'Vietnam' 164 | } 165 | 166 | 167 | 168 | var hex = '0123456789abcdef'; 169 | var country_counts; 170 | var country_counts_max; 171 | var svg1; 172 | var data; 173 | var render_graph; 174 | $(function() { 175 | // build the path to the websocket 176 | var loc = window.location, 177 | new_uri; 178 | if (loc.protocol === "https:") { 179 | new_uri = "wss:"; 180 | } else { 181 | new_uri = "ws:"; 182 | } 183 | new_uri += "//" + loc.host; 184 | new_uri += loc.pathname + "stats"; 185 | 186 | // connect 187 | var ws = new WebSocket(new_uri); 188 | 189 | // handle new data 190 | ws.onmessage = function(e) { 191 | var parsed = JSON.parse(e.data); 192 | console.log(parsed); 193 | country_counts = parsed.country_counts; 194 | var max = 0; 195 | for (var k in country_counts) { 196 | var v = country_counts[k]; 197 | if (v > max) { 198 | max = v; 199 | } 200 | } 201 | country_counts_max = max; 202 | data = parsed.numbers_list; 203 | render_graph(); 204 | redraw(); 205 | }; 206 | 207 | var margin = { 208 | top: 20, 209 | right: 20, 210 | bottom: 30, 211 | left: 50 212 | }; 213 | 214 | 215 | render_graph = function() { 216 | var width = document.getElementById('container').offsetWidth - margin.left - margin.right; 217 | var height = width / 2 - margin.top - margin.bottom; 218 | 219 | var parseDate = d3.time.format.iso.parse; 220 | 221 | var x = d3.time.scale() 222 | .range([0, width]); 223 | 224 | var y = d3.scale.linear() 225 | .range([height, 0]); 226 | 227 | var xAxis = d3.svg.axis() 228 | .scale(x) 229 | .orient("bottom"); 230 | 231 | var yAxis = d3.svg.axis() 232 | .scale(y) 233 | .orient("left"); 234 | 235 | var line = d3.svg.line() 236 | .x(function(d) { 237 | return x(d.date); 238 | }) 239 | .y(function(d) { 240 | return y(d.close); 241 | }); 242 | 243 | if (svg1) { 244 | $(svg1[0]).parent().remove() 245 | } 246 | svg1 = d3.select("#graph").append("svg") 247 | .attr("width", width + margin.left + margin.right) 248 | .attr("height", height + margin.top + margin.bottom) 249 | .append("g") 250 | .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 251 | 252 | data.forEach(function(d) { 253 | d.date = parseDate(d.time); 254 | d.close = +d.number; 255 | }); 256 | 257 | x.domain(d3.extent(data, function(d) { 258 | return d.date; 259 | })); 260 | y.domain(d3.extent(data, function(d) { 261 | return d.close; 262 | })); 263 | 264 | svg1.append("g") 265 | .attr("class", "x axis") 266 | .attr("transform", "translate(0," + height + ")") 267 | .call(xAxis); 268 | 269 | svg1.append("g") 270 | .attr("class", "y axis") 271 | .call(yAxis) 272 | .append("text") 273 | .attr("transform", "rotate(-90)") 274 | .attr("y", 10) 275 | .attr("dy", ".71em") 276 | .style("text-anchor", "end") 277 | .text("Nodes"); 278 | 279 | svg1.append("path") 280 | .datum(data) 281 | .attr("class", "line") 282 | .attr("d", line); 283 | } 284 | }); 285 | -------------------------------------------------------------------------------- /server/old.js: -------------------------------------------------------------------------------- 1 | var redraw; 2 | (function(){ 3 | d3.select(window).on("resize", throttle); 4 | 5 | var zoom = d3.behavior.zoom() 6 | .scaleExtent([1, 9]) 7 | .on("zoom", move); 8 | 9 | 10 | var width = document.getElementById('container').offsetWidth; 11 | var height = width / 2; 12 | 13 | var topo,projection,path,svg2,g; 14 | 15 | var graticule = d3.geo.graticule(); 16 | 17 | var tooltip = d3.select("#container").append("div").attr("class", "tooltip hidden"); 18 | 19 | setup(width,height); 20 | 21 | function setup(width,height){ 22 | projection = d3.geo.mercator() 23 | .translate([(width/2), (height/2)]) 24 | .scale( width / 2 / Math.PI); 25 | 26 | path = d3.geo.path().projection(projection); 27 | 28 | svg2 = d3.select("#container").append("svg") 29 | .attr("width", width) 30 | .attr("height", height) 31 | .call(zoom) 32 | //.on("click", click) 33 | .append("g"); 34 | 35 | g = svg2.append("g") 36 | .on("click", click); 37 | 38 | } 39 | 40 | d3.json("data/world-topo-min.json", function(error, world) { 41 | 42 | var countries = topojson.feature(world, world.objects.countries).features; 43 | 44 | topo = countries; 45 | draw(topo); 46 | 47 | }); 48 | 49 | function draw(topo) { 50 | 51 | svg2.append("path") 52 | .datum(graticule) 53 | .attr("class", "graticule") 54 | .attr("d", path); 55 | 56 | 57 | g.append("path") 58 | .datum({type: "LineString", coordinates: [[-180, 0], [-90, 0], [0, 0], [90, 0], [180, 0]]}) 59 | .attr("class", "equator") 60 | .attr("d", path); 61 | 62 | 63 | var country = g.selectAll(".country").data(topo); 64 | 65 | country.enter().insert("path") 66 | .attr("class", "country") 67 | .attr("d", path) 68 | .attr("id", function(d,i) { return d.id; }) 69 | //.attr("title", function(d,i) { return name_correction(d.properties.name); }) 70 | .style("fill", function(d, i) { 71 | if (country_counts) { 72 | var count = country_counts[name_correction(d.properties.name)]; 73 | if (count !== undefined) { 74 | var percent = count / country_counts_max; 75 | // give the space a bit of an exponential curve 76 | percent = Math.log(Math.floor(percent*1023)+1)/Math.log(2)/10 77 | var value = Math.floor(percent * 255); 78 | var upper = Math.floor(value / 16); 79 | var lower = value % 16; 80 | if (d.properties.name == 'United States') { 81 | console.log('#0000' + hex[upper] + hex[lower]) 82 | } 83 | return '#0000' + hex[upper] + hex[lower]; 84 | } else { 85 | return '#000000'; 86 | } 87 | } else { 88 | return d.properties.color; 89 | } 90 | }); 91 | 92 | //offsets for tooltips 93 | var offsetL = document.getElementById('container').offsetLeft+20; 94 | var offsetT = document.getElementById('container').offsetTop+10; 95 | 96 | //tooltips 97 | country 98 | .on("mousemove", function(d,i) { 99 | 100 | var mouse = d3.mouse(svg2.node()).map( function(d) { return parseInt(d); } ); 101 | 102 | tooltip.classed("hidden", false) 103 | .attr("style", "left:"+(mouse[0]+offsetL)+"px;top:"+(mouse[1]+offsetT)+"px") 104 | .html( 105 | d.properties.name + ": " + country_counts[name_correction(d.properties.name)] 106 | ); 107 | 108 | }) 109 | .on("mouseout", function(d,i) { 110 | tooltip.classed("hidden", true); 111 | }); 112 | 113 | 114 | //EXAMPLE: adding some capitals from external CSV file 115 | //d3.csv("data/country-capitals.csv", function(err, capitals) { 116 | 117 | // capitals.forEach(function(i){ 118 | // addpoint(i.CapitalLongitude, i.CapitalLatitude, i.CapitalName ); 119 | // }); 120 | 121 | //}); 122 | 123 | } 124 | 125 | 126 | redraw = function() { 127 | width = document.getElementById('container').offsetWidth; 128 | height = width / 2; 129 | d3.select('#container svg').remove(); 130 | setup(width,height); 131 | draw(topo); 132 | } 133 | 134 | 135 | function move() { 136 | 137 | var t = d3.event.translate; 138 | var s = d3.event.scale; 139 | zscale = s; 140 | var h = height/4; 141 | 142 | 143 | t[0] = Math.min( 144 | (width/height) * (s - 1), 145 | Math.max( width * (1 - s), t[0] ) 146 | ); 147 | 148 | t[1] = Math.min( 149 | h * (s - 1) + h * s, 150 | Math.max(height * (1 - s) - h * s, t[1]) 151 | ); 152 | 153 | zoom.translate(t); 154 | g.attr("transform", "translate(" + t + ")scale(" + s + ")"); 155 | 156 | //adjust the country hover stroke width based on zoom level 157 | d3.selectAll(".country").style("stroke-width", 1.5 / s); 158 | 159 | } 160 | 161 | 162 | 163 | var throttleTimer; 164 | function throttle() { 165 | window.clearTimeout(throttleTimer); 166 | throttleTimer = window.setTimeout(function() { 167 | redraw(); 168 | }, 200); 169 | } 170 | 171 | 172 | //geo translation on mouse click in map 173 | function click() { 174 | var latlon = projection.invert(d3.mouse(this)); 175 | console.log(latlon); 176 | } 177 | 178 | 179 | //function to add points and text to the map (used in plotting capitals) 180 | function addpoint(lat,lon,text) { 181 | 182 | var gpoint = g.append("g").attr("class", "gpoint"); 183 | var x = projection([lat,lon])[0]; 184 | var y = projection([lat,lon])[1]; 185 | 186 | gpoint.append("svg:circle") 187 | .attr("cx", x) 188 | .attr("cy", y) 189 | .attr("class","point") 190 | .attr("r", 1.5); 191 | 192 | //conditional in case a point has no associated text 193 | if(text.length>0){ 194 | 195 | gpoint.append("text") 196 | .attr("x", x+2) 197 | .attr("y", y+2) 198 | .attr("class","text") 199 | .text(text); 200 | } 201 | 202 | } 203 | })(); 204 | 205 | 206 | 207 | 208 | function name_correction(name) { 209 | if (name_corrections[name] !== undefined) { 210 | return name_corrections[name] 211 | } 212 | name = name.split(',')[0]; 213 | return name 214 | } 215 | var name_corrections = { 216 | 'Russian Federation': 'Russia' 217 | } 218 | 219 | 220 | 221 | var hex = '0123456789abcdef'; 222 | var country_counts; 223 | var country_counts_max; 224 | var svg1; 225 | $(function() { 226 | // build the path to the websocket 227 | var loc = window.location, new_uri; 228 | if (loc.protocol === "https:") { 229 | new_uri = "wss:"; 230 | } else { 231 | new_uri = "ws:"; 232 | } 233 | new_uri += "//" + loc.host; 234 | new_uri += loc.pathname + "stats"; 235 | 236 | // connect 237 | var ws = new WebSocket(new_uri); 238 | // handle new data 239 | ws.onmessage = function(e) { 240 | var data = JSON.parse(e.data); 241 | console.log(data); 242 | country_counts = data.country_counts; 243 | var max = 0; 244 | for (var k in country_counts) { 245 | var v = country_counts[k]; 246 | if (v > max) { 247 | max = v; 248 | } 249 | } 250 | country_counts_max = max; 251 | render_graph(data.numbers_list); 252 | redraw(); 253 | }; 254 | 255 | // allow forced refresh 256 | $('#sendBtn').click(function(){ 257 | ws.send("refresh"); 258 | }); 259 | 260 | var margin = {top: 20, right: 20, bottom: 30, left: 50}, 261 | width = 960 - margin.left - margin.right, 262 | height = 500 - margin.top - margin.bottom; 263 | 264 | //var parseDate = Date 265 | var parseDate = d3.time.format.iso.parse; 266 | //var parseDate = d3.time.format("%d-%b-%y").parse; 267 | 268 | var x = d3.time.scale() 269 | .range([0, width]); 270 | 271 | var y = d3.scale.linear() 272 | .range([height, 0]); 273 | 274 | var xAxis = d3.svg.axis() 275 | .scale(x) 276 | .orient("bottom"); 277 | 278 | var yAxis = d3.svg.axis() 279 | .scale(y) 280 | .orient("left"); 281 | 282 | var line = d3.svg.line() 283 | .x(function(d) { return x(d.date); }) 284 | .y(function(d) { return y(d.close); }); 285 | 286 | function render_graph(data) { 287 | if (svg1) { 288 | $(svg1[0]).parent().remove() 289 | } 290 | svg1 = d3.select("#graph").append("svg") 291 | .attr("width", width + margin.left + margin.right) 292 | .attr("height", height + margin.top + margin.bottom) 293 | .append("g") 294 | .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 295 | if (data === null) { 296 | data = [ 297 | // {number: 2253, 298 | // time: "2015-10-23T01:31:45.452030533-07:00"}, 299 | // {number: 2222, 300 | // time: "2015-10-23T01:32:30.38162021-07:00"}, 301 | // {number: 2225, 302 | // time: "2015-10-23T01:33:20.942007336-07:00"} 303 | ]; 304 | } 305 | // data = [ 306 | // { time:"1-May-12", number: 2253}, 307 | // {time:"30-Apr-12", number: 2222}, 308 | // {time:"27-Apr-12", number: 2225} 309 | //]; 310 | data.forEach(function(d) { 311 | d.date = parseDate(d.time); 312 | d.close = +d.number; 313 | }); 314 | 315 | x.domain(d3.extent(data, function(d) { return d.date; })); 316 | y.domain(d3.extent(data, function(d) { return d.close; })); 317 | 318 | svg1.append("g") 319 | .attr("class", "x axis") 320 | .attr("transform", "translate(0," + height + ")") 321 | .call(xAxis); 322 | 323 | svg1.append("g") 324 | .attr("class", "y axis") 325 | .call(yAxis) 326 | .append("text") 327 | .attr("transform", "rotate(-90)") 328 | .attr("y", -20) 329 | .attr("dy", ".71em") 330 | .style("text-anchor", "end") 331 | .text("Nodes"); 332 | 333 | svg1.append("path") 334 | .datum(data) 335 | .attr("class", "line") 336 | .attr("d", line); 337 | } 338 | 339 | }); 340 | 341 | 342 | --------------------------------------------------------------------------------