Example #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
}
Example #2
0
func (d *discoveryServer) Announce(ctx context.Context, announcement *pb.Announcement) (*empty.Empty, error) {
	claims, err := d.discovery.ValidateTTNAuthContext(ctx)
	if err != nil {
		return nil, err
	}

	// If not in development mode
	if d.discovery.Component.Identity.Id != "dev" {
		if !d.discovery.IsMasterAuthServer(claims.Issuer) {
			return nil, errPermissionDeniedf("Token issuer %s is not allowed to make changes to the network settings", claims.Issuer)
		}

		// Can't announce development components
		if claims.Subject == "dev" {
			return nil, errPermissionDeniedf("Can't announce development components to production networks")
		}
	}

	if claims.Subject != announcement.Id {
		return nil, errPermissionDeniedf("Token subject %s does not correspond with announcement ID %s", claims.Subject, announcement.Id)
	}
	if claims.Type != announcement.ServiceName {
		return nil, errPermissionDeniedf("Token type %s does not correspond with announcement service type %s", claims.Type, announcement.ServiceName)
	}
	announcementCopy := *announcement
	announcement.Metadata = []*pb.Metadata{} // This will be taken from existing announcement
	err = d.discovery.Announce(&announcementCopy)
	if err != nil {
		return nil, err
	}
	return &empty.Empty{}, nil
}