func (client *Client) initBalancer() *balancer.Balancer { dialers := make([]*balancer.Dialer, 0, len(client.cfg.Client.FrontedServers)) for _, s := range client.cfg.Client.FrontedServers { dialer := (&s).dialer() dialers = append(dialers, dialer) } bal := balancer.New(dialers...) if client.balInitialized { log.Printf("Draining balancer channel.") old := <-client.balCh // Close old balancer on a goroutine to avoid blocking here go func() { old.Close() log.Printf("Closed old balancer.") }() } else { log.Printf("Creating balancer channel.") client.balCh = make(chan *balancer.Balancer, 1) } log.Printf("Publishing balancer.") client.balInitialized = true client.balCh <- bal return bal }
// initBalancer takes hosts from cfg.FrontedServers and cfg.ChainedServers and // it uses them to create a balancer. It also looks for the highest QOS dialer // available among the fronted servers. func (client *Client) initBalancer(cfg *ClientConfig) (*balancer.Balancer, fronted.Dialer) { var highestQOSFrontedDialer fronted.Dialer // The dialers slice must be large enough to handle all fronted and chained // servers. dialers := make([]*balancer.Dialer, 0, len(cfg.FrontedServers)+len(cfg.ChainedServers)) // Add fronted servers. log.Debugf("Adding %d domain fronted servers", len(cfg.FrontedServers)) highestQOS := math.MinInt32 for _, s := range cfg.FrontedServers { // Get a dialer for domain fronting (fd) and a dialer to dial to arbitrary // addreses (dialer). fd, dialer := s.dialer(cfg.MasqueradeSets) dialers = append(dialers, dialer) if dialer.QOS > highestQOS { // If this dialer as a higher QOS than our current highestQOS, set it as // the highestQOSFrontedDialer. highestQOSFrontedDialer = fd highestQOS = dialer.QOS } } // Add chained (CONNECT proxy) servers. log.Debugf("Adding %d chained servers", len(cfg.ChainedServers)) for _, s := range cfg.ChainedServers { dialer, err := s.Dialer() if err == nil { dialers = append(dialers, dialer) } else { log.Errorf("Unable to configure chained server. Received error: %v", err) } } bal := balancer.New(dialers...) if client.balInitialized { log.Trace("Draining balancer channel") old := <-client.balCh // Close old balancer on a goroutine to avoid blocking here go func() { old.Close() log.Debug("Closed old balancer") }() } else { log.Trace("Creating balancer channel") client.balCh = make(chan *balancer.Balancer, 1) } log.Trace("Publishing balancer") client.balCh <- bal // We don't need to protect client.balInitialized from race conditions // because it's only accessed here in initBalancer, which always gets called // under Configure, which never gets called concurrently with itself. client.balInitialized = true return bal, highestQOSFrontedDialer }
// initBalancer takes hosts from cfg.ChainedServers and it uses them to create a // balancer. func (client *Client) initBalancer(cfg *ClientConfig) (*balancer.Balancer, error) { if len(cfg.ChainedServers) == 0 { return nil, fmt.Errorf("No chained servers configured, not initializing balancer") } // The dialers slice must be large enough to handle all chained // servers. dialers := make([]*balancer.Dialer, 0, len(cfg.ChainedServers)) // Add chained (CONNECT proxy) servers. log.Debugf("Adding %d chained servers", len(cfg.ChainedServers)) for _, s := range cfg.ChainedServers { dialer, err := s.Dialer(cfg.DeviceID) if err == nil { dialers = append(dialers, dialer) } else { log.Errorf("Unable to configure chained server. Received error: %v", err) } } bal := balancer.New(dialers...) var oldBal *balancer.Balancer var ok bool ob, ok := client.bal.Get(0 * time.Millisecond) if ok { oldBal = ob.(*balancer.Balancer) } log.Trace("Publishing balancer") client.bal.Set(bal) if oldBal != nil { // Close old balancer on a goroutine to avoid blocking here go func() { oldBal.Close() log.Debug("Closed old balancer") }() } return bal, nil }