From dea631bedca9f24c86cd4b3ce56f27c917c3382c Mon Sep 17 00:00:00 2001 From: bergquist Date: Tue, 24 Oct 2017 14:09:39 +0200 Subject: [PATCH] tech: remove rabbitmq event publisher closes #9645 --- conf/defaults.ini | 7 - conf/sample.ini | 6 - docs/sources/http_api/admin.md | 5 - pkg/cmd/grafana-server/server.go | 2 - pkg/services/eventpublisher/eventpublisher.go | 150 - vendor/github.com/streadway/amqp/.gitignore | 3 - vendor/github.com/streadway/amqp/.travis.yml | 13 - vendor/github.com/streadway/amqp/LICENSE | 23 - vendor/github.com/streadway/amqp/README.md | 76 - vendor/github.com/streadway/amqp/allocator.go | 106 - .../streadway/amqp/allocator_test.go | 90 - vendor/github.com/streadway/amqp/auth.go | 44 - vendor/github.com/streadway/amqp/certs.sh | 159 - vendor/github.com/streadway/amqp/channel.go | 1589 -------- .../github.com/streadway/amqp/client_test.go | 559 --- .../github.com/streadway/amqp/connection.go | 764 ---- vendor/github.com/streadway/amqp/consumers.go | 118 - vendor/github.com/streadway/amqp/delivery.go | 173 - .../streadway/amqp/delivery_test.go | 33 - vendor/github.com/streadway/amqp/doc.go | 108 - .../streadway/amqp/examples_test.go | 395 -- vendor/github.com/streadway/amqp/gen.sh | 2 - .../streadway/amqp/integration_test.go | 1772 --------- vendor/github.com/streadway/amqp/read.go | 444 --- .../streadway/amqp/reconnect_test.go | 113 - vendor/github.com/streadway/amqp/return.go | 64 - .../github.com/streadway/amqp/shared_test.go | 71 - .../amqp/spec/amqp0-9-1.stripped.extended.xml | 537 --- vendor/github.com/streadway/amqp/spec/gen.go | 536 --- vendor/github.com/streadway/amqp/spec091.go | 3306 ----------------- vendor/github.com/streadway/amqp/tls_test.go | 218 -- vendor/github.com/streadway/amqp/types.go | 382 -- vendor/github.com/streadway/amqp/uri.go | 170 - vendor/github.com/streadway/amqp/uri_test.go | 328 -- vendor/github.com/streadway/amqp/write.go | 411 -- 35 files changed, 12777 deletions(-) delete mode 100644 pkg/services/eventpublisher/eventpublisher.go delete mode 100644 vendor/github.com/streadway/amqp/.gitignore delete mode 100644 vendor/github.com/streadway/amqp/.travis.yml delete mode 100644 vendor/github.com/streadway/amqp/LICENSE delete mode 100644 vendor/github.com/streadway/amqp/README.md delete mode 100644 vendor/github.com/streadway/amqp/allocator.go delete mode 100644 vendor/github.com/streadway/amqp/allocator_test.go delete mode 100644 vendor/github.com/streadway/amqp/auth.go delete mode 100644 vendor/github.com/streadway/amqp/certs.sh delete mode 100644 vendor/github.com/streadway/amqp/channel.go delete mode 100644 vendor/github.com/streadway/amqp/client_test.go delete mode 100644 vendor/github.com/streadway/amqp/connection.go delete mode 100644 vendor/github.com/streadway/amqp/consumers.go delete mode 100644 vendor/github.com/streadway/amqp/delivery.go delete mode 100644 vendor/github.com/streadway/amqp/delivery_test.go delete mode 100644 vendor/github.com/streadway/amqp/doc.go delete mode 100644 vendor/github.com/streadway/amqp/examples_test.go delete mode 100644 vendor/github.com/streadway/amqp/gen.sh delete mode 100644 vendor/github.com/streadway/amqp/integration_test.go delete mode 100644 vendor/github.com/streadway/amqp/read.go delete mode 100644 vendor/github.com/streadway/amqp/reconnect_test.go delete mode 100644 vendor/github.com/streadway/amqp/return.go delete mode 100644 vendor/github.com/streadway/amqp/shared_test.go delete mode 100644 vendor/github.com/streadway/amqp/spec/amqp0-9-1.stripped.extended.xml delete mode 100644 vendor/github.com/streadway/amqp/spec/gen.go delete mode 100644 vendor/github.com/streadway/amqp/spec091.go delete mode 100644 vendor/github.com/streadway/amqp/tls_test.go delete mode 100644 vendor/github.com/streadway/amqp/types.go delete mode 100644 vendor/github.com/streadway/amqp/uri.go delete mode 100644 vendor/github.com/streadway/amqp/uri_test.go delete mode 100644 vendor/github.com/streadway/amqp/write.go diff --git a/conf/defaults.ini b/conf/defaults.ini index 14e77449241..404a7950bf3 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -381,13 +381,6 @@ facility = # Syslog tag. By default, the process' argv[0] is used. tag = - -#################################### AMQP Event Publisher ################ -[event_publisher] -enabled = false -rabbitmq_url = amqp://localhost/ -exchange = grafana_events - #################################### Dashboard JSON files ################ [dashboards.json] enabled = false diff --git a/conf/sample.ini b/conf/sample.ini index 1aedfbf6532..c7d2d1d2695 100644 --- a/conf/sample.ini +++ b/conf/sample.ini @@ -360,12 +360,6 @@ ;tag = -#################################### AMQP Event Publisher ########################## -[event_publisher] -;enabled = false -;rabbitmq_url = amqp://localhost/ -;exchange = grafana_events - ;#################################### Dashboard JSON files ########################## [dashboards.json] ;enabled = false diff --git a/docs/sources/http_api/admin.md b/docs/sources/http_api/admin.md index 3ef5fb1136a..716246102bc 100644 --- a/docs/sources/http_api/admin.md +++ b/docs/sources/http_api/admin.md @@ -102,11 +102,6 @@ Content-Type: application/json "templates_pattern":"emails/*.html", "welcome_email_on_sign_up":"false" }, - "event_publisher":{ - "enabled":"false", - "exchange":"grafana_events", - "rabbitmq_url":"amqp://localhost/" - }, "log":{ "buffer_len":"10000", "level":"Info", diff --git a/pkg/cmd/grafana-server/server.go b/pkg/cmd/grafana-server/server.go index f6a94ac6ef0..4bbabbe3273 100644 --- a/pkg/cmd/grafana-server/server.go +++ b/pkg/cmd/grafana-server/server.go @@ -19,7 +19,6 @@ import ( "github.com/grafana/grafana/pkg/plugins" "github.com/grafana/grafana/pkg/services/alerting" "github.com/grafana/grafana/pkg/services/cleanup" - "github.com/grafana/grafana/pkg/services/eventpublisher" "github.com/grafana/grafana/pkg/services/notifications" "github.com/grafana/grafana/pkg/services/search" "github.com/grafana/grafana/pkg/setting" @@ -59,7 +58,6 @@ func (g *GrafanaServerImpl) Start() { search.Init() login.Init() social.NewOAuthService() - eventpublisher.Init() plugins.Init() closer, err := tracing.Init(setting.Cfg) diff --git a/pkg/services/eventpublisher/eventpublisher.go b/pkg/services/eventpublisher/eventpublisher.go deleted file mode 100644 index 2854b63a9a5..00000000000 --- a/pkg/services/eventpublisher/eventpublisher.go +++ /dev/null @@ -1,150 +0,0 @@ -package eventpublisher - -import ( - "encoding/json" - "fmt" - "log" - "time" - - "github.com/grafana/grafana/pkg/bus" - "github.com/grafana/grafana/pkg/events" - "github.com/grafana/grafana/pkg/setting" - "github.com/streadway/amqp" -) - -var ( - url string - exchange string - conn *amqp.Connection - channel *amqp.Channel -) - -func getConnection() (*amqp.Connection, error) { - c, err := amqp.Dial(url) - if err != nil { - return nil, err - } - return c, err -} - -func getChannel() (*amqp.Channel, error) { - ch, err := conn.Channel() - if err != nil { - return nil, err - } - - err = ch.ExchangeDeclare( - exchange, // name - "topic", // type - true, // durable - false, // auto-deleted - false, // internal - false, // no-wait - nil, // arguments - ) - if err != nil { - return nil, err - } - return ch, err -} - -func Init() { - sec := setting.Cfg.Section("event_publisher") - - if !sec.Key("enabled").MustBool(false) { - return - } - - url = sec.Key("rabbitmq_url").String() - exchange = sec.Key("exchange").String() - bus.AddWildcardListener(eventListener) - - if err := Setup(); err != nil { - log.Fatal(4, "Failed to connect to notification queue: %v", err) - return - } -} - -// Every connection should declare the topology they expect -func Setup() error { - c, err := getConnection() - if err != nil { - return err - } - conn = c - ch, err := getChannel() - if err != nil { - return err - } - - channel = ch - - // listen for close events so we can reconnect. - errChan := channel.NotifyClose(make(chan *amqp.Error)) - go func() { - for e := range errChan { - fmt.Println("connection to rabbitmq lost.") - fmt.Println(e) - fmt.Println("attempting to create new rabbitmq channel.") - ch, err := getChannel() - if err == nil { - channel = ch - break - } - - //could not create channel, so lets close the connection - // and re-create. - _ = conn.Close() - - for err != nil { - time.Sleep(2 * time.Second) - fmt.Println("attempting to reconnect to rabbitmq.") - err = Setup() - } - fmt.Println("Connected to rabbitmq again.") - } - }() - - return nil -} - -func publish(routingKey string, msgString []byte) { - for { - err := channel.Publish( - exchange, //exchange - routingKey, // routing key - false, // mandatory - false, // immediate - amqp.Publishing{ - ContentType: "application/json", - Body: msgString, - }, - ) - if err == nil { - return - } - // failures are most likely because the connection was lost. - // the connection will be re-established, so just keep - // retrying every 2seconds until we successfully publish. - time.Sleep(2 * time.Second) - fmt.Println("publish failed, retrying.") - } -} - -func eventListener(event interface{}) error { - wireEvent, err := events.ToOnWriteEvent(event) - if err != nil { - return err - } - - msgString, err := json.Marshal(wireEvent) - if err != nil { - return err - } - - routingKey := fmt.Sprintf("%s.%s", wireEvent.Priority, wireEvent.EventType) - // this is run in a greenthread and we expect that publish will keep - // retrying until the message gets sent. - go publish(routingKey, msgString) - return nil -} diff --git a/vendor/github.com/streadway/amqp/.gitignore b/vendor/github.com/streadway/amqp/.gitignore deleted file mode 100644 index 58b0e8f326f..00000000000 --- a/vendor/github.com/streadway/amqp/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -spec/spec -examples/simple-consumer/simple-consumer -examples/simple-producer/simple-producer diff --git a/vendor/github.com/streadway/amqp/.travis.yml b/vendor/github.com/streadway/amqp/.travis.yml deleted file mode 100644 index f3e3708d4d0..00000000000 --- a/vendor/github.com/streadway/amqp/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: go - -go: - - 1.1 - - tip - -services: - - rabbitmq - -env: - - AMQP_URL=amqp://guest:guest@127.0.0.1:5672/ GOMAXPROCS=2 - -script: go test -tags integration ./... diff --git a/vendor/github.com/streadway/amqp/LICENSE b/vendor/github.com/streadway/amqp/LICENSE deleted file mode 100644 index 243c0ce7c00..00000000000 --- a/vendor/github.com/streadway/amqp/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this -list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/streadway/amqp/README.md b/vendor/github.com/streadway/amqp/README.md deleted file mode 100644 index 4949ac99218..00000000000 --- a/vendor/github.com/streadway/amqp/README.md +++ /dev/null @@ -1,76 +0,0 @@ -# AMQP - -AMQP 0.9.1 client with RabbitMQ extensions in Go. - -# Status - -*Beta* - -[![Build Status](https://secure.travis-ci.org/streadway/amqp.png)](http://travis-ci.org/streadway/amqp) - -API changes unlikely and will be discussed on [Github -issues](https://github.com/streadway/amqp/issues) along with any bugs or -enhancements. - -# Goals - -Provide an functional interface that closely represents the AMQP 0.9.1 model -targeted to RabbitMQ as a server. This includes the minimum necessary to -interact the semantics of the protocol. - -# Non-goals - -Things not intended to be supported. - - * Auto reconnect and re-synchronization of client and server topologies. - * Reconnection would require understanding the error paths when the - topology cannot be declared on reconnect. This would require a new set - of types and code paths that are best suited at the call-site of this - package. AMQP has a dynamic topology that needs all peers to agree. If - this doesn't happen, the behavior is undefined. Instead of producing a - possible interface with undefined behavior, this package is designed to - be simple for the caller to implement the necessary connection-time - topology declaration so that reconnection is trivial and encapsulated in - the caller's application code. - * AMQP Protocol negotiation for forward or backward compatibility. - * 0.9.1 is stable and widely deployed. Versions 0.10 and 1.0 are divergent - specifications that change the semantics and wire format of the protocol. - We will accept patches for other protocol support but have no plans for - implementation ourselves. - * Anything other than PLAIN and EXTERNAL authentication mechanisms. - * Keeping the mechanisms interface modular makes it possible to extend - outside of this package. If other mechanisms prove to be popular, then - we would accept patches to include them in this pacakge. - -# Usage - -See the 'examples' subdirectory for simple producers and consumers executables. -If you have a use-case in mind which isn't well-represented by the examples, -please file an issue. - -# Documentation - -Use [Godoc documentation](http://godoc.org/github.com/streadway/amqp) for -reference and usage. - -[RabbitMQ tutorials in -Go](https://github.com/rabbitmq/rabbitmq-tutorials/tree/master/go) are also -available. - -# Contributing - -Pull requests are very much welcomed. Create your pull request on a non-master -branch, make sure a test or example is included that covers your change and -your commits represent coherent changes that include a reason for the change. - -To run the integration tests, make sure you have RabbitMQ running on any host, -export the environment variable `AMQP_URL=amqp://host/` and run `go test -tags -integration`. TravisCI will also run the integration tests. - -Thanks to the [community of contributors](https://github.com/streadway/amqp/graphs/contributors). - -# License - -BSD 2 clause - see LICENSE for more details. - - diff --git a/vendor/github.com/streadway/amqp/allocator.go b/vendor/github.com/streadway/amqp/allocator.go deleted file mode 100644 index 92841882620..00000000000 --- a/vendor/github.com/streadway/amqp/allocator.go +++ /dev/null @@ -1,106 +0,0 @@ -package amqp - -import ( - "bytes" - "fmt" - "math/big" -) - -const ( - free = 0 - allocated = 1 -) - -// allocator maintains a bitset of allocated numbers. -type allocator struct { - pool *big.Int - last int - low int - high int -} - -// NewAllocator reserves and frees integers out of a range between low and -// high. -// -// O(N) worst case space used, where N is maximum allocated, divided by -// sizeof(big.Word) -func newAllocator(low, high int) *allocator { - return &allocator{ - pool: big.NewInt(0), - last: low, - low: low, - high: high, - } -} - -// String returns a string describing the contents of the allocator like -// "allocator[low..high] reserved..until" -// -// O(N) where N is high-low -func (a allocator) String() string { - b := &bytes.Buffer{} - fmt.Fprintf(b, "allocator[%d..%d]", a.low, a.high) - - for low := a.low; low <= a.high; low++ { - high := low - for a.reserved(high) && high <= a.high { - high++ - } - - if high > low+1 { - fmt.Fprintf(b, " %d..%d", low, high-1) - } else if high > low { - fmt.Fprintf(b, " %d", high-1) - } - - low = high - } - return b.String() -} - -// Next reserves and returns the next available number out of the range between -// low and high. If no number is available, false is returned. -// -// O(N) worst case runtime where N is allocated, but usually O(1) due to a -// rolling index into the oldest allocation. -func (a *allocator) next() (int, bool) { - wrapped := a.last - - // Find trailing bit - for ; a.last <= a.high; a.last++ { - if a.reserve(a.last) { - return a.last, true - } - } - - // Find preceeding free'd pool - a.last = a.low - - for ; a.last < wrapped; a.last++ { - if a.reserve(a.last) { - return a.last, true - } - } - - return 0, false -} - -// reserve claims the bit if it is not already claimed, returning true if -// succesfully claimed. -func (a *allocator) reserve(n int) bool { - if a.reserved(n) { - return false - } - a.pool.SetBit(a.pool, n-a.low, allocated) - return true -} - -// reserved returns true if the integer has been allocated -func (a *allocator) reserved(n int) bool { - return a.pool.Bit(n-a.low) == allocated -} - -// release frees the use of the number for another allocation -func (a *allocator) release(n int) { - a.pool.SetBit(a.pool, n-a.low, free) -} diff --git a/vendor/github.com/streadway/amqp/allocator_test.go b/vendor/github.com/streadway/amqp/allocator_test.go deleted file mode 100644 index 2d6fd5dbaf8..00000000000 --- a/vendor/github.com/streadway/amqp/allocator_test.go +++ /dev/null @@ -1,90 +0,0 @@ -package amqp - -import ( - "math/rand" - "testing" -) - -func TestAllocatorFirstShouldBeTheLow(t *testing.T) { - n, ok := newAllocator(1, 2).next() - if !ok { - t.Fatalf("expected to allocate between 1 and 2") - } - - if want, got := 1, n; want != got { - t.Fatalf("expected to first allocation to be 1") - } -} - -func TestAllocatorShouldBeBoundByHigh(t *testing.T) { - a := newAllocator(1, 2) - - if n, ok := a.next(); n != 1 || !ok { - t.Fatalf("expected to allocate between 1 and 2, got %d, %v", n, ok) - } - if n, ok := a.next(); n != 2 || !ok { - t.Fatalf("expected to allocate between 1 and 2, got %d, %v", n, ok) - } - if _, ok := a.next(); ok { - t.Fatalf("expected not to allocate outside of 1 and 2") - } -} - -func TestAllocatorStringShouldIncludeAllocatedRanges(t *testing.T) { - a := newAllocator(1, 10) - a.reserve(1) - a.reserve(2) - a.reserve(3) - a.reserve(5) - a.reserve(6) - a.reserve(8) - a.reserve(10) - - if want, got := "allocator[1..10] 1..3 5..6 8 10", a.String(); want != got { - t.Fatalf("expected String of %q, got %q", want, got) - } -} - -func TestAllocatorShouldReuseReleased(t *testing.T) { - a := newAllocator(1, 2) - - first, _ := a.next() - if want, got := 1, first; want != got { - t.Fatalf("expected allocation to be %d, got: %d", want, got) - } - - second, _ := a.next() - if want, got := 2, second; want != got { - t.Fatalf("expected allocation to be %d, got: %d", want, got) - } - - a.release(first) - - third, _ := a.next() - if want, got := first, third; want != got { - t.Fatalf("expected third allocation to be %d, got: %d", want, got) - } - - _, ok := a.next() - if want, got := false, ok; want != got { - t.Fatalf("expected fourth allocation to saturate the pool") - } -} - -func TestAllocatorReleasesKeepUpWithAllocationsForAllSizes(t *testing.T) { - const runs = 5 - const max = 13 - - for lim := 1; lim < 2<= lim { // fills the allocator - a.release(int(rand.Int63n(int64(lim)))) - } - if _, ok := a.next(); !ok { - t.Fatalf("expected %d runs of random release of size %d not to fail on allocation %d", runs, lim, i) - } - } - } -} diff --git a/vendor/github.com/streadway/amqp/auth.go b/vendor/github.com/streadway/amqp/auth.go deleted file mode 100644 index bff7d7948ba..00000000000 --- a/vendor/github.com/streadway/amqp/auth.go +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Source code and contact info at http://github.com/streadway/amqp - -package amqp - -import ( - "fmt" -) - -// Authentication interface provides a means for different SASL authentication -// mechanisms to be used during connection tuning. -type Authentication interface { - Mechanism() string - Response() string -} - -// PlainAuth is a similar to Basic Auth in HTTP. -type PlainAuth struct { - Username string - Password string -} - -func (me *PlainAuth) Mechanism() string { - return "PLAIN" -} - -func (me *PlainAuth) Response() string { - return fmt.Sprintf("\000%s\000%s", me.Username, me.Password) -} - -// Finds the first mechanism preferred by the client that the server supports. -func pickSASLMechanism(client []Authentication, serverMechanisms []string) (auth Authentication, ok bool) { - for _, auth = range client { - for _, mech := range serverMechanisms { - if auth.Mechanism() == mech { - return auth, true - } - } - } - - return -} diff --git a/vendor/github.com/streadway/amqp/certs.sh b/vendor/github.com/streadway/amqp/certs.sh deleted file mode 100644 index 834f4224270..00000000000 --- a/vendor/github.com/streadway/amqp/certs.sh +++ /dev/null @@ -1,159 +0,0 @@ -#!/bin/sh -# -# Creates the CA, server and client certs to be used by tls_test.go -# http://www.rabbitmq.com/ssl.html -# -# Copy stdout into the const section of tls_test.go or use for RabbitMQ -# -root=$PWD/certs - -if [ -f $root/ca/serial ]; then - echo >&2 "Previous installation found" - echo >&2 "Remove $root/ca and rerun to overwrite" - exit 1 -fi - -mkdir -p $root/ca/private -mkdir -p $root/ca/certs -mkdir -p $root/server -mkdir -p $root/client - -cd $root/ca - -chmod 700 private -touch index.txt -echo 'unique_subject = no' > index.txt.attr -echo '01' > serial -echo >openssl.cnf ' -[ ca ] -default_ca = testca - -[ testca ] -dir = . -certificate = $dir/cacert.pem -database = $dir/index.txt -new_certs_dir = $dir/certs -private_key = $dir/private/cakey.pem -serial = $dir/serial - -default_crl_days = 7 -default_days = 3650 -default_md = sha1 - -policy = testca_policy -x509_extensions = certificate_extensions - -[ testca_policy ] -commonName = supplied -stateOrProvinceName = optional -countryName = optional -emailAddress = optional -organizationName = optional -organizationalUnitName = optional - -[ certificate_extensions ] -basicConstraints = CA:false - -[ req ] -default_bits = 2048 -default_keyfile = ./private/cakey.pem -default_md = sha1 -prompt = yes -distinguished_name = root_ca_distinguished_name -x509_extensions = root_ca_extensions - -[ root_ca_distinguished_name ] -commonName = hostname - -[ root_ca_extensions ] -basicConstraints = CA:true -keyUsage = keyCertSign, cRLSign - -[ client_ca_extensions ] -basicConstraints = CA:false -keyUsage = digitalSignature -extendedKeyUsage = 1.3.6.1.5.5.7.3.2 - -[ server_ca_extensions ] -basicConstraints = CA:false -keyUsage = keyEncipherment -extendedKeyUsage = 1.3.6.1.5.5.7.3.1 -subjectAltName = @alt_names - -[ alt_names ] -IP.1 = 127.0.0.1 -' - -openssl req \ - -x509 \ - -nodes \ - -config openssl.cnf \ - -newkey rsa:2048 \ - -days 3650 \ - -subj "/CN=MyTestCA/" \ - -out cacert.pem \ - -outform PEM - -openssl x509 \ - -in cacert.pem \ - -out cacert.cer \ - -outform DER - -openssl genrsa -out $root/server/key.pem 2048 -openssl genrsa -out $root/client/key.pem 2048 - -openssl req \ - -new \ - -nodes \ - -config openssl.cnf \ - -subj "/CN=127.0.0.1/O=server/" \ - -key $root/server/key.pem \ - -out $root/server/req.pem \ - -outform PEM - -openssl req \ - -new \ - -nodes \ - -config openssl.cnf \ - -subj "/CN=127.0.0.1/O=client/" \ - -key $root/client/key.pem \ - -out $root/client/req.pem \ - -outform PEM - -openssl ca \ - -config openssl.cnf \ - -in $root/server/req.pem \ - -out $root/server/cert.pem \ - -notext \ - -batch \ - -extensions server_ca_extensions - -openssl ca \ - -config openssl.cnf \ - -in $root/client/req.pem \ - -out $root/client/cert.pem \ - -notext \ - -batch \ - -extensions client_ca_extensions - -cat <<-END -const caCert = \` -`cat $root/ca/cacert.pem` -\` - -const serverCert = \` -`cat $root/server/cert.pem` -\` - -const serverKey = \` -`cat $root/server/key.pem` -\` - -const clientCert = \` -`cat $root/client/cert.pem` -\` - -const clientKey = \` -`cat $root/client/key.pem` -\` -END diff --git a/vendor/github.com/streadway/amqp/channel.go b/vendor/github.com/streadway/amqp/channel.go deleted file mode 100644 index f8710c6c706..00000000000 --- a/vendor/github.com/streadway/amqp/channel.go +++ /dev/null @@ -1,1589 +0,0 @@ -// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Source code and contact info at http://github.com/streadway/amqp - -package amqp - -import ( - "container/heap" - "reflect" - "sync" -) - -// 0 1 3 7 size+7 size+8 -// +------+---------+-------------+ +------------+ +-----------+ -// | type | channel | size | | payload | | frame-end | -// +------+---------+-------------+ +------------+ +-----------+ -// octet short long size octets octet -const frameHeaderSize = 1 + 2 + 4 + 1 - -/* -Channel represents an AMQP channel. Used as a context for valid message -exchange. Errors on methods with this Channel as a receiver means this channel -should be discarded and a new channel established. - -*/ -type Channel struct { - destructor sync.Once - sendM sync.Mutex // sequence channel frames - m sync.Mutex // struct field mutex - - connection *Connection - - rpc chan message - consumers *consumers - - id uint16 - - // true when we will never notify again - noNotify bool - - // Channel and Connection exceptions will be broadcast on these listeners. - closes []chan *Error - - // Listeners for active=true flow control. When true is sent to a listener, - // publishing should pause until false is sent to listeners. - flows []chan bool - - // Listeners for returned publishings for unroutable messages on mandatory - // publishings or undeliverable messages on immediate publishings. - returns []chan Return - - // Listeners for when the server notifies the client that - // a consumer has been cancelled. - cancels []chan string - - // Listeners for Acks/Nacks when the channel is in Confirm mode - // the value is the sequentially increasing delivery tag - // starting at 1 immediately after the Confirm - acks []chan uint64 - nacks []chan uint64 - - // When in confirm mode, track publish counter and order confirms - confirms tagSet - publishCounter uint64 - - // Selects on any errors from shutdown during RPC - errors chan *Error - - // State machine that manages frame order, must only be mutated by the connection - recv func(*Channel, frame) error - - // State that manages the send behavior after before and after shutdown, must - // only be mutated in shutdown() - send func(*Channel, message) error - - // Current state for frame re-assembly, only mutated from recv - message messageWithContent - header *headerFrame - body []byte -} - -// Constructs a new channel with the given framing rules -func newChannel(c *Connection, id uint16) *Channel { - return &Channel{ - connection: c, - id: id, - rpc: make(chan message), - consumers: makeConsumers(), - recv: (*Channel).recvMethod, - send: (*Channel).sendOpen, - errors: make(chan *Error, 1), - } -} - -// shutdown is called by Connection after the channel has been removed from the -// connection registry. -func (me *Channel) shutdown(e *Error) { - me.destructor.Do(func() { - me.m.Lock() - defer me.m.Unlock() - - // Broadcast abnormal shutdown - if e != nil { - for _, c := range me.closes { - c <- e - } - } - - me.send = (*Channel).sendClosed - - // Notify RPC if we're selecting - if e != nil { - me.errors <- e - } - - me.consumers.closeAll() - - for _, c := range me.closes { - close(c) - } - - for _, c := range me.flows { - close(c) - } - - for _, c := range me.returns { - close(c) - } - - for _, c := range me.cancels { - close(c) - } - - // A seen map to keep from double closing the ack and nacks. the other - // channels are different types and are not shared - seen := make(map[chan uint64]bool) - - for _, c := range me.acks { - if !seen[c] { - close(c) - seen[c] = true - } - } - - for _, c := range me.nacks { - if !seen[c] { - close(c) - seen[c] = true - } - } - - me.noNotify = true - }) -} - -func (me *Channel) open() error { - return me.call(&channelOpen{}, &channelOpenOk{}) -} - -// Performs a request/response call for when the message is not NoWait and is -// specified as Synchronous. -func (me *Channel) call(req message, res ...message) error { - if err := me.send(me, req); err != nil { - return err - } - - if req.wait() { - select { - case e := <-me.errors: - return e - - case msg := <-me.rpc: - if msg != nil { - for _, try := range res { - if reflect.TypeOf(msg) == reflect.TypeOf(try) { - // *res = *msg - vres := reflect.ValueOf(try).Elem() - vmsg := reflect.ValueOf(msg).Elem() - vres.Set(vmsg) - return nil - } - } - return ErrCommandInvalid - } else { - // RPC channel has been closed without an error, likely due to a hard - // error on the Connection. This indicates we have already been - // shutdown and if were waiting, will have returned from the errors chan. - return ErrClosed - } - } - } - - return nil -} - -func (me *Channel) sendClosed(msg message) (err error) { - me.sendM.Lock() - defer me.sendM.Unlock() - - // After a 'channel.close' is sent or received the only valid response is - // channel.close-ok - if _, ok := msg.(*channelCloseOk); ok { - return me.connection.send(&methodFrame{ - ChannelId: me.id, - Method: msg, - }) - } - - return ErrClosed -} - -func (me *Channel) sendOpen(msg message) (err error) { - me.sendM.Lock() - defer me.sendM.Unlock() - - if content, ok := msg.(messageWithContent); ok { - props, body := content.getContent() - class, _ := content.id() - size := me.connection.Config.FrameSize - frameHeaderSize - - if err = me.connection.send(&methodFrame{ - ChannelId: me.id, - Method: content, - }); err != nil { - return - } - - if err = me.connection.send(&headerFrame{ - ChannelId: me.id, - ClassId: class, - Size: uint64(len(body)), - Properties: props, - }); err != nil { - return - } - - for i, j := 0, size; i < len(body); i, j = j, j+size { - if j > len(body) { - j = len(body) - } - - if err = me.connection.send(&bodyFrame{ - ChannelId: me.id, - Body: body[i:j], - }); err != nil { - return - } - } - } else { - err = me.connection.send(&methodFrame{ - ChannelId: me.id, - Method: msg, - }) - } - - return -} - -// Eventually called via the state machine from the connection's reader -// goroutine, so assumes serialized access. -func (me *Channel) dispatch(msg message) { - switch m := msg.(type) { - case *channelClose: - me.connection.closeChannel(me, newError(m.ReplyCode, m.ReplyText)) - me.send(me, &channelCloseOk{}) - - case *channelFlow: - for _, c := range me.flows { - c <- m.Active - } - me.send(me, &channelFlowOk{Active: m.Active}) - - case *basicCancel: - for _, c := range me.cancels { - c <- m.ConsumerTag - } - me.send(me, &basicCancelOk{ConsumerTag: m.ConsumerTag}) - - case *basicReturn: - ret := newReturn(*m) - for _, c := range me.returns { - c <- *ret - } - - case *basicAck: - if m.Multiple { - me.confimMultiple(m.DeliveryTag, me.acks) - } else { - me.confimOne(m.DeliveryTag, me.acks) - } - - case *basicNack: - if m.Multiple { - me.confimMultiple(m.DeliveryTag, me.nacks) - } else { - me.confimOne(m.DeliveryTag, me.nacks) - } - - case *basicDeliver: - me.consumers.send(m.ConsumerTag, newDelivery(me, m)) - // TODO log failed consumer and close channel, this can happen when - // deliveries are in flight and a no-wait cancel has happened - - default: - me.rpc <- msg - } -} - -func (me *Channel) transition(f func(*Channel, frame) error) error { - me.recv = f - return nil -} - -func (me *Channel) recvMethod(f frame) error { - switch frame := f.(type) { - case *methodFrame: - if msg, ok := frame.Method.(messageWithContent); ok { - me.body = make([]byte, 0) - me.message = msg - return me.transition((*Channel).recvHeader) - } - - me.dispatch(frame.Method) // termination state - return me.transition((*Channel).recvMethod) - - case *headerFrame: - // drop - return me.transition((*Channel).recvMethod) - - case *bodyFrame: - // drop - return me.transition((*Channel).recvMethod) - - default: - panic("unexpected frame type") - } - - panic("unreachable") -} - -func (me *Channel) recvHeader(f frame) error { - switch frame := f.(type) { - case *methodFrame: - // interrupt content and handle method - return me.recvMethod(f) - - case *headerFrame: - // start collecting if we expect body frames - me.header = frame - - if frame.Size == 0 { - me.message.setContent(me.header.Properties, me.body) - me.dispatch(me.message) // termination state - return me.transition((*Channel).recvMethod) - } else { - return me.transition((*Channel).recvContent) - } - - case *bodyFrame: - // drop and reset - return me.transition((*Channel).recvMethod) - - default: - panic("unexpected frame type") - } - - panic("unreachable") -} - -// state after method + header and before the length -// defined by the header has been reached -func (me *Channel) recvContent(f frame) error { - switch frame := f.(type) { - case *methodFrame: - // interrupt content and handle method - return me.recvMethod(f) - - case *headerFrame: - // drop and reset - return me.transition((*Channel).recvMethod) - - case *bodyFrame: - me.body = append(me.body, frame.Body...) - - if uint64(len(me.body)) >= me.header.Size { - me.message.setContent(me.header.Properties, me.body) - me.dispatch(me.message) // termination state - return me.transition((*Channel).recvMethod) - } - - return me.transition((*Channel).recvContent) - - default: - panic("unexpected frame type") - } - - panic("unreachable") -} - -/* -Close initiate a clean channel closure by sending a close message with the error -code set to '200'. - -It is safe to call this method multiple times. - -*/ -func (me *Channel) Close() error { - defer me.connection.closeChannel(me, nil) - return me.call( - &channelClose{ReplyCode: replySuccess}, - &channelCloseOk{}, - ) -} - -/* -NotifyClose registers a listener for when the server sends a channel or -connection exception in the form of a Connection.Close or Channel.Close method. -Connection exceptions will be broadcast to all open channels and all channels -will be closed, where channel exceptions will only be broadcast to listeners to -this channel. - -The chan provided will be closed when the Channel is closed and on a -graceful close, no error will be sent. - -*/ -func (me *Channel) NotifyClose(c chan *Error) chan *Error { - me.m.Lock() - defer me.m.Unlock() - - if me.noNotify { - close(c) - } else { - me.closes = append(me.closes, c) - } - - return c -} - -/* -NotifyFlow registers a listener for basic.flow methods sent by the server. -When `true` is sent on one of the listener channels, all publishers should -pause until a `false` is sent. - -The server may ask the producer to pause or restart the flow of Publishings -sent by on a channel. This is a simple flow-control mechanism that a server can -use to avoid overflowing its queues or otherwise finding itself receiving more -messages than it can process. Note that this method is not intended for window -control. It does not affect contents returned by basic.get-ok methods. - -When a new channel is opened, it is active (flow is active). Some -applications assume that channels are inactive until started. To emulate -this behavior a client MAY open the channel, then pause it. - -Publishers should respond to a flow messages as rapidly as possible and the -server may disconnect over producing channels that do not respect these -messages. - -basic.flow-ok methods will always be returned to the server regardless of -the number of listeners there are. - -To control the flow of deliveries from the server. Use the Channel.Flow() -method instead. - -Note: RabbitMQ will rather use TCP pushback on the network connection instead -of sending basic.flow. This means that if a single channel is producing too -much on the same connection, all channels using that connection will suffer, -including acknowledgments from deliveries. Use different Connections if you -desire to interleave consumers and producers in the same process to avoid your -basic.ack messages from getting rate limited with your basic.publish messages. - -*/ -func (me *Channel) NotifyFlow(c chan bool) chan bool { - me.m.Lock() - defer me.m.Unlock() - - if me.noNotify { - close(c) - } else { - me.flows = append(me.flows, c) - } - - return c -} - -/* -NotifyReturn registers a listener for basic.return methods. These can be sent -from the server when a publish is undeliverable either from the mandatory or -immediate flags. - -A return struct has a copy of the Publishing along with some error -information about why the publishing failed. - -*/ -func (me *Channel) NotifyReturn(c chan Return) chan Return { - me.m.Lock() - defer me.m.Unlock() - - if me.noNotify { - close(c) - } else { - me.returns = append(me.returns, c) - } - - return c -} - -/* -NotifyCancel registers a listener for basic.cancel methods. These can be sent -from the server when a queue is deleted or when consuming from a mirrored queue -where the master has just failed (and was moved to another node) - -The subscription tag is returned to the listener. - -*/ -func (me *Channel) NotifyCancel(c chan string) chan string { - me.m.Lock() - defer me.m.Unlock() - - if me.noNotify { - close(c) - } else { - me.cancels = append(me.cancels, c) - } - - return c -} - -/* -NotifyConfirm registers a listener chan for reliable publishing to receive -basic.ack and basic.nack messages. These messages will be sent by the server -for every publish after Channel.Confirm has been called. The value sent on -these channels is the sequence number of the publishing. It is up to client of -this channel to maintain the sequence number of each publishing and handle -resends on basic.nack. - -There will be either at most one Ack or Nack delivered for every Publishing. - -Acknowledgments will be received in the order of delivery from the -NotifyConfirm channels even if the server acknowledges them out of order. - -The capacity of the ack and nack channels must be at least as large as the -number of outstanding publishings. Not having enough buffered chans will -create a deadlock if you attempt to perform other operations on the Connection -or Channel while confirms are in-flight. - -It's advisable to wait for all acks or nacks to arrive before calling -Channel.Close(). - -*/ -func (me *Channel) NotifyConfirm(ack, nack chan uint64) (chan uint64, chan uint64) { - me.m.Lock() - defer me.m.Unlock() - - if me.noNotify { - close(ack) - close(nack) - } else { - me.acks = append(me.acks, ack) - me.nacks = append(me.nacks, nack) - } - - return ack, nack -} - -// Since the acknowledgments may come out of order, scan the heap -// until found. In most cases, only the head will be found. -func (me *Channel) confimOne(tag uint64, ch []chan uint64) { - me.m.Lock() - defer me.m.Unlock() - - if me.confirms != nil { - var unacked []uint64 - - for { - // We expect once and only once delivery - next := heap.Pop(&me.confirms).(uint64) - - if next != tag { - unacked = append(unacked, next) - } else { - for _, c := range ch { - c <- tag - } - break - } - } - - for _, pending := range unacked { - heap.Push(&me.confirms, pending) - } - } -} - -// Instead of pushing the pending acknowledgments, deliver them as we should ack -// all up until this tag. -func (me *Channel) confimMultiple(tag uint64, ch []chan uint64) { - me.m.Lock() - defer me.m.Unlock() - - if me.confirms != nil { - for { - // We expect once and only once delivery - next := heap.Pop(&me.confirms).(uint64) - - for _, c := range ch { - c <- next - } - - if next == tag { - break - } - } - } -} - -/* -Qos controls how many messages or how many bytes the server will try to keep on -the network for consumers before receiving delivery acks. The intent of Qos is -to make sure the network buffers stay full between the server and client. - -With a prefetch count greater than zero, the server will deliver that many -messages to consumers before acknowledgments are received. The server ignores -this option when consumers are started with noAck because no acknowledgments -are expected or sent. - -With a prefetch size greater than zero, the server will try to keep at least -that many bytes of deliveries flushed to the network before receiving -acknowledgments from the consumers. This option is ignored when consumers are -started with noAck. - -When global is true, these Qos settings apply to all existing and future -consumers on all channels on the same connection. When false, the Channel.Qos -settings will apply to all existing and future consumers on this channel. -RabbitMQ does not implement the global flag. - -To get round-robin behavior between consumers consuming from the same queue on -different connections, set the prefetch count to 1, and the next available -message on the server will be delivered to the next available consumer. - -If your consumer work time is reasonably is consistent and not much greater -than two times your network round trip time, you will see significant -throughput improvements starting with a prefetch count of 2 or slightly -greater as described by benchmarks on RabbitMQ. - -http://www.rabbitmq.com/blog/2012/04/25/rabbitmq-performance-measurements-part-2/ -*/ -func (me *Channel) Qos(prefetchCount, prefetchSize int, global bool) error { - return me.call( - &basicQos{ - PrefetchCount: uint16(prefetchCount), - PrefetchSize: uint32(prefetchSize), - Global: global, - }, - &basicQosOk{}, - ) -} - -/* -Cancel stops deliveries to the consumer chan established in Channel.Consume and -identified by consumer. - -Only use this method to cleanly stop receiving deliveries from the server and -cleanly shut down the consumer chan identified by this tag. Using this method -and waiting for remaining messages to flush from the consumer chan will ensure -all messages received on the network will be delivered to the receiver of your -consumer chan. - -Continue consuming from the chan Delivery provided by Channel.Consume until the -chan closes. - -When noWait is true, do not wait for the server to acknowledge the cancel. -Only use this when you are certain there are no deliveries requiring -acknowledgment are in-flight otherwise they will arrive and be dropped in the -client without an ack and will not be redelivered to other consumers. - -*/ -func (me *Channel) Cancel(consumer string, noWait bool) error { - req := &basicCancel{ - ConsumerTag: consumer, - NoWait: noWait, - } - res := &basicCancelOk{} - - if err := me.call(req, res); err != nil { - return err - } - - if req.wait() { - me.consumers.close(res.ConsumerTag) - } else { - // Potentially could drop deliveries in flight - me.consumers.close(consumer) - } - - return nil -} - -/* -QueueDeclare declares a queue to hold messages and deliver to consumers. -Declaring creates a queue if it doesn't already exist, or ensures that an -existing queue matches the same parameters. - -Every queue declared gets a default binding to the empty exchange "" which has -the type "direct" with the routing key matching the queue's name. With this -default binding, it is possible to publish messages that route directly to -this queue by publishing to "" with the routing key of the queue name. - - QueueDeclare("alerts", true, false, false false, false, nil) - Publish("", "alerts", false, false, Publishing{Body: []byte("...")}) - - Delivery Exchange Key Queue - ----------------------------------------------- - key: alerts -> "" -> alerts -> alerts - -The queue name may be empty, in which the server will generate a unique name -which will be returned in the Name field of Queue struct. - -Durable and Non-Auto-Deleted queues will survive server restarts and remain -when there are no remaining consumers or bindings. Persistent publishings will -be restored in this queue on server restart. These queues are only able to be -bound to durable exchanges. - -Non-Durable and Auto-Deleted queues will not be redeclared on server restart -and will be deleted by the server after a short time when the last consumer is -canceled or the last consumer's channel is closed. Queues with this lifetime -can also be deleted normally with QueueDelete. These durable queues can only -be bound to non-durable exchanges. - -Non-Durable and Non-Auto-Deleted queues will remain declared as long as the -server is running regardless of how many consumers. This lifetime is useful -for temporary topologies that may have long delays between consumer activity. -These queues can only be bound to non-durable exchanges. - -Durable and Auto-Deleted queues will be restored on server restart, but without -active consumers, will not survive and be removed. This Lifetime is unlikely -to be useful. - -Exclusive queues are only accessible by the connection that declares them and -will be deleted when the connection closes. Channels on other connections -will receive an error when attempting declare, bind, consume, purge or delete a -queue with the same name. - -When noWait is true, the queue will assume to be declared on the server. A -channel exception will arrive if the conditions are met for existing queues -or attempting to modify an existing queue from a different connection. - -When the error return value is not nil, you can assume the queue could not be -declared with these parameters and the channel will be closed. - -*/ -func (me *Channel) QueueDeclare(name string, durable, autoDelete, exclusive, noWait bool, args Table) (Queue, error) { - if err := args.Validate(); err != nil { - return Queue{}, err - } - - req := &queueDeclare{ - Queue: name, - Passive: false, - Durable: durable, - AutoDelete: autoDelete, - Exclusive: exclusive, - NoWait: noWait, - Arguments: args, - } - res := &queueDeclareOk{} - - if err := me.call(req, res); err != nil { - return Queue{}, err - } - - if req.wait() { - return Queue{ - Name: res.Queue, - Messages: int(res.MessageCount), - Consumers: int(res.ConsumerCount), - }, nil - } - - return Queue{ - Name: name, - }, nil - - panic("unreachable") -} - -/* - -QueueDeclarePassive is functionally and parametrically equivalent to -QueueDeclare, except that it sets the "passive" attribute to true. A passive -queue is assumed by RabbitMQ to already exist, and attempting to connect to a -non-existent queue will cause RabbitMQ to throw an exception. This function -can be used to test for the existence of a queue. - -*/ -func (me *Channel) QueueDeclarePassive(name string, durable, autoDelete, exclusive, noWait bool, args Table) (Queue, error) { - if err := args.Validate(); err != nil { - return Queue{}, err - } - - req := &queueDeclare{ - Queue: name, - Passive: true, - Durable: durable, - AutoDelete: autoDelete, - Exclusive: exclusive, - NoWait: noWait, - Arguments: args, - } - res := &queueDeclareOk{} - - if err := me.call(req, res); err != nil { - return Queue{}, err - } - - if req.wait() { - return Queue{ - Name: res.Queue, - Messages: int(res.MessageCount), - Consumers: int(res.ConsumerCount), - }, nil - } - - return Queue{ - Name: name, - }, nil - - panic("unreachable") -} - -/* -QueueInspect passively declares a queue by name to inspect the current message -count, consumer count. - -Use this method to check how many unacknowledged messages reside in the queue -and how many consumers are receiving deliveries and whether a queue by this -name already exists. - -If the queue by this name exists, use Channel.QueueDeclare check if it is -declared with specific parameters. - -If a queue by this name does not exist, an error will be returned and the -channel will be closed. - -*/ -func (me *Channel) QueueInspect(name string) (Queue, error) { - req := &queueDeclare{ - Queue: name, - Passive: true, - } - res := &queueDeclareOk{} - - err := me.call(req, res) - - state := Queue{ - Name: name, - Messages: int(res.MessageCount), - Consumers: int(res.ConsumerCount), - } - - return state, err -} - -/* -QueueBind binds an exchange to a queue so that publishings to the exchange will -be routed to the queue when the publishing routing key matches the binding -routing key. - - QueueBind("pagers", "alert", "log", false, nil) - QueueBind("emails", "info", "log", false, nil) - - Delivery Exchange Key Queue - ----------------------------------------------- - key: alert --> log ----> alert --> pagers - key: info ---> log ----> info ---> emails - key: debug --> log (none) (dropped) - -If a binding with the same key and arguments already exists between the -exchange and queue, the attempt to rebind will be ignored and the existing -binding will be retained. - -In the case that multiple bindings may cause the message to be routed to the -same queue, the server will only route the publishing once. This is possible -with topic exchanges. - - QueueBind("pagers", "alert", "amq.topic", false, nil) - QueueBind("emails", "info", "amq.topic", false, nil) - QueueBind("emails", "#", "amq.topic", false, nil) // match everything - - Delivery Exchange Key Queue - ----------------------------------------------- - key: alert --> amq.topic ----> alert --> pagers - key: info ---> amq.topic ----> # ------> emails - \---> info ---/ - key: debug --> amq.topic ----> # ------> emails - -It is only possible to bind a durable queue to a durable exchange regardless of -whether the queue or exchange is auto-deleted. Bindings between durable queues -and exchanges will also be restored on server restart. - -If the binding could not complete, an error will be returned and the channel -will be closed. - -When noWait is true and the queue could not be bound, the channel will be -closed with an error. - -*/ -func (me *Channel) QueueBind(name, key, exchange string, noWait bool, args Table) error { - if err := args.Validate(); err != nil { - return err - } - - return me.call( - &queueBind{ - Queue: name, - Exchange: exchange, - RoutingKey: key, - NoWait: noWait, - Arguments: args, - }, - &queueBindOk{}, - ) -} - -/* -QueueUnbind removes a binding between an exchange and queue matching the key and -arguments. - -It is possible to send and empty string for the exchange name which means to -unbind the queue from the default exchange. - -*/ -func (me *Channel) QueueUnbind(name, key, exchange string, args Table) error { - if err := args.Validate(); err != nil { - return err - } - - return me.call( - &queueUnbind{ - Queue: name, - Exchange: exchange, - RoutingKey: key, - Arguments: args, - }, - &queueUnbindOk{}, - ) -} - -/* -QueuePurge removes all messages from the named queue which are not waiting to -be acknowledged. Messages that have been delivered but have not yet been -acknowledged will not be removed. - -When successful, returns the number of messages purged. - -If noWait is true, do not wait for the server response and the number of -messages purged will not be meaningful. -*/ -func (me *Channel) QueuePurge(name string, noWait bool) (int, error) { - req := &queuePurge{ - Queue: name, - NoWait: noWait, - } - res := &queuePurgeOk{} - - err := me.call(req, res) - - return int(res.MessageCount), err -} - -/* -QueueDelete removes the queue from the server including all bindings then -purges the messages based on server configuration, returning the number of -messages purged. - -When ifUnused is true, the queue will not be deleted if there are any -consumers on the queue. If there are consumers, an error will be returned and -the channel will be closed. - -When ifEmpty is true, the queue will not be deleted if there are any messages -remaining on the queue. If there are messages, an error will be returned and -the channel will be closed. - -When noWait is true, the queue will be deleted without waiting for a response -from the server. The purged message count will not be meaningful. If the queue -could not be deleted, a channel exception will be raised and the channel will -be closed. - -*/ -func (me *Channel) QueueDelete(name string, ifUnused, ifEmpty, noWait bool) (int, error) { - req := &queueDelete{ - Queue: name, - IfUnused: ifUnused, - IfEmpty: ifEmpty, - NoWait: noWait, - } - res := &queueDeleteOk{} - - err := me.call(req, res) - - return int(res.MessageCount), err -} - -/* -Consume immediately starts delivering queued messages. - -Begin receiving on the returned chan Delivery before any other operation on the -Connection or Channel. - -Continues deliveries to the returned chan Delivery until Channel.Cancel, -Connection.Close, Channel.Close, or an AMQP exception occurs. Consumers must -range over the chan to ensure all deliveries are received. Unreceived -deliveries will block all methods on the same connection. - -All deliveries in AMQP must be acknowledged. It is expected of the consumer to -call Delivery.Ack after it has successfully processed the delivery. If the -consumer is cancelled or the channel or connection is closed any unacknowledged -deliveries will be requeued at the end of the same queue. - -The consumer is identified by a string that is unique and scoped for all -consumers on this channel. If you wish to eventually cancel the consumer, use -the same non-empty idenfitier in Channel.Cancel. An empty string will cause -the library to generate a unique identity. The consumer identity will be -included in every Delivery in the ConsumerTag field - -When autoAck (also known as noAck) is true, the server will acknowledge -deliveries to this consumer prior to writing the delivery to the network. When -autoAck is true, the consumer should not call Delivery.Ack. Automatically -acknowledging deliveries means that some deliveries may get lost if the -consumer is unable to process them after the server delivers them. - -When exclusive is true, the server will ensure that this is the sole consumer -from this queue. When exclusive is false, the server will fairly distribute -deliveries across multiple consumers. - -When noLocal is true, the server will not deliver publishing sent from the same -connection to this consumer. It's advisable to use separate connections for -Channel.Publish and Channel.Consume so not to have TCP pushback on publishing -affect the ability to consume messages, so this parameter is here mostly for -completeness. - -When noWait is true, do not wait for the server to confirm the request and -immediately begin deliveries. If it is not possible to consume, a channel -exception will be raised and the channel will be closed. - -Optional arguments can be provided that have specific semantics for the queue -or server. - -When the channel or connection closes, all delivery chans will also close. - -Deliveries on the returned chan will be buffered indefinitely. To limit memory -of this buffer, use the Channel.Qos method to limit the amount of -unacknowledged/buffered deliveries the server will deliver on this Channel. - -*/ -func (me *Channel) Consume(queue, consumer string, autoAck, exclusive, noLocal, noWait bool, args Table) (<-chan Delivery, error) { - // When we return from me.call, there may be a delivery already for the - // consumer that hasn't been added to the consumer hash yet. Because of - // this, we never rely on the server picking a consumer tag for us. - - if err := args.Validate(); err != nil { - return nil, err - } - - if consumer == "" { - consumer = uniqueConsumerTag() - } - - req := &basicConsume{ - Queue: queue, - ConsumerTag: consumer, - NoLocal: noLocal, - NoAck: autoAck, - Exclusive: exclusive, - NoWait: noWait, - Arguments: args, - } - res := &basicConsumeOk{} - - deliveries := make(chan Delivery) - - me.consumers.add(consumer, deliveries) - - if err := me.call(req, res); err != nil { - me.consumers.close(consumer) - return nil, err - } - - return (<-chan Delivery)(deliveries), nil -} - -/* -ExchangeDeclare declares an exchange on the server. If the exchange does not -already exist, the server will create it. If the exchange exists, the server -verifies that it is of the provided type, durability and auto-delete flags. - -Errors returned from this method will close the channel. - -Exchange names starting with "amq." are reserved for pre-declared and -standardized exchanges. The client MAY declare an exchange starting with -"amq." if the passive option is set, or the exchange already exists. Names can -consists of a non-empty sequence of letters, digits, hyphen, underscore, -period, or colon. - -Each exchange belongs to one of a set of exchange kinds/types implemented by -the server. The exchange types define the functionality of the exchange - i.e. -how messages are routed through it. Once an exchange is declared, its type -cannot be changed. The common types are "direct", "fanout", "topic" and -"headers". - -Durable and Non-Auto-Deleted exchanges will survive server restarts and remain -declared when there are no remaining bindings. This is the best lifetime for -long-lived exchange configurations like stable routes and default exchanges. - -Non-Durable and Auto-Deleted exchanges will be deleted when there are no -remaining bindings and not restored on server restart. This lifetime is -useful for temporary topologies that should not pollute the virtual host on -failure or after the consumers have completed. - -Non-Durable and Non-Auto-deleted exchanges will remain as long as the server is -running including when there are no remaining bindings. This is useful for -temporary topologies that may have long delays between bindings. - -Durable and Auto-Deleted exchanges will survive server restarts and will be -removed before and after server restarts when there are no remaining bindings. -These exchanges are useful for robust temporary topologies or when you require -binding durable queues to auto-deleted exchanges. - -Note: RabbitMQ declares the default exchange types like 'amq.fanout' as -durable, so queues that bind to these pre-declared exchanges must also be -durable. - -Exchanges declared as `internal` do not accept accept publishings. Internal -exchanges are useful for when you wish to implement inter-exchange topologies -that should not be exposed to users of the broker. - -When noWait is true, declare without waiting for a confirmation from the server. -The channel may be closed as a result of an error. Add a NotifyClose listener -to respond to any exceptions. - -Optional amqp.Table of arguments that are specific to the server's implementation of -the exchange can be sent for exchange types that require extra parameters. -*/ -func (me *Channel) ExchangeDeclare(name, kind string, durable, autoDelete, internal, noWait bool, args Table) error { - if err := args.Validate(); err != nil { - return err - } - - return me.call( - &exchangeDeclare{ - Exchange: name, - Type: kind, - Passive: false, - Durable: durable, - AutoDelete: autoDelete, - Internal: internal, - NoWait: noWait, - Arguments: args, - }, - &exchangeDeclareOk{}, - ) -} - -/* - -ExchangeDeclarePassive is functionally and parametrically equivalent to -ExchangeDeclare, except that it sets the "passive" attribute to true. A passive -exchange is assumed by RabbitMQ to already exist, and attempting to connect to a -non-existent exchange will cause RabbitMQ to throw an exception. This function -can be used to detect the existence of an exchange. - -*/ -func (me *Channel) ExchangeDeclarePassive(name, kind string, durable, autoDelete, internal, noWait bool, args Table) error { - if err := args.Validate(); err != nil { - return err - } - - return me.call( - &exchangeDeclare{ - Exchange: name, - Type: kind, - Passive: true, - Durable: durable, - AutoDelete: autoDelete, - Internal: internal, - NoWait: noWait, - Arguments: args, - }, - &exchangeDeclareOk{}, - ) -} - -/* -ExchangeDelete removes the named exchange from the server. When an exchange is -deleted all queue bindings on the exchange are also deleted. If this exchange -does not exist, the channel will be closed with an error. - -When ifUnused is true, the server will only delete the exchange if it has no queue -bindings. If the exchange has queue bindings the server does not delete it -but close the channel with an exception instead. Set this to true if you are -not the sole owner of the exchange. - -When noWait is true, do not wait for a server confirmation that the exchange has -been deleted. Failing to delete the channel could close the channel. Add a -NotifyClose listener to respond to these channel exceptions. -*/ -func (me *Channel) ExchangeDelete(name string, ifUnused, noWait bool) error { - return me.call( - &exchangeDelete{ - Exchange: name, - IfUnused: ifUnused, - NoWait: noWait, - }, - &exchangeDeleteOk{}, - ) -} - -/* -ExchangeBind binds an exchange to another exchange to create inter-exchange -routing topologies on the server. This can decouple the private topology and -routing exchanges from exchanges intended solely for publishing endpoints. - -Binding two exchanges with identical arguments will not create duplicate -bindings. - -Binding one exchange to another with multiple bindings will only deliver a -message once. For example if you bind your exchange to `amq.fanout` with two -different binding keys, only a single message will be delivered to your -exchange even though multiple bindings will match. - -Given a message delivered to the source exchange, the message will be forwarded -to the destination exchange when the routing key is matched. - - ExchangeBind("sell", "MSFT", "trade", false, nil) - ExchangeBind("buy", "AAPL", "trade", false, nil) - - Delivery Source Key Destination - example exchange exchange - ----------------------------------------------- - key: AAPL --> trade ----> MSFT sell - \---> AAPL --> buy - -When noWait is true, do not wait for the server to confirm the binding. If any -error occurs the channel will be closed. Add a listener to NotifyClose to -handle these errors. - -Optional arguments specific to the exchanges bound can also be specified. -*/ -func (me *Channel) ExchangeBind(destination, key, source string, noWait bool, args Table) error { - if err := args.Validate(); err != nil { - return err - } - - return me.call( - &exchangeBind{ - Destination: destination, - Source: source, - RoutingKey: key, - NoWait: noWait, - Arguments: args, - }, - &exchangeBindOk{}, - ) -} - -/* -ExchangeUnbind unbinds the destination exchange from the source exchange on the -server by removing the routing key between them. This is the inverse of -ExchangeBind. If the binding does not currently exist, an error will be -returned. - -When noWait is true, do not wait for the server to confirm the deletion of the -binding. If any error occurs the channel will be closed. Add a listener to -NotifyClose to handle these errors. - -Optional arguments that are specific to the type of exchanges bound can also be -provided. These must match the same arguments specified in ExchangeBind to -identify the binding. -*/ -func (me *Channel) ExchangeUnbind(destination, key, source string, noWait bool, args Table) error { - if err := args.Validate(); err != nil { - return err - } - - return me.call( - &exchangeUnbind{ - Destination: destination, - Source: source, - RoutingKey: key, - NoWait: noWait, - Arguments: args, - }, - &exchangeUnbindOk{}, - ) -} - -/* -Publish sends a Publishing from the client to an exchange on the server. - -When you want a single message to be delivered to a single queue, you can -publish to the default exchange with the routingKey of the queue name. This is -because every declared queue gets an implicit route to the default exchange. - -Since publishings are asynchronous, any undeliverable message will get returned -by the server. Add a listener with Channel.NotifyReturn to handle any -undeliverable message when calling publish with either the mandatory or -immediate parameters as true. - -Publishings can be undeliverable when the mandatory flag is true and no queue is -bound that matches the routing key, or when the immediate flag is true and no -consumer on the matched queue is ready to accept the delivery. - -This can return an error when the channel, connection or socket is closed. The -error or lack of an error does not indicate whether the server has received this -publishing. - -It is possible for publishing to not reach the broker if the underlying socket -is shutdown without pending publishing packets being flushed from the kernel -buffers. The easy way of making it probable that all publishings reach the -server is to always call Connection.Close before terminating your publishing -application. The way to ensure that all publishings reach the server is to add -a listener to Channel.NotifyConfirm and keep track of the server acks and nacks -for every publishing you publish, only exiting when all publishings are -accounted for. - -*/ -func (me *Channel) Publish(exchange, key string, mandatory, immediate bool, msg Publishing) error { - if err := msg.Headers.Validate(); err != nil { - return err - } - - me.m.Lock() - defer me.m.Unlock() - - if err := me.send(me, &basicPublish{ - Exchange: exchange, - RoutingKey: key, - Mandatory: mandatory, - Immediate: immediate, - Body: msg.Body, - Properties: properties{ - Headers: msg.Headers, - ContentType: msg.ContentType, - ContentEncoding: msg.ContentEncoding, - DeliveryMode: msg.DeliveryMode, - Priority: msg.Priority, - CorrelationId: msg.CorrelationId, - ReplyTo: msg.ReplyTo, - Expiration: msg.Expiration, - MessageId: msg.MessageId, - Timestamp: msg.Timestamp, - Type: msg.Type, - UserId: msg.UserId, - AppId: msg.AppId, - }, - }); err != nil { - return err - } - - me.publishCounter += 1 - - if me.confirms != nil { - heap.Push(&me.confirms, me.publishCounter) - } - - return nil -} - -/* -Get synchronously receives a single Delivery from the head of a queue from the -server to the client. In almost all cases, using Channel.Consume will be -preferred. - -If there was a delivery waiting on the queue and that delivery was received the -second return value will be true. If there was no delivery waiting or an error -occured, the ok bool will be false. - -All deliveries must be acknowledged including those from Channel.Get. Call -Delivery.Ack on the returned delivery when you have fully processed this -delivery. - -When autoAck is true, the server will automatically acknowledge this message so -you don't have to. But if you are unable to fully process this message before -the channel or connection is closed, the message will not get requeued. - -*/ -func (me *Channel) Get(queue string, autoAck bool) (msg Delivery, ok bool, err error) { - req := &basicGet{Queue: queue, NoAck: autoAck} - res := &basicGetOk{} - empty := &basicGetEmpty{} - - if err := me.call(req, res, empty); err != nil { - return Delivery{}, false, err - } - - if res.DeliveryTag > 0 { - return *(newDelivery(me, res)), true, nil - } - - return Delivery{}, false, nil -} - -/* -Tx puts the channel into transaction mode on the server. All publishings and -acknowledgments following this method will be atomically committed or rolled -back for a single queue. Call either Channel.TxCommit or Channel.TxRollback to -leave a this transaction and immediately start a new transaction. - -The atomicity across multiple queues is not defined as queue declarations and -bindings are not included in the transaction. - -The behavior of publishings that are delivered as mandatory or immediate while -the channel is in a transaction is not defined. - -Once a channel has been put into transaction mode, it cannot be taken out of -transaction mode. Use a different channel for non-transactional semantics. - -*/ -func (me *Channel) Tx() error { - return me.call( - &txSelect{}, - &txSelectOk{}, - ) -} - -/* -TxCommit atomically commits all publishings and acknowledgments for a single -queue and immediately start a new transaction. - -Calling this method without having called Channel.Tx is an error. - -*/ -func (me *Channel) TxCommit() error { - return me.call( - &txCommit{}, - &txCommitOk{}, - ) -} - -/* -TxRollback atomically rolls back all publishings and acknowledgments for a -single queue and immediately start a new transaction. - -Calling this method without having called Channel.Tx is an error. - -*/ -func (me *Channel) TxRollback() error { - return me.call( - &txRollback{}, - &txRollbackOk{}, - ) -} - -/* -Flow pauses the delivery of messages to consumers on this channel. Channels -are opened with flow control not active, to open a channel with paused -deliveries immediately call this method with true after calling -Connection.Channel. - -When active is true, this method asks the server to temporarily pause deliveries -until called again with active as false. - -Channel.Get methods will not be affected by flow control. - -This method is not intended to act as window control. Use Channel.Qos to limit -the number of unacknowledged messages or bytes in flight instead. - -The server may also send us flow methods to throttle our publishings. A well -behaving publishing client should add a listener with Channel.NotifyFlow and -pause its publishings when true is sent on that channel. - -Note: RabbitMQ prefers to use TCP push back to control flow for all channels on -a connection, so under high volume scenarios, it's wise to open separate -Connections for publishings and deliveries. - -*/ -func (me *Channel) Flow(active bool) error { - return me.call( - &channelFlow{Active: active}, - &channelFlowOk{}, - ) -} - -/* -Confirm puts this channel into confirm mode so that the client can ensure all -publishings have successfully been received by the server. After entering this -mode, the server will send a basic.ack or basic.nack message with the deliver -tag set to a 1 based incrementing index corresponding to every publishing -received after the this method returns. - -Add a listener to Channel.NotifyConfirm to respond to the acknowledgments and -negative acknowledgments before publishing. If Channel.NotifyConfirm is not -called, the Ack/Nacks will be silently ignored. - -The order of acknowledgments is not bound to the order of deliveries. - -Ack and Nack confirmations will arrive at some point in the future. - -Unroutable mandatory or immediate messages are acknowledged immediately after -any Channel.NotifyReturn listeners have been notified. Other messages are -acknowledged when all queues that should have the message routed to them have -either have received acknowledgment of delivery or have enqueued the message, -persisting the message if necessary. - -When noWait is true, the client will not wait for a response. A channel -exception could occur if the server does not support this method. - -*/ -func (me *Channel) Confirm(noWait bool) error { - me.m.Lock() - defer me.m.Unlock() - - if err := me.call( - &confirmSelect{Nowait: noWait}, - &confirmSelectOk{}, - ); err != nil { - return err - } - - // Indicates we're in confirm mode - me.confirms = make(tagSet, 0) - - return nil -} - -/* -Recover redelivers all unacknowledged deliveries on this channel. - -When requeue is false, messages will be redelivered to the original consumer. - -When requeue is true, messages will be redelivered to any available consumer, -potentially including the original. - -If the deliveries cannot be recovered, an error will be returned and the channel -will be closed. - -Note: this method is not implemented on RabbitMQ, use Delivery.Nack instead -*/ -func (me *Channel) Recover(requeue bool) error { - return me.call( - &basicRecover{Requeue: requeue}, - &basicRecoverOk{}, - ) -} - -/* -Ack acknowledges a delivery by its delivery tag when having been consumed with -Channel.Consume or Channel.Get. - -Ack acknowledges all message received prior to the delivery tag when multiple -is true. - -See also Delivery.Ack -*/ -func (me *Channel) Ack(tag uint64, multiple bool) error { - return me.send(me, &basicAck{ - DeliveryTag: tag, - Multiple: multiple, - }) -} - -/* -Nack negatively acknowledges a delivery by its delivery tag. Prefer this -method to notify the server that you were not able to process this delivery and -it must be redelivered or dropped. - -See also Delivery.Nack -*/ -func (me *Channel) Nack(tag uint64, multiple bool, requeue bool) error { - return me.send(me, &basicNack{ - DeliveryTag: tag, - Multiple: multiple, - Requeue: requeue, - }) -} - -/* -Reject negatively acknowledges a delivery by its delivery tag. Prefer Nack -over Reject when communicating with a RabbitMQ server because you can Nack -multiple messages, reducing the amount of protocol messages to exchange. - -See also Delivery.Reject -*/ -func (me *Channel) Reject(tag uint64, requeue bool) error { - return me.send(me, &basicReject{ - DeliveryTag: tag, - Requeue: requeue, - }) -} diff --git a/vendor/github.com/streadway/amqp/client_test.go b/vendor/github.com/streadway/amqp/client_test.go deleted file mode 100644 index 7d0362845ff..00000000000 --- a/vendor/github.com/streadway/amqp/client_test.go +++ /dev/null @@ -1,559 +0,0 @@ -// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Source code and contact info at http://github.com/streadway/amqp - -package amqp - -import ( - "bytes" - "io" - "reflect" - "testing" - "time" -) - -type server struct { - *testing.T - r reader // framer <- client - w writer // framer -> client - S io.ReadWriteCloser // Server IO - C io.ReadWriteCloser // Client IO - - // captured client frames - start connectionStartOk - tune connectionTuneOk -} - -func defaultConfig() Config { - return Config{SASL: []Authentication{&PlainAuth{"guest", "guest"}}, Vhost: "/"} -} - -func newSession(t *testing.T) (io.ReadWriteCloser, *server) { - rs, wc := io.Pipe() - rc, ws := io.Pipe() - - rws := &logIO{t, "server", pipe{rs, ws}} - rwc := &logIO{t, "client", pipe{rc, wc}} - - server := server{ - T: t, - r: reader{rws}, - w: writer{rws}, - S: rws, - C: rwc, - } - - return rwc, &server -} - -func (t *server) expectBytes(b []byte) { - in := make([]byte, len(b)) - if _, err := io.ReadFull(t.S, in); err != nil { - t.Fatalf("io error expecting bytes: %v", err) - } - - if bytes.Compare(b, in) != 0 { - t.Fatalf("failed bytes: expected: %s got: %s", string(b), string(in)) - } -} - -func (t *server) send(channel int, m message) { - defer time.AfterFunc(time.Second, func() { panic("send deadlock") }).Stop() - - if err := t.w.WriteFrame(&methodFrame{ - ChannelId: uint16(channel), - Method: m, - }); err != nil { - t.Fatalf("frame err, write: %s", err) - } -} - -// drops all but method frames expected on the given channel -func (t *server) recv(channel int, m message) message { - defer time.AfterFunc(time.Second, func() { panic("recv deadlock") }).Stop() - - var remaining int - var header *headerFrame - var body []byte - - for { - frame, err := t.r.ReadFrame() - if err != nil { - t.Fatalf("frame err, read: %s", err) - } - - if frame.channel() != uint16(channel) { - t.Fatalf("expected frame on channel %d, got channel %d", channel, frame.channel()) - } - - switch f := frame.(type) { - case *heartbeatFrame: - // drop - - case *headerFrame: - // start content state - header = f - remaining = int(header.Size) - if remaining == 0 { - m.(messageWithContent).setContent(header.Properties, nil) - return m - } - - case *bodyFrame: - // continue until terminated - body = append(body, f.Body...) - remaining -= len(f.Body) - if remaining <= 0 { - m.(messageWithContent).setContent(header.Properties, body) - return m - } - - case *methodFrame: - if reflect.TypeOf(m) == reflect.TypeOf(f.Method) { - wantv := reflect.ValueOf(m).Elem() - havev := reflect.ValueOf(f.Method).Elem() - wantv.Set(havev) - if _, ok := m.(messageWithContent); !ok { - return m - } - } else { - t.Fatalf("expected method type: %T, got: %T", m, f.Method) - } - - default: - t.Fatalf("unexpected frame: %+v", f) - } - } - - panic("unreachable") -} - -func (t *server) expectAMQP() { - t.expectBytes([]byte{'A', 'M', 'Q', 'P', 0, 0, 9, 1}) -} - -func (t *server) connectionStart() { - t.send(0, &connectionStart{ - VersionMajor: 0, - VersionMinor: 9, - Mechanisms: "PLAIN", - Locales: "en-us", - }) - - t.recv(0, &t.start) -} - -func (t *server) connectionTune() { - t.send(0, &connectionTune{ - ChannelMax: 11, - FrameMax: 20000, - Heartbeat: 10, - }) - - t.recv(0, &t.tune) -} - -func (t *server) connectionOpen() { - t.expectAMQP() - t.connectionStart() - t.connectionTune() - - t.recv(0, &connectionOpen{}) - t.send(0, &connectionOpenOk{}) -} - -func (t *server) connectionClose() { - t.recv(0, &connectionClose{}) - t.send(0, &connectionCloseOk{}) -} - -func (t *server) channelOpen(id int) { - t.recv(id, &channelOpen{}) - t.send(id, &channelOpenOk{}) -} - -func TestDefaultClientProperties(t *testing.T) { - rwc, srv := newSession(t) - - go func() { - srv.connectionOpen() - rwc.Close() - }() - - if c, err := Open(rwc, defaultConfig()); err != nil { - t.Fatalf("could not create connection: %v (%s)", c, err) - } - - if want, got := defaultProduct, srv.start.ClientProperties["product"]; want != got { - t.Errorf("expected product %s got: %s", want, got) - } - - if want, got := defaultVersion, srv.start.ClientProperties["version"]; want != got { - t.Errorf("expected version %s got: %s", want, got) - } -} - -func TestCustomClientProperties(t *testing.T) { - rwc, srv := newSession(t) - - config := defaultConfig() - config.Properties = Table{ - "product": "foo", - "version": "1.0", - } - - go func() { - srv.connectionOpen() - rwc.Close() - }() - - if c, err := Open(rwc, config); err != nil { - t.Fatalf("could not create connection: %v (%s)", c, err) - } - - if want, got := config.Properties["product"], srv.start.ClientProperties["product"]; want != got { - t.Errorf("expected product %s got: %s", want, got) - } - - if want, got := config.Properties["version"], srv.start.ClientProperties["version"]; want != got { - t.Errorf("expected version %s got: %s", want, got) - } -} - -func TestOpen(t *testing.T) { - rwc, srv := newSession(t) - go func() { - srv.connectionOpen() - rwc.Close() - }() - - if c, err := Open(rwc, defaultConfig()); err != nil { - t.Fatalf("could not create connection: %v (%s)", c, err) - } -} - -func TestChannelOpen(t *testing.T) { - rwc, srv := newSession(t) - - go func() { - srv.connectionOpen() - srv.channelOpen(1) - - rwc.Close() - }() - - c, err := Open(rwc, defaultConfig()) - if err != nil { - t.Fatalf("could not create connection: %v (%s)", c, err) - } - - ch, err := c.Channel() - if err != nil { - t.Fatalf("could not open channel: %v (%s)", ch, err) - } -} - -func TestOpenFailedSASLUnsupportedMechanisms(t *testing.T) { - rwc, srv := newSession(t) - - go func() { - srv.expectAMQP() - srv.send(0, &connectionStart{ - VersionMajor: 0, - VersionMinor: 9, - Mechanisms: "KERBEROS NTLM", - Locales: "en-us", - }) - }() - - c, err := Open(rwc, defaultConfig()) - if err != ErrSASL { - t.Fatalf("expected ErrSASL got: %+v on %+v", err, c) - } -} - -func TestOpenFailedCredentials(t *testing.T) { - rwc, srv := newSession(t) - - go func() { - srv.expectAMQP() - srv.connectionStart() - // Now kill/timeout the connection indicating bad auth - rwc.Close() - }() - - c, err := Open(rwc, defaultConfig()) - if err != ErrCredentials { - t.Fatalf("expected ErrCredentials got: %+v on %+v", err, c) - } -} - -func TestOpenFailedVhost(t *testing.T) { - rwc, srv := newSession(t) - - go func() { - srv.expectAMQP() - srv.connectionStart() - srv.connectionTune() - srv.recv(0, &connectionOpen{}) - - // Now kill/timeout the connection on bad Vhost - rwc.Close() - }() - - c, err := Open(rwc, defaultConfig()) - if err != ErrVhost { - t.Fatalf("expected ErrVhost got: %+v on %+v", err, c) - } -} - -func TestConfirmMultipleOrdersDeliveryTags(t *testing.T) { - rwc, srv := newSession(t) - defer rwc.Close() - - go func() { - srv.connectionOpen() - srv.channelOpen(1) - - srv.recv(1, &confirmSelect{}) - srv.send(1, &confirmSelectOk{}) - - srv.recv(1, &basicPublish{}) - srv.recv(1, &basicPublish{}) - srv.recv(1, &basicPublish{}) - srv.recv(1, &basicPublish{}) - - // Single tag, plus multiple, should produce - // 2, 1, 3, 4 - srv.send(1, &basicAck{DeliveryTag: 2}) - srv.send(1, &basicAck{DeliveryTag: 4, Multiple: true}) - - srv.recv(1, &basicPublish{}) - srv.recv(1, &basicPublish{}) - srv.recv(1, &basicPublish{}) - srv.recv(1, &basicPublish{}) - - // And some more, but in reverse order, multiple then one - // 5, 6, 7, 8 - srv.send(1, &basicAck{DeliveryTag: 6, Multiple: true}) - srv.send(1, &basicAck{DeliveryTag: 8}) - srv.send(1, &basicAck{DeliveryTag: 7}) - }() - - c, err := Open(rwc, defaultConfig()) - if err != nil { - t.Fatalf("could not create connection: %v (%s)", c, err) - } - - ch, err := c.Channel() - if err != nil { - t.Fatalf("could not open channel: %v (%s)", ch, err) - } - - acks, _ := ch.NotifyConfirm(make(chan uint64), make(chan uint64)) - - ch.Confirm(false) - - ch.Publish("", "q", false, false, Publishing{Body: []byte("pub 1")}) - ch.Publish("", "q", false, false, Publishing{Body: []byte("pub 2")}) - ch.Publish("", "q", false, false, Publishing{Body: []byte("pub 3")}) - ch.Publish("", "q", false, false, Publishing{Body: []byte("pub 4")}) - - for i, tag := range []uint64{2, 1, 3, 4} { - if ack := <-acks; tag != ack { - t.Fatalf("failed ack, expected ack#%d to be %d, got %d", i, tag, ack) - } - } - - ch.Publish("", "q", false, false, Publishing{Body: []byte("pub 5")}) - ch.Publish("", "q", false, false, Publishing{Body: []byte("pub 6")}) - ch.Publish("", "q", false, false, Publishing{Body: []byte("pub 7")}) - ch.Publish("", "q", false, false, Publishing{Body: []byte("pub 8")}) - - for i, tag := range []uint64{5, 6, 8, 7} { - if ack := <-acks; tag != ack { - t.Fatalf("failed ack, expected ack#%d to be %d, got %d", i, tag, ack) - } - } - -} - -func TestNotifyClosesReusedPublisherConfirmChan(t *testing.T) { - rwc, srv := newSession(t) - - go func() { - srv.connectionOpen() - srv.channelOpen(1) - - srv.recv(1, &confirmSelect{}) - srv.send(1, &confirmSelectOk{}) - - srv.recv(0, &connectionClose{}) - srv.send(0, &connectionCloseOk{}) - }() - - c, err := Open(rwc, defaultConfig()) - if err != nil { - t.Fatalf("could not create connection: %v (%s)", c, err) - } - - ch, err := c.Channel() - if err != nil { - t.Fatalf("could not open channel: %v (%s)", ch, err) - } - - ackAndNack := make(chan uint64) - ch.NotifyConfirm(ackAndNack, ackAndNack) - - if err := ch.Confirm(false); err != nil { - t.Fatalf("expected to enter confirm mode: %v", err) - } - - if err := c.Close(); err != nil { - t.Fatalf("could not close connection: %v (%s)", c, err) - } -} - -func TestNotifyClosesAllChansAfterConnectionClose(t *testing.T) { - rwc, srv := newSession(t) - - go func() { - srv.connectionOpen() - srv.channelOpen(1) - - srv.recv(0, &connectionClose{}) - srv.send(0, &connectionCloseOk{}) - }() - - c, err := Open(rwc, defaultConfig()) - if err != nil { - t.Fatalf("could not create connection: %v (%s)", c, err) - } - - ch, err := c.Channel() - if err != nil { - t.Fatalf("could not open channel: %v (%s)", ch, err) - } - - if err := c.Close(); err != nil { - t.Fatalf("could not close connection: %v (%s)", c, err) - } - - select { - case <-c.NotifyClose(make(chan *Error)): - case <-time.After(time.Millisecond): - t.Errorf("expected to close NotifyClose chan after Connection.Close") - } - - select { - case <-ch.NotifyClose(make(chan *Error)): - case <-time.After(time.Millisecond): - t.Errorf("expected to close Connection.NotifyClose chan after Connection.Close") - } - - select { - case <-ch.NotifyFlow(make(chan bool)): - case <-time.After(time.Millisecond): - t.Errorf("expected to close Channel.NotifyFlow chan after Connection.Close") - } - - select { - case <-ch.NotifyCancel(make(chan string)): - case <-time.After(time.Millisecond): - t.Errorf("expected to close Channel.NofityCancel chan after Connection.Close") - } - - select { - case <-ch.NotifyReturn(make(chan Return)): - case <-time.After(time.Millisecond): - t.Errorf("expected to close Channel.NotifyReturn chan after Connection.Close") - } - - ack, nack := ch.NotifyConfirm(make(chan uint64), make(chan uint64)) - - select { - case <-ack: - case <-time.After(time.Millisecond): - t.Errorf("expected to close acks on Channel.NotifyConfirm chan after Connection.Close") - } - - select { - case <-nack: - case <-time.After(time.Millisecond): - t.Errorf("expected to close nacks Channel.NotifyConfirm chan after Connection.Close") - } -} - -// Should not panic when sending bodies split at differnet boundaries -func TestPublishBodySliceIssue74(t *testing.T) { - rwc, srv := newSession(t) - defer rwc.Close() - - const frameSize = 100 - const publishings = frameSize * 3 - - done := make(chan bool) - base := make([]byte, publishings) - - go func() { - srv.connectionOpen() - srv.channelOpen(1) - - for i := 0; i < publishings; i++ { - srv.recv(1, &basicPublish{}) - } - - done <- true - }() - - cfg := defaultConfig() - cfg.FrameSize = frameSize - - c, err := Open(rwc, cfg) - if err != nil { - t.Fatalf("could not create connection: %v (%s)", c, err) - } - - ch, err := c.Channel() - if err != nil { - t.Fatalf("could not open channel: %v (%s)", ch, err) - } - - for i := 0; i < publishings; i++ { - go ch.Publish("", "q", false, false, Publishing{Body: base[0:i]}) - } - - <-done -} - -func TestPublishAndShutdownDeadlockIssue84(t *testing.T) { - rwc, srv := newSession(t) - defer rwc.Close() - - go func() { - srv.connectionOpen() - srv.channelOpen(1) - srv.recv(1, &basicPublish{}) - // Mimic a broken io pipe so that Publish catches the error and goes into shutdown - srv.S.Close() - }() - - c, err := Open(rwc, defaultConfig()) - if err != nil { - t.Fatalf("couldn't create connection: %v (%s)", c, err) - } - - ch, err := c.Channel() - if err != nil { - t.Fatalf("couldn't open channel: %v (%s)", ch, err) - } - - defer time.AfterFunc(500*time.Millisecond, func() { panic("Publish deadlock") }).Stop() - for { - if err := ch.Publish("exchange", "q", false, false, Publishing{Body: []byte("test")}); err != nil { - t.Log("successfully caught disconnect error", err) - return - } - } -} diff --git a/vendor/github.com/streadway/amqp/connection.go b/vendor/github.com/streadway/amqp/connection.go deleted file mode 100644 index 5c46f45ac4c..00000000000 --- a/vendor/github.com/streadway/amqp/connection.go +++ /dev/null @@ -1,764 +0,0 @@ -// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Source code and contact info at http://github.com/streadway/amqp - -package amqp - -import ( - "bufio" - "crypto/tls" - "io" - "net" - "reflect" - "strconv" - "strings" - "sync" - "time" -) - -const ( - defaultHeartbeat = 10 * time.Second - defaultConnectionTimeout = 30 * time.Second - defaultProduct = "https://github.com/streadway/amqp" - defaultVersion = "β" - defaultChannelMax = (2 << 16) - 1 -) - -// Config is used in DialConfig and Open to specify the desired tuning -// parameters used during a connection open handshake. The negotiated tuning -// will be stored in the returned connection's Config field. -type Config struct { - // The SASL mechanisms to try in the client request, and the successful - // mechanism used on the Connection object. - // If SASL is nil, PlainAuth from the URL is used. - SASL []Authentication - - // Vhost specifies the namespace of permissions, exchanges, queues and - // bindings on the server. Dial sets this to the path parsed from the URL. - Vhost string - - ChannelMax int // 0 max channels means 2^16 - 1 - FrameSize int // 0 max bytes means unlimited - Heartbeat time.Duration // less than 1s uses the server's interval - - // TLSClientConfig specifies the client configuration of the TLS connection - // when establishing a tls transport. - // If the URL uses an amqps scheme, then an empty tls.Config with the - // ServerName from the URL is used. - TLSClientConfig *tls.Config - - // Properties is table of properties that the client advertises to the server. - // This is an optional setting - if the application does not set this, - // the underlying library will use a generic set of client properties. - Properties Table - - // Dial returns a net.Conn prepared for a TLS handshake with TSLClientConfig, - // then an AMQP connection handshake. - // If Dial is nil, net.DialTimeout with a 30s connection and 30s read - // deadline is used. - Dial func(network, addr string) (net.Conn, error) -} - -// Connection manages the serialization and deserialization of frames from IO -// and dispatches the frames to the appropriate channel. All RPC methods and -// asyncronous Publishing, Delivery, Ack, Nack and Return messages are -// multiplexed on this channel. There must always be active receivers for -// every asynchronous message on this connection. -type Connection struct { - destructor sync.Once // shutdown once - sendM sync.Mutex // conn writer mutex - m sync.Mutex // struct field mutex - - conn io.ReadWriteCloser - - rpc chan message - writer *writer - sends chan time.Time // timestamps of each frame sent - deadlines chan readDeadliner // heartbeater updates read deadlines - - allocator *allocator // id generator valid after openTune - channels map[uint16]*Channel - - noNotify bool // true when we will never notify again - closes []chan *Error - blocks []chan Blocking - - errors chan *Error - - Config Config // The negotiated Config after connection.open - - Major int // Server's major version - Minor int // Server's minor version - Properties Table // Server properties -} - -type readDeadliner interface { - SetReadDeadline(time.Time) error -} - -type localNetAddr interface { - LocalAddr() net.Addr -} - -// defaultDial establishes a connection when config.Dial is not provided -func defaultDial(network, addr string) (net.Conn, error) { - conn, err := net.DialTimeout(network, addr, defaultConnectionTimeout) - if err != nil { - return nil, err - } - - // Heartbeating hasn't started yet, don't stall forever on a dead server. - if err := conn.SetReadDeadline(time.Now().Add(defaultConnectionTimeout)); err != nil { - return nil, err - } - - return conn, nil -} - -// Dial accepts a string in the AMQP URI format and returns a new Connection -// over TCP using PlainAuth. Defaults to a server heartbeat interval of 10 -// seconds and sets the initial read deadline to 30 seconds. -// -// Dial uses the zero value of tls.Config when it encounters an amqps:// -// scheme. It is equivalent to calling DialTLS(amqp, nil). -func Dial(url string) (*Connection, error) { - return DialConfig(url, Config{ - Heartbeat: defaultHeartbeat, - }) -} - -// DialTLS accepts a string in the AMQP URI format and returns a new Connection -// over TCP using PlainAuth. Defaults to a server heartbeat interval of 10 -// seconds and sets the initial read deadline to 30 seconds. -// -// DialTLS uses the provided tls.Config when encountering an amqps:// scheme. -func DialTLS(url string, amqps *tls.Config) (*Connection, error) { - return DialConfig(url, Config{ - Heartbeat: defaultHeartbeat, - TLSClientConfig: amqps, - }) -} - -// DialConfig accepts a string in the AMQP URI format and a configuration for -// the transport and connection setup, returning a new Connection. Defaults to -// a server heartbeat interval of 10 seconds and sets the initial read deadline -// to 30 seconds. -func DialConfig(url string, config Config) (*Connection, error) { - var err error - var conn net.Conn - - uri, err := ParseURI(url) - if err != nil { - return nil, err - } - - if config.SASL == nil { - config.SASL = []Authentication{uri.PlainAuth()} - } - - if config.Vhost == "" { - config.Vhost = uri.Vhost - } - - if uri.Scheme == "amqps" && config.TLSClientConfig == nil { - config.TLSClientConfig = new(tls.Config) - } - - addr := net.JoinHostPort(uri.Host, strconv.FormatInt(int64(uri.Port), 10)) - - dialer := config.Dial - if dialer == nil { - dialer = defaultDial - } - - conn, err = dialer("tcp", addr) - if err != nil { - return nil, err - } - - if config.TLSClientConfig != nil { - // Use the URI's host for hostname validation unless otherwise set. Make a - // copy so not to modify the caller's reference when the caller reuses a - // tls.Config for a different URL. - if config.TLSClientConfig.ServerName == "" { - c := *config.TLSClientConfig - c.ServerName = uri.Host - config.TLSClientConfig = &c - } - - client := tls.Client(conn, config.TLSClientConfig) - if err := client.Handshake(); err != nil { - conn.Close() - return nil, err - } - - conn = client - } - - return Open(conn, config) -} - -/* -Open accepts an already established connection, or other io.ReadWriteCloser as -a transport. Use this method if you have established a TLS connection or wish -to use your own custom transport. - -*/ -func Open(conn io.ReadWriteCloser, config Config) (*Connection, error) { - me := &Connection{ - conn: conn, - writer: &writer{bufio.NewWriter(conn)}, - channels: make(map[uint16]*Channel), - rpc: make(chan message), - sends: make(chan time.Time), - errors: make(chan *Error, 1), - deadlines: make(chan readDeadliner, 1), - } - go me.reader(conn) - return me, me.open(config) -} - -/* -LocalAddr returns the local TCP peer address, or ":0" (the zero value of net.TCPAddr) -as a fallback default value if the underlying transport does not support LocalAddr(). -*/ -func (me *Connection) LocalAddr() net.Addr { - if c, ok := me.conn.(localNetAddr); ok { - return c.LocalAddr() - } - return &net.TCPAddr{} -} - -/* -NotifyClose registers a listener for close events either initiated by an error -accompaning a connection.close method or by a normal shutdown. - -On normal shutdowns, the chan will be closed. - -To reconnect after a transport or protocol error, register a listener here and -re-run your setup process. - -*/ -func (me *Connection) NotifyClose(c chan *Error) chan *Error { - me.m.Lock() - defer me.m.Unlock() - - if me.noNotify { - close(c) - } else { - me.closes = append(me.closes, c) - } - - return c -} - -/* -NotifyBlock registers a listener for RabbitMQ specific TCP flow control method -extensions connection.blocked and connection.unblocked. Flow control is active -with a reason when Blocking.Blocked is true. When a Connection is blocked, all -methods will block across all connections until server resources become free -again. - -This optional extension is supported by the server when the -"connection.blocked" server capability key is true. - -*/ -func (me *Connection) NotifyBlocked(c chan Blocking) chan Blocking { - me.m.Lock() - defer me.m.Unlock() - - if me.noNotify { - close(c) - } else { - me.blocks = append(me.blocks, c) - } - - return c -} - -/* -Close requests and waits for the response to close the AMQP connection. - -It's advisable to use this message when publishing to ensure all kernel buffers -have been flushed on the server and client before exiting. - -An error indicates that server may not have received this request to close but -the connection should be treated as closed regardless. - -After returning from this call, all resources associated with this connection, -including the underlying io, Channels, Notify listeners and Channel consumers -will also be closed. -*/ -func (me *Connection) Close() error { - defer me.shutdown(nil) - return me.call( - &connectionClose{ - ReplyCode: replySuccess, - ReplyText: "kthxbai", - }, - &connectionCloseOk{}, - ) -} - -func (me *Connection) closeWith(err *Error) error { - defer me.shutdown(err) - return me.call( - &connectionClose{ - ReplyCode: uint16(err.Code), - ReplyText: err.Reason, - }, - &connectionCloseOk{}, - ) -} - -func (me *Connection) send(f frame) error { - me.sendM.Lock() - err := me.writer.WriteFrame(f) - me.sendM.Unlock() - - if err != nil { - // shutdown could be re-entrant from signaling notify chans - go me.shutdown(&Error{ - Code: FrameError, - Reason: err.Error(), - }) - } else { - // Broadcast we sent a frame, reducing heartbeats, only - // if there is something that can receive - like a non-reentrant - // call or if the heartbeater isn't running - select { - case me.sends <- time.Now(): - default: - } - } - - return err -} - -func (me *Connection) shutdown(err *Error) { - me.destructor.Do(func() { - if err != nil { - for _, c := range me.closes { - c <- err - } - } - - for _, ch := range me.channels { - me.closeChannel(ch, err) - } - - if err != nil { - me.errors <- err - } - - me.conn.Close() - - for _, c := range me.closes { - close(c) - } - - for _, c := range me.blocks { - close(c) - } - - me.m.Lock() - me.noNotify = true - me.m.Unlock() - }) -} - -// All methods sent to the connection channel should be synchronous so we -// can handle them directly without a framing component -func (me *Connection) demux(f frame) { - if f.channel() == 0 { - me.dispatch0(f) - } else { - me.dispatchN(f) - } -} - -func (me *Connection) dispatch0(f frame) { - switch mf := f.(type) { - case *methodFrame: - switch m := mf.Method.(type) { - case *connectionClose: - // Send immediately as shutdown will close our side of the writer. - me.send(&methodFrame{ - ChannelId: 0, - Method: &connectionCloseOk{}, - }) - - me.shutdown(newError(m.ReplyCode, m.ReplyText)) - case *connectionBlocked: - for _, c := range me.blocks { - c <- Blocking{Active: true, Reason: m.Reason} - } - case *connectionUnblocked: - for _, c := range me.blocks { - c <- Blocking{Active: false} - } - default: - me.rpc <- m - } - case *heartbeatFrame: - // kthx - all reads reset our deadline. so we can drop this - default: - // lolwat - channel0 only responds to methods and heartbeats - me.closeWith(ErrUnexpectedFrame) - } -} - -func (me *Connection) dispatchN(f frame) { - me.m.Lock() - channel := me.channels[f.channel()] - me.m.Unlock() - - if channel != nil { - channel.recv(channel, f) - } else { - me.dispatchClosed(f) - } -} - -// section 2.3.7: "When a peer decides to close a channel or connection, it -// sends a Close method. The receiving peer MUST respond to a Close with a -// Close-Ok, and then both parties can close their channel or connection. Note -// that if peers ignore Close, deadlock can happen when both peers send Close -// at the same time." -// -// When we don't have a channel, so we must respond with close-ok on a close -// method. This can happen between a channel exception on an asynchronous -// method like basic.publish and a synchronous close with channel.close. -// In that case, we'll get both a channel.close and channel.close-ok in any -// order. -func (me *Connection) dispatchClosed(f frame) { - // Only consider method frames, drop content/header frames - if mf, ok := f.(*methodFrame); ok { - switch mf.Method.(type) { - case *channelClose: - me.send(&methodFrame{ - ChannelId: f.channel(), - Method: &channelCloseOk{}, - }) - case *channelCloseOk: - // we are already closed, so do nothing - default: - // unexpected method on closed channel - me.closeWith(ErrClosed) - } - } -} - -// Reads each frame off the IO and hand off to the connection object that -// will demux the streams and dispatch to one of the opened channels or -// handle on channel 0 (the connection channel). -func (me *Connection) reader(r io.Reader) { - buf := bufio.NewReader(r) - frames := &reader{buf} - conn, haveDeadliner := r.(readDeadliner) - - for { - frame, err := frames.ReadFrame() - - if err != nil { - me.shutdown(&Error{Code: FrameError, Reason: err.Error()}) - return - } - - me.demux(frame) - - if haveDeadliner { - me.deadlines <- conn - } - } -} - -// Ensures that at least one frame is being sent at the tuned interval with a -// jitter tolerance of 1s -func (me *Connection) heartbeater(interval time.Duration, done chan *Error) { - const maxServerHeartbeatsInFlight = 3 - - var sendTicks <-chan time.Time - if interval > 0 { - ticker := time.NewTicker(interval) - defer ticker.Stop() - sendTicks = ticker.C - } - - lastSent := time.Now() - - for { - select { - case at, stillSending := <-me.sends: - // When actively sending, depend on sent frames to reset server timer - if stillSending { - lastSent = at - } else { - return - } - - case at := <-sendTicks: - // When idle, fill the space with a heartbeat frame - if at.Sub(lastSent) > interval-time.Second { - if err := me.send(&heartbeatFrame{}); err != nil { - // send heartbeats even after close/closeOk so we - // tick until the connection starts erroring - return - } - } - - case conn := <-me.deadlines: - // When reading, reset our side of the deadline, if we've negotiated one with - // a deadline that covers at least 2 server heartbeats - if interval > 0 { - conn.SetReadDeadline(time.Now().Add(maxServerHeartbeatsInFlight * interval)) - } - - case <-done: - return - } - } -} - -// Convenience method to inspect the Connection.Properties["capabilities"] -// Table for server identified capabilities like "basic.ack" or -// "confirm.select". -func (me *Connection) isCapable(featureName string) bool { - capabilities, _ := me.Properties["capabilities"].(Table) - hasFeature, _ := capabilities[featureName].(bool) - return hasFeature -} - -// allocateChannel records but does not open a new channel with a unique id. -// This method is the initial part of the channel lifecycle and paired with -// releaseChannel -func (me *Connection) allocateChannel() (*Channel, error) { - me.m.Lock() - defer me.m.Unlock() - - id, ok := me.allocator.next() - if !ok { - return nil, ErrChannelMax - } - - ch := newChannel(me, uint16(id)) - me.channels[uint16(id)] = ch - - return ch, nil -} - -// releaseChannel removes a channel from the registry as the final part of the -// channel lifecycle -func (me *Connection) releaseChannel(id uint16) { - me.m.Lock() - defer me.m.Unlock() - - delete(me.channels, id) - me.allocator.release(int(id)) -} - -// openChannel allocates and opens a channel, must be paired with closeChannel -func (me *Connection) openChannel() (*Channel, error) { - ch, err := me.allocateChannel() - if err != nil { - return nil, err - } - - if err := ch.open(); err != nil { - return nil, err - } - return ch, nil -} - -// closeChannel releases and initiates a shutdown of the channel. All channel -// closures should be initiated here for proper channel lifecycle management on -// this connection. -func (me *Connection) closeChannel(ch *Channel, e *Error) { - ch.shutdown(e) - me.releaseChannel(ch.id) -} - -/* -Channel opens a unique, concurrent server channel to process the bulk of AMQP -messages. Any error from methods on this receiver will render the receiver -invalid and a new Channel should be opened. - -*/ -func (me *Connection) Channel() (*Channel, error) { - return me.openChannel() -} - -func (me *Connection) call(req message, res ...message) error { - // Special case for when the protocol header frame is sent insted of a - // request method - if req != nil { - if err := me.send(&methodFrame{ChannelId: 0, Method: req}); err != nil { - return err - } - } - - select { - case err := <-me.errors: - return err - - case msg := <-me.rpc: - // Try to match one of the result types - for _, try := range res { - if reflect.TypeOf(msg) == reflect.TypeOf(try) { - // *res = *msg - vres := reflect.ValueOf(try).Elem() - vmsg := reflect.ValueOf(msg).Elem() - vres.Set(vmsg) - return nil - } - } - return ErrCommandInvalid - } - - panic("unreachable") -} - -// Connection = open-Connection *use-Connection close-Connection -// open-Connection = C:protocol-header -// S:START C:START-OK -// *challenge -// S:TUNE C:TUNE-OK -// C:OPEN S:OPEN-OK -// challenge = S:SECURE C:SECURE-OK -// use-Connection = *channel -// close-Connection = C:CLOSE S:CLOSE-OK -// / S:CLOSE C:CLOSE-OK -func (me *Connection) open(config Config) error { - if err := me.send(&protocolHeader{}); err != nil { - return err - } - - return me.openStart(config) -} - -func (me *Connection) openStart(config Config) error { - start := &connectionStart{} - - if err := me.call(nil, start); err != nil { - return err - } - - me.Major = int(start.VersionMajor) - me.Minor = int(start.VersionMinor) - me.Properties = Table(start.ServerProperties) - - // eventually support challenge/response here by also responding to - // connectionSecure. - auth, ok := pickSASLMechanism(config.SASL, strings.Split(start.Mechanisms, " ")) - if !ok { - return ErrSASL - } - - // Save this mechanism off as the one we chose - me.Config.SASL = []Authentication{auth} - - return me.openTune(config, auth) -} - -func (me *Connection) openTune(config Config, auth Authentication) error { - if len(config.Properties) == 0 { - config.Properties = Table{ - "product": defaultProduct, - "version": defaultVersion, - } - } - - config.Properties["capabilities"] = Table{ - "connection.blocked": true, - "consumer_cancel_notify": true, - } - - ok := &connectionStartOk{ - Mechanism: auth.Mechanism(), - Response: auth.Response(), - ClientProperties: config.Properties, - } - tune := &connectionTune{} - - if err := me.call(ok, tune); err != nil { - // per spec, a connection can only be closed when it has been opened - // so at this point, we know it's an auth error, but the socket - // was closed instead. Return a meaningful error. - return ErrCredentials - } - - // When the server and client both use default 0, then the max channel is - // only limited by uint16. - me.Config.ChannelMax = pick(config.ChannelMax, int(tune.ChannelMax)) - if me.Config.ChannelMax == 0 { - me.Config.ChannelMax = defaultChannelMax - } - - // Frame size includes headers and end byte (len(payload)+8), even if - // this is less than FrameMinSize, use what the server sends because the - // alternative is to stop the handshake here. - me.Config.FrameSize = pick(config.FrameSize, int(tune.FrameMax)) - - // Save this off for resetDeadline() - me.Config.Heartbeat = time.Second * time.Duration(pick( - int(config.Heartbeat/time.Second), - int(tune.Heartbeat))) - - // "The client should start sending heartbeats after receiving a - // Connection.Tune method" - go me.heartbeater(me.Config.Heartbeat, me.NotifyClose(make(chan *Error, 1))) - - if err := me.send(&methodFrame{ - ChannelId: 0, - Method: &connectionTuneOk{ - ChannelMax: uint16(me.Config.ChannelMax), - FrameMax: uint32(me.Config.FrameSize), - Heartbeat: uint16(me.Config.Heartbeat / time.Second), - }, - }); err != nil { - return err - } - - return me.openVhost(config) -} - -func (me *Connection) openVhost(config Config) error { - req := &connectionOpen{VirtualHost: config.Vhost} - res := &connectionOpenOk{} - - if err := me.call(req, res); err != nil { - // Cannot be closed yet, but we know it's a vhost problem - return ErrVhost - } - - me.Config.Vhost = config.Vhost - - return me.openComplete() -} - -// openComplete performs any final Connection initialization dependent on the -// connection handshake. -func (me *Connection) openComplete() error { - me.allocator = newAllocator(1, me.Config.ChannelMax) - return nil -} - -func pick(client, server int) int { - if client == 0 || server == 0 { - // max - if client > server { - return client - } else { - return server - } - } else { - // min - if client > server { - return server - } else { - return client - } - } - panic("unreachable") -} diff --git a/vendor/github.com/streadway/amqp/consumers.go b/vendor/github.com/streadway/amqp/consumers.go deleted file mode 100644 index b6bd60575ae..00000000000 --- a/vendor/github.com/streadway/amqp/consumers.go +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Source code and contact info at http://github.com/streadway/amqp - -package amqp - -import ( - "fmt" - "os" - "sync" - "sync/atomic" -) - -var consumerSeq uint64 - -func uniqueConsumerTag() string { - return fmt.Sprintf("ctag-%s-%d", os.Args[0], atomic.AddUint64(&consumerSeq, 1)) -} - -type consumerBuffers map[string]chan *Delivery - -// Concurrent type that manages the consumerTag -> -// ingress consumerBuffer mapping -type consumers struct { - sync.Mutex - chans consumerBuffers -} - -func makeConsumers() *consumers { - return &consumers{chans: make(consumerBuffers)} -} - -func bufferDeliveries(in chan *Delivery, out chan Delivery) { - var queue []*Delivery - var queueIn = in - - for delivery := range in { - select { - case out <- *delivery: - // delivered immediately while the consumer chan can receive - default: - queue = append(queue, delivery) - } - - for len(queue) > 0 { - select { - case out <- *queue[0]: - queue = queue[1:] - case delivery, open := <-queueIn: - if open { - queue = append(queue, delivery) - } else { - // stop receiving to drain the queue - queueIn = nil - } - } - } - } - - close(out) -} - -// On key conflict, close the previous channel. -func (me *consumers) add(tag string, consumer chan Delivery) { - me.Lock() - defer me.Unlock() - - if prev, found := me.chans[tag]; found { - close(prev) - } - - in := make(chan *Delivery) - go bufferDeliveries(in, consumer) - - me.chans[tag] = in -} - -func (me *consumers) close(tag string) (found bool) { - me.Lock() - defer me.Unlock() - - ch, found := me.chans[tag] - - if found { - delete(me.chans, tag) - close(ch) - } - - return found -} - -func (me *consumers) closeAll() { - me.Lock() - defer me.Unlock() - - for _, ch := range me.chans { - close(ch) - } - - me.chans = make(consumerBuffers) -} - -// Sends a delivery to a the consumer identified by `tag`. -// If unbuffered channels are used for Consume this method -// could block all deliveries until the consumer -// receives on the other end of the channel. -func (me *consumers) send(tag string, msg *Delivery) bool { - me.Lock() - defer me.Unlock() - - buffer, found := me.chans[tag] - if found { - buffer <- msg - } - - return found -} diff --git a/vendor/github.com/streadway/amqp/delivery.go b/vendor/github.com/streadway/amqp/delivery.go deleted file mode 100644 index f84ae4592ab..00000000000 --- a/vendor/github.com/streadway/amqp/delivery.go +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Source code and contact info at http://github.com/streadway/amqp - -package amqp - -import ( - "errors" - "time" -) - -var errDeliveryNotInitialized = errors.New("delivery not initialized") - -// Acknowledger notifies the server of successful or failed consumption of -// delivieries via identifier found in the Delivery.DeliveryTag field. -// -// Applications can provide mock implementations in tests of Delivery handlers. -type Acknowledger interface { - Ack(tag uint64, multiple bool) error - Nack(tag uint64, multiple bool, requeue bool) error - Reject(tag uint64, requeue bool) error -} - -// Delivery captures the fields for a previously delivered message resident in -// a queue to be delivered by the server to a consumer from Channel.Consume or -// Channel.Get. -type Delivery struct { - Acknowledger Acknowledger // the channel from which this delivery arrived - - Headers Table // Application or header exchange table - - // Properties - ContentType string // MIME content type - ContentEncoding string // MIME content encoding - DeliveryMode uint8 // queue implemention use - non-persistent (1) or persistent (2) - Priority uint8 // queue implementation use - 0 to 9 - CorrelationId string // application use - correlation identifier - ReplyTo string // application use - address to to reply to (ex: RPC) - Expiration string // implementation use - message expiration spec - MessageId string // application use - message identifier - Timestamp time.Time // application use - message timestamp - Type string // application use - message type name - UserId string // application use - creating user - should be authenticated user - AppId string // application use - creating application id - - // Valid only with Channel.Consume - ConsumerTag string - - // Valid only with Channel.Get - MessageCount uint32 - - DeliveryTag uint64 - Redelivered bool - Exchange string // basic.publish exhange - RoutingKey string // basic.publish routing key - - Body []byte -} - -func newDelivery(channel *Channel, msg messageWithContent) *Delivery { - props, body := msg.getContent() - - delivery := Delivery{ - Acknowledger: channel, - - Headers: props.Headers, - ContentType: props.ContentType, - ContentEncoding: props.ContentEncoding, - DeliveryMode: props.DeliveryMode, - Priority: props.Priority, - CorrelationId: props.CorrelationId, - ReplyTo: props.ReplyTo, - Expiration: props.Expiration, - MessageId: props.MessageId, - Timestamp: props.Timestamp, - Type: props.Type, - UserId: props.UserId, - AppId: props.AppId, - - Body: body, - } - - // Properties for the delivery types - switch m := msg.(type) { - case *basicDeliver: - delivery.ConsumerTag = m.ConsumerTag - delivery.DeliveryTag = m.DeliveryTag - delivery.Redelivered = m.Redelivered - delivery.Exchange = m.Exchange - delivery.RoutingKey = m.RoutingKey - - case *basicGetOk: - delivery.MessageCount = m.MessageCount - delivery.DeliveryTag = m.DeliveryTag - delivery.Redelivered = m.Redelivered - delivery.Exchange = m.Exchange - delivery.RoutingKey = m.RoutingKey - } - - return &delivery -} - -/* -Ack delegates an acknowledgement through the Acknowledger interface that the -client or server has finished work on a delivery. - -All deliveries in AMQP must be acknowledged. If you called Channel.Consume -with autoAck true then the server will be automatically ack each message and -this method should not be called. Otherwise, you must call Delivery.Ack after -you have successfully processed this delivery. - -When multiple is true, this delivery and all prior unacknowledged deliveries -on the same channel will be acknowledged. This is useful for batch processing -of deliveries. - -An error will indicate that the acknowledge could not be delivered to the -channel it was sent from. - -Either Delivery.Ack, Delivery.Reject or Delivery.Nack must be called for every -delivery that is not automatically acknowledged. -*/ -func (me Delivery) Ack(multiple bool) error { - if me.Acknowledger == nil { - return errDeliveryNotInitialized - } - return me.Acknowledger.Ack(me.DeliveryTag, multiple) -} - -/* -Reject delegates a negatively acknowledgement through the Acknowledger interface. - -When requeue is true, queue this message to be delivered to a consumer on a -different channel. When requeue is false or the server is unable to queue this -message, it will be dropped. - -If you are batch processing deliveries, and your server supports it, prefer -Delivery.Nack. - -Either Delivery.Ack, Delivery.Reject or Delivery.Nack must be called for every -delivery that is not automatically acknowledged. -*/ -func (me Delivery) Reject(requeue bool) error { - if me.Acknowledger == nil { - return errDeliveryNotInitialized - } - return me.Acknowledger.Reject(me.DeliveryTag, requeue) -} - -/* -Nack negatively acknowledge the delivery of message(s) identified by the -delivery tag from either the client or server. - -When multiple is true, nack messages up to and including delivered messages up -until the delivery tag delivered on the same channel. - -When requeue is true, request the server to deliver this message to a different -consumer. If it is not possible or requeue is false, the message will be -dropped or delivered to a server configured dead-letter queue. - -This method must not be used to select or requeue messages the client wishes -not to handle, rather it is to inform the server that the client is incapable -of handling this message at this time. - -Either Delivery.Ack, Delivery.Reject or Delivery.Nack must be called for every -delivery that is not automatically acknowledged. -*/ -func (me Delivery) Nack(multiple, requeue bool) error { - if me.Acknowledger == nil { - return errDeliveryNotInitialized - } - return me.Acknowledger.Nack(me.DeliveryTag, multiple, requeue) -} diff --git a/vendor/github.com/streadway/amqp/delivery_test.go b/vendor/github.com/streadway/amqp/delivery_test.go deleted file mode 100644 index f126f87d8f3..00000000000 --- a/vendor/github.com/streadway/amqp/delivery_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package amqp - -import "testing" - -func shouldNotPanic(t *testing.T) { - if err := recover(); err != nil { - t.Fatalf("should not panic, got: %s", err) - } -} - -// A closed delivery chan could produce zero value. Ack/Nack/Reject on these -// deliveries can produce a nil pointer panic. Instead return an error when -// the method can never be successful. -func TestAckZeroValueAcknowledgerDoesNotPanic(t *testing.T) { - defer shouldNotPanic(t) - if err := (Delivery{}).Ack(false); err == nil { - t.Errorf("expected Delivery{}.Ack to error") - } -} - -func TestNackZeroValueAcknowledgerDoesNotPanic(t *testing.T) { - defer shouldNotPanic(t) - if err := (Delivery{}).Nack(false, false); err == nil { - t.Errorf("expected Delivery{}.Ack to error") - } -} - -func TestRejectZeroValueAcknowledgerDoesNotPanic(t *testing.T) { - defer shouldNotPanic(t) - if err := (Delivery{}).Reject(false); err == nil { - t.Errorf("expected Delivery{}.Ack to error") - } -} diff --git a/vendor/github.com/streadway/amqp/doc.go b/vendor/github.com/streadway/amqp/doc.go deleted file mode 100644 index 94c29f825a1..00000000000 --- a/vendor/github.com/streadway/amqp/doc.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Source code and contact info at http://github.com/streadway/amqp - -/* -AMQP 0.9.1 client with RabbitMQ extensions - -Understand the AMQP 0.9.1 messaging model by reviewing these links first. Much -of the terminology in this library directly relates to AMQP concepts. - - Resources - - http://www.rabbitmq.com/tutorials/amqp-concepts.html - http://www.rabbitmq.com/getstarted.html - http://www.rabbitmq.com/amqp-0-9-1-reference.html - -Design - -Most other broker clients publish to queues, but in AMQP, clients publish -Exchanges instead. AMQP is programmable, meaning that both the producers and -consumers agree on the configuration of the broker, instead requiring an -operator or system configuration that declares the logical topology in the -broker. The routing between producers and consumer queues is via Bindings. -These bindings form the logical topology of the broker. - -In this library, a message sent from publisher is called a "Publishing" and a -message received to a consumer is called a "Delivery". The fields of -Publishings and Deliveries are close but not exact mappings to the underlying -wire format to maintain stronger types. Many other libraries will combine -message properties with message headers. In this library, the message well -known properties are strongly typed fields on the Publishings and Deliveries, -whereas the user defined headers are in the Headers field. - -The method naming closely matches the protocol's method name with positional -parameters mapping to named protocol message fields. The motivation here is to -present a comprehensive view over all possible interactions with the server. - -Generally, methods that map to protocol methods of the "basic" class will be -elided in this interface, and "select" methods of various channel mode selectors -will be elided for example Channel.Confirm and Channel.Tx. - -The library is intentionally designed to be synchronous, where responses for -each protocol message are required to be received in an RPC manner. Some -methods have a noWait parameter like Channel.QueueDeclare, and some methods are -asynchronous like Channel.Publish. The error values should still be checked for -these methods as they will indicate IO failures like when the underlying -connection closes. - -Asynchronous Events - -Clients of this library may be interested in receiving some of the protocol -messages other than Deliveries like basic.ack methods while a channel is in -confirm mode. - -The Notify* methods with Connection and Channel receivers model the pattern of -asynchronous events like closes due to exceptions, or messages that are sent out -of band from an RPC call like basic.ack or basic.flow. - -Any asynchronous events, including Deliveries and Publishings must always have -a receiver until the corresponding chans are closed. Without asynchronous -receivers, the sychronous methods will block. - -Use Case - -It's important as a client to an AMQP topology to ensure the state of the -broker matches your expectations. For both publish and consume use cases, -make sure you declare the queues, exchanges and bindings you expect to exist -prior to calling Channel.Publish or Channel.Consume. - - // Connections start with amqp.Dial() typically from a command line argument - // or environment variable. - connection, err := amqp.Dial(os.Getenv("AMQP_URL")) - - // To cleanly shutdown by flushing kernel buffers, make sure to close and - // wait for the response. - defer connection.Close() - - // Most operations happen on a channel. If any error is returned on a - // channel, the channel will no longer be valid, throw it away and try with - // a different channel. If you use many channels, it's useful for the - // server to - channel, err := connection.Channel() - - // Declare your topology here, if it doesn't exist, it will be created, if - // it existed already and is not what you expect, then that's considered an - // error. - - // Use your connection on this topology with either Publish or Consume, or - // inspect your queues with QueueInspect. It's unwise to mix Publish and - // Consume to let TCP do its job well. - -SSL/TLS - Secure connections - -When Dial encounters an amqps:// scheme, it will use the zero value of a -tls.Config. This will only perform server certificate and host verification. - -Use DialTLS when you wish to provide a client certificate (recommended), -include a private certificate authority's certificate in the cert chain for -server validity, or run insecure by not verifying the server certificate dial -your own connection. DialTLS will use the provided tls.Config when it -encounters an amqps:// scheme and will dial a plain connection when it -encounters an amqp:// scheme. - -SSL/TLS in RabbitMQ is documented here: http://www.rabbitmq.com/ssl.html - -*/ -package amqp diff --git a/vendor/github.com/streadway/amqp/examples_test.go b/vendor/github.com/streadway/amqp/examples_test.go deleted file mode 100644 index 6b581816afe..00000000000 --- a/vendor/github.com/streadway/amqp/examples_test.go +++ /dev/null @@ -1,395 +0,0 @@ -package amqp_test - -import ( - "crypto/tls" - "crypto/x509" - "github.com/streadway/amqp" - "io/ioutil" - "log" - "net" - "runtime" - "time" -) - -func ExampleConfig_timeout() { - // Provide your own anonymous Dial function that delgates to net.DialTimout - // for custom timeouts - - conn, err := amqp.DialConfig("amqp:///", amqp.Config{ - Dial: func(network, addr string) (net.Conn, error) { - return net.DialTimeout(network, addr, 2*time.Second) - }, - }) - - log.Printf("conn: %v, err: %v", conn, err) -} - -func ExampleDialTLS() { - // To get started with SSL/TLS follow the instructions for adding SSL/TLS - // support in RabbitMQ with a private certificate authority here: - // - // http://www.rabbitmq.com/ssl.html - // - // Then in your rabbitmq.config, disable the plain AMQP port, verify clients - // and fail if no certificate is presented with the following: - // - // [ - // {rabbit, [ - // {tcp_listeners, []}, % listens on 127.0.0.1:5672 - // {ssl_listeners, [5671]}, % listens on 0.0.0.0:5671 - // {ssl_options, [{cacertfile,"/path/to/your/testca/cacert.pem"}, - // {certfile,"/path/to/your/server/cert.pem"}, - // {keyfile,"/path/to/your/server/key.pem"}, - // {verify,verify_peer}, - // {fail_if_no_peer_cert,true}]} - // ]} - // ]. - - cfg := new(tls.Config) - - // The self-signing certificate authority's certificate must be included in - // the RootCAs to be trusted so that the server certificate can be verified. - // - // Alternatively to adding it to the tls.Config you can add the CA's cert to - // your system's root CAs. The tls package will use the system roots - // specific to each support OS. Under OS X, add (drag/drop) your cacert.pem - // file to the 'Certificates' section of KeyChain.app to add and always - // trust. - // - // Or with the command line add and trust the DER encoded certificate: - // - // security add-certificate testca/cacert.cer - // security add-trusted-cert testca/cacert.cer - // - // If you depend on the system root CAs, then use nil for the RootCAs field - // so the system roots will be loaded. - - cfg.RootCAs = x509.NewCertPool() - - if ca, err := ioutil.ReadFile("testca/cacert.pem"); err == nil { - cfg.RootCAs.AppendCertsFromPEM(ca) - } - - // Move the client cert and key to a location specific to your application - // and load them here. - - if cert, err := tls.LoadX509KeyPair("client/cert.pem", "client/key.pem"); err == nil { - cfg.Certificates = append(cfg.Certificates, cert) - } - - // Server names are validated by the crypto/tls package, so the server - // certificate must be made for the hostname in the URL. Find the commonName - // (CN) and make sure the hostname in the URL matches this common name. Per - // the RabbitMQ instructions for a self-signed cert, this defautls to the - // current hostname. - // - // openssl x509 -noout -in server/cert.pem -subject - // - // If your server name in your certificate is different than the host you are - // connecting to, set the hostname used for verification in - // ServerName field of the tls.Config struct. - - conn, err := amqp.DialTLS("amqps://server-name-from-certificate/", cfg) - - log.Printf("conn: %v, err: %v", conn, err) -} - -func ExampleChannel_Confirm_bridge() { - // This example acts as a bridge, shoveling all messages sent from the source - // exchange "log" to destination exchange "log". - - // Confirming publishes can help from overproduction and ensure every message - // is delivered. - - // Setup the source of the store and forward - source, err := amqp.Dial("amqp://source/") - if err != nil { - log.Fatalf("connection.open source: %s", err) - } - defer source.Close() - - chs, err := source.Channel() - if err != nil { - log.Fatalf("channel.open source: %s", err) - } - - if err := chs.ExchangeDeclare("log", "topic", true, false, false, false, nil); err != nil { - log.Fatalf("exchange.declare destination: %s", err) - } - - if _, err := chs.QueueDeclare("remote-tee", true, true, false, false, nil); err != nil { - log.Fatalf("queue.declare source: %s", err) - } - - if err := chs.QueueBind("remote-tee", "#", "logs", false, nil); err != nil { - log.Fatalf("queue.bind source: %s", err) - } - - shovel, err := chs.Consume("remote-tee", "shovel", false, false, false, false, nil) - if err != nil { - log.Fatalf("basic.consume source: %s", err) - } - - // Setup the destination of the store and forward - destination, err := amqp.Dial("amqp://destination/") - if err != nil { - log.Fatalf("connection.open destination: %s", err) - } - defer destination.Close() - - chd, err := destination.Channel() - if err != nil { - log.Fatalf("channel.open destination: %s", err) - } - - if err := chd.ExchangeDeclare("log", "topic", true, false, false, false, nil); err != nil { - log.Fatalf("exchange.declare destination: %s", err) - } - - // Buffer of 1 for our single outstanding publishing - pubAcks, pubNacks := chd.NotifyConfirm(make(chan uint64, 1), make(chan uint64, 1)) - - if err := chd.Confirm(false); err != nil { - log.Fatalf("confirm.select destination: %s", err) - } - - // Now pump the messages, one by one, a smarter implementation - // would batch the deliveries and use multiple ack/nacks - for { - msg, ok := <-shovel - if !ok { - log.Fatalf("source channel closed, see the reconnect example for handling this") - } - - err = chd.Publish("logs", msg.RoutingKey, false, false, amqp.Publishing{ - // Copy all the properties - ContentType: msg.ContentType, - ContentEncoding: msg.ContentEncoding, - DeliveryMode: msg.DeliveryMode, - Priority: msg.Priority, - CorrelationId: msg.CorrelationId, - ReplyTo: msg.ReplyTo, - Expiration: msg.Expiration, - MessageId: msg.MessageId, - Timestamp: msg.Timestamp, - Type: msg.Type, - UserId: msg.UserId, - AppId: msg.AppId, - - // Custom headers - Headers: msg.Headers, - - // And the body - Body: msg.Body, - }) - - if err != nil { - msg.Nack(false, false) - log.Fatalf("basic.publish destination: %s", msg) - } - - // only ack the source delivery when the destination acks the publishing - // here you could check for delivery order by keeping a local state of - // expected delivery tags - select { - case <-pubAcks: - msg.Ack(false) - case <-pubNacks: - msg.Nack(false, false) - } - } -} - -func ExampleChannel_Consume() { - // Connects opens an AMQP connection from the credentials in the URL. - conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/") - if err != nil { - log.Fatalf("connection.open: %s", err) - } - defer conn.Close() - - c, err := conn.Channel() - if err != nil { - log.Fatalf("channel.open: %s", err) - } - - // We declare our topology on both the publisher and consumer to ensure they - // are the same. This is part of AMQP being a programmable messaging model. - // - // See the Channel.Publish example for the complimentary declare. - err = c.ExchangeDeclare("logs", "topic", true, false, false, false, nil) - if err != nil { - log.Fatalf("exchange.declare: %s", err) - } - - // Establish our queue topologies that we are responsible for - type bind struct { - queue string - key string - } - - bindings := []bind{ - bind{"page", "alert"}, - bind{"email", "info"}, - bind{"firehose", "#"}, - } - - for _, b := range bindings { - _, err = c.QueueDeclare(b.queue, true, false, false, false, nil) - if err != nil { - log.Fatalf("queue.declare: %v", err) - } - - err = c.QueueBind(b.queue, b.key, "logs", false, nil) - if err != nil { - log.Fatalf("queue.bind: %v", err) - } - } - - // Set our quality of service. Since we're sharing 3 consumers on the same - // channel, we want at least 3 messages in flight. - err = c.Qos(3, 0, false) - if err != nil { - log.Fatalf("basic.qos: %v", err) - } - - // Establish our consumers that have different responsibilities. Our first - // two queues do not ack the messages on the server, so require to be acked - // on the client. - - pages, err := c.Consume("page", "pager", false, false, false, false, nil) - if err != nil { - log.Fatalf("basic.consume: %v", err) - } - - go func() { - for log := range pages { - // ... this consumer is responsible for sending pages per log - log.Ack(false) - } - }() - - // Notice how the concern for which messages arrive here are in the AMQP - // topology and not in the queue. We let the server pick a consumer tag this - // time. - - emails, err := c.Consume("email", "", false, false, false, false, nil) - if err != nil { - log.Fatalf("basic.consume: %v", err) - } - - go func() { - for log := range emails { - // ... this consumer is responsible for sending emails per log - log.Ack(false) - } - }() - - // This consumer requests that every message is acknowledged as soon as it's - // delivered. - - firehose, err := c.Consume("firehose", "", true, false, false, false, nil) - if err != nil { - log.Fatalf("basic.consume: %v", err) - } - - // To show how to process the items in parallel, we'll use a work pool. - for i := 0; i < runtime.NumCPU(); i++ { - go func(work <-chan amqp.Delivery) { - for _ = range work { - // ... this consumer pulls from the firehose and doesn't need to acknowledge - } - }(firehose) - } - - // Wait until you're ready to finish, could be a signal handler here. - time.Sleep(10 * time.Second) - - // Cancelling a consumer by name will finish the range and gracefully end the - // goroutine - err = c.Cancel("pager", false) - if err != nil { - log.Fatalf("basic.cancel: %v", err) - } - - // deferred closing the Connection will also finish the consumer's ranges of - // their delivery chans. If you need every delivery to be processed, make - // sure to wait for all consumers goroutines to finish before exiting your - // process. -} - -func ExampleChannel_Publish() { - // Connects opens an AMQP connection from the credentials in the URL. - conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/") - if err != nil { - log.Fatalf("connection.open: %s", err) - } - - // This waits for a server acknowledgment which means the sockets will have - // flushed all outbound publishings prior to returning. It's important to - // block on Close to not lose any publishings. - defer conn.Close() - - c, err := conn.Channel() - if err != nil { - log.Fatalf("channel.open: %s", err) - } - - // We declare our topology on both the publisher and consumer to ensure they - // are the same. This is part of AMQP being a programmable messaging model. - // - // See the Channel.Consume example for the complimentary declare. - err = c.ExchangeDeclare("logs", "topic", true, false, false, false, nil) - if err != nil { - log.Fatalf("exchange.declare: %v", err) - } - - // Prepare this message to be persistent. Your publishing requirements may - // be different. - msg := amqp.Publishing{ - DeliveryMode: amqp.Persistent, - Timestamp: time.Now(), - ContentType: "text/plain", - Body: []byte("Go Go AMQP!"), - } - - // This is not a mandatory delivery, so it will be dropped if there are no - // queues bound to the logs exchange. - err = c.Publish("logs", "info", false, false, msg) - if err != nil { - // Since publish is asynchronous this can happen if the network connection - // is reset or if the server has run out of resources. - log.Fatalf("basic.publish: %v", err) - } -} - -func publishAllTheThings(conn *amqp.Connection) { - // ... snarf snarf, barf barf -} - -func ExampleConnection_NotifyBlocked() { - // Simply logs when the server throttles the TCP connection for publishers - - // Test this by tuning your server to have a low memory watermark: - // rabbitmqctl set_vm_memory_high_watermark 0.00000001 - - conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/") - if err != nil { - log.Fatalf("connection.open: %s", err) - } - defer conn.Close() - - blockings := conn.NotifyBlocked(make(chan amqp.Blocking)) - go func() { - for b := range blockings { - if b.Active { - log.Printf("TCP blocked: %q", b.Reason) - } else { - log.Printf("TCP unblocked") - } - } - }() - - // Your application domain channel setup publishings - publishAllTheThings(conn) -} diff --git a/vendor/github.com/streadway/amqp/gen.sh b/vendor/github.com/streadway/amqp/gen.sh deleted file mode 100644 index d46e19bd812..00000000000 --- a/vendor/github.com/streadway/amqp/gen.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -go run spec/gen.go < spec/amqp0-9-1.stripped.extended.xml | gofmt > spec091.go diff --git a/vendor/github.com/streadway/amqp/integration_test.go b/vendor/github.com/streadway/amqp/integration_test.go deleted file mode 100644 index 5db5b067d37..00000000000 --- a/vendor/github.com/streadway/amqp/integration_test.go +++ /dev/null @@ -1,1772 +0,0 @@ -// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Source code and contact info at http://github.com/streadway/amqp - -// +build integration - -package amqp - -import ( - "bytes" - devrand "crypto/rand" - "encoding/binary" - "fmt" - "hash/crc32" - "io" - "math/rand" - "net" - "os" - "reflect" - "strconv" - "testing" - "testing/quick" - "time" -) - -func TestIntegrationOpenClose(t *testing.T) { - if c := integrationConnection(t, "open-close"); c != nil { - t.Logf("have connection, calling connection close") - if err := c.Close(); err != nil { - t.Fatalf("connection close: %s", err) - } - t.Logf("connection close OK") - } -} - -func TestIntegrationOpenCloseChannel(t *testing.T) { - if c := integrationConnection(t, "channel"); c != nil { - defer c.Close() - - if _, err := c.Channel(); err != nil { - t.Errorf("Channel could not be opened: %s", err) - } - } -} - -func TestIntegrationOpenConfig(t *testing.T) { - config := Config{} - - c, err := DialConfig(integrationURLFromEnv(), config) - if err != nil { - t.Errorf("expected to dial with config %+v integration server: %s", config, err) - } - - if _, err := c.Channel(); err != nil { - t.Fatalf("expected to open channel: %s", err) - } - - if err := c.Close(); err != nil { - t.Fatalf("connection close: %s", err) - } -} - -func TestIntegrationOpenConfigWithNetDial(t *testing.T) { - config := Config{Dial: net.Dial} - - c, err := DialConfig(integrationURLFromEnv(), config) - if err != nil { - t.Errorf("expected to dial with config %+v integration server: %s", config, err) - } - - if _, err := c.Channel(); err != nil { - t.Fatalf("expected to open channel: %s", err) - } - - if err := c.Close(); err != nil { - t.Fatalf("connection close: %s", err) - } -} - -func TestIntegrationLocalAddr(t *testing.T) { - config := Config{} - - c, err := DialConfig(integrationURLFromEnv(), config) - defer c.Close() - if err != nil { - t.Errorf("expected to dial with config %+v integration server: %s", config, err) - } - - a := c.LocalAddr() - _, portString, err := net.SplitHostPort(a.String()) - if err != nil { - t.Errorf("expected to get a local network address with config %+v integration server: %s", config, a.String()) - } - - port, err := strconv.Atoi(portString) - if err != nil { - t.Errorf("expected to get a TCP port number with config %+v integration server: %s", config, err) - } - t.Logf("Connected to port %d\n", port) -} - -// https://github.com/streadway/amqp/issues/94 -func TestExchangePassiveOnMissingExchangeShouldError(t *testing.T) { - c := integrationConnection(t, "exch") - if c != nil { - defer c.Close() - - ch, err := c.Channel() - if err != nil { - t.Fatalf("create channel 1: %s", err) - } - defer ch.Close() - - if err := ch.ExchangeDeclarePassive( - "test-integration-missing-passive-exchange", - "direct", // type - false, // duration (note: is durable) - true, // auto-delete - false, // internal - false, // nowait - nil, // args - ); err == nil { - t.Fatal("ExchangeDeclarePassive of a missing exchange should return error") - } - } -} - -// https://github.com/streadway/amqp/issues/94 -func TestIntegrationExchangeDeclarePassiveOnDeclaredShouldNotError(t *testing.T) { - c := integrationConnection(t, "exch") - if c != nil { - defer c.Close() - - exchange := "test-integration-decalred-passive-exchange" - - ch, err := c.Channel() - if err != nil { - t.Fatalf("create channel: %s", err) - } - defer ch.Close() - - if err := ch.ExchangeDeclare( - exchange, // name - "direct", // type - false, // durable - true, // auto-delete - false, // internal - false, // nowait - nil, // args - ); err != nil { - t.Fatalf("declare exchange: %s", err) - } - - if err := ch.ExchangeDeclarePassive( - exchange, // name - "direct", // type - false, // durable - true, // auto-delete - false, // internal - false, // nowait - nil, // args - ); err != nil { - t.Fatalf("ExchangeDeclarePassive on a declared exchange should not error, got: %q", err) - } - } -} - -func TestIntegrationExchange(t *testing.T) { - c := integrationConnection(t, "exch") - if c != nil { - defer c.Close() - - channel, err := c.Channel() - if err != nil { - t.Fatalf("create channel: %s", err) - } - t.Logf("create channel OK") - - exchange := "test-integration-exchange" - - if err := channel.ExchangeDeclare( - exchange, // name - "direct", // type - false, // duration - true, // auto-delete - false, // internal - false, // nowait - nil, // args - ); err != nil { - t.Fatalf("declare exchange: %s", err) - } - t.Logf("declare exchange OK") - - if err := channel.ExchangeDelete(exchange, false, false); err != nil { - t.Fatalf("delete exchange: %s", err) - } - t.Logf("delete exchange OK") - - if err := channel.Close(); err != nil { - t.Fatalf("close channel: %s", err) - } - t.Logf("close channel OK") - } -} - -// https://github.com/streadway/amqp/issues/94 -func TestIntegrationQueueDeclarePassiveOnMissingExchangeShouldError(t *testing.T) { - c := integrationConnection(t, "queue") - if c != nil { - defer c.Close() - - ch, err := c.Channel() - if err != nil { - t.Fatalf("create channel1: %s", err) - } - defer ch.Close() - - if _, err := ch.QueueDeclarePassive( - "test-integration-missing-passive-queue", // name - false, // duration (note: not durable) - true, // auto-delete - false, // exclusive - false, // noWait - nil, // arguments - ); err == nil { - t.Fatal("QueueDeclarePassive of a missing queue should error") - } - } -} - -// https://github.com/streadway/amqp/issues/94 -func TestIntegrationPassiveQueue(t *testing.T) { - c := integrationConnection(t, "queue") - if c != nil { - defer c.Close() - - name := "test-integration-declared-passive-queue" - - ch, err := c.Channel() - if err != nil { - t.Fatalf("create channel1: %s", err) - } - defer ch.Close() - - if _, err := ch.QueueDeclare( - name, // name - false, // durable - true, // auto-delete - false, // exclusive - false, // noWait - nil, // arguments - ); err != nil { - t.Fatalf("queue declare: %s", err) - } - - if _, err := ch.QueueDeclarePassive( - name, // name - false, // durable - true, // auto-delete - false, // exclusive - false, // noWait - nil, // arguments - ); err != nil { - t.Fatalf("QueueDeclarePassive on declared queue should not error, got: %q", err) - } - - if _, err := ch.QueueDeclarePassive( - name, // name - true, // durable (note: differs) - true, // auto-delete - false, // exclusive - false, // noWait - nil, // arguments - ); err != nil { - t.Fatalf("QueueDeclarePassive on declared queue with different flags should error") - } - } -} - -func TestIntegrationBasicQueueOperations(t *testing.T) { - c := integrationConnection(t, "queue") - if c != nil { - defer c.Close() - - channel, err := c.Channel() - if err != nil { - t.Fatalf("create channel: %s", err) - } - t.Logf("create channel OK") - - exchangeName := "test-basic-ops-exchange" - queueName := "test-basic-ops-queue" - - deleteQueueFirstOptions := []bool{true, false} - for _, deleteQueueFirst := range deleteQueueFirstOptions { - - if err := channel.ExchangeDeclare( - exchangeName, // name - "direct", // type - true, // duration (note: is durable) - false, // auto-delete - false, // internal - false, // nowait - nil, // args - ); err != nil { - t.Fatalf("declare exchange: %s", err) - } - t.Logf("declare exchange OK") - - if _, err := channel.QueueDeclare( - queueName, // name - true, // duration (note: durable) - false, // auto-delete - false, // exclusive - false, // noWait - nil, // arguments - ); err != nil { - t.Fatalf("queue declare: %s", err) - } - t.Logf("declare queue OK") - - if err := channel.QueueBind( - queueName, // name - "", // routingKey - exchangeName, // sourceExchange - false, // noWait - nil, // arguments - ); err != nil { - t.Fatalf("queue bind: %s", err) - } - t.Logf("queue bind OK") - - if deleteQueueFirst { - if _, err := channel.QueueDelete( - queueName, // name - false, // ifUnused (false=be aggressive) - false, // ifEmpty (false=be aggressive) - false, // noWait - ); err != nil { - t.Fatalf("delete queue (first): %s", err) - } - t.Logf("delete queue (first) OK") - - if err := channel.ExchangeDelete(exchangeName, false, false); err != nil { - t.Fatalf("delete exchange (after delete queue): %s", err) - } - t.Logf("delete exchange (after delete queue) OK") - - } else { // deleteExchangeFirst - if err := channel.ExchangeDelete(exchangeName, false, false); err != nil { - t.Fatalf("delete exchange (first): %s", err) - } - t.Logf("delete exchange (first) OK") - - if _, err := channel.QueueInspect(queueName); err != nil { - t.Fatalf("inspect queue state after deleting exchange: %s", err) - } - t.Logf("queue properly remains after exchange is deleted") - - if _, err := channel.QueueDelete( - queueName, - false, // ifUnused - false, // ifEmpty - false, // noWait - ); err != nil { - t.Fatalf("delete queue (after delete exchange): %s", err) - } - t.Logf("delete queue (after delete exchange) OK") - } - } - - if err := channel.Close(); err != nil { - t.Fatalf("close channel: %s", err) - } - t.Logf("close channel OK") - } -} - -func TestIntegrationConnectionNegotiatesMaxChannels(t *testing.T) { - config := Config{ChannelMax: 0} - - c, err := DialConfig(integrationURLFromEnv(), config) - if err != nil { - t.Errorf("expected to dial with config %+v integration server: %s", config, err) - } - defer c.Close() - - if want, got := defaultChannelMax, c.Config.ChannelMax; want != got { - t.Fatalf("expected connection to negotiate uint16 (%d) channels, got: %d", want, got) - } -} - -func TestIntegrationConnectionNegotiatesClientMaxChannels(t *testing.T) { - config := Config{ChannelMax: 16} - - c, err := DialConfig(integrationURLFromEnv(), config) - if err != nil { - t.Errorf("expected to dial with config %+v integration server: %s", config, err) - } - defer c.Close() - - if want, got := config.ChannelMax, c.Config.ChannelMax; want != got { - t.Fatalf("expected client specified channel limit after handshake %d, got: %d", want, got) - } -} - -func TestIntegrationChannelIDsExhausted(t *testing.T) { - config := Config{ChannelMax: 16} - - c, err := DialConfig(integrationURLFromEnv(), config) - if err != nil { - t.Errorf("expected to dial with config %+v integration server: %s", config, err) - } - defer c.Close() - - for i := 1; i <= c.Config.ChannelMax; i++ { - if _, err := c.Channel(); err != nil { - t.Fatalf("expected allocating all channel ids to succed, failed on %d with %v", i, err) - } - } - - if _, err := c.Channel(); err != ErrChannelMax { - t.Fatalf("expected allocating all channels to produce the client side error %#v, got: %#v", ErrChannelMax, err) - } -} - -func TestIntegrationChannelClosing(t *testing.T) { - c := integrationConnection(t, "closings") - if c != nil { - defer c.Close() - - // This function is run on every channel after it is successfully - // opened. It can do something to verify something. It should be - // quick; many channels may be opened! - f := func(t *testing.T, c *Channel) { - return - } - - // open and close - channel, err := c.Channel() - if err != nil { - t.Fatalf("basic create channel: %s", err) - } - t.Logf("basic create channel OK") - - if err := channel.Close(); err != nil { - t.Fatalf("basic close channel: %s", err) - } - t.Logf("basic close channel OK") - - // deferred close - signal := make(chan bool) - go func() { - channel, err := c.Channel() - if err != nil { - t.Fatalf("second create channel: %s", err) - } - t.Logf("second create channel OK") - - <-signal // a bit of synchronization - f(t, channel) - - defer func() { - if err := channel.Close(); err != nil { - t.Fatalf("deferred close channel: %s", err) - } - t.Logf("deferred close channel OK") - signal <- true - }() - }() - signal <- true - select { - case <-signal: - t.Logf("(got close signal OK)") - break - case <-time.After(250 * time.Millisecond): - t.Fatalf("deferred close: timeout") - } - - // multiple channels - for _, n := range []int{2, 4, 8, 16, 32, 64, 128, 256} { - channels := make([]*Channel, n) - for i := 0; i < n; i++ { - var err error - if channels[i], err = c.Channel(); err != nil { - t.Fatalf("create channel %d/%d: %s", i+1, n, err) - } - } - f(t, channel) - for i, channel := range channels { - if err := channel.Close(); err != nil { - t.Fatalf("close channel %d/%d: %s", i+1, n, err) - } - } - t.Logf("created/closed %d channels OK", n) - } - - } -} - -func TestIntegrationMeaningfulChannelErrors(t *testing.T) { - c := integrationConnection(t, "pub") - if c != nil { - defer c.Close() - - ch, err := c.Channel() - if err != nil { - t.Fatalf("Could not create channel") - } - - queue := "test.integration.channel.error" - - _, err = ch.QueueDeclare(queue, false, true, false, false, nil) - if err != nil { - t.Fatalf("Could not declare") - } - - _, err = ch.QueueDeclare(queue, true, false, false, false, nil) - if err == nil { - t.Fatalf("Expected error, got nil") - } - - e, ok := err.(*Error) - if !ok { - t.Fatalf("Expected type Error response, got %T", err) - } - - if e.Code != PreconditionFailed { - t.Fatalf("Expected PreconditionFailed, got: %+v", e) - } - - _, err = ch.QueueDeclare(queue, false, true, false, false, nil) - if err != ErrClosed { - t.Fatalf("Expected channel to be closed, got: %T", err) - } - } -} - -// https://github.com/streadway/amqp/issues/6 -func TestIntegrationNonBlockingClose(t *testing.T) { - c := integrationConnection(t, "#6") - if c != nil { - defer c.Close() - - ch, err := c.Channel() - if err != nil { - t.Fatalf("Could not create channel") - } - - queue := "test.integration.blocking.close" - - _, err = ch.QueueDeclare(queue, false, true, false, false, nil) - if err != nil { - t.Fatalf("Could not declare") - } - - msgs, err := ch.Consume(queue, "", false, false, false, false, nil) - if err != nil { - t.Fatalf("Could not consume") - } - - // Simulate a consumer - go func() { - for _ = range msgs { - t.Logf("Oh my, received message on an empty queue") - } - }() - - succeed := make(chan bool) - - go func() { - if err = ch.Close(); err != nil { - t.Fatalf("Close produced an error when it shouldn't") - } - succeed <- true - }() - - select { - case <-succeed: - break - case <-time.After(1 * time.Second): - t.Fatalf("Close timed out after 1s") - } - } -} - -func TestIntegrationPublishConsume(t *testing.T) { - queue := "test.integration.publish.consume" - - c1 := integrationConnection(t, "pub") - c2 := integrationConnection(t, "sub") - - if c1 != nil && c2 != nil { - defer c1.Close() - defer c2.Close() - - pub, _ := c1.Channel() - sub, _ := c2.Channel() - - pub.QueueDeclare(queue, false, true, false, false, nil) - sub.QueueDeclare(queue, false, true, false, false, nil) - defer pub.QueueDelete(queue, false, false, false) - - messages, _ := sub.Consume(queue, "", false, false, false, false, nil) - - pub.Publish("", queue, false, false, Publishing{Body: []byte("pub 1")}) - pub.Publish("", queue, false, false, Publishing{Body: []byte("pub 2")}) - pub.Publish("", queue, false, false, Publishing{Body: []byte("pub 3")}) - - assertConsumeBody(t, messages, []byte("pub 1")) - assertConsumeBody(t, messages, []byte("pub 2")) - assertConsumeBody(t, messages, []byte("pub 3")) - } -} - -func TestIntegrationConsumeFlow(t *testing.T) { - queue := "test.integration.consumer-flow" - - c1 := integrationConnection(t, "pub-flow") - c2 := integrationConnection(t, "sub-flow") - - if c1 != nil && c2 != nil { - defer c1.Close() - defer c2.Close() - - pub, _ := c1.Channel() - sub, _ := c2.Channel() - - pub.QueueDeclare(queue, false, true, false, false, nil) - sub.QueueDeclare(queue, false, true, false, false, nil) - defer pub.QueueDelete(queue, false, false, false) - - sub.Qos(1, 0, false) - - messages, _ := sub.Consume(queue, "", false, false, false, false, nil) - - pub.Publish("", queue, false, false, Publishing{Body: []byte("pub 1")}) - pub.Publish("", queue, false, false, Publishing{Body: []byte("pub 2")}) - - msg := assertConsumeBody(t, messages, []byte("pub 1")) - - if err := sub.Flow(false); err.(*Error).Code == NotImplemented { - t.Log("flow control is not supported on this version of rabbitmq") - return - } - - msg.Ack(false) - - select { - case <-messages: - t.Fatalf("message was delivered when flow was not active") - default: - } - - sub.Flow(true) - - msg = assertConsumeBody(t, messages, []byte("pub 2")) - msg.Ack(false) - } -} - -func TestIntegrationRecoverNotImplemented(t *testing.T) { - queue := "test.recover" - - if c, ch := integrationQueue(t, queue); c != nil { - if product, ok := c.Properties["product"]; ok && product.(string) == "RabbitMQ" { - defer c.Close() - - err := ch.Recover(false) - - if ex, ok := err.(*Error); !ok || ex.Code != 540 { - t.Fatalf("Expected NOT IMPLEMENTED got: %v", ex) - } - } - } -} - -// This test is driven by a private API to simulate the server sending a channelFlow message -func TestIntegrationPublishFlow(t *testing.T) { - // TODO - no idea how to test without affecting the server or mucking internal APIs - // i'd like to make sure the RW lock can be held by multiple publisher threads - // and that multiple channelFlow messages do not block the dispatch thread -} - -func TestIntegrationConsumeCancel(t *testing.T) { - queue := "test.integration.consume-cancel" - - c := integrationConnection(t, "pub") - - if c != nil { - defer c.Close() - - ch, _ := c.Channel() - - ch.QueueDeclare(queue, false, true, false, false, nil) - defer ch.QueueDelete(queue, false, false, false) - - messages, _ := ch.Consume(queue, "integration-tag", false, false, false, false, nil) - - ch.Publish("", queue, false, false, Publishing{Body: []byte("1")}) - - assertConsumeBody(t, messages, []byte("1")) - - err := ch.Cancel("integration-tag", false) - if err != nil { - t.Fatalf("error cancelling the consumer: %v", err) - } - - ch.Publish("", queue, false, false, Publishing{Body: []byte("2")}) - - select { - case <-time.After(100 * time.Millisecond): - t.Fatalf("Timeout on Close") - case _, ok := <-messages: - if ok { - t.Fatalf("Extra message on consumer when consumer should have been closed") - } - } - } -} - -func (c *Connection) Generate(r *rand.Rand, _ int) reflect.Value { - urlStr := os.Getenv("AMQP_URL") - if urlStr == "" { - return reflect.ValueOf(nil) - } - - conn, err := Dial(urlStr) - if err != nil { - return reflect.ValueOf(nil) - } - - return reflect.ValueOf(conn) -} - -func (c Publishing) Generate(r *rand.Rand, _ int) reflect.Value { - var ok bool - var t reflect.Value - - p := Publishing{} - //p.DeliveryMode = uint8(r.Intn(3)) - //p.Priority = uint8(r.Intn(8)) - - if r.Intn(2) > 0 { - p.ContentType = "application/octet-stream" - } - - if r.Intn(2) > 0 { - p.ContentEncoding = "gzip" - } - - if r.Intn(2) > 0 { - p.CorrelationId = fmt.Sprintf("%d", r.Int()) - } - - if r.Intn(2) > 0 { - p.ReplyTo = fmt.Sprintf("%d", r.Int()) - } - - if r.Intn(2) > 0 { - p.MessageId = fmt.Sprintf("%d", r.Int()) - } - - if r.Intn(2) > 0 { - p.Type = fmt.Sprintf("%d", r.Int()) - } - - if r.Intn(2) > 0 { - p.AppId = fmt.Sprintf("%d", r.Int()) - } - - if r.Intn(2) > 0 { - p.Timestamp = time.Unix(r.Int63(), r.Int63()) - } - - if t, ok = quick.Value(reflect.TypeOf(p.Body), r); ok { - p.Body = t.Bytes() - } - - return reflect.ValueOf(p) -} - -func TestQuickPublishOnly(t *testing.T) { - if c := integrationConnection(t, "quick"); c != nil { - defer c.Close() - pub, err := c.Channel() - queue := "test-publish" - - if _, err = pub.QueueDeclare(queue, false, true, false, false, nil); err != nil { - t.Errorf("Failed to declare: %s", err) - return - } - - defer pub.QueueDelete(queue, false, false, false) - - quick.Check(func(msg Publishing) bool { - return pub.Publish("", queue, false, false, msg) == nil - }, nil) - } -} - -func TestPublishEmptyBody(t *testing.T) { - c := integrationConnection(t, "empty") - if c != nil { - defer c.Close() - - ch, err := c.Channel() - if err != nil { - t.Errorf("Failed to create channel") - return - } - - queue := "test-TestPublishEmptyBody" - - if _, err := ch.QueueDeclare(queue, false, true, false, false, nil); err != nil { - t.Fatalf("Could not declare") - } - - messages, err := ch.Consume(queue, "", false, false, false, false, nil) - if err != nil { - t.Fatalf("Could not consume") - } - - err = ch.Publish("", queue, false, false, Publishing{}) - if err != nil { - t.Fatalf("Could not publish") - } - - select { - case msg := <-messages: - if len(msg.Body) != 0 { - t.Errorf("Received non empty body") - } - case <-time.After(200 * time.Millisecond): - t.Errorf("Timeout on receive") - } - } -} - -func TestPublishEmptyBodyWithHeadersIssue67(t *testing.T) { - c := integrationConnection(t, "issue67") - if c != nil { - defer c.Close() - - ch, err := c.Channel() - if err != nil { - t.Errorf("Failed to create channel") - return - } - - queue := "test-TestPublishEmptyBodyWithHeaders" - - if _, err := ch.QueueDeclare(queue, false, true, false, false, nil); err != nil { - t.Fatalf("Could not declare") - } - - messages, err := ch.Consume(queue, "", false, false, false, false, nil) - if err != nil { - t.Fatalf("Could not consume") - } - - headers := Table{ - "ham": "spam", - } - - err = ch.Publish("", queue, false, false, Publishing{Headers: headers}) - if err != nil { - t.Fatalf("Could not publish") - } - - select { - case msg := <-messages: - if msg.Headers["ham"] == nil { - t.Fatalf("Headers aren't sent") - } - if msg.Headers["ham"] != "spam" { - t.Fatalf("Headers are wrong") - } - case <-time.After(200 * time.Millisecond): - t.Errorf("Timeout on receive") - } - } -} - -func TestQuickPublishConsumeOnly(t *testing.T) { - c1 := integrationConnection(t, "quick-pub") - c2 := integrationConnection(t, "quick-sub") - - if c1 != nil && c2 != nil { - defer c1.Close() - defer c2.Close() - - pub, err := c1.Channel() - sub, err := c2.Channel() - - queue := "TestPublishConsumeOnly" - - if _, err = pub.QueueDeclare(queue, false, true, false, false, nil); err != nil { - t.Errorf("Failed to declare: %s", err) - return - } - - if _, err = sub.QueueDeclare(queue, false, true, false, false, nil); err != nil { - t.Errorf("Failed to declare: %s", err) - return - } - - defer sub.QueueDelete(queue, false, false, false) - - ch, err := sub.Consume(queue, "", false, false, false, false, nil) - if err != nil { - t.Errorf("Could not sub: %s", err) - } - - quick.CheckEqual( - func(msg Publishing) []byte { - empty := Publishing{Body: msg.Body} - if pub.Publish("", queue, false, false, empty) != nil { - return []byte{'X'} - } - return msg.Body - }, - func(msg Publishing) []byte { - out := <-ch - out.Ack(false) - return out.Body - }, - nil) - } -} - -func TestQuickPublishConsumeBigBody(t *testing.T) { - c1 := integrationConnection(t, "big-pub") - c2 := integrationConnection(t, "big-sub") - - if c1 != nil && c2 != nil { - defer c1.Close() - defer c2.Close() - - pub, err := c1.Channel() - sub, err := c2.Channel() - - queue := "test-pubsub" - - if _, err = sub.QueueDeclare(queue, false, true, false, false, nil); err != nil { - t.Errorf("Failed to declare: %s", err) - return - } - - ch, err := sub.Consume(queue, "", false, false, false, false, nil) - if err != nil { - t.Errorf("Could not sub: %s", err) - } - - fixture := Publishing{ - Body: make([]byte, 1e4+1000), - } - - if _, err = pub.QueueDeclare(queue, false, true, false, false, nil); err != nil { - t.Errorf("Failed to declare: %s", err) - return - } - - err = pub.Publish("", queue, false, false, fixture) - if err != nil { - t.Errorf("Could not publish big body") - } - - select { - case msg := <-ch: - if bytes.Compare(msg.Body, fixture.Body) != 0 { - t.Errorf("Consumed big body didn't match") - } - case <-time.After(200 * time.Millisecond): - t.Errorf("Timeout on receive") - } - } -} - -func TestIntegrationGetOk(t *testing.T) { - if c := integrationConnection(t, "getok"); c != nil { - defer c.Close() - - queue := "test.get-ok" - ch, _ := c.Channel() - - ch.QueueDeclare(queue, false, true, false, false, nil) - ch.Publish("", queue, false, false, Publishing{Body: []byte("ok")}) - - msg, ok, err := ch.Get(queue, false) - - if err != nil { - t.Fatalf("Failed get: %v", err) - } - - if !ok { - t.Fatalf("Get on a queued message did not find the message") - } - - if string(msg.Body) != "ok" { - t.Fatalf("Get did not get the correct message") - } - } -} - -func TestIntegrationGetEmpty(t *testing.T) { - if c := integrationConnection(t, "getok"); c != nil { - defer c.Close() - - queue := "test.get-ok" - ch, _ := c.Channel() - - ch.QueueDeclare(queue, false, true, false, false, nil) - - _, ok, err := ch.Get(queue, false) - - if err != nil { - t.Fatalf("Failed get: %v", err) - } - - if !ok { - t.Fatalf("Get on a queued message retrieved a message when it shouldn't have") - } - } -} - -func TestIntegrationTxCommit(t *testing.T) { - if c := integrationConnection(t, "txcommit"); c != nil { - defer c.Close() - - queue := "test.tx.commit" - ch, _ := c.Channel() - - ch.QueueDeclare(queue, false, true, false, false, nil) - - if err := ch.Tx(); err != nil { - t.Fatalf("tx.select failed") - } - - ch.Publish("", queue, false, false, Publishing{Body: []byte("ok")}) - - if err := ch.TxCommit(); err != nil { - t.Fatalf("tx.commit failed") - } - - msg, ok, err := ch.Get(queue, false) - - if err != nil || !ok { - t.Fatalf("Failed get: %v", err) - } - - if string(msg.Body) != "ok" { - t.Fatalf("Get did not get the correct message from the transaction") - } - } -} - -func TestIntegrationTxRollback(t *testing.T) { - if c := integrationConnection(t, "txrollback"); c != nil { - defer c.Close() - - queue := "test.tx.rollback" - ch, _ := c.Channel() - - ch.QueueDeclare(queue, false, true, false, false, nil) - - if err := ch.Tx(); err != nil { - t.Fatalf("tx.select failed") - } - - ch.Publish("", queue, false, false, Publishing{Body: []byte("ok")}) - - if err := ch.TxRollback(); err != nil { - t.Fatalf("tx.rollback failed") - } - - _, ok, err := ch.Get(queue, false) - - if err != nil { - t.Fatalf("Failed get: %v", err) - } - - if ok { - t.Fatalf("message was published when it should have been rolled back") - } - } -} - -func TestIntegrationReturn(t *testing.T) { - if c, ch := integrationQueue(t, "return"); c != nil { - defer c.Close() - - ret := make(chan Return, 1) - - ch.NotifyReturn(ret) - - // mandatory publish to an exchange without a binding should be returned - ch.Publish("", "return-without-binding", true, false, Publishing{Body: []byte("mandatory")}) - - select { - case res := <-ret: - if string(res.Body) != "mandatory" { - t.Fatalf("expected return of the same message") - } - - if res.ReplyCode != NoRoute { - t.Fatalf("expected no consumers reply code on the Return result, got: %v", res.ReplyCode) - } - - case <-time.After(200 * time.Millisecond): - t.Fatalf("no return was received within 200ms") - } - } -} - -func TestIntegrationCancel(t *testing.T) { - queue := "cancel" - consumerTag := "test.cancel" - - if c, ch := integrationQueue(t, queue); c != nil { - defer c.Close() - - cancels := ch.NotifyCancel(make(chan string, 1)) - - go func() { - if _, err := ch.Consume(queue, consumerTag, false, false, false, false, nil); err != nil { - t.Fatalf("cannot consume from %q to test NotifyCancel: %v", queue, err) - } - if _, err := ch.QueueDelete(queue, false, false, false); err != nil { - t.Fatalf("cannot delete integration queue: %v", err) - } - }() - - select { - case tag := <-cancels: - if want, got := consumerTag, tag; want != got { - t.Fatalf("expected to be notified of deleted queue with consumer tag, got: %q", got) - } - case <-time.After(200 * time.Millisecond): - t.Fatalf("expected to be notified of deleted queue with 200ms") - } - } -} - -func TestIntegrationConfirm(t *testing.T) { - if c, ch := integrationQueue(t, "confirm"); c != nil { - defer c.Close() - - ack, nack := make(chan uint64, 1), make(chan uint64, 1) - - ch.NotifyConfirm(ack, nack) - - if err := ch.Confirm(false); err != nil { - t.Fatalf("could not confirm") - } - - ch.Publish("", "confirm", false, false, Publishing{Body: []byte("confirm")}) - - select { - case tag := <-ack: - if tag != 1 { - t.Fatalf("expected ack starting with delivery tag of 1") - } - case <-time.After(200 * time.Millisecond): - t.Fatalf("no ack was received within 200ms") - } - } -} - -// https://github.com/streadway/amqp/issues/61 -func TestRoundTripAllFieldValueTypes61(t *testing.T) { - if conn := integrationConnection(t, "issue61"); conn != nil { - defer conn.Close() - timestamp := time.Unix(100000000, 0) - - headers := Table{ - "A": []interface{}{ - []interface{}{"nested array", int32(3)}, - Decimal{2, 1}, - Table{"S": "nested table in array"}, - int32(2 << 20), - string("array string"), - timestamp, - nil, - byte(2), - float64(2.64), - float32(2.32), - int64(2 << 60), - int16(2 << 10), - bool(true), - []byte{'b', '2'}, - }, - "D": Decimal{1, 1}, - "F": Table{"S": "nested table in table"}, - "I": int32(1 << 20), - "S": string("string"), - "T": timestamp, - "V": nil, - "b": byte(1), - "d": float64(1.64), - "f": float32(1.32), - "l": int64(1 << 60), - "s": int16(1 << 10), - "t": bool(true), - "x": []byte{'b', '1'}, - } - - queue := "test.issue61-roundtrip" - ch, _ := conn.Channel() - - if _, err := ch.QueueDeclare(queue, false, true, false, false, nil); err != nil { - t.Fatalf("Could not declare") - } - - msgs, err := ch.Consume(queue, "", false, false, false, false, nil) - if err != nil { - t.Fatalf("Could not consume") - } - - err = ch.Publish("", queue, false, false, Publishing{Body: []byte("ignored"), Headers: headers}) - if err != nil { - t.Fatalf("Could not publish: %v", err) - } - - msg, ok := <-msgs - - if !ok { - t.Fatalf("Channel closed prematurely likely due to publish exception") - } - - for k, v := range headers { - if !reflect.DeepEqual(v, msg.Headers[k]) { - t.Errorf("Round trip header not the same for key %q: expected: %#v, got %#v", k, v, msg.Headers[k]) - } - } - } -} - -// Declares a queue with the x-message-ttl extension to exercise integer -// serialization. -// -// Relates to https://github.com/streadway/amqp/issues/60 -// -func TestDeclareArgsXMessageTTL(t *testing.T) { - if conn := integrationConnection(t, "declareTTL"); conn != nil { - defer conn.Close() - - ch, _ := conn.Channel() - args := Table{"x-message-ttl": int32(9000000)} - - // should not drop the connection - if _, err := ch.QueueDeclare("declareWithTTL", false, true, false, false, args); err != nil { - t.Fatalf("cannot declare with TTL: got: %v", err) - } - } -} - -// Sets up the topology where rejected messages will be forwarded -// to a fanout exchange, with a single queue bound. -// -// Relates to https://github.com/streadway/amqp/issues/56 -// -func TestDeclareArgsRejectToDeadLetterQueue(t *testing.T) { - if conn := integrationConnection(t, "declareArgs"); conn != nil { - defer conn.Close() - - ex, q := "declareArgs", "declareArgs-deliveries" - dlex, dlq := ex+"-dead-letter", q+"-dead-letter" - - ch, _ := conn.Channel() - - if err := ch.ExchangeDeclare(ex, "fanout", false, true, false, false, nil); err != nil { - t.Fatalf("cannot declare %v: got: %v", ex, err) - } - - if err := ch.ExchangeDeclare(dlex, "fanout", false, true, false, false, nil); err != nil { - t.Fatalf("cannot declare %v: got: %v", dlex, err) - } - - if _, err := ch.QueueDeclare(dlq, false, true, false, false, nil); err != nil { - t.Fatalf("cannot declare %v: got: %v", dlq, err) - } - - if err := ch.QueueBind(dlq, "#", dlex, false, nil); err != nil { - t.Fatalf("cannot bind %v to %v: got: %v", dlq, dlex, err) - } - - if _, err := ch.QueueDeclare(q, false, true, false, false, Table{ - "x-dead-letter-exchange": dlex, - }); err != nil { - t.Fatalf("cannot declare %v with dlq %v: got: %v", q, dlex, err) - } - - if err := ch.QueueBind(q, "#", ex, false, nil); err != nil { - t.Fatalf("cannot bind %v: got: %v", ex, err) - } - - fails, err := ch.Consume(q, "", false, false, false, false, nil) - if err != nil { - t.Fatalf("cannot consume %v: got: %v", q, err) - } - - // Reject everything consumed - go func() { - for d := range fails { - d.Reject(false) - } - }() - - // Publish the 'poison' - if err := ch.Publish(ex, q, true, false, Publishing{Body: []byte("ignored")}); err != nil { - t.Fatalf("publishing failed") - } - - // spin-get until message arrives on the dead-letter queue with a - // synchronous parse to exercise the array field (x-death) set by the - // server relating to issue-56 - for i := 0; i < 10; i++ { - d, got, err := ch.Get(dlq, false) - if !got && err == nil { - continue - } else if err != nil { - t.Fatalf("expected success in parsing reject, got: %v", err) - } else { - // pass if we've parsed an array - if v, ok := d.Headers["x-death"]; ok { - if _, ok := v.([]interface{}); ok { - return - } - } - t.Fatalf("array field x-death expected in the headers, got: %v (%T)", d.Headers, d.Headers["x-death"]) - } - } - - t.Fatalf("expectd dead-letter after 10 get attempts") - } -} - -// https://github.com/streadway/amqp/issues/48 -func TestDeadlockConsumerIssue48(t *testing.T) { - if conn := integrationConnection(t, "issue48"); conn != nil { - defer conn.Close() - - deadline := make(chan bool) - go func() { - select { - case <-time.After(5 * time.Second): - panic("expected to receive 2 deliveries while in an RPC, got a deadlock") - case <-deadline: - // pass - } - }() - - ch, err := conn.Channel() - if err != nil { - t.Fatalf("got error on channel.open: %v", err) - } - - queue := "test-issue48" - - if _, err := ch.QueueDeclare(queue, false, true, false, false, nil); err != nil { - t.Fatalf("expected to declare a queue: %v", err) - } - - if err := ch.Confirm(false); err != nil { - t.Fatalf("got error on confirm: %v", err) - } - - ack, nack := make(chan uint64, 2), make(chan uint64, 2) - ch.NotifyConfirm(ack, nack) - - for i := 0; i < cap(ack); i++ { - // Fill the queue with some new or remaining publishings - ch.Publish("", queue, false, false, Publishing{Body: []byte("")}) - } - - for i := 0; i < cap(ack); i++ { - // Wait for them to land on the queue so they'll be delivered on consume - <-ack - } - - // Consuming should send them all on the wire - msgs, err := ch.Consume(queue, "", false, false, false, false, nil) - if err != nil { - t.Fatalf("got error on consume: %v", err) - } - - // We pop one off the chan, the other is on the wire - <-msgs - - // Opening a new channel (any RPC) while another delivery is on the wire - if _, err := conn.Channel(); err != nil { - t.Fatalf("got error on consume: %v", err) - } - - // We pop the next off the chan - <-msgs - - deadline <- true - } -} - -// https://github.com/streadway/amqp/issues/46 -func TestRepeatedChannelExceptionWithPublishAndMaxProcsIssue46(t *testing.T) { - conn := integrationConnection(t, "issue46") - if conn != nil { - for i := 0; i < 100; i++ { - ch, err := conn.Channel() - if err != nil { - t.Fatalf("expected error only on publish, got error on channel.open: %v", err) - } - - for j := 0; j < 10; j++ { - err = ch.Publish("not-existing-exchange", "some-key", false, false, Publishing{Body: []byte("some-data")}) - if err, ok := err.(Error); ok { - if err.Code != 504 { - t.Fatalf("expected channel only exception, got: %v", err) - } - } - } - } - } -} - -// https://github.com/streadway/amqp/issues/43 -func TestChannelExceptionWithCloseIssue43(t *testing.T) { - conn := integrationConnection(t, "issue43") - if conn != nil { - go func() { - for err := range conn.NotifyClose(make(chan *Error)) { - t.Log(err.Error()) - } - }() - - c1, err := conn.Channel() - if err != nil { - panic(err) - } - - go func() { - for err := range c1.NotifyClose(make(chan *Error)) { - t.Log("Channel1 Close: " + err.Error()) - } - }() - - c2, err := conn.Channel() - if err != nil { - panic(err) - } - - go func() { - for err := range c2.NotifyClose(make(chan *Error)) { - t.Log("Channel2 Close: " + err.Error()) - } - }() - - // Cause an asynchronous channel exception causing the server - // to send a "channel.close" method either before or after the next - // asynchronous method. - err = c1.Publish("nonexisting-exchange", "", false, false, Publishing{}) - if err != nil { - panic(err) - } - - // Receive or send the channel close method, the channel shuts down - // but this expects a channel.close-ok to be received. - c1.Close() - - // This ensures that the 2nd channel is unaffected by the channel exception - // on channel 1. - err = c2.ExchangeDeclare("test-channel-still-exists", "direct", false, true, false, false, nil) - if err != nil { - panic(err) - } - } -} - -// https://github.com/streadway/amqp/issues/7 -func TestCorruptedMessageIssue7(t *testing.T) { - messageCount := 1024 - - c1 := integrationConnection(t, "") - c2 := integrationConnection(t, "") - - if c1 != nil && c2 != nil { - defer c1.Close() - defer c2.Close() - - pub, err := c1.Channel() - if err != nil { - t.Fatalf("Cannot create Channel") - } - - sub, err := c2.Channel() - if err != nil { - t.Fatalf("Cannot create Channel") - } - - queue := "test-corrupted-message-regression" - - if _, err := pub.QueueDeclare(queue, false, true, false, false, nil); err != nil { - t.Fatalf("Cannot declare") - } - - if _, err := sub.QueueDeclare(queue, false, true, false, false, nil); err != nil { - t.Fatalf("Cannot declare") - } - - msgs, err := sub.Consume(queue, "", false, false, false, false, nil) - if err != nil { - t.Fatalf("Cannot consume") - } - - for i := 0; i < messageCount; i++ { - err := pub.Publish("", queue, false, false, Publishing{ - Body: generateCrc32Random(7 * i), - }) - - if err != nil { - t.Fatalf("Failed to publish") - } - } - - for i := 0; i < messageCount; i++ { - select { - case msg := <-msgs: - assertMessageCrc32(t, msg.Body, fmt.Sprintf("missed match at %d", i)) - case <-time.After(200 * time.Millisecond): - t.Fatalf("Timeout on recv") - } - } - } -} - -func TestExchangeDeclarePrecondition(t *testing.T) { - c1 := integrationConnection(t, "exchange-double-declare") - c2 := integrationConnection(t, "exchange-double-declare-cleanup") - if c1 != nil && c2 != nil { - defer c1.Close() - defer c2.Close() - - ch, err := c1.Channel() - if err != nil { - t.Fatalf("Create channel") - } - - exchange := "test-mismatched-redeclare" - - err = ch.ExchangeDeclare( - exchange, - "direct", // exchangeType - false, // durable - true, // auto-delete - false, // internal - false, // noWait - nil, // arguments - ) - if err != nil { - t.Fatalf("Could not initially declare exchange") - } - - err = ch.ExchangeDeclare( - exchange, - "direct", - true, // different durability - true, - false, - false, - nil, - ) - - if err == nil { - t.Fatalf("Expected to fail a redeclare with different durability, didn't receive an error") - } - - if err, ok := err.(Error); ok { - if err.Code != PreconditionFailed { - t.Fatalf("Expected precondition error") - } - if !err.Recover { - t.Fatalf("Expected to be able to recover") - } - } - - ch2, _ := c2.Channel() - if err = ch2.ExchangeDelete(exchange, false, false); err != nil { - t.Fatalf("Could not delete exchange: %v", err) - } - } -} - -func TestRabbitMQQueueTTLGet(t *testing.T) { - if c := integrationRabbitMQ(t, "ttl"); c != nil { - defer c.Close() - - queue := "test.rabbitmq-message-ttl" - channel, err := c.Channel() - if err != nil { - t.Fatalf("channel: %v", err) - } - - if _, err = channel.QueueDeclare( - queue, - false, - true, - false, - false, - Table{"x-message-ttl": int32(100)}, // in ms - ); err != nil { - t.Fatalf("queue declare: %s", err) - } - - channel.Publish("", queue, false, false, Publishing{Body: []byte("ttl")}) - - time.Sleep(200 * time.Millisecond) - - _, ok, err := channel.Get(queue, false) - - if ok { - t.Fatalf("Expected the message to expire in 100ms, it didn't expire after 200ms") - } - - if err != nil { - t.Fatalf("Failed to get on ttl queue") - } - } -} - -func TestRabbitMQQueueNackMultipleRequeue(t *testing.T) { - if c := integrationRabbitMQ(t, "nack"); c != nil { - defer c.Close() - - if c.isCapable("basic.nack") { - queue := "test.rabbitmq-basic-nack" - channel, err := c.Channel() - if err != nil { - t.Fatalf("channel: %v", err) - } - - if _, err = channel.QueueDeclare(queue, false, true, false, false, nil); err != nil { - t.Fatalf("queue declare: %s", err) - } - - channel.Publish("", queue, false, false, Publishing{Body: []byte("1")}) - channel.Publish("", queue, false, false, Publishing{Body: []byte("2")}) - - m1, ok, err := channel.Get(queue, false) - if !ok || err != nil || m1.Body[0] != '1' { - t.Fatalf("could not get message %v", m1) - } - - m2, ok, err := channel.Get(queue, false) - if !ok || err != nil || m2.Body[0] != '2' { - t.Fatalf("could not get message %v", m2) - } - - m2.Nack(true, true) - - m1, ok, err = channel.Get(queue, false) - if !ok || err != nil || m1.Body[0] != '1' { - t.Fatalf("could not get message %v", m1) - } - - m2, ok, err = channel.Get(queue, false) - if !ok || err != nil || m2.Body[0] != '2' { - t.Fatalf("could not get message %v", m2) - } - } - } -} - -/* - * Support for integration tests - */ - -func integrationURLFromEnv() string { - url := os.Getenv("AMQP_URL") - if url == "" { - url = "amqp://" - } - return url -} - -func loggedConnection(t *testing.T, conn *Connection, name string) *Connection { - if name != "" { - conn.conn = &logIO{t, name, conn.conn} - } - return conn -} - -// Returns a conneciton to the AMQP if the AMQP_URL environment -// variable is set and a connnection can be established. -func integrationConnection(t *testing.T, name string) *Connection { - conn, err := Dial(integrationURLFromEnv()) - if err != nil { - t.Errorf("dial integration server: %s", err) - return nil - } - return loggedConnection(t, conn, name) -} - -// Returns a connection, channel and delcares a queue when the AMQP_URL is in the environment -func integrationQueue(t *testing.T, name string) (*Connection, *Channel) { - if conn := integrationConnection(t, name); conn != nil { - if channel, err := conn.Channel(); err == nil { - if _, err = channel.QueueDeclare(name, false, true, false, false, nil); err == nil { - return conn, channel - } - } - } - return nil, nil -} - -// Delegates to integrationConnection and only returns a connection if the -// product is RabbitMQ -func integrationRabbitMQ(t *testing.T, name string) *Connection { - if conn := integrationConnection(t, "connect"); conn != nil { - if server, ok := conn.Properties["product"]; ok && server == "RabbitMQ" { - return conn - } - } - - return nil -} - -func assertConsumeBody(t *testing.T, messages <-chan Delivery, want []byte) (msg *Delivery) { - select { - case got := <-messages: - if bytes.Compare(want, got.Body) != 0 { - t.Fatalf("Message body does not match want: %v, got: %v, for: %+v", want, got.Body, got) - } - msg = &got - case <-time.After(200 * time.Millisecond): - t.Fatalf("Timeout waiting for %v", want) - } - - return msg -} - -// Pulls out the CRC and verifies the remaining content against the CRC -func assertMessageCrc32(t *testing.T, msg []byte, assert string) { - size := binary.BigEndian.Uint32(msg[:4]) - - crc := crc32.NewIEEE() - crc.Write(msg[8:]) - - if binary.BigEndian.Uint32(msg[4:8]) != crc.Sum32() { - t.Fatalf("Message does not match CRC: %s", assert) - } - - if int(size) != len(msg)-8 { - t.Fatalf("Message does not match size, should=%d, is=%d: %s", size, len(msg)-8, assert) - } -} - -// Creates a random body size with a leading 32-bit CRC in network byte order -// that verifies the remaining slice -func generateCrc32Random(size int) []byte { - msg := make([]byte, size+8) - if _, err := io.ReadFull(devrand.Reader, msg); err != nil { - panic(err) - } - - crc := crc32.NewIEEE() - crc.Write(msg[8:]) - - binary.BigEndian.PutUint32(msg[0:4], uint32(size)) - binary.BigEndian.PutUint32(msg[4:8], crc.Sum32()) - - return msg -} diff --git a/vendor/github.com/streadway/amqp/read.go b/vendor/github.com/streadway/amqp/read.go deleted file mode 100644 index 2ef7a9e47d4..00000000000 --- a/vendor/github.com/streadway/amqp/read.go +++ /dev/null @@ -1,444 +0,0 @@ -// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Source code and contact info at http://github.com/streadway/amqp - -package amqp - -import ( - "bytes" - "encoding/binary" - "io" - "time" -) - -/* -Reads a frame from an input stream and returns an interface that can be cast into -one of the following: - - methodFrame - PropertiesFrame - bodyFrame - heartbeatFrame - -2.3.5 frame Details - -All frames consist of a header (7 octets), a payload of arbitrary size, and a -'frame-end' octet that detects malformed frames: - - 0 1 3 7 size+7 size+8 - +------+---------+-------------+ +------------+ +-----------+ - | type | channel | size | | payload | | frame-end | - +------+---------+-------------+ +------------+ +-----------+ - octet short long size octets octet - -To read a frame, we: - 1. Read the header and check the frame type and channel. - 2. Depending on the frame type, we read the payload and process it. - 3. Read the frame end octet. - -In realistic implementations where performance is a concern, we would use -“read-ahead buffering” or - -“gathering reads” to avoid doing three separate system calls to read a frame. -*/ -func (me *reader) ReadFrame() (frame frame, err error) { - var scratch [7]byte - - if _, err = io.ReadFull(me.r, scratch[:7]); err != nil { - return - } - - typ := uint8(scratch[0]) - channel := binary.BigEndian.Uint16(scratch[1:3]) - size := binary.BigEndian.Uint32(scratch[3:7]) - - switch typ { - case frameMethod: - if frame, err = me.parseMethodFrame(channel, size); err != nil { - return - } - - case frameHeader: - if frame, err = me.parseHeaderFrame(channel, size); err != nil { - return - } - - case frameBody: - if frame, err = me.parseBodyFrame(channel, size); err != nil { - return - } - - case frameHeartbeat: - if frame, err = me.parseHeartbeatFrame(channel, size); err != nil { - return - } - - default: - return nil, ErrFrame - } - - if _, err = io.ReadFull(me.r, scratch[:1]); err != nil { - return - } - - if scratch[0] != frameEnd { - return nil, ErrFrame - } - - return -} - -func readShortstr(r io.Reader) (v string, err error) { - var length uint8 - if err = binary.Read(r, binary.BigEndian, &length); err != nil { - return - } - - bytes := make([]byte, length) - if _, err = io.ReadFull(r, bytes); err != nil { - return - } - return string(bytes), nil -} - -func readLongstr(r io.Reader) (v string, err error) { - var length uint32 - if err = binary.Read(r, binary.BigEndian, &length); err != nil { - return - } - - bytes := make([]byte, length) - if _, err = io.ReadFull(r, bytes); err != nil { - return - } - return string(bytes), nil -} - -func readDecimal(r io.Reader) (v Decimal, err error) { - if err = binary.Read(r, binary.BigEndian, &v.Scale); err != nil { - return - } - if err = binary.Read(r, binary.BigEndian, &v.Value); err != nil { - return - } - return -} - -func readFloat32(r io.Reader) (v float32, err error) { - if err = binary.Read(r, binary.BigEndian, &v); err != nil { - return - } - return -} - -func readFloat64(r io.Reader) (v float64, err error) { - if err = binary.Read(r, binary.BigEndian, &v); err != nil { - return - } - return -} - -func readTimestamp(r io.Reader) (v time.Time, err error) { - var sec int64 - if err = binary.Read(r, binary.BigEndian, &sec); err != nil { - return - } - return time.Unix(sec, 0), nil -} - -/* -'A': []interface{} -'D': Decimal -'F': Table -'I': int32 -'S': string -'T': time.Time -'V': nil -'b': byte -'d': float64 -'f': float32 -'l': int64 -'s': int16 -'t': bool -'x': []byte -*/ -func readField(r io.Reader) (v interface{}, err error) { - var typ byte - if err = binary.Read(r, binary.BigEndian, &typ); err != nil { - return - } - - switch typ { - case 't': - var value uint8 - if err = binary.Read(r, binary.BigEndian, &value); err != nil { - return - } - return (value != 0), nil - - case 'b': - var value [1]byte - if _, err = io.ReadFull(r, value[0:1]); err != nil { - return - } - return value[0], nil - - case 's': - var value int16 - if err = binary.Read(r, binary.BigEndian, &value); err != nil { - return - } - return value, nil - - case 'I': - var value int32 - if err = binary.Read(r, binary.BigEndian, &value); err != nil { - return - } - return value, nil - - case 'l': - var value int64 - if err = binary.Read(r, binary.BigEndian, &value); err != nil { - return - } - return value, nil - - case 'f': - var value float32 - if err = binary.Read(r, binary.BigEndian, &value); err != nil { - return - } - return value, nil - - case 'd': - var value float64 - if err = binary.Read(r, binary.BigEndian, &value); err != nil { - return - } - return value, nil - - case 'D': - return readDecimal(r) - - case 'S': - return readLongstr(r) - - case 'A': - return readArray(r) - - case 'T': - return readTimestamp(r) - - case 'F': - return readTable(r) - - case 'x': - var len int32 - if err = binary.Read(r, binary.BigEndian, &len); err != nil { - return nil, err - } - - value := make([]byte, len) - if _, err = io.ReadFull(r, value); err != nil { - return nil, err - } - return value, err - - case 'V': - return nil, nil - } - - return nil, ErrSyntax -} - -/* - Field tables are long strings that contain packed name-value pairs. The - name-value pairs are encoded as short string defining the name, and octet - defining the values type and then the value itself. The valid field types for - tables are an extension of the native integer, bit, string, and timestamp - types, and are shown in the grammar. Multi-octet integer fields are always - held in network byte order. -*/ -func readTable(r io.Reader) (table Table, err error) { - var nested bytes.Buffer - var str string - - if str, err = readLongstr(r); err != nil { - return - } - - nested.Write([]byte(str)) - - table = make(Table) - - for nested.Len() > 0 { - var key string - var value interface{} - - if key, err = readShortstr(&nested); err != nil { - return - } - - if value, err = readField(&nested); err != nil { - return - } - - table[key] = value - } - - return -} - -func readArray(r io.Reader) ([]interface{}, error) { - var size uint32 - var err error - - if err = binary.Read(r, binary.BigEndian, &size); err != nil { - return nil, err - } - - lim := &io.LimitedReader{R: r, N: int64(size)} - arr := make([]interface{}, 0) - var field interface{} - - for { - if field, err = readField(lim); err != nil { - if err == io.EOF { - break - } - return nil, err - } - arr = append(arr, field) - } - - return arr, nil -} - -// Checks if this bit mask matches the flags bitset -func hasProperty(mask uint16, prop int) bool { - return int(mask)&prop > 0 -} - -func (me *reader) parseHeaderFrame(channel uint16, size uint32) (frame frame, err error) { - hf := &headerFrame{ - ChannelId: channel, - } - - if err = binary.Read(me.r, binary.BigEndian, &hf.ClassId); err != nil { - return - } - - if err = binary.Read(me.r, binary.BigEndian, &hf.weight); err != nil { - return - } - - if err = binary.Read(me.r, binary.BigEndian, &hf.Size); err != nil { - return - } - - var flags uint16 - - if err = binary.Read(me.r, binary.BigEndian, &flags); err != nil { - return - } - - if hasProperty(flags, flagContentType) { - if hf.Properties.ContentType, err = readShortstr(me.r); err != nil { - return - } - } - if hasProperty(flags, flagContentEncoding) { - if hf.Properties.ContentEncoding, err = readShortstr(me.r); err != nil { - return - } - } - if hasProperty(flags, flagHeaders) { - if hf.Properties.Headers, err = readTable(me.r); err != nil { - return - } - } - if hasProperty(flags, flagDeliveryMode) { - if err = binary.Read(me.r, binary.BigEndian, &hf.Properties.DeliveryMode); err != nil { - return - } - } - if hasProperty(flags, flagPriority) { - if err = binary.Read(me.r, binary.BigEndian, &hf.Properties.Priority); err != nil { - return - } - } - if hasProperty(flags, flagCorrelationId) { - if hf.Properties.CorrelationId, err = readShortstr(me.r); err != nil { - return - } - } - if hasProperty(flags, flagReplyTo) { - if hf.Properties.ReplyTo, err = readShortstr(me.r); err != nil { - return - } - } - if hasProperty(flags, flagExpiration) { - if hf.Properties.Expiration, err = readShortstr(me.r); err != nil { - return - } - } - if hasProperty(flags, flagMessageId) { - if hf.Properties.MessageId, err = readShortstr(me.r); err != nil { - return - } - } - if hasProperty(flags, flagTimestamp) { - if hf.Properties.Timestamp, err = readTimestamp(me.r); err != nil { - return - } - } - if hasProperty(flags, flagType) { - if hf.Properties.Type, err = readShortstr(me.r); err != nil { - return - } - } - if hasProperty(flags, flagUserId) { - if hf.Properties.UserId, err = readShortstr(me.r); err != nil { - return - } - } - if hasProperty(flags, flagAppId) { - if hf.Properties.AppId, err = readShortstr(me.r); err != nil { - return - } - } - if hasProperty(flags, flagReserved1) { - if hf.Properties.reserved1, err = readShortstr(me.r); err != nil { - return - } - } - - return hf, nil -} - -func (me *reader) parseBodyFrame(channel uint16, size uint32) (frame frame, err error) { - bf := &bodyFrame{ - ChannelId: channel, - Body: make([]byte, size), - } - - if _, err = io.ReadFull(me.r, bf.Body); err != nil { - return - } - - return bf, nil -} - -func (me *reader) parseHeartbeatFrame(channel uint16, size uint32) (frame frame, err error) { - hf := &heartbeatFrame{ - ChannelId: channel, - } - - if size > 0 { - panic("Heartbeats should not have a payload") - } - - return hf, nil -} diff --git a/vendor/github.com/streadway/amqp/reconnect_test.go b/vendor/github.com/streadway/amqp/reconnect_test.go deleted file mode 100644 index 5a06cb7aef4..00000000000 --- a/vendor/github.com/streadway/amqp/reconnect_test.go +++ /dev/null @@ -1,113 +0,0 @@ -package amqp_test - -import ( - "fmt" - "github.com/streadway/amqp" - "os" -) - -// Every connection should declare the topology they expect -func setup(url, queue string) (*amqp.Connection, *amqp.Channel, error) { - conn, err := amqp.Dial(url) - if err != nil { - return nil, nil, err - } - - ch, err := conn.Channel() - if err != nil { - return nil, nil, err - } - - if _, err := ch.QueueDeclare(queue, false, true, false, false, nil); err != nil { - return nil, nil, err - } - - return conn, ch, nil -} - -func consume(url, queue string) (*amqp.Connection, <-chan amqp.Delivery, error) { - conn, ch, err := setup(url, queue) - if err != nil { - return nil, nil, err - } - - // Indicate we only want 1 message to acknowledge at a time. - if err := ch.Qos(1, 0, false); err != nil { - return nil, nil, err - } - - // Exclusive consumer - deliveries, err := ch.Consume(queue, "", false, true, false, false, nil) - - return conn, deliveries, err -} - -func ExampleConnection_reconnect() { - if url := os.Getenv("AMQP_URL"); url != "" { - queue := "example.reconnect" - - // The connection/channel for publishing to interleave the ingress messages - // between reconnects, shares the same topology as the consumer. If we rather - // sent all messages up front, the first consumer would receive every message. - // We would rather show how the messages are not lost between reconnects. - _, pub, err := setup(url, queue) - if err != nil { - fmt.Println("err publisher setup:", err) - return - } - - // Purge the queue from the publisher side to establish initial state - if _, err := pub.QueuePurge(queue, false); err != nil { - fmt.Println("err purge:", err) - return - } - - // Reconnect simulation, should be for { ... } in production - for i := 1; i <= 3; i++ { - fmt.Println("connect") - - conn, deliveries, err := consume(url, queue) - if err != nil { - fmt.Println("err consume:", err) - return - } - - // Simulate a producer on a different connection showing that consumers - // continue where they were left off after each reconnect. - if err := pub.Publish("", queue, false, false, amqp.Publishing{ - Body: []byte(fmt.Sprintf("%d", i)), - }); err != nil { - fmt.Println("err publish:", err) - return - } - - // Simulates a consumer that when the range finishes, will setup a new - // session and begin ranging over the deliveries again. - for msg := range deliveries { - fmt.Println(string(msg.Body)) - msg.Ack(false) - - // Simulate an error like a server restart, loss of route or operator - // intervention that results in the connection terminating - go conn.Close() - } - } - } else { - // pass with expected output when not running in an integration - // environment. - fmt.Println("connect") - fmt.Println("1") - fmt.Println("connect") - fmt.Println("2") - fmt.Println("connect") - fmt.Println("3") - } - - // Output: - // connect - // 1 - // connect - // 2 - // connect - // 3 -} diff --git a/vendor/github.com/streadway/amqp/return.go b/vendor/github.com/streadway/amqp/return.go deleted file mode 100644 index dfebd635dd1..00000000000 --- a/vendor/github.com/streadway/amqp/return.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Source code and contact info at http://github.com/streadway/amqp - -package amqp - -import ( - "time" -) - -// Return captures a flattened struct of fields returned by the server when a -// Publishing is unable to be delivered either due to the `mandatory` flag set -// and no route found, or `immediate` flag set and no free consumer. -type Return struct { - ReplyCode uint16 // reason - ReplyText string // description - Exchange string // basic.publish exchange - RoutingKey string // basic.publish routing key - - // Properties - ContentType string // MIME content type - ContentEncoding string // MIME content encoding - Headers Table // Application or header exchange table - DeliveryMode uint8 // queue implemention use - non-persistent (1) or persistent (2) - Priority uint8 // queue implementation use - 0 to 9 - CorrelationId string // application use - correlation identifier - ReplyTo string // application use - address to to reply to (ex: RPC) - Expiration string // implementation use - message expiration spec - MessageId string // application use - message identifier - Timestamp time.Time // application use - message timestamp - Type string // application use - message type name - UserId string // application use - creating user id - AppId string // application use - creating application - - Body []byte -} - -func newReturn(msg basicReturn) *Return { - props, body := msg.getContent() - - return &Return{ - ReplyCode: msg.ReplyCode, - ReplyText: msg.ReplyText, - Exchange: msg.Exchange, - RoutingKey: msg.RoutingKey, - - Headers: props.Headers, - ContentType: props.ContentType, - ContentEncoding: props.ContentEncoding, - DeliveryMode: props.DeliveryMode, - Priority: props.Priority, - CorrelationId: props.CorrelationId, - ReplyTo: props.ReplyTo, - Expiration: props.Expiration, - MessageId: props.MessageId, - Timestamp: props.Timestamp, - Type: props.Type, - UserId: props.UserId, - AppId: props.AppId, - - Body: body, - } -} diff --git a/vendor/github.com/streadway/amqp/shared_test.go b/vendor/github.com/streadway/amqp/shared_test.go deleted file mode 100644 index 2e4715fa0eb..00000000000 --- a/vendor/github.com/streadway/amqp/shared_test.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Source code and contact info at http://github.com/streadway/amqp - -package amqp - -import ( - "encoding/hex" - "io" - "testing" -) - -type pipe struct { - r *io.PipeReader - w *io.PipeWriter -} - -func (p pipe) Read(b []byte) (int, error) { - return p.r.Read(b) -} - -func (p pipe) Write(b []byte) (int, error) { - return p.w.Write(b) -} - -func (p pipe) Close() error { - p.r.Close() - p.w.Close() - return nil -} - -type logIO struct { - t *testing.T - prefix string - proxy io.ReadWriteCloser -} - -func (me *logIO) Read(p []byte) (n int, err error) { - me.t.Logf("%s reading %d\n", me.prefix, len(p)) - n, err = me.proxy.Read(p) - if err != nil { - me.t.Logf("%s read %x: %v\n", me.prefix, p[0:n], err) - } else { - me.t.Logf("%s read:\n%s\n", me.prefix, hex.Dump(p[0:n])) - //fmt.Printf("%s read:\n%s\n", me.prefix, hex.Dump(p[0:n])) - } - return -} - -func (me *logIO) Write(p []byte) (n int, err error) { - me.t.Logf("%s writing %d\n", me.prefix, len(p)) - n, err = me.proxy.Write(p) - if err != nil { - me.t.Logf("%s write %d, %x: %v\n", me.prefix, len(p), p[0:n], err) - } else { - me.t.Logf("%s write %d:\n%s", me.prefix, len(p), hex.Dump(p[0:n])) - //fmt.Printf("%s write %d:\n%s", me.prefix, len(p), hex.Dump(p[0:n])) - } - return -} - -func (me *logIO) Close() (err error) { - err = me.proxy.Close() - if err != nil { - me.t.Logf("%s close : %v\n", me.prefix, err) - } else { - me.t.Logf("%s close\n", me.prefix, err) - } - return -} diff --git a/vendor/github.com/streadway/amqp/spec/amqp0-9-1.stripped.extended.xml b/vendor/github.com/streadway/amqp/spec/amqp0-9-1.stripped.extended.xml deleted file mode 100644 index fbddb93a3db..00000000000 --- a/vendor/github.com/streadway/amqp/spec/amqp0-9-1.stripped.extended.xml +++ /dev/null @@ -1,537 +0,0 @@ - - - - - - - - - - - - - - - - - Errata: Section 1.2 ought to define an exception 312 "No route", which used to - exist in 0-9 and is what RabbitMQ sends back with 'basic.return' when a - 'mandatory' message cannot be delivered to any queue. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vendor/github.com/streadway/amqp/spec/gen.go b/vendor/github.com/streadway/amqp/spec/gen.go deleted file mode 100644 index 1861b9ebbb3..00000000000 --- a/vendor/github.com/streadway/amqp/spec/gen.go +++ /dev/null @@ -1,536 +0,0 @@ -// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Source code and contact info at http://github.com/streadway/amqp - -// +build ignore - -package main - -import ( - "bytes" - "encoding/xml" - "errors" - "fmt" - "io/ioutil" - "log" - "os" - "regexp" - "strings" - "text/template" -) - -var ( - ErrUnknownType = errors.New("Unknown field type in gen") - ErrUnknownDomain = errors.New("Unknown domain type in gen") -) - -var amqpTypeToNative = map[string]string{ - "bit": "bool", - "octet": "byte", - "shortshort": "uint8", - "short": "uint16", - "long": "uint32", - "longlong": "uint64", - "timestamp": "time.Time", - "table": "Table", - "shortstr": "string", - "longstr": "string", -} - -type Rule struct { - Name string `xml:"name,attr"` - Docs []string `xml:"doc"` -} - -type Doc struct { - Type string `xml:"type,attr"` - Body string `xml:",innerxml"` -} - -type Chassis struct { - Name string `xml:"name,attr"` - Implement string `xml:"implement,attr"` -} - -type Assert struct { - Check string `xml:"check,attr"` - Value string `xml:"value,attr"` - Method string `xml:"method,attr"` -} - -type Field struct { - Name string `xml:"name,attr"` - Domain string `xml:"domain,attr"` - Type string `xml:"type,attr"` - Label string `xml:"label,attr"` - Reserved bool `xml:"reserved,attr"` - Docs []Doc `xml:"doc"` - Asserts []Assert `xml:"assert"` -} - -type Response struct { - Name string `xml:"name,attr"` -} - -type Method struct { - Name string `xml:"name,attr"` - Response Response `xml:"response"` - Synchronous bool `xml:"synchronous,attr"` - Content bool `xml:"content,attr"` - Index string `xml:"index,attr"` - Label string `xml:"label,attr"` - Docs []Doc `xml:"doc"` - Rules []Rule `xml:"rule"` - Fields []Field `xml:"field"` - Chassis []Chassis `xml:"chassis"` -} - -type Class struct { - Name string `xml:"name,attr"` - Handler string `xml:"handler,attr"` - Index string `xml:"index,attr"` - Label string `xml:"label,attr"` - Docs []Doc `xml:"doc"` - Methods []Method `xml:"method"` - Chassis []Chassis `xml:"chassis"` -} - -type Domain struct { - Name string `xml:"name,attr"` - Type string `xml:"type,attr"` - Label string `xml:"label,attr"` - Rules []Rule `xml:"rule"` - Docs []Doc `xml:"doc"` -} - -type Constant struct { - Name string `xml:"name,attr"` - Value int `xml:"value,attr"` - Class string `xml:"class,attr"` - Doc string `xml:"doc"` -} - -type Amqp struct { - Major int `xml:"major,attr"` - Minor int `xml:"minor,attr"` - Port int `xml:"port,attr"` - Comment string `xml:"comment,attr"` - - Constants []Constant `xml:"constant"` - Domains []Domain `xml:"domain"` - Classes []Class `xml:"class"` -} - -type renderer struct { - Root Amqp - bitcounter int -} - -type fieldset struct { - AmqpType string - NativeType string - Fields []Field - *renderer -} - -var ( - helpers = template.FuncMap{ - "public": public, - "private": private, - "clean": clean, - } - - packageTemplate = template.Must(template.New("package").Funcs(helpers).Parse(` - // Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. - // Use of this source code is governed by a BSD-style - // license that can be found in the LICENSE file. - // Source code and contact info at http://github.com/streadway/amqp - - /* GENERATED FILE - DO NOT EDIT */ - /* Rebuild from the spec/gen.go tool */ - - {{with .Root}} - package amqp - - import ( - "fmt" - "encoding/binary" - "io" - ) - - // Error codes that can be sent from the server during a connection or - // channel exception or used by the client to indicate a class of error like - // ErrCredentials. The text of the error is likely more interesting than - // these constants. - const ( - {{range $c := .Constants}} - {{if $c.IsError}}{{.Name | public}}{{else}}{{.Name | private}}{{end}} = {{.Value}}{{end}} - ) - - func isSoftExceptionCode(code int) bool { - switch code { - {{range $c := .Constants}} {{if $c.IsSoftError}} case {{$c.Value}}: - return true - {{end}}{{end}} - } - return false - } - - {{range .Classes}} - {{$class := .}} - {{range .Methods}} - {{$method := .}} - {{$struct := $.StructName $class.Name $method.Name}} - {{if .Docs}}/* {{range .Docs}} {{.Body | clean}} {{end}} */{{end}} - type {{$struct}} struct { - {{range .Fields}} - {{$.FieldName .}} {{$.FieldType . | $.NativeType}} {{if .Label}}// {{.Label}}{{end}}{{end}} - {{if .Content}}Properties properties - Body []byte{{end}} - } - - func (me *{{$struct}}) id() (uint16, uint16) { - return {{$class.Index}}, {{$method.Index}} - } - - func (me *{{$struct}}) wait() (bool) { - return {{.Synchronous}}{{if $.HasField "NoWait" .}} && !me.NoWait{{end}} - } - - {{if .Content}} - func (me *{{$struct}}) getContent() (properties, []byte) { - return me.Properties, me.Body - } - - func (me *{{$struct}}) setContent(props properties, body []byte) { - me.Properties, me.Body = props, body - } - {{end}} - func (me *{{$struct}}) write(w io.Writer) (err error) { - {{if $.HasType "bit" $method}}var bits byte{{end}} - {{.Fields | $.Fieldsets | $.Partial "enc-"}} - return - } - - func (me *{{$struct}}) read(r io.Reader) (err error) { - {{if $.HasType "bit" $method}}var bits byte{{end}} - {{.Fields | $.Fieldsets | $.Partial "dec-"}} - return - } - {{end}} - {{end}} - - func (me *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err error) { - mf := &methodFrame { - ChannelId: channel, - } - - if err = binary.Read(me.r, binary.BigEndian, &mf.ClassId); err != nil { - return - } - - if err = binary.Read(me.r, binary.BigEndian, &mf.MethodId); err != nil { - return - } - - switch mf.ClassId { - {{range .Classes}} - {{$class := .}} - case {{.Index}}: // {{.Name}} - switch mf.MethodId { - {{range .Methods}} - case {{.Index}}: // {{$class.Name}} {{.Name}} - //fmt.Println("NextMethod: class:{{$class.Index}} method:{{.Index}}") - method := &{{$.StructName $class.Name .Name}}{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - {{end}} - default: - return nil, fmt.Errorf("Bad method frame, unknown method %d for class %d", mf.MethodId, mf.ClassId) - } - {{end}} - default: - return nil, fmt.Errorf("Bad method frame, unknown class %d", mf.ClassId) - } - - return mf, nil - } - {{end}} - - {{define "enc-bit"}} - {{range $off, $field := .Fields}} - if me.{{$field | $.FieldName}} { bits |= 1 << {{$off}} } - {{end}} - if err = binary.Write(w, binary.BigEndian, bits); err != nil { return } - {{end}} - {{define "enc-octet"}} - {{range .Fields}} if err = binary.Write(w, binary.BigEndian, me.{{. | $.FieldName}}); err != nil { return } - {{end}} - {{end}} - {{define "enc-shortshort"}} - {{range .Fields}} if err = binary.Write(w, binary.BigEndian, me.{{. | $.FieldName}}); err != nil { return } - {{end}} - {{end}} - {{define "enc-short"}} - {{range .Fields}} if err = binary.Write(w, binary.BigEndian, me.{{. | $.FieldName}}); err != nil { return } - {{end}} - {{end}} - {{define "enc-long"}} - {{range .Fields}} if err = binary.Write(w, binary.BigEndian, me.{{. | $.FieldName}}); err != nil { return } - {{end}} - {{end}} - {{define "enc-longlong"}} - {{range .Fields}} if err = binary.Write(w, binary.BigEndian, me.{{. | $.FieldName}}); err != nil { return } - {{end}} - {{end}} - {{define "enc-timestamp"}} - {{range .Fields}} if err = writeTimestamp(w, me.{{. | $.FieldName}}); err != nil { return } - {{end}} - {{end}} - {{define "enc-shortstr"}} - {{range .Fields}} if err = writeShortstr(w, me.{{. | $.FieldName}}); err != nil { return } - {{end}} - {{end}} - {{define "enc-longstr"}} - {{range .Fields}} if err = writeLongstr(w, me.{{. | $.FieldName}}); err != nil { return } - {{end}} - {{end}} - {{define "enc-table"}} - {{range .Fields}} if err = writeTable(w, me.{{. | $.FieldName}}); err != nil { return } - {{end}} - {{end}} - - {{define "dec-bit"}} - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - {{range $off, $field := .Fields}} me.{{$field | $.FieldName}} = (bits & (1 << {{$off}}) > 0) - {{end}} - {{end}} - {{define "dec-octet"}} - {{range .Fields}} if err = binary.Read(r, binary.BigEndian, &me.{{. | $.FieldName}}); err != nil { return } - {{end}} - {{end}} - {{define "dec-shortshort"}} - {{range .Fields}} if err = binary.Read(r, binary.BigEndian, &me.{{. | $.FieldName}}); err != nil { return } - {{end}} - {{end}} - {{define "dec-short"}} - {{range .Fields}} if err = binary.Read(r, binary.BigEndian, &me.{{. | $.FieldName}}); err != nil { return } - {{end}} - {{end}} - {{define "dec-long"}} - {{range .Fields}} if err = binary.Read(r, binary.BigEndian, &me.{{. | $.FieldName}}); err != nil { return } - {{end}} - {{end}} - {{define "dec-longlong"}} - {{range .Fields}} if err = binary.Read(r, binary.BigEndian, &me.{{. | $.FieldName}}); err != nil { return } - {{end}} - {{end}} - {{define "dec-timestamp"}} - {{range .Fields}} if me.{{. | $.FieldName}}, err = readTimestamp(r); err != nil { return } - {{end}} - {{end}} - {{define "dec-shortstr"}} - {{range .Fields}} if me.{{. | $.FieldName}}, err = readShortstr(r); err != nil { return } - {{end}} - {{end}} - {{define "dec-longstr"}} - {{range .Fields}} if me.{{. | $.FieldName}}, err = readLongstr(r); err != nil { return } - {{end}} - {{end}} - {{define "dec-table"}} - {{range .Fields}} if me.{{. | $.FieldName}}, err = readTable(r); err != nil { return } - {{end}} - {{end}} - - `)) -) - -func (me *Constant) IsError() bool { - return strings.Contains(me.Class, "error") -} - -func (me *Constant) IsSoftError() bool { - return me.Class == "soft-error" -} - -func (me *renderer) Partial(prefix string, fields []fieldset) (s string, err error) { - var buf bytes.Buffer - for _, set := range fields { - name := prefix + set.AmqpType - t := packageTemplate.Lookup(name) - if t == nil { - return "", errors.New(fmt.Sprintf("Missing template: %s", name)) - } - if err = t.Execute(&buf, set); err != nil { - return - } - } - return string(buf.Bytes()), nil -} - -// Groups the fields so that the right encoder/decoder can be called -func (me *renderer) Fieldsets(fields []Field) (f []fieldset, err error) { - if len(fields) > 0 { - for _, field := range fields { - cur := fieldset{} - cur.AmqpType, err = me.FieldType(field) - if err != nil { - return - } - - cur.NativeType, err = me.NativeType(cur.AmqpType) - if err != nil { - return - } - cur.Fields = append(cur.Fields, field) - f = append(f, cur) - } - - i, j := 0, 1 - for j < len(f) { - if f[i].AmqpType == f[j].AmqpType { - f[i].Fields = append(f[i].Fields, f[j].Fields...) - } else { - i++ - f[i] = f[j] - } - j++ - } - return f[:i+1], nil - } - - return -} - -func (me *renderer) HasType(typ string, method Method) bool { - for _, f := range method.Fields { - name, _ := me.FieldType(f) - if name == typ { - return true - } - } - return false -} - -func (me *renderer) HasField(field string, method Method) bool { - for _, f := range method.Fields { - name := me.FieldName(f) - if name == field { - return true - } - } - return false -} - -func (me *renderer) Domain(field Field) (domain Domain, err error) { - for _, domain = range me.Root.Domains { - if field.Domain == domain.Name { - return - } - } - return domain, nil - //return domain, ErrUnknownDomain -} - -func (me *renderer) FieldName(field Field) (t string) { - t = public(field.Name) - - if field.Reserved { - t = strings.ToLower(t) - } - - return -} - -func (me *renderer) FieldType(field Field) (t string, err error) { - t = field.Type - - if t == "" { - var domain Domain - domain, err = me.Domain(field) - if err != nil { - return "", err - } - t = domain.Type - } - - return -} - -func (me *renderer) NativeType(amqpType string) (t string, err error) { - if t, ok := amqpTypeToNative[amqpType]; ok { - return t, nil - } - return "", ErrUnknownType -} - -func (me *renderer) Tag(d Domain) string { - label := "`" - - label += `domain:"` + d.Name + `"` - - if len(d.Type) > 0 { - label += `,type:"` + d.Type + `"` - } - - label += "`" - - return label -} - -func (me *renderer) StructName(parts ...string) string { - return parts[0] + public(parts[1:]...) -} - -func clean(body string) (res string) { - return strings.Replace(body, "\r", "", -1) -} - -func private(parts ...string) string { - return export(regexp.MustCompile(`[-_]\w`), parts...) -} - -func public(parts ...string) string { - return export(regexp.MustCompile(`^\w|[-_]\w`), parts...) -} - -func export(delim *regexp.Regexp, parts ...string) (res string) { - for _, in := range parts { - - res += delim.ReplaceAllStringFunc(in, func(match string) string { - switch len(match) { - case 1: - return strings.ToUpper(match) - case 2: - return strings.ToUpper(match[1:]) - } - panic("unreachable") - }) - } - - return -} - -func main() { - var r renderer - - spec, err := ioutil.ReadAll(os.Stdin) - if err != nil { - log.Fatalln("Please pass spec on stdin", err) - } - - err = xml.Unmarshal(spec, &r.Root) - - if err != nil { - log.Fatalln("Could not parse XML:", err) - } - - if err = packageTemplate.Execute(os.Stdout, &r); err != nil { - log.Fatalln("Generate error: ", err) - } -} diff --git a/vendor/github.com/streadway/amqp/spec091.go b/vendor/github.com/streadway/amqp/spec091.go deleted file mode 100644 index a9538030392..00000000000 --- a/vendor/github.com/streadway/amqp/spec091.go +++ /dev/null @@ -1,3306 +0,0 @@ -// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Source code and contact info at http://github.com/streadway/amqp - -/* GENERATED FILE - DO NOT EDIT */ -/* Rebuild from the spec/gen.go tool */ - -package amqp - -import ( - "encoding/binary" - "fmt" - "io" -) - -// Error codes that can be sent from the server during a connection or -// channel exception or used by the client to indicate a class of error like -// ErrCredentials. The text of the error is likely more interesting than -// these constants. -const ( - frameMethod = 1 - frameHeader = 2 - frameBody = 3 - frameHeartbeat = 8 - frameMinSize = 4096 - frameEnd = 206 - replySuccess = 200 - ContentTooLarge = 311 - NoRoute = 312 - NoConsumers = 313 - ConnectionForced = 320 - InvalidPath = 402 - AccessRefused = 403 - NotFound = 404 - ResourceLocked = 405 - PreconditionFailed = 406 - FrameError = 501 - SyntaxError = 502 - CommandInvalid = 503 - ChannelError = 504 - UnexpectedFrame = 505 - ResourceError = 506 - NotAllowed = 530 - NotImplemented = 540 - InternalError = 541 -) - -func isSoftExceptionCode(code int) bool { - switch code { - case 311: - return true - case 312: - return true - case 313: - return true - case 403: - return true - case 404: - return true - case 405: - return true - case 406: - return true - - } - return false -} - -type connectionStart struct { - VersionMajor byte - VersionMinor byte - ServerProperties Table - Mechanisms string - Locales string -} - -func (me *connectionStart) id() (uint16, uint16) { - return 10, 10 -} - -func (me *connectionStart) wait() bool { - return true -} - -func (me *connectionStart) write(w io.Writer) (err error) { - - if err = binary.Write(w, binary.BigEndian, me.VersionMajor); err != nil { - return - } - if err = binary.Write(w, binary.BigEndian, me.VersionMinor); err != nil { - return - } - - if err = writeTable(w, me.ServerProperties); err != nil { - return - } - - if err = writeLongstr(w, me.Mechanisms); err != nil { - return - } - if err = writeLongstr(w, me.Locales); err != nil { - return - } - - return -} - -func (me *connectionStart) read(r io.Reader) (err error) { - - if err = binary.Read(r, binary.BigEndian, &me.VersionMajor); err != nil { - return - } - if err = binary.Read(r, binary.BigEndian, &me.VersionMinor); err != nil { - return - } - - if me.ServerProperties, err = readTable(r); err != nil { - return - } - - if me.Mechanisms, err = readLongstr(r); err != nil { - return - } - if me.Locales, err = readLongstr(r); err != nil { - return - } - - return -} - -type connectionStartOk struct { - ClientProperties Table - Mechanism string - Response string - Locale string -} - -func (me *connectionStartOk) id() (uint16, uint16) { - return 10, 11 -} - -func (me *connectionStartOk) wait() bool { - return true -} - -func (me *connectionStartOk) write(w io.Writer) (err error) { - - if err = writeTable(w, me.ClientProperties); err != nil { - return - } - - if err = writeShortstr(w, me.Mechanism); err != nil { - return - } - - if err = writeLongstr(w, me.Response); err != nil { - return - } - - if err = writeShortstr(w, me.Locale); err != nil { - return - } - - return -} - -func (me *connectionStartOk) read(r io.Reader) (err error) { - - if me.ClientProperties, err = readTable(r); err != nil { - return - } - - if me.Mechanism, err = readShortstr(r); err != nil { - return - } - - if me.Response, err = readLongstr(r); err != nil { - return - } - - if me.Locale, err = readShortstr(r); err != nil { - return - } - - return -} - -type connectionSecure struct { - Challenge string -} - -func (me *connectionSecure) id() (uint16, uint16) { - return 10, 20 -} - -func (me *connectionSecure) wait() bool { - return true -} - -func (me *connectionSecure) write(w io.Writer) (err error) { - - if err = writeLongstr(w, me.Challenge); err != nil { - return - } - - return -} - -func (me *connectionSecure) read(r io.Reader) (err error) { - - if me.Challenge, err = readLongstr(r); err != nil { - return - } - - return -} - -type connectionSecureOk struct { - Response string -} - -func (me *connectionSecureOk) id() (uint16, uint16) { - return 10, 21 -} - -func (me *connectionSecureOk) wait() bool { - return true -} - -func (me *connectionSecureOk) write(w io.Writer) (err error) { - - if err = writeLongstr(w, me.Response); err != nil { - return - } - - return -} - -func (me *connectionSecureOk) read(r io.Reader) (err error) { - - if me.Response, err = readLongstr(r); err != nil { - return - } - - return -} - -type connectionTune struct { - ChannelMax uint16 - FrameMax uint32 - Heartbeat uint16 -} - -func (me *connectionTune) id() (uint16, uint16) { - return 10, 30 -} - -func (me *connectionTune) wait() bool { - return true -} - -func (me *connectionTune) write(w io.Writer) (err error) { - - if err = binary.Write(w, binary.BigEndian, me.ChannelMax); err != nil { - return - } - - if err = binary.Write(w, binary.BigEndian, me.FrameMax); err != nil { - return - } - - if err = binary.Write(w, binary.BigEndian, me.Heartbeat); err != nil { - return - } - - return -} - -func (me *connectionTune) read(r io.Reader) (err error) { - - if err = binary.Read(r, binary.BigEndian, &me.ChannelMax); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &me.FrameMax); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &me.Heartbeat); err != nil { - return - } - - return -} - -type connectionTuneOk struct { - ChannelMax uint16 - FrameMax uint32 - Heartbeat uint16 -} - -func (me *connectionTuneOk) id() (uint16, uint16) { - return 10, 31 -} - -func (me *connectionTuneOk) wait() bool { - return true -} - -func (me *connectionTuneOk) write(w io.Writer) (err error) { - - if err = binary.Write(w, binary.BigEndian, me.ChannelMax); err != nil { - return - } - - if err = binary.Write(w, binary.BigEndian, me.FrameMax); err != nil { - return - } - - if err = binary.Write(w, binary.BigEndian, me.Heartbeat); err != nil { - return - } - - return -} - -func (me *connectionTuneOk) read(r io.Reader) (err error) { - - if err = binary.Read(r, binary.BigEndian, &me.ChannelMax); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &me.FrameMax); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &me.Heartbeat); err != nil { - return - } - - return -} - -type connectionOpen struct { - VirtualHost string - reserved1 string - reserved2 bool -} - -func (me *connectionOpen) id() (uint16, uint16) { - return 10, 40 -} - -func (me *connectionOpen) wait() bool { - return true -} - -func (me *connectionOpen) write(w io.Writer) (err error) { - var bits byte - - if err = writeShortstr(w, me.VirtualHost); err != nil { - return - } - if err = writeShortstr(w, me.reserved1); err != nil { - return - } - - if me.reserved2 { - bits |= 1 << 0 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - return -} - -func (me *connectionOpen) read(r io.Reader) (err error) { - var bits byte - - if me.VirtualHost, err = readShortstr(r); err != nil { - return - } - if me.reserved1, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.reserved2 = (bits&(1<<0) > 0) - - return -} - -type connectionOpenOk struct { - reserved1 string -} - -func (me *connectionOpenOk) id() (uint16, uint16) { - return 10, 41 -} - -func (me *connectionOpenOk) wait() bool { - return true -} - -func (me *connectionOpenOk) write(w io.Writer) (err error) { - - if err = writeShortstr(w, me.reserved1); err != nil { - return - } - - return -} - -func (me *connectionOpenOk) read(r io.Reader) (err error) { - - if me.reserved1, err = readShortstr(r); err != nil { - return - } - - return -} - -type connectionClose struct { - ReplyCode uint16 - ReplyText string - ClassId uint16 - MethodId uint16 -} - -func (me *connectionClose) id() (uint16, uint16) { - return 10, 50 -} - -func (me *connectionClose) wait() bool { - return true -} - -func (me *connectionClose) write(w io.Writer) (err error) { - - if err = binary.Write(w, binary.BigEndian, me.ReplyCode); err != nil { - return - } - - if err = writeShortstr(w, me.ReplyText); err != nil { - return - } - - if err = binary.Write(w, binary.BigEndian, me.ClassId); err != nil { - return - } - if err = binary.Write(w, binary.BigEndian, me.MethodId); err != nil { - return - } - - return -} - -func (me *connectionClose) read(r io.Reader) (err error) { - - if err = binary.Read(r, binary.BigEndian, &me.ReplyCode); err != nil { - return - } - - if me.ReplyText, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &me.ClassId); err != nil { - return - } - if err = binary.Read(r, binary.BigEndian, &me.MethodId); err != nil { - return - } - - return -} - -type connectionCloseOk struct { -} - -func (me *connectionCloseOk) id() (uint16, uint16) { - return 10, 51 -} - -func (me *connectionCloseOk) wait() bool { - return true -} - -func (me *connectionCloseOk) write(w io.Writer) (err error) { - - return -} - -func (me *connectionCloseOk) read(r io.Reader) (err error) { - - return -} - -type connectionBlocked struct { - Reason string -} - -func (me *connectionBlocked) id() (uint16, uint16) { - return 10, 60 -} - -func (me *connectionBlocked) wait() bool { - return false -} - -func (me *connectionBlocked) write(w io.Writer) (err error) { - - if err = writeShortstr(w, me.Reason); err != nil { - return - } - - return -} - -func (me *connectionBlocked) read(r io.Reader) (err error) { - - if me.Reason, err = readShortstr(r); err != nil { - return - } - - return -} - -type connectionUnblocked struct { -} - -func (me *connectionUnblocked) id() (uint16, uint16) { - return 10, 61 -} - -func (me *connectionUnblocked) wait() bool { - return false -} - -func (me *connectionUnblocked) write(w io.Writer) (err error) { - - return -} - -func (me *connectionUnblocked) read(r io.Reader) (err error) { - - return -} - -type channelOpen struct { - reserved1 string -} - -func (me *channelOpen) id() (uint16, uint16) { - return 20, 10 -} - -func (me *channelOpen) wait() bool { - return true -} - -func (me *channelOpen) write(w io.Writer) (err error) { - - if err = writeShortstr(w, me.reserved1); err != nil { - return - } - - return -} - -func (me *channelOpen) read(r io.Reader) (err error) { - - if me.reserved1, err = readShortstr(r); err != nil { - return - } - - return -} - -type channelOpenOk struct { - reserved1 string -} - -func (me *channelOpenOk) id() (uint16, uint16) { - return 20, 11 -} - -func (me *channelOpenOk) wait() bool { - return true -} - -func (me *channelOpenOk) write(w io.Writer) (err error) { - - if err = writeLongstr(w, me.reserved1); err != nil { - return - } - - return -} - -func (me *channelOpenOk) read(r io.Reader) (err error) { - - if me.reserved1, err = readLongstr(r); err != nil { - return - } - - return -} - -type channelFlow struct { - Active bool -} - -func (me *channelFlow) id() (uint16, uint16) { - return 20, 20 -} - -func (me *channelFlow) wait() bool { - return true -} - -func (me *channelFlow) write(w io.Writer) (err error) { - var bits byte - - if me.Active { - bits |= 1 << 0 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - return -} - -func (me *channelFlow) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.Active = (bits&(1<<0) > 0) - - return -} - -type channelFlowOk struct { - Active bool -} - -func (me *channelFlowOk) id() (uint16, uint16) { - return 20, 21 -} - -func (me *channelFlowOk) wait() bool { - return false -} - -func (me *channelFlowOk) write(w io.Writer) (err error) { - var bits byte - - if me.Active { - bits |= 1 << 0 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - return -} - -func (me *channelFlowOk) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.Active = (bits&(1<<0) > 0) - - return -} - -type channelClose struct { - ReplyCode uint16 - ReplyText string - ClassId uint16 - MethodId uint16 -} - -func (me *channelClose) id() (uint16, uint16) { - return 20, 40 -} - -func (me *channelClose) wait() bool { - return true -} - -func (me *channelClose) write(w io.Writer) (err error) { - - if err = binary.Write(w, binary.BigEndian, me.ReplyCode); err != nil { - return - } - - if err = writeShortstr(w, me.ReplyText); err != nil { - return - } - - if err = binary.Write(w, binary.BigEndian, me.ClassId); err != nil { - return - } - if err = binary.Write(w, binary.BigEndian, me.MethodId); err != nil { - return - } - - return -} - -func (me *channelClose) read(r io.Reader) (err error) { - - if err = binary.Read(r, binary.BigEndian, &me.ReplyCode); err != nil { - return - } - - if me.ReplyText, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &me.ClassId); err != nil { - return - } - if err = binary.Read(r, binary.BigEndian, &me.MethodId); err != nil { - return - } - - return -} - -type channelCloseOk struct { -} - -func (me *channelCloseOk) id() (uint16, uint16) { - return 20, 41 -} - -func (me *channelCloseOk) wait() bool { - return true -} - -func (me *channelCloseOk) write(w io.Writer) (err error) { - - return -} - -func (me *channelCloseOk) read(r io.Reader) (err error) { - - return -} - -type exchangeDeclare struct { - reserved1 uint16 - Exchange string - Type string - Passive bool - Durable bool - AutoDelete bool - Internal bool - NoWait bool - Arguments Table -} - -func (me *exchangeDeclare) id() (uint16, uint16) { - return 40, 10 -} - -func (me *exchangeDeclare) wait() bool { - return true && !me.NoWait -} - -func (me *exchangeDeclare) write(w io.Writer) (err error) { - var bits byte - - if err = binary.Write(w, binary.BigEndian, me.reserved1); err != nil { - return - } - - if err = writeShortstr(w, me.Exchange); err != nil { - return - } - if err = writeShortstr(w, me.Type); err != nil { - return - } - - if me.Passive { - bits |= 1 << 0 - } - - if me.Durable { - bits |= 1 << 1 - } - - if me.AutoDelete { - bits |= 1 << 2 - } - - if me.Internal { - bits |= 1 << 3 - } - - if me.NoWait { - bits |= 1 << 4 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - if err = writeTable(w, me.Arguments); err != nil { - return - } - - return -} - -func (me *exchangeDeclare) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &me.reserved1); err != nil { - return - } - - if me.Exchange, err = readShortstr(r); err != nil { - return - } - if me.Type, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.Passive = (bits&(1<<0) > 0) - me.Durable = (bits&(1<<1) > 0) - me.AutoDelete = (bits&(1<<2) > 0) - me.Internal = (bits&(1<<3) > 0) - me.NoWait = (bits&(1<<4) > 0) - - if me.Arguments, err = readTable(r); err != nil { - return - } - - return -} - -type exchangeDeclareOk struct { -} - -func (me *exchangeDeclareOk) id() (uint16, uint16) { - return 40, 11 -} - -func (me *exchangeDeclareOk) wait() bool { - return true -} - -func (me *exchangeDeclareOk) write(w io.Writer) (err error) { - - return -} - -func (me *exchangeDeclareOk) read(r io.Reader) (err error) { - - return -} - -type exchangeDelete struct { - reserved1 uint16 - Exchange string - IfUnused bool - NoWait bool -} - -func (me *exchangeDelete) id() (uint16, uint16) { - return 40, 20 -} - -func (me *exchangeDelete) wait() bool { - return true && !me.NoWait -} - -func (me *exchangeDelete) write(w io.Writer) (err error) { - var bits byte - - if err = binary.Write(w, binary.BigEndian, me.reserved1); err != nil { - return - } - - if err = writeShortstr(w, me.Exchange); err != nil { - return - } - - if me.IfUnused { - bits |= 1 << 0 - } - - if me.NoWait { - bits |= 1 << 1 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - return -} - -func (me *exchangeDelete) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &me.reserved1); err != nil { - return - } - - if me.Exchange, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.IfUnused = (bits&(1<<0) > 0) - me.NoWait = (bits&(1<<1) > 0) - - return -} - -type exchangeDeleteOk struct { -} - -func (me *exchangeDeleteOk) id() (uint16, uint16) { - return 40, 21 -} - -func (me *exchangeDeleteOk) wait() bool { - return true -} - -func (me *exchangeDeleteOk) write(w io.Writer) (err error) { - - return -} - -func (me *exchangeDeleteOk) read(r io.Reader) (err error) { - - return -} - -type exchangeBind struct { - reserved1 uint16 - Destination string - Source string - RoutingKey string - NoWait bool - Arguments Table -} - -func (me *exchangeBind) id() (uint16, uint16) { - return 40, 30 -} - -func (me *exchangeBind) wait() bool { - return true && !me.NoWait -} - -func (me *exchangeBind) write(w io.Writer) (err error) { - var bits byte - - if err = binary.Write(w, binary.BigEndian, me.reserved1); err != nil { - return - } - - if err = writeShortstr(w, me.Destination); err != nil { - return - } - if err = writeShortstr(w, me.Source); err != nil { - return - } - if err = writeShortstr(w, me.RoutingKey); err != nil { - return - } - - if me.NoWait { - bits |= 1 << 0 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - if err = writeTable(w, me.Arguments); err != nil { - return - } - - return -} - -func (me *exchangeBind) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &me.reserved1); err != nil { - return - } - - if me.Destination, err = readShortstr(r); err != nil { - return - } - if me.Source, err = readShortstr(r); err != nil { - return - } - if me.RoutingKey, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.NoWait = (bits&(1<<0) > 0) - - if me.Arguments, err = readTable(r); err != nil { - return - } - - return -} - -type exchangeBindOk struct { -} - -func (me *exchangeBindOk) id() (uint16, uint16) { - return 40, 31 -} - -func (me *exchangeBindOk) wait() bool { - return true -} - -func (me *exchangeBindOk) write(w io.Writer) (err error) { - - return -} - -func (me *exchangeBindOk) read(r io.Reader) (err error) { - - return -} - -type exchangeUnbind struct { - reserved1 uint16 - Destination string - Source string - RoutingKey string - NoWait bool - Arguments Table -} - -func (me *exchangeUnbind) id() (uint16, uint16) { - return 40, 40 -} - -func (me *exchangeUnbind) wait() bool { - return true && !me.NoWait -} - -func (me *exchangeUnbind) write(w io.Writer) (err error) { - var bits byte - - if err = binary.Write(w, binary.BigEndian, me.reserved1); err != nil { - return - } - - if err = writeShortstr(w, me.Destination); err != nil { - return - } - if err = writeShortstr(w, me.Source); err != nil { - return - } - if err = writeShortstr(w, me.RoutingKey); err != nil { - return - } - - if me.NoWait { - bits |= 1 << 0 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - if err = writeTable(w, me.Arguments); err != nil { - return - } - - return -} - -func (me *exchangeUnbind) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &me.reserved1); err != nil { - return - } - - if me.Destination, err = readShortstr(r); err != nil { - return - } - if me.Source, err = readShortstr(r); err != nil { - return - } - if me.RoutingKey, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.NoWait = (bits&(1<<0) > 0) - - if me.Arguments, err = readTable(r); err != nil { - return - } - - return -} - -type exchangeUnbindOk struct { -} - -func (me *exchangeUnbindOk) id() (uint16, uint16) { - return 40, 51 -} - -func (me *exchangeUnbindOk) wait() bool { - return true -} - -func (me *exchangeUnbindOk) write(w io.Writer) (err error) { - - return -} - -func (me *exchangeUnbindOk) read(r io.Reader) (err error) { - - return -} - -type queueDeclare struct { - reserved1 uint16 - Queue string - Passive bool - Durable bool - Exclusive bool - AutoDelete bool - NoWait bool - Arguments Table -} - -func (me *queueDeclare) id() (uint16, uint16) { - return 50, 10 -} - -func (me *queueDeclare) wait() bool { - return true && !me.NoWait -} - -func (me *queueDeclare) write(w io.Writer) (err error) { - var bits byte - - if err = binary.Write(w, binary.BigEndian, me.reserved1); err != nil { - return - } - - if err = writeShortstr(w, me.Queue); err != nil { - return - } - - if me.Passive { - bits |= 1 << 0 - } - - if me.Durable { - bits |= 1 << 1 - } - - if me.Exclusive { - bits |= 1 << 2 - } - - if me.AutoDelete { - bits |= 1 << 3 - } - - if me.NoWait { - bits |= 1 << 4 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - if err = writeTable(w, me.Arguments); err != nil { - return - } - - return -} - -func (me *queueDeclare) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &me.reserved1); err != nil { - return - } - - if me.Queue, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.Passive = (bits&(1<<0) > 0) - me.Durable = (bits&(1<<1) > 0) - me.Exclusive = (bits&(1<<2) > 0) - me.AutoDelete = (bits&(1<<3) > 0) - me.NoWait = (bits&(1<<4) > 0) - - if me.Arguments, err = readTable(r); err != nil { - return - } - - return -} - -type queueDeclareOk struct { - Queue string - MessageCount uint32 - ConsumerCount uint32 -} - -func (me *queueDeclareOk) id() (uint16, uint16) { - return 50, 11 -} - -func (me *queueDeclareOk) wait() bool { - return true -} - -func (me *queueDeclareOk) write(w io.Writer) (err error) { - - if err = writeShortstr(w, me.Queue); err != nil { - return - } - - if err = binary.Write(w, binary.BigEndian, me.MessageCount); err != nil { - return - } - if err = binary.Write(w, binary.BigEndian, me.ConsumerCount); err != nil { - return - } - - return -} - -func (me *queueDeclareOk) read(r io.Reader) (err error) { - - if me.Queue, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &me.MessageCount); err != nil { - return - } - if err = binary.Read(r, binary.BigEndian, &me.ConsumerCount); err != nil { - return - } - - return -} - -type queueBind struct { - reserved1 uint16 - Queue string - Exchange string - RoutingKey string - NoWait bool - Arguments Table -} - -func (me *queueBind) id() (uint16, uint16) { - return 50, 20 -} - -func (me *queueBind) wait() bool { - return true && !me.NoWait -} - -func (me *queueBind) write(w io.Writer) (err error) { - var bits byte - - if err = binary.Write(w, binary.BigEndian, me.reserved1); err != nil { - return - } - - if err = writeShortstr(w, me.Queue); err != nil { - return - } - if err = writeShortstr(w, me.Exchange); err != nil { - return - } - if err = writeShortstr(w, me.RoutingKey); err != nil { - return - } - - if me.NoWait { - bits |= 1 << 0 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - if err = writeTable(w, me.Arguments); err != nil { - return - } - - return -} - -func (me *queueBind) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &me.reserved1); err != nil { - return - } - - if me.Queue, err = readShortstr(r); err != nil { - return - } - if me.Exchange, err = readShortstr(r); err != nil { - return - } - if me.RoutingKey, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.NoWait = (bits&(1<<0) > 0) - - if me.Arguments, err = readTable(r); err != nil { - return - } - - return -} - -type queueBindOk struct { -} - -func (me *queueBindOk) id() (uint16, uint16) { - return 50, 21 -} - -func (me *queueBindOk) wait() bool { - return true -} - -func (me *queueBindOk) write(w io.Writer) (err error) { - - return -} - -func (me *queueBindOk) read(r io.Reader) (err error) { - - return -} - -type queueUnbind struct { - reserved1 uint16 - Queue string - Exchange string - RoutingKey string - Arguments Table -} - -func (me *queueUnbind) id() (uint16, uint16) { - return 50, 50 -} - -func (me *queueUnbind) wait() bool { - return true -} - -func (me *queueUnbind) write(w io.Writer) (err error) { - - if err = binary.Write(w, binary.BigEndian, me.reserved1); err != nil { - return - } - - if err = writeShortstr(w, me.Queue); err != nil { - return - } - if err = writeShortstr(w, me.Exchange); err != nil { - return - } - if err = writeShortstr(w, me.RoutingKey); err != nil { - return - } - - if err = writeTable(w, me.Arguments); err != nil { - return - } - - return -} - -func (me *queueUnbind) read(r io.Reader) (err error) { - - if err = binary.Read(r, binary.BigEndian, &me.reserved1); err != nil { - return - } - - if me.Queue, err = readShortstr(r); err != nil { - return - } - if me.Exchange, err = readShortstr(r); err != nil { - return - } - if me.RoutingKey, err = readShortstr(r); err != nil { - return - } - - if me.Arguments, err = readTable(r); err != nil { - return - } - - return -} - -type queueUnbindOk struct { -} - -func (me *queueUnbindOk) id() (uint16, uint16) { - return 50, 51 -} - -func (me *queueUnbindOk) wait() bool { - return true -} - -func (me *queueUnbindOk) write(w io.Writer) (err error) { - - return -} - -func (me *queueUnbindOk) read(r io.Reader) (err error) { - - return -} - -type queuePurge struct { - reserved1 uint16 - Queue string - NoWait bool -} - -func (me *queuePurge) id() (uint16, uint16) { - return 50, 30 -} - -func (me *queuePurge) wait() bool { - return true && !me.NoWait -} - -func (me *queuePurge) write(w io.Writer) (err error) { - var bits byte - - if err = binary.Write(w, binary.BigEndian, me.reserved1); err != nil { - return - } - - if err = writeShortstr(w, me.Queue); err != nil { - return - } - - if me.NoWait { - bits |= 1 << 0 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - return -} - -func (me *queuePurge) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &me.reserved1); err != nil { - return - } - - if me.Queue, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.NoWait = (bits&(1<<0) > 0) - - return -} - -type queuePurgeOk struct { - MessageCount uint32 -} - -func (me *queuePurgeOk) id() (uint16, uint16) { - return 50, 31 -} - -func (me *queuePurgeOk) wait() bool { - return true -} - -func (me *queuePurgeOk) write(w io.Writer) (err error) { - - if err = binary.Write(w, binary.BigEndian, me.MessageCount); err != nil { - return - } - - return -} - -func (me *queuePurgeOk) read(r io.Reader) (err error) { - - if err = binary.Read(r, binary.BigEndian, &me.MessageCount); err != nil { - return - } - - return -} - -type queueDelete struct { - reserved1 uint16 - Queue string - IfUnused bool - IfEmpty bool - NoWait bool -} - -func (me *queueDelete) id() (uint16, uint16) { - return 50, 40 -} - -func (me *queueDelete) wait() bool { - return true && !me.NoWait -} - -func (me *queueDelete) write(w io.Writer) (err error) { - var bits byte - - if err = binary.Write(w, binary.BigEndian, me.reserved1); err != nil { - return - } - - if err = writeShortstr(w, me.Queue); err != nil { - return - } - - if me.IfUnused { - bits |= 1 << 0 - } - - if me.IfEmpty { - bits |= 1 << 1 - } - - if me.NoWait { - bits |= 1 << 2 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - return -} - -func (me *queueDelete) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &me.reserved1); err != nil { - return - } - - if me.Queue, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.IfUnused = (bits&(1<<0) > 0) - me.IfEmpty = (bits&(1<<1) > 0) - me.NoWait = (bits&(1<<2) > 0) - - return -} - -type queueDeleteOk struct { - MessageCount uint32 -} - -func (me *queueDeleteOk) id() (uint16, uint16) { - return 50, 41 -} - -func (me *queueDeleteOk) wait() bool { - return true -} - -func (me *queueDeleteOk) write(w io.Writer) (err error) { - - if err = binary.Write(w, binary.BigEndian, me.MessageCount); err != nil { - return - } - - return -} - -func (me *queueDeleteOk) read(r io.Reader) (err error) { - - if err = binary.Read(r, binary.BigEndian, &me.MessageCount); err != nil { - return - } - - return -} - -type basicQos struct { - PrefetchSize uint32 - PrefetchCount uint16 - Global bool -} - -func (me *basicQos) id() (uint16, uint16) { - return 60, 10 -} - -func (me *basicQos) wait() bool { - return true -} - -func (me *basicQos) write(w io.Writer) (err error) { - var bits byte - - if err = binary.Write(w, binary.BigEndian, me.PrefetchSize); err != nil { - return - } - - if err = binary.Write(w, binary.BigEndian, me.PrefetchCount); err != nil { - return - } - - if me.Global { - bits |= 1 << 0 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - return -} - -func (me *basicQos) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &me.PrefetchSize); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &me.PrefetchCount); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.Global = (bits&(1<<0) > 0) - - return -} - -type basicQosOk struct { -} - -func (me *basicQosOk) id() (uint16, uint16) { - return 60, 11 -} - -func (me *basicQosOk) wait() bool { - return true -} - -func (me *basicQosOk) write(w io.Writer) (err error) { - - return -} - -func (me *basicQosOk) read(r io.Reader) (err error) { - - return -} - -type basicConsume struct { - reserved1 uint16 - Queue string - ConsumerTag string - NoLocal bool - NoAck bool - Exclusive bool - NoWait bool - Arguments Table -} - -func (me *basicConsume) id() (uint16, uint16) { - return 60, 20 -} - -func (me *basicConsume) wait() bool { - return true && !me.NoWait -} - -func (me *basicConsume) write(w io.Writer) (err error) { - var bits byte - - if err = binary.Write(w, binary.BigEndian, me.reserved1); err != nil { - return - } - - if err = writeShortstr(w, me.Queue); err != nil { - return - } - if err = writeShortstr(w, me.ConsumerTag); err != nil { - return - } - - if me.NoLocal { - bits |= 1 << 0 - } - - if me.NoAck { - bits |= 1 << 1 - } - - if me.Exclusive { - bits |= 1 << 2 - } - - if me.NoWait { - bits |= 1 << 3 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - if err = writeTable(w, me.Arguments); err != nil { - return - } - - return -} - -func (me *basicConsume) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &me.reserved1); err != nil { - return - } - - if me.Queue, err = readShortstr(r); err != nil { - return - } - if me.ConsumerTag, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.NoLocal = (bits&(1<<0) > 0) - me.NoAck = (bits&(1<<1) > 0) - me.Exclusive = (bits&(1<<2) > 0) - me.NoWait = (bits&(1<<3) > 0) - - if me.Arguments, err = readTable(r); err != nil { - return - } - - return -} - -type basicConsumeOk struct { - ConsumerTag string -} - -func (me *basicConsumeOk) id() (uint16, uint16) { - return 60, 21 -} - -func (me *basicConsumeOk) wait() bool { - return true -} - -func (me *basicConsumeOk) write(w io.Writer) (err error) { - - if err = writeShortstr(w, me.ConsumerTag); err != nil { - return - } - - return -} - -func (me *basicConsumeOk) read(r io.Reader) (err error) { - - if me.ConsumerTag, err = readShortstr(r); err != nil { - return - } - - return -} - -type basicCancel struct { - ConsumerTag string - NoWait bool -} - -func (me *basicCancel) id() (uint16, uint16) { - return 60, 30 -} - -func (me *basicCancel) wait() bool { - return true && !me.NoWait -} - -func (me *basicCancel) write(w io.Writer) (err error) { - var bits byte - - if err = writeShortstr(w, me.ConsumerTag); err != nil { - return - } - - if me.NoWait { - bits |= 1 << 0 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - return -} - -func (me *basicCancel) read(r io.Reader) (err error) { - var bits byte - - if me.ConsumerTag, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.NoWait = (bits&(1<<0) > 0) - - return -} - -type basicCancelOk struct { - ConsumerTag string -} - -func (me *basicCancelOk) id() (uint16, uint16) { - return 60, 31 -} - -func (me *basicCancelOk) wait() bool { - return true -} - -func (me *basicCancelOk) write(w io.Writer) (err error) { - - if err = writeShortstr(w, me.ConsumerTag); err != nil { - return - } - - return -} - -func (me *basicCancelOk) read(r io.Reader) (err error) { - - if me.ConsumerTag, err = readShortstr(r); err != nil { - return - } - - return -} - -type basicPublish struct { - reserved1 uint16 - Exchange string - RoutingKey string - Mandatory bool - Immediate bool - Properties properties - Body []byte -} - -func (me *basicPublish) id() (uint16, uint16) { - return 60, 40 -} - -func (me *basicPublish) wait() bool { - return false -} - -func (me *basicPublish) getContent() (properties, []byte) { - return me.Properties, me.Body -} - -func (me *basicPublish) setContent(props properties, body []byte) { - me.Properties, me.Body = props, body -} - -func (me *basicPublish) write(w io.Writer) (err error) { - var bits byte - - if err = binary.Write(w, binary.BigEndian, me.reserved1); err != nil { - return - } - - if err = writeShortstr(w, me.Exchange); err != nil { - return - } - if err = writeShortstr(w, me.RoutingKey); err != nil { - return - } - - if me.Mandatory { - bits |= 1 << 0 - } - - if me.Immediate { - bits |= 1 << 1 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - return -} - -func (me *basicPublish) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &me.reserved1); err != nil { - return - } - - if me.Exchange, err = readShortstr(r); err != nil { - return - } - if me.RoutingKey, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.Mandatory = (bits&(1<<0) > 0) - me.Immediate = (bits&(1<<1) > 0) - - return -} - -type basicReturn struct { - ReplyCode uint16 - ReplyText string - Exchange string - RoutingKey string - Properties properties - Body []byte -} - -func (me *basicReturn) id() (uint16, uint16) { - return 60, 50 -} - -func (me *basicReturn) wait() bool { - return false -} - -func (me *basicReturn) getContent() (properties, []byte) { - return me.Properties, me.Body -} - -func (me *basicReturn) setContent(props properties, body []byte) { - me.Properties, me.Body = props, body -} - -func (me *basicReturn) write(w io.Writer) (err error) { - - if err = binary.Write(w, binary.BigEndian, me.ReplyCode); err != nil { - return - } - - if err = writeShortstr(w, me.ReplyText); err != nil { - return - } - if err = writeShortstr(w, me.Exchange); err != nil { - return - } - if err = writeShortstr(w, me.RoutingKey); err != nil { - return - } - - return -} - -func (me *basicReturn) read(r io.Reader) (err error) { - - if err = binary.Read(r, binary.BigEndian, &me.ReplyCode); err != nil { - return - } - - if me.ReplyText, err = readShortstr(r); err != nil { - return - } - if me.Exchange, err = readShortstr(r); err != nil { - return - } - if me.RoutingKey, err = readShortstr(r); err != nil { - return - } - - return -} - -type basicDeliver struct { - ConsumerTag string - DeliveryTag uint64 - Redelivered bool - Exchange string - RoutingKey string - Properties properties - Body []byte -} - -func (me *basicDeliver) id() (uint16, uint16) { - return 60, 60 -} - -func (me *basicDeliver) wait() bool { - return false -} - -func (me *basicDeliver) getContent() (properties, []byte) { - return me.Properties, me.Body -} - -func (me *basicDeliver) setContent(props properties, body []byte) { - me.Properties, me.Body = props, body -} - -func (me *basicDeliver) write(w io.Writer) (err error) { - var bits byte - - if err = writeShortstr(w, me.ConsumerTag); err != nil { - return - } - - if err = binary.Write(w, binary.BigEndian, me.DeliveryTag); err != nil { - return - } - - if me.Redelivered { - bits |= 1 << 0 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - if err = writeShortstr(w, me.Exchange); err != nil { - return - } - if err = writeShortstr(w, me.RoutingKey); err != nil { - return - } - - return -} - -func (me *basicDeliver) read(r io.Reader) (err error) { - var bits byte - - if me.ConsumerTag, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &me.DeliveryTag); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.Redelivered = (bits&(1<<0) > 0) - - if me.Exchange, err = readShortstr(r); err != nil { - return - } - if me.RoutingKey, err = readShortstr(r); err != nil { - return - } - - return -} - -type basicGet struct { - reserved1 uint16 - Queue string - NoAck bool -} - -func (me *basicGet) id() (uint16, uint16) { - return 60, 70 -} - -func (me *basicGet) wait() bool { - return true -} - -func (me *basicGet) write(w io.Writer) (err error) { - var bits byte - - if err = binary.Write(w, binary.BigEndian, me.reserved1); err != nil { - return - } - - if err = writeShortstr(w, me.Queue); err != nil { - return - } - - if me.NoAck { - bits |= 1 << 0 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - return -} - -func (me *basicGet) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &me.reserved1); err != nil { - return - } - - if me.Queue, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.NoAck = (bits&(1<<0) > 0) - - return -} - -type basicGetOk struct { - DeliveryTag uint64 - Redelivered bool - Exchange string - RoutingKey string - MessageCount uint32 - Properties properties - Body []byte -} - -func (me *basicGetOk) id() (uint16, uint16) { - return 60, 71 -} - -func (me *basicGetOk) wait() bool { - return true -} - -func (me *basicGetOk) getContent() (properties, []byte) { - return me.Properties, me.Body -} - -func (me *basicGetOk) setContent(props properties, body []byte) { - me.Properties, me.Body = props, body -} - -func (me *basicGetOk) write(w io.Writer) (err error) { - var bits byte - - if err = binary.Write(w, binary.BigEndian, me.DeliveryTag); err != nil { - return - } - - if me.Redelivered { - bits |= 1 << 0 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - if err = writeShortstr(w, me.Exchange); err != nil { - return - } - if err = writeShortstr(w, me.RoutingKey); err != nil { - return - } - - if err = binary.Write(w, binary.BigEndian, me.MessageCount); err != nil { - return - } - - return -} - -func (me *basicGetOk) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &me.DeliveryTag); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.Redelivered = (bits&(1<<0) > 0) - - if me.Exchange, err = readShortstr(r); err != nil { - return - } - if me.RoutingKey, err = readShortstr(r); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &me.MessageCount); err != nil { - return - } - - return -} - -type basicGetEmpty struct { - reserved1 string -} - -func (me *basicGetEmpty) id() (uint16, uint16) { - return 60, 72 -} - -func (me *basicGetEmpty) wait() bool { - return true -} - -func (me *basicGetEmpty) write(w io.Writer) (err error) { - - if err = writeShortstr(w, me.reserved1); err != nil { - return - } - - return -} - -func (me *basicGetEmpty) read(r io.Reader) (err error) { - - if me.reserved1, err = readShortstr(r); err != nil { - return - } - - return -} - -type basicAck struct { - DeliveryTag uint64 - Multiple bool -} - -func (me *basicAck) id() (uint16, uint16) { - return 60, 80 -} - -func (me *basicAck) wait() bool { - return false -} - -func (me *basicAck) write(w io.Writer) (err error) { - var bits byte - - if err = binary.Write(w, binary.BigEndian, me.DeliveryTag); err != nil { - return - } - - if me.Multiple { - bits |= 1 << 0 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - return -} - -func (me *basicAck) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &me.DeliveryTag); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.Multiple = (bits&(1<<0) > 0) - - return -} - -type basicReject struct { - DeliveryTag uint64 - Requeue bool -} - -func (me *basicReject) id() (uint16, uint16) { - return 60, 90 -} - -func (me *basicReject) wait() bool { - return false -} - -func (me *basicReject) write(w io.Writer) (err error) { - var bits byte - - if err = binary.Write(w, binary.BigEndian, me.DeliveryTag); err != nil { - return - } - - if me.Requeue { - bits |= 1 << 0 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - return -} - -func (me *basicReject) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &me.DeliveryTag); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.Requeue = (bits&(1<<0) > 0) - - return -} - -type basicRecoverAsync struct { - Requeue bool -} - -func (me *basicRecoverAsync) id() (uint16, uint16) { - return 60, 100 -} - -func (me *basicRecoverAsync) wait() bool { - return false -} - -func (me *basicRecoverAsync) write(w io.Writer) (err error) { - var bits byte - - if me.Requeue { - bits |= 1 << 0 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - return -} - -func (me *basicRecoverAsync) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.Requeue = (bits&(1<<0) > 0) - - return -} - -type basicRecover struct { - Requeue bool -} - -func (me *basicRecover) id() (uint16, uint16) { - return 60, 110 -} - -func (me *basicRecover) wait() bool { - return true -} - -func (me *basicRecover) write(w io.Writer) (err error) { - var bits byte - - if me.Requeue { - bits |= 1 << 0 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - return -} - -func (me *basicRecover) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.Requeue = (bits&(1<<0) > 0) - - return -} - -type basicRecoverOk struct { -} - -func (me *basicRecoverOk) id() (uint16, uint16) { - return 60, 111 -} - -func (me *basicRecoverOk) wait() bool { - return true -} - -func (me *basicRecoverOk) write(w io.Writer) (err error) { - - return -} - -func (me *basicRecoverOk) read(r io.Reader) (err error) { - - return -} - -type basicNack struct { - DeliveryTag uint64 - Multiple bool - Requeue bool -} - -func (me *basicNack) id() (uint16, uint16) { - return 60, 120 -} - -func (me *basicNack) wait() bool { - return false -} - -func (me *basicNack) write(w io.Writer) (err error) { - var bits byte - - if err = binary.Write(w, binary.BigEndian, me.DeliveryTag); err != nil { - return - } - - if me.Multiple { - bits |= 1 << 0 - } - - if me.Requeue { - bits |= 1 << 1 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - return -} - -func (me *basicNack) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &me.DeliveryTag); err != nil { - return - } - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.Multiple = (bits&(1<<0) > 0) - me.Requeue = (bits&(1<<1) > 0) - - return -} - -type txSelect struct { -} - -func (me *txSelect) id() (uint16, uint16) { - return 90, 10 -} - -func (me *txSelect) wait() bool { - return true -} - -func (me *txSelect) write(w io.Writer) (err error) { - - return -} - -func (me *txSelect) read(r io.Reader) (err error) { - - return -} - -type txSelectOk struct { -} - -func (me *txSelectOk) id() (uint16, uint16) { - return 90, 11 -} - -func (me *txSelectOk) wait() bool { - return true -} - -func (me *txSelectOk) write(w io.Writer) (err error) { - - return -} - -func (me *txSelectOk) read(r io.Reader) (err error) { - - return -} - -type txCommit struct { -} - -func (me *txCommit) id() (uint16, uint16) { - return 90, 20 -} - -func (me *txCommit) wait() bool { - return true -} - -func (me *txCommit) write(w io.Writer) (err error) { - - return -} - -func (me *txCommit) read(r io.Reader) (err error) { - - return -} - -type txCommitOk struct { -} - -func (me *txCommitOk) id() (uint16, uint16) { - return 90, 21 -} - -func (me *txCommitOk) wait() bool { - return true -} - -func (me *txCommitOk) write(w io.Writer) (err error) { - - return -} - -func (me *txCommitOk) read(r io.Reader) (err error) { - - return -} - -type txRollback struct { -} - -func (me *txRollback) id() (uint16, uint16) { - return 90, 30 -} - -func (me *txRollback) wait() bool { - return true -} - -func (me *txRollback) write(w io.Writer) (err error) { - - return -} - -func (me *txRollback) read(r io.Reader) (err error) { - - return -} - -type txRollbackOk struct { -} - -func (me *txRollbackOk) id() (uint16, uint16) { - return 90, 31 -} - -func (me *txRollbackOk) wait() bool { - return true -} - -func (me *txRollbackOk) write(w io.Writer) (err error) { - - return -} - -func (me *txRollbackOk) read(r io.Reader) (err error) { - - return -} - -type confirmSelect struct { - Nowait bool -} - -func (me *confirmSelect) id() (uint16, uint16) { - return 85, 10 -} - -func (me *confirmSelect) wait() bool { - return true -} - -func (me *confirmSelect) write(w io.Writer) (err error) { - var bits byte - - if me.Nowait { - bits |= 1 << 0 - } - - if err = binary.Write(w, binary.BigEndian, bits); err != nil { - return - } - - return -} - -func (me *confirmSelect) read(r io.Reader) (err error) { - var bits byte - - if err = binary.Read(r, binary.BigEndian, &bits); err != nil { - return - } - me.Nowait = (bits&(1<<0) > 0) - - return -} - -type confirmSelectOk struct { -} - -func (me *confirmSelectOk) id() (uint16, uint16) { - return 85, 11 -} - -func (me *confirmSelectOk) wait() bool { - return true -} - -func (me *confirmSelectOk) write(w io.Writer) (err error) { - - return -} - -func (me *confirmSelectOk) read(r io.Reader) (err error) { - - return -} - -func (me *reader) parseMethodFrame(channel uint16, size uint32) (f frame, err error) { - mf := &methodFrame{ - ChannelId: channel, - } - - if err = binary.Read(me.r, binary.BigEndian, &mf.ClassId); err != nil { - return - } - - if err = binary.Read(me.r, binary.BigEndian, &mf.MethodId); err != nil { - return - } - - switch mf.ClassId { - - case 10: // connection - switch mf.MethodId { - - case 10: // connection start - //fmt.Println("NextMethod: class:10 method:10") - method := &connectionStart{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 11: // connection start-ok - //fmt.Println("NextMethod: class:10 method:11") - method := &connectionStartOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 20: // connection secure - //fmt.Println("NextMethod: class:10 method:20") - method := &connectionSecure{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 21: // connection secure-ok - //fmt.Println("NextMethod: class:10 method:21") - method := &connectionSecureOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 30: // connection tune - //fmt.Println("NextMethod: class:10 method:30") - method := &connectionTune{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 31: // connection tune-ok - //fmt.Println("NextMethod: class:10 method:31") - method := &connectionTuneOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 40: // connection open - //fmt.Println("NextMethod: class:10 method:40") - method := &connectionOpen{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 41: // connection open-ok - //fmt.Println("NextMethod: class:10 method:41") - method := &connectionOpenOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 50: // connection close - //fmt.Println("NextMethod: class:10 method:50") - method := &connectionClose{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 51: // connection close-ok - //fmt.Println("NextMethod: class:10 method:51") - method := &connectionCloseOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 60: // connection blocked - //fmt.Println("NextMethod: class:10 method:60") - method := &connectionBlocked{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 61: // connection unblocked - //fmt.Println("NextMethod: class:10 method:61") - method := &connectionUnblocked{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - default: - return nil, fmt.Errorf("Bad method frame, unknown method %d for class %d", mf.MethodId, mf.ClassId) - } - - case 20: // channel - switch mf.MethodId { - - case 10: // channel open - //fmt.Println("NextMethod: class:20 method:10") - method := &channelOpen{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 11: // channel open-ok - //fmt.Println("NextMethod: class:20 method:11") - method := &channelOpenOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 20: // channel flow - //fmt.Println("NextMethod: class:20 method:20") - method := &channelFlow{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 21: // channel flow-ok - //fmt.Println("NextMethod: class:20 method:21") - method := &channelFlowOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 40: // channel close - //fmt.Println("NextMethod: class:20 method:40") - method := &channelClose{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 41: // channel close-ok - //fmt.Println("NextMethod: class:20 method:41") - method := &channelCloseOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - default: - return nil, fmt.Errorf("Bad method frame, unknown method %d for class %d", mf.MethodId, mf.ClassId) - } - - case 40: // exchange - switch mf.MethodId { - - case 10: // exchange declare - //fmt.Println("NextMethod: class:40 method:10") - method := &exchangeDeclare{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 11: // exchange declare-ok - //fmt.Println("NextMethod: class:40 method:11") - method := &exchangeDeclareOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 20: // exchange delete - //fmt.Println("NextMethod: class:40 method:20") - method := &exchangeDelete{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 21: // exchange delete-ok - //fmt.Println("NextMethod: class:40 method:21") - method := &exchangeDeleteOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 30: // exchange bind - //fmt.Println("NextMethod: class:40 method:30") - method := &exchangeBind{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 31: // exchange bind-ok - //fmt.Println("NextMethod: class:40 method:31") - method := &exchangeBindOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 40: // exchange unbind - //fmt.Println("NextMethod: class:40 method:40") - method := &exchangeUnbind{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 51: // exchange unbind-ok - //fmt.Println("NextMethod: class:40 method:51") - method := &exchangeUnbindOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - default: - return nil, fmt.Errorf("Bad method frame, unknown method %d for class %d", mf.MethodId, mf.ClassId) - } - - case 50: // queue - switch mf.MethodId { - - case 10: // queue declare - //fmt.Println("NextMethod: class:50 method:10") - method := &queueDeclare{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 11: // queue declare-ok - //fmt.Println("NextMethod: class:50 method:11") - method := &queueDeclareOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 20: // queue bind - //fmt.Println("NextMethod: class:50 method:20") - method := &queueBind{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 21: // queue bind-ok - //fmt.Println("NextMethod: class:50 method:21") - method := &queueBindOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 50: // queue unbind - //fmt.Println("NextMethod: class:50 method:50") - method := &queueUnbind{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 51: // queue unbind-ok - //fmt.Println("NextMethod: class:50 method:51") - method := &queueUnbindOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 30: // queue purge - //fmt.Println("NextMethod: class:50 method:30") - method := &queuePurge{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 31: // queue purge-ok - //fmt.Println("NextMethod: class:50 method:31") - method := &queuePurgeOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 40: // queue delete - //fmt.Println("NextMethod: class:50 method:40") - method := &queueDelete{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 41: // queue delete-ok - //fmt.Println("NextMethod: class:50 method:41") - method := &queueDeleteOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - default: - return nil, fmt.Errorf("Bad method frame, unknown method %d for class %d", mf.MethodId, mf.ClassId) - } - - case 60: // basic - switch mf.MethodId { - - case 10: // basic qos - //fmt.Println("NextMethod: class:60 method:10") - method := &basicQos{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 11: // basic qos-ok - //fmt.Println("NextMethod: class:60 method:11") - method := &basicQosOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 20: // basic consume - //fmt.Println("NextMethod: class:60 method:20") - method := &basicConsume{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 21: // basic consume-ok - //fmt.Println("NextMethod: class:60 method:21") - method := &basicConsumeOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 30: // basic cancel - //fmt.Println("NextMethod: class:60 method:30") - method := &basicCancel{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 31: // basic cancel-ok - //fmt.Println("NextMethod: class:60 method:31") - method := &basicCancelOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 40: // basic publish - //fmt.Println("NextMethod: class:60 method:40") - method := &basicPublish{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 50: // basic return - //fmt.Println("NextMethod: class:60 method:50") - method := &basicReturn{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 60: // basic deliver - //fmt.Println("NextMethod: class:60 method:60") - method := &basicDeliver{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 70: // basic get - //fmt.Println("NextMethod: class:60 method:70") - method := &basicGet{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 71: // basic get-ok - //fmt.Println("NextMethod: class:60 method:71") - method := &basicGetOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 72: // basic get-empty - //fmt.Println("NextMethod: class:60 method:72") - method := &basicGetEmpty{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 80: // basic ack - //fmt.Println("NextMethod: class:60 method:80") - method := &basicAck{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 90: // basic reject - //fmt.Println("NextMethod: class:60 method:90") - method := &basicReject{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 100: // basic recover-async - //fmt.Println("NextMethod: class:60 method:100") - method := &basicRecoverAsync{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 110: // basic recover - //fmt.Println("NextMethod: class:60 method:110") - method := &basicRecover{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 111: // basic recover-ok - //fmt.Println("NextMethod: class:60 method:111") - method := &basicRecoverOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 120: // basic nack - //fmt.Println("NextMethod: class:60 method:120") - method := &basicNack{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - default: - return nil, fmt.Errorf("Bad method frame, unknown method %d for class %d", mf.MethodId, mf.ClassId) - } - - case 90: // tx - switch mf.MethodId { - - case 10: // tx select - //fmt.Println("NextMethod: class:90 method:10") - method := &txSelect{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 11: // tx select-ok - //fmt.Println("NextMethod: class:90 method:11") - method := &txSelectOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 20: // tx commit - //fmt.Println("NextMethod: class:90 method:20") - method := &txCommit{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 21: // tx commit-ok - //fmt.Println("NextMethod: class:90 method:21") - method := &txCommitOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 30: // tx rollback - //fmt.Println("NextMethod: class:90 method:30") - method := &txRollback{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 31: // tx rollback-ok - //fmt.Println("NextMethod: class:90 method:31") - method := &txRollbackOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - default: - return nil, fmt.Errorf("Bad method frame, unknown method %d for class %d", mf.MethodId, mf.ClassId) - } - - case 85: // confirm - switch mf.MethodId { - - case 10: // confirm select - //fmt.Println("NextMethod: class:85 method:10") - method := &confirmSelect{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - case 11: // confirm select-ok - //fmt.Println("NextMethod: class:85 method:11") - method := &confirmSelectOk{} - if err = method.read(me.r); err != nil { - return - } - mf.Method = method - - default: - return nil, fmt.Errorf("Bad method frame, unknown method %d for class %d", mf.MethodId, mf.ClassId) - } - - default: - return nil, fmt.Errorf("Bad method frame, unknown class %d", mf.ClassId) - } - - return mf, nil -} diff --git a/vendor/github.com/streadway/amqp/tls_test.go b/vendor/github.com/streadway/amqp/tls_test.go deleted file mode 100644 index a0795b6413c..00000000000 --- a/vendor/github.com/streadway/amqp/tls_test.go +++ /dev/null @@ -1,218 +0,0 @@ -package amqp_test - -import ( - "crypto/tls" - "crypto/x509" - "fmt" - "github.com/streadway/amqp" - "io" - "net" - "testing" - "time" -) - -type tlsServer struct { - net.Listener - URL string - Config *tls.Config - Header chan []byte -} - -// Captures the header for each accepted connection -func (s *tlsServer) Serve() { - for { - c, err := s.Accept() - if err != nil { - return - } - - header := make([]byte, 4) - io.ReadFull(c, header) - s.Header <- header - c.Write([]byte{'A', 'M', 'Q', 'P', 0, 0, 0, 0}) - c.Close() - } -} - -func tlsConfig() *tls.Config { - cfg := new(tls.Config) - - cfg.ClientCAs = x509.NewCertPool() - cfg.ClientCAs.AppendCertsFromPEM([]byte(caCert)) - - cert, err := tls.X509KeyPair([]byte(serverCert), []byte(serverKey)) - if err != nil { - panic(err) - } - - cfg.Certificates = append(cfg.Certificates, cert) - cfg.ClientAuth = tls.RequireAndVerifyClientCert - - return cfg -} - -func startTlsServer() tlsServer { - cfg := tlsConfig() - - l, err := tls.Listen("tcp", "127.0.0.1:0", cfg) - if err != nil { - panic(err) - } - - s := tlsServer{ - Listener: l, - Config: cfg, - URL: fmt.Sprintf("amqps://%s/", l.Addr().String()), - Header: make(chan []byte, 1), - } - - go s.Serve() - return s -} - -// Tests that the server has handshaked the connection and seen the client -// protocol announcement. Does not nest that the connection.open is successful. -func TestTLSHandshake(t *testing.T) { - srv := startTlsServer() - defer srv.Close() - - cfg := new(tls.Config) - cfg.RootCAs = x509.NewCertPool() - cfg.RootCAs.AppendCertsFromPEM([]byte(caCert)) - - cert, _ := tls.X509KeyPair([]byte(clientCert), []byte(clientKey)) - cfg.Certificates = append(cfg.Certificates, cert) - - _, err := amqp.DialTLS(srv.URL, cfg) - - select { - case <-time.After(10 * time.Millisecond): - t.Fatalf("did not succeed to handshake the TLS connection after 10ms") - case header := <-srv.Header: - if string(header) != "AMQP" { - t.Fatalf("expected to handshake a TLS connection, got err: %v", err) - } - } -} - -const caCert = ` ------BEGIN CERTIFICATE----- -MIICxjCCAa6gAwIBAgIJANWuMWMQSxvdMA0GCSqGSIb3DQEBBQUAMBMxETAPBgNV -BAMTCE15VGVzdENBMB4XDTE0MDEyNzE5NTIyMloXDTI0MDEyNTE5NTIyMlowEzER -MA8GA1UEAxMITXlUZXN0Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB -AQDBsIrkW4ob9Z/gzR2/Maa2stbutry6/vvz8eiJwIKIbaHGwqtFOUGiWeKw7H76 -IH3SjTAhNQY2hoKPyH41D36sDJkYBRyHFJTK/6ffvOhpyLnuXJAnoS62eKPSNUAx -5i/lkHj42ESutYAH9qbHCI/gBm9G4WmhGAyA16xzC1n07JObl6KFoY1PqHKl823z -mvF47I24DzemEfjdwC9nAAX/pGYOg9FA9nQv7NnhlsJMxueCx55RNU1ADRoqsbfE -T0CQTOT4ryugGrUp9J4Cwen6YbXZrS6+Kff5SQCAns0Qu8/bwj0DKkuBGLF+Mnwe -mq9bMzyZPUrPM3Gu48ao8YAfAgMBAAGjHTAbMAwGA1UdEwQFMAMBAf8wCwYDVR0P -BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQCBwXGblRxIEOlEP6ANZ1C8AHWyG8lR -CQduFclc0tmyCCz5fnyLK0aGu9LhXXe6/HSKqgs4mJqeqYOojdjkfOme/YdwDzjK -WIf0kRYQHcB6NeyEZwW8C7subTP1Xw6zbAmjvQrtCGvRM+fi3/cs1sSSkd/EoRk4 -7GM9qQl/JIIoCOGncninf2NQm5YSpbit6/mOQD7EhqXsw+bX+IRh3DHC1Apv/PoA -HlDNeM4vjWaBxsmvRSndrIvew1czboFM18oRSSIqAkU7dKZ0SbC11grzmNxMG2aD -f9y8FIG6RK/SEaOZuc+uBGXx7tj7dczpE/2puqYcaVGwcv4kkrC/ZuRm ------END CERTIFICATE----- -` - -const serverCert = ` ------BEGIN CERTIFICATE----- -MIIC8zCCAdugAwIBAgIBATANBgkqhkiG9w0BAQUFADATMREwDwYDVQQDEwhNeVRl -c3RDQTAeFw0xNDAxMjcxOTUyMjNaFw0yNDAxMjUxOTUyMjNaMCUxEjAQBgNVBAMT -CTEyNy4wLjAuMTEPMA0GA1UEChMGc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEAxYAKbeGyg0gP0xwVsZsufzk/SUCtD44Gp3lQYQ9QumQ1IVZu -PmZWwPWrzI93a1Abruz6ZhXaB3jcL5QPAy1N44IiFgVN45CZXBsqkpJe/abzRFOV -DRnHxattPDHdgwML5d3nURKGUM/7+ACj5E4pZEDlM3RIjIKVd+doJsL7n6myO8FE -tIpt4vTz1MFp3F+ntPnHU3BZ/VZ1UjSlFWnCjT0CR0tnXsPmlIaC98HThS8x5zNB -fvvSN+Zln8RWdNLnEVHVdqYtOQ828QbCx8s1HfClGgaVoSDrzz+qQgtZFO4wW264 -2CWkNd8DSJUJ/HlPNXmbXsrRMgvGaL7YUz2yRQIDAQABo0AwPjAJBgNVHRMEAjAA -MAsGA1UdDwQEAwIFIDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHREECDAGhwR/ -AAABMA0GCSqGSIb3DQEBBQUAA4IBAQAE2g+wAFf9Xg5svcnb7+mfseYV16k9l5WG -onrmR3FLsbTxfbr4PZJMHrswPbi2NRk0+ETPUpcv1RP7pUB7wSEvuS1NPGcU92iP -58ycP3dYtLzmuu6BkgToZqwsCU8fC2zM0wt3+ifzPpDMffWWOioVuA3zdM9WPQYz -+Ofajd0XaZwFZS8uTI5WXgObz7Xqfmln4tF3Sq1CTyuJ44qK4p83XOKFq+L04aD0 -d0c8w3YQNUENny/vMP9mDu3FQ3SnDz2GKl1LSjGe2TUnkoMkDfdk4wSzndTz/ecb -QiCPKijwVPWNOWV3NDE2edMxDPxDoKoEm5F4UGfGjxSRnYCIoZLh ------END CERTIFICATE----- -` - -const serverKey = ` ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAxYAKbeGyg0gP0xwVsZsufzk/SUCtD44Gp3lQYQ9QumQ1IVZu -PmZWwPWrzI93a1Abruz6ZhXaB3jcL5QPAy1N44IiFgVN45CZXBsqkpJe/abzRFOV -DRnHxattPDHdgwML5d3nURKGUM/7+ACj5E4pZEDlM3RIjIKVd+doJsL7n6myO8FE -tIpt4vTz1MFp3F+ntPnHU3BZ/VZ1UjSlFWnCjT0CR0tnXsPmlIaC98HThS8x5zNB -fvvSN+Zln8RWdNLnEVHVdqYtOQ828QbCx8s1HfClGgaVoSDrzz+qQgtZFO4wW264 -2CWkNd8DSJUJ/HlPNXmbXsrRMgvGaL7YUz2yRQIDAQABAoIBAGsyEvcPAGg3DbfE -z5WFp9gPx2TIAOanbL8rnlAAEw4H47qDgfTGcSHsdeHioKuTYGMyZrpP8/YISGJe -l0NfLJ5mfH+9Q0hXrJWMfS/u2DYOjo0wXH8u1fpZEEISwqsgVS3fonSjfFmSea1j -E5GQRvEONBkYbWQuYFgjNqmLPS2r5lKbWCQvc1MB/vvVBwOTiO0ON7m/EkM5RKt9 -cDT5ZhhVjBpdmd9HpVbKTdBj8Q0l5/ZHZUEgZA6FDZEwYxTd9l87Z4YT+5SR0z9t -k8/Z0CHd3x3Rv891t7m66ZJkaOda8NC65/432MQEQwJltmrKnc22dS8yI26rrmpp -g3tcbSUCgYEA5nMXdQKS4vF+Kp10l/HqvGz2sU8qQaWYZQIg7Th3QJPo6N52po/s -nn3UF0P5mT1laeZ5ZQJKx4gnmuPnIZ2ZtJQDyFhIbRPcZ+2hSNSuLYVcrumOC3EP -3OZyFtFE1THO73aFe5e1jEdtoOne3Bds/Hq6NF45fkVdL+M9e8pfXIsCgYEA22W8 -zGjbWyrFOYvKknMQVtHnMx8BJEtsvWRknP6CWAv/8WyeZpE128Pve1m441AQnopS -CuOF5wFK0iUXBFbS3Pe1/1j3em6yfVznuUHqJ7Qc+dNzxVvkTK8jGB6x+vm+M9Hg -muHUM726IUxckoSNXbPNAVPIZab1NdSxam7F9m8CgYEAx55QZmIJXJ41XLKxqWC7 -peZ5NpPNlbncrTpPzUzJN94ntXfmrVckbxGt401VayEctMQYyZ9XqUlOjUP3FU5Q -M3S3Zhba/eljVX8o406fZf0MkNLs4QpZ5E6V6x/xEP+pMhKng6yhbVb+JpIPIvUD -yhyBKRWplbB+DRo5Sv685gsCgYA7l5m9h+m1DJv/cnn2Z2yTuHXtC8namuYRV1iA -0ByFX9UINXGc+GpBpCnDPm6ax5+MAJQiQwSW52H0TIDA+/hQbrQvhHHL/o9av8Zt -Kns4h5KrRQUYIUqUjamhnozHV9iS6LnyN87Usv8AlmY6oehoADN53dD702qdUYVT -HH2G3wKBgCdvqyw78FR/n8cUWesTPnxx5HCeWJ1J+2BESnUnPmKZ71CV1H7uweja -vPUxuuuGLKfNx84OKCfRDbtOgMOeyh9T1RmXry6Srz/7/udjlF0qmFiRXfBNAgoR -tNb0+Ri/vY0AHrQ7UnCbl12qPVaqhEXLr+kCGNEPFqpMJPPEeMK0 ------END RSA PRIVATE KEY----- -` - -const clientCert = ` ------BEGIN CERTIFICATE----- -MIIC4jCCAcqgAwIBAgIBAjANBgkqhkiG9w0BAQUFADATMREwDwYDVQQDEwhNeVRl -c3RDQTAeFw0xNDAxMjcxOTUyMjNaFw0yNDAxMjUxOTUyMjNaMCUxEjAQBgNVBAMT -CTEyNy4wLjAuMTEPMA0GA1UEChMGY2xpZW50MIIBIjANBgkqhkiG9w0BAQEFAAOC -AQ8AMIIBCgKCAQEAu7LMqd+agoH168Bsi0WJ36ulYqDypq+GZPF7uWOo2pE0raKH -B++31/hjnkt6yC5kLKVZZ0EfolBa9q4Cy6swfGaEMafy44ZCRneLnt1azL1N6Kfz -+U0KsOqyQDoMxYJG1gVTEZN19/U/ew2eazcxKyERI3oGCQ4SbpkxBTbfxtAFk49e -xIB3obsuMVUrmtXE4FkUkvG7NgpPUgrhp0yxYpj9zruZGzGGT1zNhcarbQ/4i7It -ZMbnv6pqQWtYDgnGX2TDRcEiXGeO+KrzhfpTRLfO3K4np8e8cmTyXM+4lMlWUgma -KrRdu1QXozGqRs47u2prGKGdSQWITpqNVCY8fQIDAQABoy8wLTAJBgNVHRMEAjAA -MAsGA1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQUF -AAOCAQEAhCuBCLznPc4O96hT3P8Fx19L3ltrWbc/pWrx8JjxUaGk8kNmjMjY+/Mt -JBbjUBx2kJwaY0EHMAfw7D1f1wcCeNycx/0dyb0E6xzhmPw5fY15GGNg8rzWwqSY -+i/1iqU0IRkmRHV7XCF+trd2H0Ec+V1Fd/61E2ccJfOL5aSAyWbMCUtWxS3QMnqH -FBfKdVEiY9WNht5hnvsXQBRaNhowJ6Cwa7/1/LZjmhcXiJ0xrc1Hggj3cvS+4vll -Ew+20a0tPKjD/v/2oSQL+qkeYKV4fhCGkaBHCpPlSJrqorb7B6NmPy3nS26ETKE/ -o2UCfZc5g2MU1ENa31kT1iuhKZapsA== ------END CERTIFICATE----- -` - -const clientKey = ` ------BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAu7LMqd+agoH168Bsi0WJ36ulYqDypq+GZPF7uWOo2pE0raKH -B++31/hjnkt6yC5kLKVZZ0EfolBa9q4Cy6swfGaEMafy44ZCRneLnt1azL1N6Kfz -+U0KsOqyQDoMxYJG1gVTEZN19/U/ew2eazcxKyERI3oGCQ4SbpkxBTbfxtAFk49e -xIB3obsuMVUrmtXE4FkUkvG7NgpPUgrhp0yxYpj9zruZGzGGT1zNhcarbQ/4i7It -ZMbnv6pqQWtYDgnGX2TDRcEiXGeO+KrzhfpTRLfO3K4np8e8cmTyXM+4lMlWUgma -KrRdu1QXozGqRs47u2prGKGdSQWITpqNVCY8fQIDAQABAoIBAGSEn3hFyEAmCyYi -2b5IEksXaC2GlgxQKb/7Vs/0oCPU6YonZPsKFMFzQx4tu+ZiecEzF8rlJGTPdbdv -fw3FcuTcHeVd1QSmDO4h7UK5tnu40XVMJKsY6CXQun8M13QajYbmORNLjjypOULU -C0fNueYoAj6mhX7p61MRdSAev/5+0+bVQQG/tSVDQzdngvKpaCunOphiB2VW2Aa0 -7aYPOFCoPB2uo0DwUmBB0yfx9x4hXX9ovQI0YFou7bq6iYJ0vlZBvYQ9YrVdxjKL -avcz1N5xM3WFAkZJSVT/Ho5+uTbZx4RrJ8b5T+t2spOKmXyAjwS2rL/XMAh8YRZ1 -u44duoECgYEA4jpK2qshgQ0t49rjVHEDKX5x7ElEZefl0rHZ/2X/uHUDKpKj2fTq -3TQzHquiQ4Aof7OEB9UE3DGrtpvo/j/PYxL5Luu5VR4AIEJm+CA8GYuE96+uIL0Z -M2r3Lux6Bp30Z47Eit2KiY4fhrWs59WB3NHHoFxgzHSVbnuA02gcX2ECgYEA1GZw -iXIVYaK07ED+q/0ObyS5hD1cMhJ7ifSN9BxuG0qUpSigbkTGj09fUDS4Fqsz9dvz -F0P93fZvyia242TIfDUwJEsDQCgHk7SGa4Rx/p/3x/obIEERk7K76Hdg93U5NXhV -NvczvgL0HYxnb+qtumwMgGPzncB4lGcTnRyOfp0CgYBTIsDnYwRI/KLknUf1fCKB -WSpcfwBXwsS+jQVjygQTsUyclI8KResZp1kx6DkVPT+kzj+y8SF8GfTUgq844BJC -gnJ4P8A3+3JoaH6WqKHtcUxICZOgDF36e1CjOdwOGnX6qIipz4hdzJDhXFpSSDAV -CjKmR8x61k0j8NcC2buzgQKBgFr7eo9VwBTvpoJhIPY5UvqHB7S+uAR26FZi3H/J -wdyM6PmKWpaBfXCb9l8cBhMnyP0y94FqzY9L5fz48nSbkkmqWvHg9AaCXySFOuNJ -e68vhOszlnUNimLzOAzPPkkh/JyL7Cy8XXyyNTGHGDPXmg12BTDmH8/eR4iCUuOE -/QD9AoGBALQ/SkvfO3D5+k9e/aTHRuMJ0+PWdLUMTZ39oJQxUx+qj7/xpjDvWTBn -eDmF/wjnIAg+020oXyBYo6plEZfDz3EYJQZ+3kLLEU+O/A7VxCakPYPwCr7N/InL -Ccg/TVSIXxw/6uJnojoAjMIEU45NoP6RMp0mWYYb2OlteEv08Ovp ------END RSA PRIVATE KEY----- -` diff --git a/vendor/github.com/streadway/amqp/types.go b/vendor/github.com/streadway/amqp/types.go deleted file mode 100644 index 6566198cea7..00000000000 --- a/vendor/github.com/streadway/amqp/types.go +++ /dev/null @@ -1,382 +0,0 @@ -// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Source code and contact info at http://github.com/streadway/amqp - -package amqp - -import ( - "fmt" - "io" - "time" -) - -var ( - // Errors that this library could return/emit from a channel or connection - ErrClosed = &Error{Code: ChannelError, Reason: "channel/connection is not open"} - ErrChannelMax = &Error{Code: ChannelError, Reason: "channel id space exhausted"} - ErrSASL = &Error{Code: AccessRefused, Reason: "SASL could not negotiate a shared mechanism"} - ErrCredentials = &Error{Code: AccessRefused, Reason: "username or password not allowed"} - ErrVhost = &Error{Code: AccessRefused, Reason: "no access to this vhost"} - ErrSyntax = &Error{Code: SyntaxError, Reason: "invalid field or value inside of a frame"} - ErrFrame = &Error{Code: FrameError, Reason: "frame could not be parsed"} - ErrCommandInvalid = &Error{Code: CommandInvalid, Reason: "unexpected command received"} - ErrUnexpectedFrame = &Error{Code: UnexpectedFrame, Reason: "unexpected frame received"} - ErrFieldType = &Error{Code: SyntaxError, Reason: "unsupported table field type"} -) - -// Error captures the code and reason a channel or connection has been closed -// by the server. -type Error struct { - Code int // constant code from the specification - Reason string // description of the error - Server bool // true when initiated from the server, false when from this library - Recover bool // true when this error can be recovered by retrying later or with differnet parameters -} - -func newError(code uint16, text string) *Error { - return &Error{ - Code: int(code), - Reason: text, - Recover: isSoftExceptionCode(int(code)), - Server: true, - } -} - -func (me Error) Error() string { - return fmt.Sprintf("Exception (%d) Reason: %q", me.Code, me.Reason) -} - -// Used by header frames to capture routing and header information -type properties struct { - ContentType string // MIME content type - ContentEncoding string // MIME content encoding - Headers Table // Application or header exchange table - DeliveryMode uint8 // queue implemention use - Transient (1) or Persistent (2) - Priority uint8 // queue implementation use - 0 to 9 - CorrelationId string // application use - correlation identifier - ReplyTo string // application use - address to to reply to (ex: RPC) - Expiration string // implementation use - message expiration spec - MessageId string // application use - message identifier - Timestamp time.Time // application use - message timestamp - Type string // application use - message type name - UserId string // application use - creating user id - AppId string // application use - creating application - reserved1 string // was cluster-id - process for buffer consumption -} - -// DeliveryMode. Transient means higher throughput but messages will not be -// restored on broker restart. The delivery mode of publishings is unrelated -// to the durability of the queues they reside on. Transient messages will -// not be restored to durable queues, persistent messages will be restored to -// durable queues and lost on non-durable queues during server restart. -// -// This remains typed as uint8 to match Publishing.DeliveryMode. Other -// delivery modes specific to custom queue implementations are not enumerated -// here. -const ( - Transient uint8 = 1 - Persistent uint8 = 2 -) - -// The property flags are an array of bits that indicate the presence or -// absence of each property value in sequence. The bits are ordered from most -// high to low - bit 15 indicates the first property. -const ( - flagContentType = 0x8000 - flagContentEncoding = 0x4000 - flagHeaders = 0x2000 - flagDeliveryMode = 0x1000 - flagPriority = 0x0800 - flagCorrelationId = 0x0400 - flagReplyTo = 0x0200 - flagExpiration = 0x0100 - flagMessageId = 0x0080 - flagTimestamp = 0x0040 - flagType = 0x0020 - flagUserId = 0x0010 - flagAppId = 0x0008 - flagReserved1 = 0x0004 -) - -// Queue captures the current server state of the queue on the server returned -// from Channel.QueueDeclare or Channel.QueueInspect. -type Queue struct { - Name string // server confirmed or generated name - Messages int // count of messages not awaiting acknowledgment - Consumers int // number of consumers receiving deliveries -} - -// Publishing captures the client message sent to the server. The fields -// outside of the Headers table included in this struct mirror the underlying -// fields in the content frame. They use native types for convenience and -// efficiency. -type Publishing struct { - // Application or exchange specific fields, - // the headers exchange will inspect this field. - Headers Table - - // Properties - ContentType string // MIME content type - ContentEncoding string // MIME content encoding - DeliveryMode uint8 // Transient (0 or 1) or Persistent (2) - Priority uint8 // 0 to 9 - CorrelationId string // correlation identifier - ReplyTo string // address to to reply to (ex: RPC) - Expiration string // message expiration spec - MessageId string // message identifier - Timestamp time.Time // message timestamp - Type string // message type name - UserId string // creating user id - ex: "guest" - AppId string // creating application id - - // The application specific payload of the message - Body []byte -} - -// Blocking notifies the server's TCP flow control of the Connection. When a -// server hits a memory or disk alarm it will block all connections until the -// resources are reclaimed. Use NotifyBlock on the Connection to receive these -// events. -type Blocking struct { - Active bool // TCP pushback active/inactive on server - Reason string // Server reason for activation -} - -// Decimal matches the AMQP decimal type. Scale is the number of decimal -// digits Scale == 2, Value == 12345, Decimal == 123.45 -type Decimal struct { - Scale uint8 - Value int32 -} - -// Table stores user supplied fields of the following types: -// -// bool -// byte -// float32 -// float64 -// int16 -// int32 -// int64 -// nil -// string -// time.Time -// amqp.Decimal -// amqp.Table -// []byte -// []interface{} - containing above types -// -// Functions taking a table will immediately fail when the table contains a -// value of an unsupported type. -// -// The caller must be specific in which precision of integer it wishes to -// encode. -// -// Use a type assertion when reading values from a table for type converstion. -// -// RabbitMQ expects int32 for integer values. -// -type Table map[string]interface{} - -func validateField(f interface{}) error { - switch fv := f.(type) { - case nil, bool, byte, int16, int32, int64, float32, float64, string, []byte, Decimal, time.Time: - return nil - - case []interface{}: - for _, v := range fv { - if err := validateField(v); err != nil { - return fmt.Errorf("in array %s", err) - } - } - return nil - - case Table: - for k, v := range fv { - if err := validateField(v); err != nil { - return fmt.Errorf("table field %q %s", k, err) - } - } - return nil - } - - return fmt.Errorf("value %t not supported", f) -} - -func (t Table) Validate() error { - return validateField(t) -} - -// Heap interface for maintaining delivery tags -type tagSet []uint64 - -func (me tagSet) Len() int { return len(me) } -func (me tagSet) Less(i, j int) bool { return (me)[i] < (me)[j] } -func (me tagSet) Swap(i, j int) { (me)[i], (me)[j] = (me)[j], (me)[i] } -func (me *tagSet) Push(tag interface{}) { *me = append(*me, tag.(uint64)) } -func (me *tagSet) Pop() interface{} { - val := (*me)[len(*me)-1] - *me = (*me)[:len(*me)-1] - return val -} - -type message interface { - id() (uint16, uint16) - wait() bool - read(io.Reader) error - write(io.Writer) error -} - -type messageWithContent interface { - message - getContent() (properties, []byte) - setContent(properties, []byte) -} - -/* -The base interface implemented as: - -2.3.5 frame Details - -All frames consist of a header (7 octets), a payload of arbitrary size, and a 'frame-end' octet that detects -malformed frames: - - 0 1 3 7 size+7 size+8 - +------+---------+-------------+ +------------+ +-----------+ - | type | channel | size | | payload | | frame-end | - +------+---------+-------------+ +------------+ +-----------+ - octet short long size octets octet - -To read a frame, we: - - 1. Read the header and check the frame type and channel. - 2. Depending on the frame type, we read the payload and process it. - 3. Read the frame end octet. - -In realistic implementations where performance is a concern, we would use -“read-ahead buffering” or “gathering reads” to avoid doing three separate -system calls to read a frame. - -*/ -type frame interface { - write(io.Writer) error - channel() uint16 -} - -type reader struct { - r io.Reader -} - -type writer struct { - w io.Writer -} - -// Implements the frame interface for Connection RPC -type protocolHeader struct{} - -func (protocolHeader) write(w io.Writer) error { - _, err := w.Write([]byte{'A', 'M', 'Q', 'P', 0, 0, 9, 1}) - return err -} - -func (protocolHeader) channel() uint16 { - panic("only valid as initial handshake") -} - -/* -Method frames carry the high-level protocol commands (which we call "methods"). -One method frame carries one command. The method frame payload has this format: - - 0 2 4 - +----------+-----------+-------------- - - - | class-id | method-id | arguments... - +----------+-----------+-------------- - - - short short ... - -To process a method frame, we: - 1. Read the method frame payload. - 2. Unpack it into a structure. A given method always has the same structure, - so we can unpack the method rapidly. 3. Check that the method is allowed in - the current context. - 4. Check that the method arguments are valid. - 5. Execute the method. - -Method frame bodies are constructed as a list of AMQP data fields (bits, -integers, strings and string tables). The marshalling code is trivially -generated directly from the protocol specifications, and can be very rapid. -*/ -type methodFrame struct { - ChannelId uint16 - ClassId uint16 - MethodId uint16 - Method message -} - -func (me *methodFrame) channel() uint16 { return me.ChannelId } - -/* -Heartbeating is a technique designed to undo one of TCP/IP's features, namely -its ability to recover from a broken physical connection by closing only after -a quite long time-out. In some scenarios we need to know very rapidly if a -peer is disconnected or not responding for other reasons (e.g. it is looping). -Since heartbeating can be done at a low level, we implement this as a special -type of frame that peers exchange at the transport level, rather than as a -class method. -*/ -type heartbeatFrame struct { - ChannelId uint16 -} - -func (me *heartbeatFrame) channel() uint16 { return me.ChannelId } - -/* -Certain methods (such as Basic.Publish, Basic.Deliver, etc.) are formally -defined as carrying content. When a peer sends such a method frame, it always -follows it with a content header and zero or more content body frames. - -A content header frame has this format: - - 0 2 4 12 14 - +----------+--------+-----------+----------------+------------- - - - | class-id | weight | body size | property flags | property list... - +----------+--------+-----------+----------------+------------- - - - short short long long short remainder... - -We place content body in distinct frames (rather than including it in the -method) so that AMQP may support "zero copy" techniques in which content is -never marshalled or encoded. We place the content properties in their own -frame so that recipients can selectively discard contents they do not want to -process -*/ -type headerFrame struct { - ChannelId uint16 - ClassId uint16 - weight uint16 - Size uint64 - Properties properties -} - -func (me *headerFrame) channel() uint16 { return me.ChannelId } - -/* -Content is the application data we carry from client-to-client via the AMQP -server. Content is, roughly speaking, a set of properties plus a binary data -part. The set of allowed properties are defined by the Basic class, and these -form the "content header frame". The data can be any size, and MAY be broken -into several (or many) chunks, each forming a "content body frame". - -Looking at the frames for a specific channel, as they pass on the wire, we -might see something like this: - - [method] - [method] [header] [body] [body] - [method] - ... -*/ -type bodyFrame struct { - ChannelId uint16 - Body []byte -} - -func (me *bodyFrame) channel() uint16 { return me.ChannelId } diff --git a/vendor/github.com/streadway/amqp/uri.go b/vendor/github.com/streadway/amqp/uri.go deleted file mode 100644 index 582464db576..00000000000 --- a/vendor/github.com/streadway/amqp/uri.go +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Source code and contact info at http://github.com/streadway/amqp - -package amqp - -import ( - "errors" - "fmt" - "net/url" - "strconv" - "strings" -) - -var errURIScheme = errors.New("AMQP scheme must be either 'amqp://' or 'amqps://'") - -var schemePorts = map[string]int{ - "amqp": 5672, - "amqps": 5671, -} - -var defaultURI = URI{ - Scheme: "amqp", - Host: "localhost", - Port: 5672, - Username: "guest", - Password: "guest", - Vhost: "/", -} - -// URI represents a parsed AMQP URI string. -type URI struct { - Scheme string - Host string - Port int - Username string - Password string - Vhost string -} - -// ParseURI attempts to parse the given AMQP URI according to the spec. -// See http://www.rabbitmq.com/uri-spec.html. -// -// Default values for the fields are: -// -// Scheme: amqp -// Host: localhost -// Port: 5672 -// Username: guest -// Password: guest -// Vhost: / -// -func ParseURI(uri string) (URI, error) { - me := defaultURI - - u, err := url.Parse(uri) - if err != nil { - return me, err - } - - defaultPort, okScheme := schemePorts[u.Scheme] - - if okScheme { - me.Scheme = u.Scheme - } else { - return me, errURIScheme - } - - host, port := splitHostPort(u.Host) - - if host != "" { - me.Host = host - } - - if port != "" { - port32, err := strconv.ParseInt(port, 10, 32) - if err != nil { - return me, err - } - me.Port = int(port32) - } else { - me.Port = defaultPort - } - - if u.User != nil { - me.Username = u.User.Username() - if password, ok := u.User.Password(); ok { - me.Password = password - } - } - - if u.Path != "" { - if strings.HasPrefix(u.Path, "/") { - if u.Host == "" && strings.HasPrefix(u.Path, "///") { - // net/url doesn't handle local context authorities and leaves that up - // to the scheme handler. In our case, we translate amqp:/// into the - // default host and whatever the vhost should be - if len(u.Path) > 3 { - me.Vhost = u.Path[3:] - } - } else if len(u.Path) > 1 { - me.Vhost = u.Path[1:] - } - } else { - me.Vhost = u.Path - } - } - - return me, nil -} - -// Splits host:port, host, [ho:st]:port, or [ho:st]. Unlike net.SplitHostPort -// which splits :port, host:port or [host]:port -// -// Handles hosts that have colons that are in brackets like [::1]:http -func splitHostPort(addr string) (host, port string) { - i := strings.LastIndex(addr, ":") - - if i >= 0 { - host, port = addr[:i], addr[i+1:] - - if len(port) > 0 && port[len(port)-1] == ']' && addr[0] == '[' { - // we've split on an inner colon, the port was missing outside of the - // brackets so use the full addr. We could assert that host should not - // contain any colons here - host, port = addr, "" - } - } else { - host = addr - } - - return -} - -// PlainAuth returns a PlainAuth structure based on the parsed URI's -// Username and Password fields. -func (me URI) PlainAuth() *PlainAuth { - return &PlainAuth{ - Username: me.Username, - Password: me.Password, - } -} - -func (me URI) String() string { - var authority string - - if me.Username != defaultURI.Username || me.Password != defaultURI.Password { - authority += me.Username - - if me.Password != defaultURI.Password { - authority += ":" + me.Password - } - - authority += "@" - } - - authority += me.Host - - if defaultPort, found := schemePorts[me.Scheme]; !found || defaultPort != me.Port { - authority += ":" + strconv.FormatInt(int64(me.Port), 10) - } - - var vhost string - if me.Vhost != defaultURI.Vhost { - vhost = me.Vhost - } - - return fmt.Sprintf("%s://%s/%s", me.Scheme, authority, url.QueryEscape(vhost)) -} diff --git a/vendor/github.com/streadway/amqp/uri_test.go b/vendor/github.com/streadway/amqp/uri_test.go deleted file mode 100644 index 5d93e0bc73d..00000000000 --- a/vendor/github.com/streadway/amqp/uri_test.go +++ /dev/null @@ -1,328 +0,0 @@ -package amqp - -import ( - "testing" -) - -// Test matrix defined on http://www.rabbitmq.com/uri-spec.html -type testURI struct { - url string - username string - password string - host string - port int - vhost string - canon string -} - -var uriTests = []testURI{ - { - url: "amqp://user:pass@host:10000/vhost", - username: "user", - password: "pass", - host: "host", - port: 10000, - vhost: "vhost", - canon: "amqp://user:pass@host:10000/vhost", - }, - - // this fails due to net/url not parsing pct-encoding in host - // testURI{url: "amqp://user%61:%61pass@ho%61st:10000/v%2Fhost", - // username: "usera", - // password: "apass", - // host: "hoast", - // port: 10000, - // vhost: "v/host", - // }, - - { - url: "amqp://", - username: defaultURI.Username, - password: defaultURI.Password, - host: defaultURI.Host, - port: defaultURI.Port, - vhost: defaultURI.Vhost, - canon: "amqp://localhost/", - }, - - { - url: "amqp://:@/", - username: "", - password: "", - host: defaultURI.Host, - port: defaultURI.Port, - vhost: defaultURI.Vhost, - canon: "amqp://:@localhost/", - }, - - { - url: "amqp://user@", - username: "user", - password: defaultURI.Password, - host: defaultURI.Host, - port: defaultURI.Port, - vhost: defaultURI.Vhost, - canon: "amqp://user@localhost/", - }, - - { - url: "amqp://user:pass@", - username: "user", - password: "pass", - host: defaultURI.Host, - port: defaultURI.Port, - vhost: defaultURI.Vhost, - canon: "amqp://user:pass@localhost/", - }, - - { - url: "amqp://guest:pass@", - username: "guest", - password: "pass", - host: defaultURI.Host, - port: defaultURI.Port, - vhost: defaultURI.Vhost, - canon: "amqp://guest:pass@localhost/", - }, - - { - url: "amqp://host", - username: defaultURI.Username, - password: defaultURI.Password, - host: "host", - port: defaultURI.Port, - vhost: defaultURI.Vhost, - canon: "amqp://host/", - }, - - { - url: "amqp://:10000", - username: defaultURI.Username, - password: defaultURI.Password, - host: defaultURI.Host, - port: 10000, - vhost: defaultURI.Vhost, - canon: "amqp://localhost:10000/", - }, - - { - url: "amqp:///vhost", - username: defaultURI.Username, - password: defaultURI.Password, - host: defaultURI.Host, - port: defaultURI.Port, - vhost: "vhost", - canon: "amqp://localhost/vhost", - }, - - { - url: "amqp://host/", - username: defaultURI.Username, - password: defaultURI.Password, - host: "host", - port: defaultURI.Port, - vhost: defaultURI.Vhost, - canon: "amqp://host/", - }, - - { - url: "amqp://host/%2F", - username: defaultURI.Username, - password: defaultURI.Password, - host: "host", - port: defaultURI.Port, - vhost: "/", - canon: "amqp://host/", - }, - - { - url: "amqp://host/%2F%2F", - username: defaultURI.Username, - password: defaultURI.Password, - host: "host", - port: defaultURI.Port, - vhost: "//", - canon: "amqp://host/%2F%2F", - }, - - { - url: "amqp://host/%2Fslash%2F", - username: defaultURI.Username, - password: defaultURI.Password, - host: "host", - port: defaultURI.Port, - vhost: "/slash/", - canon: "amqp://host/%2Fslash%2F", - }, - - { - url: "amqp://192.168.1.1:1000/", - username: defaultURI.Username, - password: defaultURI.Password, - host: "192.168.1.1", - port: 1000, - vhost: defaultURI.Vhost, - canon: "amqp://192.168.1.1:1000/", - }, - - { - url: "amqp://[::1]", - username: defaultURI.Username, - password: defaultURI.Password, - host: "[::1]", - port: defaultURI.Port, - vhost: defaultURI.Vhost, - canon: "amqp://[::1]/", - }, - - { - url: "amqp://[::1]:1000", - username: defaultURI.Username, - password: defaultURI.Password, - host: "[::1]", - port: 1000, - vhost: defaultURI.Vhost, - canon: "amqp://[::1]:1000/", - }, - - { - url: "amqps:///", - username: defaultURI.Username, - password: defaultURI.Password, - host: defaultURI.Host, - port: schemePorts["amqps"], - vhost: defaultURI.Vhost, - canon: "amqps://localhost/", - }, - - { - url: "amqps://host:1000/", - username: defaultURI.Username, - password: defaultURI.Password, - host: "host", - port: 1000, - vhost: defaultURI.Vhost, - canon: "amqps://host:1000/", - }, -} - -func TestURISpec(t *testing.T) { - for _, test := range uriTests { - u, err := ParseURI(test.url) - if err != nil { - t.Fatal("Could not parse spec URI: ", test.url, " err: ", err) - } - - if test.username != u.Username { - t.Error("For: ", test.url, " usernames do not match. want: ", test.username, " got: ", u.Username) - } - - if test.password != u.Password { - t.Error("For: ", test.url, " passwords do not match. want: ", test.password, " got: ", u.Password) - } - - if test.host != u.Host { - t.Error("For: ", test.url, " hosts do not match. want: ", test.host, " got: ", u.Host) - } - - if test.port != u.Port { - t.Error("For: ", test.url, " ports do not match. want: ", test.port, " got: ", u.Port) - } - - if test.vhost != u.Vhost { - t.Error("For: ", test.url, " vhosts do not match. want: ", test.vhost, " got: ", u.Vhost) - } - - if test.canon != u.String() { - t.Error("For: ", test.url, " canonical string does not match. want: ", test.canon, " got: ", u.String()) - } - } -} - -func TestURIUnknownScheme(t *testing.T) { - if _, err := ParseURI("http://example.com/"); err == nil { - t.Fatal("Expected error when parsing non-amqp scheme") - } -} - -func TestURIScheme(t *testing.T) { - if _, err := ParseURI("amqp://example.com/"); err != nil { - t.Fatalf("Expected to parse amqp scheme, got %v", err) - } - - if _, err := ParseURI("amqps://example.com/"); err != nil { - t.Fatalf("Expected to parse amqps scheme, got %v", err) - } -} - -func TestURIDefaults(t *testing.T) { - url := "amqp://" - uri, err := ParseURI(url) - if err != nil { - t.Fatal("Could not parse") - } - - if uri.String() != "amqp://localhost/" { - t.Fatal("Defaults not encoded properly got:", uri.String()) - } -} - -func TestURIComplete(t *testing.T) { - url := "amqp://bob:dobbs@foo.bar:5678/private" - uri, err := ParseURI(url) - if err != nil { - t.Fatal("Could not parse") - } - - if uri.String() != url { - t.Fatal("Defaults not encoded properly want:", url, " got:", uri.String()) - } -} - -func TestURIDefaultPortAmqpNotIncluded(t *testing.T) { - url := "amqp://foo.bar:5672/" - uri, err := ParseURI(url) - if err != nil { - t.Fatal("Could not parse") - } - - if uri.String() != "amqp://foo.bar/" { - t.Fatal("Defaults not encoded properly got:", uri.String()) - } -} - -func TestURIDefaultPortAmqp(t *testing.T) { - url := "amqp://foo.bar/" - uri, err := ParseURI(url) - if err != nil { - t.Fatal("Could not parse") - } - - if uri.Port != 5672 { - t.Fatal("Default port not correct for amqp, got:", uri.Port) - } -} - -func TestURIDefaultPortAmqpsNotIncludedInString(t *testing.T) { - url := "amqps://foo.bar:5671/" - uri, err := ParseURI(url) - if err != nil { - t.Fatal("Could not parse") - } - - if uri.String() != "amqps://foo.bar/" { - t.Fatal("Defaults not encoded properly got:", uri.String()) - } -} - -func TestURIDefaultPortAmqps(t *testing.T) { - url := "amqps://foo.bar/" - uri, err := ParseURI(url) - if err != nil { - t.Fatal("Could not parse") - } - - if uri.Port != 5671 { - t.Fatal("Default port not correct for amqps, got:", uri.Port) - } -} diff --git a/vendor/github.com/streadway/amqp/write.go b/vendor/github.com/streadway/amqp/write.go deleted file mode 100644 index d392ca237b7..00000000000 --- a/vendor/github.com/streadway/amqp/write.go +++ /dev/null @@ -1,411 +0,0 @@ -// Copyright (c) 2012, Sean Treadway, SoundCloud Ltd. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. -// Source code and contact info at http://github.com/streadway/amqp - -package amqp - -import ( - "bufio" - "bytes" - "encoding/binary" - "errors" - "io" - "math" - "time" -) - -func (me *writer) WriteFrame(frame frame) (err error) { - if err = frame.write(me.w); err != nil { - return - } - - if buf, ok := me.w.(*bufio.Writer); ok { - err = buf.Flush() - } - - return -} - -func (me *methodFrame) write(w io.Writer) (err error) { - var payload bytes.Buffer - - if me.Method == nil { - return errors.New("malformed frame: missing method") - } - - class, method := me.Method.id() - - if err = binary.Write(&payload, binary.BigEndian, class); err != nil { - return - } - - if err = binary.Write(&payload, binary.BigEndian, method); err != nil { - return - } - - if err = me.Method.write(&payload); err != nil { - return - } - - return writeFrame(w, frameMethod, me.ChannelId, payload.Bytes()) -} - -// Heartbeat -// -// Payload is empty -func (me *heartbeatFrame) write(w io.Writer) (err error) { - return writeFrame(w, frameHeartbeat, me.ChannelId, []byte{}) -} - -// CONTENT HEADER -// 0 2 4 12 14 -// +----------+--------+-----------+----------------+------------- - - -// | class-id | weight | body size | property flags | property list... -// +----------+--------+-----------+----------------+------------- - - -// short short long long short remainder... -// -func (me *headerFrame) write(w io.Writer) (err error) { - var payload bytes.Buffer - var zeroTime time.Time - - if err = binary.Write(&payload, binary.BigEndian, me.ClassId); err != nil { - return - } - - if err = binary.Write(&payload, binary.BigEndian, me.weight); err != nil { - return - } - - if err = binary.Write(&payload, binary.BigEndian, me.Size); err != nil { - return - } - - // First pass will build the mask to be serialized, second pass will serialize - // each of the fields that appear in the mask. - - var mask uint16 - - if len(me.Properties.ContentType) > 0 { - mask = mask | flagContentType - } - if len(me.Properties.ContentEncoding) > 0 { - mask = mask | flagContentEncoding - } - if me.Properties.Headers != nil && len(me.Properties.Headers) > 0 { - mask = mask | flagHeaders - } - if me.Properties.DeliveryMode > 0 { - mask = mask | flagDeliveryMode - } - if me.Properties.Priority > 0 { - mask = mask | flagPriority - } - if len(me.Properties.CorrelationId) > 0 { - mask = mask | flagCorrelationId - } - if len(me.Properties.ReplyTo) > 0 { - mask = mask | flagReplyTo - } - if len(me.Properties.Expiration) > 0 { - mask = mask | flagExpiration - } - if len(me.Properties.MessageId) > 0 { - mask = mask | flagMessageId - } - if me.Properties.Timestamp != zeroTime { - mask = mask | flagTimestamp - } - if len(me.Properties.Type) > 0 { - mask = mask | flagType - } - if len(me.Properties.UserId) > 0 { - mask = mask | flagUserId - } - if len(me.Properties.AppId) > 0 { - mask = mask | flagAppId - } - - if err = binary.Write(&payload, binary.BigEndian, mask); err != nil { - return - } - - if hasProperty(mask, flagContentType) { - if err = writeShortstr(&payload, me.Properties.ContentType); err != nil { - return - } - } - if hasProperty(mask, flagContentEncoding) { - if err = writeShortstr(&payload, me.Properties.ContentEncoding); err != nil { - return - } - } - if hasProperty(mask, flagHeaders) { - if err = writeTable(&payload, me.Properties.Headers); err != nil { - return - } - } - if hasProperty(mask, flagDeliveryMode) { - if err = binary.Write(&payload, binary.BigEndian, me.Properties.DeliveryMode); err != nil { - return - } - } - if hasProperty(mask, flagPriority) { - if err = binary.Write(&payload, binary.BigEndian, me.Properties.Priority); err != nil { - return - } - } - if hasProperty(mask, flagCorrelationId) { - if err = writeShortstr(&payload, me.Properties.CorrelationId); err != nil { - return - } - } - if hasProperty(mask, flagReplyTo) { - if err = writeShortstr(&payload, me.Properties.ReplyTo); err != nil { - return - } - } - if hasProperty(mask, flagExpiration) { - if err = writeShortstr(&payload, me.Properties.Expiration); err != nil { - return - } - } - if hasProperty(mask, flagMessageId) { - if err = writeShortstr(&payload, me.Properties.MessageId); err != nil { - return - } - } - if hasProperty(mask, flagTimestamp) { - if err = binary.Write(&payload, binary.BigEndian, uint64(me.Properties.Timestamp.Unix())); err != nil { - return - } - } - if hasProperty(mask, flagType) { - if err = writeShortstr(&payload, me.Properties.Type); err != nil { - return - } - } - if hasProperty(mask, flagUserId) { - if err = writeShortstr(&payload, me.Properties.UserId); err != nil { - return - } - } - if hasProperty(mask, flagAppId) { - if err = writeShortstr(&payload, me.Properties.AppId); err != nil { - return - } - } - - return writeFrame(w, frameHeader, me.ChannelId, payload.Bytes()) -} - -// Body -// -// Payload is one byterange from the full body who's size is declared in the -// Header frame -func (me *bodyFrame) write(w io.Writer) (err error) { - return writeFrame(w, frameBody, me.ChannelId, me.Body) -} - -func writeFrame(w io.Writer, typ uint8, channel uint16, payload []byte) (err error) { - end := []byte{frameEnd} - size := uint(len(payload)) - - _, err = w.Write([]byte{ - byte(typ), - byte((channel & 0xff00) >> 8), - byte((channel & 0x00ff) >> 0), - byte((size & 0xff000000) >> 24), - byte((size & 0x00ff0000) >> 16), - byte((size & 0x0000ff00) >> 8), - byte((size & 0x000000ff) >> 0), - }) - - if err != nil { - return - } - - if _, err = w.Write(payload); err != nil { - return - } - - if _, err = w.Write(end); err != nil { - return - } - - return -} - -func writeShortstr(w io.Writer, s string) (err error) { - b := []byte(s) - - var length uint8 = uint8(len(b)) - - if err = binary.Write(w, binary.BigEndian, length); err != nil { - return - } - - if _, err = w.Write(b[:length]); err != nil { - return - } - - return -} - -func writeLongstr(w io.Writer, s string) (err error) { - b := []byte(s) - - var length uint32 = uint32(len(b)) - - if err = binary.Write(w, binary.BigEndian, length); err != nil { - return - } - - if _, err = w.Write(b[:length]); err != nil { - return - } - - return -} - -/* -'A': []interface{} -'D': Decimal -'F': Table -'I': int32 -'S': string -'T': time.Time -'V': nil -'b': byte -'d': float64 -'f': float32 -'l': int64 -'s': int16 -'t': bool -'x': []byte -*/ -func writeField(w io.Writer, value interface{}) (err error) { - var buf [9]byte - var enc []byte - - switch v := value.(type) { - case bool: - buf[0] = 't' - if v { - buf[1] = byte(1) - } else { - buf[1] = byte(0) - } - enc = buf[:2] - - case byte: - buf[0] = 'b' - buf[1] = byte(v) - enc = buf[:2] - - case int16: - buf[0] = 's' - binary.BigEndian.PutUint16(buf[1:3], uint16(v)) - enc = buf[:3] - - case int32: - buf[0] = 'I' - binary.BigEndian.PutUint32(buf[1:5], uint32(v)) - enc = buf[:5] - - case int64: - buf[0] = 'l' - binary.BigEndian.PutUint64(buf[1:9], uint64(v)) - enc = buf[:9] - - case float32: - buf[0] = 'f' - binary.BigEndian.PutUint32(buf[1:5], math.Float32bits(v)) - enc = buf[:5] - - case float64: - buf[0] = 'd' - binary.BigEndian.PutUint64(buf[1:9], math.Float64bits(v)) - enc = buf[:9] - - case Decimal: - buf[0] = 'D' - buf[1] = byte(v.Scale) - binary.BigEndian.PutUint32(buf[2:6], uint32(v.Value)) - enc = buf[:6] - - case string: - buf[0] = 'S' - binary.BigEndian.PutUint32(buf[1:5], uint32(len(v))) - enc = append(buf[:5], []byte(v)...) - - case []interface{}: // field-array - buf[0] = 'A' - - sec := new(bytes.Buffer) - for _, val := range v { - if err = writeField(sec, val); err != nil { - return - } - } - - binary.BigEndian.PutUint32(buf[1:5], uint32(sec.Len())) - if _, err = w.Write(buf[:5]); err != nil { - return - } - - if _, err = w.Write(sec.Bytes()); err != nil { - return - } - - return - - case time.Time: - buf[0] = 'T' - binary.BigEndian.PutUint64(buf[1:9], uint64(v.Unix())) - enc = buf[:9] - - case Table: - if _, err = w.Write([]byte{'F'}); err != nil { - return - } - return writeTable(w, v) - - case []byte: - buf[0] = 'x' - binary.BigEndian.PutUint32(buf[1:5], uint32(len(v))) - if _, err = w.Write(buf[0:5]); err != nil { - return - } - if _, err = w.Write(v); err != nil { - return - } - return - - case nil: - buf[0] = 'V' - enc = buf[:1] - - default: - return ErrFieldType - } - - _, err = w.Write(enc) - - return -} - -func writeTable(w io.Writer, table Table) (err error) { - var buf bytes.Buffer - - for key, val := range table { - if err = writeShortstr(&buf, key); err != nil { - return - } - if err = writeField(&buf, val); err != nil { - return - } - } - - return writeLongstr(w, string(buf.Bytes())) -}