// NewDownloader initiates the download request loop with a host, and returns a // Downloader. func NewDownloader(host modules.HostDBEntry, contract modules.RenterContract) (*Downloader, error) { // check that contract has enough value to support a download if len(contract.LastRevision.NewValidProofOutputs) != 2 { return nil, errors.New("invalid contract") } sectorPrice := host.DownloadBandwidthPrice.Mul64(modules.SectorSize) if contract.RenterFunds().Cmp(sectorPrice) < 0 { return nil, errors.New("contract has insufficient funds to support download") } // initiate download loop conn, err := net.DialTimeout("tcp", string(contract.NetAddress), 15*time.Second) if err != nil { return nil, err } // allot 2 minutes for RPC request + revision exchange extendDeadline(conn, modules.NegotiateRecentRevisionTime) defer extendDeadline(conn, time.Hour) if err := encoding.WriteObject(conn, modules.RPCDownload); err != nil { conn.Close() return nil, errors.New("couldn't initiate RPC: " + err.Error()) } if err := verifyRecentRevision(conn, contract); err != nil { conn.Close() // TODO: close gracefully if host has entered revision loop return nil, err } // the host is now ready to accept revisions return &Downloader{ contract: contract, host: host, conn: conn, }, nil }