Esempio n. 1
0
// getBroker gets or creates a broker association and returns the broker
// the first time it also starts a goroutine that receives downlink from the broker
func (r *router) getBroker(brokerAnnouncement *pb_discovery.Announcement) (*broker, error) {
	// We're going to be optimistic and guess that the broker is already active
	r.brokersLock.RLock()
	brk, ok := r.brokers[brokerAnnouncement.Id]
	r.brokersLock.RUnlock()
	if ok {
		return brk, nil
	}

	// If it doesn't we still have to lock
	r.brokersLock.Lock()
	defer r.brokersLock.Unlock()
	if _, ok := r.brokers[brokerAnnouncement.Id]; !ok {

		// Connect to the server
		// TODO(htdvisser): This is blocking
		conn, err := brokerAnnouncement.Dial()
		if err != nil {
			return nil, err
		}
		client := pb_broker.NewBrokerClient(conn)

		association := pb_broker.NewMonitoredRouterStream(client, func() context.Context {
			return r.GetContext("")
		})
		downlink := association.Channel()

		brk := &broker{
			conn:        conn,
			association: association,
			client:      client,
			uplink:      make(chan *pb_broker.UplinkMessage),
		}

		go func() {
			for {
				select {
				case message := <-brk.uplink:
					association.Send(message)
				case message := <-downlink:
					go r.HandleDownlink(message)
				}
			}
		}()

		r.brokers[brokerAnnouncement.Id] = brk
	}
	return r.brokers[brokerAnnouncement.Id], nil
}