func connectAMQP(URI string, id string, sub string) (*Connection, error) { uriParts, err := amqp.ParseURI(URI) if err != nil { return nil, err } // all resources are prefixed with username var prefix string if len(sub) > 0 { prefix = fmt.Sprintf("%s-%s", uriParts.Username, sub) } else { prefix = uriParts.Username } in := make(chan Message, 10) out := make(chan Message, 10) done := make(chan error) conn := &Connection{In: in, Out: out, uri: URI, prefix: prefix, Id: id} logrus.Debugf("calling listen/send AMQP") go listenToAMQP(conn, done, id) go sendToAMQP(conn, done, id) for i := 1; i <= 2; i++ { err := <-done if err != nil { return nil, err } } return conn, nil }
func connect(URI string, id string) (*Connection, error) { uriParts, err := amqp.ParseURI(URI) if err != nil { return nil, err } // all resources are prefixed with username prefix := uriParts.Username in := make(chan Message, 10) out := make(chan Message, 10) done := make(chan error) conn := &Connection{In: in, Out: out, uri: URI, prefix: prefix} logger.Debugf("calling listen/send") go listenToAMQP(conn, done, id) go sendToAMQP(conn, done, id) for i := 1; i <= 2; i++ { err := <-done if err != nil { return nil, err } } return conn, nil }
func New(uri string) (*AMQPRedialer, error) { u, err := amqp.ParseURI(uri) if err != nil { return nil, err } u.Password = "******" // do not print in logs d := amqpDialer{ uri: uri, address: u.String(), } return &AMQPRedialer{ redialer.New(d), }, nil }
func Open(addr string) (*Cap, error) { _, err := amqp.ParseURI(addr) if err != nil { return nil, err } cap := &Cap{ addr: addr, connectReq: make(chan bool, 0), getConnReq: make(chan getConnReq, 0), } go cap.connectLoop() go cap.connect() return cap, nil }
// ConfigFromURI attempts to parse the given AMQP URI according to the spec // and return a relay config based on it. // 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 ConfigFromURI(amqpUri string) (*Config, error) { uri, err := amqp.ParseURI(amqpUri) if err != nil { return nil, err } // build the configuration, note the defaults above config := &Config{ Addr: uri.Host, Port: uri.Port, Vhost: uri.Vhost, Username: uri.Username, Password: uri.Password, } // assign this field based on wether the scheme is amqps, which is amqp with TLS config.EnableTLS = (uri.Scheme == "amqps") return config, nil }
func init() { // get boxen AMQP config from environment if boxenAMQP := os.Getenv("BOXEN_RABBITMQ_URL"); boxenAMQP != "" { AmqpUri = boxenAMQP if config, err := amqp.ParseURI(boxenAMQP); err == nil { fmt.Printf("Using custom boxen config: %v", boxenAMQP) fmt.Println() HOSTNAME = config.Host USERNAME = config.Username PASSWORD = config.Password PORT = &config.Port } } else { AmqpUri = fmt.Sprintf("amqp://%s:%s@%s:%s/", USERNAME, PASSWORD, HOSTNAME, strconv.Itoa(*PORT)) } if mgmtPort := os.Getenv("BOXEN_RABBITMQ_MGMT_PORT"); mgmtPort != "" { if p, err := strconv.Atoi(mgmtPort); err == nil { ADMINPORT = &p } } // connect AMQP Connection = &AMQPConnection{} // connect Send channel Publisher = &AMQPChannel{ name: "publisher", conn: Connection, } // connect Consume channel Consumer = &AMQPChannel{ name: "consumer", conn: Connection, } }
func initMQ(orig_ctx Context, try_proxy bool, proxy string) (ctx Context, err error) { ctx = orig_ctx defer func() { if e := recover(); e != nil { err = fmt.Errorf("initMQ() -> %v", e) } ctx.Channels.Log <- mig.Log{Desc: "leaving initMQ()"}.Debug() }() //Define the AMQP binding ctx.MQ.Bind.Queue = fmt.Sprintf("mig.agt.%s", ctx.Agent.QueueLoc) ctx.MQ.Bind.Key = fmt.Sprintf("mig.agt.%s", ctx.Agent.QueueLoc) // parse the dial string and use TLS if using amqps amqp_uri, err := amqp.ParseURI(AMQPBROKER) if err != nil { panic(err) } ctx.Channels.Log <- mig.Log{Desc: fmt.Sprintf("AMQP: host=%s, port=%d, vhost=%s", amqp_uri.Host, amqp_uri.Port, amqp_uri.Vhost)}.Debug() if amqp_uri.Scheme == "amqps" { ctx.MQ.UseTLS = true } // create an AMQP configuration with specific timers var dialConfig amqp.Config dialConfig.Heartbeat = 2 * ctx.Sleeper if try_proxy { // if in try_proxy mode, the agent will try to connect to the relay using a CONNECT proxy // but because CONNECT is a HTTP method, not available in AMQP, we need to establish // that connection ourselves, and give it back to the amqp.DialConfig method if proxy == "" { // try to get the proxy from the environemnt (variable HTTP_PROXY) target := "http://" + amqp_uri.Host + ":" + fmt.Sprintf("%d", amqp_uri.Port) req, err := http.NewRequest("GET", target, nil) if err != nil { panic(err) } proxy_url, err := http.ProxyFromEnvironment(req) if err != nil { panic(err) } if proxy_url == nil { panic("Failed to find a suitable proxy in environment") } proxy = proxy_url.Host ctx.Channels.Log <- mig.Log{Desc: fmt.Sprintf("Found proxy at %s", proxy)}.Debug() } ctx.Channels.Log <- mig.Log{Desc: fmt.Sprintf("Connecting via proxy %s", proxy)}.Debug() dialConfig.Dial = func(network, addr string) (conn net.Conn, err error) { // connect to the proxy conn, err = net.DialTimeout("tcp", proxy, 5*time.Second) if err != nil { return } // write a CONNECT request in the tcp connection fmt.Fprintf(conn, "CONNECT "+addr+" HTTP/1.1\r\nHost: "+addr+"\r\n\r\n") // verify status is 200, and flush the buffer status, err := bufio.NewReader(conn).ReadString('\n') if err != nil { return } if status == "" || len(status) < 12 { err = fmt.Errorf("Invalid status received from proxy: '%s'", status[0:len(status)-2]) return } // 9th character in response should be "2" // HTTP/1.0 200 Connection established // ^ if status[9] != '2' { err = fmt.Errorf("Invalid status received from proxy: '%s'", status[0:len(status)-2]) return } ctx.Agent.Env.IsProxied = true ctx.Agent.Env.Proxy = proxy return } } else { dialConfig.Dial = func(network, addr string) (net.Conn, error) { return net.DialTimeout(network, addr, 5*time.Second) } } if ctx.MQ.UseTLS { ctx.Channels.Log <- mig.Log{Desc: "Loading AMQPS TLS parameters"}.Debug() // import the client certificates cert, err := tls.X509KeyPair(AGENTCERT, AGENTKEY) if err != nil { panic(err) } // import the ca cert ca := x509.NewCertPool() if ok := ca.AppendCertsFromPEM(CACERT); !ok { panic("failed to import CA Certificate") } TLSconfig := tls.Config{Certificates: []tls.Certificate{cert}, RootCAs: ca, InsecureSkipVerify: false, Rand: rand.Reader} dialConfig.TLSClientConfig = &TLSconfig } // Open AMQP connection ctx.Channels.Log <- mig.Log{Desc: "Establishing connection to relay"}.Debug() ctx.MQ.conn, err = amqp.DialConfig(AMQPBROKER, dialConfig) if err != nil { ctx.Channels.Log <- mig.Log{Desc: "Connection failed"}.Debug() panic(err) } ctx.MQ.Chan, err = ctx.MQ.conn.Channel() if err != nil { panic(err) } // Limit the number of message the channel will receive at once err = ctx.MQ.Chan.Qos(1, // prefetch count (in # of msg) 0, // prefetch size (in bytes) false) // is global _, err = ctx.MQ.Chan.QueueDeclare(ctx.MQ.Bind.Queue, // Queue name true, // is durable false, // is autoDelete false, // is exclusive false, // is noWait nil) // AMQP args if err != nil { panic(err) } err = ctx.MQ.Chan.QueueBind(ctx.MQ.Bind.Queue, // Queue name ctx.MQ.Bind.Key, // Routing key name mig.Mq_Ex_ToAgents, // Exchange name false, // is noWait nil) // AMQP args if err != nil { panic(err) } // Consume AMQP message into channel ctx.MQ.Bind.Chan, err = ctx.MQ.Chan.Consume(ctx.MQ.Bind.Queue, // queue name "", // some tag false, // is autoAck false, // is exclusive false, // is noLocal false, // is noWait nil) // AMQP args if err != nil { panic(err) } return }