github.com/deroproject/derosuite@v2.1.6-1.0.20200307070847-0f2e589c7a2b+incompatible/walletapi/rpcserver.go (about) 1 // Copyright 2017-2018 DERO Project. All rights reserved. 2 // Use of this source code in any form is governed by RESEARCH license. 3 // license can be found in the LICENSE file. 4 // GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8 5 // 6 // 7 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 8 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 9 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 10 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 11 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 12 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 13 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 14 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 15 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 16 17 // the rpc server is an extension of walletapi and doesnot employ any global variables 18 // so a number can be simultaneously active ( based on resources) 19 package walletapi 20 21 import "io" 22 23 //import "fmt" 24 import "time" 25 import "sync" 26 import "log" 27 import "strings" 28 import "net/http" 29 30 //import "github.com/intel-go/fastjson" 31 import "github.com/osamingo/jsonrpc" 32 33 import "github.com/deroproject/derosuite/globals" 34 import "github.com/deroproject/derosuite/structures" 35 36 // all components requiring access to wallet must use , this struct to communicate 37 // this structure must be update while mutex 38 type RPCServer struct { 39 address string 40 srv *http.Server 41 mux *http.ServeMux 42 mr *jsonrpc.MethodRepository 43 Exit_Event chan bool // wallet is shutting down and we must quit ASAP 44 Exit_In_Progress bool 45 46 w *Wallet // reference to the wallet which is open 47 sync.RWMutex 48 } 49 50 func RPCServer_Start(w *Wallet, address string) (*RPCServer, error) { 51 52 //var err error 53 var r RPCServer 54 55 //_ = err 56 57 r.Exit_Event = make(chan bool) 58 r.w = w 59 r.address = address 60 61 go r.Run() 62 //logger.Infof("RPC server started") 63 64 return &r, nil 65 } 66 67 // shutdown the rpc server component 68 func (r *RPCServer) RPCServer_Stop() { 69 r.srv.Shutdown(nil) // shutdown the server 70 r.Exit_In_Progress = true 71 close(r.Exit_Event) // send signal to all connections to exit 72 // TODO we must wait for connections to kill themselves 73 time.Sleep(1 * time.Second) 74 //logger.Infof("RPC Shutdown") 75 76 } 77 78 func (r *RPCServer) ServeHTTP(w http.ResponseWriter, req *http.Request) { 79 80 basic_auth_enabled := false 81 var parts []string 82 83 if globals.Arguments["--rpc-login"] != nil { 84 userpass := globals.Arguments["--rpc-login"].(string) 85 parts = strings.SplitN(userpass, ":", 2) 86 87 basic_auth_enabled = true 88 /*if len(parts) != 2 { // these checks are done and verified during program init 89 globals.Logger.Warnf("RPC user name or password invalid") 90 return 91 }*/ 92 //log.Infof("RPC username \"%s\" password \"%s\" ", parts[0],parts[1]) 93 } 94 95 if basic_auth_enabled { 96 u, p, ok := req.BasicAuth() 97 if !ok { 98 http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) 99 return 100 } 101 if u != parts[0] || p != parts[1] { 102 http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) 103 return 104 } 105 106 } 107 // log.Printf("basic_auth_handler") serve if everything looks okay 108 r.mr.ServeHTTP(w, req) 109 } 110 111 // setup handlers 112 func (r *RPCServer) Run() { 113 114 mr := jsonrpc.NewMethodRepository() 115 r.mr = mr 116 117 // install getbalance handler 118 if err := mr.RegisterMethod("getbalance", GetBalance_Handler{r: r}, structures.GetBalance_Params{}, structures.GetBalance_Result{}); err != nil { 119 log.Fatalln(err) 120 } 121 122 // install getaddress handler 123 if err := mr.RegisterMethod("getaddress", GetAddress_Handler{r: r}, structures.GetAddress_Params{}, structures.GetBalance_Result{}); err != nil { 124 log.Fatalln(err) 125 } 126 127 // install getheight handler 128 if err := mr.RegisterMethod("getheight", GetHeight_Handler{r: r}, structures.GetHeight_Params{}, structures.GetBalance_Result{}); err != nil { 129 log.Fatalln(err) 130 } 131 132 // install transfer handler 133 if err := mr.RegisterMethod("transfer", Transfer_Handler{r: r}, structures.Transfer_Params{}, structures.Transfer_Result{}); err != nil { 134 log.Fatalln(err) 135 } 136 // install transfer_split handler 137 if err := mr.RegisterMethod("transfer_split", TransferSplit_Handler{r: r}, structures.TransferSplit_Params{}, structures.TransferSplit_Result{}); err != nil { 138 log.Fatalln(err) 139 } 140 141 // install get_bulk_payments handler 142 if err := mr.RegisterMethod("get_bulk_payments", Get_Bulk_Payments_Handler{r: r}, structures.Get_Bulk_Payments_Params{}, structures.Get_Bulk_Payments_Result{}); err != nil { 143 log.Fatalln(err) 144 } 145 146 // install query_key handler 147 if err := mr.RegisterMethod("query_key", Query_Key_Handler{r: r}, structures.Query_Key_Params{}, structures.Query_Key_Result{}); err != nil { 148 log.Fatalln(err) 149 } 150 151 // install make_integrated_address handler 152 if err := mr.RegisterMethod("make_integrated_address", Make_Integrated_Address_Handler{r: r}, structures.Make_Integrated_Address_Params{}, structures.Make_Integrated_Address_Result{}); err != nil { 153 log.Fatalln(err) 154 } 155 156 // install split_integrated_address handler 157 if err := mr.RegisterMethod("split_integrated_address", Split_Integrated_Address_Handler{r: r}, structures.Split_Integrated_Address_Params{}, structures.Split_Integrated_Address_Result{}); err != nil { 158 log.Fatalln(err) 159 } 160 161 // install get_transfer_by_txid handler 162 if err := mr.RegisterMethod("get_transfer_by_txid", Get_Transfer_By_TXID_Handler{r: r}, structures.Get_Transfer_By_TXID_Params{}, structures.Get_Transfer_By_TXID_Result{}); err != nil { 163 log.Fatalln(err) 164 } 165 166 // install get_transfers 167 if err := mr.RegisterMethod("get_transfers", Get_Transfers_Handler{r: r}, structures.Get_Transfers_Params{}, structures.Get_Transfers_Result{}); err != nil { 168 log.Fatalln(err) 169 } 170 171 /* 172 if err := mr.RegisterMethod("Main.Echo", EchoHandler{}, EchoParams{}, EchoResult{}); err != nil { 173 log.Fatalln(err) 174 } 175 176 // install getblockcount handler 177 if err := mr.RegisterMethod("getblockcount", GetBlockCount_Handler{}, structures.GetBlockCount_Params{}, structures.GetBlockCount_Result{}); err != nil { 178 log.Fatalln(err) 179 } 180 181 // install on_getblockhash 182 if err := mr.RegisterMethod("on_getblockhash", On_GetBlockHash_Handler{}, structures.On_GetBlockHash_Params{}, structures.On_GetBlockHash_Result{}); err != nil { 183 log.Fatalln(err) 184 } 185 186 // install getblocktemplate handler 187 if err := mr.RegisterMethod("getblocktemplate", GetBlockTemplate_Handler{}, structures.GetBlockTemplate_Params{}, structures.GetBlockTemplate_Result{}); err != nil { 188 log.Fatalln(err) 189 } 190 191 // submitblock handler 192 if err := mr.RegisterMethod("submitblock", SubmitBlock_Handler{}, structures.SubmitBlock_Params{}, structures.SubmitBlock_Result{}); err != nil { 193 log.Fatalln(err) 194 } 195 196 if err := mr.RegisterMethod("getlastblockheader", GetLastBlockHeader_Handler{}, structures.GetLastBlockHeader_Params{}, structures.GetLastBlockHeader_Result{}); err != nil { 197 log.Fatalln(err) 198 } 199 200 if err := mr.RegisterMethod("getblockheaderbyhash", GetBlockHeaderByHash_Handler{}, structures.GetBlockHeaderByHash_Params{}, structures.GetBlockHeaderByHash_Result{}); err != nil { 201 log.Fatalln(err) 202 } 203 204 if err := mr.RegisterMethod("getblockheaderbyheight", GetBlockHeaderByHeight_Handler{}, structures.GetBlockHeaderByHeight_Params{}, structures.GetBlockHeaderByHeight_Result{}); err != nil { 205 log.Fatalln(err) 206 } 207 if err := mr.RegisterMethod("getblock", GetBlock_Handler{}, structures.GetBlock_Params{}, structures.GetBlock_Result{}); err != nil { 208 log.Fatalln(err) 209 } 210 211 if err := mr.RegisterMethod("get_info", GetInfo_Handler{}, structures.GetInfo_Params{}, structures.GetInfo_Result{}); err != nil { 212 log.Fatalln(err) 213 } 214 215 if err := mr.RegisterMethod("gettxpool", GetTxPool_Handler{}, structures.GetTxPool_Params{}, structures.GetTxPool_Result{}); err != nil { 216 log.Fatalln(err) 217 } 218 219 */ 220 // create a new mux 221 r.mux = http.NewServeMux() 222 r.srv = &http.Server{Addr: r.address, Handler: r.mux} 223 224 r.mux.HandleFunc("/", hello) 225 r.mux.Handle("/json_rpc", r) 226 /* 227 // handle nasty http requests 228 r.mux.HandleFunc("/getoutputs.bin", getoutputs) // stream any outputs to server, can make wallet work offline 229 r.mux.HandleFunc("/gettransactions", gettransactions) 230 r.mux.HandleFunc("/sendrawtransaction", SendRawTransaction_Handler) 231 */ 232 //r.mux.HandleFunc("/json_rpc/debug", mr.ServeDebug) 233 234 if err := r.srv.ListenAndServe(); err != http.ErrServerClosed { 235 log.Fatalf("ERR listening to address err %s", err) 236 } 237 238 } 239 240 func hello(w http.ResponseWriter, r *http.Request) { 241 io.WriteString(w, "Hello world!") 242 }