Example #1
0
File: amqp.go Project: justone/pmb
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
}
Example #2
0
File: message.go Project: mwidz/pmb
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
}
Example #3
0
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
}
Example #4
0
File: cap.go Project: ilgooz/cap
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
}
Example #5
0
// 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
}
Example #6
0
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,
	}
}
Example #7
0
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
}