You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

167 lines
5.0 KiB

// 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/deroproject/derosuite/globals"
import "github.com/deroproject/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)
}
}