Compare commits

...

9 Commits

18 changed files with 80 additions and 282 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
__dist/

View File

@ -1,14 +0,0 @@
mode:regex
# Compilation output
\.(?:exe|a)$
^pkg/
# Dependencies
^src/(?:github.com|gopkg.in|golang.org)/
# Scratch space
^src/nmdc/
# Binary release artefacts
/?__dist/

21
.hgtags
View File

@ -1,21 +0,0 @@
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
a48811ff2cfe5246c26801cf27da25bf56fec8bb v0.16.0

View File

@ -468,8 +468,8 @@ func (this *AdcProtocol) ourINFO(includePid bool) string {
return ret[1:]
}
func (this *AdcProtocol) SayInfo() {
this.hc.SayRaw("BINF " + this.escape(this.sid) + " " + this.ourINFO(true) + "\n")
func (this *AdcProtocol) SayInfo() error {
return this.hc.SayRaw("BINF " + this.escape(this.sid) + " " + this.ourINFO(true) + "\n")
}
func (this *AdcProtocol) parts2flags(parts []string) (map[string]string, error) {
@ -614,16 +614,17 @@ func (this *AdcProtocol) unescape(encoded string) string {
return strings.Replace(v2, `\\`, `\`, -1)
}
func (this *AdcProtocol) SayPublic(msg string) {
this.hc.SayRaw("BMSG " + this.sid + " " + this.escape(msg) + "\n")
func (this *AdcProtocol) SayPublic(msg string) error {
return 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) SayPrivate(user, message string) error {
sid, ok := this.Nick2SID(user)
if !ok {
return fmt.Errorf("Unknown user '%s'", user)
}
return this.hc.SayRaw("DMSG " + this.sid + " " + sid + " " + this.escape(message) + "\n")
}
func (this *AdcProtocol) ProtoMessageSeparator() string {

View File

@ -49,34 +49,34 @@ func (this *AutodetectProtocol) ProcessCommand(msg string) {
this.realProto.ProcessCommand(msg)
}
func (this *AutodetectProtocol) SayPublic(msg string) {
func (this *AutodetectProtocol) SayPublic(msg string) error {
this.realProtoMut.Lock()
defer this.realProtoMut.Unlock()
if this.realProto == nil {
this.realProto = NewNmdcProtocol(this.hc)
}
this.realProto.SayPublic(msg)
return this.realProto.SayPublic(msg)
}
func (this *AutodetectProtocol) SayPrivate(user, message string) {
func (this *AutodetectProtocol) SayPrivate(user, message string) error {
this.realProtoMut.Lock()
defer this.realProtoMut.Unlock()
if this.realProto == nil {
this.realProto = NewNmdcProtocol(this.hc)
}
this.realProto.SayPrivate(user, message)
return this.realProto.SayPrivate(user, message)
}
func (this *AutodetectProtocol) SayInfo() {
func (this *AutodetectProtocol) SayInfo() error {
this.realProtoMut.Lock()
defer this.realProtoMut.Unlock()
if this.realProto == nil {
this.realProto = NewNmdcProtocol(this.hc)
}
this.realProto.SayInfo()
return this.realProto.SayInfo()
}
func (this *AutodetectProtocol) ProtoMessageSeparator() string {

15
Gopkg.lock generated
View File

@ -1,15 +0,0 @@
# 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

View File

@ -1,26 +0,0 @@
# 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"

View File

@ -41,16 +41,25 @@ func (this *HubConnection) Users(cb func(*map[string]UserInfo) error) error {
return cb(&this.users)
}
func (this *HubConnection) SayPublic(message string) {
this.proto.SayPublic(message)
func (this *HubConnection) SayPublic(message string) error {
if this.proto == nil {
return ErrNotConnected
}
return this.proto.SayPublic(message)
}
func (this *HubConnection) SayPrivate(recipient string, message string) {
this.proto.SayPrivate(recipient, message)
func (this *HubConnection) SayPrivate(recipient string, message string) error {
if this.proto == nil {
return ErrNotConnected
}
return this.proto.SayPrivate(recipient, message)
}
func (this *HubConnection) SayInfo() {
this.proto.SayInfo()
func (this *HubConnection) SayInfo() error {
if this.proto == nil {
return ErrNotConnected
}
return this.proto.SayInfo()
}
func (this *HubConnection) UserExists(nick string) bool {

View File

@ -14,6 +14,7 @@ const (
EVENT_HUBNAME_CHANGED HubEventType = 9
EVENT_DEBUG_MESSAGE HubEventType = 10
EVENT_USERCOMMAND HubEventType = 11
EVENT_BAD_LOGIN_FAILURE HubEventType = 12
)
type HubEvent struct {

View File

@ -94,6 +94,7 @@ func (this *NmdcProtocol) ProcessCommand(message string) {
this.hc.processEvent(HubEvent{EventType: EVENT_HUBNAME_CHANGED, Nick: commandParts[1]})
case "$ValidateDenide": // sic
this.hc.processEvent(HubEvent{EventType: EVENT_BAD_LOGIN_FAILURE})
if len(this.hc.Hco.NickPassword) > 0 {
this.hc.processEvent(HubEvent{EventType: EVENT_SYSTEM_MESSAGE_FROM_CONN, Message: "Incorrect password."})
} else {
@ -101,15 +102,18 @@ func (this *NmdcProtocol) ProcessCommand(message string) {
}
case "$HubIsFull":
this.hc.processEvent(HubEvent{EventType: EVENT_BAD_LOGIN_FAILURE})
this.hc.processEvent(HubEvent{EventType: EVENT_SYSTEM_MESSAGE_FROM_CONN, Message: "Hub is full."})
case "$BadPass":
this.hc.processEvent(HubEvent{EventType: EVENT_BAD_LOGIN_FAILURE})
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_BAD_LOGIN_FAILURE})
this.hc.processEvent(HubEvent{EventType: EVENT_SYSTEM_MESSAGE_FROM_CONN, Message: "This account is passworded."})
this.hc.Disconnect()
} else {
@ -292,16 +296,16 @@ func (this *NmdcProtocol) unescape(encoded string) string {
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) SayPublic(message string) error {
return 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) SayPrivate(recipient, message string) error {
return 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) SayInfo() error {
return this.hc.SayRaw(this.getUserMyINFO(this.hc.Hco.Self) + "|")
}
func (this *NmdcProtocol) parseMyINFO(protomsg string) (*UserInfo, error) {

View File

@ -3,11 +3,11 @@ package libnmdc
type Protocol interface {
ProcessCommand(msg string)
SayPublic(string)
SayPublic(string) error
SayPrivate(user, message string)
SayPrivate(user, message string) error
SayInfo()
SayInfo() error
ProtoMessageSeparator() string
}

View File

@ -1,9 +1,10 @@
# libnmdc
An NMDC / ADC client protocol library for Golang.
Written in golang
Tags: nmdc
Install via go get: `go get code.ivysaur.me/libnmdc`
=FEATURES=
## Features
- Connect to NMDC and ADC hubs
- SSL (NMDCS/ADCS) with option to ignore certificate validity
@ -14,41 +15,41 @@ Tags: nmdc
- Fast NMDC login via NoHello and QuickList
- Both synchronous (callback) and asynchronous (channel) -based APIs, including example
=GO GET=
## Changelog
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]
2018-12-31 0.18.0
- BREAKING: Return error from more functions
- Feature: Add new `EVENT` constant to detect connection failures caused by bad password, hub full, etc
- Convert to Go Modules
=CHANGELOG=
2018-03-24 0.17
2018-03-24 0.17.0
- Feature: Re-add sayInfo() function for reannouncing MyINFO changes
2017-11-26 0.16
2017-11-26 0.16.0
- 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
2017-11-14 0.15.0
- 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
2017-02-09 0.14.0
- Fix an issue with crashing on malformed IP addresses supplied by the hub
2017-02-09 0.13
2017-02-09 0.13.0
- 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
2017-02-05 0.12.0
- 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
2016-11-29 0.11.0
- BREAKING: Remove some exported methods
- BREAKING: Fix an issue with missing sufficient parameters in the synchronous API
- Enhancement: Improve output under godoc
@ -56,17 +57,17 @@ This package can be installed via go get: `go get code.ivysaur.me/libnmdc`
- Fix an issue with parsing active/passive connection modes
- Fix an issue with errors appearing on stdout
2016-10-08 r10
2016-10-08 0.10.0
- Feature: Support `$UserCommand`
2016-08-27 r9
2016-08-27 0.9.0
- 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
2016-05-10 0.8.0
- Enhancement: Separate `ClientTag` and `ClientVersion` in `UserInfo` structs
2016-05-08 r7
2016-05-08 0.7.0
- BREAKING: Remove direct access to `HubConnection.Users` map
- Feature: Threadsafe user map accessor
- Feature: Option to disable auto-reconnection
@ -74,28 +75,28 @@ This package can be installed via go get: `go get code.ivysaur.me/libnmdc`
- Enhancement: Support `$OpList`, add `IsOperator` member to `UserInfo` structs
- Refactor into multiple files
2016-04-16 r6
2016-04-16 0.6.0
- Fix an issue with calling `panic()` on certain types of abnormal network failure
2016-04-04 r5
2016-04-04 0.5.0
- Enhancement: Support protocol keepalives
- Enhancement: Support hub redirects (`$ForceMove`)
2016-04-03 r4
2016-04-03 0.4.0
- Feature: Add synchronous API
- Fix an issue with reading HubConnection's state parameter
- Fix an issue with buffered protocol commands
2016-04-03 r3
2016-04-03 0.3.0
- Feature: Add `SkipVerifyTLS` option
- Fix an issue with calling `panic()` if connection failed
2016-04-02 r2
2016-04-02 0.2.0
- 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
2016-02-12 0.1.0
- Initial public release

View File

@ -1,6 +0,0 @@
NMDC:
- Implement ZPipe ($ZOn)
ADC:
- Usercommands
- ???

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module code.ivysaur.me/libnmdc
require github.com/cxmcc/tiger v0.0.0-20170524142333-bde35e2713d7

2
go.sum Normal file
View File

@ -0,0 +1,2 @@
github.com/cxmcc/tiger v0.0.0-20170524142333-bde35e2713d7 h1:jBEtq1t2gpn2kEzvRlCUxvvrxl5aSWkXNPwe/hwvSNQ=
github.com/cxmcc/tiger v0.0.0-20170524142333-bde35e2713d7/go.mod h1:ruCYvt9rtYymAr4rNmfYJrl1dz8HSXUFP7cufqKOsDI=

View File

@ -8,7 +8,7 @@ import (
const (
DEFAULT_CLIENT_TAG string = "libnmdc.go"
DEFAULT_CLIENT_VERSION string = "0.17"
DEFAULT_CLIENT_VERSION string = "0.18"
DEFAULT_HUB_NAME string = "(unknown)"
SEND_KEEPALIVE_EVERY time.Duration = 29 * time.Second
AUTO_RECONNECT_AFTER time.Duration = 30 * time.Second

View File

@ -1,144 +0,0 @@
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)
}

2
vendor/modules.txt vendored Normal file
View File

@ -0,0 +1,2 @@
# github.com/cxmcc/tiger v0.0.0-20170524142333-bde35e2713d7
github.com/cxmcc/tiger