// 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 }
func (h *handler) associateBroker() error { broker, err := h.Discover("broker", h.ttnBrokerID) if err != nil { return err } conn, err := broker.Dial() if err != nil { return err } h.ttnBrokerConn = conn h.ttnBroker = pb_broker.NewBrokerClient(conn) h.ttnBrokerManager = pb_broker.NewBrokerManagerClient(conn) h.downlink = make(chan *pb_broker.DownlinkMessage) contextFunc := func() context.Context { return h.GetContext("") } upStream := pb_broker.NewMonitoredHandlerSubscribeStream(h.ttnBroker, contextFunc) downStream := pb_broker.NewMonitoredHandlerPublishStream(h.ttnBroker, contextFunc) go func() { for message := range upStream.Channel() { go h.HandleUplink(message) } }() go func() { for message := range h.downlink { if err := downStream.Send(message); err != nil { h.Ctx.WithError(err).Warn("Could not send downlink to Broker") } } }() return nil }