From 8f443e1cfbb61a4f0314f03bb2b71507e57dface Mon Sep 17 00:00:00 2001 From: mappu Date: Mon, 31 Dec 2018 18:21:15 +1300 Subject: [PATCH] vendor: commit existing golang vendor directory --- .gitignore | 1 - vendor/code.ivysaur.me/libnmdc/.hgignore | 14 + vendor/code.ivysaur.me/libnmdc/.hgtags | 20 + vendor/code.ivysaur.me/libnmdc/AdcProtocol.go | 711 ++ .../libnmdc/AutodetectProtocol.go | 80 + .../code.ivysaur.me/libnmdc/ConnectionMode.go | 29 + .../libnmdc/ConnectionState.go | 40 + .../code.ivysaur.me/libnmdc/Example_test.go | 58 + vendor/code.ivysaur.me/libnmdc/Gopkg.lock | 15 + vendor/code.ivysaur.me/libnmdc/Gopkg.toml | 26 + vendor/code.ivysaur.me/libnmdc/HubAddress.go | 48 + .../code.ivysaur.me/libnmdc/HubConnection.go | 229 + .../libnmdc/HubConnectionOptions.go | 79 + vendor/code.ivysaur.me/libnmdc/HubEvent.go | 25 + .../code.ivysaur.me/libnmdc/NmdcProtocol.go | 407 + .../libnmdc/NmdcProtocol_test.go | 97 + vendor/code.ivysaur.me/libnmdc/Protocol.go | 31 + vendor/code.ivysaur.me/libnmdc/TODO.txt | 6 + vendor/code.ivysaur.me/libnmdc/UserCommand.go | 27 + vendor/code.ivysaur.me/libnmdc/UserFlag.go | 17 + vendor/code.ivysaur.me/libnmdc/UserInfo.go | 53 + .../code.ivysaur.me/libnmdc/__dist/README.txt | 98 + vendor/code.ivysaur.me/libnmdc/libnmdc.go | 28 + vendor/code.ivysaur.me/libnmdc/tth.go | 41 + vendor/code.ivysaur.me/libnmdc/tth_test.go | 36 + vendor/github.com/cxmcc/tiger/.gitignore | 22 + vendor/github.com/cxmcc/tiger/.travis.yml | 7 + vendor/github.com/cxmcc/tiger/LICENSE | 20 + vendor/github.com/cxmcc/tiger/README.md | 48 + vendor/github.com/cxmcc/tiger/compress.go | 96 + vendor/github.com/cxmcc/tiger/sboxes.go | 269 + vendor/github.com/cxmcc/tiger/tiger.go | 117 + vendor/github.com/cxmcc/tiger/tiger_test.go | 144 + .../googollee/go-engine.io/.travis.yml | 7 + .../github.com/googollee/go-engine.io/LICENSE | 23 + .../googollee/go-engine.io/README.md | 78 + .../go-engine.io/example/asset/index.html | 14 + .../go-engine.io/example/asset/index.js | 4137 +++++++ .../go-engine.io/example/asset/style.css | 5 + .../googollee/go-engine.io/example/main.go | 60 + .../googollee/go-engine.io/ioutil.go | 50 + .../googollee/go-engine.io/ioutil_test.go | 123 + .../googollee/go-engine.io/message/message.go | 8 + .../go-engine.io/parser/limit_reader.go | 45 + .../go-engine.io/parser/limit_reader_test.go | 58 + .../googollee/go-engine.io/parser/packet.go | 191 + .../go-engine.io/parser/packet_test.go | 297 + .../googollee/go-engine.io/parser/parser.go | 3 + .../googollee/go-engine.io/parser/payload.go | 170 + .../go-engine.io/parser/payload_test.go | 212 + .../googollee/go-engine.io/polling/client.go | 149 + .../go-engine.io/polling/polling_test.go | 231 + .../googollee/go-engine.io/polling/server.go | 197 + .../go-engine.io/polling/server_test.go | 507 + .../go-engine.io/polling/try_locker.go | 28 + .../go-engine.io/polling/try_locker_test.go | 47 + .../googollee/go-engine.io/polling/writer.go | 33 + .../go-engine.io/polling/writer_test.go | 89 + .../googollee/go-engine.io/polling/xhr.go | 12 + .../googollee/go-engine.io/server.go | 188 + .../googollee/go-engine.io/server_conn.go | 388 + .../go-engine.io/server_conn_test.go | 377 + .../googollee/go-engine.io/server_test.go | 92 + .../googollee/go-engine.io/sessions.go | 47 + .../googollee/go-engine.io/sessions_test.go | 25 + .../go-engine.io/transport/transport.go | 50 + .../go-engine.io/websocket/client.go | 72 + .../go-engine.io/websocket/server.go | 81 + .../go-engine.io/websocket/websocket.go | 12 + .../go-engine.io/websocket/websocket_test.go | 458 + .../googollee/go-socket.io/.travis.yml | 5 + .../github.com/googollee/go-socket.io/LICENSE | 23 + .../googollee/go-socket.io/README.md | 127 + .../googollee/go-socket.io/adapter.go | 70 + .../googollee/go-socket.io/attachment.go | 168 + .../googollee/go-socket.io/attachment_test.go | 184 + .../googollee/go-socket.io/caller.go | 82 + .../go-socket.io/example/asset/index.html | 38 + .../example/asset/jquery-1.11.1.js | 10308 ++++++++++++++++ .../example/asset/socket.io-1.3.7.js | 3 + .../googollee/go-socket.io/example/main.go | 53 + .../googollee/go-socket.io/handler.go | 213 + .../googollee/go-socket.io/handler_test.go | 105 + .../googollee/go-socket.io/helper_test.go | 50 + .../googollee/go-socket.io/ioutil.go | 34 + .../github.com/googollee/go-socket.io/main.go | 6 + .../googollee/go-socket.io/message_reader.go | 60 + .../go-socket.io/message_reader_test.go | 54 + .../googollee/go-socket.io/namespace.go | 47 + .../googollee/go-socket.io/parser.go | 338 + .../googollee/go-socket.io/parser_test.go | 191 + .../googollee/go-socket.io/server.go | 106 + .../googollee/go-socket.io/socket.go | 174 + .../googollee/go-socket.io/trim_writer.go | 45 + .../go-socket.io/trim_writer_test.go | 64 + .../github.com/gorilla/websocket/.gitignore | 25 + .../github.com/gorilla/websocket/.travis.yml | 19 + vendor/github.com/gorilla/websocket/AUTHORS | 8 + vendor/github.com/gorilla/websocket/LICENSE | 22 + vendor/github.com/gorilla/websocket/README.md | 64 + vendor/github.com/gorilla/websocket/client.go | 392 + .../gorilla/websocket/client_clone.go | 16 + .../gorilla/websocket/client_clone_legacy.go | 38 + .../gorilla/websocket/client_server_test.go | 512 + .../gorilla/websocket/client_test.go | 72 + .../gorilla/websocket/compression.go | 148 + .../gorilla/websocket/compression_test.go | 80 + vendor/github.com/gorilla/websocket/conn.go | 1149 ++ .../gorilla/websocket/conn_broadcast_test.go | 134 + .../github.com/gorilla/websocket/conn_read.go | 18 + .../gorilla/websocket/conn_read_legacy.go | 21 + .../github.com/gorilla/websocket/conn_test.go | 497 + vendor/github.com/gorilla/websocket/doc.go | 180 + .../gorilla/websocket/example_test.go | 46 + .../websocket/examples/autobahn/README.md | 13 + .../examples/autobahn/fuzzingclient.json | 15 + .../websocket/examples/autobahn/server.go | 265 + .../gorilla/websocket/examples/chat/README.md | 102 + .../gorilla/websocket/examples/chat/client.go | 137 + .../gorilla/websocket/examples/chat/home.html | 98 + .../gorilla/websocket/examples/chat/hub.go | 53 + .../gorilla/websocket/examples/chat/main.go | 40 + .../websocket/examples/command/README.md | 19 + .../websocket/examples/command/home.html | 102 + .../websocket/examples/command/main.go | 193 + .../gorilla/websocket/examples/echo/README.md | 17 + .../gorilla/websocket/examples/echo/client.go | 81 + .../gorilla/websocket/examples/echo/server.go | 132 + .../websocket/examples/filewatch/README.md | 9 + .../websocket/examples/filewatch/main.go | 193 + vendor/github.com/gorilla/websocket/json.go | 55 + .../github.com/gorilla/websocket/json_test.go | 119 + vendor/github.com/gorilla/websocket/mask.go | 55 + .../github.com/gorilla/websocket/mask_safe.go | 15 + .../github.com/gorilla/websocket/mask_test.go | 73 + .../github.com/gorilla/websocket/prepared.go | 103 + .../gorilla/websocket/prepared_test.go | 74 + vendor/github.com/gorilla/websocket/server.go | 291 + .../gorilla/websocket/server_test.go | 51 + vendor/github.com/gorilla/websocket/util.go | 214 + .../github.com/gorilla/websocket/util_test.go | 74 + 141 files changed, 30084 insertions(+), 1 deletion(-) create mode 100644 vendor/code.ivysaur.me/libnmdc/.hgignore create mode 100644 vendor/code.ivysaur.me/libnmdc/.hgtags create mode 100644 vendor/code.ivysaur.me/libnmdc/AdcProtocol.go create mode 100644 vendor/code.ivysaur.me/libnmdc/AutodetectProtocol.go create mode 100644 vendor/code.ivysaur.me/libnmdc/ConnectionMode.go create mode 100644 vendor/code.ivysaur.me/libnmdc/ConnectionState.go create mode 100644 vendor/code.ivysaur.me/libnmdc/Example_test.go create mode 100644 vendor/code.ivysaur.me/libnmdc/Gopkg.lock create mode 100644 vendor/code.ivysaur.me/libnmdc/Gopkg.toml create mode 100644 vendor/code.ivysaur.me/libnmdc/HubAddress.go create mode 100644 vendor/code.ivysaur.me/libnmdc/HubConnection.go create mode 100644 vendor/code.ivysaur.me/libnmdc/HubConnectionOptions.go create mode 100644 vendor/code.ivysaur.me/libnmdc/HubEvent.go create mode 100644 vendor/code.ivysaur.me/libnmdc/NmdcProtocol.go create mode 100644 vendor/code.ivysaur.me/libnmdc/NmdcProtocol_test.go create mode 100644 vendor/code.ivysaur.me/libnmdc/Protocol.go create mode 100644 vendor/code.ivysaur.me/libnmdc/TODO.txt create mode 100644 vendor/code.ivysaur.me/libnmdc/UserCommand.go create mode 100644 vendor/code.ivysaur.me/libnmdc/UserFlag.go create mode 100644 vendor/code.ivysaur.me/libnmdc/UserInfo.go create mode 100644 vendor/code.ivysaur.me/libnmdc/__dist/README.txt create mode 100644 vendor/code.ivysaur.me/libnmdc/libnmdc.go create mode 100644 vendor/code.ivysaur.me/libnmdc/tth.go create mode 100644 vendor/code.ivysaur.me/libnmdc/tth_test.go create mode 100644 vendor/github.com/cxmcc/tiger/.gitignore create mode 100644 vendor/github.com/cxmcc/tiger/.travis.yml create mode 100644 vendor/github.com/cxmcc/tiger/LICENSE create mode 100644 vendor/github.com/cxmcc/tiger/README.md create mode 100644 vendor/github.com/cxmcc/tiger/compress.go create mode 100644 vendor/github.com/cxmcc/tiger/sboxes.go create mode 100644 vendor/github.com/cxmcc/tiger/tiger.go create mode 100644 vendor/github.com/cxmcc/tiger/tiger_test.go create mode 100644 vendor/github.com/googollee/go-engine.io/.travis.yml create mode 100644 vendor/github.com/googollee/go-engine.io/LICENSE create mode 100644 vendor/github.com/googollee/go-engine.io/README.md create mode 100644 vendor/github.com/googollee/go-engine.io/example/asset/index.html create mode 100644 vendor/github.com/googollee/go-engine.io/example/asset/index.js create mode 100644 vendor/github.com/googollee/go-engine.io/example/asset/style.css create mode 100644 vendor/github.com/googollee/go-engine.io/example/main.go create mode 100644 vendor/github.com/googollee/go-engine.io/ioutil.go create mode 100644 vendor/github.com/googollee/go-engine.io/ioutil_test.go create mode 100644 vendor/github.com/googollee/go-engine.io/message/message.go create mode 100644 vendor/github.com/googollee/go-engine.io/parser/limit_reader.go create mode 100644 vendor/github.com/googollee/go-engine.io/parser/limit_reader_test.go create mode 100644 vendor/github.com/googollee/go-engine.io/parser/packet.go create mode 100644 vendor/github.com/googollee/go-engine.io/parser/packet_test.go create mode 100644 vendor/github.com/googollee/go-engine.io/parser/parser.go create mode 100644 vendor/github.com/googollee/go-engine.io/parser/payload.go create mode 100644 vendor/github.com/googollee/go-engine.io/parser/payload_test.go create mode 100644 vendor/github.com/googollee/go-engine.io/polling/client.go create mode 100644 vendor/github.com/googollee/go-engine.io/polling/polling_test.go create mode 100644 vendor/github.com/googollee/go-engine.io/polling/server.go create mode 100644 vendor/github.com/googollee/go-engine.io/polling/server_test.go create mode 100644 vendor/github.com/googollee/go-engine.io/polling/try_locker.go create mode 100644 vendor/github.com/googollee/go-engine.io/polling/try_locker_test.go create mode 100644 vendor/github.com/googollee/go-engine.io/polling/writer.go create mode 100644 vendor/github.com/googollee/go-engine.io/polling/writer_test.go create mode 100644 vendor/github.com/googollee/go-engine.io/polling/xhr.go create mode 100644 vendor/github.com/googollee/go-engine.io/server.go create mode 100644 vendor/github.com/googollee/go-engine.io/server_conn.go create mode 100644 vendor/github.com/googollee/go-engine.io/server_conn_test.go create mode 100644 vendor/github.com/googollee/go-engine.io/server_test.go create mode 100644 vendor/github.com/googollee/go-engine.io/sessions.go create mode 100644 vendor/github.com/googollee/go-engine.io/sessions_test.go create mode 100644 vendor/github.com/googollee/go-engine.io/transport/transport.go create mode 100644 vendor/github.com/googollee/go-engine.io/websocket/client.go create mode 100644 vendor/github.com/googollee/go-engine.io/websocket/server.go create mode 100644 vendor/github.com/googollee/go-engine.io/websocket/websocket.go create mode 100644 vendor/github.com/googollee/go-engine.io/websocket/websocket_test.go create mode 100644 vendor/github.com/googollee/go-socket.io/.travis.yml create mode 100644 vendor/github.com/googollee/go-socket.io/LICENSE create mode 100644 vendor/github.com/googollee/go-socket.io/README.md create mode 100644 vendor/github.com/googollee/go-socket.io/adapter.go create mode 100644 vendor/github.com/googollee/go-socket.io/attachment.go create mode 100644 vendor/github.com/googollee/go-socket.io/attachment_test.go create mode 100644 vendor/github.com/googollee/go-socket.io/caller.go create mode 100644 vendor/github.com/googollee/go-socket.io/example/asset/index.html create mode 100644 vendor/github.com/googollee/go-socket.io/example/asset/jquery-1.11.1.js create mode 100644 vendor/github.com/googollee/go-socket.io/example/asset/socket.io-1.3.7.js create mode 100644 vendor/github.com/googollee/go-socket.io/example/main.go create mode 100644 vendor/github.com/googollee/go-socket.io/handler.go create mode 100644 vendor/github.com/googollee/go-socket.io/handler_test.go create mode 100644 vendor/github.com/googollee/go-socket.io/helper_test.go create mode 100644 vendor/github.com/googollee/go-socket.io/ioutil.go create mode 100644 vendor/github.com/googollee/go-socket.io/main.go create mode 100644 vendor/github.com/googollee/go-socket.io/message_reader.go create mode 100644 vendor/github.com/googollee/go-socket.io/message_reader_test.go create mode 100644 vendor/github.com/googollee/go-socket.io/namespace.go create mode 100644 vendor/github.com/googollee/go-socket.io/parser.go create mode 100644 vendor/github.com/googollee/go-socket.io/parser_test.go create mode 100644 vendor/github.com/googollee/go-socket.io/server.go create mode 100644 vendor/github.com/googollee/go-socket.io/socket.go create mode 100644 vendor/github.com/googollee/go-socket.io/trim_writer.go create mode 100644 vendor/github.com/googollee/go-socket.io/trim_writer_test.go create mode 100644 vendor/github.com/gorilla/websocket/.gitignore create mode 100644 vendor/github.com/gorilla/websocket/.travis.yml create mode 100644 vendor/github.com/gorilla/websocket/AUTHORS create mode 100644 vendor/github.com/gorilla/websocket/LICENSE create mode 100644 vendor/github.com/gorilla/websocket/README.md create mode 100644 vendor/github.com/gorilla/websocket/client.go create mode 100644 vendor/github.com/gorilla/websocket/client_clone.go create mode 100644 vendor/github.com/gorilla/websocket/client_clone_legacy.go create mode 100644 vendor/github.com/gorilla/websocket/client_server_test.go create mode 100644 vendor/github.com/gorilla/websocket/client_test.go create mode 100644 vendor/github.com/gorilla/websocket/compression.go create mode 100644 vendor/github.com/gorilla/websocket/compression_test.go create mode 100644 vendor/github.com/gorilla/websocket/conn.go create mode 100644 vendor/github.com/gorilla/websocket/conn_broadcast_test.go create mode 100644 vendor/github.com/gorilla/websocket/conn_read.go create mode 100644 vendor/github.com/gorilla/websocket/conn_read_legacy.go create mode 100644 vendor/github.com/gorilla/websocket/conn_test.go create mode 100644 vendor/github.com/gorilla/websocket/doc.go create mode 100644 vendor/github.com/gorilla/websocket/example_test.go create mode 100644 vendor/github.com/gorilla/websocket/examples/autobahn/README.md create mode 100644 vendor/github.com/gorilla/websocket/examples/autobahn/fuzzingclient.json create mode 100644 vendor/github.com/gorilla/websocket/examples/autobahn/server.go create mode 100644 vendor/github.com/gorilla/websocket/examples/chat/README.md create mode 100644 vendor/github.com/gorilla/websocket/examples/chat/client.go create mode 100644 vendor/github.com/gorilla/websocket/examples/chat/home.html create mode 100644 vendor/github.com/gorilla/websocket/examples/chat/hub.go create mode 100644 vendor/github.com/gorilla/websocket/examples/chat/main.go create mode 100644 vendor/github.com/gorilla/websocket/examples/command/README.md create mode 100644 vendor/github.com/gorilla/websocket/examples/command/home.html create mode 100644 vendor/github.com/gorilla/websocket/examples/command/main.go create mode 100644 vendor/github.com/gorilla/websocket/examples/echo/README.md create mode 100644 vendor/github.com/gorilla/websocket/examples/echo/client.go create mode 100644 vendor/github.com/gorilla/websocket/examples/echo/server.go create mode 100644 vendor/github.com/gorilla/websocket/examples/filewatch/README.md create mode 100644 vendor/github.com/gorilla/websocket/examples/filewatch/main.go create mode 100644 vendor/github.com/gorilla/websocket/json.go create mode 100644 vendor/github.com/gorilla/websocket/json_test.go create mode 100644 vendor/github.com/gorilla/websocket/mask.go create mode 100644 vendor/github.com/gorilla/websocket/mask_safe.go create mode 100644 vendor/github.com/gorilla/websocket/mask_test.go create mode 100644 vendor/github.com/gorilla/websocket/prepared.go create mode 100644 vendor/github.com/gorilla/websocket/prepared_test.go create mode 100644 vendor/github.com/gorilla/websocket/server.go create mode 100644 vendor/github.com/gorilla/websocket/server_test.go create mode 100644 vendor/github.com/gorilla/websocket/util.go create mode 100644 vendor/github.com/gorilla/websocket/util_test.go diff --git a/.gitignore b/.gitignore index f00f3c2..f92bd5a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,3 @@ nmdc-webfrontend.conf clientpack/ _dist/ node_modules/ -vendor/ diff --git a/vendor/code.ivysaur.me/libnmdc/.hgignore b/vendor/code.ivysaur.me/libnmdc/.hgignore new file mode 100644 index 0000000..5c7f679 --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/.hgignore @@ -0,0 +1,14 @@ +mode:regex + +# Compilation output +\.(?:exe|a)$ +^pkg/ + +# Dependencies +^src/(?:github.com|gopkg.in|golang.org)/ + +# Scratch space +^src/nmdc/ + +# Binary release artefacts +/?__dist/ diff --git a/vendor/code.ivysaur.me/libnmdc/.hgtags b/vendor/code.ivysaur.me/libnmdc/.hgtags new file mode 100644 index 0000000..50c3590 --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/.hgtags @@ -0,0 +1,20 @@ +945ab4b16d05aa084f71bf5da9a3f687e0ec8bbd v0.1.0 +02a360e95480b97ddad83add5db48b2766339a99 nmdc-log-service-1.0.0 +137c1b65039e03c80379826a6efdfd808f6fbc8f v0.2.0 +d8b64d5527c2a5e4d76872e5bc3d69f7646135c6 v0.3.0 +fca41372e400853775b02e951f9db91d87f41adb nmdc-log-service-1.0.1 +050b424a7c5d5a27c9323c8810f3afbead1f5b96 v0.4.0 +da9f123633f9c28be6435ed7898139665d4c39d9 nmdc-log-service-1.0.2 +75a78f6a78f249a2cd8aa3d29f7e5e6319b4e03b v0.5.0 +4116422bb10229d887f9296970a166fa1ef8c5fd nmdc-log-service-1.0.3 +cb86f3a40115cc46f450c0c83fd9b9d3b740e820 nmdc-log-service-1.0.4 +cb86f3a40115cc46f450c0c83fd9b9d3b740e820 v0.6.0 +71343a2c641a438206d30ea7e75dc89a11dbef00 v0.7.0 +b0e57a5fcffdf4102d669db51a3648ddf66a0792 v0.8.0 +e7c2c71ef24b386add728fad35fff4a996fccbac v0.9.0 +3ecc037cf2d7080572fe87c2e39ecd153fb0e947 v0.10.0 +5149ffe70ea8475e480b682345b31aa45a3352db v0.11.0 +22b156a6fc2f6161765317f4ec9ab3731a26e0e2 v0.12.0 +3ee0f4ea5142d66079a9500bdcd48a53bdcf362f v0.13.0 +6422ed687cd308c339b6dc188bbe1034ed93f893 v0.14.0 +84fb191007017862ffc37af68dcdace5d8c06eee v0.15.0 diff --git a/vendor/code.ivysaur.me/libnmdc/AdcProtocol.go b/vendor/code.ivysaur.me/libnmdc/AdcProtocol.go new file mode 100644 index 0000000..fe4bdfa --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/AdcProtocol.go @@ -0,0 +1,711 @@ +package libnmdc + +import ( + "encoding/base32" + "fmt" + "regexp" + "strconv" + "strings" +) + +type adcState int + +const ( + adcStateProtocol adcState = 0 + adcStateIdentify adcState = 1 + adcStateVerify adcState = 2 + adcStateNormal adcState = 3 + adcStateData adcState = 4 +) + +type AdcProtocol struct { + hc *HubConnection + state adcState + sid, pid, cid string // all in base32 encoding + supports map[string]struct{} +} + +const ( + // extra extensions that aren't flagged in SUPPORTS + adcSeparateApVe string = "SEPARATE_AP_VE" // we invented this string +) + +func NewAdcProtocol(hc *HubConnection) Protocol { + proto := AdcProtocol{ + hc: hc, + state: adcStateProtocol, + supports: make(map[string]struct{}), + } + + rxPid := regexp.MustCompile("^[A-Z2-7]{39}$") + if !rxPid.MatchString(hc.Hco.AdcPID) { + hc.processEvent(HubEvent{EventType: EVENT_SYSTEM_MESSAGE_FROM_CONN, Message: "Invalid custom PID, regenerating"}) + hc.Hco.AdcPID = NewPID() + } + + pid_base32 := hc.Hco.AdcPID + cid_base32, err := proto.pid2cid(pid_base32) + if err != nil { + panic(err) + } + + proto.cid = cid_base32 + proto.pid = pid_base32 + + // Start logging in + hc.SayRaw("HSUP ADBASE ADTIGR ADUCMD\n") + + return &proto +} + +func (this *AdcProtocol) pid2cid(pid_base32 string) (string, error) { + + pid_raw, err := base32.StdEncoding.DecodeString(pid_base32 + "=") + if err != nil { + return "", err + } + + cid_raw := Tiger(string(pid_raw)) + cid_base32 := Base32(cid_raw) + + return cid_base32, nil +} + +func (this *AdcProtocol) SID2Nick(sid string) (string, bool) { + this.hc.usersMut.Lock() + defer this.hc.usersMut.Unlock() + + nick, ok := this.hc.userSIDs[sid] + return nick, ok +} + +func (this *AdcProtocol) Nick2SID(targetNick string) (string, bool) { + this.hc.usersMut.Lock() + defer this.hc.usersMut.Unlock() + + for sid, nick := range this.hc.userSIDs { + if nick == targetNick { + return sid, true + } + } + + return "", false +} + +func (this *AdcProtocol) ProcessCommand(msg string) { + + if len(msg) == 0 { + return + } + + this.hc.processEvent(HubEvent{EventType: EVENT_DEBUG_MESSAGE, Message: msg}) + + parts := strings.Split(msg, " ") + switch parts[0] { + + case "ISUP": + if !(this.state == adcStateProtocol || this.state == adcStateNormal) { + this.malformed(parts) + return + } + for _, supportflag := range parts[1:] { + if len(supportflag) < 2 { + this.malformed(parts) + return + } + + if supportflag[0:2] == "AD" { + this.supports[supportflag[2:]] = struct{}{} + } else if supportflag[0:2] == "RM" { + delete(this.supports, supportflag[2:]) + } else { + this.malformed(parts) + return + } + } + if this.state == adcStateProtocol { + this.state = adcStateIdentify + } + + case "ISID": + if this.state != adcStateIdentify { + this.malformed(parts) + return + } + this.sid = parts[1] + + // State transition IDENTIFY --> VERIFY and send our own info + this.hc.SayRaw("BINF " + this.escape(this.sid) + " " + this.ourINFO(true) + "\n") + this.state = adcStateVerify + + case "IINF": + // Hub telling information about itself + // ADCH++ sends this once we are successfully logged in + + flags, err := this.parts2flags(parts[1:]) + if err != nil { + this.logError(err) + return + } + + if flags["CT"] != "32" { + this.malformed(parts) + return + } + + err = this.handleHubInfo(flags) + if err != nil { + this.logError(err) + return + } + + if this.state != adcStateNormal { + this.enterNormalState() // successful login + } + + case "BINF": + if this.state != adcStateNormal { + this.enterNormalState() // successful login + } + + sid := parts[1] + flags, err := this.parts2flags(parts[2:]) + if err != nil { + this.logError(err) + return + } + + // Log this user in, and associate this SID with this user + this.hc.usersMut.Lock() + defer this.hc.usersMut.Unlock() + + oldNick, sidExists := this.hc.userSIDs[sid] + + uinfo := UserInfo{} + if sidExists { + uinfo_lookup, ok := this.hc.users[oldNick] + if !ok { + // Shouldn't happen + this.hc.processEvent(HubEvent{ + EventType: EVENT_SYSTEM_MESSAGE_FROM_CONN, + Message: fmt.Sprintf("Hub connection corrupted (missing info for SID='%s' nick='%s'), disconnecting", sid, oldNick), + }) + this.hc.Disconnect() + return + } + + uinfo = uinfo_lookup + } + + this.updateUserInfo(&uinfo, flags) + newNick := uinfo.Nick + if len(newNick) == 0 { + this.logError(fmt.Errorf("Zero-length nick for user (SID='%s')", sid)) + } + + shouldHandleNewUser := false + if sidExists && oldNick != newNick { + // Nick change = delete all trace of this user first, treat as new + + delete(this.hc.users, oldNick) + delete(this.hc.userSIDs, sid) + this.hc.processEvent(HubEvent{EventType: EVENT_USER_PART, Nick: oldNick}) + shouldHandleNewUser = true + + } else if sidExists && oldNick == newNick { + // Updating existing user + this.hc.users[newNick] = uinfo + this.hc.processEvent(HubEvent{EventType: EVENT_USER_UPDATED_INFO, Nick: newNick}) + + } else if !sidExists { + // User joined + shouldHandleNewUser = true + } + + // + + if shouldHandleNewUser { + // Install this SID as pointing to this nick + this.hc.userSIDs[sid] = uinfo.Nick + + // Check if this nick was in use by any other SID already + for otherSid, otherSidNick := range this.hc.userSIDs { + if otherSidNick == newNick && otherSid != sid { + this.hc.processEvent(HubEvent{ + EventType: EVENT_SYSTEM_MESSAGE_FROM_CONN, + Message: fmt.Sprintf("Hub connection corrupted (duplicate SIDs '%s' and '%s' for nick '%s'), disconnecting", sid, otherSid, newNick), + }) + this.hc.Disconnect() + return + } + } + + // Notifications + this.hc.users[newNick] = uinfo + this.hc.processEvent(HubEvent{EventType: EVENT_USER_JOINED, Nick: newNick}) + } + + case "IMSG": + // General message from the hub + if len(parts) < 2 { + this.malformed(parts) + return + } + + this.hc.processEvent(HubEvent{EventType: EVENT_SYSTEM_MESSAGE_FROM_HUB, Message: this.unescape(parts[1])}) + + case "ISTA": + // Error message from the hub + if len(parts) < 3 { + this.malformed(parts) + return + } + + code, _ := strconv.Atoi(parts[1]) + msg := this.unescape(parts[2]) + this.hc.processEvent(HubEvent{EventType: EVENT_SYSTEM_MESSAGE_FROM_HUB, Message: this.ErrorMessage(code, msg)}) + + case "IQUI": + // Error message from the hub + // IQUI V3M6 DI1 MSNick\staken,\splease\spick\sanother\sone TL-1 + if len(parts) < 2 { + this.malformed(parts) + return + } + + sid := parts[1] + + flags, err := this.parts2flags(parts[2:]) + if err != nil { + return + } + + if sid == this.sid { + if msg, ok := flags["MS"]; ok { + this.hc.processEvent(HubEvent{EventType: EVENT_SYSTEM_MESSAGE_FROM_HUB, Message: "The hub is closing our connection because: " + this.unescape(msg)}) + } else { + this.hc.processEvent(HubEvent{EventType: EVENT_SYSTEM_MESSAGE_FROM_HUB, Message: "The hub is closing our connection"}) + } + } else { + this.hc.usersMut.Lock() + defer this.hc.usersMut.Unlock() + otherSidNick, ok := this.hc.userSIDs[sid] + if ok { + delete(this.hc.userSIDs, sid) + delete(this.hc.users, otherSidNick) + this.hc.processEvent(HubEvent{EventType: EVENT_USER_PART, Nick: otherSidNick}) + } else { + // ?? + this.logError(fmt.Errorf("An unknown user quit the hub (SID=%s)", sid)) + } + } + + case "BMSG": + // Message from a user + // BMSG ZVF4 hi + if len(parts) < 3 { + this.malformed(parts) + return + } + + sid := this.unescape(parts[1]) + msg := this.unescape(parts[2]) + + this.hc.usersMut.Lock() + defer this.hc.usersMut.Unlock() + nick, ok := this.hc.userSIDs[sid] + if !ok { + this.logError(fmt.Errorf("Recieved message from unknown SID '%s'", sid)) + return + } + + this.hc.processEvent(HubEvent{EventType: EVENT_PUBLIC, Nick: nick, Message: msg}) + + case "IGPA": + // Password is needed + // IGPA 7EIAAAECLMAAAPJQAAADQQYAAAWAYAAAKVFQAAF6EAAAAAYFAAAA + // HPAS LZDIJOTZDPWHINHGPT5RHT6WLU7DRME7DQO2O3Q + if len(parts) < 2 { + this.malformed(parts) + return + } + + /* + For GPA/PAS, assuming that '12345' is the random data supplied in GPA, then; + PAS = Base32( Hash( password + '12345' ) ) + + GPA: The data parameter is at least 24 random bytes (base32 encoded). + */ + + data_base32 := parts[1] + if len(data_base32)%8 != 0 { + data_base32 += strings.Repeat("=", 8-(len(data_base32)%8)) + } + + data_raw, err := base32.StdEncoding.DecodeString(data_base32) + if err != nil { + this.logError(err) + return + } + + resp := Base32(Tiger(this.hc.Hco.NickPassword + string(data_raw))) + this.hc.SayRaw("HPAS " + resp + "\n") + + case "EMSG": + // Private message from other user + // EMSG I5RO FMWH test\spm PMI5RO + // EMSG sender recip==us message [flags...] + if len(parts) < 4 { + this.malformed(parts) + return + } + + if parts[2] != this.sid { + this.logError(fmt.Errorf("Recieved a PM intended for someone else (got SID=%s expected SID=%s)", parts[2], this.sid)) + return + } + + senderSid := parts[1] + senderNick, ok := this.SID2Nick(parts[1]) + if !ok { + this.logError(fmt.Errorf("Recieved a PM from an unknown user (SID=%s)", senderSid)) + return + } + + msg := this.unescape(parts[3]) + this.hc.processEvent(HubEvent{EventType: EVENT_PRIVATE, Nick: senderNick, Message: msg}) + + case "ICMD": + // Usercommand + // ICMD ADCH++/About\sthis\shub TTHMSG\s+about\n CT3 + + if len(parts) < 2 { + this.malformed(parts) + return + } + + uc := UserCommand{ + Message: this.unescape(parts[1]), + Type: USERCOMMAND_TYPE_RAW, // default + } + + flags, err := this.parts2flags(parts[2:]) + if err != nil { + this.malformed(parts) + return + } + + if ct, ok := flags["CT"]; ok { + ct64, _ := strconv.ParseUint(ct, 10, 64) + uc.Context = UserCommandContext(ct64) + } + + if tt, ok := flags["TT"]; ok { + uc.Command = tt + } + + if sp, ok := flags["SP"]; ok && sp == "1" { + uc.Type = USERCOMMAND_TYPE_SEPARATOR + } + + if co, ok := flags["CO"]; ok && co == "1" { + uc.Type = USERCOMMAND_TYPE_NICKLIMITED // "Constrained" in ADC parlance + } + + if rm, ok := flags["RM"]; ok && rm == "1" { + uc.RemoveThis = true + } + + this.hc.processEvent(HubEvent{EventType: EVENT_USERCOMMAND, UserCommand: &uc}) + + // Ignored messages + // ```````````````` + + case "DCTM": // Client-client ConnectToMe + case "BSCH": // Search + + default: + this.malformed(parts) + } +} + +func (this *AdcProtocol) infoFlagsFor(u *UserInfo) map[string]string { + parts := map[string]string{ + "NI": u.Nick, + "SS": fmt.Sprintf("%d", u.ShareSize), + "SF": fmt.Sprintf("%d", u.SharedFiles), + "US": fmt.Sprintf("%d", u.UploadSpeedBps), + "DS": fmt.Sprintf("%d", u.DownloadSpeedBps), + "SL": fmt.Sprintf("%d", u.Slots), + "HN": fmt.Sprintf("%d", u.HubsUnregistered), + "HR": fmt.Sprintf("%d", u.HubsRegistered), + "HO": fmt.Sprintf("%d", u.HubsOperator), + } + + if _, ok := this.supports[adcSeparateApVe]; ok { + parts["AP"] = u.ClientTag + parts["VE"] = u.ClientVersion + } else { + parts["VE"] = fmt.Sprintf("%s %s", u.ClientTag, u.ClientVersion) + } + + // Do not send the hub a CT (it decides what type we are) + + return parts +} + +func (this *AdcProtocol) ourINFO(includePid bool) string { + parts := this.infoFlagsFor(this.hc.Hco.Self) + parts["ID"] = this.cid + if includePid { + parts["PD"] = this.pid + } + + ret := "" + for k, v := range parts { + ret += " " + k + this.escape(v) + } + return ret[1:] +} + +func (this *AdcProtocol) parts2flags(parts []string) (map[string]string, error) { + flags := make(map[string]string, len(parts)) + for _, flag := range parts { + if len(flag) < 2 { + return nil, fmt.Errorf("Malformed flag '%s'", flag) + } + flags[flag[0:2]] = this.unescape(flag[2:]) + } + + return flags, nil +} + +func (this *AdcProtocol) handleHubInfo(flags map[string]string) error { + if flags["CT"] != "32" { + return fmt.Errorf("Expected CT==32") + } + + // IINF DEADCH++\sTest\shub VE2.12.1\s(r"[unknown]")\sRelease HI1 NIADCH++ APADCH++ CT32 + // AP: extension 3.24 "Application and version separation in INF" + // HI: + + // Hub properties updated + + // Special SUPPORT that is only indicated in IINF + if _, ok := flags["AP"]; ok { + this.supports[adcSeparateApVe] = struct{}{} + } + + // Hub's name is in "NI", hub description in "DE" + hubName, ok := flags["NI"] + if ok { + if hubDesc, ok := flags["DE"]; ok && len(hubDesc) > 0 { + hubName += " - " + hubDesc + } + + this.hc.HubName = hubName + this.hc.processEvent(HubEvent{EventType: EVENT_HUBNAME_CHANGED, Nick: this.hc.HubName}) + } + + return nil +} + +func (this *AdcProtocol) updateUserInfo(u *UserInfo, flags map[string]string) { + + // User MyINFO + // BINF GUPR IDFEARIFD33NTGC4YBEZ3UFQS5R4ZXXTFL2QN2GRY PDZMIFLG5EKZG3BDRRMIJPG7ARNA6KW3JVIH3DF7Q NIivysaur5 SL3 FS3 SS0 SF0 HN1 HR0 HO0 VEEiskaltDC++\s2.2.9 US2621440 KPSHA256/3UPRORG4BLJ4CG6TO6R3G75A67LXOGD437NALQALRWJF6XBOECTA I40.0.0.0 U418301 + // BINF GUPR I4172.17.0.1 U418301 IDFEARIFD33NTGC4YBEZ3UFQS5R4ZXXTFL2QN2GRY VEEiskaltDC++\s2.2.9 SF0 NIivysaur5 SL3 HN1 HO0 KPSHA256/3UPRORG4BLJ4CG6TO6R3G75A67LXOGD437NALQALRWJF6XBOECTA HR0 FS3 SS0 US2621440 SUSEGA,ADC0,TCP4,UDP4 + // Or maybe only incremental: + // BINF Z3BA HO1 + // TODO + + for prop, val := range flags { + switch prop { + case "ID": + u.CID = val + case "PD": + // ignore PID - it will only appear if we're talking about our own user + case "NI": + u.Nick = val + case "SL": + u.Slots, _ = strconv.ParseUint(val, 10, 64) + case "SS": + u.ShareSize, _ = strconv.ParseUint(val, 10, 64) + case "SF": + u.SharedFiles, _ = strconv.ParseUint(val, 10, 64) + case "HN": + u.HubsUnregistered, _ = strconv.ParseUint(val, 10, 64) + case "HR": + u.HubsRegistered, _ = strconv.ParseUint(val, 10, 64) + case "HO": + u.HubsOperator, _ = strconv.ParseUint(val, 10, 64) + case "US": + u.UploadSpeedBps, _ = strconv.ParseUint(val, 10, 64) + case "DS": + u.DownloadSpeedBps, _ = strconv.ParseUint(val, 10, 64) + case "KP": + u.Keyprint = val + case "I4": + u.IPv4Address = val + case "I6": + u.IPv6Address = val + case "U4": + u.IPv4UDPPort, _ = strconv.ParseUint(val, 10, 64) + case "U6": + u.IPv6UDPPort, _ = strconv.ParseUint(val, 10, 64) + case "SU": + u.SupportFlags = make(map[string]struct{}) + for _, supportFlag := range strings.Split(val, ",") { + u.SupportFlags[supportFlag] = struct{}{} + } + } + } + + // VE / AP + AP, hasAP := flags["AP"] + VE, hasVE := flags["VE"] + if hasAP && hasVE { + u.ClientTag = AP + u.ClientVersion = VE + } else if hasAP && !hasVE { + u.ClientTag, u.ClientVersion = this.getAPVEFromSingle(AP) + } else if !hasAP && hasVE { + u.ClientTag, u.ClientVersion = this.getAPVEFromSingle(VE) + } +} + +func (this *AdcProtocol) getAPVEFromSingle(term string) (string, string) { + words := strings.Split(term, " ") + if len(words) > 1 { + return strings.Join(words[0:len(words)-1], " "), words[len(words)-1] + } else { + return term, "0" + } +} + +func (this *AdcProtocol) enterNormalState() { + this.state = adcStateNormal + this.hc.processEvent(HubEvent{EventType: EVENT_CONNECTION_STATE_CHANGED, StateChange: CONNECTIONSTATE_CONNECTED}) + this.hc.State = CONNECTIONSTATE_CONNECTED +} + +func (this *AdcProtocol) malformed(parts []string) { + this.logError(fmt.Errorf("Ignoring malformed, unhandled, or out-of-state protocol command %v", parts)) +} + +func (this *AdcProtocol) logError(e error) { + this.hc.processEvent(HubEvent{EventType: EVENT_DEBUG_MESSAGE, Message: "Protocol error: " + e.Error()}) +} + +func (this *AdcProtocol) escape(plaintext string) string { + // The string "\s" escapes space, "\n" newline and "\\" backslash. This version of the protocol reserves all other escapes for future use; any message containing unknown escapes must be discarded. + v1 := strings.Replace(plaintext, `\`, `\\`, -1) + v2 := strings.Replace(v1, "\n", `\n`, -1) + return strings.Replace(v2, " ", `\s`, -1) +} + +func (this *AdcProtocol) unescape(encoded string) string { + v1 := strings.Replace(encoded, `\s`, " ", -1) + v2 := strings.Replace(v1, `\n`, "\n", -1) + return strings.Replace(v2, `\\`, `\`, -1) +} + +func (this *AdcProtocol) SayPublic(msg string) { + this.hc.SayRaw("BMSG " + this.sid + " " + this.escape(msg) + "\n") +} + +func (this *AdcProtocol) SayPrivate(user, message string) { + if sid, ok := this.Nick2SID(user); ok { + this.hc.SayRaw("DMSG " + this.sid + " " + sid + " " + this.escape(message) + "\n") + } else { + this.logError(fmt.Errorf("Unknown user '%s'", user)) + } +} + +func (this *AdcProtocol) ProtoMessageSeparator() string { + return "\n" +} + +func (this *AdcProtocol) ErrorMessage(code int, msg string) string { + severity := code / 100 + category := (code % 100) / 10 + cat_sub := (code % 100) + + formatSeverity := func(severity int) string { + switch severity { + case 0: + return "OK" + case 1: + return "Warning" + case 2: + return "Error" + default: + return "" + } + } + + formatCategory := func(category int) string { + switch category { + case 0: + return "" + case 1: + return "Hub not accepting users" + case 2: + return "Login failed" + case 3: + return "Access denied" + case 4: + return "Protocol error" + case 5: + return "Transfer error" + default: + return "" + } + } + + formatCatSub := func(cat_sub int) string { + switch cat_sub { + case 11: + return "Hub is full" + case 12: + return "Hub is disabled" + case 21: + return "Invalid nick" + case 22: + return "Nick is already in use" + case 23: + return "Invalid password" + case 24: + return "CID already connected" + case 25: + return "Access denied" + case 26: + return "Registered users only" + case 27: + return "Invalid PID" + case 31: + return "Permanently banned" + case 32: + return "Temporarily banned" + default: + return "" + } + } + + parts := make([]string, 0, 4) + if fs := formatSeverity(severity); len(fs) > 0 { + parts = append(parts, fs) + } + if fc := formatCategory(category); len(fc) > 0 { + parts = append(parts, fc) + } + if fcs := formatCatSub(cat_sub); len(fcs) > 0 { + parts = append(parts, fcs) + } + if len(msg) > 0 { + parts = append(parts, msg) + } + + return strings.Join(parts, ": ") + fmt.Sprintf(" (code %d)", code) + +} diff --git a/vendor/code.ivysaur.me/libnmdc/AutodetectProtocol.go b/vendor/code.ivysaur.me/libnmdc/AutodetectProtocol.go new file mode 100644 index 0000000..8ab97da --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/AutodetectProtocol.go @@ -0,0 +1,80 @@ +package libnmdc + +import ( + "sync" + "time" +) + +type AutodetectProtocol struct { + hc *HubConnection + + realProtoMut sync.Mutex + realProto Protocol +} + +func NewAutodetectProtocol(hc *HubConnection) Protocol { + proto := AutodetectProtocol{ + hc: hc, + realProto: nil, + } + + go proto.timeout() + + return &proto +} + +func (this *AutodetectProtocol) timeout() { + time.Sleep(AUTODETECT_ADC_NMDC_TIMEOUT) + + this.realProtoMut.Lock() + defer this.realProtoMut.Unlock() + + if this.realProto == nil { + this.realProto = NewAdcProtocol(this.hc) + this.hc.processEvent(HubEvent{EventType: EVENT_DEBUG_MESSAGE, Message: "Detected ADC protocol"}) + } +} + +func (this *AutodetectProtocol) ProcessCommand(msg string) { + this.realProtoMut.Lock() + defer this.realProtoMut.Unlock() + + if this.realProto == nil { + // We actually got some data using $ as the separator? + // Upgrade to a full NMDC protocol + this.realProto = NewNmdcProtocol(this.hc) + this.hc.processEvent(HubEvent{EventType: EVENT_DEBUG_MESSAGE, Message: "Detected NMDC protocol"}) + } + + this.realProto.ProcessCommand(msg) +} + +func (this *AutodetectProtocol) SayPublic(msg string) { + this.realProtoMut.Lock() + defer this.realProtoMut.Unlock() + + if this.realProto == nil { + this.realProto = NewNmdcProtocol(this.hc) + } + this.realProto.SayPublic(msg) +} + +func (this *AutodetectProtocol) SayPrivate(user, message string) { + this.realProtoMut.Lock() + defer this.realProtoMut.Unlock() + + if this.realProto == nil { + this.realProto = NewNmdcProtocol(this.hc) + } + this.realProto.SayPrivate(user, message) +} + +func (this *AutodetectProtocol) ProtoMessageSeparator() string { + this.realProtoMut.Lock() + defer this.realProtoMut.Unlock() + + if this.realProto == nil { + return "|" + } + return this.realProto.ProtoMessageSeparator() +} diff --git a/vendor/code.ivysaur.me/libnmdc/ConnectionMode.go b/vendor/code.ivysaur.me/libnmdc/ConnectionMode.go new file mode 100644 index 0000000..00f0105 --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/ConnectionMode.go @@ -0,0 +1,29 @@ +package libnmdc + +import ( + "fmt" +) + +type ConnectionMode rune + +const ( + CONNECTIONMODE_ACTIVE ConnectionMode = 'A' // 65 + CONNECTIONMODE_PASSIVE ConnectionMode = 'P' // 49 + CONNECTIONMODE_SOCKS5 ConnectionMode = '5' // 53 +) + +func (this ConnectionMode) String() string { + switch this { + case CONNECTIONMODE_ACTIVE: + return "Active" + + case CONNECTIONMODE_PASSIVE: + return "Passive" + + case CONNECTIONMODE_SOCKS5: + return "SOCKS5" + + default: + return fmt.Sprintf("ConnectionMode(\"%s\")", string(this)) + } +} diff --git a/vendor/code.ivysaur.me/libnmdc/ConnectionState.go b/vendor/code.ivysaur.me/libnmdc/ConnectionState.go new file mode 100644 index 0000000..fbb163e --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/ConnectionState.go @@ -0,0 +1,40 @@ +package libnmdc + +import ( + "net" +) + +type ConnectionState int + +const ( + CONNECTIONSTATE_DISCONNECTED = 1 + CONNECTIONSTATE_CONNECTING = 2 // Handshake in progress + CONNECTIONSTATE_CONNECTED = 3 +) + +func (cs ConnectionState) String() string { + switch cs { + case CONNECTIONSTATE_DISCONNECTED: + return "Disconnected" + case CONNECTIONSTATE_CONNECTING: + return "Connecting" + case CONNECTIONSTATE_CONNECTED: + return "Connected" + default: + return "?" + } +} + +func checkIsNetTimeout(err error) bool { + if err == nil { + return false + } + + switch err.(type) { + case net.Error: + return err.(net.Error).Timeout() + + default: + return false + } +} diff --git a/vendor/code.ivysaur.me/libnmdc/Example_test.go b/vendor/code.ivysaur.me/libnmdc/Example_test.go new file mode 100644 index 0000000..9f98b4c --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/Example_test.go @@ -0,0 +1,58 @@ +package libnmdc + +import ( + "fmt" +) + +func ExampleHubConnectionOptions_Connect() { + opts := HubConnectionOptions{ + Address: "127.0.0.1", + Self: NewUserInfo("slowpoke9"), + } + + events := make(chan HubEvent, 0) + hub := ConnectAsync(&opts, events) + + for event := range events { + switch event.EventType { + case EVENT_CONNECTION_STATE_CHANGED: + fmt.Printf("Connection -- %s (%s)\n", event.StateChange, event.Message) + + case EVENT_PUBLIC: + fmt.Printf("Message from '%s': '%s'\n", event.Nick, event.Message) + if event.Message == "how are you" { + hub.SayPublic("good thanks!") + } + + default: + fmt.Printf("%+v\n", event) + + } + } +} + +func ExampleHubConnectionOptions_ConnectSync() { + cb := func(hub *HubConnection, event HubEvent) { + switch event.EventType { + case EVENT_CONNECTION_STATE_CHANGED: + fmt.Printf("Connection -- %s (%s)\n", event.StateChange, event.Message) + + case EVENT_PUBLIC: + fmt.Printf("Message from '%s': '%s'\n", event.Nick, event.Message) + if event.Message == "how are you" { + hub.SayPublic("good thanks!") + } + + default: + fmt.Printf("%+v\n", event) + + } + } + + opts := HubConnectionOptions{ + Address: "127.0.0.1", + Self: NewUserInfo("slowpoke9"), + } + + ConnectSync(&opts, cb) // blocking +} diff --git a/vendor/code.ivysaur.me/libnmdc/Gopkg.lock b/vendor/code.ivysaur.me/libnmdc/Gopkg.lock new file mode 100644 index 0000000..32350dc --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/Gopkg.lock @@ -0,0 +1,15 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + branch = "master" + name = "github.com/cxmcc/tiger" + packages = ["."] + revision = "bde35e2713d7f674987c2ecb21a6b0fc33749516" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "c88ee670a5600b482019325b6d6633bb6b5fe789596dc29ef809aa7bb013927b" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/vendor/code.ivysaur.me/libnmdc/Gopkg.toml b/vendor/code.ivysaur.me/libnmdc/Gopkg.toml new file mode 100644 index 0000000..a16c0fb --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/Gopkg.toml @@ -0,0 +1,26 @@ + +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" + + +[[constraint]] + branch = "master" + name = "github.com/cxmcc/tiger" diff --git a/vendor/code.ivysaur.me/libnmdc/HubAddress.go b/vendor/code.ivysaur.me/libnmdc/HubAddress.go new file mode 100644 index 0000000..1847bbf --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/HubAddress.go @@ -0,0 +1,48 @@ +package libnmdc + +import ( + "net/url" + "strings" +) + +type HubAddress string + +func (this *HubAddress) parse() url.URL { + parsed, err := url.Parse(strings.ToLower(string(*this))) + if err != nil || len(parsed.Host) == 0 { + parsed = &url.URL{ + Scheme: "", + Host: string(*this), + } + } + + // Add default port if not specified + if !strings.ContainsRune(parsed.Host, ':') { + parsed.Host = parsed.Host + ":411" + } + + return *parsed +} + +func (this *HubAddress) IsSecure() bool { + parsed := this.parse() + + return parsed.Scheme == "nmdcs" || parsed.Scheme == "dchubs" || parsed.Scheme == "adcs" +} + +func (this *HubAddress) GetHostOnly() string { + return this.parse().Host +} + +func (this *HubAddress) GetProtocol() HubProtocol { + parsed := this.parse() + + switch parsed.Scheme { + case "nmdc", "dchub", "nmdcs", "dchubs": + return HubProtocolNmdc + case "adc", "adcs": + return HubProtocolAdc + default: + return HubProtocolAutodetect + } +} diff --git a/vendor/code.ivysaur.me/libnmdc/HubConnection.go b/vendor/code.ivysaur.me/libnmdc/HubConnection.go new file mode 100644 index 0000000..5780cdc --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/HubConnection.go @@ -0,0 +1,229 @@ +package libnmdc + +import ( + "crypto/tls" + "fmt" + "net" + "regexp" + "sync" + "time" +) + +type HubConnection struct { + // Supplied parameters + Hco *HubConnectionOptions + + // Current remote status + HubName string + State ConnectionState + + usersMut sync.RWMutex + users map[string]UserInfo + userSIDs map[string]string + + proto Protocol + + // Event callback + processEvent func(HubEvent) + + // Private state + conn net.Conn // this is an interface + connValid bool + autoReconnect bool + lastDataRecieved time.Time +} + +// Thread-safe user accessor. +func (this *HubConnection) Users(cb func(*map[string]UserInfo) error) error { + this.usersMut.Lock() + defer this.usersMut.Unlock() + + return cb(&this.users) +} + +func (this *HubConnection) SayPublic(message string) { + this.proto.SayPublic(message) +} + +func (this *HubConnection) SayPrivate(recipient string, message string) { + this.proto.SayPrivate(recipient, message) +} + +func (this *HubConnection) UserExists(nick string) bool { + this.usersMut.RLock() + defer this.usersMut.RUnlock() + + _, already_existed := this.users[nick] + return already_existed +} + +func (this *HubConnection) UserCount() int { + this.usersMut.RLock() + defer this.usersMut.RUnlock() + + return len(this.users) +} + +func (this *HubConnection) userJoined_NameOnly(nick string) { + if !this.UserExists(nick) { + + this.usersMut.Lock() + this.users[nick] = *NewUserInfo(nick) + this.usersMut.Unlock() // Don't lock over a processEvent boundary + + this.processEvent(HubEvent{EventType: EVENT_USER_JOINED, Nick: nick}) + } +} + +func (this *HubConnection) userJoined_Full(uinf *UserInfo) { + // n.b. also called when we get a replacement MyINFO for someone + this.usersMut.Lock() + _, userExisted := this.users[uinf.Nick] // don't use UserExists as it would deadlock the mutex + this.users[uinf.Nick] = *uinf + this.usersMut.Unlock() // Don't lock over a processEvent boundary + + if !userExisted { + this.processEvent(HubEvent{EventType: EVENT_USER_JOINED, Nick: uinf.Nick}) + } else { + this.processEvent(HubEvent{EventType: EVENT_USER_UPDATED_INFO, Nick: uinf.Nick}) + } +} + +// SayRaw sends raw bytes over the TCP socket. Callers should add the protocol +// terminating character themselves (e.g. `|` for NMDC). +// Note that protocol messages are transmitted on the caller thread, not from +// any internal libnmdc thread. +func (this *HubConnection) SayRaw(protocolCommand string) error { + if !this.connValid { + return ErrNotConnected + } + + _, err := this.conn.Write([]byte(protocolCommand)) + return err +} + +func (this *HubConnection) SayKeepalive() error { + if !this.connValid { + return ErrNotConnected + } + + return this.SayRaw(this.proto.ProtoMessageSeparator()) +} + +func (this *HubConnection) Disconnect() { + this.autoReconnect = false + if this.conn != nil { + this.conn.Close() + } + // A CONNECTIONSTATE_DISCONNECTED message will be emitted by the worker. +} + +func (this *HubConnection) worker() { + var fullBuffer string + var err error = nil + var nbytes int = 0 + + for { + + // If we're not connected, attempt reconnect + if this.conn == nil { + + fullBuffer = "" // clear + + if this.Hco.Address.IsSecure() { + this.conn, err = tls.Dial("tcp", this.Hco.Address.GetHostOnly(), &tls.Config{ + InsecureSkipVerify: this.Hco.SkipVerifyTLS, + }) + } else { + this.conn, err = net.Dial("tcp", this.Hco.Address.GetHostOnly()) + } + + if err != nil { + this.State = CONNECTIONSTATE_DISCONNECTED + this.connValid = false + this.proto = nil + + } else { + this.State = CONNECTIONSTATE_CONNECTING + this.connValid = true + this.processEvent(HubEvent{EventType: EVENT_CONNECTION_STATE_CHANGED, StateChange: CONNECTIONSTATE_CONNECTING}) + this.proto = this.Hco.Address.GetProtocol().Create(this) + + } + } + + // Read from socket into our local buffer (blocking) + if this.connValid { + + readBuff := make([]byte, 1024) + this.conn.SetReadDeadline(time.Now().Add(SEND_KEEPALIVE_EVERY)) + + nbytes, err = this.conn.Read(readBuff) + + if checkIsNetTimeout(err) { + // No data before read deadline + err = nil + + if this.proto == nil { + // Autodetect: switch to ADC + this.proto = NewAdcProtocol(this) + } else { + // Normal + // Send KA packet + err = this.SayKeepalive() + } + } + + if nbytes > 0 { + this.lastDataRecieved = time.Now() + fullBuffer += string(readBuff[0:nbytes]) + } + } + + if this.proto != nil { + rxSeparator := regexp.QuoteMeta(this.proto.ProtoMessageSeparator()) + rxProtocolMessage := regexp.MustCompile(`(?ms)\A[^` + rxSeparator + `]*` + rxSeparator) + + // Attempt to parse a message block + for len(fullBuffer) > 0 { + + // FIXME nmdc + for len(fullBuffer) > 0 && fullBuffer[0] == '|' { + fullBuffer = fullBuffer[1:] + } + + protocolMessage := rxProtocolMessage.FindString(fullBuffer) + if len(protocolMessage) > 0 { + this.proto.ProcessCommand(protocolMessage[:len(protocolMessage)-1]) + fullBuffer = fullBuffer[len(protocolMessage):] + } else { + break + } + } + + if err == nil && time.Now().Sub(this.lastDataRecieved) > RECONNECT_IF_NO_DATA_RECIEVED_IN { + err = fmt.Errorf("No packets recieved since %s, connection presumed lost", this.lastDataRecieved.Format(time.RFC3339)) + } + } + + // Maybe we disconnected + // Perform this check *last*, to ensure we've had a final shot at + // clearing out any queued messages + if err != nil { + this.State = CONNECTIONSTATE_DISCONNECTED + this.conn = nil + this.connValid = false + this.proto = nil + this.processEvent(HubEvent{EventType: EVENT_CONNECTION_STATE_CHANGED, StateChange: CONNECTIONSTATE_DISCONNECTED, Message: err.Error()}) + + if this.autoReconnect { + time.Sleep(AUTO_RECONNECT_AFTER) // Wait before reconnect + continue + } else { + return // leave the worker for good + } + } + + } + +} diff --git a/vendor/code.ivysaur.me/libnmdc/HubConnectionOptions.go b/vendor/code.ivysaur.me/libnmdc/HubConnectionOptions.go new file mode 100644 index 0000000..063e775 --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/HubConnectionOptions.go @@ -0,0 +1,79 @@ +package libnmdc + +import ( + "crypto/rand" +) + +type HubConnectionOptions struct { + Address HubAddress + SkipVerifyTLS bool // using a negative verb, because bools default to false + SkipAutoReconnect bool // as above + Self *UserInfo + NickPassword string + AdcPID string // blank: autogenerate +} + +func NewPID() string { + pidBytes := make([]byte, 24) + n, err := rand.Read(pidBytes) + if err != nil { + panic(err) // Insufficient cryptographic randomness + } + + if n != 24 { + panic("Insufficient cryptographic randomness") + } + + return Base32(pidBytes) +} + +func (this *HubConnectionOptions) prepareConnection() *HubConnection { + if this.Self.ClientTag == "" { + this.Self.ClientTag = DEFAULT_CLIENT_TAG + this.Self.ClientVersion = DEFAULT_CLIENT_VERSION + } + + // Shouldn't be blank either + if this.Self.ClientVersion == "" { + this.Self.ClientVersion = "0" + } + + if this.AdcPID == "" { + this.AdcPID = NewPID() + } + + hc := HubConnection{ + Hco: this, + HubName: DEFAULT_HUB_NAME, + State: CONNECTIONSTATE_DISCONNECTED, + users: make(map[string]UserInfo), + userSIDs: make(map[string]string), + + autoReconnect: !this.SkipAutoReconnect, + } + + return &hc +} + +// ConnectAsync connects to a hub server, and spawns a background goroutine to handle +// protocol messages. Events will be sent by channel to the supplied onEvent channel, +// the client is responsible for selecting off this. +func ConnectAsync(opts *HubConnectionOptions, onEvent chan HubEvent) *HubConnection { + hc := opts.prepareConnection() + hc.processEvent = func(ev HubEvent) { + onEvent <- ev + } + + go hc.worker() + return hc +} + +// ConnectSync connects to a hub server, and blocks forever to handle protocol messages. +// Client code should supply an event handling function as hco.OnEventSync. +func ConnectSync(opts *HubConnectionOptions, onEvent func(hub *HubConnection, ev HubEvent)) { + hc := opts.prepareConnection() + hc.processEvent = func(ev HubEvent) { + onEvent(hc, ev) + } + hc.worker() +} diff --git a/vendor/code.ivysaur.me/libnmdc/HubEvent.go b/vendor/code.ivysaur.me/libnmdc/HubEvent.go new file mode 100644 index 0000000..3334328 --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/HubEvent.go @@ -0,0 +1,25 @@ +package libnmdc + +type HubEventType int + +const ( + EVENT_PUBLIC HubEventType = 1 + EVENT_PRIVATE HubEventType = 2 + EVENT_SYSTEM_MESSAGE_FROM_HUB HubEventType = 3 + EVENT_SYSTEM_MESSAGE_FROM_CONN HubEventType = 4 + EVENT_USER_JOINED HubEventType = 5 + EVENT_USER_PART HubEventType = 6 + EVENT_USER_UPDATED_INFO HubEventType = 7 + EVENT_CONNECTION_STATE_CHANGED HubEventType = 8 + EVENT_HUBNAME_CHANGED HubEventType = 9 + EVENT_DEBUG_MESSAGE HubEventType = 10 + EVENT_USERCOMMAND HubEventType = 11 +) + +type HubEvent struct { + EventType HubEventType + Nick string + Message string + StateChange ConnectionState + UserCommand *UserCommand +} diff --git a/vendor/code.ivysaur.me/libnmdc/NmdcProtocol.go b/vendor/code.ivysaur.me/libnmdc/NmdcProtocol.go new file mode 100644 index 0000000..42dce25 --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/NmdcProtocol.go @@ -0,0 +1,407 @@ +package libnmdc + +import ( + "errors" + "fmt" + "regexp" + "strconv" + "strings" +) + +type NmdcProtocol struct { + hc *HubConnection + sentOurHello bool + supports map[string]struct{} + + rxPublicChat *regexp.Regexp + rxIncomingTo *regexp.Regexp + rxUserCommand *regexp.Regexp + rxMyInfo *regexp.Regexp + rxMyInfoNoTag *regexp.Regexp +} + +func NewNmdcProtocol(hc *HubConnection) Protocol { + proto := NmdcProtocol{} + proto.hc = hc + + // With the `m` flag, use \A instead of ^ to anchor to start + // This fixes accidentally finding a better match in the middle of a multi-line message + + proto.rxPublicChat = regexp.MustCompile(`(?ms)\A<([^>]*)> (.*)$`) + proto.rxIncomingTo = regexp.MustCompile(`(?ms)\A([^ ]+) From: ([^ ]+) \$<([^>]*)> (.*)`) + proto.rxUserCommand = regexp.MustCompile(`(?ms)\A(\d+) (\d+)\s?([^\$]*)\$?(.*)`) + + // Format: $ALL $ $$$$ + + HEAD := `(?ms)^\$ALL ([^ ]+) ` + FOOT := `\$.\$([^$]+)\$([^$]*)\$([0-9]*)\$$` + + proto.rxMyInfo = regexp.MustCompile(HEAD + `([^<]*)<(.+?) V:([^,]+),M:(.),H:([0-9]+)/([0-9]+)/([0-9]+),S:([0-9]+)>` + FOOT) + proto.rxMyInfoNoTag = regexp.MustCompile(HEAD + `([^$]*)` + FOOT) // Fallback for no tag + + // Done + return &proto +} + +func (this *NmdcProtocol) ProcessCommand(message string) { + + // Zero-length protocol message + // ```````````````````````````` + if len(message) == 0 { + return + } + + // Public chat + // ``````````` + if this.rxPublicChat.MatchString(message) { + pubchat_parts := this.rxPublicChat.FindStringSubmatch(message) + this.hc.processEvent(HubEvent{EventType: EVENT_PUBLIC, Nick: pubchat_parts[1], Message: this.unescape(pubchat_parts[2])}) + return + } + + // System messages + // ``````````````` + if message[0] != '$' { + this.hc.processEvent(HubEvent{EventType: EVENT_SYSTEM_MESSAGE_FROM_HUB, Nick: this.hc.HubName, Message: this.unescape(message)}) + return + } + + // Protocol messages + // ````````````````` + + commandParts := strings.SplitN(message, " ", 2) + switch commandParts[0] { + + case "$Lock": + this.hc.SayRaw("$Supports NoHello NoGetINFO UserCommand UserIP2 QuickList ChatOnly|" + + "$Key " + this.unlock([]byte(commandParts[1])) + "|") + this.sentOurHello = false + + case "$Hello": + if commandParts[1] == this.hc.Hco.Self.Nick && !this.sentOurHello { + this.hc.SayRaw("$Version 1,0091|") + this.hc.SayRaw("$GetNickList|") + this.sayInfo() + this.sentOurHello = true + + } else { + this.hc.userJoined_NameOnly(commandParts[1]) + + } + + case "$HubName": + this.hc.HubName = commandParts[1] + this.hc.processEvent(HubEvent{EventType: EVENT_HUBNAME_CHANGED, Nick: commandParts[1]}) + + case "$ValidateDenide": // sic + if len(this.hc.Hco.NickPassword) > 0 { + this.hc.processEvent(HubEvent{EventType: EVENT_SYSTEM_MESSAGE_FROM_CONN, Message: "Incorrect password."}) + } else { + this.hc.processEvent(HubEvent{EventType: EVENT_SYSTEM_MESSAGE_FROM_CONN, Message: "Nick already in use."}) + } + + case "$HubIsFull": + this.hc.processEvent(HubEvent{EventType: EVENT_SYSTEM_MESSAGE_FROM_CONN, Message: "Hub is full."}) + + case "$BadPass": + this.hc.processEvent(HubEvent{EventType: EVENT_SYSTEM_MESSAGE_FROM_CONN, Message: "Incorrect password."}) + + case "$GetPass": + if len(this.hc.Hco.NickPassword) == 0 { + // We've got a problem. MyPass with no arguments is a syntax error with no message = instant close + // Just drop the connection + this.hc.processEvent(HubEvent{EventType: EVENT_SYSTEM_MESSAGE_FROM_CONN, Message: "This account is passworded."}) + this.hc.Disconnect() + } else { + this.hc.SayRaw("$MyPass " + this.escape(this.hc.Hco.NickPassword) + "|") + } + + case "$Quit": + this.hc.usersMut.Lock() + delete(this.hc.users, commandParts[1]) + this.hc.usersMut.Unlock() // Don't lock over a processEvent boundary + + this.hc.processEvent(HubEvent{EventType: EVENT_USER_PART, Nick: commandParts[1]}) + + case "$MyINFO": + u, err := this.parseMyINFO(commandParts[1]) + if err != nil { + this.hc.processEvent(HubEvent{EventType: EVENT_DEBUG_MESSAGE, Message: err.Error()}) + return + } + + this.hc.userJoined_Full(u) + + case "$NickList": + nicklist := strings.Split(commandParts[1], "$$") + for _, nick := range nicklist { + if len(nick) > 0 { + this.hc.userJoined_NameOnly(nick) + } + } + + case "$OpList": + oplist := strings.Split(commandParts[1], "$$") + opmap := map[string]struct{}{} + + // Organise/sort the list, and ensure we're not meeting an operator for + // the first time + for _, nick := range oplist { + if len(nick) > 0 { + opmap[nick] = struct{}{} + this.hc.userJoined_NameOnly(nick) // assert existence; noop otherwise + } + } + + // Mark all mentioned nicks as being operators, and all unmentioned nicks + // as being /not/ an operator. (second pass minimises RW mutex use) + func() { + this.hc.usersMut.Lock() + defer this.hc.usersMut.Unlock() + + for nick, userinfo := range this.hc.users { + _, isop := opmap[nick] + + userinfo.IsOperator = isop + this.hc.users[nick] = userinfo + } + }() + + case "$To:": + valid := false + if this.rxIncomingTo.MatchString(commandParts[1]) { + txparts := this.rxIncomingTo.FindStringSubmatch(commandParts[1]) + if txparts[1] == this.hc.Hco.Self.Nick && txparts[2] == txparts[3] { + this.hc.processEvent(HubEvent{EventType: EVENT_PRIVATE, Nick: txparts[2], Message: this.unescape(txparts[4])}) + valid = true + } + } + + if !valid { + this.hc.processEvent(HubEvent{EventType: EVENT_DEBUG_MESSAGE, Message: "Malformed private message '" + commandParts[1] + "'"}) + } + + case "$UserIP": + this.hc.usersMut.Lock() + + pairs := strings.Split(commandParts[1], "$$") + notifyOfUpdate := make([]string, 0, len(pairs)) + + nextIPPair: + for _, pair := range pairs { + parts := strings.SplitN(pair, " ", 2) + if len(parts) != 2 { + // ???? + continue nextIPPair + } + + ip2nick := parts[0] + ip2addr := parts[1] + + uinfo, ok := this.hc.users[ip2nick] + if !ok { + this.hc.processEvent(HubEvent{EventType: EVENT_DEBUG_MESSAGE, Message: "Recieved IP '" + ip2addr + "' for unknown user '" + ip2nick + "'"}) + continue nextIPPair + } + + if uinfo.IPAddress != ip2addr { + uinfo.IPAddress = ip2addr + notifyOfUpdate = append(notifyOfUpdate, ip2nick) + this.hc.users[ip2nick] = uinfo + } + } + + this.hc.usersMut.Unlock() + + for _, nick := range notifyOfUpdate { + this.hc.processEvent(HubEvent{EventType: EVENT_USER_UPDATED_INFO, Nick: nick}) + } + + case "$ForceMove": + this.hc.Hco.Address = HubAddress(commandParts[1]) + this.hc.conn.Close() // we'll reconnect onto the new address + + case "$UserCommand": + // $UserCommand 1 1 Group chat\New group chat$<%[mynick]> !groupchat_new|| + if this.rxUserCommand.MatchString(commandParts[1]) { + usc := this.rxUserCommand.FindStringSubmatch(commandParts[1]) + + typeInt, _ := strconv.Atoi(usc[1]) + contextInt, _ := strconv.Atoi(usc[2]) + + uscStruct := UserCommand{ + Type: UserCommandType(typeInt), + Context: UserCommandContext(contextInt), + Message: usc[3], + Command: this.unescape(usc[4]), + } + + this.hc.processEvent(HubEvent{EventType: EVENT_USERCOMMAND, UserCommand: &uscStruct}) + + } else { + this.hc.processEvent(HubEvent{EventType: EVENT_DEBUG_MESSAGE, Message: "Malformed usercommand '" + commandParts[1] + "'"}) + } + + case "$Supports": + this.supports = make(map[string]struct{}) + for _, s := range strings.Split(commandParts[1], " ") { + this.supports[s] = struct{}{} + } + + if !this.sentOurHello { + + // Need to log in. + // If the hub supports QuickList, we can skip one network roundtrip + if _, ok := this.supports["QuickList"]; ok { + this.sayInfo() + this.hc.SayRaw("$GetNickList|") + } else { + this.hc.SayRaw("$ValidateNick " + this.escape(this.hc.Hco.Self.Nick) + "|") + } + + // This also counts as the end of the handshake from our POV. Consider + // ourselves logged in + this.sentOurHello = true + if this.hc.State != CONNECTIONSTATE_CONNECTED { + this.hc.processEvent(HubEvent{EventType: EVENT_CONNECTION_STATE_CHANGED, StateChange: CONNECTIONSTATE_CONNECTED}) + this.hc.State = CONNECTIONSTATE_CONNECTED + } + + } + + // IGNORABLE COMMANDS + case "$HubTopic": + case "$Search": + case "$ConnectToMe": + + default: + this.hc.processEvent(HubEvent{EventType: EVENT_DEBUG_MESSAGE, Message: "Unhandled protocol command '" + commandParts[0] + "'"}) + + } +} + +func (this *NmdcProtocol) escape(plaintext string) string { + v1 := strings.Replace(plaintext, "&", "&", -1) + v2 := strings.Replace(v1, "|", "|", -1) + return strings.Replace(v2, "$", "$", -1) +} + +func (this *NmdcProtocol) unescape(encoded string) string { + v1 := strings.Replace(encoded, "$", "$", -1) + v2 := strings.Replace(v1, "|", "|", -1) + return strings.Replace(v2, "&", "&", -1) +} + +func (this *NmdcProtocol) SayPublic(message string) { + this.hc.SayRaw("<" + this.hc.Hco.Self.Nick + "> " + this.escape(message) + "|") +} + +func (this *NmdcProtocol) SayPrivate(recipient, message string) { + this.hc.SayRaw("$To: " + recipient + " From: " + this.hc.Hco.Self.Nick + " $<" + this.hc.Hco.Self.Nick + "> " + this.escape(message) + "|") +} + +func (this *NmdcProtocol) sayInfo() { + this.hc.SayRaw(this.getUserMyINFO(this.hc.Hco.Self) + "|") +} + +func (this *NmdcProtocol) parseMyINFO(protomsg string) (*UserInfo, error) { + ret := UserInfo{} + + // Normal format (with tag in exact V/M/H/S order) + matches := this.rxMyInfo.FindStringSubmatch(protomsg) + if matches != nil { + ret.Nick = matches[1] + ret.Description = this.unescape(matches[2]) + ret.ClientTag = this.unescape(matches[3]) + ret.ClientVersion = matches[4] + ret.ConnectionMode = ConnectionMode(matches[5][0]) + maybeParse(matches[6], &ret.HubsUnregistered, 0) + maybeParse(matches[7], &ret.HubsRegistered, 0) + maybeParse(matches[8], &ret.HubsOperator, 0) + maybeParse(matches[9], &ret.Slots, 0) + if len(matches[10]) > 1 { + ret.Speed = matches[10][:len(matches[10])-2] + } else { + ret.Speed = "" + } + ret.Flag = UserFlag(matches[10][len(matches[10])-1]) + ret.Email = this.unescape(matches[11]) + maybeParse(matches[12], &ret.ShareSize, 0) + + return &ret, nil + } + + // No-tag format, used in early connection + matches = this.rxMyInfoNoTag.FindStringSubmatch(protomsg) + if matches != nil { + ret.Nick = matches[1] + ret.Description = this.unescape(matches[2]) + ret.ClientTag = "" + ret.ClientVersion = "0" + ret.ConnectionMode = CONNECTIONMODE_PASSIVE + ret.HubsUnregistered = 0 + ret.HubsRegistered = 0 + ret.HubsOperator = 0 + ret.Slots = 0 + + if len(matches[3]) > 1 { + ret.Speed = matches[3][:len(matches[3])-2] + } else { + ret.Speed = "" + } + ret.Flag = UserFlag(matches[3][len(matches[3])-1]) + ret.Email = this.unescape(matches[4]) + maybeParse(matches[5], &ret.ShareSize, 0) + + return &ret, nil + } + + // Couldn't get anything out of it... + return nil, errors.New("Malformed MyINFO") +} + +// Returns the MyINFO command, WITH leading $MyINFO, and WITHOUT trailing pipe +func (this *NmdcProtocol) getUserMyINFO(u *UserInfo) string { + return fmt.Sprintf( + "$MyINFO $ALL %s %s<%s V:%s,M:%c,H:%d/%d/%d,S:%d>$ $%s%c$%s$%d$", + u.Nick, + u.Description, + u.ClientTag, + strings.Replace(u.ClientVersion, ",", "-", -1), // just in case + u.ConnectionMode, + u.HubsUnregistered, + u.HubsRegistered, + u.HubsOperator, + u.Slots, + u.Speed, + u.Flag, + u.Email, + u.ShareSize, + ) +} + +func (this *NmdcProtocol) ProtoMessageSeparator() string { + return "|" +} + +func (this *NmdcProtocol) unlock(lock []byte) string { + + nibble_swap := func(b byte) byte { + return ((b << 4) & 0xF0) | ((b >> 4) & 0x0F) + } + + chr := func(b byte) string { + if b == 0 || b == 5 || b == 36 || b == 96 || b == 124 || b == 126 { + return fmt.Sprintf("/%%DCN%04d%%/", b) + } else { + return string(b) + } + } + + key := chr(nibble_swap(lock[0] ^ lock[len(lock)-2] ^ lock[len(lock)-3] ^ 5)) + for i := 1; i < len(lock); i += 1 { + key += chr(nibble_swap(lock[i] ^ lock[i-1])) + } + + return key +} diff --git a/vendor/code.ivysaur.me/libnmdc/NmdcProtocol_test.go b/vendor/code.ivysaur.me/libnmdc/NmdcProtocol_test.go new file mode 100644 index 0000000..70c4f34 --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/NmdcProtocol_test.go @@ -0,0 +1,97 @@ +package libnmdc + +import ( + "testing" +) + +func TestMyINFOParse(t *testing.T) { + + np := NewNmdcProtocol(nil).(*NmdcProtocol) + + type myInfoTestPair struct { + in string + expect UserInfo + } + + cases := []myInfoTestPair{ + + myInfoTestPair{ + in: "$ALL Bxxxy description$ $0.01\x01$xyz@example.com$53054999578$", + expect: UserInfo{ + Nick: "Bxxxy", + Description: "description", + ClientTag: "ApexDC++", + ClientVersion: "1.4.3", + Email: "xyz@example.com", + ShareSize: 53054999578, + Flag: FLAG_NORMAL, + Slots: 1, + HubsUnregistered: 9, + HubsRegistered: 0, + HubsOperator: 2, + UserInfo_NMDCOnly: UserInfo_NMDCOnly{ + ConnectionMode: CONNECTIONMODE_PASSIVE, + Speed: "0.0", + }, + }, + }, + myInfoTestPair{ + in: "$ALL ixxxxxxx0 $P$10A$$0$", + expect: UserInfo{ + Nick: "ixxxxxxx0", + ClientVersion: "0", // Auto-inserted by the parser for short-format MyINFO strings + Flag: UserFlag(rune('A')), + UserInfo_NMDCOnly: UserInfo_NMDCOnly{ + ConnectionMode: CONNECTIONMODE_PASSIVE, + Speed: "1", + }, + }, + }, + myInfoTestPair{ + in: "$ALL SXXXX_XXXXXXR $ $0.005Q$$0$", + expect: UserInfo{ + Nick: "SXXXX_XXXXXXR", + ClientTag: "ncdc", + ClientVersion: "1.19.1-12-g5561", + Flag: UserFlag(rune('Q')), + Slots: 10, + HubsUnregistered: 1, + UserInfo_NMDCOnly: UserInfo_NMDCOnly{ + ConnectionMode: CONNECTIONMODE_PASSIVE, + Speed: "0.00", + }, + }, + }, + myInfoTestPair{ + in: "$ALL mxxxu desccccc$ $p$$0$", + expect: UserInfo{ + Nick: "mxxxu", + Description: "desccccc", + ClientTag: "HexChat", + ClientVersion: "2.12.1", + Flag: UserFlag(rune('p')), + HubsUnregistered: 1, + Slots: 0, + UserInfo_NMDCOnly: UserInfo_NMDCOnly{ + ConnectionMode: CONNECTIONMODE_PASSIVE, + }, + }, + }, + } + + for _, v := range cases { + + got, err := np.parseMyINFO(v.in) + + if err != nil { + t.Errorf("MyINFO parse warning (%s)", err.Error()) + continue + } + + if *got != v.expect { + t.Errorf("MyINFO parse failure\nExpected:\n%+v\nGot:\n%+v\n", v.expect, got) + continue + } + } + +} diff --git a/vendor/code.ivysaur.me/libnmdc/Protocol.go b/vendor/code.ivysaur.me/libnmdc/Protocol.go new file mode 100644 index 0000000..e587a11 --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/Protocol.go @@ -0,0 +1,31 @@ +package libnmdc + +type Protocol interface { + ProcessCommand(msg string) + + SayPublic(string) + + SayPrivate(user, message string) + + ProtoMessageSeparator() string +} + +type HubProtocol int + +const ( + HubProtocolAutodetect HubProtocol = 0 + HubProtocolNmdc HubProtocol = 1 + HubProtocolAdc HubProtocol = 2 +) + +func (hp HubProtocol) Create(hc *HubConnection) Protocol { + if hp == HubProtocolNmdc { + return NewNmdcProtocol(hc) + + } else if hp == HubProtocolAdc { + return NewAdcProtocol(hc) + + } else { + return NewAutodetectProtocol(hc) + } +} diff --git a/vendor/code.ivysaur.me/libnmdc/TODO.txt b/vendor/code.ivysaur.me/libnmdc/TODO.txt new file mode 100644 index 0000000..bd95b9b --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/TODO.txt @@ -0,0 +1,6 @@ +NMDC: +- Implement ZPipe ($ZOn) + +ADC: +- Usercommands +- ??? diff --git a/vendor/code.ivysaur.me/libnmdc/UserCommand.go b/vendor/code.ivysaur.me/libnmdc/UserCommand.go new file mode 100644 index 0000000..6b7c0a5 --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/UserCommand.go @@ -0,0 +1,27 @@ +package libnmdc + +type UserCommandType uint8 + +const ( + USERCOMMAND_TYPE_SEPARATOR UserCommandType = 0 + USERCOMMAND_TYPE_RAW UserCommandType = 1 + USERCOMMAND_TYPE_NICKLIMITED UserCommandType = 2 + USERCOMMAND_TYPE_CLEARALL UserCommandType = 255 +) + +type UserCommandContext uint8 + +const ( + USERCOMMAND_CONTEXT_HUB UserCommandContext = 1 + USERCOMMAND_CONTEXT_USER UserCommandContext = 2 + USERCOMMAND_CONTEXT_SEARCH UserCommandContext = 4 + USERCOMMAND_CONTEXT_FILELIST UserCommandContext = 8 +) + +type UserCommand struct { + Type UserCommandType + Context UserCommandContext + Message string + Command string + RemoveThis bool // Currently only set by ADC hubs +} diff --git a/vendor/code.ivysaur.me/libnmdc/UserFlag.go b/vendor/code.ivysaur.me/libnmdc/UserFlag.go new file mode 100644 index 0000000..7664aea --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/UserFlag.go @@ -0,0 +1,17 @@ +package libnmdc + +type UserFlag byte + +const ( + FLAG_NORMAL UserFlag = 1 + FLAG_AWAY_1 UserFlag = 2 + FLAG_AWAY_2 UserFlag = 3 + FLAG_SERVER_1 UserFlag = 4 + FLAG_SERVER_2 UserFlag = 5 + FLAG_SERVER_AWAY_1 UserFlag = 6 + FLAG_SERVER_AWAY_2 UserFlag = 7 + FLAG_FIREBALL_1 UserFlag = 8 + FLAG_FIREBALL_2 UserFlag = 9 + FLAG_FIREBALL_AWAY_1 UserFlag = 10 + FLAG_FIREBALL_AWAY_2 UserFlag = 11 +) diff --git a/vendor/code.ivysaur.me/libnmdc/UserInfo.go b/vendor/code.ivysaur.me/libnmdc/UserInfo.go new file mode 100644 index 0000000..9450e9e --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/UserInfo.go @@ -0,0 +1,53 @@ +package libnmdc + +// This structure represents a user connected to a hub. +type UserInfo struct { + Nick string + Description string + ClientTag string + ClientVersion string + Email string + ShareSize uint64 + Flag UserFlag + Slots uint64 + HubsUnregistered uint64 + HubsRegistered uint64 + HubsOperator uint64 + IsOperator bool + + UserInfo_NMDCOnly + UserInfo_ADCOnly +} + +type UserInfo_NMDCOnly struct { + Speed string + IPAddress string + ConnectionMode ConnectionMode +} + +type UserInfo_ADCOnly struct { + SharedFiles uint64 + UploadSpeedBps uint64 + DownloadSpeedBps uint64 + IsBot bool + IsRegistered bool + IsSuperUser bool + IsHubOwner bool + IPv4Address string // Passive <==> these fields are not set + IPv6Address string + IPv4UDPPort uint64 + IPv6UDPPort uint64 + Keyprint string + CID string + SupportFlags map[string]struct{} +} + +func NewUserInfo(username string) *UserInfo { + return &UserInfo{ + Nick: username, + HubsUnregistered: 1, + UserInfo_NMDCOnly: UserInfo_NMDCOnly{ + ConnectionMode: CONNECTIONMODE_PASSIVE, + }, + } +} diff --git a/vendor/code.ivysaur.me/libnmdc/__dist/README.txt b/vendor/code.ivysaur.me/libnmdc/__dist/README.txt new file mode 100644 index 0000000..e1edf59 --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/__dist/README.txt @@ -0,0 +1,98 @@ +An NMDC / ADC client protocol library for Golang. + +Written in golang +Tags: nmdc + +=FEATURES= + +- Connect to NMDC and ADC hubs +- SSL (NMDCS/ADCS) with option to ignore certificate validity +- Autodetect NMDC/ADC protocol by timeout +- Send public and private chat messages, UserCommand support +- Protocol keepalives +- Parse user details (including UserIP2 for NMDC) +- Fast NMDC login via NoHello and QuickList +- Both synchronous (callback) and asynchronous (channel) -based APIs, including example + +=GO GET= + +This package can be installed via go get: `go get code.ivysaur.me/libnmdc` +[go-get]code.ivysaur.me/libnmdc git https://git.ivysaur.me/code.ivysaur.me/libnmdc.git[/go-get] + +=CHANGELOG= + +2017-11-26 0.16 +- Feature: Support connecting to ADC hubs +- BREAKING: Simplify connection API +- Vendor new dependency on github.com/cxmcc/tiger (MIT license) + +2017-11-14 0.15 +- Feature: Fallback reconnection if no data (not even keepalives) are recieved from the hub in 24 hours +- Fix an issue with detecting protocol messages inside multi-line chat messages +- Update examples and the default client version number + +2017-02-09 0.14 +- Fix an issue with crashing on malformed IP addresses supplied by the hub + +2017-02-09 0.13 +- Feature: Implement UserIP2 extension, to retrieve IP addresses of other users +- Enhancement: Implement QuickList extension (reduce one network roundtrip during initial connection) +- Enhancement: Implement NoHello extension (faster connection performance) +- Enhancement: Implement ChatOnly extension +- Fix an issue with not notifying client on all MyINFO updates + +2017-02-05 0.12 +- Fix an issue with mutex deadlock when accessing user information from a callback +- Fix an issue with silent disconnection if a password was required but not present + +2016-11-29 0.11 +- BREAKING: Remove some exported methods +- BREAKING: Fix an issue with missing sufficient parameters in the synchronous API +- Enhancement: Improve output under godoc +- Fix an issue with special characters appearing in recieved private messages +- Fix an issue with parsing active/passive connection modes +- Fix an issue with errors appearing on stdout + +2016-10-08 r10 +- Feature: Support `$UserCommand` + +2016-08-27 r9 +- Fix an issue with parsing MyINFO strings with zero-length speed descriptions +- Fix an issue with not storing updated profile information + +2016-05-10 r8 +- Enhancement: Separate `ClientTag` and `ClientVersion` in `UserInfo` structs + +2016-05-08 r7 +- BREAKING: Remove direct access to `HubConnection.Users` map +- Feature: Threadsafe user map accessor +- Feature: Option to disable auto-reconnection +- Feature: New `Disconnect()`, `UserCount()`, `UserExists()` functions +- Enhancement: Support `$OpList`, add `IsOperator` member to `UserInfo` structs +- Refactor into multiple files + +2016-04-16 r6 +- Fix an issue with calling `panic()` on certain types of abnormal network failure + +2016-04-04 r5 +- Enhancement: Support protocol keepalives +- Enhancement: Support hub redirects (`$ForceMove`) + +2016-04-03 r4 +- Feature: Add synchronous API +- Fix an issue with reading HubConnection's state parameter +- Fix an issue with buffered protocol commands + +2016-04-03 r3 +- Feature: Add `SkipVerifyTLS` option +- Fix an issue with calling `panic()` if connection failed + +2016-04-02 r2 +- Enhancement: Support NMDC-over-TLS (NMDCS) +- Fix an issue recieving private messages +- Fix an issue with calling `panic()` if connection failed +- Fix an issue parsing URIs without a specified port +- Move sample content into directory with excluded build + +2016-02-12 r1 +- Initial public release diff --git a/vendor/code.ivysaur.me/libnmdc/libnmdc.go b/vendor/code.ivysaur.me/libnmdc/libnmdc.go new file mode 100644 index 0000000..bb7fd94 --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/libnmdc.go @@ -0,0 +1,28 @@ +package libnmdc + +import ( + "errors" + "strconv" + "time" +) + +const ( + DEFAULT_CLIENT_TAG string = "libnmdc.go" + DEFAULT_CLIENT_VERSION string = "0.16" + DEFAULT_HUB_NAME string = "(unknown)" + SEND_KEEPALIVE_EVERY time.Duration = 29 * time.Second + AUTO_RECONNECT_AFTER time.Duration = 30 * time.Second + RECONNECT_IF_NO_DATA_RECIEVED_IN time.Duration = 24 * time.Hour // we expect keepalives wayyyy more frequently than this + AUTODETECT_ADC_NMDC_TIMEOUT time.Duration = 3 * time.Second +) + +var ErrNotConnected error = errors.New("Not connected") + +func maybeParse(str string, dest *uint64, default_val uint64) { + sz, err := strconv.ParseUint(str, 10, 64) + if err == nil { + *dest = sz + } else { + *dest = default_val + } +} diff --git a/vendor/code.ivysaur.me/libnmdc/tth.go b/vendor/code.ivysaur.me/libnmdc/tth.go new file mode 100644 index 0000000..612bef4 --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/tth.go @@ -0,0 +1,41 @@ +package libnmdc + +import ( + "encoding/base32" + "errors" + "strings" + + "github.com/cxmcc/tiger" +) + +// Base32 encodes the input slice in BASE32 string format without any trailing +// padding equals characters. +func Base32(input []byte) string { + return strings.TrimRight(base32.StdEncoding.EncodeToString(input), "=") +} + +// TTH returns the TTH hash of a string in raw byte format. Use the Base32() +// function to convert it to normal string format. +// This is a basic implementation that only supports content up to 1024 bytes in length. +func TTH(input string) ([]byte, error) { + + // Short segments do not need to be padded. + // Content above 1024 bytes needs tree handling (0x00 prefix for leaf nodes, + // 0x01 prefix for hash nodes) but for content less than 1024 bytes, just + // return the leaf hash + // @ref http://adc.sourceforge.net/draft-jchapweske-thex-02.html + if len(input) > 1024 { + return nil, errors.New("TTH content exceeded 1024 bytes") + } + + // Single leaf hash only + leafHash := tiger.New() + leafHash.Write([]byte("\x00" + input)) + return leafHash.Sum(nil), nil +} + +func Tiger(input string) []byte { + leafHash := tiger.New() + leafHash.Write([]byte(input)) + return leafHash.Sum(nil) +} diff --git a/vendor/code.ivysaur.me/libnmdc/tth_test.go b/vendor/code.ivysaur.me/libnmdc/tth_test.go new file mode 100644 index 0000000..817c61e --- /dev/null +++ b/vendor/code.ivysaur.me/libnmdc/tth_test.go @@ -0,0 +1,36 @@ +package libnmdc + +import ( + "strings" + "testing" +) + +func TestTTH(t *testing.T) { + + // echo -n 'hello world' | tthsum + testCases := [][2]string{ + [2]string{"hello world", "ZIIVRZDR2FD3W4KKNMNYUU3765LPPK7BWY64CHI"}, + [2]string{"", "LWPNACQDBZRYXW3VHJVCJ64QBZNGHOHHHZWCLNQ"}, + [2]string{"\x00", "VK54ZIEEVTWNAUI5D5RDFIL37LX2IQNSTAXFKSA"}, + [2]string{strings.Repeat("A", 1024), "L66Q4YVNAFWVS23X2HJIRA5ZJ7WXR3F26RSASFA"}, + } + + short := func(s string) string { + if len(s) > 15 { + return s[0:15] + "..." + } + return s + } + + for _, testCase := range testCases { + input, expected := testCase[0], testCase[1] + result, err := TTH(input) + if err != nil { + t.Fatalf("Error getting TTH for '%s': %s", short(input), err.Error()) + } + + if Base32(result) != expected { + t.Fatalf("Wrong TTH for '%s' (got '%s' expected '%s')", short(input), result, expected) + } + } +} diff --git a/vendor/github.com/cxmcc/tiger/.gitignore b/vendor/github.com/cxmcc/tiger/.gitignore new file mode 100644 index 0000000..0026861 --- /dev/null +++ b/vendor/github.com/cxmcc/tiger/.gitignore @@ -0,0 +1,22 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/vendor/github.com/cxmcc/tiger/.travis.yml b/vendor/github.com/cxmcc/tiger/.travis.yml new file mode 100644 index 0000000..69d2f6d --- /dev/null +++ b/vendor/github.com/cxmcc/tiger/.travis.yml @@ -0,0 +1,7 @@ +language: go + +go: + - 1.x + - 1.6 + - 1.7.x + - master diff --git a/vendor/github.com/cxmcc/tiger/LICENSE b/vendor/github.com/cxmcc/tiger/LICENSE new file mode 100644 index 0000000..c811438 --- /dev/null +++ b/vendor/github.com/cxmcc/tiger/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 Xiuming Chen + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/cxmcc/tiger/README.md b/vendor/github.com/cxmcc/tiger/README.md new file mode 100644 index 0000000..5306b7f --- /dev/null +++ b/vendor/github.com/cxmcc/tiger/README.md @@ -0,0 +1,48 @@ +Tiger cryptographic hash function for Go + +----- + +[![Build Status](https://travis-ci.org/cxmcc/tiger.svg?branch=master)](https://travis-ci.org/cxmcc/tiger) +[![GoDoc](http://godoc.org/github.com/cxmcc/tiger?status.png)](http://godoc.org/github.com/cxmcc/tiger) + + +### About Tiger + +* Tiger cryptographic hash function is designed by Ross Anderson and Eli Biham in 1995. +* The size of a Tiger hash value is 192 bits. Truncated versions (Tiger/128, Tiger/160) are simply prefixes of Tiger/192. +* Tiger2 is a variant where the message is padded by first appending a byte 0x80, rather than 0x01 as in the case of Tiger. +* Links: [paper](http://www.cs.technion.ac.il/~biham/Reports/Tiger/), [wikipedia](http://en.wikipedia.org/wiki/Tiger_\(cryptography\)) + +### API Documentation + +Implementing [hash.Hash](http://golang.org/pkg/hash/#Hash). Usage is pretty much the same as other stanard hashing libraries. +Documentation currently available at Godoc: [http://godoc.org/github.com/cxmcc/tiger](http://godoc.org/github.com/cxmcc/tiger) + + +### Installing +~~~ +go get github.com/cxmcc/tiger +~~~ + +### Example +~~~ go +package main + +import ( + "fmt" + "io" + "github.com/cxmcc/tiger" +) + +func main() { + h := tiger.New() + io.WriteString(h, "Example for tiger") + fmt.Printf("Output: %x\n", h.Sum(nil)) + // Output: 82bd060e19f945014f0063e8f0e6d7decfa9edfd97e76743 +} +~~~ + + +### License + +It's MIT License diff --git a/vendor/github.com/cxmcc/tiger/compress.go b/vendor/github.com/cxmcc/tiger/compress.go new file mode 100644 index 0000000..9da8b33 --- /dev/null +++ b/vendor/github.com/cxmcc/tiger/compress.go @@ -0,0 +1,96 @@ +package tiger + +import ( + "encoding/binary" + "unsafe" +) + +var littleEndian bool + +func init() { + x := uint32(0x04030201) + y := [4]byte{0x1, 0x2, 0x3, 0x4} + littleEndian = *(*[4]byte)(unsafe.Pointer(&x)) == y +} + +func pass(a, b, c uint64, x []uint64, mul uint64) (uint64, uint64, uint64) { + a, b, c = round(a, b, c, x[0], mul) + b, c, a = round(b, c, a, x[1], mul) + c, a, b = round(c, a, b, x[2], mul) + a, b, c = round(a, b, c, x[3], mul) + b, c, a = round(b, c, a, x[4], mul) + c, a, b = round(c, a, b, x[5], mul) + a, b, c = round(a, b, c, x[6], mul) + b, c, a = round(b, c, a, x[7], mul) + return a, b, c +} + +func round(a, b, c, x, mul uint64) (uint64, uint64, uint64) { + c ^= x + a -= t1[c&0xff] ^ t2[(c>>16)&0xff] ^ t3[(c>>32)&0xff] ^ t4[(c>>48)&0xff] + b += t4[(c>>8)&0xff] ^ t3[(c>>24)&0xff] ^ t2[(c>>40)&0xff] ^ t1[(c>>56)&0xff] + b *= mul + return a, b, c +} + +func keySchedule(x []uint64) { + x[0] -= x[7] ^ 0xa5a5a5a5a5a5a5a5 + x[1] ^= x[0] + x[2] += x[1] + x[3] -= x[2] ^ ((^x[1]) << 19) + x[4] ^= x[3] + x[5] += x[4] + x[6] -= x[5] ^ ((^x[4]) >> 23) + x[7] ^= x[6] + x[0] += x[7] + x[1] -= x[0] ^ ((^x[7]) << 19) + x[2] ^= x[1] + x[3] += x[2] + x[4] -= x[3] ^ ((^x[2]) >> 23) + x[5] ^= x[4] + x[6] += x[5] + x[7] -= x[6] ^ 0x0123456789abcdef +} + +func (d *digest) compress(data []byte) { + // save_abc + a := d.a + b := d.b + c := d.c + + var x []uint64 + if littleEndian { + x = []uint64{ + binary.LittleEndian.Uint64(data[0:8]), + binary.LittleEndian.Uint64(data[8:16]), + binary.LittleEndian.Uint64(data[16:24]), + binary.LittleEndian.Uint64(data[24:32]), + binary.LittleEndian.Uint64(data[32:40]), + binary.LittleEndian.Uint64(data[40:48]), + binary.LittleEndian.Uint64(data[48:56]), + binary.LittleEndian.Uint64(data[56:64]), + } + } else { + x = []uint64{ + binary.BigEndian.Uint64(data[0:8]), + binary.BigEndian.Uint64(data[8:16]), + binary.BigEndian.Uint64(data[16:24]), + binary.BigEndian.Uint64(data[24:32]), + binary.BigEndian.Uint64(data[32:40]), + binary.BigEndian.Uint64(data[40:48]), + binary.BigEndian.Uint64(data[48:56]), + binary.BigEndian.Uint64(data[56:64]), + } + } + + d.a, d.b, d.c = pass(d.a, d.b, d.c, x, 5) + keySchedule(x) + d.c, d.a, d.b = pass(d.c, d.a, d.b, x, 7) + keySchedule(x) + d.b, d.c, d.a = pass(d.b, d.c, d.a, x, 9) + + // feedforward + d.a ^= a + d.b -= b + d.c += c +} diff --git a/vendor/github.com/cxmcc/tiger/sboxes.go b/vendor/github.com/cxmcc/tiger/sboxes.go new file mode 100644 index 0000000..cd05dff --- /dev/null +++ b/vendor/github.com/cxmcc/tiger/sboxes.go @@ -0,0 +1,269 @@ +package tiger + +var t1 = [...]uint64{ + 0x02aab17cf7e90c5e, 0xac424b03e243a8ec, 0x72cd5be30dd5fcd3, 0x6d019b93f6f97f3a, + 0xcd9978ffd21f9193, 0x7573a1c9708029e2, 0xb164326b922a83c3, 0x46883eee04915870, + 0xeaace3057103ece6, 0xc54169b808a3535c, 0x4ce754918ddec47c, 0x0aa2f4dfdc0df40c, + 0x10b76f18a74dbefa, 0xc6ccb6235ad1ab6a, 0x13726121572fe2ff, 0x1a488c6f199d921e, + 0x4bc9f9f4da0007ca, 0x26f5e6f6e85241c7, 0x859079dbea5947b6, 0x4f1885c5c99e8c92, + 0xd78e761ea96f864b, 0x8e36428c52b5c17d, 0x69cf6827373063c1, 0xb607c93d9bb4c56e, + 0x7d820e760e76b5ea, 0x645c9cc6f07fdc42, 0xbf38a078243342e0, 0x5f6b343c9d2e7d04, + 0xf2c28aeb600b0ec6, 0x6c0ed85f7254bcac, 0x71592281a4db4fe5, 0x1967fa69ce0fed9f, + 0xfd5293f8b96545db, 0xc879e9d7f2a7600b, 0x860248920193194e, 0xa4f9533b2d9cc0b3, + 0x9053836c15957613, 0xdb6dcf8afc357bf1, 0x18beea7a7a370f57, 0x037117ca50b99066, + 0x6ab30a9774424a35, 0xf4e92f02e325249b, 0x7739db07061ccae1, 0xd8f3b49ceca42a05, + 0xbd56be3f51382f73, 0x45faed5843b0bb28, 0x1c813d5c11bf1f83, 0x8af0e4b6d75fa169, + 0x33ee18a487ad9999, 0x3c26e8eab1c94410, 0xb510102bc0a822f9, 0x141eef310ce6123b, + 0xfc65b90059ddb154, 0xe0158640c5e0e607, 0x884e079826c3a3cf, 0x930d0d9523c535fd, + 0x35638d754e9a2b00, 0x4085fccf40469dd5, 0xc4b17ad28be23a4c, 0xcab2f0fc6a3e6a2e, + 0x2860971a6b943fcd, 0x3dde6ee212e30446, 0x6222f32ae01765ae, 0x5d550bb5478308fe, + 0xa9efa98da0eda22a, 0xc351a71686c40da7, 0x1105586d9c867c84, 0xdcffee85fda22853, + 0xccfbd0262c5eef76, 0xbaf294cb8990d201, 0xe69464f52afad975, 0x94b013afdf133e14, + 0x06a7d1a32823c958, 0x6f95fe5130f61119, 0xd92ab34e462c06c0, 0xed7bde33887c71d2, + 0x79746d6e6518393e, 0x5ba419385d713329, 0x7c1ba6b948a97564, 0x31987c197bfdac67, + 0xde6c23c44b053d02, 0x581c49fed002d64d, 0xdd474d6338261571, 0xaa4546c3e473d062, + 0x928fce349455f860, 0x48161bbacaab94d9, 0x63912430770e6f68, 0x6ec8a5e602c6641c, + 0x87282515337ddd2b, 0x2cda6b42034b701b, 0xb03d37c181cb096d, 0xe108438266c71c6f, + 0x2b3180c7eb51b255, 0xdf92b82f96c08bbc, 0x5c68c8c0a632f3ba, 0x5504cc861c3d0556, + 0xabbfa4e55fb26b8f, 0x41848b0ab3baceb4, 0xb334a273aa445d32, 0xbca696f0a85ad881, + 0x24f6ec65b528d56c, 0x0ce1512e90f4524a, 0x4e9dd79d5506d35a, 0x258905fac6ce9779, + 0x2019295b3e109b33, 0xf8a9478b73a054cc, 0x2924f2f934417eb0, 0x3993357d536d1bc4, + 0x38a81ac21db6ff8b, 0x47c4fbf17d6016bf, 0x1e0faadd7667e3f5, 0x7abcff62938beb96, + 0xa78dad948fc179c9, 0x8f1f98b72911e50d, 0x61e48eae27121a91, 0x4d62f7ad31859808, + 0xeceba345ef5ceaeb, 0xf5ceb25ebc9684ce, 0xf633e20cb7f76221, 0xa32cdf06ab8293e4, + 0x985a202ca5ee2ca4, 0xcf0b8447cc8a8fb1, 0x9f765244979859a3, 0xa8d516b1a1240017, + 0x0bd7ba3ebb5dc726, 0xe54bca55b86adb39, 0x1d7a3afd6c478063, 0x519ec608e7669edd, + 0x0e5715a2d149aa23, 0x177d4571848ff194, 0xeeb55f3241014c22, 0x0f5e5ca13a6e2ec2, + 0x8029927b75f5c361, 0xad139fabc3d6e436, 0x0d5df1a94ccf402f, 0x3e8bd948bea5dfc8, + 0xa5a0d357bd3ff77e, 0xa2d12e251f74f645, 0x66fd9e525e81a082, 0x2e0c90ce7f687a49, + 0xc2e8bcbeba973bc5, 0x000001bce509745f, 0x423777bbe6dab3d6, 0xd1661c7eaef06eb5, + 0xa1781f354daacfd8, 0x2d11284a2b16affc, 0xf1fc4f67fa891d1f, 0x73ecc25dcb920ada, + 0xae610c22c2a12651, 0x96e0a810d356b78a, 0x5a9a381f2fe7870f, 0xd5ad62ede94e5530, + 0xd225e5e8368d1427, 0x65977b70c7af4631, 0x99f889b2de39d74f, 0x233f30bf54e1d143, + 0x9a9675d3d9a63c97, 0x5470554ff334f9a8, 0x166acb744a4f5688, 0x70c74caab2e4aead, + 0xf0d091646f294d12, 0x57b82a89684031d1, 0xefd95a5a61be0b6b, 0x2fbd12e969f2f29a, + 0x9bd37013feff9fe8, 0x3f9b0404d6085a06, 0x4940c1f3166cfe15, 0x09542c4dcdf3defb, + 0xb4c5218385cd5ce3, 0xc935b7dc4462a641, 0x3417f8a68ed3b63f, 0xb80959295b215b40, + 0xf99cdaef3b8c8572, 0x018c0614f8fcb95d, 0x1b14accd1a3acdf3, 0x84d471f200bb732d, + 0xc1a3110e95e8da16, 0x430a7220bf1a82b8, 0xb77e090d39df210e, 0x5ef4bd9f3cd05e9d, + 0x9d4ff6da7e57a444, 0xda1d60e183d4a5f8, 0xb287c38417998e47, 0xfe3edc121bb31886, + 0xc7fe3ccc980ccbef, 0xe46fb590189bfd03, 0x3732fd469a4c57dc, 0x7ef700a07cf1ad65, + 0x59c64468a31d8859, 0x762fb0b4d45b61f6, 0x155baed099047718, 0x68755e4c3d50baa6, + 0xe9214e7f22d8b4df, 0x2addbf532eac95f4, 0x32ae3909b4bd0109, 0x834df537b08e3450, + 0xfa209da84220728d, 0x9e691d9b9efe23f7, 0x0446d288c4ae8d7f, 0x7b4cc524e169785b, + 0x21d87f0135ca1385, 0xcebb400f137b8aa5, 0x272e2b66580796be, 0x3612264125c2b0de, + 0x057702bdad1efbb2, 0xd4babb8eacf84be9, 0x91583139641bc67b, 0x8bdc2de08036e024, + 0x603c8156f49f68ed, 0xf7d236f7dbef5111, 0x9727c4598ad21e80, 0xa08a0896670a5fd7, + 0xcb4a8f4309eba9cb, 0x81af564b0f7036a1, 0xc0b99aa778199abd, 0x959f1ec83fc8e952, + 0x8c505077794a81b9, 0x3acaaf8f056338f0, 0x07b43f50627a6778, 0x4a44ab49f5eccc77, + 0x3bc3d6e4b679ee98, 0x9cc0d4d1cf14108c, 0x4406c00b206bc8a0, 0x82a18854c8d72d89, + 0x67e366b35c3c432c, 0xb923dd61102b37f2, 0x56ab2779d884271d, 0xbe83e1b0ff1525af, + 0xfb7c65d4217e49a9, 0x6bdbe0e76d48e7d4, 0x08df828745d9179e, 0x22ea6a9add53bd34, + 0xe36e141c5622200a, 0x7f805d1b8cb750ee, 0xafe5c7a59f58e837, 0xe27f996a4fb1c23c, + 0xd3867dfb0775f0d0, 0xd0e673de6e88891a, 0x123aeb9eafb86c25, 0x30f1d5d5c145b895, + 0xbb434a2dee7269e7, 0x78cb67ecf931fa38, 0xf33b0372323bbf9c, 0x52d66336fb279c74, + 0x505f33ac0afb4eaa, 0xe8a5cd99a2cce187, 0x534974801e2d30bb, 0x8d2d5711d5876d90, + 0x1f1a412891bc038e, 0xd6e2e71d82e56648, 0x74036c3a497732b7, 0x89b67ed96361f5ab, + 0xffed95d8f1ea02a2, 0xe72b3bd61464d43d, 0xa6300f170bdc4820, 0xebc18760ed78a77a, +} + +var t2 = [...]uint64{ + 0xe6a6be5a05a12138, 0xb5a122a5b4f87c98, 0x563c6089140b6990, 0x4c46cb2e391f5dd5, + 0xd932addbc9b79434, 0x08ea70e42015aff5, 0xd765a6673e478cf1, 0xc4fb757eab278d99, + 0xdf11c6862d6e0692, 0xddeb84f10d7f3b16, 0x6f2ef604a665ea04, 0x4a8e0f0ff0e0dfb3, + 0xa5edeef83dbcba51, 0xfc4f0a2a0ea4371e, 0xe83e1da85cb38429, 0xdc8ff882ba1b1ce2, + 0xcd45505e8353e80d, 0x18d19a00d4db0717, 0x34a0cfeda5f38101, 0x0be77e518887caf2, + 0x1e341438b3c45136, 0xe05797f49089ccf9, 0xffd23f9df2591d14, 0x543dda228595c5cd, + 0x661f81fd99052a33, 0x8736e641db0f7b76, 0x15227725418e5307, 0xe25f7f46162eb2fa, + 0x48a8b2126c13d9fe, 0xafdc541792e76eea, 0x03d912bfc6d1898f, 0x31b1aafa1b83f51b, + 0xf1ac2796e42ab7d9, 0x40a3a7d7fcd2ebac, 0x1056136d0afbbcc5, 0x7889e1dd9a6d0c85, + 0xd33525782a7974aa, 0xa7e25d09078ac09b, 0xbd4138b3eac6edd0, 0x920abfbe71eb9e70, + 0xa2a5d0f54fc2625c, 0xc054e36b0b1290a3, 0xf6dd59ff62fe932b, 0x3537354511a8ac7d, + 0xca845e9172fadcd4, 0x84f82b60329d20dc, 0x79c62ce1cd672f18, 0x8b09a2add124642c, + 0xd0c1e96a19d9e726, 0x5a786a9b4ba9500c, 0x0e020336634c43f3, 0xc17b474aeb66d822, + 0x6a731ae3ec9baac2, 0x8226667ae0840258, 0x67d4567691caeca5, 0x1d94155c4875adb5, + 0x6d00fd985b813fdf, 0x51286efcb774cd06, 0x5e8834471fa744af, 0xf72ca0aee761ae2e, + 0xbe40e4cdaee8e09a, 0xe9970bbb5118f665, 0x726e4beb33df1964, 0x703b000729199762, + 0x4631d816f5ef30a7, 0xb880b5b51504a6be, 0x641793c37ed84b6c, 0x7b21ed77f6e97d96, + 0x776306312ef96b73, 0xae528948e86ff3f4, 0x53dbd7f286a3f8f8, 0x16cadce74cfc1063, + 0x005c19bdfa52c6dd, 0x68868f5d64d46ad3, 0x3a9d512ccf1e186a, 0x367e62c2385660ae, + 0xe359e7ea77dcb1d7, 0x526c0773749abe6e, 0x735ae5f9d09f734b, 0x493fc7cc8a558ba8, + 0xb0b9c1533041ab45, 0x321958ba470a59bd, 0x852db00b5f46c393, 0x91209b2bd336b0e5, + 0x6e604f7d659ef19f, 0xb99a8ae2782ccb24, 0xccf52ab6c814c4c7, 0x4727d9afbe11727b, + 0x7e950d0c0121b34d, 0x756f435670ad471f, 0xf5add442615a6849, 0x4e87e09980b9957a, + 0x2acfa1df50aee355, 0xd898263afd2fd556, 0xc8f4924dd80c8fd6, 0xcf99ca3d754a173a, + 0xfe477bacaf91bf3c, 0xed5371f6d690c12d, 0x831a5c285e687094, 0xc5d3c90a3708a0a4, + 0x0f7f903717d06580, 0x19f9bb13b8fdf27f, 0xb1bd6f1b4d502843, 0x1c761ba38fff4012, + 0x0d1530c4e2e21f3b, 0x8943ce69a7372c8a, 0xe5184e11feb5ce66, 0x618bdb80bd736621, + 0x7d29bad68b574d0b, 0x81bb613e25e6fe5b, 0x071c9c10bc07913f, 0xc7beeb7909ac2d97, + 0xc3e58d353bc5d757, 0xeb017892f38f61e8, 0xd4effb9c9b1cc21a, 0x99727d26f494f7ab, + 0xa3e063a2956b3e03, 0x9d4a8b9a4aa09c30, 0x3f6ab7d500090fb4, 0x9cc0f2a057268ac0, + 0x3dee9d2dedbf42d1, 0x330f49c87960a972, 0xc6b2720287421b41, 0x0ac59ec07c00369c, + 0xef4eac49cb353425, 0xf450244eef0129d8, 0x8acc46e5caf4deb6, 0x2ffeab63989263f7, + 0x8f7cb9fe5d7a4578, 0x5bd8f7644e634635, 0x427a7315bf2dc900, 0x17d0c4aa2125261c, + 0x3992486c93518e50, 0xb4cbfee0a2d7d4c3, 0x7c75d6202c5ddd8d, 0xdbc295d8e35b6c61, + 0x60b369d302032b19, 0xce42685fdce44132, 0x06f3ddb9ddf65610, 0x8ea4d21db5e148f0, + 0x20b0fce62fcd496f, 0x2c1b912358b0ee31, 0xb28317b818f5a308, 0xa89c1e189ca6d2cf, + 0x0c6b18576aaadbc8, 0xb65deaa91299fae3, 0xfb2b794b7f1027e7, 0x04e4317f443b5beb, + 0x4b852d325939d0a6, 0xd5ae6beefb207ffc, 0x309682b281c7d374, 0xbae309a194c3b475, + 0x8cc3f97b13b49f05, 0x98a9422ff8293967, 0x244b16b01076ff7c, 0xf8bf571c663d67ee, + 0x1f0d6758eee30da1, 0xc9b611d97adeb9b7, 0xb7afd5887b6c57a2, 0x6290ae846b984fe1, + 0x94df4cdeacc1a5fd, 0x058a5bd1c5483aff, 0x63166cc142ba3c37, 0x8db8526eb2f76f40, + 0xe10880036f0d6d4e, 0x9e0523c9971d311d, 0x45ec2824cc7cd691, 0x575b8359e62382c9, + 0xfa9e400dc4889995, 0xd1823ecb45721568, 0xdafd983b8206082f, 0xaa7d29082386a8cb, + 0x269fcd4403b87588, 0x1b91f5f728bdd1e0, 0xe4669f39040201f6, 0x7a1d7c218cf04ade, + 0x65623c29d79ce5ce, 0x2368449096c00bb1, 0xab9bf1879da503ba, 0xbc23ecb1a458058e, + 0x9a58df01bb401ecc, 0xa070e868a85f143d, 0x4ff188307df2239e, 0x14d565b41a641183, + 0xee13337452701602, 0x950e3dcf3f285e09, 0x59930254b9c80953, 0x3bf299408930da6d, + 0xa955943f53691387, 0xa15edecaa9cb8784, 0x29142127352be9a0, 0x76f0371fff4e7afb, + 0x0239f450274f2228, 0xbb073af01d5e868b, 0xbfc80571c10e96c1, 0xd267088568222e23, + 0x9671a3d48e80b5b0, 0x55b5d38ae193bb81, 0x693ae2d0a18b04b8, 0x5c48b4ecadd5335f, + 0xfd743b194916a1ca, 0x2577018134be98c4, 0xe77987e83c54a4ad, 0x28e11014da33e1b9, + 0x270cc59e226aa213, 0x71495f756d1a5f60, 0x9be853fb60afef77, 0xadc786a7f7443dbf, + 0x0904456173b29a82, 0x58bc7a66c232bd5e, 0xf306558c673ac8b2, 0x41f639c6b6c9772a, + 0x216defe99fda35da, 0x11640cc71c7be615, 0x93c43694565c5527, 0xea038e6246777839, + 0xf9abf3ce5a3e2469, 0x741e768d0fd312d2, 0x0144b883ced652c6, 0xc20b5a5ba33f8552, + 0x1ae69633c3435a9d, 0x97a28ca4088cfdec, 0x8824a43c1e96f420, 0x37612fa66eeea746, + 0x6b4cb165f9cf0e5a, 0x43aa1c06a0abfb4a, 0x7f4dc26ff162796b, 0x6cbacc8e54ed9b0f, + 0xa6b7ffefd2bb253e, 0x2e25bc95b0a29d4f, 0x86d6a58bdef1388c, 0xded74ac576b6f054, + 0x8030bdbc2b45805d, 0x3c81af70e94d9289, 0x3eff6dda9e3100db, 0xb38dc39fdfcc8847, + 0x123885528d17b87e, 0xf2da0ed240b1b642, 0x44cefadcd54bf9a9, 0x1312200e433c7ee6, + 0x9ffcc84f3a78c748, 0xf0cd1f72248576bb, 0xec6974053638cfe4, 0x2ba7b67c0cec4e4c, + 0xac2f4df3e5ce32ed, 0xcb33d14326ea4c11, 0xa4e9044cc77e58bc, 0x5f513293d934fcef, + 0x5dc9645506e55444, 0x50de418f317de40a, 0x388cb31a69dde259, 0x2db4a83455820a86, + 0x9010a91e84711ae9, 0x4df7f0b7b1498371, 0xd62a2eabc0977179, 0x22fac097aa8d5c0e, +} + +var t3 = [...]uint64{ + 0xf49fcc2ff1daf39b, 0x487fd5c66ff29281, 0xe8a30667fcdca83f, 0x2c9b4be3d2fcce63, + 0xda3ff74b93fbbbc2, 0x2fa165d2fe70ba66, 0xa103e279970e93d4, 0xbecdec77b0e45e71, + 0xcfb41e723985e497, 0xb70aaa025ef75017, 0xd42309f03840b8e0, 0x8efc1ad035898579, + 0x96c6920be2b2abc5, 0x66af4163375a9172, 0x2174abdcca7127fb, 0xb33ccea64a72ff41, + 0xf04a4933083066a5, 0x8d970acdd7289af5, 0x8f96e8e031c8c25e, 0xf3fec02276875d47, + 0xec7bf310056190dd, 0xf5adb0aebb0f1491, 0x9b50f8850fd58892, 0x4975488358b74de8, + 0xa3354ff691531c61, 0x0702bbe481d2c6ee, 0x89fb24057deded98, 0xac3075138596e902, + 0x1d2d3580172772ed, 0xeb738fc28e6bc30d, 0x5854ef8f63044326, 0x9e5c52325add3bbe, + 0x90aa53cf325c4623, 0xc1d24d51349dd067, 0x2051cfeea69ea624, 0x13220f0a862e7e4f, + 0xce39399404e04864, 0xd9c42ca47086fcb7, 0x685ad2238a03e7cc, 0x066484b2ab2ff1db, + 0xfe9d5d70efbf79ec, 0x5b13b9dd9c481854, 0x15f0d475ed1509ad, 0x0bebcd060ec79851, + 0xd58c6791183ab7f8, 0xd1187c5052f3eee4, 0xc95d1192e54e82ff, 0x86eea14cb9ac6ca2, + 0x3485beb153677d5d, 0xdd191d781f8c492a, 0xf60866baa784ebf9, 0x518f643ba2d08c74, + 0x8852e956e1087c22, 0xa768cb8dc410ae8d, 0x38047726bfec8e1a, 0xa67738b4cd3b45aa, + 0xad16691cec0dde19, 0xc6d4319380462e07, 0xc5a5876d0ba61938, 0x16b9fa1fa58fd840, + 0x188ab1173ca74f18, 0xabda2f98c99c021f, 0x3e0580ab134ae816, 0x5f3b05b773645abb, + 0x2501a2be5575f2f6, 0x1b2f74004e7e8ba9, 0x1cd7580371e8d953, 0x7f6ed89562764e30, + 0xb15926ff596f003d, 0x9f65293da8c5d6b9, 0x6ecef04dd690f84c, 0x4782275fff33af88, + 0xe41433083f820801, 0xfd0dfe409a1af9b5, 0x4325a3342cdb396b, 0x8ae77e62b301b252, + 0xc36f9e9f6655615a, 0x85455a2d92d32c09, 0xf2c7dea949477485, 0x63cfb4c133a39eba, + 0x83b040cc6ebc5462, 0x3b9454c8fdb326b0, 0x56f56a9e87ffd78c, 0x2dc2940d99f42bc6, + 0x98f7df096b096e2d, 0x19a6e01e3ad852bf, 0x42a99ccbdbd4b40b, 0xa59998af45e9c559, + 0x366295e807d93186, 0x6b48181bfaa1f773, 0x1fec57e2157a0a1d, 0x4667446af6201ad5, + 0xe615ebcacfb0f075, 0xb8f31f4f68290778, 0x22713ed6ce22d11e, 0x3057c1a72ec3c93b, + 0xcb46acc37c3f1f2f, 0xdbb893fd02aaf50e, 0x331fd92e600b9fcf, 0xa498f96148ea3ad6, + 0xa8d8426e8b6a83ea, 0xa089b274b7735cdc, 0x87f6b3731e524a11, 0x118808e5cbc96749, + 0x9906e4c7b19bd394, 0xafed7f7e9b24a20c, 0x6509eadeeb3644a7, 0x6c1ef1d3e8ef0ede, + 0xb9c97d43e9798fb4, 0xa2f2d784740c28a3, 0x7b8496476197566f, 0x7a5be3e6b65f069d, + 0xf96330ed78be6f10, 0xeee60de77a076a15, 0x2b4bee4aa08b9bd0, 0x6a56a63ec7b8894e, + 0x02121359ba34fef4, 0x4cbf99f8283703fc, 0x398071350caf30c8, 0xd0a77a89f017687a, + 0xf1c1a9eb9e423569, 0x8c7976282dee8199, 0x5d1737a5dd1f7abd, 0x4f53433c09a9fa80, + 0xfa8b0c53df7ca1d9, 0x3fd9dcbc886ccb77, 0xc040917ca91b4720, 0x7dd00142f9d1dcdf, + 0x8476fc1d4f387b58, 0x23f8e7c5f3316503, 0x032a2244e7e37339, 0x5c87a5d750f5a74b, + 0x082b4cc43698992e, 0xdf917becb858f63c, 0x3270b8fc5bf86dda, 0x10ae72bb29b5dd76, + 0x576ac94e7700362b, 0x1ad112dac61efb8f, 0x691bc30ec5faa427, 0xff246311cc327143, + 0x3142368e30e53206, 0x71380e31e02ca396, 0x958d5c960aad76f1, 0xf8d6f430c16da536, + 0xc8ffd13f1be7e1d2, 0x7578ae66004ddbe1, 0x05833f01067be646, 0xbb34b5ad3bfe586d, + 0x095f34c9a12b97f0, 0x247ab64525d60ca8, 0xdcdbc6f3017477d1, 0x4a2e14d4decad24d, + 0xbdb5e6d9be0a1eeb, 0x2a7e70f7794301ab, 0xdef42d8a270540fd, 0x01078ec0a34c22c1, + 0xe5de511af4c16387, 0x7ebb3a52bd9a330a, 0x77697857aa7d6435, 0x004e831603ae4c32, + 0xe7a21020ad78e312, 0x9d41a70c6ab420f2, 0x28e06c18ea1141e6, 0xd2b28cbd984f6b28, + 0x26b75f6c446e9d83, 0xba47568c4d418d7f, 0xd80badbfe6183d8e, 0x0e206d7f5f166044, + 0xe258a43911cbca3e, 0x723a1746b21dc0bc, 0xc7caa854f5d7cdd3, 0x7cac32883d261d9c, + 0x7690c26423ba942c, 0x17e55524478042b8, 0xe0be477656a2389f, 0x4d289b5e67ab2da0, + 0x44862b9c8fbbfd31, 0xb47cc8049d141365, 0x822c1b362b91c793, 0x4eb14655fb13dfd8, + 0x1ecbba0714e2a97b, 0x6143459d5cde5f14, 0x53a8fbf1d5f0ac89, 0x97ea04d81c5e5b00, + 0x622181a8d4fdb3f3, 0xe9bcd341572a1208, 0x1411258643cce58a, 0x9144c5fea4c6e0a4, + 0x0d33d06565cf620f, 0x54a48d489f219ca1, 0xc43e5eac6d63c821, 0xa9728b3a72770daf, + 0xd7934e7b20df87ef, 0xe35503b61a3e86e5, 0xcae321fbc819d504, 0x129a50b3ac60bfa6, + 0xcd5e68ea7e9fb6c3, 0xb01c90199483b1c7, 0x3de93cd5c295376c, 0xaed52edf2ab9ad13, + 0x2e60f512c0a07884, 0xbc3d86a3e36210c9, 0x35269d9b163951ce, 0x0c7d6e2ad0cdb5fa, + 0x59e86297d87f5733, 0x298ef221898db0e7, 0x55000029d1a5aa7e, 0x8bc08ae1b5061b45, + 0xc2c31c2b6c92703a, 0x94cc596baf25ef42, 0x0a1d73db22540456, 0x04b6a0f9d9c4179a, + 0xeffdafa2ae3d3c60, 0xf7c8075bb49496c4, 0x9cc5c7141d1cd4e3, 0x78bd1638218e5534, + 0xb2f11568f850246a, 0xedfabcfa9502bc29, 0x796ce5f2da23051b, 0xaae128b0dc93537c, + 0x3a493da0ee4b29ae, 0xb5df6b2c416895d7, 0xfcabbd25122d7f37, 0x70810b58105dc4b1, + 0xe10fdd37f7882a90, 0x524dcab5518a3f5c, 0x3c9e85878451255b, 0x4029828119bd34e2, + 0x74a05b6f5d3ceccb, 0xb610021542e13eca, 0x0ff979d12f59e2ac, 0x6037da27e4f9cc50, + 0x5e92975a0df1847d, 0xd66de190d3e623fe, 0x5032d6b87b568048, 0x9a36b7ce8235216e, + 0x80272a7a24f64b4a, 0x93efed8b8c6916f7, 0x37ddbff44cce1555, 0x4b95db5d4b99bd25, + 0x92d3fda169812fc0, 0xfb1a4a9a90660bb6, 0x730c196946a4b9b2, 0x81e289aa7f49da68, + 0x64669a0f83b1a05f, 0x27b3ff7d9644f48b, 0xcc6b615c8db675b3, 0x674f20b9bcebbe95, + 0x6f31238275655982, 0x5ae488713e45cf05, 0xbf619f9954c21157, 0xeabac46040a8eae9, + 0x454c6fe9f2c0c1cd, 0x419cf6496412691c, 0xd3dc3bef265b0f70, 0x6d0e60f5c3578a9e, +} + +var t4 = [...]uint64{ + 0x5b0e608526323c55, 0x1a46c1a9fa1b59f5, 0xa9e245a17c4c8ffa, 0x65ca5159db2955d7, + 0x05db0a76ce35afc2, 0x81eac77ea9113d45, 0x528ef88ab6ac0a0d, 0xa09ea253597be3ff, + 0x430ddfb3ac48cd56, 0xc4b3a67af45ce46f, 0x4ececfd8fbe2d05e, 0x3ef56f10b39935f0, + 0x0b22d6829cd619c6, 0x17fd460a74df2069, 0x6cf8cc8e8510ed40, 0xd6c824bf3a6ecaa7, + 0x61243d581a817049, 0x048bacb6bbc163a2, 0xd9a38ac27d44cc32, 0x7fddff5baaf410ab, + 0xad6d495aa804824b, 0xe1a6a74f2d8c9f94, 0xd4f7851235dee8e3, 0xfd4b7f886540d893, + 0x247c20042aa4bfda, 0x096ea1c517d1327c, 0xd56966b4361a6685, 0x277da5c31221057d, + 0x94d59893a43acff7, 0x64f0c51ccdc02281, 0x3d33bcc4ff6189db, 0xe005cb184ce66af1, + 0xff5ccd1d1db99bea, 0xb0b854a7fe42980f, 0x7bd46a6a718d4b9f, 0xd10fa8cc22a5fd8c, + 0xd31484952be4bd31, 0xc7fa975fcb243847, 0x4886ed1e5846c407, 0x28cddb791eb70b04, + 0xc2b00be2f573417f, 0x5c9590452180f877, 0x7a6bddfff370eb00, 0xce509e38d6d9d6a4, + 0xebeb0f00647fa702, 0x1dcc06cf76606f06, 0xe4d9f28ba286ff0a, 0xd85a305dc918c262, + 0x475b1d8732225f54, 0x2d4fb51668ccb5fe, 0xa679b9d9d72bba20, 0x53841c0d912d43a5, + 0x3b7eaa48bf12a4e8, 0x781e0e47f22f1ddf, 0xeff20ce60ab50973, 0x20d261d19dffb742, + 0x16a12b03062a2e39, 0x1960eb2239650495, 0x251c16fed50eb8b8, 0x9ac0c330f826016e, + 0xed152665953e7671, 0x02d63194a6369570, 0x5074f08394b1c987, 0x70ba598c90b25ce1, + 0x794a15810b9742f6, 0x0d5925e9fcaf8c6c, 0x3067716cd868744e, 0x910ab077e8d7731b, + 0x6a61bbdb5ac42f61, 0x93513efbf0851567, 0xf494724b9e83e9d5, 0xe887e1985c09648d, + 0x34b1d3c675370cfd, 0xdc35e433bc0d255d, 0xd0aab84234131be0, 0x08042a50b48b7eaf, + 0x9997c4ee44a3ab35, 0x829a7b49201799d0, 0x263b8307b7c54441, 0x752f95f4fd6a6ca6, + 0x927217402c08c6e5, 0x2a8ab754a795d9ee, 0xa442f7552f72943d, 0x2c31334e19781208, + 0x4fa98d7ceaee6291, 0x55c3862f665db309, 0xbd0610175d53b1f3, 0x46fe6cb840413f27, + 0x3fe03792df0cfa59, 0xcfe700372eb85e8f, 0xa7be29e7adbce118, 0xe544ee5cde8431dd, + 0x8a781b1b41f1873e, 0xa5c94c78a0d2f0e7, 0x39412e2877b60728, 0xa1265ef3afc9a62c, + 0xbcc2770c6a2506c5, 0x3ab66dd5dce1ce12, 0xe65499d04a675b37, 0x7d8f523481bfd216, + 0x0f6f64fcec15f389, 0x74efbe618b5b13c8, 0xacdc82b714273e1d, 0xdd40bfe003199d17, + 0x37e99257e7e061f8, 0xfa52626904775aaa, 0x8bbbf63a463d56f9, 0xf0013f1543a26e64, + 0xa8307e9f879ec898, 0xcc4c27a4150177cc, 0x1b432f2cca1d3348, 0xde1d1f8f9f6fa013, + 0x606602a047a7ddd6, 0xd237ab64cc1cb2c7, 0x9b938e7225fcd1d3, 0xec4e03708e0ff476, + 0xfeb2fbda3d03c12d, 0xae0bced2ee43889a, 0x22cb8923ebfb4f43, 0x69360d013cf7396d, + 0x855e3602d2d4e022, 0x073805bad01f784c, 0x33e17a133852f546, 0xdf4874058ac7b638, + 0xba92b29c678aa14a, 0x0ce89fc76cfaadcd, 0x5f9d4e0908339e34, 0xf1afe9291f5923b9, + 0x6e3480f60f4a265f, 0xeebf3a2ab29b841c, 0xe21938a88f91b4ad, 0x57dfeff845c6d3c3, + 0x2f006b0bf62caaf2, 0x62f479ef6f75ee78, 0x11a55ad41c8916a9, 0xf229d29084fed453, + 0x42f1c27b16b000e6, 0x2b1f76749823c074, 0x4b76eca3c2745360, 0x8c98f463b91691bd, + 0x14bcc93cf1ade66a, 0x8885213e6d458397, 0x8e177df0274d4711, 0xb49b73b5503f2951, + 0x10168168c3f96b6b, 0x0e3d963b63cab0ae, 0x8dfc4b5655a1db14, 0xf789f1356e14de5c, + 0x683e68af4e51dac1, 0xc9a84f9d8d4b0fd9, 0x3691e03f52a0f9d1, 0x5ed86e46e1878e80, + 0x3c711a0e99d07150, 0x5a0865b20c4e9310, 0x56fbfc1fe4f0682e, 0xea8d5de3105edf9b, + 0x71abfdb12379187a, 0x2eb99de1bee77b9c, 0x21ecc0ea33cf4523, 0x59a4d7521805c7a1, + 0x3896f5eb56ae7c72, 0xaa638f3db18f75dc, 0x9f39358dabe9808e, 0xb7defa91c00b72ac, + 0x6b5541fd62492d92, 0x6dc6dee8f92e4d5b, 0x353f57abc4beea7e, 0x735769d6da5690ce, + 0x0a234aa642391484, 0xf6f9508028f80d9d, 0xb8e319a27ab3f215, 0x31ad9c1151341a4d, + 0x773c22a57bef5805, 0x45c7561a07968633, 0xf913da9e249dbe36, 0xda652d9b78a64c68, + 0x4c27a97f3bc334ef, 0x76621220e66b17f4, 0x967743899acd7d0b, 0xf3ee5bcae0ed6782, + 0x409f753600c879fc, 0x06d09a39b5926db6, 0x6f83aeb0317ac588, 0x01e6ca4a86381f21, + 0x66ff3462d19f3025, 0x72207c24ddfd3bfb, 0x4af6b6d3e2ece2eb, 0x9c994dbec7ea08de, + 0x49ace597b09a8bc4, 0xb38c4766cf0797ba, 0x131b9373c57c2a75, 0xb1822cce61931e58, + 0x9d7555b909ba1c0c, 0x127fafdd937d11d2, 0x29da3badc66d92e4, 0xa2c1d57154c2ecbc, + 0x58c5134d82f6fe24, 0x1c3ae3515b62274f, 0xe907c82e01cb8126, 0xf8ed091913e37fcb, + 0x3249d8f9c80046c9, 0x80cf9bede388fb63, 0x1881539a116cf19e, 0x5103f3f76bd52457, + 0x15b7e6f5ae47f7a8, 0xdbd7c6ded47e9ccf, 0x44e55c410228bb1a, 0xb647d4255edb4e99, + 0x5d11882bb8aafc30, 0xf5098bbb29d3212a, 0x8fb5ea14e90296b3, 0x677b942157dd025a, + 0xfb58e7c0a390acb5, 0x89d3674c83bd4a01, 0x9e2da4df4bf3b93b, 0xfcc41e328cab4829, + 0x03f38c96ba582c52, 0xcad1bdbd7fd85db2, 0xbbb442c16082ae83, 0xb95fe86ba5da9ab0, + 0xb22e04673771a93f, 0x845358c9493152d8, 0xbe2a488697b4541e, 0x95a2dc2dd38e6966, + 0xc02c11ac923c852b, 0x2388b1990df2a87b, 0x7c8008fa1b4f37be, 0x1f70d0c84d54e503, + 0x5490adec7ece57d4, 0x002b3c27d9063a3a, 0x7eaea3848030a2bf, 0xc602326ded2003c0, + 0x83a7287d69a94086, 0xc57a5fcb30f57a8a, 0xb56844e479ebe779, 0xa373b40f05dcbce9, + 0xd71a786e88570ee2, 0x879cbacdbde8f6a0, 0x976ad1bcc164a32f, 0xab21e25e9666d78b, + 0x901063aae5e5c33c, 0x9818b34448698d90, 0xe36487ae3e1e8abb, 0xafbdf931893bdcb4, + 0x6345a0dc5fbbd519, 0x8628fe269b9465ca, 0x1e5d01603f9c51ec, 0x4de44006a15049b7, + 0xbf6c70e5f776cbb1, 0x411218f2ef552bed, 0xcb0c0708705a36a3, 0xe74d14754f986044, + 0xcd56d9430ea8280e, 0xc12591d7535f5065, 0xc83223f1720aef96, 0xc3a0396f7363a51f, +} diff --git a/vendor/github.com/cxmcc/tiger/tiger.go b/vendor/github.com/cxmcc/tiger/tiger.go new file mode 100644 index 0000000..504bd66 --- /dev/null +++ b/vendor/github.com/cxmcc/tiger/tiger.go @@ -0,0 +1,117 @@ +// Package tiger implements the Tiger hash algorithm +// https://github.com/cxmcc/tiger +package tiger + +import "hash" + +// The size of a Tiger hash value in bytes +const Size = 24 + +// The blocksize of Tiger hash function in bytes +const BlockSize = 64 + +const ( + chunk = 64 + initA = 0x0123456789abcdef + initB = 0xfedcba9876543210 + initC = 0xf096a5b4c3b2e187 +) + +type digest struct { + a uint64 + b uint64 + c uint64 + x [chunk]byte + nx int + length uint64 + ver int +} + +func (d *digest) Reset() { + d.a = initA + d.b = initB + d.c = initC + d.nx = 0 + d.length = 0 +} + +// New returns a new hash.Hash computing the Tiger hash value +func New() hash.Hash { + d := new(digest) + d.Reset() + d.ver = 1 + return d +} + +// New returns a new hash.Hash computing the Tiger2 hash value +func New2() hash.Hash { + d := new(digest) + d.Reset() + d.ver = 2 + return d +} + +func (d *digest) BlockSize() int { + return BlockSize +} + +func (d *digest) Size() int { + return Size +} + +func (d *digest) Write(p []byte) (length int, err error) { + length = len(p) + d.length += uint64(length) + if d.nx > 0 { + n := len(p) + if n > chunk-d.nx { + n = chunk - d.nx + } + copy(d.x[d.nx:d.nx+n], p[:n]) + d.nx += n + if d.nx == chunk { + d.compress(d.x[:chunk]) + d.nx = 0 + } + p = p[n:] + } + for len(p) >= chunk { + d.compress(p[:chunk]) + p = p[chunk:] + } + if len(p) > 0 { + d.nx = copy(d.x[:], p) + } + return +} + +func (d digest) Sum(in []byte) []byte { + length := d.length + var tmp [64]byte + if d.ver == 1 { + tmp[0] = 0x01 + } else { + tmp[0] = 0x80 + } + + size := length & 0x3f + if size < 56 { + d.Write(tmp[:56-size]) + } else { + d.Write(tmp[:64+56-size]) + } + + length <<= 3 + for i := uint(0); i < 8; i++ { + tmp[i] = byte(length >> (8 * i)) + } + d.Write(tmp[:8]) + + for i := uint(0); i < 8; i++ { + tmp[i] = byte(d.a >> (8 * i)) + tmp[i+8] = byte(d.b >> (8 * i)) + tmp[i+16] = byte(d.c >> (8 * i)) + } + + return append(in, tmp[:24]...) +} diff --git a/vendor/github.com/cxmcc/tiger/tiger_test.go b/vendor/github.com/cxmcc/tiger/tiger_test.go new file mode 100644 index 0000000..a7068aa --- /dev/null +++ b/vendor/github.com/cxmcc/tiger/tiger_test.go @@ -0,0 +1,144 @@ +package tiger + +import ( + "fmt" + "io" + "strings" + "testing" + "unsafe" +) + +type Test struct { + out string + in string +} + +var golden = []Test{ + {"3293ac630c13f0245f92bbb1766e16167a4e58492dde73f3", ""}, + {"77befbef2e7ef8ab2ec8f93bf587a7fc613e247f5f247809", "a"}, + {"2aab1484e8c158f2bfb8c5ff41b57a525129131c957b5f93", "abc"}, + {"d981f8cb78201a950dcf3048751e441c517fca1aa55a29f6", "message digest"}, + {"1714a472eee57d30040412bfcc55032a0b11602ff37beee9", "abcdefghijklmnopqrstuvwxyz"}, + {"0f7bf9a19b9c58f2b7610df7e84f0ac3a71c631e7b53f78e", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"}, + {"8dcea680a17583ee502ba38a3c368651890ffbccdc49a8cc", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"}, + {"1c14795529fd9f207a958f84c52f11e887fa0cabdfd91bfd", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"}, + {"cdf0990c5c6b6b0bddd63a75ed20e2d448bf44e15fde0df4", strings.Repeat("A", 1024)}, + {"89292aee0f82842abc080c57b3aadd9ca84d66bf0cae77aa", strings.Repeat("A", 1025)}, +} + +func TestGolden(t *testing.T) { + for i := 0; i < len(golden); i++ { + g := golden[i] + c := New() + buf := make([]byte, len(g.in)+4) + for j := 0; j < 7; j++ { + if j < 2 { + io.WriteString(c, g.in) + } else if j == 2 { + io.WriteString(c, g.in[0:len(g.in)/2]) + c.Sum(nil) + io.WriteString(c, g.in[len(g.in)/2:]) + } else if j > 2 { + // test unaligned write + buf = buf[1:] + copy(buf, g.in) + c.Write(buf[:len(g.in)]) + } + s := fmt.Sprintf("%x", c.Sum(nil)) + if s != g.out { + t.Fatalf("tiger[%d](%s) = %s want %s", j, g.in, s, g.out) + } + c.Reset() + } + } +} + +type WriteTest struct { + out int + in string +} + +var writeTestVectors = []WriteTest{ + {0, ""}, + {1, "A"}, + {2, "AA"}, + {10, strings.Repeat("A", 10)}, + {1024, strings.Repeat("A", 1024)}, + {1025, strings.Repeat("A", 1025)}, + {0, ""}, +} + +func TestWriteReturnsCorrectSize(t *testing.T) { + c := New() + for i := 0; i < len(writeTestVectors); i++ { + v := writeTestVectors[i] + b := []byte(v.in) + length, err := c.Write(b[:len(v.in)]) + if length != v.out { + t.Fatalf("Write() = %d want %d", length, v.out) + } + if err != nil { + t.Fatalf("Write(%s) failed.", v.in) + } + } +} + +func ExampleNew() { + h := New() + io.WriteString(h, "It's the eye of the tiger, it's the thrill of the fight") + io.WriteString(h, "Rising up to the challenge of our rival!") + fmt.Printf("%x", h.Sum(nil)) + // Output: a7bbad36cc17918e399ae8ee893e4595e4d24e1639fe822c +} + +func ExampleNew2() { + h := New2() + io.WriteString(h, "It's the eye of the tiger, it's the thrill of the fight") + io.WriteString(h, "Rising up to the challenge of our rival!") + fmt.Printf("%x", h.Sum(nil)) + // Output: c86695c2a639506682de2c12c2d23b61a12db78ea1ee1001 +} + +var bench = New() +var buf = make([]byte, 8192+1) +var sum = make([]byte, bench.Size()) + +func benchmarkSize(b *testing.B, size int, unaligned bool) { + b.SetBytes(int64(size)) + buf := buf + if unaligned { + if uintptr(unsafe.Pointer(&buf[0]))&(unsafe.Alignof(uint32(0))-1) == 0 { + buf = buf[1:] + } + } + b.ResetTimer() + for i := 0; i < b.N; i++ { + bench.Reset() + bench.Write(buf[:size]) + bench.Sum(sum[:0]) + } +} + +func BenchmarkHash8Bytes(b *testing.B) { + benchmarkSize(b, 8, false) +} + +func BenchmarkHash1K(b *testing.B) { + benchmarkSize(b, 1024, false) +} + +func BenchmarkHash8K(b *testing.B) { + benchmarkSize(b, 8192, false) +} + +func BenchmarkHash8BytesUnaligned(b *testing.B) { + benchmarkSize(b, 8, true) +} + +func BenchmarkHash1KUnaligned(b *testing.B) { + benchmarkSize(b, 1024, true) +} + +func BenchmarkHash8KUnaligned(b *testing.B) { + benchmarkSize(b, 8192, true) +} diff --git a/vendor/github.com/googollee/go-engine.io/.travis.yml b/vendor/github.com/googollee/go-engine.io/.travis.yml new file mode 100644 index 0000000..0a5134f --- /dev/null +++ b/vendor/github.com/googollee/go-engine.io/.travis.yml @@ -0,0 +1,7 @@ +language: go +go: 1.5 +install: + - go get "github.com/smartystreets/goconvey/convey" + - go get -v . +script: + - go test -race -v ./... diff --git a/vendor/github.com/googollee/go-engine.io/LICENSE b/vendor/github.com/googollee/go-engine.io/LICENSE new file mode 100644 index 0000000..04a4430 --- /dev/null +++ b/vendor/github.com/googollee/go-engine.io/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2014-2014 Googol Lee + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/vendor/github.com/googollee/go-engine.io/README.md b/vendor/github.com/googollee/go-engine.io/README.md new file mode 100644 index 0000000..c5d603f --- /dev/null +++ b/vendor/github.com/googollee/go-engine.io/README.md @@ -0,0 +1,78 @@ +# go-engine.io + +[![GoDoc](http://godoc.org/github.com/googollee/go-engine.io?status.svg)](http://godoc.org/github.com/googollee/go-engine.io) [![Build Status](https://travis-ci.org/googollee/go-engine.io.svg)](https://travis-ci.org/googollee/go-engine.io) + +go-engine.io is the implement of engine.io in golang, which is transport-based cross-browser/cross-device bi-directional communication layer for [go-socket.io](https://github.com/googollee/go-socket.io). + +It is compatible with node.js implement, and supported long-polling and websocket transport. + +## Install + +Install the package with: + +```bash +go get github.com/googollee/go-engine.io +``` + +Import it with: + +```go +import "github.com/googollee/go-engine.io" +``` + +and use `engineio` as the package name inside the code. + +## Example + +Please check example folder for details. + +```go +package main + +import ( + "encoding/hex" + "io/ioutil" + "log" + "net/http" + + "github.com/googollee/go-engine.io" +) + +func main() { + server, err := engineio.NewServer(nil) + if err != nil { + log.Fatal(err) + } + + go func() { + for { + conn, _ := server.Accept() + go func() { + defer conn.Close() + for i := 0; i < 10; i++ { + t, r, _ := conn.NextReader() + b, _ := ioutil.ReadAll(r) + r.Close() + if t == engineio.MessageText { + log.Println(t, string(b)) + } else { + log.Println(t, hex.EncodeToString(b)) + } + w, _ := conn.NextWriter(t) + w.Write([]byte("pong")) + w.Close() + } + }() + } + }() + + http.Handle("/engine.io/", server) + http.Handle("/", http.FileServer(http.Dir("./asset"))) + log.Println("Serving at localhost:5000...") + log.Fatal(http.ListenAndServe(":5000", nil)) +} +``` + +## License + +The 3-clause BSD License - see LICENSE for more details \ No newline at end of file diff --git a/vendor/github.com/googollee/go-engine.io/example/asset/index.html b/vendor/github.com/googollee/go-engine.io/example/asset/index.html new file mode 100644 index 0000000..a89d95d --- /dev/null +++ b/vendor/github.com/googollee/go-engine.io/example/asset/index.html @@ -0,0 +1,14 @@ + + + + EIO Latency + + + +

EIO Latency

+

(connecting)

+ + + + + diff --git a/vendor/github.com/googollee/go-engine.io/example/asset/index.js b/vendor/github.com/googollee/go-engine.io/example/asset/index.js new file mode 100644 index 0000000..2822d97 --- /dev/null +++ b/vendor/github.com/googollee/go-engine.io/example/asset/index.js @@ -0,0 +1,4137 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o