Example #1
0
// Creates a new bootstrapper, configuring to listen on the given interface for
// for incoming requests and scan the same interface for other peers. The magic
// is used to filter multiple Iris networks in the same physical network, while
// the overlay is the TCP listener port of the DHT.
func New(ipnet *net.IPNet, magic []byte, node *big.Int, overlay int) (*Bootstrapper, chan *Event, error) {
	// Issue a warning if we have a single machine subnet
	if ones, bits := ipnet.Mask.Size(); bits-ones < 2 {
		log.Printf("bootstrap: WARNING! cannot search on interface %v, network mask covers the whole space", ipnet)
	}
	bs := &Bootstrapper{
		magic: magic,
		beats: make(chan *Event, config.BootBeatsBuffer),
		fast:  true,
	}
	// Open the server socket
	var err error
	for _, port := range config.BootPorts {
		bs.addr, err = net.ResolveUDPAddr("udp", net.JoinHostPort(ipnet.IP.String(), strconv.Itoa(port)))
		if err != nil {
			return nil, nil, err
		}
		bs.sock, err = net.ListenUDP("udp", bs.addr)
		if err != nil {
			continue
		} else {
			bs.addr.Port = bs.sock.LocalAddr().(*net.UDPAddr).Port
			bs.mask = &ipnet.Mask
			break
		}
	}
	if err != nil {
		return nil, nil, fmt.Errorf("no available ports")
	}
	// Generate the local heartbeat messages (request and response)
	bs.magic = magic
	bs.gob = gobber.New()
	bs.gob.Init(new(Message))

	msg := Message{
		Version: config.ProtocolVersion,
		Magic:   magic,
		NodeId:  node,
		Overlay: overlay,
		Request: true,
	}
	if buf, err := bs.gob.Encode(msg); err != nil {
		return nil, nil, fmt.Errorf("request encode failed: %v.", err)
	} else {
		bs.request = make([]byte, len(buf))
		copy(bs.request, buf)
	}

	msg.Request = false
	if buf, err := bs.gob.Encode(msg); err != nil {
		return nil, nil, fmt.Errorf("response encode failed: %v.", err)
	} else {
		bs.response = make([]byte, len(buf))
		copy(bs.response, buf)
	}
	// Return the ready-to-boot bootstrapper
	return bs, bs.beats, nil
}
Example #2
0
// Creates a new bootstrapper, configuring to listen on the given interface for
// for incoming requests and scan the same interface for other peers. The magic
// is used to filter multiple Iris networks in the same physical network, while
// the overlay is the TCP listener port of the DHT.
func New(ipnet *net.IPNet, magic []byte, owner *big.Int, endpoint int) (*Bootstrapper, chan *Event, error) {
	logger := log15.New("subsys", "bootstrap", "ipnet", ipnet)
	gobber := gobber.New()
	gobber.Init(new(Message))

	// Do some environment dependent IP black magic
	if detectGoogleComputeEngine() {
		// Google Compute Engine issues /32 addresses, find real subnet
		logger.Info("detected GCE, retrieving real netmask")
		old := ipnet.String()
		if err := updateIPNet(ipnet); err != nil {
			logger.Error("failed to retrieve netmask, defaulting", "error", err)
			ipnet.Mask = ipnet.IP.DefaultMask()
		}
		logger.Info("network subnet mask replaced", "old", old, "new", ipnet)
		logger = log15.New("subsys", "bootstrap", "ipnet", ipnet)
	}
	b := &Bootstrapper{
		ipnet: ipnet,
		magic: magic,
		beats: make(chan *Event, config.BootBeatsBuffer),
		phase: uint32(0),

		gob:      gobber,
		request:  newBootstrapRequest(magic, owner, endpoint, gobber),
		response: newBootstrapResponse(magic, owner, endpoint, gobber),

		// Seeding algorithms and address sinks
		scanSeed:   newScanSeeder(ipnet, logger),
		probeSeed:  newProbeSeeder(ipnet, logger),
		coreOSSeed: newCoreOSSeeder(ipnet, logger),
		scanSink:   make(chan *net.IPAddr, config.BootSeedSinkBuffer),
		probeSink:  make(chan *net.IPAddr, config.BootSeedSinkBuffer),
		coreOSSink: make(chan *net.IPAddr, config.BootSeedSinkBuffer),

		// Maintenance fields
		quit: make(chan chan error),
		log:  logger,
	}
	// Open the server socket
	var err error
	for _, port := range config.BootPorts {
		b.addr, err = net.ResolveUDPAddr("udp", net.JoinHostPort(ipnet.IP.String(), strconv.Itoa(port)))
		if err != nil {
			return nil, nil, err
		}
		b.sock, err = net.ListenUDP("udp", b.addr)
		if err != nil {
			continue
		} else {
			b.addr.Port = b.sock.LocalAddr().(*net.UDPAddr).Port
			b.mask = &ipnet.Mask
			break
		}
	}
	if err != nil {
		return nil, nil, fmt.Errorf("no available ports")
	}
	// Return the ready-to-boot bootstrapper
	return b, b.beats, nil
}