|
|
// Copyright 2017-2018 DERO Project. All rights reserved.
// Use of this source code in any form is governed by RESEARCH license.
// license can be found in the LICENSE file.
// GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8
//
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package main
/* this file handles communication with the daemon * this includes receiving output information * * */ import "io" import "fmt" import "net" import "time" import "sync" import "net/http" import "compress/gzip"
//import "github.com/romana/rlog"
//import "github.com/pierrec/lz4"
import "github.com/ybbus/jsonrpc"
import "github.com/arnaucode/derosuite/globals" import "github.com/arnaucode/derosuite/blockchain/rpcserver"
var Wallet_Height uint64 // height of wallet
var Daemon_Height uint64 // height of daemon
var Connected bool = true
var rpcClient *jsonrpc.RPCClient var netClient *http.Client var endpoint string
var output_lock sync.Mutex
// this is as simple as it gets
// single threaded communication to get the daemon status and height
func Run_Communication_Engine() {
// check if user specified daemon address explicitly
if globals.Arguments["--daemon-address"] != nil { daemon_address := globals.Arguments["--daemon-address"].(string)
remote_end, err := net.ResolveTCPAddr("tcp", daemon_address) if err != nil { globals.Logger.Warnf("Daemon address \"%s\" is invalid. parse err %s", daemon_address, err) } else {
fmt.Printf("%+v\n", remote_end.IP) if remote_end.IP == nil || remote_end.IP.IsUnspecified() { // user never provided an ipaddress, use loopback
globals.Logger.Debugf("Setting loopback ip on daemon endpoint") remote_end.IP = net.IPv4(127, 0, 0, 1) } endpoint = remote_end.String() }
}
// if user provided endpoint has error, use default
if endpoint == "" { endpoint = "127.0.0.1:9999" if !globals.IsMainnet() { endpoint = "127.0.0.1:28091" } }
globals.Logger.Debugf("Daemon endpoint %s", endpoint)
// TODO enable socks support here
var netTransport = &http.Transport{ Dial: (&net.Dialer{ Timeout: 5 * time.Second, // 5 second timeout
}).Dial, TLSHandshakeTimeout: 5 * time.Second, }
netClient = &http.Client{ Timeout: time.Second * 10, Transport: netTransport, }
// create client
rpcClient = jsonrpc.NewRPCClient("http://" + endpoint + "/json_rpc")
for { time.Sleep(1 * time.Second) // ping server every second
// execute rpc to service
response, err := rpcClient.Call("get_info")
// notify user of any state change
// if daemon connection breaks or comes live again
if err == nil { if !Connected { globals.Logger.Infof("Connection to RPC server successful") Connected = true } } else { if Connected { globals.Logger.Warnf("Connection to RPC server Failed err %s", err) Connected = false } continue // try next time
} var info rpcserver.GetInfo_Result err = response.GetObject(&info) if err != nil { globals.Logger.Warnf("Daemon getinfo RPC parsing error err: %s\n", err) continue } // detect whether both are in different modes
// daemon is in testnet and wallet in mainnet or
// daemon
if info.Testnet != !globals.IsMainnet() { globals.Logger.Warnf("Mainnet/TestNet is different between wallet/daemon.Please run daemon/wallet without --testnet") } Daemon_Height = info.Height
}
}
// get the outputs from the daemon, requesting specfic outputs
// the range can be anything
// if stop is zero,
// the daemon will flush out everything it has ASAP
// the stream can be saved and used later on
func Get_Outputs(start uint64, stop uint64) {
output_lock.Lock() defer output_lock.Unlock() if Connected { // only execute query if we are connected
response, err := http.Get(fmt.Sprintf("http://%s/getoutputs.bin?start=%d", endpoint, start)) if err != nil { globals.Logger.Warnf("Error while requesting outputs from daemon err %s", err) // os.Exit(1)
} else { defer response.Body.Close()
// lz4reader := lz4.NewReader(response.Body)
// io.Copy(pipe_writer, lz4reader)
gzipreader, err := gzip.NewReader(response.Body) if err != nil { globals.Logger.Warnf("Error while decompressing output from daemon err: %s ", err) return } defer gzipreader.Close() io.Copy(pipe_writer, gzipreader)
} // contents, err := ioutil.ReadAll(response.Body)
}
}
|