// threadedProbeHosts tries to fetch the settings of a host. If successful, the // host is put in the set of active hosts. If unsuccessful, the host id deleted // from the set of active hosts. func (hdb *HostDB) threadedProbeHosts() { defer hdb.threadGroup.Done() for hostEntry := range hdb.scanPool { // Request settings from the queued host entry. // TODO: use dialer.Cancel to shutdown quickly hdb.log.Debugln("Scanning", hostEntry.NetAddress, hostEntry.PublicKey) var settings modules.HostExternalSettings err := func() error { conn, err := hdb.dialer.DialTimeout(hostEntry.NetAddress, hostRequestTimeout) if err != nil { return err } defer conn.Close() err = encoding.WriteObject(conn, modules.RPCSettings) if err != nil { return err } var pubkey crypto.PublicKey copy(pubkey[:], hostEntry.PublicKey.Key) return crypto.ReadSignedObject(conn, &settings, maxSettingsLen, pubkey) }() if err != nil { hdb.log.Debugln("Scanning", hostEntry.NetAddress, hostEntry.PublicKey, "failed", err) } else { hdb.log.Debugln("Scanning", hostEntry.NetAddress, hostEntry.PublicKey, "succeeded") } // Update the host tree to have a new entry. hdb.managedUpdateEntry(hostEntry, settings, err) } }
// verifySettings reads a signed HostSettings object from conn, validates the // signature, and checks for discrepancies between the known settings and the // received settings. If there is a discrepancy, the hostDB is notified. The // received settings are returned. func verifySettings(conn net.Conn, host modules.HostDBEntry) (modules.HostDBEntry, error) { // convert host key (types.SiaPublicKey) to a crypto.PublicKey if host.PublicKey.Algorithm != types.SignatureEd25519 || len(host.PublicKey.Key) != crypto.PublicKeySize { build.Critical("hostdb did not filter out host with wrong signature algorithm:", host.PublicKey.Algorithm) return modules.HostDBEntry{}, errors.New("host used unsupported signature algorithm") } var pk crypto.PublicKey copy(pk[:], host.PublicKey.Key) // read signed host settings var recvSettings modules.HostExternalSettings if err := crypto.ReadSignedObject(conn, &recvSettings, modules.NegotiateMaxHostExternalSettingsLen, pk); err != nil { return modules.HostDBEntry{}, errors.New("couldn't read host's settings: " + err.Error()) } // TODO: check recvSettings against host.HostExternalSettings. If there is // a discrepancy, write the error to conn. if recvSettings.NetAddress != host.NetAddress { // for now, just overwrite the NetAddress, since we know that // host.NetAddress works (it was the one we dialed to get conn) recvSettings.NetAddress = host.NetAddress } host.HostExternalSettings = recvSettings return host, nil }