-
Notifications
You must be signed in to change notification settings - Fork 16
/
rpc.go
134 lines (125 loc) · 3.59 KB
/
rpc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package common
import (
"bytes"
"crypto/tls"
"crypto/x509"
"encoding/json"
"github.com/Qitmeer/qng/cmd/miner/common/socks"
"github.com/Qitmeer/qng/rpc/client/cmds"
"io/ioutil"
"net"
"net/http"
"strings"
"time"
)
type RpcClient struct {
Cfg *GlobalConfig
GbtID int64
SubmitID int64
}
// newHTTPClient returns a new HTTP client that is configured according to the
// proxy and TLS settings in the associated connection configuration.
func (rpc *RpcClient) newHTTPClient() (*http.Client, error) {
// Configure proxy if needed.
var dial func(network, addr string) (net.Conn, error)
if rpc.Cfg.OptionConfig.Proxy != "" {
proxy := &socks.Proxy{
Addr: rpc.Cfg.OptionConfig.Proxy,
Username: rpc.Cfg.OptionConfig.ProxyUser,
Password: rpc.Cfg.OptionConfig.ProxyPass,
}
dial = func(network, addr string) (net.Conn, error) {
c, err := proxy.Dial(network, addr)
if err != nil {
return nil, err
}
return c, nil
}
}
// Configure TLS if needed.
var tlsConfig *tls.Config
if !rpc.Cfg.SoloConfig.NoTLS && rpc.Cfg.SoloConfig.RPCCert != "" {
pem, err := ioutil.ReadFile(rpc.Cfg.SoloConfig.RPCCert)
if err != nil {
return nil, err
}
pool := x509.NewCertPool()
pool.AppendCertsFromPEM(pem)
tlsConfig = &tls.Config{
RootCAs: pool,
InsecureSkipVerify: rpc.Cfg.SoloConfig.NoTLS,
}
} else {
tlsConfig = &tls.Config{
InsecureSkipVerify: rpc.Cfg.SoloConfig.NoTLS,
}
}
// Create and return the new HTTP client potentially configured with a
// proxy and TLS.
client := http.Client{
Transport: &http.Transport{
Dial: dial,
TLSClientConfig: tlsConfig,
DialContext: (&net.Dialer{
Timeout: time.Duration(rpc.Cfg.OptionConfig.Timeout) * time.Second,
KeepAlive: time.Duration(rpc.Cfg.OptionConfig.Timeout) * time.Second,
DualStack: true,
}).DialContext,
},
}
return &client, nil
}
func (rpc *RpcClient) RpcResult(method string, params []interface{}, id string) []byte {
protocol := "http"
if !rpc.Cfg.SoloConfig.NoTLS {
protocol = "https"
}
req, err := cmds.NewRequest(id, method, params)
url := rpc.Cfg.SoloConfig.RPCServer
if !strings.Contains(rpc.Cfg.SoloConfig.RPCServer, "://") {
url = protocol + "://" + url
}
bodyB, err := json.Marshal(req)
if err != nil {
MinerLoger.Error("request failed ", "error", err)
return nil
}
bodyBuff := bytes.NewBuffer(bodyB)
httpRequest, err := http.NewRequest("POST", url, bodyBuff)
if err != nil {
MinerLoger.Error("rpc connect failed ", "error", err)
return nil
}
httpRequest.Close = true
httpRequest.Header.Set("Content-Type", "application/json")
// Configure basic access authorization.
httpRequest.SetBasicAuth(rpc.Cfg.SoloConfig.RPCUser, rpc.Cfg.SoloConfig.RPCPassword)
// Create the new HTTP client that is configured according to the user-
// specified options and submit the request.
httpClient, err := rpc.newHTTPClient()
if err != nil {
MinerLoger.Error("rpc auth faild ", "error", err)
return nil
}
defer httpClient.CloseIdleConnections()
httpClient.Timeout = time.Duration(rpc.Cfg.OptionConfig.Timeout) * time.Second
httpResponse, err := httpClient.Do(httpRequest)
if err != nil {
MinerLoger.Error("rpc request faild ", "error", err)
return nil
}
defer func() {
_ = httpResponse.Body.Close()
}()
body, err := ioutil.ReadAll(httpResponse.Body)
if err != nil {
MinerLoger.Error("error reading json reply", "error", err)
return nil
}
if httpResponse.StatusCode != 200 {
time.Sleep(30 * time.Second)
MinerLoger.Error("error http response", "status", httpResponse.Status, "body", string(body), "wait sec", 30)
return nil
}
return body
}