示例#1
0
文件: dns.go 项目: ably-forks/flynn
func (srv *DNSServer) ListenAndServe() error {
	if srv.GetStore() == nil {
		panic("missing Store")
	}
	if srv.Domain == "" {
		srv.Domain = dnsDomain
	}
	if err := srv.validateRecursors(); err != nil {
		return err
	}

	api := dnsAPI{srv}
	mux := dns.NewServeMux()
	mux.HandleFunc(srv.Domain, api.ServiceLookup)
	if len(srv.Recursors) > 0 {
		mux.HandleFunc(".", api.Recurse)
	}

	errors := make(chan error, 4)
	done := func() { errors <- nil }

	if srv.UDPAddr != "" {
		l, err := reuseport.NewReusablePortPacketConn("udp4", srv.UDPAddr)
		if err != nil {
			return err
		}
		srv.UDPAddr = l.(*net.UDPConn).LocalAddr().String()
		server := &dns.Server{
			Net:               "udp",
			PacketConn:        l,
			Handler:           mux,
			NotifyStartedFunc: done,
		}
		go func() { errors <- server.ActivateAndServe() }()
		srv.servers = append(srv.servers, server)
	}

	if srv.TCPAddr != "" {
		l, err := keepalive.ReusableListen("tcp4", srv.TCPAddr)
		if err != nil {
			return err
		}
		srv.TCPAddr = l.Addr().String()
		server := &dns.Server{
			Net:               "tcp",
			Listener:          l,
			Handler:           mux,
			NotifyStartedFunc: done,
		}
		go func() { errors <- server.ActivateAndServe() }()
		srv.servers = append(srv.servers, server)
	}

	for range srv.servers {
		if err := <-errors; err != nil {
			return err
		}
	}
	return nil
}
示例#2
0
// Ensure the store can be restored from a snapshot
func TestStore_RestoreSnapshot(t *testing.T) {
	// open a store, add some services and trigger a snapshot
	s := MustOpenStore()
	serviceNames := []string{"service0", "service1"}
	for _, name := range serviceNames {
		if err := s.AddService(name, nil); err != nil {
			s.Close()
			t.Fatal(err)
		}
	}
	if err := s.TriggerSnapshot(); err != nil {
		s.Close()
		t.Fatal(err)
	}
	s.Store.Close()

	// open another store with same path and port which will attempt
	// to restore the snapshot
	_, port, _ := net.SplitHostPort(s.Listener.Addr().String())
	ln, err := keepalive.ReusableListen("tcp4", "127.0.0.1:"+port)
	if err != nil {
		t.Fatal(err)
	}
	s = NewStoreWithConfig(StoreConfig{Path: s.Path(), Listener: ln})
	defer s.Close()
	if err := s.Open(); err != nil {
		t.Fatal(err)
	}

	// check the data was restored
	if !reflect.DeepEqual(s.ServiceNames(), serviceNames) {
		t.Fatalf("expected service names %v, got %v", serviceNames, s.ServiceNames())
	}
}
示例#3
0
func NewStoreWithConfig(config StoreConfig) *Store {
	if config.Path == "" {
		// Generate a temporary path.
		f, _ := ioutil.TempFile("", "discoverd-store-")
		f.Close()
		os.Remove(f.Name())
		config.Path = f.Name()
	}

	// Initialize store.
	s := &Store{Store: server.NewStore(config.Path)}

	if config.Listener == nil {
		// Open listener on random port.
		ln, err := keepalive.ReusableListen("tcp4", "127.0.0.1:0")
		if err != nil {
			panic(err)
		}
		config.Listener = ln
	}
	_, port, _ := net.SplitHostPort(config.Listener.Addr().String())

	// Set default test settings.
	s.Listener = config.Listener
	s.Advertise, _ = net.ResolveTCPAddr("tcp", net.JoinHostPort("localhost", port))
	s.HeartbeatTimeout = 50 * time.Millisecond
	s.ElectionTimeout = 50 * time.Millisecond
	s.LeaderLeaseTimeout = 50 * time.Millisecond
	s.CommitTimeout = 5 * time.Millisecond
	s.EnableSingleNode = true

	// Turn off logs if verbose flag is not set.
	if !testing.Verbose() {
		s.LogOutput = ioutil.Discard
	}

	return s
}