├── stomp ├── conn_test.go ├── handler.go ├── peer_test.go ├── selector │ ├── selector.go │ ├── parse │ │ └── node.go │ └── eval.go ├── context.go ├── dialer │ └── dialer.go ├── reader_test.go ├── peer.go ├── const.go ├── option_test.go ├── header.go ├── option.go ├── header_test.go ├── reader.go ├── conn.go ├── writer_test.go ├── message.go └── writer.go ├── server ├── queue_test.go ├── option.go ├── option_test.go ├── auth.go ├── subscription_test.go ├── auth_test.go ├── store.go ├── subscription.go ├── session.go ├── session_test.go ├── router_test.go ├── topic.go ├── server.go └── queue.go ├── vendor ├── github.com │ ├── kr │ │ ├── text │ │ │ ├── doc.go │ │ │ ├── Readme │ │ │ ├── License │ │ │ ├── indent.go │ │ │ └── wrap.go │ │ └── pretty │ │ │ ├── Readme │ │ │ ├── License │ │ │ ├── zero.go │ │ │ └── pretty.go │ ├── golang │ │ └── snappy │ │ │ ├── decode_amd64.go │ │ │ ├── AUTHORS │ │ │ ├── encode_amd64.go │ │ │ ├── CONTRIBUTORS │ │ │ ├── LICENSE │ │ │ ├── decode_other.go │ │ │ ├── snappy.go │ │ │ └── README │ ├── urfave │ │ └── cli │ │ │ ├── appveyor.yml │ │ │ ├── cli.go │ │ │ ├── LICENSE │ │ │ ├── category.go │ │ │ ├── funcs.go │ │ │ ├── errors.go │ │ │ ├── flag-types.json │ │ │ └── runtests │ ├── syndtr │ │ └── goleveldb │ │ │ ├── leveldb │ │ │ ├── errors.go │ │ │ ├── storage │ │ │ │ ├── file_storage_nacl.go │ │ │ │ ├── file_storage_plan9.go │ │ │ │ ├── file_storage_solaris.go │ │ │ │ ├── file_storage_unix.go │ │ │ │ └── file_storage_windows.go │ │ │ ├── filter.go │ │ │ ├── util │ │ │ │ ├── crc32.go │ │ │ │ ├── range.go │ │ │ │ ├── hash.go │ │ │ │ └── util.go │ │ │ ├── comparer │ │ │ │ ├── bytes_comparer.go │ │ │ │ └── comparer.go │ │ │ ├── util.go │ │ │ ├── comparer.go │ │ │ ├── errors │ │ │ │ └── errors.go │ │ │ ├── filter │ │ │ │ ├── filter.go │ │ │ │ └── bloom.go │ │ │ ├── doc.go │ │ │ ├── db_util.go │ │ │ ├── options.go │ │ │ ├── cache │ │ │ │ └── lru.go │ │ │ └── iterator │ │ │ │ └── array_iter.go │ │ │ └── LICENSE │ ├── tidwall │ │ └── redlog │ │ │ ├── LICENSE │ │ │ └── README.md │ └── dchest │ │ └── uniuri │ │ ├── README.md │ │ └── uniuri.go └── golang.org │ └── x │ ├── crypto │ ├── ssh │ │ └── terminal │ │ │ ├── util_bsd.go │ │ │ ├── util_linux.go │ │ │ └── util_plan9.go │ ├── PATENTS │ ├── LICENSE │ └── acme │ │ └── autocert │ │ ├── renewal.go │ │ └── cache.go │ └── net │ ├── websocket │ ├── dial.go │ ├── client.go │ └── server.go │ ├── PATENTS │ ├── LICENSE │ └── context │ ├── ctxhttp │ ├── ctxhttp.go │ └── ctxhttp_pre17.go │ └── go17.go ├── .github ├── pull_request_template.md └── issue_template.md ├── Dockerfile ├── README ├── .gitignore ├── .drone.yml ├── LICENSE ├── .drone.yml.sig ├── logger └── logger.go └── cmd └── mq └── serve.go /stomp/conn_test.go: -------------------------------------------------------------------------------- 1 | package stomp 2 | -------------------------------------------------------------------------------- /server/queue_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | // TODO 4 | -------------------------------------------------------------------------------- /vendor/github.com/kr/text/doc.go: -------------------------------------------------------------------------------- 1 | // Package text provides rudimentary functions for manipulating text in 2 | // paragraphs. 3 | package text 4 | -------------------------------------------------------------------------------- /vendor/github.com/kr/text/Readme: -------------------------------------------------------------------------------- 1 | This is a Go package for manipulating paragraphs of text. 2 | 3 | See http://go.pkgdoc.org/github.com/kr/text for full documentation. 4 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM centurylink/ca-certs 2 | MAINTAINER Brad Rydzewski 3 | EXPOSE 8000 9000 4 | 5 | ENV GODEBUG=netdns=go 6 | ADD release/linux_amd64/mq /mq 7 | 8 | ENTRYPOINT ["/mq"] 9 | CMD ["start"] 10 | -------------------------------------------------------------------------------- /vendor/github.com/kr/pretty/Readme: -------------------------------------------------------------------------------- 1 | package pretty 2 | 3 | import "github.com/kr/pretty" 4 | 5 | Package pretty provides pretty-printing for Go values. 6 | 7 | Documentation 8 | 9 | http://godoc.org/github.com/kr/pretty 10 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Lightweight message broker written in the Go programming language. 2 | 3 | Documentation: 4 | 5 | http://mq.drone.io 6 | 7 | Installation: 8 | 9 | docker run -p 9000:9000 drone/mq 10 | 11 | Developer Channel: 12 | 13 | https://gitter.im/drone/mq 14 | -------------------------------------------------------------------------------- /stomp/handler.go: -------------------------------------------------------------------------------- 1 | package stomp 2 | 3 | // Handler handles a STOMP message. 4 | type Handler interface { 5 | Handle(*Message) 6 | } 7 | 8 | // The HandlerFunc type is an adapter to allow the use of an ordinary 9 | // function as a STOMP message handler. 10 | type HandlerFunc func(*Message) 11 | 12 | // Handle calls f(m). 13 | func (f HandlerFunc) Handle(m *Message) { f(m) } 14 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/terminal/util_bsd.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build darwin dragonfly freebsd netbsd openbsd 6 | 7 | package terminal 8 | 9 | import "syscall" 10 | 11 | const ioctlReadTermios = syscall.TIOCGETA 12 | const ioctlWriteTermios = syscall.TIOCSETA 13 | -------------------------------------------------------------------------------- /vendor/github.com/golang/snappy/decode_amd64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Snappy-Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !appengine 6 | // +build gc 7 | // +build !noasm 8 | 9 | package snappy 10 | 11 | // decode has the same semantics as in decode_other.go. 12 | // 13 | //go:noescape 14 | func decode(dst, src []byte) int 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | *.txt 26 | *.out 27 | cmd/mq/mq 28 | release 29 | 30 | USE_CASES.md 31 | stomp/cron/*.go 32 | server/store/*.go 33 | server/aof/*.go 34 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/terminal/util_linux.go: -------------------------------------------------------------------------------- 1 | // Copyright 2013 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package terminal 6 | 7 | // These constants are declared here, rather than importing 8 | // them from the syscall package as some syscall packages, even 9 | // on linux, for example gccgo, do not declare them. 10 | const ioctlReadTermios = 0x5401 // syscall.TCGETS 11 | const ioctlWriteTermios = 0x5402 // syscall.TCSETS 12 | -------------------------------------------------------------------------------- /server/option.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | // Option configures server options. 4 | type Option func(*Server) 5 | 6 | // WithAuth returns an Option which configures custom authorization 7 | // for the STOMP server. 8 | func WithAuth(auth Authorizer) Option { 9 | return func(s *Server) { 10 | s.router.authorizer = auth 11 | } 12 | } 13 | 14 | // WithCredentials returns an Option which configures basic authorization 15 | // using the given username and password 16 | func WithCredentials(username, password string) Option { 17 | return WithAuth(BasicAuth(username, password)) 18 | } 19 | -------------------------------------------------------------------------------- /vendor/github.com/golang/snappy/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of Snappy-Go authors for copyright purposes. 2 | # This file is distinct from the CONTRIBUTORS files. 3 | # See the latter for an explanation. 4 | 5 | # Names should be added to this file as 6 | # Name or Organization 7 | # The email address is not required for organizations. 8 | 9 | # Please keep the list sorted. 10 | 11 | Damian Gryski 12 | Google Inc. 13 | Jan Mercl <0xjnml@gmail.com> 14 | Rodolfo Carvalho 15 | Sebastien Binet 16 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/cli/appveyor.yml: -------------------------------------------------------------------------------- 1 | version: "{build}" 2 | 3 | os: Windows Server 2012 R2 4 | 5 | clone_folder: c:\gopath\src\github.com\urfave\cli 6 | 7 | environment: 8 | GOPATH: C:\gopath 9 | GOVERSION: 1.6 10 | PYTHON: C:\Python27-x64 11 | PYTHON_VERSION: 2.7.x 12 | PYTHON_ARCH: 64 13 | GFMXR_DEBUG: 1 14 | 15 | install: 16 | - set PATH=%GOPATH%\bin;C:\go\bin;%PATH% 17 | - go version 18 | - go env 19 | - go get github.com/urfave/gfmrun/... 20 | - go get -v -t ./... 21 | 22 | build_script: 23 | - python runtests vet 24 | - python runtests test 25 | - python runtests gfmrun 26 | -------------------------------------------------------------------------------- /stomp/peer_test.go: -------------------------------------------------------------------------------- 1 | package stomp 2 | 3 | import ( 4 | "io" 5 | "testing" 6 | ) 7 | 8 | func TestPeer(t *testing.T) { 9 | a, b := Pipe() 10 | 11 | sent := NewMessage() 12 | a.Send(sent) 13 | 14 | recv := <-b.Receive() 15 | if sent != recv { 16 | t.Errorf("Sending message to pipe a should be received by pipe b") 17 | } 18 | 19 | a.Close() 20 | b.Close() 21 | 22 | if a.Send(nil) != io.EOF { 23 | t.Errorf("Want error when sending a message to a closed peer") 24 | } 25 | if b.Send(nil) != io.EOF { 26 | t.Errorf("Want error when sending a message to a closed peer") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/errors.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | package leveldb 8 | 9 | import ( 10 | "github.com/syndtr/goleveldb/leveldb/errors" 11 | ) 12 | 13 | var ( 14 | ErrNotFound = errors.ErrNotFound 15 | ErrReadOnly = errors.New("leveldb: read-only mode") 16 | ErrSnapshotReleased = errors.New("leveldb: snapshot released") 17 | ErrIterReleased = errors.New("leveldb: iterator released") 18 | ErrClosed = errors.New("leveldb: closed") 19 | ) 20 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/websocket/dial.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "crypto/tls" 9 | "net" 10 | ) 11 | 12 | func dialWithDialer(dialer *net.Dialer, config *Config) (conn net.Conn, err error) { 13 | switch config.Location.Scheme { 14 | case "ws": 15 | conn, err = dialer.Dial("tcp", parseAuthority(config.Location)) 16 | 17 | case "wss": 18 | conn, err = tls.DialWithDialer(dialer, "tcp", parseAuthority(config.Location), config.TlsConfig) 19 | 20 | default: 21 | err = ErrBadScheme 22 | } 23 | return 24 | } 25 | -------------------------------------------------------------------------------- /server/option_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/drone/mq/stomp" 7 | ) 8 | 9 | func TestOptions(t *testing.T) { 10 | s := NewServer(WithCredentials("janedoe", "password")) 11 | if s.router.authorizer == nil { 12 | t.Errorf("Expect WithCredentials configures authorizer") 13 | } 14 | 15 | m := stomp.NewMessage() 16 | if s.router.authorizer(m) != ErrNotAuthorized { 17 | t.Errorf("Expect failed authorization when empty username") 18 | } 19 | 20 | m.Reset() 21 | m.User = []byte("janedoe") 22 | m.Pass = []byte("password") 23 | if err := s.router.authorizer(m); err != nil { 24 | t.Errorf("Expect successful authorization, got error %s", err) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/cli/cli.go: -------------------------------------------------------------------------------- 1 | // Package cli provides a minimal framework for creating and organizing command line 2 | // Go applications. cli is designed to be easy to understand and write, the most simple 3 | // cli application can be written as follows: 4 | // func main() { 5 | // cli.NewApp().Run(os.Args) 6 | // } 7 | // 8 | // Of course this application does not do much, so let's make this an actual application: 9 | // func main() { 10 | // app := cli.NewApp() 11 | // app.Name = "greet" 12 | // app.Usage = "say a greeting" 13 | // app.Action = func(c *cli.Context) error { 14 | // println("Greetings") 15 | // } 16 | // 17 | // app.Run(os.Args) 18 | // } 19 | package cli 20 | 21 | //go:generate python ./generate-flag-types cli -i flag-types.json -o flag_generated.go 22 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/storage/file_storage_nacl.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | // +build nacl 8 | 9 | package storage 10 | 11 | import ( 12 | "os" 13 | "syscall" 14 | ) 15 | 16 | func newFileLock(path string, readOnly bool) (fl fileLock, err error) { 17 | return nil, syscall.ENOTSUP 18 | } 19 | 20 | func setFileLock(f *os.File, readOnly, lock bool) error { 21 | return syscall.ENOTSUP 22 | } 23 | 24 | func rename(oldpath, newpath string) error { 25 | return syscall.ENOTSUP 26 | } 27 | 28 | func isErrInvalid(err error) bool { 29 | return false 30 | } 31 | 32 | func syncDir(name string) error { 33 | return syscall.ENOTSUP 34 | } 35 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/filter.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | package leveldb 8 | 9 | import ( 10 | "github.com/syndtr/goleveldb/leveldb/filter" 11 | ) 12 | 13 | type iFilter struct { 14 | filter.Filter 15 | } 16 | 17 | func (f iFilter) Contains(filter, key []byte) bool { 18 | return f.Filter.Contains(filter, internalKey(key).ukey()) 19 | } 20 | 21 | func (f iFilter) NewGenerator() filter.FilterGenerator { 22 | return iFilterGenerator{f.Filter.NewGenerator()} 23 | } 24 | 25 | type iFilterGenerator struct { 26 | filter.FilterGenerator 27 | } 28 | 29 | func (g iFilterGenerator) Add(key []byte) { 30 | g.FilterGenerator.Add(internalKey(key).ukey()) 31 | } 32 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/util/crc32.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The LevelDB-Go Authors. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style license that can be 4 | // found in the LICENSE file. 5 | 6 | package util 7 | 8 | import ( 9 | "hash/crc32" 10 | ) 11 | 12 | var table = crc32.MakeTable(crc32.Castagnoli) 13 | 14 | // CRC is a CRC-32 checksum computed using Castagnoli's polynomial. 15 | type CRC uint32 16 | 17 | // NewCRC creates a new crc based on the given bytes. 18 | func NewCRC(b []byte) CRC { 19 | return CRC(0).Update(b) 20 | } 21 | 22 | // Update updates the crc with the given bytes. 23 | func (c CRC) Update(b []byte) CRC { 24 | return CRC(crc32.Update(uint32(c), table, b)) 25 | } 26 | 27 | // Value returns a masked crc. 28 | func (c CRC) Value() uint32 { 29 | return uint32(c>>15|c<<17) + 0xa282ead8 30 | } 31 | -------------------------------------------------------------------------------- /vendor/github.com/golang/snappy/encode_amd64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Snappy-Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !appengine 6 | // +build gc 7 | // +build !noasm 8 | 9 | package snappy 10 | 11 | // emitLiteral has the same semantics as in encode_other.go. 12 | // 13 | //go:noescape 14 | func emitLiteral(dst, lit []byte) int 15 | 16 | // emitCopy has the same semantics as in encode_other.go. 17 | // 18 | //go:noescape 19 | func emitCopy(dst []byte, offset, length int) int 20 | 21 | // extendMatch has the same semantics as in encode_other.go. 22 | // 23 | //go:noescape 24 | func extendMatch(src []byte, i, j int) int 25 | 26 | // encodeBlock has the same semantics as in encode_other.go. 27 | // 28 | //go:noescape 29 | func encodeBlock(dst, src []byte) (d int) -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/util/range.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | package util 8 | 9 | // Range is a key range. 10 | type Range struct { 11 | // Start of the key range, include in the range. 12 | Start []byte 13 | 14 | // Limit of the key range, not include in the range. 15 | Limit []byte 16 | } 17 | 18 | // BytesPrefix returns key range that satisfy the given prefix. 19 | // This only applicable for the standard 'bytes comparer'. 20 | func BytesPrefix(prefix []byte) *Range { 21 | var limit []byte 22 | for i := len(prefix) - 1; i >= 0; i-- { 23 | c := prefix[i] 24 | if c < 0xff { 25 | limit = make([]byte, i+1) 26 | copy(limit, prefix) 27 | limit[i] = c + 1 28 | break 29 | } 30 | } 31 | return &Range{prefix, limit} 32 | } 33 | -------------------------------------------------------------------------------- /.drone.yml: -------------------------------------------------------------------------------- 1 | workspace: 2 | base: /go 3 | path: src/github.com/drone/mq 4 | 5 | pipeline: 6 | test: 7 | image: golang:1.7.1-alpine 8 | commands: 9 | - go install github.com/drone/mq/cmd/mq 10 | - go test -cover -v github.com/drone/mq/stomp/... 11 | - go test -cover -v github.com/drone/mq/server/... 12 | 13 | build: 14 | image: golang:1.7.1-alpine 15 | commands: ./build.sh 16 | when: 17 | event: [ tag, push ] 18 | 19 | docker: 20 | image: plugins/docker 21 | repo: drone/mq 22 | tags: [ latest, 1, 1.0, 1.0.0 ] 23 | when: 24 | branch: master 25 | event: push 26 | 27 | feature: 28 | image: plugins/docker 29 | repo: drone/mq 30 | tags: [ 1.0.1 ] 31 | when: 32 | branch: feature/reconnect 33 | event: push 34 | 35 | release: 36 | image: plugins/github-release 37 | files: release/*.tar.gz 38 | when: 39 | event: tag 40 | 41 | gitter: 42 | image: plugins/gitter 43 | when: 44 | status: [ success, failure ] 45 | -------------------------------------------------------------------------------- /server/auth.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | 7 | "github.com/drone/mq/stomp" 8 | ) 9 | 10 | // ErrNotAuthorized is returned when the peer connection is not 11 | // authorized to establish a connection with the STOMP server. 12 | var ErrNotAuthorized = errors.New("stomp: not authorized") 13 | 14 | // Authorizer is a callback function used to authenticate a peer 15 | // connection prior to establishing the session. If the callback 16 | // returns a non-nil error an error message is sent to the peer 17 | // and the connection is closed. 18 | type Authorizer func(*stomp.Message) error 19 | 20 | // BasicAuth is a authorization callback function that authorizes 21 | // the peer connection using a basic, global username and password. 22 | func BasicAuth(username, password string) Authorizer { 23 | var ( 24 | user = []byte(username) 25 | pass = []byte(password) 26 | ) 27 | return func(m *stomp.Message) (err error) { 28 | if bytes.Equal(m.User, user) && bytes.Equal(m.Pass, pass) { 29 | return nil 30 | } 31 | return ErrNotAuthorized 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /server/subscription_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func Test_subscription_reset(t *testing.T) { 8 | sub := &subscription{ 9 | id: []byte("1"), 10 | dest: []byte("/topic/test"), 11 | ack: true, 12 | prefetch: 1, 13 | pending: 1, 14 | session: &session{}, 15 | } 16 | sub.reset() 17 | 18 | if len(sub.id) != 0 { 19 | t.Errorf("expect subscription id reset") 20 | } 21 | if len(sub.dest) != 0 { 22 | t.Errorf("expect subscription destination reset") 23 | } 24 | if sub.ack != false { 25 | t.Errorf("expect subscription ack flag reset") 26 | } 27 | if sub.prefetch != 0 { 28 | t.Errorf("expect subscription prefetch count reset") 29 | } 30 | if sub.pending != 0 { 31 | t.Errorf("expect subscription pending cout reset") 32 | } 33 | if sub.session != nil { 34 | t.Errorf("expect session subscription reset") 35 | } 36 | } 37 | 38 | func Test_subscription_pool(t *testing.T) { 39 | s := requestSubscription() 40 | if s == nil { 41 | t.Errorf("expected subscription from pool") 42 | } 43 | s.release() 44 | } 45 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/util/hash.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | package util 8 | 9 | import ( 10 | "encoding/binary" 11 | ) 12 | 13 | // Hash return hash of the given data. 14 | func Hash(data []byte, seed uint32) uint32 { 15 | // Similar to murmur hash 16 | const ( 17 | m = uint32(0xc6a4a793) 18 | r = uint32(24) 19 | ) 20 | var ( 21 | h = seed ^ (uint32(len(data)) * m) 22 | i int 23 | ) 24 | 25 | for n := len(data) - len(data)%4; i < n; i += 4 { 26 | h += binary.LittleEndian.Uint32(data[i:]) 27 | h *= m 28 | h ^= (h >> 16) 29 | } 30 | 31 | switch len(data) - i { 32 | default: 33 | panic("not reached") 34 | case 3: 35 | h += uint32(data[i+2]) << 16 36 | fallthrough 37 | case 2: 38 | h += uint32(data[i+1]) << 8 39 | fallthrough 40 | case 1: 41 | h += uint32(data[i]) 42 | h *= m 43 | h ^= (h >> r) 44 | case 0: 45 | } 46 | 47 | return h 48 | } 49 | -------------------------------------------------------------------------------- /server/auth_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/drone/mq/stomp" 7 | ) 8 | 9 | func TestBasicAuth(t *testing.T) { 10 | f := BasicAuth("janedoe", "password") 11 | 12 | m := stomp.NewMessage() 13 | m.Pass = []byte("password") 14 | if f(m) != ErrNotAuthorized { 15 | t.Errorf("Expect failed authorization when empty username") 16 | } 17 | 18 | m.Reset() 19 | m.User = []byte("johnsmith") 20 | m.Pass = []byte("password") 21 | if f(m) != ErrNotAuthorized { 22 | t.Errorf("Expect failed authorization when invalid username") 23 | } 24 | 25 | m.Reset() 26 | m.User = []byte("janedoe") 27 | if f(m) != ErrNotAuthorized { 28 | t.Errorf("Expect failed authorization when empty password") 29 | } 30 | 31 | m.Reset() 32 | m.User = []byte("janedoe") 33 | m.Pass = []byte("pa55word") 34 | if f(m) != ErrNotAuthorized { 35 | t.Errorf("Expect failed authorization when invalid password") 36 | } 37 | 38 | m.Reset() 39 | m.User = []byte("janedoe") 40 | m.Pass = []byte("password") 41 | if err := f(m); err != nil { 42 | t.Errorf("Expect successful authorization, got error %s", err) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /vendor/github.com/kr/text/License: -------------------------------------------------------------------------------- 1 | Copyright 2012 Keith Rarick 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Brad Rydzewski 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.drone.yml.sig: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJIUzI1NiJ9.d29ya3NwYWNlOgogIGJhc2U6IC9nbwogIHBhdGg6IHNyYy9naXRodWIuY29tL2Ryb25lL21xCgpwaXBlbGluZToKICB0ZXN0OgogICAgaW1hZ2U6IGdvbGFuZzoxLjcuMS1hbHBpbmUKICAgIGNvbW1hbmRzOgogICAgICAtIGdvIGluc3RhbGwgZ2l0aHViLmNvbS9kcm9uZS9tcS9jbWQvbXEKICAgICAgLSBnbyB0ZXN0IC1jb3ZlciAtdiBnaXRodWIuY29tL2Ryb25lL21xL3N0b21wLy4uLgogICAgICAtIGdvIHRlc3QgLWNvdmVyIC12IGdpdGh1Yi5jb20vZHJvbmUvbXEvc2VydmVyLy4uLgoKICBidWlsZDoKICAgIGltYWdlOiBnb2xhbmc6MS43LjEtYWxwaW5lCiAgICBjb21tYW5kczogLi9idWlsZC5zaAogICAgd2hlbjoKICAgICAgZXZlbnQ6IFsgdGFnLCBwdXNoIF0KCiAgZG9ja2VyOgogICAgaW1hZ2U6IHBsdWdpbnMvZG9ja2VyCiAgICByZXBvOiBkcm9uZS9tcQogICAgdGFnczogWyBsYXRlc3QsIDEsIDEuMCwgMS4wLjAgXQogICAgd2hlbjoKICAgICAgYnJhbmNoOiBtYXN0ZXIKICAgICAgZXZlbnQ6IHB1c2gKCiAgZmVhdHVyZToKICAgIGltYWdlOiBwbHVnaW5zL2RvY2tlcgogICAgcmVwbzogZHJvbmUvbXEKICAgIHRhZ3M6IFsgMS4wLjEgXQogICAgd2hlbjoKICAgICAgYnJhbmNoOiBmZWF0dXJlL3JlY29ubmVjdAogICAgICBldmVudDogcHVzaAoKICByZWxlYXNlOgogICAgaW1hZ2U6IHBsdWdpbnMvZ2l0aHViLXJlbGVhc2UKICAgIGZpbGVzOiByZWxlYXNlLyoudGFyLmd6CiAgICB3aGVuOgogICAgICBldmVudDogdGFnCgogIGdpdHRlcjoKICAgIGltYWdlOiBwbHVnaW5zL2dpdHRlcgogICAgd2hlbjoKICAgICAgc3RhdHVzOiBbIHN1Y2Nlc3MsIGZhaWx1cmUgXQo.nqdOVMN9fnhAFddK9RgyOW2EZGXw8PoXKzbqMtg9tQg -------------------------------------------------------------------------------- /stomp/selector/selector.go: -------------------------------------------------------------------------------- 1 | package selector 2 | 3 | import "github.com/drone/mq/stomp/selector/parse" 4 | 5 | // Selector reprents a parsed SQL selector statement. 6 | type Selector struct { 7 | *parse.Tree 8 | } 9 | 10 | // Parse parses the SQL statement and returns a new Statement object. 11 | func Parse(b []byte) (selector *Selector, err error) { 12 | selector = new(Selector) 13 | selector.Tree, err = parse.Parse(b) 14 | return 15 | } 16 | 17 | // Eval evaluates the SQL statement using the provided data and returns true 18 | // if all conditions are satisfied. If a runtime error is experiences a false 19 | // value is returned along with an error message. 20 | func (s *Selector) Eval(row Row) (match bool, err error) { 21 | defer errRecover(&err) 22 | state := &state{vars: row} 23 | match = state.walk(s.Root) 24 | return 25 | } 26 | 27 | // Row defines a row of columnar data. 28 | // 29 | // Note that the field name and field values are represented as []byte 30 | // since stomp header names and values are represented as []byte to avoid 31 | // extra allocations when converting from []byte to string. 32 | type Row interface { 33 | Field([]byte) []byte 34 | } 35 | -------------------------------------------------------------------------------- /vendor/github.com/kr/pretty/License: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright 2012 Keith Rarick 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/tidwall/redlog/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Josh Baker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /stomp/context.go: -------------------------------------------------------------------------------- 1 | package stomp 2 | 3 | import "golang.org/x/net/context" 4 | 5 | const clientKey = "stomp.client" 6 | 7 | // NewContext adds the client to the context. 8 | func (c *Client) NewContext(ctx context.Context, client *Client) context.Context { 9 | // HACK for use with gin and echo 10 | if s, ok := ctx.(setter); ok { 11 | s.Set(clientKey, clientKey) 12 | return ctx 13 | } 14 | return context.WithValue(ctx, clientKey, client) 15 | } 16 | 17 | // FromContext retrieves the client from context 18 | func FromContext(ctx context.Context) (*Client, bool) { 19 | client, ok := ctx.Value(clientKey).(*Client) 20 | return client, ok 21 | } 22 | 23 | // MustFromContext retrieves the client from context. Panics if not found 24 | func MustFromContext(ctx context.Context) *Client { 25 | client, ok := FromContext(ctx) 26 | if !ok { 27 | panic("stomp.Client not found in context") 28 | } 29 | return client 30 | } 31 | 32 | // HACK setter defines a context that enables setting values. This is a 33 | // temporary workaround for use with gin and echo and will eventually 34 | // be removed. DO NOT depend on this. 35 | type setter interface { 36 | Set(string, interface{}) 37 | } 38 | -------------------------------------------------------------------------------- /stomp/dialer/dialer.go: -------------------------------------------------------------------------------- 1 | package dialer 2 | 3 | import ( 4 | "net" 5 | "net/url" 6 | 7 | "golang.org/x/net/websocket" 8 | ) 9 | 10 | const ( 11 | protoHTTP = "http" 12 | protoHTTPS = "https" 13 | protoWS = "ws" 14 | protoWSS = "wss" 15 | protoTCP = "tcp" 16 | ) 17 | 18 | // Dial creates a client connection to the given target. 19 | func Dial(target string) (net.Conn, error) { 20 | u, err := url.Parse(target) 21 | if err != nil { 22 | return nil, err 23 | } 24 | 25 | switch u.Scheme { 26 | case protoHTTP, protoHTTPS, protoWS, protoWSS: 27 | return dialWebsocket(u) 28 | case protoTCP: 29 | return dialSocket(u) 30 | default: 31 | panic("stomp: invalid protocol") 32 | } 33 | } 34 | 35 | func dialWebsocket(target *url.URL) (net.Conn, error) { 36 | origin, err := target.Parse("/") 37 | if err != nil { 38 | return nil, err 39 | } 40 | switch origin.Scheme { 41 | case protoWS: 42 | origin.Scheme = protoHTTP 43 | case protoWSS: 44 | origin.Scheme = protoHTTPS 45 | } 46 | return websocket.Dial(target.String(), "", origin.String()) 47 | } 48 | 49 | func dialSocket(target *url.URL) (net.Conn, error) { 50 | return net.Dial(protoTCP, target.Host) 51 | } 52 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/cli/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Jeremy Saenz & Contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/kr/pretty/zero.go: -------------------------------------------------------------------------------- 1 | package pretty 2 | 3 | import ( 4 | "reflect" 5 | ) 6 | 7 | func nonzero(v reflect.Value) bool { 8 | switch v.Kind() { 9 | case reflect.Bool: 10 | return v.Bool() 11 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 12 | return v.Int() != 0 13 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 14 | return v.Uint() != 0 15 | case reflect.Float32, reflect.Float64: 16 | return v.Float() != 0 17 | case reflect.Complex64, reflect.Complex128: 18 | return v.Complex() != complex(0, 0) 19 | case reflect.String: 20 | return v.String() != "" 21 | case reflect.Struct: 22 | for i := 0; i < v.NumField(); i++ { 23 | if nonzero(getField(v, i)) { 24 | return true 25 | } 26 | } 27 | return false 28 | case reflect.Array: 29 | for i := 0; i < v.Len(); i++ { 30 | if nonzero(v.Index(i)) { 31 | return true 32 | } 33 | } 34 | return false 35 | case reflect.Map, reflect.Interface, reflect.Slice, reflect.Ptr, reflect.Chan, reflect.Func: 36 | return !v.IsNil() 37 | case reflect.UnsafePointer: 38 | return v.Pointer() != 0 39 | } 40 | return true 41 | } 42 | -------------------------------------------------------------------------------- /vendor/github.com/tidwall/redlog/README.md: -------------------------------------------------------------------------------- 1 | Redlog 2 | ====== 3 | Build Status 4 | GoDoc 5 | 6 | Redlog is a [Redis style logger](http://build47.com/redis-log-format-levels/) for Go. 7 | 8 | Installing 9 | ---------- 10 | 11 | ``` 12 | go get -u github.com/tidwall/redlog 13 | ``` 14 | 15 | Example 16 | ------- 17 | 18 | ```go 19 | log := redlog.New(os.Stderr) 20 | log.Printf("Server started at 10.0.1.5:6379") 21 | log.Debugf("Connected to leader") 22 | log.Warningf("Heartbeat timeout reached, starting election") 23 | ``` 24 | 25 | Output: 26 | 27 | ``` 28 | [93324:M] 29 Aug 09:30:59.943 * Server started at 10.0.1.5:6379 29 | [93324:M] 29 Aug 09:31:01.892 . Connected to leader 30 | [93324:M] 29 Aug 09:31:02.331 # Heartbeat timeout reached, starting election 31 | ``` 32 | 33 | Contact 34 | ------- 35 | Josh Baker [@tidwall](http://twitter.com/tidwall) 36 | 37 | License 38 | ------- 39 | Redcon source code is available under the MIT [License](/LICENSE). 40 | -------------------------------------------------------------------------------- /server/store.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | // http://oldblog.antirez.com/post/redis-persistence-demystified.html 4 | 5 | import ( 6 | "github.com/drone/mq/stomp" 7 | 8 | "github.com/syndtr/goleveldb/leveldb" 9 | ) 10 | 11 | type store interface { 12 | put(*stomp.Message) error 13 | delete(*stomp.Message) error 14 | close() error 15 | } 16 | 17 | type datastore struct { 18 | db *leveldb.DB 19 | } 20 | 21 | func (d *datastore) put(m *stomp.Message) error { 22 | return d.db.Put(m.ID, m.Bytes(), nil) 23 | } 24 | 25 | func (d *datastore) delete(m *stomp.Message) error { 26 | return d.db.Delete(m.ID, nil) 27 | } 28 | 29 | func (d *datastore) close() error { 30 | return d.db.Close() 31 | } 32 | 33 | // loadDatastore reads the datastore from disk and restores 34 | // persisted message to the appropriate queues. 35 | func loadDatastore(path string, b *router) (store, error) { 36 | db, err := leveldb.RecoverFile(path, nil) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | // iterate through the persisted messages 42 | // and send to the broker. 43 | iter := db.NewIterator(nil, nil) 44 | for iter.Next() { 45 | m := stomp.NewMessage() 46 | m.Parse(iter.Value()) 47 | b.publish(m) 48 | } 49 | iter.Release() 50 | 51 | return &datastore{db: db}, nil 52 | } 53 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/cli/category.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | // CommandCategories is a slice of *CommandCategory. 4 | type CommandCategories []*CommandCategory 5 | 6 | // CommandCategory is a category containing commands. 7 | type CommandCategory struct { 8 | Name string 9 | Commands Commands 10 | } 11 | 12 | func (c CommandCategories) Less(i, j int) bool { 13 | return c[i].Name < c[j].Name 14 | } 15 | 16 | func (c CommandCategories) Len() int { 17 | return len(c) 18 | } 19 | 20 | func (c CommandCategories) Swap(i, j int) { 21 | c[i], c[j] = c[j], c[i] 22 | } 23 | 24 | // AddCommand adds a command to a category. 25 | func (c CommandCategories) AddCommand(category string, command Command) CommandCategories { 26 | for _, commandCategory := range c { 27 | if commandCategory.Name == category { 28 | commandCategory.Commands = append(commandCategory.Commands, command) 29 | return c 30 | } 31 | } 32 | return append(c, &CommandCategory{Name: category, Commands: []Command{command}}) 33 | } 34 | 35 | // VisibleCommands returns a slice of the Commands with Hidden=false 36 | func (c *CommandCategory) VisibleCommands() []Command { 37 | ret := []Command{} 38 | for _, command := range c.Commands { 39 | if !command.Hidden { 40 | ret = append(ret, command) 41 | } 42 | } 43 | return ret 44 | } 45 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/comparer/bytes_comparer.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | package comparer 8 | 9 | import "bytes" 10 | 11 | type bytesComparer struct{} 12 | 13 | func (bytesComparer) Compare(a, b []byte) int { 14 | return bytes.Compare(a, b) 15 | } 16 | 17 | func (bytesComparer) Name() string { 18 | return "leveldb.BytewiseComparator" 19 | } 20 | 21 | func (bytesComparer) Separator(dst, a, b []byte) []byte { 22 | i, n := 0, len(a) 23 | if n > len(b) { 24 | n = len(b) 25 | } 26 | for ; i < n && a[i] == b[i]; i++ { 27 | } 28 | if i >= n { 29 | // Do not shorten if one string is a prefix of the other 30 | } else if c := a[i]; c < 0xff && c+1 < b[i] { 31 | dst = append(dst, a[:i+1]...) 32 | dst[i]++ 33 | return dst 34 | } 35 | return nil 36 | } 37 | 38 | func (bytesComparer) Successor(dst, b []byte) []byte { 39 | for i, c := range b { 40 | if c != 0xff { 41 | dst = append(dst, b[:i+1]...) 42 | dst[i]++ 43 | return dst 44 | } 45 | } 46 | return nil 47 | } 48 | 49 | // DefaultComparer are default implementation of the Comparer interface. 50 | // It uses the natural ordering, consistent with bytes.Compare. 51 | var DefaultComparer = bytesComparer{} 52 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/cli/funcs.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | // BashCompleteFunc is an action to execute when the bash-completion flag is set 4 | type BashCompleteFunc func(*Context) 5 | 6 | // BeforeFunc is an action to execute before any subcommands are run, but after 7 | // the context is ready if a non-nil error is returned, no subcommands are run 8 | type BeforeFunc func(*Context) error 9 | 10 | // AfterFunc is an action to execute after any subcommands are run, but after the 11 | // subcommand has finished it is run even if Action() panics 12 | type AfterFunc func(*Context) error 13 | 14 | // ActionFunc is the action to execute when no subcommands are specified 15 | type ActionFunc func(*Context) error 16 | 17 | // CommandNotFoundFunc is executed if the proper command cannot be found 18 | type CommandNotFoundFunc func(*Context, string) 19 | 20 | // OnUsageErrorFunc is executed if an usage error occurs. This is useful for displaying 21 | // customized usage error messages. This function is able to replace the 22 | // original error messages. If this function is not set, the "Incorrect usage" 23 | // is displayed and the execution is interrupted. 24 | type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error 25 | 26 | // FlagStringFunc is used by the help generation to display a flag, which is 27 | // expected to be a single line. 28 | type FlagStringFunc func(Flag) string 29 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/PATENTS: -------------------------------------------------------------------------------- 1 | Additional IP Rights Grant (Patents) 2 | 3 | "This implementation" means the copyrightable works distributed by 4 | Google as part of the Go project. 5 | 6 | Google hereby grants to You a perpetual, worldwide, non-exclusive, 7 | no-charge, royalty-free, irrevocable (except as stated in this section) 8 | patent license to make, have made, use, offer to sell, sell, import, 9 | transfer and otherwise run, modify and propagate the contents of this 10 | implementation of Go, where such license applies only to those patent 11 | claims, both currently owned or controlled by Google and acquired in 12 | the future, licensable by Google that are necessarily infringed by this 13 | implementation of Go. This grant does not include claims that would be 14 | infringed only as a consequence of further modification of this 15 | implementation. If you or your agent or exclusive licensee institute or 16 | order or agree to the institution of patent litigation against any 17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging 18 | that this implementation of Go or any code incorporated within this 19 | implementation of Go constitutes direct or contributory patent 20 | infringement, or inducement of patent infringement, then any patent 21 | rights granted to you under this License for this implementation of Go 22 | shall terminate as of the date such litigation is filed. 23 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2012 Suryandaru Triandana 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/storage/file_storage_plan9.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | package storage 8 | 9 | import ( 10 | "os" 11 | "path/filepath" 12 | ) 13 | 14 | type plan9FileLock struct { 15 | f *os.File 16 | } 17 | 18 | func (fl *plan9FileLock) release() error { 19 | return fl.f.Close() 20 | } 21 | 22 | func newFileLock(path string, readOnly bool) (fl fileLock, err error) { 23 | var ( 24 | flag int 25 | perm os.FileMode 26 | ) 27 | if readOnly { 28 | flag = os.O_RDONLY 29 | } else { 30 | flag = os.O_RDWR 31 | perm = os.ModeExclusive 32 | } 33 | f, err := os.OpenFile(path, flag, perm) 34 | if os.IsNotExist(err) { 35 | f, err = os.OpenFile(path, flag|os.O_CREATE, perm|0644) 36 | } 37 | if err != nil { 38 | return 39 | } 40 | fl = &plan9FileLock{f: f} 41 | return 42 | } 43 | 44 | func rename(oldpath, newpath string) error { 45 | if _, err := os.Stat(newpath); err == nil { 46 | if err := os.Remove(newpath); err != nil { 47 | return err 48 | } 49 | } 50 | 51 | _, fname := filepath.Split(newpath) 52 | return os.Rename(oldpath, fname) 53 | } 54 | 55 | func syncDir(name string) error { 56 | f, err := os.Open(name) 57 | if err != nil { 58 | return err 59 | } 60 | defer f.Close() 61 | if err := f.Sync(); err != nil { 62 | return err 63 | } 64 | return nil 65 | } 66 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/golang/snappy/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This is the official list of people who can contribute 2 | # (and typically have contributed) code to the Snappy-Go repository. 3 | # The AUTHORS file lists the copyright holders; this file 4 | # lists people. For example, Google employees are listed here 5 | # but not in AUTHORS, because Google holds the copyright. 6 | # 7 | # The submission process automatically checks to make sure 8 | # that people submitting code are listed in this file (by email address). 9 | # 10 | # Names should be added to this file only after verifying that 11 | # the individual or the individual's organization has agreed to 12 | # the appropriate Contributor License Agreement, found here: 13 | # 14 | # http://code.google.com/legal/individual-cla-v1.0.html 15 | # http://code.google.com/legal/corporate-cla-v1.0.html 16 | # 17 | # The agreement for individuals can be filled out on the web. 18 | # 19 | # When adding J Random Contributor's name to this file, 20 | # either J's name or J's organization's name should be 21 | # added to the AUTHORS file, depending on whether the 22 | # individual or corporate CLA was used. 23 | 24 | # Names should be added to this file like so: 25 | # Name 26 | 27 | # Please keep the list sorted. 28 | 29 | Damian Gryski 30 | Jan Mercl <0xjnml@gmail.com> 31 | Kai Backman 32 | Marc-Antoine Ruel 33 | Nigel Tao 34 | Rob Pike 35 | Rodolfo Carvalho 36 | Russ Cox 37 | Sebastien Binet 38 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /vendor/github.com/golang/snappy/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 The Snappy-Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /server/subscription.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "sync" 5 | 6 | "github.com/drone/mq/stomp/selector" 7 | ) 8 | 9 | // subscription represents a session subscription to a 10 | // broker topic or queue. 11 | type subscription struct { 12 | mu sync.Mutex 13 | 14 | id []byte 15 | dest []byte 16 | ack bool 17 | prefetch int 18 | pending int 19 | session *session 20 | selector *selector.Selector 21 | } 22 | 23 | // reset the subscription properties to zero values. 24 | func (s *subscription) reset() { 25 | s.id = s.id[:0] 26 | s.dest = s.dest[:0] 27 | s.ack = false 28 | s.prefetch = 0 29 | s.pending = 0 30 | s.session = nil 31 | s.selector = nil 32 | } 33 | 34 | // release releases the subscription to the pool. 35 | func (s *subscription) release() { 36 | s.reset() 37 | subscriptionPool.Put(s) 38 | } 39 | 40 | // Pending returns the pending message count. 41 | func (s *subscription) Pending() (i int) { 42 | s.mu.Lock() 43 | i = s.pending 44 | s.mu.Unlock() 45 | return 46 | } 47 | 48 | // PendingIncr increments the pending message count. 49 | func (s *subscription) PendingIncr() { 50 | s.mu.Lock() 51 | s.pending++ 52 | s.mu.Unlock() 53 | } 54 | 55 | // PendingDecr decrements the pending message count. 56 | func (s *subscription) PendingDecr() { 57 | s.mu.Lock() 58 | if s.pending != 0 { 59 | s.pending-- 60 | } 61 | s.mu.Unlock() 62 | } 63 | 64 | // 65 | // subscription pool 66 | // 67 | 68 | var subscriptionPool = sync.Pool{New: createSubscription} 69 | 70 | func createSubscription() interface{} { 71 | return &subscription{} 72 | } 73 | 74 | func requestSubscription() *subscription { 75 | return subscriptionPool.Get().(*subscription) 76 | } 77 | -------------------------------------------------------------------------------- /logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | var std Logger = new(none) 4 | 5 | // Debugf writes a debug message to the standard logger. 6 | func Debugf(format string, args ...interface{}) { 7 | std.Debugf(format, args...) 8 | } 9 | 10 | // Verbosef writes a verbose message to the standard logger. 11 | func Verbosef(format string, args ...interface{}) { 12 | std.Verbosef(format, args...) 13 | } 14 | 15 | // Noticef writes a notice message to the standard logger. 16 | func Noticef(format string, args ...interface{}) { 17 | std.Noticef(format, args...) 18 | } 19 | 20 | // Warningf writes a warning message to the standard logger. 21 | func Warningf(format string, args ...interface{}) { 22 | std.Warningf(format, args...) 23 | } 24 | 25 | // Printf writes a default message to the standard logger. 26 | func Printf(format string, args ...interface{}) { 27 | std.Printf(format, args...) 28 | } 29 | 30 | // SetLogger sets the standard logger. 31 | func SetLogger(logger Logger) { 32 | std = logger 33 | } 34 | 35 | // Logger represents a logger. 36 | type Logger interface { 37 | 38 | // Debugf writes a debug message. 39 | Debugf(string, ...interface{}) 40 | 41 | // Verbosef writes a verbose message. 42 | Verbosef(string, ...interface{}) 43 | 44 | // Noticef writes a notice message. 45 | Noticef(string, ...interface{}) 46 | 47 | // Warningf writes a warning message. 48 | Warningf(string, ...interface{}) 49 | 50 | // Printf writes a default message. 51 | Printf(string, ...interface{}) 52 | } 53 | 54 | // none is a logger that silently ignores all writes. 55 | type none struct{} 56 | 57 | func (*none) Debugf(string, ...interface{}) {} 58 | func (*none) Verbosef(string, ...interface{}) {} 59 | func (*none) Noticef(string, ...interface{}) {} 60 | func (*none) Warningf(string, ...interface{}) {} 61 | func (*none) Printf(string, ...interface{}) {} 62 | -------------------------------------------------------------------------------- /stomp/reader_test.go: -------------------------------------------------------------------------------- 1 | package stomp 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | 7 | "github.com/kr/pretty" 8 | ) 9 | 10 | func TestRead(t *testing.T) { 11 | for _, test := range payloads { 12 | message := NewMessage() 13 | err := message.Parse([]byte(test.payload)) 14 | if err != nil { 15 | t.Errorf("error parsing message %q", test.payload) 16 | continue 17 | } 18 | 19 | if !reflect.DeepEqual(test.message, message) { 20 | t.Errorf("problems parsing message %q", test.payload) 21 | pretty.Ldiff(t, test.message, message) 22 | } 23 | } 24 | } 25 | 26 | // these are all malformed and should result in an error 27 | // and should not cause the parser to blow up. 28 | func TestReadMalformed(t *testing.T) { 29 | var tests = []string{ 30 | "", // no header 31 | "STOMP", // no header newline 32 | "STOMP\nversion", // no header separator 33 | "STOMP\nversion:", // no header value 34 | "STOMP\nversion:1.1.2", // no header newline 35 | "STOMP\nversion:1.1.2\n", // no newline before eof 36 | } 37 | 38 | for _, test := range tests { 39 | message := NewMessage() 40 | err := message.Parse([]byte(test)) 41 | if err == nil { 42 | t.Errorf("Want error parsing message %q", test) 43 | } 44 | } 45 | } 46 | 47 | var resultmsg *Message 48 | 49 | func BenchmarkParse(b *testing.B) { 50 | var msg *Message 51 | var err error 52 | 53 | msg = NewMessage() 54 | defer msg.Release() 55 | 56 | b.ReportAllocs() 57 | b.ResetTimer() 58 | 59 | for n := 0; n < b.N; n++ { 60 | msg.Reset() 61 | 62 | err = msg.Parse(sampleMessage) 63 | if err != nil { 64 | b.Error(err) 65 | return 66 | } 67 | } 68 | resultmsg = msg 69 | } 70 | 71 | var sampleMessage = []byte(`PUBLISH 72 | version:1.0.0 73 | destination:/topic/test 74 | 75 | foo 76 | bar 77 | baz 78 | qux`) 79 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/util.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | package leveldb 8 | 9 | import ( 10 | "fmt" 11 | "sort" 12 | 13 | "github.com/syndtr/goleveldb/leveldb/storage" 14 | ) 15 | 16 | func shorten(str string) string { 17 | if len(str) <= 8 { 18 | return str 19 | } 20 | return str[:3] + ".." + str[len(str)-3:] 21 | } 22 | 23 | var bunits = [...]string{"", "Ki", "Mi", "Gi"} 24 | 25 | func shortenb(bytes int) string { 26 | i := 0 27 | for ; bytes > 1024 && i < 4; i++ { 28 | bytes /= 1024 29 | } 30 | return fmt.Sprintf("%d%sB", bytes, bunits[i]) 31 | } 32 | 33 | func sshortenb(bytes int) string { 34 | if bytes == 0 { 35 | return "~" 36 | } 37 | sign := "+" 38 | if bytes < 0 { 39 | sign = "-" 40 | bytes *= -1 41 | } 42 | i := 0 43 | for ; bytes > 1024 && i < 4; i++ { 44 | bytes /= 1024 45 | } 46 | return fmt.Sprintf("%s%d%sB", sign, bytes, bunits[i]) 47 | } 48 | 49 | func sint(x int) string { 50 | if x == 0 { 51 | return "~" 52 | } 53 | sign := "+" 54 | if x < 0 { 55 | sign = "-" 56 | x *= -1 57 | } 58 | return fmt.Sprintf("%s%d", sign, x) 59 | } 60 | 61 | func minInt(a, b int) int { 62 | if a < b { 63 | return a 64 | } 65 | return b 66 | } 67 | 68 | func maxInt(a, b int) int { 69 | if a > b { 70 | return a 71 | } 72 | return b 73 | } 74 | 75 | type fdSorter []storage.FileDesc 76 | 77 | func (p fdSorter) Len() int { 78 | return len(p) 79 | } 80 | 81 | func (p fdSorter) Less(i, j int) bool { 82 | return p[i].Num < p[j].Num 83 | } 84 | 85 | func (p fdSorter) Swap(i, j int) { 86 | p[i], p[j] = p[j], p[i] 87 | } 88 | 89 | func sortFds(fds []storage.FileDesc) { 90 | sort.Sort(fdSorter(fds)) 91 | } 92 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/storage/file_storage_solaris.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | // +build solaris 8 | 9 | package storage 10 | 11 | import ( 12 | "os" 13 | "syscall" 14 | ) 15 | 16 | type unixFileLock struct { 17 | f *os.File 18 | } 19 | 20 | func (fl *unixFileLock) release() error { 21 | if err := setFileLock(fl.f, false, false); err != nil { 22 | return err 23 | } 24 | return fl.f.Close() 25 | } 26 | 27 | func newFileLock(path string, readOnly bool) (fl fileLock, err error) { 28 | var flag int 29 | if readOnly { 30 | flag = os.O_RDONLY 31 | } else { 32 | flag = os.O_RDWR 33 | } 34 | f, err := os.OpenFile(path, flag, 0) 35 | if os.IsNotExist(err) { 36 | f, err = os.OpenFile(path, flag|os.O_CREATE, 0644) 37 | } 38 | if err != nil { 39 | return 40 | } 41 | err = setFileLock(f, readOnly, true) 42 | if err != nil { 43 | f.Close() 44 | return 45 | } 46 | fl = &unixFileLock{f: f} 47 | return 48 | } 49 | 50 | func setFileLock(f *os.File, readOnly, lock bool) error { 51 | flock := syscall.Flock_t{ 52 | Type: syscall.F_UNLCK, 53 | Start: 0, 54 | Len: 0, 55 | Whence: 1, 56 | } 57 | if lock { 58 | if readOnly { 59 | flock.Type = syscall.F_RDLCK 60 | } else { 61 | flock.Type = syscall.F_WRLCK 62 | } 63 | } 64 | return syscall.FcntlFlock(f.Fd(), syscall.F_SETLK, &flock) 65 | } 66 | 67 | func rename(oldpath, newpath string) error { 68 | return os.Rename(oldpath, newpath) 69 | } 70 | 71 | func syncDir(name string) error { 72 | f, err := os.Open(name) 73 | if err != nil { 74 | return err 75 | } 76 | defer f.Close() 77 | if err := f.Sync(); err != nil { 78 | return err 79 | } 80 | return nil 81 | } 82 | -------------------------------------------------------------------------------- /vendor/github.com/kr/text/indent.go: -------------------------------------------------------------------------------- 1 | package text 2 | 3 | import ( 4 | "io" 5 | ) 6 | 7 | // Indent inserts prefix at the beginning of each non-empty line of s. The 8 | // end-of-line marker is NL. 9 | func Indent(s, prefix string) string { 10 | return string(IndentBytes([]byte(s), []byte(prefix))) 11 | } 12 | 13 | // IndentBytes inserts prefix at the beginning of each non-empty line of b. 14 | // The end-of-line marker is NL. 15 | func IndentBytes(b, prefix []byte) []byte { 16 | var res []byte 17 | bol := true 18 | for _, c := range b { 19 | if bol && c != '\n' { 20 | res = append(res, prefix...) 21 | } 22 | res = append(res, c) 23 | bol = c == '\n' 24 | } 25 | return res 26 | } 27 | 28 | // Writer indents each line of its input. 29 | type indentWriter struct { 30 | w io.Writer 31 | bol bool 32 | pre [][]byte 33 | sel int 34 | off int 35 | } 36 | 37 | // NewIndentWriter makes a new write filter that indents the input 38 | // lines. Each line is prefixed in order with the corresponding 39 | // element of pre. If there are more lines than elements, the last 40 | // element of pre is repeated for each subsequent line. 41 | func NewIndentWriter(w io.Writer, pre ...[]byte) io.Writer { 42 | return &indentWriter{ 43 | w: w, 44 | pre: pre, 45 | bol: true, 46 | } 47 | } 48 | 49 | // The only errors returned are from the underlying indentWriter. 50 | func (w *indentWriter) Write(p []byte) (n int, err error) { 51 | for _, c := range p { 52 | if w.bol { 53 | var i int 54 | i, err = w.w.Write(w.pre[w.sel][w.off:]) 55 | w.off += i 56 | if err != nil { 57 | return n, err 58 | } 59 | } 60 | _, err = w.w.Write([]byte{c}) 61 | if err != nil { 62 | return n, err 63 | } 64 | n++ 65 | w.bol = c == '\n' 66 | if w.bol { 67 | w.off = 0 68 | if w.sel < len(w.pre)-1 { 69 | w.sel++ 70 | } 71 | } 72 | } 73 | return n, nil 74 | } 75 | -------------------------------------------------------------------------------- /stomp/peer.go: -------------------------------------------------------------------------------- 1 | package stomp 2 | 3 | import ( 4 | "io" 5 | "net" 6 | "sync" 7 | ) 8 | 9 | // Peer defines a peer-to-peer connection. 10 | type Peer interface { 11 | // Send sends a message. 12 | Send(*Message) error 13 | 14 | // Receive returns a channel of inbound messages. 15 | Receive() <-chan *Message 16 | 17 | // Close closes the connection. 18 | Close() error 19 | 20 | // Addr returns the peer address. 21 | Addr() string 22 | } 23 | 24 | // Pipe creates a synchronous in-memory pipe, where reads on one end are 25 | // matched with writes on the other. This is useful for direct, in-memory 26 | // client-server communication. 27 | func Pipe() (Peer, Peer) { 28 | atob := make(chan *Message, 10) 29 | btoa := make(chan *Message, 10) 30 | 31 | a := &localPeer{ 32 | incoming: btoa, 33 | outgoing: atob, 34 | finished: make(chan bool), 35 | } 36 | b := &localPeer{ 37 | incoming: atob, 38 | outgoing: btoa, 39 | finished: make(chan bool), 40 | } 41 | 42 | return a, b 43 | } 44 | 45 | type localPeer struct { 46 | finished chan bool 47 | outgoing chan<- *Message 48 | incoming <-chan *Message 49 | } 50 | 51 | func (p *localPeer) Receive() <-chan *Message { 52 | return p.incoming 53 | } 54 | 55 | func (p *localPeer) Send(m *Message) error { 56 | select { 57 | case <-p.finished: 58 | return io.EOF 59 | default: 60 | p.outgoing <- m 61 | return nil 62 | } 63 | } 64 | 65 | func (p *localPeer) Close() error { 66 | close(p.finished) 67 | close(p.outgoing) 68 | return nil 69 | } 70 | 71 | func (p *localPeer) Addr() string { 72 | peerAddrOnce.Do(func() { 73 | // get the local address list 74 | addr, _ := net.InterfaceAddrs() 75 | if len(addr) != 0 { 76 | // use the last address in the list 77 | peerAddr = addr[len(addr)-1].String() 78 | } 79 | }) 80 | return peerAddr 81 | } 82 | 83 | var peerAddrOnce sync.Once 84 | 85 | // default address displayed for local pipes 86 | var peerAddr = "127.0.0.1/8" 87 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/storage/file_storage_unix.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | // +build darwin dragonfly freebsd linux netbsd openbsd 8 | 9 | package storage 10 | 11 | import ( 12 | "os" 13 | "syscall" 14 | ) 15 | 16 | type unixFileLock struct { 17 | f *os.File 18 | } 19 | 20 | func (fl *unixFileLock) release() error { 21 | if err := setFileLock(fl.f, false, false); err != nil { 22 | return err 23 | } 24 | return fl.f.Close() 25 | } 26 | 27 | func newFileLock(path string, readOnly bool) (fl fileLock, err error) { 28 | var flag int 29 | if readOnly { 30 | flag = os.O_RDONLY 31 | } else { 32 | flag = os.O_RDWR 33 | } 34 | f, err := os.OpenFile(path, flag, 0) 35 | if os.IsNotExist(err) { 36 | f, err = os.OpenFile(path, flag|os.O_CREATE, 0644) 37 | } 38 | if err != nil { 39 | return 40 | } 41 | err = setFileLock(f, readOnly, true) 42 | if err != nil { 43 | f.Close() 44 | return 45 | } 46 | fl = &unixFileLock{f: f} 47 | return 48 | } 49 | 50 | func setFileLock(f *os.File, readOnly, lock bool) error { 51 | how := syscall.LOCK_UN 52 | if lock { 53 | if readOnly { 54 | how = syscall.LOCK_SH 55 | } else { 56 | how = syscall.LOCK_EX 57 | } 58 | } 59 | return syscall.Flock(int(f.Fd()), how|syscall.LOCK_NB) 60 | } 61 | 62 | func rename(oldpath, newpath string) error { 63 | return os.Rename(oldpath, newpath) 64 | } 65 | 66 | func isErrInvalid(err error) bool { 67 | if err == os.ErrInvalid { 68 | return true 69 | } 70 | if syserr, ok := err.(*os.SyscallError); ok && syserr.Err == syscall.EINVAL { 71 | return true 72 | } 73 | return false 74 | } 75 | 76 | func syncDir(name string) error { 77 | f, err := os.Open(name) 78 | if err != nil { 79 | return err 80 | } 81 | defer f.Close() 82 | if err := f.Sync(); err != nil && !isErrInvalid(err) { 83 | return err 84 | } 85 | return nil 86 | } 87 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/comparer.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | package leveldb 8 | 9 | import "github.com/syndtr/goleveldb/leveldb/comparer" 10 | 11 | type iComparer struct { 12 | ucmp comparer.Comparer 13 | } 14 | 15 | func (icmp *iComparer) uName() string { 16 | return icmp.ucmp.Name() 17 | } 18 | 19 | func (icmp *iComparer) uCompare(a, b []byte) int { 20 | return icmp.ucmp.Compare(a, b) 21 | } 22 | 23 | func (icmp *iComparer) uSeparator(dst, a, b []byte) []byte { 24 | return icmp.ucmp.Separator(dst, a, b) 25 | } 26 | 27 | func (icmp *iComparer) uSuccessor(dst, b []byte) []byte { 28 | return icmp.ucmp.Successor(dst, b) 29 | } 30 | 31 | func (icmp *iComparer) Name() string { 32 | return icmp.uName() 33 | } 34 | 35 | func (icmp *iComparer) Compare(a, b []byte) int { 36 | x := icmp.ucmp.Compare(internalKey(a).ukey(), internalKey(b).ukey()) 37 | if x == 0 { 38 | if m, n := internalKey(a).num(), internalKey(b).num(); m > n { 39 | x = -1 40 | } else if m < n { 41 | x = 1 42 | } 43 | } 44 | return x 45 | } 46 | 47 | func (icmp *iComparer) Separator(dst, a, b []byte) []byte { 48 | ua, ub := internalKey(a).ukey(), internalKey(b).ukey() 49 | dst = icmp.ucmp.Separator(dst, ua, ub) 50 | if dst == nil { 51 | return nil 52 | } 53 | if len(dst) < len(ua) && icmp.uCompare(ua, dst) < 0 { 54 | dst = append(dst, keyMaxNumBytes...) 55 | } else { 56 | // Did not close possibilities that n maybe longer than len(ub). 57 | dst = append(dst, a[len(a)-8:]...) 58 | } 59 | return dst 60 | } 61 | 62 | func (icmp *iComparer) Successor(dst, b []byte) []byte { 63 | ub := internalKey(b).ukey() 64 | dst = icmp.ucmp.Successor(dst, ub) 65 | if dst == nil { 66 | return nil 67 | } 68 | if len(dst) < len(ub) && icmp.uCompare(ub, dst) < 0 { 69 | dst = append(dst, keyMaxNumBytes...) 70 | } else { 71 | // Did not close possibilities that n maybe longer than len(ub). 72 | dst = append(dst, b[len(b)-8:]...) 73 | } 74 | return dst 75 | } 76 | -------------------------------------------------------------------------------- /server/session.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "bytes" 5 | "sync" 6 | 7 | "github.com/drone/mq/logger" 8 | "github.com/drone/mq/stomp" 9 | "github.com/drone/mq/stomp/selector" 10 | ) 11 | 12 | // session represents a single client session (ie connection) 13 | type session struct { 14 | peer stomp.Peer 15 | 16 | sub map[string]*subscription 17 | ack map[string]*stomp.Message 18 | msg *stomp.Message 19 | 20 | sync.Mutex 21 | } 22 | 23 | func (s *session) init(m *stomp.Message) { 24 | s.msg = m 25 | } 26 | 27 | // send writes the message to the transport. 28 | func (s *session) send(m *stomp.Message) { 29 | logger.Debugf("stomp: sending message to client.\n%s", m) 30 | s.peer.Send(m) 31 | } 32 | 33 | // create a subscription for the current session using the 34 | // subscription settings from the given message. 35 | func (s *session) subs(m *stomp.Message) *subscription { 36 | sub := requestSubscription() 37 | sub.id = m.ID 38 | sub.dest = m.Dest 39 | sub.ack = bytes.Equal(m.Ack, stomp.AckClient) || len(m.Prefetch) != 0 40 | sub.prefetch = stomp.ParseInt(m.Prefetch) 41 | sub.session = s 42 | 43 | if len(m.Selector) != 0 { 44 | sub.selector, _ = selector.Parse(m.Selector) 45 | } 46 | 47 | s.sub[string(sub.id)] = sub 48 | return sub 49 | } 50 | 51 | // remove the subscription from the session and release 52 | // to the session pool. 53 | func (s *session) unsub(sub *subscription) { 54 | delete(s.sub, string(sub.id)) 55 | sub.release() 56 | } 57 | 58 | // reset the session properties to zero values. 59 | func (s *session) reset() { 60 | s.msg = nil 61 | s.peer = nil 62 | for id := range s.sub { 63 | delete(s.sub, id) 64 | } 65 | for id := range s.ack { 66 | delete(s.ack, id) 67 | } 68 | } 69 | 70 | // release releases the session to the pool. 71 | func (s *session) release() { 72 | s.reset() 73 | sessionPool.Put(s) 74 | } 75 | 76 | // 77 | // session pool 78 | // 79 | 80 | var sessionPool = sync.Pool{New: createSession} 81 | 82 | func createSession() interface{} { 83 | return &session{ 84 | sub: make(map[string]*subscription), 85 | ack: make(map[string]*stomp.Message), 86 | } 87 | } 88 | 89 | func requestSession() *session { 90 | return sessionPool.Get().(*session) 91 | } 92 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/storage/file_storage_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | package storage 8 | 9 | import ( 10 | "syscall" 11 | "unsafe" 12 | ) 13 | 14 | var ( 15 | modkernel32 = syscall.NewLazyDLL("kernel32.dll") 16 | 17 | procMoveFileExW = modkernel32.NewProc("MoveFileExW") 18 | ) 19 | 20 | const ( 21 | _MOVEFILE_REPLACE_EXISTING = 1 22 | ) 23 | 24 | type windowsFileLock struct { 25 | fd syscall.Handle 26 | } 27 | 28 | func (fl *windowsFileLock) release() error { 29 | return syscall.Close(fl.fd) 30 | } 31 | 32 | func newFileLock(path string, readOnly bool) (fl fileLock, err error) { 33 | pathp, err := syscall.UTF16PtrFromString(path) 34 | if err != nil { 35 | return 36 | } 37 | var access, shareMode uint32 38 | if readOnly { 39 | access = syscall.GENERIC_READ 40 | shareMode = syscall.FILE_SHARE_READ 41 | } else { 42 | access = syscall.GENERIC_READ | syscall.GENERIC_WRITE 43 | } 44 | fd, err := syscall.CreateFile(pathp, access, shareMode, nil, syscall.OPEN_EXISTING, syscall.FILE_ATTRIBUTE_NORMAL, 0) 45 | if err == syscall.ERROR_FILE_NOT_FOUND { 46 | fd, err = syscall.CreateFile(pathp, access, shareMode, nil, syscall.OPEN_ALWAYS, syscall.FILE_ATTRIBUTE_NORMAL, 0) 47 | } 48 | if err != nil { 49 | return 50 | } 51 | fl = &windowsFileLock{fd: fd} 52 | return 53 | } 54 | 55 | func moveFileEx(from *uint16, to *uint16, flags uint32) error { 56 | r1, _, e1 := syscall.Syscall(procMoveFileExW.Addr(), 3, uintptr(unsafe.Pointer(from)), uintptr(unsafe.Pointer(to)), uintptr(flags)) 57 | if r1 == 0 { 58 | if e1 != 0 { 59 | return error(e1) 60 | } 61 | return syscall.EINVAL 62 | } 63 | return nil 64 | } 65 | 66 | func rename(oldpath, newpath string) error { 67 | from, err := syscall.UTF16PtrFromString(oldpath) 68 | if err != nil { 69 | return err 70 | } 71 | to, err := syscall.UTF16PtrFromString(newpath) 72 | if err != nil { 73 | return err 74 | } 75 | return moveFileEx(from, to, _MOVEFILE_REPLACE_EXISTING) 76 | } 77 | 78 | func syncDir(name string) error { return nil } 79 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/errors/errors.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | // Package errors provides common error types used throughout leveldb. 8 | package errors 9 | 10 | import ( 11 | "errors" 12 | "fmt" 13 | 14 | "github.com/syndtr/goleveldb/leveldb/storage" 15 | "github.com/syndtr/goleveldb/leveldb/util" 16 | ) 17 | 18 | var ( 19 | ErrNotFound = New("leveldb: not found") 20 | ErrReleased = util.ErrReleased 21 | ErrHasReleaser = util.ErrHasReleaser 22 | ) 23 | 24 | // New returns an error that formats as the given text. 25 | func New(text string) error { 26 | return errors.New(text) 27 | } 28 | 29 | // ErrCorrupted is the type that wraps errors that indicate corruption in 30 | // the database. 31 | type ErrCorrupted struct { 32 | Fd storage.FileDesc 33 | Err error 34 | } 35 | 36 | func (e *ErrCorrupted) Error() string { 37 | if !e.Fd.Nil() { 38 | return fmt.Sprintf("%v [file=%v]", e.Err, e.Fd) 39 | } else { 40 | return e.Err.Error() 41 | } 42 | } 43 | 44 | // NewErrCorrupted creates new ErrCorrupted error. 45 | func NewErrCorrupted(fd storage.FileDesc, err error) error { 46 | return &ErrCorrupted{fd, err} 47 | } 48 | 49 | // IsCorrupted returns a boolean indicating whether the error is indicating 50 | // a corruption. 51 | func IsCorrupted(err error) bool { 52 | switch err.(type) { 53 | case *ErrCorrupted: 54 | return true 55 | case *storage.ErrCorrupted: 56 | return true 57 | } 58 | return false 59 | } 60 | 61 | // ErrMissingFiles is the type that indicating a corruption due to missing 62 | // files. ErrMissingFiles always wrapped with ErrCorrupted. 63 | type ErrMissingFiles struct { 64 | Fds []storage.FileDesc 65 | } 66 | 67 | func (e *ErrMissingFiles) Error() string { return "file missing" } 68 | 69 | // SetFd sets 'file info' of the given error with the given file. 70 | // Currently only ErrCorrupted is supported, otherwise will do nothing. 71 | func SetFd(err error, fd storage.FileDesc) error { 72 | switch x := err.(type) { 73 | case *ErrCorrupted: 74 | x.Fd = fd 75 | return x 76 | } 77 | return err 78 | } 79 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/util/util.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | // Package util provides utilities used throughout leveldb. 8 | package util 9 | 10 | import ( 11 | "errors" 12 | ) 13 | 14 | var ( 15 | ErrReleased = errors.New("leveldb: resource already relesed") 16 | ErrHasReleaser = errors.New("leveldb: releaser already defined") 17 | ) 18 | 19 | // Releaser is the interface that wraps the basic Release method. 20 | type Releaser interface { 21 | // Release releases associated resources. Release should always success 22 | // and can be called multipe times without causing error. 23 | Release() 24 | } 25 | 26 | // ReleaseSetter is the interface that wraps the basic SetReleaser method. 27 | type ReleaseSetter interface { 28 | // SetReleaser associates the given releaser to the resources. The 29 | // releaser will be called once coresponding resources released. 30 | // Calling SetReleaser with nil will clear the releaser. 31 | // 32 | // This will panic if a releaser already present or coresponding 33 | // resource is already released. Releaser should be cleared first 34 | // before assigned a new one. 35 | SetReleaser(releaser Releaser) 36 | } 37 | 38 | // BasicReleaser provides basic implementation of Releaser and ReleaseSetter. 39 | type BasicReleaser struct { 40 | releaser Releaser 41 | released bool 42 | } 43 | 44 | // Released returns whether Release method already called. 45 | func (r *BasicReleaser) Released() bool { 46 | return r.released 47 | } 48 | 49 | // Release implements Releaser.Release. 50 | func (r *BasicReleaser) Release() { 51 | if !r.released { 52 | if r.releaser != nil { 53 | r.releaser.Release() 54 | r.releaser = nil 55 | } 56 | r.released = true 57 | } 58 | } 59 | 60 | // SetReleaser implements ReleaseSetter.SetReleaser. 61 | func (r *BasicReleaser) SetReleaser(releaser Releaser) { 62 | if r.released { 63 | panic(ErrReleased) 64 | } 65 | if r.releaser != nil && releaser != nil { 66 | panic(ErrHasReleaser) 67 | } 68 | r.releaser = releaser 69 | } 70 | 71 | type NoopReleaser struct{} 72 | 73 | func (NoopReleaser) Release() {} 74 | -------------------------------------------------------------------------------- /server/session_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | 7 | "github.com/drone/mq/stomp" 8 | ) 9 | 10 | func Test_session_subscribe(t *testing.T) { 11 | sess := requestSession() 12 | defer sess.release() 13 | 14 | msg := stomp.NewMessage() 15 | msg.Dest = []byte("/topic/test") 16 | msg.ID = []byte("123") 17 | msg.Prefetch = []byte("2") 18 | msg.Selector = []byte("ram > 2") 19 | defer msg.Release() 20 | 21 | sub := sess.subs(msg) 22 | if sub.prefetch != 2 { 23 | t.Errorf("expected subscription prefix copied from message") 24 | } 25 | if !bytes.Equal(sub.id, []byte("123")) { 26 | t.Errorf("expected subscription id correctly set, got %d", sub.id) 27 | } 28 | if sub.session != sess { 29 | t.Errorf("expect session attached to subscription") 30 | } 31 | if sess.sub["123"] != sub { 32 | t.Errorf("expect subscription tracked in session map") 33 | } 34 | if sub.selector == nil { 35 | t.Errorf("expect subscription sql selector successfully parsed") 36 | } 37 | 38 | sess.unsub(sub) 39 | if len(sub.id) != 0 { 40 | t.Errorf("expected subscription reset") 41 | } 42 | if sess.sub["1"] != nil { 43 | t.Errorf("expect subscription removed from session") 44 | } 45 | } 46 | 47 | func Test_session_reset(t *testing.T) { 48 | sess := &session{ 49 | peer: nil, 50 | sub: map[string]*subscription{ 51 | "0": &subscription{}, 52 | }, 53 | ack: map[string]*stomp.Message{ 54 | "0": &stomp.Message{}, 55 | }, 56 | } 57 | sess.reset() 58 | 59 | if sess.peer != nil { 60 | t.Errorf("expect session transport reset") 61 | } 62 | if len(sess.sub) != 0 { 63 | t.Errorf("expect session subscription map reset") 64 | } 65 | if len(sess.ack) != 0 { 66 | t.Errorf("expect session acknowledgement map reset") 67 | } 68 | } 69 | 70 | func Test_session_send(t *testing.T) { 71 | a, b := stomp.Pipe() 72 | 73 | s := requestSession() 74 | s.peer = a 75 | 76 | sent := stomp.NewMessage() 77 | s.send(sent) 78 | 79 | recv := <-b.Receive() 80 | if sent != recv { 81 | t.Errorf("expect session.send to send message to peer") 82 | } 83 | 84 | sent.Release() 85 | s.release() 86 | } 87 | 88 | func Test_session_pool(t *testing.T) { 89 | s := requestSession() 90 | if s == nil { 91 | t.Errorf("expected session from pool") 92 | } 93 | s.release() 94 | } 95 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/ssh/terminal/util_plan9.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package terminal provides support functions for dealing with terminals, as 6 | // commonly found on UNIX systems. 7 | // 8 | // Putting a terminal into raw mode is the most common requirement: 9 | // 10 | // oldState, err := terminal.MakeRaw(0) 11 | // if err != nil { 12 | // panic(err) 13 | // } 14 | // defer terminal.Restore(0, oldState) 15 | package terminal 16 | 17 | import ( 18 | "fmt" 19 | "runtime" 20 | ) 21 | 22 | type State struct{} 23 | 24 | // IsTerminal returns true if the given file descriptor is a terminal. 25 | func IsTerminal(fd int) bool { 26 | return false 27 | } 28 | 29 | // MakeRaw put the terminal connected to the given file descriptor into raw 30 | // mode and returns the previous state of the terminal so that it can be 31 | // restored. 32 | func MakeRaw(fd int) (*State, error) { 33 | return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) 34 | } 35 | 36 | // GetState returns the current state of a terminal which may be useful to 37 | // restore the terminal after a signal. 38 | func GetState(fd int) (*State, error) { 39 | return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) 40 | } 41 | 42 | // Restore restores the terminal connected to the given file descriptor to a 43 | // previous state. 44 | func Restore(fd int, state *State) error { 45 | return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) 46 | } 47 | 48 | // GetSize returns the dimensions of the given terminal. 49 | func GetSize(fd int) (width, height int, err error) { 50 | return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) 51 | } 52 | 53 | // ReadPassword reads a line of input from a terminal without local echo. This 54 | // is commonly used for inputting passwords and other sensitive data. The slice 55 | // returned does not include the \n. 56 | func ReadPassword(fd int) ([]byte, error) { 57 | return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) 58 | } 59 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/filter/filter.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | // Package filter provides interface and implementation of probabilistic 8 | // data structure. 9 | // 10 | // The filter is resposible for creating small filter from a set of keys. 11 | // These filter will then used to test whether a key is a member of the set. 12 | // In many cases, a filter can cut down the number of disk seeks from a 13 | // handful to a single disk seek per DB.Get call. 14 | package filter 15 | 16 | // Buffer is the interface that wraps basic Alloc, Write and WriteByte methods. 17 | type Buffer interface { 18 | // Alloc allocs n bytes of slice from the buffer. This also advancing 19 | // write offset. 20 | Alloc(n int) []byte 21 | 22 | // Write appends the contents of p to the buffer. 23 | Write(p []byte) (n int, err error) 24 | 25 | // WriteByte appends the byte c to the buffer. 26 | WriteByte(c byte) error 27 | } 28 | 29 | // Filter is the filter. 30 | type Filter interface { 31 | // Name returns the name of this policy. 32 | // 33 | // Note that if the filter encoding changes in an incompatible way, 34 | // the name returned by this method must be changed. Otherwise, old 35 | // incompatible filters may be passed to methods of this type. 36 | Name() string 37 | 38 | // NewGenerator creates a new filter generator. 39 | NewGenerator() FilterGenerator 40 | 41 | // Contains returns true if the filter contains the given key. 42 | // 43 | // The filter are filters generated by the filter generator. 44 | Contains(filter, key []byte) bool 45 | } 46 | 47 | // FilterGenerator is the filter generator. 48 | type FilterGenerator interface { 49 | // Add adds a key to the filter generator. 50 | // 51 | // The key may become invalid after call to this method end, therefor 52 | // key must be copied if implementation require keeping key for later 53 | // use. The key should not modified directly, doing so may cause 54 | // undefined results. 55 | Add(key []byte) 56 | 57 | // Generate generates filters based on keys passed so far. After call 58 | // to Generate the filter generator maybe resetted, depends on implementation. 59 | Generate(b Buffer) 60 | } 61 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/comparer/comparer.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | // Package comparer provides interface and implementation for ordering 8 | // sets of data. 9 | package comparer 10 | 11 | // BasicComparer is the interface that wraps the basic Compare method. 12 | type BasicComparer interface { 13 | // Compare returns -1, 0, or +1 depending on whether a is 'less than', 14 | // 'equal to' or 'greater than' b. The two arguments can only be 'equal' 15 | // if their contents are exactly equal. Furthermore, the empty slice 16 | // must be 'less than' any non-empty slice. 17 | Compare(a, b []byte) int 18 | } 19 | 20 | // Comparer defines a total ordering over the space of []byte keys: a 'less 21 | // than' relationship. 22 | type Comparer interface { 23 | BasicComparer 24 | 25 | // Name returns name of the comparer. 26 | // 27 | // The Level-DB on-disk format stores the comparer name, and opening a 28 | // database with a different comparer from the one it was created with 29 | // will result in an error. 30 | // 31 | // An implementation to a new name whenever the comparer implementation 32 | // changes in a way that will cause the relative ordering of any two keys 33 | // to change. 34 | // 35 | // Names starting with "leveldb." are reserved and should not be used 36 | // by any users of this package. 37 | Name() string 38 | 39 | // Bellow are advanced functions used used to reduce the space requirements 40 | // for internal data structures such as index blocks. 41 | 42 | // Separator appends a sequence of bytes x to dst such that a <= x && x < b, 43 | // where 'less than' is consistent with Compare. An implementation should 44 | // return nil if x equal to a. 45 | // 46 | // Either contents of a or b should not by any means modified. Doing so 47 | // may cause corruption on the internal state. 48 | Separator(dst, a, b []byte) []byte 49 | 50 | // Successor appends a sequence of bytes x to dst such that x >= b, where 51 | // 'less than' is consistent with Compare. An implementation should return 52 | // nil if x equal to b. 53 | // 54 | // Contents of b should not by any means modified. Doing so may cause 55 | // corruption on the internal state. 56 | Successor(dst, b []byte) []byte 57 | } 58 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.7 6 | 7 | // Package ctxhttp provides helper functions for performing context-aware HTTP requests. 8 | package ctxhttp // import "golang.org/x/net/context/ctxhttp" 9 | 10 | import ( 11 | "io" 12 | "net/http" 13 | "net/url" 14 | "strings" 15 | 16 | "golang.org/x/net/context" 17 | ) 18 | 19 | // Do sends an HTTP request with the provided http.Client and returns 20 | // an HTTP response. 21 | // 22 | // If the client is nil, http.DefaultClient is used. 23 | // 24 | // The provided ctx must be non-nil. If it is canceled or times out, 25 | // ctx.Err() will be returned. 26 | func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { 27 | if client == nil { 28 | client = http.DefaultClient 29 | } 30 | resp, err := client.Do(req.WithContext(ctx)) 31 | // If we got an error, and the context has been canceled, 32 | // the context's error is probably more useful. 33 | if err != nil { 34 | select { 35 | case <-ctx.Done(): 36 | err = ctx.Err() 37 | default: 38 | } 39 | } 40 | return resp, err 41 | } 42 | 43 | // Get issues a GET request via the Do function. 44 | func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) { 45 | req, err := http.NewRequest("GET", url, nil) 46 | if err != nil { 47 | return nil, err 48 | } 49 | return Do(ctx, client, req) 50 | } 51 | 52 | // Head issues a HEAD request via the Do function. 53 | func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) { 54 | req, err := http.NewRequest("HEAD", url, nil) 55 | if err != nil { 56 | return nil, err 57 | } 58 | return Do(ctx, client, req) 59 | } 60 | 61 | // Post issues a POST request via the Do function. 62 | func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) { 63 | req, err := http.NewRequest("POST", url, body) 64 | if err != nil { 65 | return nil, err 66 | } 67 | req.Header.Set("Content-Type", bodyType) 68 | return Do(ctx, client, req) 69 | } 70 | 71 | // PostForm issues a POST request via the Do function. 72 | func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) { 73 | return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) 74 | } 75 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | // Package leveldb provides implementation of LevelDB key/value database. 8 | // 9 | // Create or open a database: 10 | // 11 | // db, err := leveldb.OpenFile("path/to/db", nil) 12 | // ... 13 | // defer db.Close() 14 | // ... 15 | // 16 | // Read or modify the database content: 17 | // 18 | // // Remember that the contents of the returned slice should not be modified. 19 | // data, err := db.Get([]byte("key"), nil) 20 | // ... 21 | // err = db.Put([]byte("key"), []byte("value"), nil) 22 | // ... 23 | // err = db.Delete([]byte("key"), nil) 24 | // ... 25 | // 26 | // Iterate over database content: 27 | // 28 | // iter := db.NewIterator(nil, nil) 29 | // for iter.Next() { 30 | // // Remember that the contents of the returned slice should not be modified, and 31 | // // only valid until the next call to Next. 32 | // key := iter.Key() 33 | // value := iter.Value() 34 | // ... 35 | // } 36 | // iter.Release() 37 | // err = iter.Error() 38 | // ... 39 | // 40 | // Iterate over subset of database content with a particular prefix: 41 | // iter := db.NewIterator(util.BytesPrefix([]byte("foo-")), nil) 42 | // for iter.Next() { 43 | // // Use key/value. 44 | // ... 45 | // } 46 | // iter.Release() 47 | // err = iter.Error() 48 | // ... 49 | // 50 | // Seek-then-Iterate: 51 | // 52 | // iter := db.NewIterator(nil, nil) 53 | // for ok := iter.Seek(key); ok; ok = iter.Next() { 54 | // // Use key/value. 55 | // ... 56 | // } 57 | // iter.Release() 58 | // err = iter.Error() 59 | // ... 60 | // 61 | // Iterate over subset of database content: 62 | // 63 | // iter := db.NewIterator(&util.Range{Start: []byte("foo"), Limit: []byte("xoo")}, nil) 64 | // for iter.Next() { 65 | // // Use key/value. 66 | // ... 67 | // } 68 | // iter.Release() 69 | // err = iter.Error() 70 | // ... 71 | // 72 | // Batch writes: 73 | // 74 | // batch := new(leveldb.Batch) 75 | // batch.Put([]byte("foo"), []byte("value")) 76 | // batch.Put([]byte("bar"), []byte("another value")) 77 | // batch.Delete([]byte("baz")) 78 | // err = db.Write(batch, nil) 79 | // ... 80 | // 81 | // Use bloom filter: 82 | // 83 | // o := &opt.Options{ 84 | // Filter: filter.NewBloomFilter(10), 85 | // } 86 | // db, err := leveldb.OpenFile("path/to/db", o) 87 | // ... 88 | // defer db.Close() 89 | // ... 90 | package leveldb 91 | -------------------------------------------------------------------------------- /vendor/github.com/dchest/uniuri/README.md: -------------------------------------------------------------------------------- 1 | Package uniuri 2 | ===================== 3 | 4 | [![Build Status](https://travis-ci.org/dchest/uniuri.svg)](https://travis-ci.org/dchest/uniuri) 5 | 6 | ```go 7 | import "github.com/dchest/uniuri" 8 | ``` 9 | 10 | Package uniuri generates random strings good for use in URIs to identify 11 | unique objects. 12 | 13 | Example usage: 14 | 15 | ```go 16 | s := uniuri.New() // s is now "apHCJBl7L1OmC57n" 17 | ``` 18 | 19 | A standard string created by New() is 16 bytes in length and consists of 20 | Latin upper and lowercase letters, and numbers (from the set of 62 allowed 21 | characters), which means that it has ~95 bits of entropy. To get more 22 | entropy, you can use NewLen(UUIDLen), which returns 20-byte string, giving 23 | ~119 bits of entropy, or any other desired length. 24 | 25 | Functions read from crypto/rand random source, and panic if they fail to 26 | read from it. 27 | 28 | 29 | Constants 30 | --------- 31 | 32 | ```go 33 | const ( 34 | // StdLen is a standard length of uniuri string to achive ~95 bits of entropy. 35 | StdLen = 16 36 | // UUIDLen is a length of uniuri string to achive ~119 bits of entropy, closest 37 | // to what can be losslessly converted to UUIDv4 (122 bits). 38 | UUIDLen = 20 39 | ) 40 | 41 | ``` 42 | 43 | 44 | 45 | Variables 46 | --------- 47 | 48 | ```go 49 | var StdChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") 50 | ``` 51 | 52 | 53 | StdChars is a set of standard characters allowed in uniuri string. 54 | 55 | 56 | Functions 57 | --------- 58 | 59 | ### func New 60 | 61 | ```go 62 | func New() string 63 | ``` 64 | 65 | New returns a new random string of the standard length, consisting of 66 | standard characters. 67 | 68 | ### func NewLen 69 | 70 | ```go 71 | func NewLen(length int) string 72 | ``` 73 | 74 | NewLen returns a new random string of the provided length, consisting of 75 | standard characters. 76 | 77 | ### func NewLenChars 78 | 79 | ```go 80 | func NewLenChars(length int, chars []byte) string 81 | ``` 82 | 83 | NewLenChars returns a new random string of the provided length, consisting 84 | of the provided byte slice of allowed characters (maximum 256). 85 | 86 | 87 | 88 | Public domain dedication 89 | ------------------------ 90 | 91 | Written in 2011-2014 by Dmitry Chestnykh 92 | 93 | The author(s) have dedicated all copyright and related and 94 | neighboring rights to this software to the public domain 95 | worldwide. Distributed without any warranty. 96 | http://creativecommons.org/publicdomain/zero/1.0/ 97 | 98 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/cli/errors.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "strings" 8 | ) 9 | 10 | // OsExiter is the function used when the app exits. If not set defaults to os.Exit. 11 | var OsExiter = os.Exit 12 | 13 | // ErrWriter is used to write errors to the user. This can be anything 14 | // implementing the io.Writer interface and defaults to os.Stderr. 15 | var ErrWriter io.Writer = os.Stderr 16 | 17 | // MultiError is an error that wraps multiple errors. 18 | type MultiError struct { 19 | Errors []error 20 | } 21 | 22 | // NewMultiError creates a new MultiError. Pass in one or more errors. 23 | func NewMultiError(err ...error) MultiError { 24 | return MultiError{Errors: err} 25 | } 26 | 27 | // Error implents the error interface. 28 | func (m MultiError) Error() string { 29 | errs := make([]string, len(m.Errors)) 30 | for i, err := range m.Errors { 31 | errs[i] = err.Error() 32 | } 33 | 34 | return strings.Join(errs, "\n") 35 | } 36 | 37 | // ExitCoder is the interface checked by `App` and `Command` for a custom exit 38 | // code 39 | type ExitCoder interface { 40 | error 41 | ExitCode() int 42 | } 43 | 44 | // ExitError fulfills both the builtin `error` interface and `ExitCoder` 45 | type ExitError struct { 46 | exitCode int 47 | message string 48 | } 49 | 50 | // NewExitError makes a new *ExitError 51 | func NewExitError(message string, exitCode int) *ExitError { 52 | return &ExitError{ 53 | exitCode: exitCode, 54 | message: message, 55 | } 56 | } 57 | 58 | // Error returns the string message, fulfilling the interface required by 59 | // `error` 60 | func (ee *ExitError) Error() string { 61 | return ee.message 62 | } 63 | 64 | // ExitCode returns the exit code, fulfilling the interface required by 65 | // `ExitCoder` 66 | func (ee *ExitError) ExitCode() int { 67 | return ee.exitCode 68 | } 69 | 70 | // HandleExitCoder checks if the error fulfills the ExitCoder interface, and if 71 | // so prints the error to stderr (if it is non-empty) and calls OsExiter with the 72 | // given exit code. If the given error is a MultiError, then this func is 73 | // called on all members of the Errors slice. 74 | func HandleExitCoder(err error) { 75 | if err == nil { 76 | return 77 | } 78 | 79 | if exitErr, ok := err.(ExitCoder); ok { 80 | if err.Error() != "" { 81 | fmt.Fprintln(ErrWriter, err) 82 | } 83 | OsExiter(exitErr.ExitCode()) 84 | return 85 | } 86 | 87 | if multiErr, ok := err.(MultiError); ok { 88 | for _, merr := range multiErr.Errors { 89 | HandleExitCoder(merr) 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /stomp/const.go: -------------------------------------------------------------------------------- 1 | package stomp 2 | 3 | // STOMP protocol version. 4 | var STOMP = []byte("1.2") 5 | 6 | // STOMP protocol methods. 7 | var ( 8 | MethodStomp = []byte("STOMP") 9 | MethodConnect = []byte("CONNECT") 10 | MethodConnected = []byte("CONNECTED") 11 | MethodSend = []byte("SEND") 12 | MethodSubscribe = []byte("SUBSCRIBE") 13 | MethodUnsubscribe = []byte("UNSUBSCRIBE") 14 | MethodAck = []byte("ACK") 15 | MethodNack = []byte("NACK") 16 | MethodDisconnect = []byte("DISCONNECT") 17 | MethodMessage = []byte("MESSAGE") 18 | MethodRecipet = []byte("RECEIPT") 19 | MethodError = []byte("ERROR") 20 | ) 21 | 22 | // STOMP protocol headers. 23 | var ( 24 | HeaderAccept = []byte("accept-version") 25 | HeaderAck = []byte("ack") 26 | HeaderExpires = []byte("expires") 27 | HeaderDest = []byte("destination") 28 | HeaderHost = []byte("host") 29 | HeaderLogin = []byte("login") 30 | HeaderPass = []byte("passcode") 31 | HeaderID = []byte("id") 32 | HeaderMessageID = []byte("message-id") 33 | HeaderPersist = []byte("persist") 34 | HeaderPrefetch = []byte("prefetch-count") 35 | HeaderReceipt = []byte("receipt") 36 | HeaderReceiptID = []byte("receipt-id") 37 | HeaderRetain = []byte("retain") 38 | HeaderSelector = []byte("selector") 39 | HeaderServer = []byte("server") 40 | HeaderSession = []byte("session") 41 | HeaderSubscription = []byte("subscription") 42 | HeaderVersion = []byte("version") 43 | ) 44 | 45 | // Common STOMP header values. 46 | var ( 47 | AckAuto = []byte("auto") 48 | AckClient = []byte("client") 49 | PersistTrue = []byte("true") 50 | RetainTrue = []byte("true") 51 | RetainLast = []byte("last") 52 | RetainAll = []byte("all") 53 | RetainRemove = []byte("remove") 54 | ) 55 | 56 | var headerLookup = map[string]struct{}{ 57 | "accept-version": struct{}{}, 58 | "ack": struct{}{}, 59 | "expires": struct{}{}, 60 | "destination": struct{}{}, 61 | "host": struct{}{}, 62 | "login": struct{}{}, 63 | "passcode": struct{}{}, 64 | "id": struct{}{}, 65 | "message-id": struct{}{}, 66 | "persist": struct{}{}, 67 | "prefetch-count": struct{}{}, 68 | "receipt": struct{}{}, 69 | "receipt-id": struct{}{}, 70 | "retain": struct{}{}, 71 | "selector": struct{}{}, 72 | "server": struct{}{}, 73 | "session": struct{}{}, 74 | "subscription": struct{}{}, 75 | "version": struct{}{}, 76 | } 77 | -------------------------------------------------------------------------------- /stomp/option_test.go: -------------------------------------------------------------------------------- 1 | package stomp 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | ) 7 | 8 | func TestOptions(t *testing.T) { 9 | opt := WithAck("auto") 10 | msg := NewMessage() 11 | msg.Apply(opt) 12 | if !bytes.Equal(msg.Ack, AckAuto) { 13 | t.Errorf("Want WiathAck to apply ack header") 14 | } 15 | 16 | opt = WithCredentials("janedoe", "password") 17 | msg = NewMessage() 18 | msg.Apply(opt) 19 | if string(msg.User) != "janedoe" { 20 | t.Errorf("Want WithCredentials to apply username header") 21 | } 22 | if string(msg.Pass) != "password" { 23 | t.Errorf("Want WithCredentials to apply password header") 24 | } 25 | 26 | opt = WithExpires(1234) 27 | msg = NewMessage() 28 | msg.Apply(opt) 29 | if !bytes.Equal(msg.Expires, []byte("1234")) { 30 | t.Errorf("Want WithExpires to apply expires header") 31 | } 32 | 33 | opt = WithHeader("foo", "bar") 34 | msg = NewMessage() 35 | msg.Apply(opt) 36 | if v := msg.Header.Get([]byte("foo")); string(v) != "bar" { 37 | t.Errorf("Want WithHeader to add header keypair") 38 | } 39 | 40 | opt = WithHeader("id", "123") 41 | msg = NewMessage() 42 | msg.Apply(opt) 43 | if v := msg.Header.Get([]byte("id")); string(v) != "" { 44 | t.Errorf("Want WithHeader to reject reserved header") 45 | } 46 | 47 | opt = WithHeaders(map[string]string{"baz": "boo", "id": "123"}) 48 | msg = NewMessage() 49 | msg.Apply(opt) 50 | if v := msg.Header.Get([]byte("baz")); string(v) != "boo" { 51 | t.Errorf("Want WithHeaders to add header keypairs") 52 | } 53 | if v := msg.Header.Get([]byte("id")); string(v) != "" { 54 | t.Errorf("Want WithHeaders to reject reserved header") 55 | } 56 | 57 | opt = WithPersistence() 58 | msg = NewMessage() 59 | msg.Apply(opt) 60 | if !bytes.Equal(msg.Persist, PersistTrue) { 61 | t.Errorf("Want WithPersistence to apply persist header") 62 | } 63 | 64 | opt = WithPrefetch(2) 65 | msg = NewMessage() 66 | msg.Apply(opt) 67 | if !bytes.Equal(msg.Prefetch, []byte("2")) { 68 | t.Errorf("Want WithPrefetch to apply persist header") 69 | } 70 | 71 | opt = WithReceipt() 72 | msg = NewMessage() 73 | msg.Apply(opt) 74 | if len(msg.Receipt) == 0 { 75 | t.Errorf("Want WithReceipt to apply receipt header") 76 | } 77 | 78 | opt = WithRetain("last") 79 | msg = NewMessage() 80 | msg.Apply(opt) 81 | if !bytes.Equal(msg.Retain, RetainLast) { 82 | t.Errorf("Want WithRetain to apply retain header") 83 | } 84 | 85 | opt = WithSelector("ram > 2") 86 | msg = NewMessage() 87 | msg.Apply(opt) 88 | if !bytes.Equal(msg.Selector, []byte("ram > 2")) { 89 | t.Errorf("Want WithRetain to apply retain header") 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /vendor/github.com/kr/text/wrap.go: -------------------------------------------------------------------------------- 1 | package text 2 | 3 | import ( 4 | "bytes" 5 | "math" 6 | ) 7 | 8 | var ( 9 | nl = []byte{'\n'} 10 | sp = []byte{' '} 11 | ) 12 | 13 | const defaultPenalty = 1e5 14 | 15 | // Wrap wraps s into a paragraph of lines of length lim, with minimal 16 | // raggedness. 17 | func Wrap(s string, lim int) string { 18 | return string(WrapBytes([]byte(s), lim)) 19 | } 20 | 21 | // WrapBytes wraps b into a paragraph of lines of length lim, with minimal 22 | // raggedness. 23 | func WrapBytes(b []byte, lim int) []byte { 24 | words := bytes.Split(bytes.Replace(bytes.TrimSpace(b), nl, sp, -1), sp) 25 | var lines [][]byte 26 | for _, line := range WrapWords(words, 1, lim, defaultPenalty) { 27 | lines = append(lines, bytes.Join(line, sp)) 28 | } 29 | return bytes.Join(lines, nl) 30 | } 31 | 32 | // WrapWords is the low-level line-breaking algorithm, useful if you need more 33 | // control over the details of the text wrapping process. For most uses, either 34 | // Wrap or WrapBytes will be sufficient and more convenient. 35 | // 36 | // WrapWords splits a list of words into lines with minimal "raggedness", 37 | // treating each byte as one unit, accounting for spc units between adjacent 38 | // words on each line, and attempting to limit lines to lim units. Raggedness 39 | // is the total error over all lines, where error is the square of the 40 | // difference of the length of the line and lim. Too-long lines (which only 41 | // happen when a single word is longer than lim units) have pen penalty units 42 | // added to the error. 43 | func WrapWords(words [][]byte, spc, lim, pen int) [][][]byte { 44 | n := len(words) 45 | 46 | length := make([][]int, n) 47 | for i := 0; i < n; i++ { 48 | length[i] = make([]int, n) 49 | length[i][i] = len(words[i]) 50 | for j := i + 1; j < n; j++ { 51 | length[i][j] = length[i][j-1] + spc + len(words[j]) 52 | } 53 | } 54 | 55 | nbrk := make([]int, n) 56 | cost := make([]int, n) 57 | for i := range cost { 58 | cost[i] = math.MaxInt32 59 | } 60 | for i := n - 1; i >= 0; i-- { 61 | if length[i][n-1] <= lim || i == n-1 { 62 | cost[i] = 0 63 | nbrk[i] = n 64 | } else { 65 | for j := i + 1; j < n; j++ { 66 | d := lim - length[i][j-1] 67 | c := d*d + cost[j] 68 | if length[i][j-1] > lim { 69 | c += pen // too-long lines get a worse penalty 70 | } 71 | if c < cost[i] { 72 | cost[i] = c 73 | nbrk[i] = j 74 | } 75 | } 76 | } 77 | } 78 | 79 | var lines [][][]byte 80 | i := 0 81 | for i < n { 82 | lines = append(lines, words[i:nbrk[i]]) 83 | i = nbrk[i] 84 | } 85 | return lines 86 | } 87 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/cli/flag-types.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Bool", 4 | "type": "bool", 5 | "value": false, 6 | "context_default": "false", 7 | "parser": "strconv.ParseBool(f.Value.String())" 8 | }, 9 | { 10 | "name": "BoolT", 11 | "type": "bool", 12 | "value": false, 13 | "doctail": " that is true by default", 14 | "context_default": "false", 15 | "parser": "strconv.ParseBool(f.Value.String())" 16 | }, 17 | { 18 | "name": "Duration", 19 | "type": "time.Duration", 20 | "doctail": " (see https://golang.org/pkg/time/#ParseDuration)", 21 | "context_default": "0", 22 | "parser": "time.ParseDuration(f.Value.String())" 23 | }, 24 | { 25 | "name": "Float64", 26 | "type": "float64", 27 | "context_default": "0", 28 | "parser": "strconv.ParseFloat(f.Value.String(), 64)" 29 | }, 30 | { 31 | "name": "Generic", 32 | "type": "Generic", 33 | "dest": false, 34 | "context_default": "nil", 35 | "context_type": "interface{}" 36 | }, 37 | { 38 | "name": "Int64", 39 | "type": "int64", 40 | "context_default": "0", 41 | "parser": "strconv.ParseInt(f.Value.String(), 0, 64)" 42 | }, 43 | { 44 | "name": "Int", 45 | "type": "int", 46 | "context_default": "0", 47 | "parser": "strconv.ParseInt(f.Value.String(), 0, 64)", 48 | "parser_cast": "int(parsed)" 49 | }, 50 | { 51 | "name": "IntSlice", 52 | "type": "*IntSlice", 53 | "dest": false, 54 | "context_default": "nil", 55 | "context_type": "[]int", 56 | "parser": "(f.Value.(*IntSlice)).Value(), error(nil)" 57 | }, 58 | { 59 | "name": "Int64Slice", 60 | "type": "*Int64Slice", 61 | "dest": false, 62 | "context_default": "nil", 63 | "context_type": "[]int64", 64 | "parser": "(f.Value.(*Int64Slice)).Value(), error(nil)" 65 | }, 66 | { 67 | "name": "String", 68 | "type": "string", 69 | "context_default": "\"\"", 70 | "parser": "f.Value.String(), error(nil)" 71 | }, 72 | { 73 | "name": "StringSlice", 74 | "type": "*StringSlice", 75 | "dest": false, 76 | "context_default": "nil", 77 | "context_type": "[]string", 78 | "parser": "(f.Value.(*StringSlice)).Value(), error(nil)" 79 | }, 80 | { 81 | "name": "Uint64", 82 | "type": "uint64", 83 | "context_default": "0", 84 | "parser": "strconv.ParseUint(f.Value.String(), 0, 64)" 85 | }, 86 | { 87 | "name": "Uint", 88 | "type": "uint", 89 | "context_default": "0", 90 | "parser": "strconv.ParseUint(f.Value.String(), 0, 64)", 91 | "parser_cast": "uint(parsed)" 92 | } 93 | ] 94 | -------------------------------------------------------------------------------- /stomp/header.go: -------------------------------------------------------------------------------- 1 | package stomp 2 | 3 | import ( 4 | "bytes" 5 | "strconv" 6 | ) 7 | 8 | const defaultHeaderLen = 5 9 | 10 | type item struct { 11 | name []byte 12 | data []byte 13 | } 14 | 15 | // Header represents the header section of the STOMP message. 16 | type Header struct { 17 | items []item 18 | itemc int 19 | } 20 | 21 | func newHeader() *Header { 22 | return &Header{ 23 | items: make([]item, defaultHeaderLen), 24 | } 25 | } 26 | 27 | // Get returns the named header value. 28 | func (h *Header) Get(name []byte) (b []byte) { 29 | for i := 0; i < h.itemc; i++ { 30 | if v := h.items[i]; bytes.Equal(v.name, name) { 31 | return v.data 32 | } 33 | } 34 | return 35 | } 36 | 37 | // GetString returns the named header value. 38 | func (h *Header) GetString(name string) string { 39 | k := []byte(name) 40 | v := h.Get(k) 41 | return string(v) 42 | } 43 | 44 | // GetBool returns the named header value. 45 | func (h *Header) GetBool(name string) bool { 46 | s := h.GetString(name) 47 | b, _ := strconv.ParseBool(s) 48 | return b 49 | } 50 | 51 | // GetInt returns the named header value. 52 | func (h *Header) GetInt(name string) int { 53 | s := h.GetString(name) 54 | i, _ := strconv.Atoi(s) 55 | return i 56 | } 57 | 58 | // GetInt64 returns the named header value. 59 | func (h *Header) GetInt64(name string) int64 { 60 | s := h.GetString(name) 61 | i, _ := strconv.ParseInt(s, 10, 64) 62 | return i 63 | } 64 | 65 | // Field returns the named header value in string format. This is used to 66 | // provide compatibility with the SQL expression evaluation package. 67 | func (h *Header) Field(name []byte) []byte { 68 | return h.Get(name) 69 | } 70 | 71 | // Add appens the key value pair to the header. 72 | func (h *Header) Add(name, data []byte) { 73 | h.grow() 74 | h.items[h.itemc].name = name 75 | h.items[h.itemc].data = data 76 | h.itemc++ 77 | } 78 | 79 | // Index returns the keypair at index i. 80 | func (h *Header) Index(i int) (k, v []byte) { 81 | if i > h.itemc { 82 | return 83 | } 84 | k = h.items[i].name 85 | v = h.items[i].data 86 | return 87 | } 88 | 89 | // Len returns the header length. 90 | func (h *Header) Len() int { 91 | return h.itemc 92 | } 93 | 94 | func (h *Header) grow() { 95 | if h.itemc > defaultHeaderLen-1 { 96 | h.items = append(h.items, item{}) 97 | } 98 | } 99 | 100 | func (h *Header) reset() { 101 | h.itemc = 0 102 | h.items = h.items[:defaultHeaderLen] 103 | for i := range h.items { 104 | h.items[i].name = zeroBytes 105 | h.items[i].data = zeroBytes 106 | } 107 | } 108 | 109 | var zeroBytes []byte 110 | -------------------------------------------------------------------------------- /stomp/option.go: -------------------------------------------------------------------------------- 1 | package stomp 2 | 3 | import ( 4 | "math/rand" 5 | "strconv" 6 | "strings" 7 | ) 8 | 9 | // MessageOption configures message options. 10 | type MessageOption func(*Message) 11 | 12 | // WithCredentials returns a MessageOption which sets credentials. 13 | func WithCredentials(username, password string) MessageOption { 14 | return func(m *Message) { 15 | m.User = []byte(username) 16 | m.Pass = []byte(password) 17 | } 18 | } 19 | 20 | // WithHeader returns a MessageOption which sets a header. 21 | func WithHeader(key, value string) MessageOption { 22 | return func(m *Message) { 23 | _, ok := headerLookup[strings.ToLower(key)] 24 | if !ok { 25 | m.Header.Add( 26 | []byte(key), 27 | []byte(value), 28 | ) 29 | } 30 | } 31 | } 32 | 33 | // WithHeaders returns a MessageOption which sets headers. 34 | func WithHeaders(headers map[string]string) MessageOption { 35 | return func(m *Message) { 36 | for key, value := range headers { 37 | _, ok := headerLookup[strings.ToLower(key)] 38 | if !ok { 39 | m.Header.Add( 40 | []byte(key), 41 | []byte(value), 42 | ) 43 | } 44 | } 45 | } 46 | } 47 | 48 | // WithExpires returns a MessageOption configured with an expiration. 49 | func WithExpires(exp int64) MessageOption { 50 | return func(m *Message) { 51 | m.Expires = strconv.AppendInt(nil, exp, 10) 52 | } 53 | } 54 | 55 | // WithPrefetch returns a MessageOption configured with a prefetch count. 56 | func WithPrefetch(prefetch int) MessageOption { 57 | return func(m *Message) { 58 | m.Prefetch = strconv.AppendInt(nil, int64(prefetch), 10) 59 | } 60 | } 61 | 62 | // WithReceipt returns a MessageOption configured with a receipt request. 63 | func WithReceipt() MessageOption { 64 | return func(m *Message) { 65 | m.Receipt = strconv.AppendInt(nil, rand.Int63(), 10) 66 | } 67 | } 68 | 69 | // WithPersistence returns a MessageOption configured to persist. 70 | func WithPersistence() MessageOption { 71 | return func(m *Message) { 72 | m.Persist = PersistTrue 73 | } 74 | } 75 | 76 | // WithRetain returns a MessageOption configured to retain the message. 77 | func WithRetain(retain string) MessageOption { 78 | return func(m *Message) { 79 | m.Retain = []byte(retain) 80 | } 81 | } 82 | 83 | // WithSelector returns a MessageOption configured to filter messages 84 | // using a sql-like evaluation string. 85 | func WithSelector(selector string) MessageOption { 86 | return func(m *Message) { 87 | m.Selector = []byte(selector) 88 | } 89 | } 90 | 91 | // WithAck returns a MessageOption configured with an ack policy. 92 | func WithAck(ack string) MessageOption { 93 | return func(m *Message) { 94 | m.Ack = []byte(ack) 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /stomp/header_test.go: -------------------------------------------------------------------------------- 1 | package stomp 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "testing" 7 | ) 8 | 9 | func TestHeader(t *testing.T) { 10 | header := newHeader() 11 | if got := len(header.items); got != defaultHeaderLen { 12 | t.Errorf("Want the default items len %v, got %d", defaultHeaderLen, got) 13 | } 14 | 15 | for i := 0; i < 10; i++ { 16 | var ( 17 | key = fmt.Sprintf("col%d", i) 18 | val = fmt.Sprintf("dat%d", i) 19 | keyb = []byte(key) 20 | valb = []byte(val) 21 | ) 22 | 23 | header.Add(keyb, valb) 24 | 25 | // the default list length is 5 and will be expanded as the 26 | // list grows. This check verifies the list grows as expected. 27 | if header.Len() != i+1 { 28 | t.Errorf("Want header length %d, got %d", i+1, header.itemc) 29 | } 30 | 31 | // this check verifies header key pairs were added to the list 32 | // and can can be retrieved by header name 33 | if got := header.Field(keyb); !bytes.Equal(got, valb) { 34 | t.Errorf("Want header value %q, got %q", val, string(got)) 35 | } 36 | if _, got := header.Index(i); !bytes.Equal(got, valb) { 37 | t.Errorf("Want header value %q, got %q", val, string(got)) 38 | } 39 | } 40 | 41 | // verify header behavior when key does not exist 42 | if got := header.Get([]byte("foo")); len(got) != 0 { 43 | t.Errorf("Expect empty slice when key does not exist") 44 | } 45 | 46 | header.reset() 47 | // verify the values are all reset properly. 48 | if header.itemc != 0 { 49 | t.Errorf("Want the header count reset to zero, got %d", header.itemc) 50 | } 51 | if got := len(header.items); got != defaultHeaderLen { 52 | t.Errorf("Want the reset items len %v, got %d", defaultHeaderLen, got) 53 | } 54 | for i := 0; i < defaultHeaderLen; i++ { 55 | if len(header.items[i].name) != 0 { 56 | t.Errorf("Want header.items[%d].name reset to the zero value", i) 57 | } 58 | if len(header.items[i].data) != 0 { 59 | t.Errorf("Want header.items[%d].value reset to the zero value", i) 60 | } 61 | } 62 | 63 | header.Add([]byte("test-true"), []byte("true")) 64 | header.Add([]byte("test-false"), []byte("false")) 65 | if got := header.GetBool("test-true"); !got { 66 | t.Errorf("Expect header.GetBool parses the boolean value true") 67 | } 68 | if got := header.GetBool("test-false"); got { 69 | t.Errorf("Expect header.GetBool parses the boolean value false") 70 | } 71 | 72 | header.Add([]byte("test-int"), []byte("123")) 73 | if got := header.GetInt64("test-int"); got != 123 { 74 | t.Errorf("Expect header.GetBool parses the boolean value true") 75 | } 76 | if got := header.GetInt("test-int"); got != 123 { 77 | t.Errorf("Expect header.GetBool parses the boolean value false") 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /vendor/github.com/dchest/uniuri/uniuri.go: -------------------------------------------------------------------------------- 1 | // Written in 2011-2014 by Dmitry Chestnykh 2 | // 3 | // The author(s) have dedicated all copyright and related and 4 | // neighboring rights to this software to the public domain 5 | // worldwide. Distributed without any warranty. 6 | // http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | // Package uniuri generates random strings good for use in URIs to identify 9 | // unique objects. 10 | // 11 | // Example usage: 12 | // 13 | // s := uniuri.New() // s is now "apHCJBl7L1OmC57n" 14 | // 15 | // A standard string created by New() is 16 bytes in length and consists of 16 | // Latin upper and lowercase letters, and numbers (from the set of 62 allowed 17 | // characters), which means that it has ~95 bits of entropy. To get more 18 | // entropy, you can use NewLen(UUIDLen), which returns 20-byte string, giving 19 | // ~119 bits of entropy, or any other desired length. 20 | // 21 | // Functions read from crypto/rand random source, and panic if they fail to 22 | // read from it. 23 | package uniuri 24 | 25 | import "crypto/rand" 26 | 27 | const ( 28 | // StdLen is a standard length of uniuri string to achive ~95 bits of entropy. 29 | StdLen = 16 30 | // UUIDLen is a length of uniuri string to achive ~119 bits of entropy, closest 31 | // to what can be losslessly converted to UUIDv4 (122 bits). 32 | UUIDLen = 20 33 | ) 34 | 35 | // StdChars is a set of standard characters allowed in uniuri string. 36 | var StdChars = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") 37 | 38 | // New returns a new random string of the standard length, consisting of 39 | // standard characters. 40 | func New() string { 41 | return NewLenChars(StdLen, StdChars) 42 | } 43 | 44 | // NewLen returns a new random string of the provided length, consisting of 45 | // standard characters. 46 | func NewLen(length int) string { 47 | return NewLenChars(length, StdChars) 48 | } 49 | 50 | // NewLenChars returns a new random string of the provided length, consisting 51 | // of the provided byte slice of allowed characters (maximum 256). 52 | func NewLenChars(length int, chars []byte) string { 53 | if length == 0 { 54 | return "" 55 | } 56 | clen := len(chars) 57 | if clen < 2 || clen > 256 { 58 | panic("uniuri: wrong charset length for NewLenChars") 59 | } 60 | maxrb := 255 - (256 % clen) 61 | b := make([]byte, length) 62 | r := make([]byte, length+(length/4)) // storage for random bytes. 63 | i := 0 64 | for { 65 | if _, err := rand.Read(r); err != nil { 66 | panic("uniuri: error reading random bytes: " + err.Error()) 67 | } 68 | for _, rb := range r { 69 | c := int(rb) 70 | if c > maxrb { 71 | // Skip this number to avoid modulo bias. 72 | continue 73 | } 74 | b[i] = chars[c%clen] 75 | i++ 76 | if i == length { 77 | return string(b) 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /stomp/selector/parse/node.go: -------------------------------------------------------------------------------- 1 | package parse 2 | 3 | // Node is an element in the parse tree. 4 | type Node interface { 5 | node() 6 | } 7 | 8 | // ValExpr defines a value expression. 9 | type ValExpr interface { 10 | Node 11 | value() 12 | } 13 | 14 | // BoolExpr defines a boolean expression. 15 | type BoolExpr interface { 16 | Node 17 | bool() 18 | } 19 | 20 | // An expression is represented by a tree consisting of one 21 | // or more of the following concrete expression nodes. 22 | // 23 | type ( 24 | // ComparisonExpr represents a two-value comparison expression. 25 | ComparisonExpr struct { 26 | Operator Operator 27 | Left, Right ValExpr 28 | } 29 | 30 | // AndExpr represents an AND expression. 31 | AndExpr struct { 32 | Left, Right BoolExpr 33 | } 34 | 35 | // OrExpr represents an OR expression. 36 | OrExpr struct { 37 | Left, Right BoolExpr 38 | } 39 | 40 | // NotExpr represents a NOT expression. 41 | NotExpr struct { 42 | Expr BoolExpr 43 | } 44 | 45 | // ParenBoolExpr represents a parenthesized boolean expression. 46 | ParenBoolExpr struct { 47 | Expr BoolExpr 48 | } 49 | 50 | // BasicLit represents a basic literal. 51 | BasicLit struct { 52 | Kind Literal // INT, REAL, TEXT 53 | Value []byte 54 | } 55 | 56 | // ArrayLit represents an array literal. 57 | ArrayLit struct { 58 | Values []ValExpr 59 | } 60 | 61 | // Field represents a value lookup by name. 62 | Field struct { 63 | Name []byte 64 | } 65 | ) 66 | 67 | // Operator identifies the type of operator. 68 | type Operator int 69 | 70 | // Comparison operators. 71 | const ( 72 | OperatorEq Operator = iota 73 | OperatorLt 74 | OperatorLte 75 | OperatorGt 76 | OperatorGte 77 | OperatorNeq 78 | OperatorIn 79 | OperatorRe 80 | OperatorGlob 81 | OperatorNotIn 82 | OperatorNotRe 83 | OperatorNotGlob 84 | ) 85 | 86 | // Literal identifies the type of literal. 87 | type Literal int 88 | 89 | // The list of possible literal kinds. 90 | const ( 91 | LiteralBool Literal = iota 92 | LiteralInt 93 | LiteralReal 94 | LiteralText 95 | ) 96 | 97 | // node() defines the node in a parse tree 98 | func (x *ComparisonExpr) node() {} 99 | func (x *AndExpr) node() {} 100 | func (x *OrExpr) node() {} 101 | func (x *NotExpr) node() {} 102 | func (x *ParenBoolExpr) node() {} 103 | func (x *BasicLit) node() {} 104 | func (x *ArrayLit) node() {} 105 | func (x *Field) node() {} 106 | 107 | // bool() defines the node as a boolean expression. 108 | func (x *ComparisonExpr) bool() {} 109 | func (x *AndExpr) bool() {} 110 | func (x *OrExpr) bool() {} 111 | func (x *NotExpr) bool() {} 112 | func (x *ParenBoolExpr) bool() {} 113 | 114 | // value() defines the node as a value expression. 115 | func (x *BasicLit) value() {} 116 | func (x *ArrayLit) value() {} 117 | func (x *Field) value() {} 118 | -------------------------------------------------------------------------------- /server/router_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | 7 | "github.com/drone/mq/stomp" 8 | ) 9 | 10 | func TestAck(t *testing.T) { 11 | client, server := stomp.Pipe() 12 | 13 | // this message will subscribe to a queue with 14 | // client acknowledgements enabled. 15 | sub := stomp.NewMessage() 16 | sub.Dest = []byte("/queue/test") 17 | sub.Ack = stomp.AckClient 18 | sess := requestSession() 19 | sess.peer = server 20 | 21 | msg := stomp.NewMessage() 22 | msg.Dest = []byte("/queue/test") 23 | msg.Body = []byte("bonjour") 24 | 25 | router := newRouter() 26 | router.subscribe(sess, sub) 27 | router.publish(msg) 28 | 29 | got := <-client.Receive() 30 | if !bytes.Equal(msg.Body, got.Body) { 31 | t.Errorf("Expect message received by subscriber") 32 | } 33 | if _, ok := sess.ack[string(got.Ack)]; !ok { 34 | t.Errorf("Expect message ack pending for subscriber") 35 | } 36 | ack := stomp.NewMessage() 37 | ack.ID = got.Ack 38 | router.ack(sess, ack) 39 | if _, ok := sess.ack[string(got.Ack)]; ok { 40 | t.Errorf("Expect message ack processed") 41 | } 42 | } 43 | 44 | func TestAckDisconnect(t *testing.T) { 45 | client, server := stomp.Pipe() 46 | 47 | // this message will subscribe to a queue with 48 | // client acknowledgements enabled. 49 | sub := stomp.NewMessage() 50 | sub.Dest = []byte("/queue/test") 51 | sub.Ack = stomp.AckClient 52 | sess := requestSession() 53 | sess.peer = server 54 | 55 | msg := stomp.NewMessage() 56 | msg.Dest = []byte("/queue/test") 57 | msg.Body = []byte("bonjour!") 58 | 59 | router := newRouter() 60 | router.publish(msg) 61 | 62 | queue := router.destinations["/queue/test"].(*queue) 63 | // verify the queue has a single item 64 | if got := queue.list.Len(); got != 1 { 65 | t.Errorf("Expect queue has 1 message enqueued. Got %d", got) 66 | } 67 | 68 | router.subscribe(sess, sub) 69 | // verify the queue has 1 subscriber 70 | if got := len(queue.subs); got != 1 { 71 | t.Errorf("Expect queue has 1 subscriber. Got %d", got) 72 | } 73 | 74 | got := <-client.Receive() 75 | if !bytes.Equal(msg.Body, got.Body) { 76 | t.Errorf("Expect message received by subscriber") 77 | } 78 | if got := len(sess.ack); got != 1 { 79 | t.Errorf("Expect message ack count 1, got %d", got) 80 | } 81 | if _, ok := sess.ack[string(got.Ack)]; !ok { 82 | t.Errorf("Expect message ack pending for subscriber") 83 | } 84 | 85 | // verify the queue is empty after popping the item 86 | if got := queue.list.Len(); got != 0 { 87 | t.Errorf("Expect message received and queue empty. Got %d", got) 88 | } 89 | 90 | router.disconnect(sess) 91 | if got := len(sess.ack); got != 0 { 92 | t.Errorf("Expect message ack removed. %d pending acks", got) 93 | } 94 | 95 | // the queue should have the message re-added 96 | if queue.list.Len() == 1 { 97 | t.Errorf("Expect message re-added to the queue") 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/db_util.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | package leveldb 8 | 9 | import ( 10 | "github.com/syndtr/goleveldb/leveldb/errors" 11 | "github.com/syndtr/goleveldb/leveldb/iterator" 12 | "github.com/syndtr/goleveldb/leveldb/opt" 13 | "github.com/syndtr/goleveldb/leveldb/storage" 14 | "github.com/syndtr/goleveldb/leveldb/util" 15 | ) 16 | 17 | // Reader is the interface that wraps basic Get and NewIterator methods. 18 | // This interface implemented by both DB and Snapshot. 19 | type Reader interface { 20 | Get(key []byte, ro *opt.ReadOptions) (value []byte, err error) 21 | NewIterator(slice *util.Range, ro *opt.ReadOptions) iterator.Iterator 22 | } 23 | 24 | // Sizes is list of size. 25 | type Sizes []int64 26 | 27 | // Sum returns sum of the sizes. 28 | func (sizes Sizes) Sum() int64 { 29 | var sum int64 30 | for _, size := range sizes { 31 | sum += size 32 | } 33 | return sum 34 | } 35 | 36 | // Logging. 37 | func (db *DB) log(v ...interface{}) { db.s.log(v...) } 38 | func (db *DB) logf(format string, v ...interface{}) { db.s.logf(format, v...) } 39 | 40 | // Check and clean files. 41 | func (db *DB) checkAndCleanFiles() error { 42 | v := db.s.version() 43 | defer v.release() 44 | 45 | tmap := make(map[int64]bool) 46 | for _, tables := range v.levels { 47 | for _, t := range tables { 48 | tmap[t.fd.Num] = false 49 | } 50 | } 51 | 52 | fds, err := db.s.stor.List(storage.TypeAll) 53 | if err != nil { 54 | return err 55 | } 56 | 57 | var nt int 58 | var rem []storage.FileDesc 59 | for _, fd := range fds { 60 | keep := true 61 | switch fd.Type { 62 | case storage.TypeManifest: 63 | keep = fd.Num >= db.s.manifestFd.Num 64 | case storage.TypeJournal: 65 | if !db.frozenJournalFd.Nil() { 66 | keep = fd.Num >= db.frozenJournalFd.Num 67 | } else { 68 | keep = fd.Num >= db.journalFd.Num 69 | } 70 | case storage.TypeTable: 71 | _, keep = tmap[fd.Num] 72 | if keep { 73 | tmap[fd.Num] = true 74 | nt++ 75 | } 76 | } 77 | 78 | if !keep { 79 | rem = append(rem, fd) 80 | } 81 | } 82 | 83 | if nt != len(tmap) { 84 | var mfds []storage.FileDesc 85 | for num, present := range tmap { 86 | if !present { 87 | mfds = append(mfds, storage.FileDesc{storage.TypeTable, num}) 88 | db.logf("db@janitor table missing @%d", num) 89 | } 90 | } 91 | return errors.NewErrCorrupted(storage.FileDesc{}, &errors.ErrMissingFiles{Fds: mfds}) 92 | } 93 | 94 | db.logf("db@janitor F·%d G·%d", len(fds), len(rem)) 95 | for _, fd := range rem { 96 | db.logf("db@janitor removing %s-%d", fd.Type, fd.Num) 97 | if err := db.s.stor.Remove(fd); err != nil { 98 | return err 99 | } 100 | } 101 | return nil 102 | } 103 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/websocket/client.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "bufio" 9 | "io" 10 | "net" 11 | "net/http" 12 | "net/url" 13 | ) 14 | 15 | // DialError is an error that occurs while dialling a websocket server. 16 | type DialError struct { 17 | *Config 18 | Err error 19 | } 20 | 21 | func (e *DialError) Error() string { 22 | return "websocket.Dial " + e.Config.Location.String() + ": " + e.Err.Error() 23 | } 24 | 25 | // NewConfig creates a new WebSocket config for client connection. 26 | func NewConfig(server, origin string) (config *Config, err error) { 27 | config = new(Config) 28 | config.Version = ProtocolVersionHybi13 29 | config.Location, err = url.ParseRequestURI(server) 30 | if err != nil { 31 | return 32 | } 33 | config.Origin, err = url.ParseRequestURI(origin) 34 | if err != nil { 35 | return 36 | } 37 | config.Header = http.Header(make(map[string][]string)) 38 | return 39 | } 40 | 41 | // NewClient creates a new WebSocket client connection over rwc. 42 | func NewClient(config *Config, rwc io.ReadWriteCloser) (ws *Conn, err error) { 43 | br := bufio.NewReader(rwc) 44 | bw := bufio.NewWriter(rwc) 45 | err = hybiClientHandshake(config, br, bw) 46 | if err != nil { 47 | return 48 | } 49 | buf := bufio.NewReadWriter(br, bw) 50 | ws = newHybiClientConn(config, buf, rwc) 51 | return 52 | } 53 | 54 | // Dial opens a new client connection to a WebSocket. 55 | func Dial(url_, protocol, origin string) (ws *Conn, err error) { 56 | config, err := NewConfig(url_, origin) 57 | if err != nil { 58 | return nil, err 59 | } 60 | if protocol != "" { 61 | config.Protocol = []string{protocol} 62 | } 63 | return DialConfig(config) 64 | } 65 | 66 | var portMap = map[string]string{ 67 | "ws": "80", 68 | "wss": "443", 69 | } 70 | 71 | func parseAuthority(location *url.URL) string { 72 | if _, ok := portMap[location.Scheme]; ok { 73 | if _, _, err := net.SplitHostPort(location.Host); err != nil { 74 | return net.JoinHostPort(location.Host, portMap[location.Scheme]) 75 | } 76 | } 77 | return location.Host 78 | } 79 | 80 | // DialConfig opens a new client connection to a WebSocket with a config. 81 | func DialConfig(config *Config) (ws *Conn, err error) { 82 | var client net.Conn 83 | if config.Location == nil { 84 | return nil, &DialError{config, ErrBadWebSocketLocation} 85 | } 86 | if config.Origin == nil { 87 | return nil, &DialError{config, ErrBadWebSocketOrigin} 88 | } 89 | dialer := config.Dialer 90 | if dialer == nil { 91 | dialer = &net.Dialer{} 92 | } 93 | client, err = dialWithDialer(dialer, config) 94 | if err != nil { 95 | goto Error 96 | } 97 | ws, err = NewClient(config, client) 98 | if err != nil { 99 | client.Close() 100 | goto Error 101 | } 102 | return 103 | 104 | Error: 105 | return nil, &DialError{config, err} 106 | } 107 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/context/go17.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.7 6 | 7 | package context 8 | 9 | import ( 10 | "context" // standard library's context, as of Go 1.7 11 | "time" 12 | ) 13 | 14 | var ( 15 | todo = context.TODO() 16 | background = context.Background() 17 | ) 18 | 19 | // Canceled is the error returned by Context.Err when the context is canceled. 20 | var Canceled = context.Canceled 21 | 22 | // DeadlineExceeded is the error returned by Context.Err when the context's 23 | // deadline passes. 24 | var DeadlineExceeded = context.DeadlineExceeded 25 | 26 | // WithCancel returns a copy of parent with a new Done channel. The returned 27 | // context's Done channel is closed when the returned cancel function is called 28 | // or when the parent context's Done channel is closed, whichever happens first. 29 | // 30 | // Canceling this context releases resources associated with it, so code should 31 | // call cancel as soon as the operations running in this Context complete. 32 | func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { 33 | ctx, f := context.WithCancel(parent) 34 | return ctx, CancelFunc(f) 35 | } 36 | 37 | // WithDeadline returns a copy of the parent context with the deadline adjusted 38 | // to be no later than d. If the parent's deadline is already earlier than d, 39 | // WithDeadline(parent, d) is semantically equivalent to parent. The returned 40 | // context's Done channel is closed when the deadline expires, when the returned 41 | // cancel function is called, or when the parent context's Done channel is 42 | // closed, whichever happens first. 43 | // 44 | // Canceling this context releases resources associated with it, so code should 45 | // call cancel as soon as the operations running in this Context complete. 46 | func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { 47 | ctx, f := context.WithDeadline(parent, deadline) 48 | return ctx, CancelFunc(f) 49 | } 50 | 51 | // WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). 52 | // 53 | // Canceling this context releases resources associated with it, so code should 54 | // call cancel as soon as the operations running in this Context complete: 55 | // 56 | // func slowOperationWithTimeout(ctx context.Context) (Result, error) { 57 | // ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) 58 | // defer cancel() // releases resources if slowOperation completes before timeout elapses 59 | // return slowOperation(ctx) 60 | // } 61 | func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { 62 | return WithDeadline(parent, time.Now().Add(timeout)) 63 | } 64 | 65 | // WithValue returns a copy of parent in which the value associated with key is 66 | // val. 67 | // 68 | // Use context Values only for request-scoped data that transits processes and 69 | // APIs, not for passing optional parameters to functions. 70 | func WithValue(parent Context, key interface{}, val interface{}) Context { 71 | return context.WithValue(parent, key, val) 72 | } 73 | -------------------------------------------------------------------------------- /stomp/reader.go: -------------------------------------------------------------------------------- 1 | package stomp 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | ) 7 | 8 | func read(input []byte, m *Message) (err error) { 9 | var ( 10 | pos int 11 | off int 12 | tot = len(input) 13 | ) 14 | 15 | // parse the stomp message 16 | for ; ; off++ { 17 | if off == tot { 18 | return fmt.Errorf("stomp: invalid method") 19 | } 20 | if input[off] == '\n' { 21 | m.Method = input[pos:off] 22 | off++ 23 | pos = off 24 | break 25 | } 26 | } 27 | 28 | // parse the stomp headers 29 | for { 30 | if off == tot { 31 | return fmt.Errorf("stomp: unexpected eof") 32 | } 33 | if input[off] == '\n' { 34 | off++ 35 | pos = off 36 | break 37 | } 38 | 39 | var ( 40 | name []byte 41 | value []byte 42 | ) 43 | 44 | loop: 45 | // parse each individual header 46 | for ; ; off++ { 47 | if off >= tot { 48 | return fmt.Errorf("stomp: unexpected eof") 49 | } 50 | 51 | switch input[off] { 52 | case '\n': 53 | value = input[pos:off] 54 | off++ 55 | pos = off 56 | break loop 57 | case ':': 58 | name = input[pos:off] 59 | off++ 60 | pos = off 61 | } 62 | } 63 | 64 | switch { 65 | case bytes.Equal(name, HeaderAccept): 66 | m.Proto = value 67 | case bytes.Equal(name, HeaderAck): 68 | m.Ack = value 69 | case bytes.Equal(name, HeaderDest): 70 | m.Dest = value 71 | case bytes.Equal(name, HeaderExpires): 72 | m.Expires = value 73 | case bytes.Equal(name, HeaderLogin): 74 | m.User = value 75 | case bytes.Equal(name, HeaderPass): 76 | m.Pass = value 77 | case bytes.Equal(name, HeaderID): 78 | m.ID = value 79 | case bytes.Equal(name, HeaderMessageID): 80 | m.ID = value 81 | case bytes.Equal(name, HeaderPersist): 82 | m.Persist = value 83 | case bytes.Equal(name, HeaderPrefetch): 84 | m.Prefetch = value 85 | case bytes.Equal(name, HeaderReceipt): 86 | m.Receipt = value 87 | case bytes.Equal(name, HeaderReceiptID): 88 | m.Receipt = value 89 | case bytes.Equal(name, HeaderRetain): 90 | m.Retain = value 91 | case bytes.Equal(name, HeaderSelector): 92 | m.Selector = value 93 | case bytes.Equal(name, HeaderSubscription): 94 | m.Subs = value 95 | case bytes.Equal(name, HeaderVersion): 96 | m.Proto = value 97 | default: 98 | m.Header.Add(name, value) 99 | } 100 | } 101 | 102 | if tot > pos { 103 | m.Body = input[pos:] 104 | } 105 | return 106 | } 107 | 108 | const ( 109 | asciiZero = 48 110 | asciiNine = 57 111 | ) 112 | 113 | // ParseInt returns the ascii integer value. 114 | func ParseInt(d []byte) (n int) { 115 | if len(d) == 0 { 116 | return 0 117 | } 118 | for _, dec := range d { 119 | if dec < asciiZero || dec > asciiNine { 120 | return 0 121 | } 122 | n = n*10 + (int(dec) - asciiZero) 123 | } 124 | return n 125 | } 126 | 127 | // ParseInt64 returns the ascii integer value. 128 | func ParseInt64(d []byte) (n int64) { 129 | if len(d) == 0 { 130 | return 0 131 | } 132 | for _, dec := range d { 133 | if dec < asciiZero || dec > asciiNine { 134 | return 0 135 | } 136 | n = n*10 + (int64(dec) - asciiZero) 137 | } 138 | return n 139 | } 140 | -------------------------------------------------------------------------------- /vendor/github.com/urfave/cli/runtests: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from __future__ import print_function 3 | 4 | import argparse 5 | import os 6 | import sys 7 | import tempfile 8 | 9 | from subprocess import check_call, check_output 10 | 11 | 12 | PACKAGE_NAME = os.environ.get( 13 | 'CLI_PACKAGE_NAME', 'github.com/urfave/cli' 14 | ) 15 | 16 | 17 | def main(sysargs=sys.argv[:]): 18 | targets = { 19 | 'vet': _vet, 20 | 'test': _test, 21 | 'gfmrun': _gfmrun, 22 | 'toc': _toc, 23 | 'gen': _gen, 24 | } 25 | 26 | parser = argparse.ArgumentParser() 27 | parser.add_argument( 28 | 'target', nargs='?', choices=tuple(targets.keys()), default='test' 29 | ) 30 | args = parser.parse_args(sysargs[1:]) 31 | 32 | targets[args.target]() 33 | return 0 34 | 35 | 36 | def _test(): 37 | if check_output('go version'.split()).split()[2] < 'go1.2': 38 | _run('go test -v .') 39 | return 40 | 41 | coverprofiles = [] 42 | for subpackage in ['', 'altsrc']: 43 | coverprofile = 'cli.coverprofile' 44 | if subpackage != '': 45 | coverprofile = '{}.coverprofile'.format(subpackage) 46 | 47 | coverprofiles.append(coverprofile) 48 | 49 | _run('go test -v'.split() + [ 50 | '-coverprofile={}'.format(coverprofile), 51 | ('{}/{}'.format(PACKAGE_NAME, subpackage)).rstrip('/') 52 | ]) 53 | 54 | combined_name = _combine_coverprofiles(coverprofiles) 55 | _run('go tool cover -func={}'.format(combined_name)) 56 | os.remove(combined_name) 57 | 58 | 59 | def _gfmrun(): 60 | _run(['gfmrun', '-c', str(_gfmrun_count()), '-s', 'README.md']) 61 | 62 | 63 | def _vet(): 64 | _run('go vet ./...') 65 | 66 | 67 | def _toc(): 68 | _run('node_modules/.bin/markdown-toc -i README.md') 69 | _run('git diff --exit-code') 70 | 71 | 72 | def _gen(): 73 | go_version = check_output('go version'.split()).split()[2] 74 | if go_version < 'go1.4': 75 | print('runtests: skip on {}'.format(go_version), file=sys.stderr) 76 | return 77 | 78 | _run('go generate ./...') 79 | _run('git diff --exit-code') 80 | 81 | 82 | def _run(command): 83 | if hasattr(command, 'split'): 84 | command = command.split() 85 | print('runtests: {}'.format(' '.join(command)), file=sys.stderr) 86 | check_call(command) 87 | 88 | 89 | def _gfmrun_count(): 90 | with open('README.md') as infile: 91 | lines = infile.read().splitlines() 92 | return len(filter(_is_go_runnable, lines)) 93 | 94 | 95 | def _is_go_runnable(line): 96 | return line.startswith('package main') 97 | 98 | 99 | def _combine_coverprofiles(coverprofiles): 100 | combined = tempfile.NamedTemporaryFile( 101 | suffix='.coverprofile', delete=False 102 | ) 103 | combined.write('mode: set\n') 104 | 105 | for coverprofile in coverprofiles: 106 | with open(coverprofile, 'r') as infile: 107 | for line in infile.readlines(): 108 | if not line.startswith('mode: '): 109 | combined.write(line) 110 | 111 | combined.flush() 112 | name = combined.name 113 | combined.close() 114 | return name 115 | 116 | 117 | if __name__ == '__main__': 118 | sys.exit(main()) 119 | -------------------------------------------------------------------------------- /server/topic.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "bytes" 5 | "sync" 6 | 7 | "github.com/drone/mq/stomp" 8 | ) 9 | 10 | // topic is a type of destination handler that implements a 11 | // publish subscribe pattern. Subscribers to a topic receive 12 | // all messages from the publisher. 13 | type topic struct { 14 | sync.RWMutex 15 | 16 | dest []byte 17 | hist []*stomp.Message 18 | subs map[*subscription]struct{} 19 | } 20 | 21 | func newTopic(dest []byte) *topic { 22 | return &topic{ 23 | dest: dest, 24 | subs: make(map[*subscription]struct{}), 25 | } 26 | } 27 | 28 | // publishes a copy of the message to the subsciber list. 29 | // If the message includes the retain:true headers the message is 30 | // saved for future use. If the message includes retain:remove the 31 | // previously retained message is set to nil. 32 | func (t *topic) publish(m *stomp.Message) error { 33 | id := stomp.Rand() 34 | 35 | t.RLock() 36 | for sub := range t.subs { 37 | if sub.selector != nil { 38 | if ok, _ := sub.selector.Eval(m.Header); !ok { 39 | continue 40 | } 41 | } 42 | c := m.Copy() 43 | c.ID = id 44 | c.Method = stomp.MethodMessage 45 | c.Subs = sub.id 46 | sub.session.send(c) 47 | } 48 | t.RUnlock() 49 | 50 | // if a message has the retain header set we should either 51 | // retain the message, or remove the existing retained message. 52 | if len(m.Retain) != 0 { 53 | c := m.Copy() 54 | 55 | t.Lock() 56 | switch { 57 | case bytes.Equal(m.Retain, stomp.RetainLast): 58 | if len(t.hist) == 1 { 59 | t.hist[0] = c 60 | } else { 61 | t.hist = t.hist[:0] 62 | t.hist = append(t.hist, c) 63 | } 64 | case bytes.Equal(m.Retain, stomp.RetainAll): 65 | t.hist = append(t.hist, c) 66 | case bytes.Equal(m.Retain, stomp.RetainRemove): 67 | t.hist = t.hist[:0] 68 | } 69 | t.Unlock() 70 | } 71 | 72 | return nil 73 | } 74 | 75 | // registers the subscription with the topic broker and 76 | // sends the last retained message, if one exists. 77 | func (t *topic) subscribe(s *subscription, m *stomp.Message) error { 78 | t.Lock() 79 | t.subs[s] = struct{}{} 80 | t.Unlock() 81 | 82 | t.RLock() 83 | hist := make([]*stomp.Message, len(t.hist)) 84 | copy(hist, t.hist) 85 | t.RUnlock() 86 | 87 | for _, m := range hist { 88 | c := m.Copy() 89 | c.Method = stomp.MethodMessage 90 | c.Subs = s.id 91 | c.ID = stomp.Rand() 92 | s.session.send(c) 93 | } 94 | 95 | return nil 96 | } 97 | 98 | func (t *topic) unsubscribe(s *subscription, m *stomp.Message) error { 99 | t.Lock() 100 | delete(t.subs, s) 101 | t.Unlock() 102 | return nil 103 | } 104 | 105 | func (t *topic) disconnect(s *session) error { 106 | t.Lock() 107 | for _, subscription := range s.sub { 108 | delete(t.subs, subscription) 109 | } 110 | t.Unlock() 111 | return nil 112 | } 113 | 114 | func (t *topic) process() error { 115 | return nil 116 | } 117 | 118 | func (t *topic) restore(m *stomp.Message) error { 119 | return nil 120 | } 121 | 122 | // returns true if the topic has zero subscribers indicating 123 | // that it can be recycled. 124 | func (t *topic) recycle() (ok bool) { 125 | t.RLock() 126 | ok = len(t.subs) == 0 && len(t.hist) == 0 127 | t.RUnlock() 128 | return 129 | } 130 | 131 | // return the destination name. 132 | func (t *topic) destination() string { 133 | return string(t.dest) 134 | } 135 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/options.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | package leveldb 8 | 9 | import ( 10 | "github.com/syndtr/goleveldb/leveldb/filter" 11 | "github.com/syndtr/goleveldb/leveldb/opt" 12 | ) 13 | 14 | func dupOptions(o *opt.Options) *opt.Options { 15 | newo := &opt.Options{} 16 | if o != nil { 17 | *newo = *o 18 | } 19 | if newo.Strict == 0 { 20 | newo.Strict = opt.DefaultStrict 21 | } 22 | return newo 23 | } 24 | 25 | func (s *session) setOptions(o *opt.Options) { 26 | no := dupOptions(o) 27 | // Alternative filters. 28 | if filters := o.GetAltFilters(); len(filters) > 0 { 29 | no.AltFilters = make([]filter.Filter, len(filters)) 30 | for i, filter := range filters { 31 | no.AltFilters[i] = &iFilter{filter} 32 | } 33 | } 34 | // Comparer. 35 | s.icmp = &iComparer{o.GetComparer()} 36 | no.Comparer = s.icmp 37 | // Filter. 38 | if filter := o.GetFilter(); filter != nil { 39 | no.Filter = &iFilter{filter} 40 | } 41 | 42 | s.o = &cachedOptions{Options: no} 43 | s.o.cache() 44 | } 45 | 46 | const optCachedLevel = 7 47 | 48 | type cachedOptions struct { 49 | *opt.Options 50 | 51 | compactionExpandLimit []int 52 | compactionGPOverlaps []int 53 | compactionSourceLimit []int 54 | compactionTableSize []int 55 | compactionTotalSize []int64 56 | } 57 | 58 | func (co *cachedOptions) cache() { 59 | co.compactionExpandLimit = make([]int, optCachedLevel) 60 | co.compactionGPOverlaps = make([]int, optCachedLevel) 61 | co.compactionSourceLimit = make([]int, optCachedLevel) 62 | co.compactionTableSize = make([]int, optCachedLevel) 63 | co.compactionTotalSize = make([]int64, optCachedLevel) 64 | 65 | for level := 0; level < optCachedLevel; level++ { 66 | co.compactionExpandLimit[level] = co.Options.GetCompactionExpandLimit(level) 67 | co.compactionGPOverlaps[level] = co.Options.GetCompactionGPOverlaps(level) 68 | co.compactionSourceLimit[level] = co.Options.GetCompactionSourceLimit(level) 69 | co.compactionTableSize[level] = co.Options.GetCompactionTableSize(level) 70 | co.compactionTotalSize[level] = co.Options.GetCompactionTotalSize(level) 71 | } 72 | } 73 | 74 | func (co *cachedOptions) GetCompactionExpandLimit(level int) int { 75 | if level < optCachedLevel { 76 | return co.compactionExpandLimit[level] 77 | } 78 | return co.Options.GetCompactionExpandLimit(level) 79 | } 80 | 81 | func (co *cachedOptions) GetCompactionGPOverlaps(level int) int { 82 | if level < optCachedLevel { 83 | return co.compactionGPOverlaps[level] 84 | } 85 | return co.Options.GetCompactionGPOverlaps(level) 86 | } 87 | 88 | func (co *cachedOptions) GetCompactionSourceLimit(level int) int { 89 | if level < optCachedLevel { 90 | return co.compactionSourceLimit[level] 91 | } 92 | return co.Options.GetCompactionSourceLimit(level) 93 | } 94 | 95 | func (co *cachedOptions) GetCompactionTableSize(level int) int { 96 | if level < optCachedLevel { 97 | return co.compactionTableSize[level] 98 | } 99 | return co.Options.GetCompactionTableSize(level) 100 | } 101 | 102 | func (co *cachedOptions) GetCompactionTotalSize(level int) int64 { 103 | if level < optCachedLevel { 104 | return co.compactionTotalSize[level] 105 | } 106 | return co.Options.GetCompactionTotalSize(level) 107 | } 108 | -------------------------------------------------------------------------------- /server/server.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "encoding/json" 5 | "net" 6 | "net/http" 7 | 8 | "github.com/drone/mq/logger" 9 | "github.com/drone/mq/stomp" 10 | 11 | "golang.org/x/net/websocket" 12 | ) 13 | 14 | // Server ... 15 | type Server struct { 16 | router *router 17 | } 18 | 19 | // NewServer returns a new STOMP server. 20 | func NewServer(options ...Option) *Server { 21 | server := &Server{ 22 | router: newRouter(), 23 | } 24 | for _, option := range options { 25 | option(server) 26 | } 27 | return server 28 | } 29 | 30 | // Serve accepts incoming net.Conn requests. 31 | func (s *Server) Serve(conn net.Conn) { 32 | logger.Verbosef("stomp: session opened.") 33 | 34 | session := requestSession() 35 | session.peer = stomp.Conn(conn) 36 | 37 | defer func() { 38 | if r := recover(); r != nil { 39 | logger.Warningf("stomp: server panic: %s", r) 40 | } 41 | 42 | s.router.disconnect(session) 43 | session.peer.Close() 44 | session.release() 45 | 46 | logger.Verbosef("stomp: session released.") 47 | }() 48 | 49 | err := s.router.serve(session) 50 | if err == nil { 51 | logger.Verbosef("stomp: session closed gracefully.") 52 | return 53 | } 54 | 55 | logger.Warningf("stomp: server error. %s", err) 56 | } 57 | 58 | // ServeHTTP accepts incoming http.Request, upgrades to a websocket and 59 | // begins sending and receiving STOMP messages. 60 | func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) { 61 | logger.Verbosef("stomp: handle websocket request.") 62 | websocket.Handler(func(conn *websocket.Conn) { 63 | s.Serve(conn) 64 | }).ServeHTTP(w, r) 65 | } 66 | 67 | // HandleSessions writes a JSON-encoded list of sessions to the http.Request. 68 | func (s *Server) HandleSessions(w http.ResponseWriter, r *http.Request) { 69 | type sessionResp struct { 70 | Addr string `json:"address"` 71 | User string `json:"username"` 72 | Headers map[string]string `json:"headers"` 73 | } 74 | 75 | var sessions []sessionResp 76 | s.router.RLock() 77 | for sess := range s.router.sessions { 78 | headers := map[string]string{} 79 | for i := 0; i < sess.msg.Header.Len(); i++ { 80 | k, v := sess.msg.Header.Index(i) 81 | headers[string(k)] = string(v) 82 | } 83 | sessions = append(sessions, sessionResp{ 84 | Addr: sess.peer.Addr(), 85 | User: string(sess.msg.User), 86 | Headers: headers, 87 | }) 88 | } 89 | s.router.RUnlock() 90 | 91 | json.NewEncoder(w).Encode(sessions) 92 | } 93 | 94 | // HandleDests writes a JSON-encoded list of destinations to the http.Request. 95 | func (s *Server) HandleDests(w http.ResponseWriter, r *http.Request) { 96 | type destionatResp struct { 97 | Dest string `json:"destination"` 98 | } 99 | 100 | var dests []destionatResp 101 | s.router.RLock() 102 | for dest := range s.router.destinations { 103 | d := destionatResp{ 104 | Dest: dest, 105 | } 106 | dests = append(dests, d) 107 | } 108 | s.router.RUnlock() 109 | 110 | json.NewEncoder(w).Encode(dests) 111 | } 112 | 113 | // Client returns a stomp.Client that has a direct peer connection 114 | // to the server. 115 | func (s *Server) Client() *stomp.Client { 116 | a, b := stomp.Pipe() 117 | 118 | go func() { 119 | session := requestSession() 120 | session.peer = b 121 | if err := s.router.serve(session); err != nil { 122 | logger.Warningf("stomp: server error. %s", err) 123 | } 124 | }() 125 | return stomp.New(a) 126 | } 127 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/filter/bloom.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | package filter 8 | 9 | import ( 10 | "github.com/syndtr/goleveldb/leveldb/util" 11 | ) 12 | 13 | func bloomHash(key []byte) uint32 { 14 | return util.Hash(key, 0xbc9f1d34) 15 | } 16 | 17 | type bloomFilter int 18 | 19 | // The bloom filter serializes its parameters and is backward compatible 20 | // with respect to them. Therefor, its parameters are not added to its 21 | // name. 22 | func (bloomFilter) Name() string { 23 | return "leveldb.BuiltinBloomFilter" 24 | } 25 | 26 | func (f bloomFilter) Contains(filter, key []byte) bool { 27 | nBytes := len(filter) - 1 28 | if nBytes < 1 { 29 | return false 30 | } 31 | nBits := uint32(nBytes * 8) 32 | 33 | // Use the encoded k so that we can read filters generated by 34 | // bloom filters created using different parameters. 35 | k := filter[nBytes] 36 | if k > 30 { 37 | // Reserved for potentially new encodings for short bloom filters. 38 | // Consider it a match. 39 | return true 40 | } 41 | 42 | kh := bloomHash(key) 43 | delta := (kh >> 17) | (kh << 15) // Rotate right 17 bits 44 | for j := uint8(0); j < k; j++ { 45 | bitpos := kh % nBits 46 | if (uint32(filter[bitpos/8]) & (1 << (bitpos % 8))) == 0 { 47 | return false 48 | } 49 | kh += delta 50 | } 51 | return true 52 | } 53 | 54 | func (f bloomFilter) NewGenerator() FilterGenerator { 55 | // Round down to reduce probing cost a little bit. 56 | k := uint8(f * 69 / 100) // 0.69 =~ ln(2) 57 | if k < 1 { 58 | k = 1 59 | } else if k > 30 { 60 | k = 30 61 | } 62 | return &bloomFilterGenerator{ 63 | n: int(f), 64 | k: k, 65 | } 66 | } 67 | 68 | type bloomFilterGenerator struct { 69 | n int 70 | k uint8 71 | 72 | keyHashes []uint32 73 | } 74 | 75 | func (g *bloomFilterGenerator) Add(key []byte) { 76 | // Use double-hashing to generate a sequence of hash values. 77 | // See analysis in [Kirsch,Mitzenmacher 2006]. 78 | g.keyHashes = append(g.keyHashes, bloomHash(key)) 79 | } 80 | 81 | func (g *bloomFilterGenerator) Generate(b Buffer) { 82 | // Compute bloom filter size (in both bits and bytes) 83 | nBits := uint32(len(g.keyHashes) * g.n) 84 | // For small n, we can see a very high false positive rate. Fix it 85 | // by enforcing a minimum bloom filter length. 86 | if nBits < 64 { 87 | nBits = 64 88 | } 89 | nBytes := (nBits + 7) / 8 90 | nBits = nBytes * 8 91 | 92 | dest := b.Alloc(int(nBytes) + 1) 93 | dest[nBytes] = g.k 94 | for _, kh := range g.keyHashes { 95 | delta := (kh >> 17) | (kh << 15) // Rotate right 17 bits 96 | for j := uint8(0); j < g.k; j++ { 97 | bitpos := kh % nBits 98 | dest[bitpos/8] |= (1 << (bitpos % 8)) 99 | kh += delta 100 | } 101 | } 102 | 103 | g.keyHashes = g.keyHashes[:0] 104 | } 105 | 106 | // NewBloomFilter creates a new initialized bloom filter for given 107 | // bitsPerKey. 108 | // 109 | // Since bitsPerKey is persisted individually for each bloom filter 110 | // serialization, bloom filters are backwards compatible with respect to 111 | // changing bitsPerKey. This means that no big performance penalty will 112 | // be experienced when changing the parameter. See documentation for 113 | // opt.Options.Filter for more information. 114 | func NewBloomFilter(bitsPerKey int) Filter { 115 | return bloomFilter(bitsPerKey) 116 | } 117 | -------------------------------------------------------------------------------- /server/queue.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "container/list" 5 | "math/rand" 6 | "sync" 7 | "time" 8 | 9 | "github.com/drone/mq/stomp" 10 | ) 11 | 12 | type queue struct { 13 | sync.RWMutex 14 | 15 | dest []byte 16 | subs map[*subscription]struct{} 17 | list *list.List 18 | } 19 | 20 | func newQueue(dest []byte) *queue { 21 | return &queue{ 22 | dest: dest, 23 | subs: make(map[*subscription]struct{}), 24 | list: list.New(), 25 | } 26 | } 27 | 28 | func (q *queue) publish(m *stomp.Message) error { 29 | c := m.Copy() 30 | c.ID = stomp.Rand() 31 | c.Method = stomp.MethodMessage 32 | q.Lock() 33 | q.list.PushBack(c) 34 | q.Unlock() 35 | return q.process() 36 | } 37 | 38 | func (q *queue) subscribe(s *subscription, m *stomp.Message) error { 39 | q.Lock() 40 | q.subs[s] = struct{}{} 41 | q.Unlock() 42 | return q.process() 43 | } 44 | 45 | func (q *queue) unsubscribe(s *subscription, m *stomp.Message) error { 46 | q.Lock() 47 | delete(q.subs, s) 48 | q.Unlock() 49 | return nil 50 | } 51 | 52 | func (q *queue) disconnect(s *session) error { 53 | q.Lock() 54 | for _, subscription := range s.sub { 55 | delete(q.subs, subscription) 56 | } 57 | q.Unlock() 58 | return nil 59 | } 60 | 61 | // returns true if the topic has zero subscribers indicating 62 | // that it can be recycled. 63 | func (q *queue) recycle() (ok bool) { 64 | q.RLock() 65 | ok = len(q.subs) == 0 && q.list.Len() == 0 66 | q.RUnlock() 67 | return 68 | } 69 | 70 | // return the destination name. 71 | func (q *queue) destination() string { 72 | return string(q.dest) 73 | } 74 | 75 | func (q *queue) restore(m *stomp.Message) error { 76 | q.Lock() 77 | q.list.PushFront(m) 78 | q.Unlock() 79 | return q.process() 80 | } 81 | 82 | func (q *queue) process() error { 83 | q.Lock() 84 | defer q.Unlock() 85 | 86 | var next *list.Element 87 | for e := q.list.Front(); e != nil; e = next { 88 | next = e.Next() 89 | m := e.Value.(*stomp.Message) 90 | 91 | // if the message expires we can remove it from the list 92 | if len(m.Expires) != 0 && stomp.ParseInt64(m.Expires) < time.Now().Unix() { 93 | q.list.Remove(e) 94 | continue 95 | } 96 | 97 | for _, sub := range shuffle(q.subs) { 98 | // evaluate against the sql selector 99 | if sub.selector != nil { 100 | if ok, _ := sub.selector.Eval(m.Header); !ok { 101 | continue 102 | } 103 | } 104 | 105 | if sub.prefetch != 0 && sub.prefetch == sub.Pending() { 106 | continue 107 | } 108 | // increment the pending prefectch 109 | if sub.prefetch != 0 { 110 | sub.PendingIncr() 111 | } 112 | if sub.ack { 113 | m.Subs = sub.id 114 | m.Ack = stomp.Rand() 115 | sub.session.Lock() 116 | sub.session.ack[string(m.Ack)] = m.Copy() 117 | sub.session.Unlock() 118 | } 119 | 120 | m.Subs = sub.id 121 | sub.session.send(m) 122 | q.list.Remove(e) 123 | return nil 124 | } 125 | } 126 | return nil 127 | } 128 | 129 | // helper function to randomize the list of subscribers in an attempt 130 | // to more evenly distribute messages in a round robin fashion. 131 | // 132 | // NOTE this is a basic implementation and we recognize there is plenty 133 | // of room for improvement here. 134 | func shuffle(subm map[*subscription]struct{}) []*subscription { 135 | var subs []*subscription 136 | for sub := range subm { 137 | subs = append(subs, sub) 138 | } 139 | for i := range subs { 140 | j := rand.Intn(i + 1) 141 | subs[i], subs[j] = subs[j], subs[i] 142 | } 143 | return subs 144 | } 145 | -------------------------------------------------------------------------------- /stomp/conn.go: -------------------------------------------------------------------------------- 1 | package stomp 2 | 3 | import ( 4 | "bufio" 5 | "io" 6 | "net" 7 | "time" 8 | 9 | "github.com/drone/mq/logger" 10 | ) 11 | 12 | const ( 13 | bufferSize = 32 << 10 // default buffer size 32KB 14 | bufferLimit = 32 << 15 // default buffer limit 1MB 15 | ) 16 | 17 | var ( 18 | never time.Time 19 | deadline = time.Second * 5 20 | 21 | heartbeatTime = time.Second * 30 22 | heartbeatWait = time.Second * 60 23 | ) 24 | 25 | type connPeer struct { 26 | conn net.Conn 27 | done chan bool 28 | 29 | reader *bufio.Reader 30 | writer *bufio.Writer 31 | incoming chan *Message 32 | outgoing chan *Message 33 | } 34 | 35 | // Conn creates a network-connected peer that reads and writes 36 | // messages using net.Conn c. 37 | func Conn(c net.Conn) Peer { 38 | p := &connPeer{ 39 | reader: bufio.NewReaderSize(c, bufferSize), 40 | writer: bufio.NewWriterSize(c, bufferSize), 41 | incoming: make(chan *Message), 42 | outgoing: make(chan *Message), 43 | done: make(chan bool), 44 | conn: c, 45 | } 46 | 47 | go p.readInto(p.incoming) 48 | go p.writeFrom(p.outgoing) 49 | return p 50 | } 51 | 52 | func (c *connPeer) Receive() <-chan *Message { 53 | return c.incoming 54 | } 55 | 56 | func (c *connPeer) Send(message *Message) error { 57 | select { 58 | case <-c.done: 59 | return io.EOF 60 | default: 61 | c.outgoing <- message 62 | return nil 63 | } 64 | } 65 | 66 | func (c *connPeer) Addr() string { 67 | return c.conn.RemoteAddr().String() 68 | } 69 | 70 | func (c *connPeer) Close() error { 71 | return c.close() 72 | } 73 | 74 | func (c *connPeer) close() error { 75 | select { 76 | case <-c.done: 77 | return io.EOF 78 | default: 79 | close(c.done) 80 | close(c.incoming) 81 | close(c.outgoing) 82 | return nil 83 | } 84 | } 85 | 86 | func (c *connPeer) readInto(messages chan<- *Message) { 87 | defer c.close() 88 | 89 | for { 90 | // lim := io.LimitReader(c.conn, bufferLimit) 91 | // buf := bufio.NewReaderSize(lim, bufferSize) 92 | 93 | buf, err := c.reader.ReadBytes(0) 94 | if err != nil { 95 | break 96 | } 97 | if len(buf) == 1 { 98 | c.conn.SetReadDeadline(time.Now().Add(heartbeatWait)) 99 | logger.Verbosef("stomp: received heart-beat") 100 | continue 101 | } 102 | 103 | msg := NewMessage() 104 | msg.Parse(buf[:len(buf)-1]) 105 | 106 | select { 107 | case <-c.done: 108 | break 109 | default: 110 | messages <- msg 111 | } 112 | } 113 | } 114 | 115 | func (c *connPeer) writeFrom(messages <-chan *Message) { 116 | tick := time.NewTicker(time.Millisecond * 100).C 117 | heartbeat := time.NewTicker(heartbeatTime).C 118 | 119 | loop: 120 | for { 121 | select { 122 | case <-c.done: 123 | break loop 124 | case <-heartbeat: 125 | logger.Verbosef("stomp: send heart-beat.") 126 | c.writer.WriteByte(0) 127 | case <-tick: 128 | c.conn.SetWriteDeadline(time.Now().Add(deadline)) 129 | if err := c.writer.Flush(); err != nil { 130 | break loop 131 | } 132 | c.conn.SetWriteDeadline(never) 133 | case msg, ok := <-messages: 134 | if !ok { 135 | break loop 136 | } 137 | writeTo(c.writer, msg) 138 | c.writer.WriteByte(0) 139 | msg.Release() 140 | } 141 | } 142 | 143 | c.drain() 144 | } 145 | 146 | func (c *connPeer) drain() error { 147 | c.conn.SetWriteDeadline(time.Now().Add(deadline)) 148 | for msg := range c.outgoing { 149 | writeTo(c.writer, msg) 150 | c.writer.WriteByte(0) 151 | msg.Release() 152 | } 153 | c.conn.SetWriteDeadline(never) 154 | c.writer.Flush() 155 | return c.conn.Close() 156 | } 157 | -------------------------------------------------------------------------------- /vendor/github.com/golang/snappy/decode_other.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Snappy-Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !amd64 appengine !gc noasm 6 | 7 | package snappy 8 | 9 | // decode writes the decoding of src to dst. It assumes that the varint-encoded 10 | // length of the decompressed bytes has already been read, and that len(dst) 11 | // equals that length. 12 | // 13 | // It returns 0 on success or a decodeErrCodeXxx error code on failure. 14 | func decode(dst, src []byte) int { 15 | var d, s, offset, length int 16 | for s < len(src) { 17 | switch src[s] & 0x03 { 18 | case tagLiteral: 19 | x := uint32(src[s] >> 2) 20 | switch { 21 | case x < 60: 22 | s++ 23 | case x == 60: 24 | s += 2 25 | if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. 26 | return decodeErrCodeCorrupt 27 | } 28 | x = uint32(src[s-1]) 29 | case x == 61: 30 | s += 3 31 | if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. 32 | return decodeErrCodeCorrupt 33 | } 34 | x = uint32(src[s-2]) | uint32(src[s-1])<<8 35 | case x == 62: 36 | s += 4 37 | if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. 38 | return decodeErrCodeCorrupt 39 | } 40 | x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16 41 | case x == 63: 42 | s += 5 43 | if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. 44 | return decodeErrCodeCorrupt 45 | } 46 | x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24 47 | } 48 | length = int(x) + 1 49 | if length <= 0 { 50 | return decodeErrCodeUnsupportedLiteralLength 51 | } 52 | if length > len(dst)-d || length > len(src)-s { 53 | return decodeErrCodeCorrupt 54 | } 55 | copy(dst[d:], src[s:s+length]) 56 | d += length 57 | s += length 58 | continue 59 | 60 | case tagCopy1: 61 | s += 2 62 | if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. 63 | return decodeErrCodeCorrupt 64 | } 65 | length = 4 + int(src[s-2])>>2&0x7 66 | offset = int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1])) 67 | 68 | case tagCopy2: 69 | s += 3 70 | if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. 71 | return decodeErrCodeCorrupt 72 | } 73 | length = 1 + int(src[s-3])>>2 74 | offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8) 75 | 76 | case tagCopy4: 77 | s += 5 78 | if uint(s) > uint(len(src)) { // The uint conversions catch overflow from the previous line. 79 | return decodeErrCodeCorrupt 80 | } 81 | length = 1 + int(src[s-5])>>2 82 | offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24) 83 | } 84 | 85 | if offset <= 0 || d < offset || length > len(dst)-d { 86 | return decodeErrCodeCorrupt 87 | } 88 | // Copy from an earlier sub-slice of dst to a later sub-slice. Unlike 89 | // the built-in copy function, this byte-by-byte copy always runs 90 | // forwards, even if the slices overlap. Conceptually, this is: 91 | // 92 | // d += forwardCopy(dst[d:d+length], dst[d-offset:]) 93 | for end := d + length; d != end; d++ { 94 | dst[d] = dst[d-offset] 95 | } 96 | } 97 | if d != len(dst) { 98 | return decodeErrCodeCorrupt 99 | } 100 | return 0 101 | } 102 | -------------------------------------------------------------------------------- /vendor/github.com/golang/snappy/snappy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 The Snappy-Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package snappy implements the snappy block-based compression format. 6 | // It aims for very high speeds and reasonable compression. 7 | // 8 | // The C++ snappy implementation is at https://github.com/google/snappy 9 | package snappy // import "github.com/golang/snappy" 10 | 11 | import ( 12 | "hash/crc32" 13 | ) 14 | 15 | /* 16 | Each encoded block begins with the varint-encoded length of the decoded data, 17 | followed by a sequence of chunks. Chunks begin and end on byte boundaries. The 18 | first byte of each chunk is broken into its 2 least and 6 most significant bits 19 | called l and m: l ranges in [0, 4) and m ranges in [0, 64). l is the chunk tag. 20 | Zero means a literal tag. All other values mean a copy tag. 21 | 22 | For literal tags: 23 | - If m < 60, the next 1 + m bytes are literal bytes. 24 | - Otherwise, let n be the little-endian unsigned integer denoted by the next 25 | m - 59 bytes. The next 1 + n bytes after that are literal bytes. 26 | 27 | For copy tags, length bytes are copied from offset bytes ago, in the style of 28 | Lempel-Ziv compression algorithms. In particular: 29 | - For l == 1, the offset ranges in [0, 1<<11) and the length in [4, 12). 30 | The length is 4 + the low 3 bits of m. The high 3 bits of m form bits 8-10 31 | of the offset. The next byte is bits 0-7 of the offset. 32 | - For l == 2, the offset ranges in [0, 1<<16) and the length in [1, 65). 33 | The length is 1 + m. The offset is the little-endian unsigned integer 34 | denoted by the next 2 bytes. 35 | - For l == 3, this tag is a legacy format that is no longer issued by most 36 | encoders. Nonetheless, the offset ranges in [0, 1<<32) and the length in 37 | [1, 65). The length is 1 + m. The offset is the little-endian unsigned 38 | integer denoted by the next 4 bytes. 39 | */ 40 | const ( 41 | tagLiteral = 0x00 42 | tagCopy1 = 0x01 43 | tagCopy2 = 0x02 44 | tagCopy4 = 0x03 45 | ) 46 | 47 | const ( 48 | checksumSize = 4 49 | chunkHeaderSize = 4 50 | magicChunk = "\xff\x06\x00\x00" + magicBody 51 | magicBody = "sNaPpY" 52 | 53 | // maxBlockSize is the maximum size of the input to encodeBlock. It is not 54 | // part of the wire format per se, but some parts of the encoder assume 55 | // that an offset fits into a uint16. 56 | // 57 | // Also, for the framing format (Writer type instead of Encode function), 58 | // https://github.com/google/snappy/blob/master/framing_format.txt says 59 | // that "the uncompressed data in a chunk must be no longer than 65536 60 | // bytes". 61 | maxBlockSize = 65536 62 | 63 | // maxEncodedLenOfMaxBlockSize equals MaxEncodedLen(maxBlockSize), but is 64 | // hard coded to be a const instead of a variable, so that obufLen can also 65 | // be a const. Their equivalence is confirmed by 66 | // TestMaxEncodedLenOfMaxBlockSize. 67 | maxEncodedLenOfMaxBlockSize = 76490 68 | 69 | obufHeaderLen = len(magicChunk) + checksumSize + chunkHeaderSize 70 | obufLen = obufHeaderLen + maxEncodedLenOfMaxBlockSize 71 | ) 72 | 73 | const ( 74 | chunkTypeCompressedData = 0x00 75 | chunkTypeUncompressedData = 0x01 76 | chunkTypePadding = 0xfe 77 | chunkTypeStreamIdentifier = 0xff 78 | ) 79 | 80 | var crcTable = crc32.MakeTable(crc32.Castagnoli) 81 | 82 | // crc implements the checksum specified in section 3 of 83 | // https://github.com/google/snappy/blob/master/framing_format.txt 84 | func crc(b []byte) uint32 { 85 | c := crc32.Update(0, crcTable, b) 86 | return uint32(c>>15|c<<17) + 0xa282ead8 87 | } 88 | -------------------------------------------------------------------------------- /vendor/github.com/kr/pretty/pretty.go: -------------------------------------------------------------------------------- 1 | // Package pretty provides pretty-printing for Go values. This is 2 | // useful during debugging, to avoid wrapping long output lines in 3 | // the terminal. 4 | // 5 | // It provides a function, Formatter, that can be used with any 6 | // function that accepts a format string. It also provides 7 | // convenience wrappers for functions in packages fmt and log. 8 | package pretty 9 | 10 | import ( 11 | "fmt" 12 | "io" 13 | "log" 14 | "reflect" 15 | ) 16 | 17 | // Errorf is a convenience wrapper for fmt.Errorf. 18 | // 19 | // Calling Errorf(f, x, y) is equivalent to 20 | // fmt.Errorf(f, Formatter(x), Formatter(y)). 21 | func Errorf(format string, a ...interface{}) error { 22 | return fmt.Errorf(format, wrap(a, false)...) 23 | } 24 | 25 | // Fprintf is a convenience wrapper for fmt.Fprintf. 26 | // 27 | // Calling Fprintf(w, f, x, y) is equivalent to 28 | // fmt.Fprintf(w, f, Formatter(x), Formatter(y)). 29 | func Fprintf(w io.Writer, format string, a ...interface{}) (n int, error error) { 30 | return fmt.Fprintf(w, format, wrap(a, false)...) 31 | } 32 | 33 | // Log is a convenience wrapper for log.Printf. 34 | // 35 | // Calling Log(x, y) is equivalent to 36 | // log.Print(Formatter(x), Formatter(y)), but each operand is 37 | // formatted with "%# v". 38 | func Log(a ...interface{}) { 39 | log.Print(wrap(a, true)...) 40 | } 41 | 42 | // Logf is a convenience wrapper for log.Printf. 43 | // 44 | // Calling Logf(f, x, y) is equivalent to 45 | // log.Printf(f, Formatter(x), Formatter(y)). 46 | func Logf(format string, a ...interface{}) { 47 | log.Printf(format, wrap(a, false)...) 48 | } 49 | 50 | // Logln is a convenience wrapper for log.Printf. 51 | // 52 | // Calling Logln(x, y) is equivalent to 53 | // log.Println(Formatter(x), Formatter(y)), but each operand is 54 | // formatted with "%# v". 55 | func Logln(a ...interface{}) { 56 | log.Println(wrap(a, true)...) 57 | } 58 | 59 | // Print pretty-prints its operands and writes to standard output. 60 | // 61 | // Calling Print(x, y) is equivalent to 62 | // fmt.Print(Formatter(x), Formatter(y)), but each operand is 63 | // formatted with "%# v". 64 | func Print(a ...interface{}) (n int, errno error) { 65 | return fmt.Print(wrap(a, true)...) 66 | } 67 | 68 | // Printf is a convenience wrapper for fmt.Printf. 69 | // 70 | // Calling Printf(f, x, y) is equivalent to 71 | // fmt.Printf(f, Formatter(x), Formatter(y)). 72 | func Printf(format string, a ...interface{}) (n int, errno error) { 73 | return fmt.Printf(format, wrap(a, false)...) 74 | } 75 | 76 | // Println pretty-prints its operands and writes to standard output. 77 | // 78 | // Calling Print(x, y) is equivalent to 79 | // fmt.Println(Formatter(x), Formatter(y)), but each operand is 80 | // formatted with "%# v". 81 | func Println(a ...interface{}) (n int, errno error) { 82 | return fmt.Println(wrap(a, true)...) 83 | } 84 | 85 | // Sprint is a convenience wrapper for fmt.Sprintf. 86 | // 87 | // Calling Sprint(x, y) is equivalent to 88 | // fmt.Sprint(Formatter(x), Formatter(y)), but each operand is 89 | // formatted with "%# v". 90 | func Sprint(a ...interface{}) string { 91 | return fmt.Sprint(wrap(a, true)...) 92 | } 93 | 94 | // Sprintf is a convenience wrapper for fmt.Sprintf. 95 | // 96 | // Calling Sprintf(f, x, y) is equivalent to 97 | // fmt.Sprintf(f, Formatter(x), Formatter(y)). 98 | func Sprintf(format string, a ...interface{}) string { 99 | return fmt.Sprintf(format, wrap(a, false)...) 100 | } 101 | 102 | func wrap(a []interface{}, force bool) []interface{} { 103 | w := make([]interface{}, len(a)) 104 | for i, x := range a { 105 | w[i] = formatter{v: reflect.ValueOf(x), force: force} 106 | } 107 | return w 108 | } 109 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/acme/autocert/renewal.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package autocert 6 | 7 | import ( 8 | "crypto" 9 | "sync" 10 | "time" 11 | 12 | "golang.org/x/net/context" 13 | ) 14 | 15 | // maxRandRenew is a maximum deviation from Manager.RenewBefore. 16 | const maxRandRenew = time.Hour 17 | 18 | // domainRenewal tracks the state used by the periodic timers 19 | // renewing a single domain's cert. 20 | type domainRenewal struct { 21 | m *Manager 22 | domain string 23 | key crypto.Signer 24 | 25 | timerMu sync.Mutex 26 | timer *time.Timer 27 | } 28 | 29 | // start starts a cert renewal timer at the time 30 | // defined by the certificate expiration time exp. 31 | // 32 | // If the timer is already started, calling start is a noop. 33 | func (dr *domainRenewal) start(exp time.Time) { 34 | dr.timerMu.Lock() 35 | defer dr.timerMu.Unlock() 36 | if dr.timer != nil { 37 | return 38 | } 39 | dr.timer = time.AfterFunc(dr.next(exp), dr.renew) 40 | } 41 | 42 | // stop stops the cert renewal timer. 43 | // If the timer is already stopped, calling stop is a noop. 44 | func (dr *domainRenewal) stop() { 45 | dr.timerMu.Lock() 46 | defer dr.timerMu.Unlock() 47 | if dr.timer == nil { 48 | return 49 | } 50 | dr.timer.Stop() 51 | dr.timer = nil 52 | } 53 | 54 | // renew is called periodically by a timer. 55 | // The first renew call is kicked off by dr.start. 56 | func (dr *domainRenewal) renew() { 57 | dr.timerMu.Lock() 58 | defer dr.timerMu.Unlock() 59 | if dr.timer == nil { 60 | return 61 | } 62 | 63 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) 64 | defer cancel() 65 | // TODO: rotate dr.key at some point? 66 | next, err := dr.do(ctx) 67 | if err != nil { 68 | next = maxRandRenew / 2 69 | next += time.Duration(pseudoRand.int63n(int64(next))) 70 | } 71 | dr.timer = time.AfterFunc(next, dr.renew) 72 | testDidRenewLoop(next, err) 73 | } 74 | 75 | // do is similar to Manager.createCert but it doesn't lock a Manager.state item. 76 | // Instead, it requests a new certificate independently and, upon success, 77 | // replaces dr.m.state item with a new one and updates cache for the given domain. 78 | // 79 | // It may return immediately if the expiration date of the currently cached cert 80 | // is far enough in the future. 81 | // 82 | // The returned value is a time interval after which the renewal should occur again. 83 | func (dr *domainRenewal) do(ctx context.Context) (time.Duration, error) { 84 | // a race is likely unavoidable in a distributed environment 85 | // but we try nonetheless 86 | if tlscert, err := dr.m.cacheGet(dr.domain); err == nil { 87 | next := dr.next(tlscert.Leaf.NotAfter) 88 | if next > dr.m.renewBefore()+maxRandRenew { 89 | return next, nil 90 | } 91 | } 92 | 93 | der, leaf, err := dr.m.authorizedCert(ctx, dr.key, dr.domain) 94 | if err != nil { 95 | return 0, err 96 | } 97 | state := &certState{ 98 | key: dr.key, 99 | cert: der, 100 | leaf: leaf, 101 | } 102 | tlscert, err := state.tlscert() 103 | if err != nil { 104 | return 0, err 105 | } 106 | dr.m.cachePut(dr.domain, tlscert) 107 | dr.m.stateMu.Lock() 108 | defer dr.m.stateMu.Unlock() 109 | // m.state is guaranteed to be non-nil at this point 110 | dr.m.state[dr.domain] = state 111 | return dr.next(leaf.NotAfter), nil 112 | } 113 | 114 | func (dr *domainRenewal) next(expiry time.Time) time.Duration { 115 | d := expiry.Sub(timeNow()) - dr.m.renewBefore() 116 | // add a bit of randomness to renew deadline 117 | n := pseudoRand.int63n(int64(maxRandRenew)) 118 | d -= time.Duration(n) 119 | if d < 0 { 120 | return 0 121 | } 122 | return d 123 | } 124 | 125 | var testDidRenewLoop = func(next time.Duration, err error) {} 126 | -------------------------------------------------------------------------------- /stomp/writer_test.go: -------------------------------------------------------------------------------- 1 | package stomp 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | ) 7 | 8 | var payloads = []struct { 9 | message *Message 10 | payload string 11 | }{ 12 | { 13 | payload: "STOMP\naccept-version:1.2\nlogin:janedoe\npasscode:pa55word\n\n", 14 | message: &Message{ 15 | Method: MethodStomp, 16 | Proto: STOMP, 17 | User: []byte("janedoe"), 18 | Pass: []byte("pa55word"), 19 | Header: newHeader(), 20 | }, 21 | }, 22 | { 23 | payload: "CONNECTED\nversion:1.2\n\n", 24 | message: &Message{ 25 | Method: MethodConnected, 26 | Proto: STOMP, 27 | Header: newHeader(), 28 | }, 29 | }, 30 | { 31 | payload: "SEND\ndestination:/queue/test\nexpires:1234\nretain:all\npersist:true\nreceipt:4321\n\nhello", 32 | message: &Message{ 33 | Method: MethodSend, 34 | Dest: []byte("/queue/test"), 35 | Expires: []byte("1234"), 36 | Retain: RetainAll, 37 | Persist: PersistTrue, 38 | Receipt: []byte("4321"), 39 | Body: []byte("hello"), 40 | Header: newHeader(), 41 | }, 42 | }, 43 | { 44 | payload: "SUBSCRIBE\nid:123\ndestination:/queue/test\nselector:foo == bar\nprefetch-count:2\nack:auto\n\n", 45 | message: &Message{ 46 | Method: MethodSubscribe, 47 | ID: []byte("123"), 48 | Dest: []byte("/queue/test"), 49 | Selector: []byte("foo == bar"), 50 | Prefetch: []byte("2"), 51 | Ack: AckAuto, 52 | Header: newHeader(), 53 | }, 54 | }, 55 | { 56 | payload: "UNSUBSCRIBE\nid:123\n\n", 57 | message: &Message{ 58 | Method: MethodUnsubscribe, 59 | ID: []byte("123"), 60 | Header: newHeader(), 61 | }, 62 | }, 63 | { 64 | payload: "ACK\nid:123\n\n", 65 | message: &Message{ 66 | Method: MethodAck, 67 | ID: []byte("123"), 68 | Header: newHeader(), 69 | }, 70 | }, 71 | { 72 | payload: "NACK\nid:123\n\n", 73 | message: &Message{ 74 | Method: MethodNack, 75 | ID: []byte("123"), 76 | Header: newHeader(), 77 | }, 78 | }, 79 | { 80 | payload: "MESSAGE\nmessage-id:123\ndestination:/queue/test\nsubscription:321\nack:312\n\nhello", 81 | message: &Message{ 82 | Method: MethodMessage, 83 | Dest: []byte("/queue/test"), 84 | ID: []byte("123"), 85 | Subs: []byte("321"), 86 | Ack: []byte("312"), 87 | Body: []byte("hello"), 88 | Header: newHeader(), 89 | }, 90 | }, 91 | { 92 | payload: "ERROR\n\n", 93 | message: &Message{ 94 | Method: MethodError, 95 | Header: newHeader(), 96 | }, 97 | }, 98 | { 99 | payload: "RECEIPT\nreceipt-id:123\n\n", 100 | message: &Message{ 101 | Method: MethodRecipet, 102 | Receipt: []byte("123"), 103 | Header: newHeader(), 104 | }, 105 | }, 106 | { 107 | payload: "RECEIPT\nreceipt-id:123\nfoo:bar\n\n", 108 | message: &Message{ 109 | Method: MethodRecipet, 110 | Receipt: []byte("123"), 111 | Header: func() *Header { 112 | header := newHeader() 113 | header.Add([]byte("foo"), []byte("bar")) 114 | return header 115 | }(), 116 | }, 117 | }, 118 | { 119 | payload: "DISCONNECT\nreceipt:123\n\n", 120 | message: &Message{ 121 | Method: MethodDisconnect, 122 | Receipt: []byte("123"), 123 | Header: newHeader(), 124 | }, 125 | }, 126 | } 127 | 128 | func TestWrite(t *testing.T) { 129 | for _, test := range payloads { 130 | if payload := test.message.String(); payload != test.payload { 131 | t.Errorf("Want serialized message %q, got %q", test.payload, payload) 132 | } 133 | } 134 | } 135 | 136 | var resultbuf bytes.Buffer 137 | 138 | func BenchmarkWrite(b *testing.B) { 139 | msg := NewMessage() 140 | msg.Method = MethodSend 141 | msg.Dest = []byte("/queue/foo") 142 | msg.Body = []byte("foo\nbar\nbaz\nqux") 143 | defer msg.Release() 144 | 145 | b.ReportAllocs() 146 | b.ResetTimer() 147 | 148 | for n := 0; n < b.N; n++ { 149 | resultbuf.Reset() 150 | writeTo(&resultbuf, msg) 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /vendor/github.com/golang/snappy/README: -------------------------------------------------------------------------------- 1 | The Snappy compression format in the Go programming language. 2 | 3 | To download and install from source: 4 | $ go get github.com/golang/snappy 5 | 6 | Unless otherwise noted, the Snappy-Go source files are distributed 7 | under the BSD-style license found in the LICENSE file. 8 | 9 | 10 | 11 | Benchmarks. 12 | 13 | The golang/snappy benchmarks include compressing (Z) and decompressing (U) ten 14 | or so files, the same set used by the C++ Snappy code (github.com/google/snappy 15 | and note the "google", not "golang"). On an "Intel(R) Core(TM) i7-3770 CPU @ 16 | 3.40GHz", Go's GOARCH=amd64 numbers as of 2016-05-29: 17 | 18 | "go test -test.bench=." 19 | 20 | _UFlat0-8 2.19GB/s ± 0% html 21 | _UFlat1-8 1.41GB/s ± 0% urls 22 | _UFlat2-8 23.5GB/s ± 2% jpg 23 | _UFlat3-8 1.91GB/s ± 0% jpg_200 24 | _UFlat4-8 14.0GB/s ± 1% pdf 25 | _UFlat5-8 1.97GB/s ± 0% html4 26 | _UFlat6-8 814MB/s ± 0% txt1 27 | _UFlat7-8 785MB/s ± 0% txt2 28 | _UFlat8-8 857MB/s ± 0% txt3 29 | _UFlat9-8 719MB/s ± 1% txt4 30 | _UFlat10-8 2.84GB/s ± 0% pb 31 | _UFlat11-8 1.05GB/s ± 0% gaviota 32 | 33 | _ZFlat0-8 1.04GB/s ± 0% html 34 | _ZFlat1-8 534MB/s ± 0% urls 35 | _ZFlat2-8 15.7GB/s ± 1% jpg 36 | _ZFlat3-8 740MB/s ± 3% jpg_200 37 | _ZFlat4-8 9.20GB/s ± 1% pdf 38 | _ZFlat5-8 991MB/s ± 0% html4 39 | _ZFlat6-8 379MB/s ± 0% txt1 40 | _ZFlat7-8 352MB/s ± 0% txt2 41 | _ZFlat8-8 396MB/s ± 1% txt3 42 | _ZFlat9-8 327MB/s ± 1% txt4 43 | _ZFlat10-8 1.33GB/s ± 1% pb 44 | _ZFlat11-8 605MB/s ± 1% gaviota 45 | 46 | 47 | 48 | "go test -test.bench=. -tags=noasm" 49 | 50 | _UFlat0-8 621MB/s ± 2% html 51 | _UFlat1-8 494MB/s ± 1% urls 52 | _UFlat2-8 23.2GB/s ± 1% jpg 53 | _UFlat3-8 1.12GB/s ± 1% jpg_200 54 | _UFlat4-8 4.35GB/s ± 1% pdf 55 | _UFlat5-8 609MB/s ± 0% html4 56 | _UFlat6-8 296MB/s ± 0% txt1 57 | _UFlat7-8 288MB/s ± 0% txt2 58 | _UFlat8-8 309MB/s ± 1% txt3 59 | _UFlat9-8 280MB/s ± 1% txt4 60 | _UFlat10-8 753MB/s ± 0% pb 61 | _UFlat11-8 400MB/s ± 0% gaviota 62 | 63 | _ZFlat0-8 409MB/s ± 1% html 64 | _ZFlat1-8 250MB/s ± 1% urls 65 | _ZFlat2-8 12.3GB/s ± 1% jpg 66 | _ZFlat3-8 132MB/s ± 0% jpg_200 67 | _ZFlat4-8 2.92GB/s ± 0% pdf 68 | _ZFlat5-8 405MB/s ± 1% html4 69 | _ZFlat6-8 179MB/s ± 1% txt1 70 | _ZFlat7-8 170MB/s ± 1% txt2 71 | _ZFlat8-8 189MB/s ± 1% txt3 72 | _ZFlat9-8 164MB/s ± 1% txt4 73 | _ZFlat10-8 479MB/s ± 1% pb 74 | _ZFlat11-8 270MB/s ± 1% gaviota 75 | 76 | 77 | 78 | For comparison (Go's encoded output is byte-for-byte identical to C++'s), here 79 | are the numbers from C++ Snappy's 80 | 81 | make CXXFLAGS="-O2 -DNDEBUG -g" clean snappy_unittest.log && cat snappy_unittest.log 82 | 83 | BM_UFlat/0 2.4GB/s html 84 | BM_UFlat/1 1.4GB/s urls 85 | BM_UFlat/2 21.8GB/s jpg 86 | BM_UFlat/3 1.5GB/s jpg_200 87 | BM_UFlat/4 13.3GB/s pdf 88 | BM_UFlat/5 2.1GB/s html4 89 | BM_UFlat/6 1.0GB/s txt1 90 | BM_UFlat/7 959.4MB/s txt2 91 | BM_UFlat/8 1.0GB/s txt3 92 | BM_UFlat/9 864.5MB/s txt4 93 | BM_UFlat/10 2.9GB/s pb 94 | BM_UFlat/11 1.2GB/s gaviota 95 | 96 | BM_ZFlat/0 944.3MB/s html (22.31 %) 97 | BM_ZFlat/1 501.6MB/s urls (47.78 %) 98 | BM_ZFlat/2 14.3GB/s jpg (99.95 %) 99 | BM_ZFlat/3 538.3MB/s jpg_200 (73.00 %) 100 | BM_ZFlat/4 8.3GB/s pdf (83.30 %) 101 | BM_ZFlat/5 903.5MB/s html4 (22.52 %) 102 | BM_ZFlat/6 336.0MB/s txt1 (57.88 %) 103 | BM_ZFlat/7 312.3MB/s txt2 (61.91 %) 104 | BM_ZFlat/8 353.1MB/s txt3 (54.99 %) 105 | BM_ZFlat/9 289.9MB/s txt4 (66.26 %) 106 | BM_ZFlat/10 1.2GB/s pb (19.68 %) 107 | BM_ZFlat/11 527.4MB/s gaviota (37.72 %) 108 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/websocket/server.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package websocket 6 | 7 | import ( 8 | "bufio" 9 | "fmt" 10 | "io" 11 | "net/http" 12 | ) 13 | 14 | func newServerConn(rwc io.ReadWriteCloser, buf *bufio.ReadWriter, req *http.Request, config *Config, handshake func(*Config, *http.Request) error) (conn *Conn, err error) { 15 | var hs serverHandshaker = &hybiServerHandshaker{Config: config} 16 | code, err := hs.ReadHandshake(buf.Reader, req) 17 | if err == ErrBadWebSocketVersion { 18 | fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code)) 19 | fmt.Fprintf(buf, "Sec-WebSocket-Version: %s\r\n", SupportedProtocolVersion) 20 | buf.WriteString("\r\n") 21 | buf.WriteString(err.Error()) 22 | buf.Flush() 23 | return 24 | } 25 | if err != nil { 26 | fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code)) 27 | buf.WriteString("\r\n") 28 | buf.WriteString(err.Error()) 29 | buf.Flush() 30 | return 31 | } 32 | if handshake != nil { 33 | err = handshake(config, req) 34 | if err != nil { 35 | code = http.StatusForbidden 36 | fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code)) 37 | buf.WriteString("\r\n") 38 | buf.Flush() 39 | return 40 | } 41 | } 42 | err = hs.AcceptHandshake(buf.Writer) 43 | if err != nil { 44 | code = http.StatusBadRequest 45 | fmt.Fprintf(buf, "HTTP/1.1 %03d %s\r\n", code, http.StatusText(code)) 46 | buf.WriteString("\r\n") 47 | buf.Flush() 48 | return 49 | } 50 | conn = hs.NewServerConn(buf, rwc, req) 51 | return 52 | } 53 | 54 | // Server represents a server of a WebSocket. 55 | type Server struct { 56 | // Config is a WebSocket configuration for new WebSocket connection. 57 | Config 58 | 59 | // Handshake is an optional function in WebSocket handshake. 60 | // For example, you can check, or don't check Origin header. 61 | // Another example, you can select config.Protocol. 62 | Handshake func(*Config, *http.Request) error 63 | 64 | // Handler handles a WebSocket connection. 65 | Handler 66 | } 67 | 68 | // ServeHTTP implements the http.Handler interface for a WebSocket 69 | func (s Server) ServeHTTP(w http.ResponseWriter, req *http.Request) { 70 | s.serveWebSocket(w, req) 71 | } 72 | 73 | func (s Server) serveWebSocket(w http.ResponseWriter, req *http.Request) { 74 | rwc, buf, err := w.(http.Hijacker).Hijack() 75 | if err != nil { 76 | panic("Hijack failed: " + err.Error()) 77 | } 78 | // The server should abort the WebSocket connection if it finds 79 | // the client did not send a handshake that matches with protocol 80 | // specification. 81 | defer rwc.Close() 82 | conn, err := newServerConn(rwc, buf, req, &s.Config, s.Handshake) 83 | if err != nil { 84 | return 85 | } 86 | if conn == nil { 87 | panic("unexpected nil conn") 88 | } 89 | s.Handler(conn) 90 | } 91 | 92 | // Handler is a simple interface to a WebSocket browser client. 93 | // It checks if Origin header is valid URL by default. 94 | // You might want to verify websocket.Conn.Config().Origin in the func. 95 | // If you use Server instead of Handler, you could call websocket.Origin and 96 | // check the origin in your Handshake func. So, if you want to accept 97 | // non-browser clients, which do not send an Origin header, set a 98 | // Server.Handshake that does not check the origin. 99 | type Handler func(*Conn) 100 | 101 | func checkOrigin(config *Config, req *http.Request) (err error) { 102 | config.Origin, err = Origin(config, req) 103 | if err == nil && config.Origin == nil { 104 | return fmt.Errorf("null origin") 105 | } 106 | return err 107 | } 108 | 109 | // ServeHTTP implements the http.Handler interface for a WebSocket 110 | func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) { 111 | s := Server{Handler: h, Handshake: checkOrigin} 112 | s.serveWebSocket(w, req) 113 | } 114 | -------------------------------------------------------------------------------- /stomp/message.go: -------------------------------------------------------------------------------- 1 | package stomp 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "math/rand" 7 | "strconv" 8 | "sync" 9 | 10 | "golang.org/x/net/context" 11 | ) 12 | 13 | // Message represents a parsed STOMP message. 14 | type Message struct { 15 | ID []byte // id header 16 | Proto []byte // stomp version 17 | Method []byte // stomp method 18 | User []byte // username header 19 | Pass []byte // password header 20 | Dest []byte // destination header 21 | Subs []byte // subscription id 22 | Ack []byte // ack id 23 | Msg []byte // message-id header 24 | Persist []byte // persist header 25 | Retain []byte // retain header 26 | Prefetch []byte // prefetch count 27 | Expires []byte // expires header 28 | Receipt []byte // receipt header 29 | Selector []byte // selector header 30 | Body []byte 31 | Header *Header // custom headers 32 | 33 | ctx context.Context 34 | } 35 | 36 | // Copy returns a copy of the Message. 37 | func (m *Message) Copy() *Message { 38 | c := NewMessage() 39 | c.ID = m.ID 40 | c.Proto = m.Proto 41 | c.Method = m.Method 42 | c.User = m.User 43 | c.Pass = m.Pass 44 | c.Dest = m.Dest 45 | c.Subs = m.Subs 46 | c.Ack = m.Ack 47 | c.Prefetch = m.Prefetch 48 | c.Selector = m.Selector 49 | c.Persist = m.Persist 50 | c.Retain = m.Retain 51 | c.Receipt = m.Receipt 52 | c.Expires = m.Expires 53 | c.Body = m.Body 54 | c.ctx = m.ctx 55 | c.Header.itemc = m.Header.itemc 56 | copy(c.Header.items, m.Header.items) 57 | return c 58 | } 59 | 60 | // Apply applies the options to the message. 61 | func (m *Message) Apply(opts ...MessageOption) { 62 | for _, opt := range opts { 63 | opt(m) 64 | } 65 | } 66 | 67 | // Parse parses the raw bytes into the message. 68 | func (m *Message) Parse(b []byte) error { 69 | return read(b, m) 70 | } 71 | 72 | // Bytes returns the Message in raw byte format. 73 | func (m *Message) Bytes() []byte { 74 | var buf bytes.Buffer 75 | writeTo(&buf, m) 76 | return buf.Bytes() 77 | } 78 | 79 | // String returns the Message in string format. 80 | func (m *Message) String() string { 81 | return string(m.Bytes()) 82 | } 83 | 84 | // Release releases the message back to the message pool. 85 | func (m *Message) Release() { 86 | m.Reset() 87 | pool.Put(m) 88 | } 89 | 90 | // Reset resets the meesage fields to their zero values. 91 | func (m *Message) Reset() { 92 | m.ID = m.ID[:0] 93 | m.Proto = m.Proto[:0] 94 | m.Method = m.Method[:0] 95 | m.User = m.User[:0] 96 | m.Pass = m.Pass[:0] 97 | m.Dest = m.Dest[:0] 98 | m.Subs = m.Subs[:0] 99 | m.Ack = m.Ack[:0] 100 | m.Prefetch = m.Prefetch[:0] 101 | m.Selector = m.Selector[:0] 102 | m.Persist = m.Persist[:0] 103 | m.Retain = m.Retain[:0] 104 | m.Receipt = m.Receipt[:0] 105 | m.Expires = m.Expires[:0] 106 | m.Body = m.Body[:0] 107 | m.ctx = nil 108 | m.Header.reset() 109 | } 110 | 111 | // Context returns the request's context. 112 | func (m *Message) Context() context.Context { 113 | if m.ctx != nil { 114 | return m.ctx 115 | } 116 | return context.Background() 117 | } 118 | 119 | // WithContext returns a shallow copy of m with its context changed 120 | // to ctx. The provided ctx must be non-nil. 121 | func (m *Message) WithContext(ctx context.Context) *Message { 122 | c := m.Copy() 123 | c.ctx = ctx 124 | return c 125 | } 126 | 127 | // Unmarshal parses the JSON-encoded body of the message and 128 | // stores the result in the value pointed to by v. 129 | func (m *Message) Unmarshal(v interface{}) error { 130 | return json.Unmarshal(m.Body, v) 131 | } 132 | 133 | // NewMessage returns an empty message from the message pool. 134 | func NewMessage() *Message { 135 | return pool.Get().(*Message) 136 | } 137 | 138 | var pool = sync.Pool{New: func() interface{} { 139 | return &Message{Header: newHeader()} 140 | }} 141 | 142 | // Rand returns a random int64 number as a []byte of 143 | // ascii characters. 144 | func Rand() []byte { 145 | return strconv.AppendInt(nil, rand.Int63(), 10) 146 | } 147 | -------------------------------------------------------------------------------- /vendor/golang.org/x/crypto/acme/autocert/cache.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package autocert 6 | 7 | import ( 8 | "errors" 9 | "io/ioutil" 10 | "os" 11 | "path/filepath" 12 | 13 | "golang.org/x/net/context" 14 | ) 15 | 16 | // ErrCacheMiss is returned when a certificate is not found in cache. 17 | var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss") 18 | 19 | // Cache is used by Manager to store and retrieve previously obtained certificates 20 | // as opaque data. 21 | // 22 | // The key argument of the methods refers to a domain name but need not be an FQDN. 23 | // Cache implementations should not rely on the key naming pattern. 24 | type Cache interface { 25 | // Get returns a certificate data for the specified key. 26 | // If there's no such key, Get returns ErrCacheMiss. 27 | Get(ctx context.Context, key string) ([]byte, error) 28 | 29 | // Put stores the data in the cache under the specified key. 30 | // Inderlying implementations may use any data storage format, 31 | // as long as the reverse operation, Get, results in the original data. 32 | Put(ctx context.Context, key string, data []byte) error 33 | 34 | // Delete removes a certificate data from the cache under the specified key. 35 | // If there's no such key in the cache, Delete returns nil. 36 | Delete(ctx context.Context, key string) error 37 | } 38 | 39 | // DirCache implements Cache using a directory on the local filesystem. 40 | // If the directory does not exist, it will be created with 0700 permissions. 41 | type DirCache string 42 | 43 | // Get reads a certificate data from the specified file name. 44 | func (d DirCache) Get(ctx context.Context, name string) ([]byte, error) { 45 | name = filepath.Join(string(d), name) 46 | var ( 47 | data []byte 48 | err error 49 | done = make(chan struct{}) 50 | ) 51 | go func() { 52 | data, err = ioutil.ReadFile(name) 53 | close(done) 54 | }() 55 | select { 56 | case <-ctx.Done(): 57 | return nil, ctx.Err() 58 | case <-done: 59 | } 60 | if os.IsNotExist(err) { 61 | return nil, ErrCacheMiss 62 | } 63 | return data, err 64 | } 65 | 66 | // Put writes the certificate data to the specified file name. 67 | // The file will be created with 0600 permissions. 68 | func (d DirCache) Put(ctx context.Context, name string, data []byte) error { 69 | if err := os.MkdirAll(string(d), 0700); err != nil { 70 | return err 71 | } 72 | 73 | done := make(chan struct{}) 74 | var err error 75 | go func() { 76 | defer close(done) 77 | var tmp string 78 | if tmp, err = d.writeTempFile(name, data); err != nil { 79 | return 80 | } 81 | // prevent overwriting the file if the context was cancelled 82 | if ctx.Err() != nil { 83 | return // no need to set err 84 | } 85 | name = filepath.Join(string(d), name) 86 | err = os.Rename(tmp, name) 87 | }() 88 | select { 89 | case <-ctx.Done(): 90 | return ctx.Err() 91 | case <-done: 92 | } 93 | return err 94 | } 95 | 96 | // Delete removes the specified file name. 97 | func (d DirCache) Delete(ctx context.Context, name string) error { 98 | name = filepath.Join(string(d), name) 99 | var ( 100 | err error 101 | done = make(chan struct{}) 102 | ) 103 | go func() { 104 | err = os.Remove(name) 105 | close(done) 106 | }() 107 | select { 108 | case <-ctx.Done(): 109 | return ctx.Err() 110 | case <-done: 111 | } 112 | if err != nil && !os.IsNotExist(err) { 113 | return err 114 | } 115 | return nil 116 | } 117 | 118 | // writeTempFile writes b to a temporary file, closes the file and returns its path. 119 | func (d DirCache) writeTempFile(prefix string, b []byte) (string, error) { 120 | // TempFile uses 0600 permissions 121 | f, err := ioutil.TempFile(string(d), prefix) 122 | if err != nil { 123 | return "", err 124 | } 125 | if _, err := f.Write(b); err != nil { 126 | f.Close() 127 | return "", err 128 | } 129 | return f.Name(), f.Close() 130 | } 131 | -------------------------------------------------------------------------------- /stomp/writer.go: -------------------------------------------------------------------------------- 1 | package stomp 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | ) 7 | 8 | var ( 9 | crlf = []byte{'\r', '\n'} 10 | newline = []byte{'\n'} 11 | separator = []byte{':'} 12 | terminator = []byte{0} 13 | ) 14 | 15 | func writeTo(w io.Writer, m *Message) { 16 | w.Write(m.Method) 17 | w.Write(newline) 18 | 19 | switch { 20 | case bytes.Equal(m.Method, MethodStomp): 21 | // version 22 | w.Write(HeaderAccept) 23 | w.Write(separator) 24 | w.Write(m.Proto) 25 | w.Write(newline) 26 | // login 27 | if len(m.User) != 0 { 28 | w.Write(HeaderLogin) 29 | w.Write(separator) 30 | w.Write(m.User) 31 | w.Write(newline) 32 | } 33 | // passcode 34 | if len(m.Pass) != 0 { 35 | w.Write(HeaderPass) 36 | w.Write(separator) 37 | w.Write(m.Pass) 38 | w.Write(newline) 39 | } 40 | case bytes.Equal(m.Method, MethodConnected): 41 | // version 42 | w.Write(HeaderVersion) 43 | w.Write(separator) 44 | w.Write(m.Proto) 45 | w.Write(newline) 46 | case bytes.Equal(m.Method, MethodSend): 47 | // dest 48 | w.Write(HeaderDest) 49 | w.Write(separator) 50 | w.Write(m.Dest) 51 | w.Write(newline) 52 | if len(m.Expires) != 0 { 53 | w.Write(HeaderExpires) 54 | w.Write(separator) 55 | w.Write(m.Expires) 56 | w.Write(newline) 57 | } 58 | if len(m.Retain) != 0 { 59 | w.Write(HeaderRetain) 60 | w.Write(separator) 61 | w.Write(m.Retain) 62 | w.Write(newline) 63 | } 64 | if len(m.Persist) != 0 { 65 | w.Write(HeaderPersist) 66 | w.Write(separator) 67 | w.Write(m.Persist) 68 | w.Write(newline) 69 | } 70 | case bytes.Equal(m.Method, MethodSubscribe): 71 | // id 72 | w.Write(HeaderID) 73 | w.Write(separator) 74 | w.Write(m.ID) 75 | w.Write(newline) 76 | // destination 77 | w.Write(HeaderDest) 78 | w.Write(separator) 79 | w.Write(m.Dest) 80 | w.Write(newline) 81 | // selector 82 | if len(m.Selector) != 0 { 83 | w.Write(HeaderSelector) 84 | w.Write(separator) 85 | w.Write(m.Selector) 86 | w.Write(newline) 87 | } 88 | // prefetch 89 | if len(m.Prefetch) != 0 { 90 | w.Write(HeaderPrefetch) 91 | w.Write(separator) 92 | w.Write(m.Prefetch) 93 | w.Write(newline) 94 | } 95 | if len(m.Ack) != 0 { 96 | w.Write(HeaderAck) 97 | w.Write(separator) 98 | w.Write(m.Ack) 99 | w.Write(newline) 100 | } 101 | case bytes.Equal(m.Method, MethodUnsubscribe): 102 | // id 103 | w.Write(HeaderID) 104 | w.Write(separator) 105 | w.Write(m.ID) 106 | w.Write(newline) 107 | case bytes.Equal(m.Method, MethodAck): 108 | // id 109 | w.Write(HeaderID) 110 | w.Write(separator) 111 | w.Write(m.ID) 112 | w.Write(newline) 113 | case bytes.Equal(m.Method, MethodNack): 114 | // id 115 | w.Write(HeaderID) 116 | w.Write(separator) 117 | w.Write(m.ID) 118 | w.Write(newline) 119 | case bytes.Equal(m.Method, MethodMessage): 120 | // message-id 121 | w.Write(HeaderMessageID) 122 | w.Write(separator) 123 | w.Write(m.ID) 124 | w.Write(newline) 125 | // destination 126 | w.Write(HeaderDest) 127 | w.Write(separator) 128 | w.Write(m.Dest) 129 | w.Write(newline) 130 | // subscription 131 | w.Write(HeaderSubscription) 132 | w.Write(separator) 133 | w.Write(m.Subs) 134 | w.Write(newline) 135 | // ack 136 | if len(m.Ack) != 0 { 137 | w.Write(HeaderAck) 138 | w.Write(separator) 139 | w.Write(m.Ack) 140 | w.Write(newline) 141 | } 142 | case bytes.Equal(m.Method, MethodRecipet): 143 | // receipt-id 144 | w.Write(HeaderReceiptID) 145 | w.Write(separator) 146 | w.Write(m.Receipt) 147 | w.Write(newline) 148 | } 149 | 150 | // receipt header 151 | if includeReceiptHeader(m) { 152 | w.Write(HeaderReceipt) 153 | w.Write(separator) 154 | w.Write(m.Receipt) 155 | w.Write(newline) 156 | } 157 | 158 | for i, item := range m.Header.items { 159 | if m.Header.itemc == i { 160 | break 161 | } 162 | w.Write(item.name) 163 | w.Write(separator) 164 | w.Write(item.data) 165 | w.Write(newline) 166 | } 167 | w.Write(newline) 168 | w.Write(m.Body) 169 | } 170 | 171 | func includeReceiptHeader(m *Message) bool { 172 | return len(m.Receipt) != 0 && !bytes.Equal(m.Method, MethodRecipet) 173 | } 174 | -------------------------------------------------------------------------------- /stomp/selector/eval.go: -------------------------------------------------------------------------------- 1 | package selector 2 | 3 | import ( 4 | "bytes" 5 | "path/filepath" 6 | "regexp" 7 | 8 | "github.com/drone/mq/stomp/selector/parse" 9 | ) 10 | 11 | // state represents the state of an execution. It's not part of the 12 | // statement so that multiple executions of the same statement 13 | // can execute in parallel. 14 | type state struct { 15 | node parse.Node 16 | vars Row 17 | } 18 | 19 | // at marks the state to be on node n, for error reporting. 20 | func (s *state) at(node parse.Node) { 21 | s.node = node 22 | } 23 | 24 | // Walk functions step through the major pieces of the template structure, 25 | // generating output as they go. 26 | func (s *state) walk(node parse.BoolExpr) bool { 27 | s.at(node) 28 | 29 | switch node := node.(type) { 30 | case *parse.ComparisonExpr: 31 | return s.eval(node) 32 | case *parse.AndExpr: 33 | return s.walk(node.Left) && s.walk(node.Right) 34 | case *parse.OrExpr: 35 | return s.walk(node.Left) || s.walk(node.Right) 36 | case *parse.NotExpr: 37 | return !s.walk(node.Expr) 38 | case *parse.ParenBoolExpr: 39 | return s.walk(node.Expr) 40 | default: 41 | panic("invalid node type") 42 | } 43 | } 44 | 45 | func (s *state) eval(node *parse.ComparisonExpr) bool { 46 | switch node.Operator { 47 | case parse.OperatorEq: 48 | return s.evalEq(node) 49 | case parse.OperatorGt: 50 | return s.evalGt(node) 51 | case parse.OperatorGte: 52 | return s.evalGte(node) 53 | case parse.OperatorLt: 54 | return s.evalLt(node) 55 | case parse.OperatorLte: 56 | return s.evalLte(node) 57 | case parse.OperatorNeq: 58 | return !s.evalEq(node) 59 | case parse.OperatorGlob: 60 | return s.evalGlob(node) 61 | case parse.OperatorNotGlob: 62 | return !s.evalGlob(node) 63 | case parse.OperatorRe: 64 | return s.evalRegexp(node) 65 | case parse.OperatorNotRe: 66 | return !s.evalRegexp(node) 67 | case parse.OperatorIn: 68 | return s.evalIn(node) 69 | case parse.OperatorNotIn: 70 | return !s.evalIn(node) 71 | default: 72 | panic("inalid operator type") 73 | } 74 | } 75 | 76 | func (s *state) evalEq(node *parse.ComparisonExpr) bool { 77 | return bytes.Equal( 78 | s.toValue(node.Left), 79 | s.toValue(node.Right), 80 | ) 81 | } 82 | 83 | func (s *state) evalGt(node *parse.ComparisonExpr) bool { 84 | return bytes.Compare( 85 | s.toValue(node.Left), 86 | s.toValue(node.Right), 87 | ) == 1 88 | } 89 | 90 | func (s *state) evalGte(node *parse.ComparisonExpr) bool { 91 | return bytes.Compare( 92 | s.toValue(node.Left), 93 | s.toValue(node.Right), 94 | ) >= 0 95 | } 96 | 97 | func (s *state) evalLt(node *parse.ComparisonExpr) bool { 98 | return bytes.Compare( 99 | s.toValue(node.Left), 100 | s.toValue(node.Right), 101 | ) == -1 102 | } 103 | 104 | func (s *state) evalLte(node *parse.ComparisonExpr) bool { 105 | return bytes.Compare( 106 | s.toValue(node.Left), 107 | s.toValue(node.Right), 108 | ) <= 0 109 | } 110 | 111 | func (s *state) evalGlob(node *parse.ComparisonExpr) bool { 112 | match, _ := filepath.Match( 113 | string(s.toValue(node.Right)), 114 | string(s.toValue(node.Left)), 115 | ) 116 | return match 117 | } 118 | 119 | func (s *state) evalRegexp(node *parse.ComparisonExpr) bool { 120 | match, _ := regexp.Match( 121 | string(s.toValue(node.Right)), 122 | s.toValue(node.Left), 123 | ) 124 | return match 125 | } 126 | 127 | func (s *state) evalIn(node *parse.ComparisonExpr) bool { 128 | left := s.toValue(node.Left) 129 | right, ok := node.Right.(*parse.ArrayLit) 130 | if !ok { 131 | panic("expected array literal") 132 | } 133 | 134 | for _, expr := range right.Values { 135 | if bytes.Equal(left, s.toValue(expr)) { 136 | return true 137 | } 138 | } 139 | return false 140 | } 141 | 142 | func (s *state) toValue(expr parse.ValExpr) []byte { 143 | switch node := expr.(type) { 144 | case *parse.Field: 145 | return s.vars.Field(node.Name) 146 | case *parse.BasicLit: 147 | return node.Value 148 | default: 149 | panic("invalid expression type") 150 | } 151 | } 152 | 153 | // errRecover is the handler that turns panics into returns. 154 | func errRecover(err *error) { 155 | if e := recover(); e != nil { 156 | *err = e.(error) 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/cache/lru.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | package cache 8 | 9 | import ( 10 | "sync" 11 | "unsafe" 12 | ) 13 | 14 | type lruNode struct { 15 | n *Node 16 | h *Handle 17 | ban bool 18 | 19 | next, prev *lruNode 20 | } 21 | 22 | func (n *lruNode) insert(at *lruNode) { 23 | x := at.next 24 | at.next = n 25 | n.prev = at 26 | n.next = x 27 | x.prev = n 28 | } 29 | 30 | func (n *lruNode) remove() { 31 | if n.prev != nil { 32 | n.prev.next = n.next 33 | n.next.prev = n.prev 34 | n.prev = nil 35 | n.next = nil 36 | } else { 37 | panic("BUG: removing removed node") 38 | } 39 | } 40 | 41 | type lru struct { 42 | mu sync.Mutex 43 | capacity int 44 | used int 45 | recent lruNode 46 | } 47 | 48 | func (r *lru) reset() { 49 | r.recent.next = &r.recent 50 | r.recent.prev = &r.recent 51 | r.used = 0 52 | } 53 | 54 | func (r *lru) Capacity() int { 55 | r.mu.Lock() 56 | defer r.mu.Unlock() 57 | return r.capacity 58 | } 59 | 60 | func (r *lru) SetCapacity(capacity int) { 61 | var evicted []*lruNode 62 | 63 | r.mu.Lock() 64 | r.capacity = capacity 65 | for r.used > r.capacity { 66 | rn := r.recent.prev 67 | if rn == nil { 68 | panic("BUG: invalid LRU used or capacity counter") 69 | } 70 | rn.remove() 71 | rn.n.CacheData = nil 72 | r.used -= rn.n.Size() 73 | evicted = append(evicted, rn) 74 | } 75 | r.mu.Unlock() 76 | 77 | for _, rn := range evicted { 78 | rn.h.Release() 79 | } 80 | } 81 | 82 | func (r *lru) Promote(n *Node) { 83 | var evicted []*lruNode 84 | 85 | r.mu.Lock() 86 | if n.CacheData == nil { 87 | if n.Size() <= r.capacity { 88 | rn := &lruNode{n: n, h: n.GetHandle()} 89 | rn.insert(&r.recent) 90 | n.CacheData = unsafe.Pointer(rn) 91 | r.used += n.Size() 92 | 93 | for r.used > r.capacity { 94 | rn := r.recent.prev 95 | if rn == nil { 96 | panic("BUG: invalid LRU used or capacity counter") 97 | } 98 | rn.remove() 99 | rn.n.CacheData = nil 100 | r.used -= rn.n.Size() 101 | evicted = append(evicted, rn) 102 | } 103 | } 104 | } else { 105 | rn := (*lruNode)(n.CacheData) 106 | if !rn.ban { 107 | rn.remove() 108 | rn.insert(&r.recent) 109 | } 110 | } 111 | r.mu.Unlock() 112 | 113 | for _, rn := range evicted { 114 | rn.h.Release() 115 | } 116 | } 117 | 118 | func (r *lru) Ban(n *Node) { 119 | r.mu.Lock() 120 | if n.CacheData == nil { 121 | n.CacheData = unsafe.Pointer(&lruNode{n: n, ban: true}) 122 | } else { 123 | rn := (*lruNode)(n.CacheData) 124 | if !rn.ban { 125 | rn.remove() 126 | rn.ban = true 127 | r.used -= rn.n.Size() 128 | r.mu.Unlock() 129 | 130 | rn.h.Release() 131 | rn.h = nil 132 | return 133 | } 134 | } 135 | r.mu.Unlock() 136 | } 137 | 138 | func (r *lru) Evict(n *Node) { 139 | r.mu.Lock() 140 | rn := (*lruNode)(n.CacheData) 141 | if rn == nil || rn.ban { 142 | r.mu.Unlock() 143 | return 144 | } 145 | n.CacheData = nil 146 | r.mu.Unlock() 147 | 148 | rn.h.Release() 149 | } 150 | 151 | func (r *lru) EvictNS(ns uint64) { 152 | var evicted []*lruNode 153 | 154 | r.mu.Lock() 155 | for e := r.recent.prev; e != &r.recent; { 156 | rn := e 157 | e = e.prev 158 | if rn.n.NS() == ns { 159 | rn.remove() 160 | rn.n.CacheData = nil 161 | r.used -= rn.n.Size() 162 | evicted = append(evicted, rn) 163 | } 164 | } 165 | r.mu.Unlock() 166 | 167 | for _, rn := range evicted { 168 | rn.h.Release() 169 | } 170 | } 171 | 172 | func (r *lru) EvictAll() { 173 | r.mu.Lock() 174 | back := r.recent.prev 175 | for rn := back; rn != &r.recent; rn = rn.prev { 176 | rn.n.CacheData = nil 177 | } 178 | r.reset() 179 | r.mu.Unlock() 180 | 181 | for rn := back; rn != &r.recent; rn = rn.prev { 182 | rn.h.Release() 183 | } 184 | } 185 | 186 | func (r *lru) Close() error { 187 | return nil 188 | } 189 | 190 | // NewLRU create a new LRU-cache. 191 | func NewLRU(capacity int) Cacher { 192 | r := &lru{capacity: capacity} 193 | r.reset() 194 | return r 195 | } 196 | -------------------------------------------------------------------------------- /cmd/mq/serve.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "io" 6 | "net" 7 | "net/http" 8 | "os" 9 | "path" 10 | 11 | "github.com/tidwall/redlog" 12 | "github.com/urfave/cli" 13 | "golang.org/x/crypto/acme/autocert" 14 | 15 | "github.com/drone/mq/logger" 16 | "github.com/drone/mq/server" 17 | ) 18 | 19 | var comandServe = cli.Command{ 20 | Name: "start", 21 | Usage: "start the message broker daemon", 22 | Action: serve, 23 | Flags: []cli.Flag{ 24 | cli.StringFlag{ 25 | Name: "tcp", 26 | Usage: "stomp tcp server address", 27 | Value: ":9000", 28 | EnvVar: "STOMP_TCP", 29 | }, 30 | cli.StringFlag{ 31 | Name: "http", 32 | Usage: "stomp http server address", 33 | Value: ":8000", 34 | EnvVar: "STOMP_HTTP", 35 | }, 36 | cli.StringFlag{ 37 | Name: "cert", 38 | Usage: "stomp ssl cert", 39 | EnvVar: "STOMP_CERT", 40 | }, 41 | cli.StringFlag{ 42 | Name: "key", 43 | Usage: "stomp ssl key", 44 | EnvVar: "STOMP_KEY", 45 | }, 46 | cli.BoolFlag{ 47 | Name: "lets-encrypt", 48 | Usage: "stomp ssl using lets encrypt", 49 | EnvVar: "STOMP_LETS_ENCRYPT", 50 | }, 51 | cli.StringFlag{ 52 | Name: "lets-encrypt-host", 53 | Usage: "stomp lets encrypt host", 54 | EnvVar: "STOMP_LETS_ENCRYPT_HOST", 55 | }, 56 | cli.StringFlag{ 57 | Name: "lets-encrypt-email", 58 | Usage: "stomp lets encrypt email", 59 | EnvVar: "STOMP_LETS_ENCRYPT_EMAIL", 60 | }, 61 | cli.StringFlag{ 62 | Name: "lets-encrypt-cache", 63 | Usage: "stomp lets encrypt cache directory", 64 | EnvVar: "STOMP_LETS_ENCRYPT_DIR", 65 | }, 66 | cli.StringFlag{ 67 | Name: "base, b", 68 | Usage: "stomp server base", 69 | Value: "/", 70 | EnvVar: "STOMP_BASE", 71 | }, 72 | }, 73 | } 74 | 75 | func serve(c *cli.Context) error { 76 | var ( 77 | errc = make(chan error) 78 | 79 | user = c.GlobalString("username") 80 | pass = c.GlobalString("password") 81 | addr1 = c.String("tcp") 82 | addr2 = c.String("http") 83 | base = c.String("base") 84 | route = c.String("path") 85 | cert = c.String("cert") 86 | key = c.String("key") 87 | 88 | acme = c.Bool("lets-encrypt") 89 | host = c.String("lets-encrypt-host") 90 | email = c.String("lets-encrypt-email") 91 | cache = c.String("lets-encrypt-cache") 92 | ) 93 | 94 | var opts []server.Option 95 | if user != "" || pass != "" { 96 | opts = append(opts, 97 | server.WithCredentials(user, pass), 98 | ) 99 | } 100 | 101 | logs := redlog.New(os.Stderr) 102 | logs.SetLevel( 103 | c.GlobalInt("level"), 104 | ) 105 | logger.SetLogger(logs) 106 | logger.Noticef("stomp: starting server") 107 | 108 | server := server.NewServer(opts...) 109 | http.HandleFunc(path.Join("/", base, "meta/sessions"), server.HandleSessions) 110 | http.HandleFunc(path.Join("/", base, "meta/destinations"), server.HandleDests) 111 | http.Handle(path.Join("/", base, route), server) 112 | 113 | go func() { 114 | switch { 115 | case acme: 116 | errc <- listendAndServeAcme(host, email, cache) 117 | case cert != "": 118 | errc <- http.ListenAndServeTLS(addr2, cert, key, nil) 119 | default: 120 | errc <- http.ListenAndServe(addr2, nil) 121 | } 122 | }() 123 | 124 | go func() { 125 | l, err := net.Listen("tcp", addr1) 126 | if err != nil { 127 | errc <- err 128 | return 129 | } 130 | defer l.Close() 131 | 132 | for { 133 | conn, err := l.Accept() 134 | if err == io.EOF { 135 | errc <- nil 136 | return 137 | } 138 | if err != nil { 139 | errc <- err 140 | return 141 | } 142 | go server.Serve(conn) 143 | } 144 | }() 145 | 146 | return <-errc 147 | } 148 | 149 | // helper function to setup and http server using let's encrypt 150 | // certificates with auto-renewal. 151 | func listendAndServeAcme(host, email, cache string) error { 152 | m := autocert.Manager{ 153 | Prompt: autocert.AcceptTOS, 154 | HostPolicy: autocert.HostWhitelist(host), 155 | Email: email, 156 | } 157 | if cache != "" { 158 | m.Cache = autocert.DirCache(cache) 159 | } 160 | s := &http.Server{ 161 | Addr: ":https", 162 | TLSConfig: &tls.Config{GetCertificate: m.GetCertificate}, 163 | } 164 | return s.ListenAndServeTLS("", "") 165 | } 166 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !go1.7 6 | 7 | package ctxhttp // import "golang.org/x/net/context/ctxhttp" 8 | 9 | import ( 10 | "io" 11 | "net/http" 12 | "net/url" 13 | "strings" 14 | 15 | "golang.org/x/net/context" 16 | ) 17 | 18 | func nop() {} 19 | 20 | var ( 21 | testHookContextDoneBeforeHeaders = nop 22 | testHookDoReturned = nop 23 | testHookDidBodyClose = nop 24 | ) 25 | 26 | // Do sends an HTTP request with the provided http.Client and returns an HTTP response. 27 | // If the client is nil, http.DefaultClient is used. 28 | // If the context is canceled or times out, ctx.Err() will be returned. 29 | func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { 30 | if client == nil { 31 | client = http.DefaultClient 32 | } 33 | 34 | // TODO(djd): Respect any existing value of req.Cancel. 35 | cancel := make(chan struct{}) 36 | req.Cancel = cancel 37 | 38 | type responseAndError struct { 39 | resp *http.Response 40 | err error 41 | } 42 | result := make(chan responseAndError, 1) 43 | 44 | // Make local copies of test hooks closed over by goroutines below. 45 | // Prevents data races in tests. 46 | testHookDoReturned := testHookDoReturned 47 | testHookDidBodyClose := testHookDidBodyClose 48 | 49 | go func() { 50 | resp, err := client.Do(req) 51 | testHookDoReturned() 52 | result <- responseAndError{resp, err} 53 | }() 54 | 55 | var resp *http.Response 56 | 57 | select { 58 | case <-ctx.Done(): 59 | testHookContextDoneBeforeHeaders() 60 | close(cancel) 61 | // Clean up after the goroutine calling client.Do: 62 | go func() { 63 | if r := <-result; r.resp != nil { 64 | testHookDidBodyClose() 65 | r.resp.Body.Close() 66 | } 67 | }() 68 | return nil, ctx.Err() 69 | case r := <-result: 70 | var err error 71 | resp, err = r.resp, r.err 72 | if err != nil { 73 | return resp, err 74 | } 75 | } 76 | 77 | c := make(chan struct{}) 78 | go func() { 79 | select { 80 | case <-ctx.Done(): 81 | close(cancel) 82 | case <-c: 83 | // The response's Body is closed. 84 | } 85 | }() 86 | resp.Body = ¬ifyingReader{resp.Body, c} 87 | 88 | return resp, nil 89 | } 90 | 91 | // Get issues a GET request via the Do function. 92 | func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) { 93 | req, err := http.NewRequest("GET", url, nil) 94 | if err != nil { 95 | return nil, err 96 | } 97 | return Do(ctx, client, req) 98 | } 99 | 100 | // Head issues a HEAD request via the Do function. 101 | func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) { 102 | req, err := http.NewRequest("HEAD", url, nil) 103 | if err != nil { 104 | return nil, err 105 | } 106 | return Do(ctx, client, req) 107 | } 108 | 109 | // Post issues a POST request via the Do function. 110 | func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) { 111 | req, err := http.NewRequest("POST", url, body) 112 | if err != nil { 113 | return nil, err 114 | } 115 | req.Header.Set("Content-Type", bodyType) 116 | return Do(ctx, client, req) 117 | } 118 | 119 | // PostForm issues a POST request via the Do function. 120 | func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) { 121 | return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) 122 | } 123 | 124 | // notifyingReader is an io.ReadCloser that closes the notify channel after 125 | // Close is called or a Read fails on the underlying ReadCloser. 126 | type notifyingReader struct { 127 | io.ReadCloser 128 | notify chan<- struct{} 129 | } 130 | 131 | func (r *notifyingReader) Read(p []byte) (int, error) { 132 | n, err := r.ReadCloser.Read(p) 133 | if err != nil && r.notify != nil { 134 | close(r.notify) 135 | r.notify = nil 136 | } 137 | return n, err 138 | } 139 | 140 | func (r *notifyingReader) Close() error { 141 | err := r.ReadCloser.Close() 142 | if r.notify != nil { 143 | close(r.notify) 144 | r.notify = nil 145 | } 146 | return err 147 | } 148 | -------------------------------------------------------------------------------- /vendor/github.com/syndtr/goleveldb/leveldb/iterator/array_iter.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, Suryandaru Triandana 2 | // All rights reserved. 3 | // 4 | // Use of this source code is governed by a BSD-style license that can be 5 | // found in the LICENSE file. 6 | 7 | package iterator 8 | 9 | import ( 10 | "github.com/syndtr/goleveldb/leveldb/util" 11 | ) 12 | 13 | // BasicArray is the interface that wraps basic Len and Search method. 14 | type BasicArray interface { 15 | // Len returns length of the array. 16 | Len() int 17 | 18 | // Search finds smallest index that point to a key that is greater 19 | // than or equal to the given key. 20 | Search(key []byte) int 21 | } 22 | 23 | // Array is the interface that wraps BasicArray and basic Index method. 24 | type Array interface { 25 | BasicArray 26 | 27 | // Index returns key/value pair with index of i. 28 | Index(i int) (key, value []byte) 29 | } 30 | 31 | // Array is the interface that wraps BasicArray and basic Get method. 32 | type ArrayIndexer interface { 33 | BasicArray 34 | 35 | // Get returns a new data iterator with index of i. 36 | Get(i int) Iterator 37 | } 38 | 39 | type basicArrayIterator struct { 40 | util.BasicReleaser 41 | array BasicArray 42 | pos int 43 | err error 44 | } 45 | 46 | func (i *basicArrayIterator) Valid() bool { 47 | return i.pos >= 0 && i.pos < i.array.Len() && !i.Released() 48 | } 49 | 50 | func (i *basicArrayIterator) First() bool { 51 | if i.Released() { 52 | i.err = ErrIterReleased 53 | return false 54 | } 55 | 56 | if i.array.Len() == 0 { 57 | i.pos = -1 58 | return false 59 | } 60 | i.pos = 0 61 | return true 62 | } 63 | 64 | func (i *basicArrayIterator) Last() bool { 65 | if i.Released() { 66 | i.err = ErrIterReleased 67 | return false 68 | } 69 | 70 | n := i.array.Len() 71 | if n == 0 { 72 | i.pos = 0 73 | return false 74 | } 75 | i.pos = n - 1 76 | return true 77 | } 78 | 79 | func (i *basicArrayIterator) Seek(key []byte) bool { 80 | if i.Released() { 81 | i.err = ErrIterReleased 82 | return false 83 | } 84 | 85 | n := i.array.Len() 86 | if n == 0 { 87 | i.pos = 0 88 | return false 89 | } 90 | i.pos = i.array.Search(key) 91 | if i.pos >= n { 92 | return false 93 | } 94 | return true 95 | } 96 | 97 | func (i *basicArrayIterator) Next() bool { 98 | if i.Released() { 99 | i.err = ErrIterReleased 100 | return false 101 | } 102 | 103 | i.pos++ 104 | if n := i.array.Len(); i.pos >= n { 105 | i.pos = n 106 | return false 107 | } 108 | return true 109 | } 110 | 111 | func (i *basicArrayIterator) Prev() bool { 112 | if i.Released() { 113 | i.err = ErrIterReleased 114 | return false 115 | } 116 | 117 | i.pos-- 118 | if i.pos < 0 { 119 | i.pos = -1 120 | return false 121 | } 122 | return true 123 | } 124 | 125 | func (i *basicArrayIterator) Error() error { return i.err } 126 | 127 | type arrayIterator struct { 128 | basicArrayIterator 129 | array Array 130 | pos int 131 | key, value []byte 132 | } 133 | 134 | func (i *arrayIterator) updateKV() { 135 | if i.pos == i.basicArrayIterator.pos { 136 | return 137 | } 138 | i.pos = i.basicArrayIterator.pos 139 | if i.Valid() { 140 | i.key, i.value = i.array.Index(i.pos) 141 | } else { 142 | i.key = nil 143 | i.value = nil 144 | } 145 | } 146 | 147 | func (i *arrayIterator) Key() []byte { 148 | i.updateKV() 149 | return i.key 150 | } 151 | 152 | func (i *arrayIterator) Value() []byte { 153 | i.updateKV() 154 | return i.value 155 | } 156 | 157 | type arrayIteratorIndexer struct { 158 | basicArrayIterator 159 | array ArrayIndexer 160 | } 161 | 162 | func (i *arrayIteratorIndexer) Get() Iterator { 163 | if i.Valid() { 164 | return i.array.Get(i.basicArrayIterator.pos) 165 | } 166 | return nil 167 | } 168 | 169 | // NewArrayIterator returns an iterator from the given array. 170 | func NewArrayIterator(array Array) Iterator { 171 | return &arrayIterator{ 172 | basicArrayIterator: basicArrayIterator{array: array, pos: -1}, 173 | array: array, 174 | pos: -1, 175 | } 176 | } 177 | 178 | // NewArrayIndexer returns an index iterator from the given array. 179 | func NewArrayIndexer(array ArrayIndexer) IteratorIndexer { 180 | return &arrayIteratorIndexer{ 181 | basicArrayIterator: basicArrayIterator{array: array, pos: -1}, 182 | array: array, 183 | } 184 | } 185 | --------------------------------------------------------------------------------