github.com/avahowell/sia@v0.5.1-beta.0.20160524050156-83dcc3d37c94/api/host.go (about) 1 package api 2 3 import ( 4 "errors" 5 "fmt" 6 "net/http" 7 8 "github.com/NebulousLabs/Sia/crypto" 9 "github.com/NebulousLabs/Sia/modules" 10 11 "github.com/julienschmidt/httprouter" 12 ) 13 14 var ( 15 // errStorageFolderNotFound is returned if a call is made looking for a 16 // storage folder which does not appear to exist within the storage 17 // manager. 18 errStorageFolderNotFound = errors.New("storage folder with the provided path could not be found") 19 ) 20 21 type ( 22 // HostGET contains the information that is returned after a GET request to 23 // /host - a bunch of information about the status of the host. 24 HostGET struct { 25 ExternalSettings modules.HostExternalSettings `json:"externalsettings"` 26 FinancialMetrics modules.HostFinancialMetrics `json:"financialmetrics"` 27 InternalSettings modules.HostInternalSettings `json:"internalsettings"` 28 NetworkMetrics modules.HostNetworkMetrics `json:"networkmetrics"` 29 } 30 31 // StorageGET contains the information that is returned after a GET request 32 // to /storage - a bunch of information about the status of storage 33 // management on the host. 34 StorageGET struct { 35 StorageFolderMetadata []modules.StorageFolderMetadata 36 } 37 ) 38 39 // folderIndex determines the index of the storage folder with the provided 40 // path. 41 func folderIndex(folderPath string, storageFolders []modules.StorageFolderMetadata) (int, error) { 42 for i, sf := range storageFolders { 43 if sf.Path == folderPath { 44 return i, nil 45 } 46 } 47 return -1, errStorageFolderNotFound 48 } 49 50 // hostHandlerGET handles GET requests to the /host API endpoint, returning key 51 // information about the host. 52 func (srv *Server) hostHandlerGET(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { 53 es := srv.host.ExternalSettings() 54 fm := srv.host.FinancialMetrics() 55 is := srv.host.InternalSettings() 56 nm := srv.host.NetworkMetrics() 57 hg := HostGET{ 58 ExternalSettings: es, 59 FinancialMetrics: fm, 60 InternalSettings: is, 61 NetworkMetrics: nm, 62 } 63 writeJSON(w, hg) 64 } 65 66 // hostHandlerPOST handles POST request to the /host API endpoint, which sets 67 // the internal settings of the host. 68 func (srv *Server) hostHandlerPOST(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { 69 // Map each query string to a field in the host settings. 70 settings := srv.host.InternalSettings() 71 qsVars := map[string]interface{}{ 72 "acceptingcontracts": &settings.AcceptingContracts, 73 "maxduration": &settings.MaxDuration, 74 "maxdownloadbatchsize": &settings.MaxDownloadBatchSize, 75 "maxrevisebatchsize": &settings.MaxReviseBatchSize, 76 "netaddress": &settings.NetAddress, 77 "windowsize": &settings.WindowSize, 78 79 "collateral": &settings.Collateral, 80 "collateralbudget": &settings.CollateralBudget, 81 "maxcollateral": &settings.MaxCollateral, 82 83 "downloadlimitgrowth": &settings.DownloadLimitGrowth, 84 "downloadlimitcap": &settings.DownloadLimitCap, 85 "downloadspeedlimit": &settings.DownloadSpeedLimit, 86 "uploadlimitgrowth": &settings.UploadLimitGrowth, 87 "uploadlimitcap": &settings.UploadLimitCap, 88 "uploadspeedlimit": &settings.UploadSpeedLimit, 89 90 "minimumcontractprice": &settings.MinimumContractPrice, 91 "minimumdownloadbandwidthprice": &settings.MinimumDownloadBandwidthPrice, 92 "minimumstorageprice": &settings.MinimumStoragePrice, 93 "minimumuploadbandwidthprice": &settings.MinimumUploadBandwidthPrice, 94 } 95 96 // Iterate through the query string and replace any fields that have been 97 // altered. 98 for qs := range qsVars { 99 if req.FormValue(qs) != "" { // skip empty values 100 _, err := fmt.Sscan(req.FormValue(qs), qsVars[qs]) 101 if err != nil { 102 writeError(w, "Malformed "+qs, http.StatusBadRequest) 103 return 104 } 105 } 106 } 107 err := srv.host.SetInternalSettings(settings) 108 if err != nil { 109 writeError(w, err.Error(), http.StatusBadRequest) 110 return 111 } 112 writeSuccess(w) 113 } 114 115 // hostAnnounceHandler handles the API call to get the host to announce itself 116 // to the network. 117 func (srv *Server) hostAnnounceHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { 118 var err error 119 if addr := req.FormValue("netaddress"); addr != "" { 120 err = srv.host.AnnounceAddress(modules.NetAddress(addr)) 121 } else { 122 err = srv.host.Announce() 123 } 124 if err != nil { 125 writeError(w, err.Error(), http.StatusBadRequest) 126 return 127 } 128 writeSuccess(w) 129 } 130 131 // storageHandler returns a bunch of information about storage management on 132 // the host. 133 func (srv *Server) storageHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { 134 sfs := srv.host.StorageFolders() 135 sg := StorageGET{ 136 StorageFolderMetadata: sfs, 137 } 138 writeJSON(w, sg) 139 } 140 141 // storageFoldersAddHandler adds a storage folder to the storage manager. 142 func (srv *Server) storageFoldersAddHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { 143 folderPath := req.FormValue("path") 144 var folderSize uint64 145 _, err := fmt.Sscan(req.FormValue("size"), &folderSize) 146 if err != nil { 147 writeError(w, err.Error(), http.StatusBadRequest) 148 return 149 } 150 err = srv.host.AddStorageFolder(folderPath, folderSize) 151 if err != nil { 152 writeError(w, err.Error(), http.StatusBadRequest) 153 return 154 } 155 writeSuccess(w) 156 } 157 158 // storageFoldersResizeHandler resizes a storage folder in the storage manager. 159 func (srv *Server) storageFoldersResizeHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { 160 folderPath := req.FormValue("path") 161 storageFolders := srv.host.StorageFolders() 162 folderIndex, err := folderIndex(folderPath, storageFolders) 163 if err != nil { 164 writeError(w, err.Error(), http.StatusBadRequest) 165 return 166 } 167 168 var newSize uint64 169 _, err = fmt.Sscan(req.FormValue("newsize"), &newSize) 170 if err != nil { 171 writeError(w, err.Error(), http.StatusBadRequest) 172 return 173 } 174 err = srv.host.ResizeStorageFolder(folderIndex, newSize) 175 if err != nil { 176 writeError(w, err.Error(), http.StatusBadRequest) 177 return 178 } 179 writeSuccess(w) 180 } 181 182 // storageFoldersRemoveHandler removes a storage folder from the storage 183 // manager. 184 func (srv *Server) storageFoldersRemoveHandler(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { 185 folderPath := req.FormValue("path") 186 storageFolders := srv.host.StorageFolders() 187 folderIndex, err := folderIndex(folderPath, storageFolders) 188 if err != nil { 189 writeError(w, err.Error(), http.StatusBadRequest) 190 return 191 } 192 193 force := req.FormValue("force") == "true" 194 err = srv.host.RemoveStorageFolder(folderIndex, force) 195 if err != nil { 196 writeError(w, err.Error(), http.StatusBadRequest) 197 return 198 } 199 writeSuccess(w) 200 } 201 202 // storageSectorsDeleteHandler handles the call to delete a sector from the 203 // storage manager. 204 func (srv *Server) storageSectorsDeleteHandler(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { 205 sectorRoot, err := scanAddress(ps.ByName("merkleroot")) 206 if err != nil { 207 writeError(w, err.Error(), http.StatusBadRequest) 208 return 209 } 210 err = srv.host.DeleteSector(crypto.Hash(sectorRoot)) 211 if err != nil { 212 writeError(w, err.Error(), http.StatusBadRequest) 213 return 214 } 215 writeSuccess(w) 216 }