1// Copyright (c) 2014-2017 The btcsuite developers
2// Use of this source code is governed by an ISC
3// license that can be found in the LICENSE file.
4
5package rpcclient
6
7import (
8	"encoding/json"
9
10	"github.com/btcsuite/btcd/btcjson"
11)
12
13// AddNodeCommand enumerates the available commands that the AddNode function
14// accepts.
15type AddNodeCommand string
16
17// Constants used to indicate the command for the AddNode function.
18const (
19	// ANAdd indicates the specified host should be added as a persistent
20	// peer.
21	ANAdd AddNodeCommand = "add"
22
23	// ANRemove indicates the specified peer should be removed.
24	ANRemove AddNodeCommand = "remove"
25
26	// ANOneTry indicates the specified host should try to connect once,
27	// but it should not be made persistent.
28	ANOneTry AddNodeCommand = "onetry"
29)
30
31// String returns the AddNodeCommand in human-readable form.
32func (cmd AddNodeCommand) String() string {
33	return string(cmd)
34}
35
36// FutureAddNodeResult is a future promise to deliver the result of an
37// AddNodeAsync RPC invocation (or an applicable error).
38type FutureAddNodeResult chan *response
39
40// Receive waits for the response promised by the future and returns an error if
41// any occurred when performing the specified command.
42func (r FutureAddNodeResult) Receive() error {
43	_, err := receiveFuture(r)
44	return err
45}
46
47// AddNodeAsync returns an instance of a type that can be used to get the result
48// of the RPC at some future time by invoking the Receive function on the
49// returned instance.
50//
51// See AddNode for the blocking version and more details.
52func (c *Client) AddNodeAsync(host string, command AddNodeCommand) FutureAddNodeResult {
53	cmd := btcjson.NewAddNodeCmd(host, btcjson.AddNodeSubCmd(command))
54	return c.sendCmd(cmd)
55}
56
57// AddNode attempts to perform the passed command on the passed persistent peer.
58// For example, it can be used to add or a remove a persistent peer, or to do
59// a one time connection to a peer.
60//
61// It may not be used to remove non-persistent peers.
62func (c *Client) AddNode(host string, command AddNodeCommand) error {
63	return c.AddNodeAsync(host, command).Receive()
64}
65
66// FutureNodeResult is a future promise to deliver the result of a NodeAsync
67// RPC invocation (or an applicable error).
68type FutureNodeResult chan *response
69
70// Receive waits for the response promised by the future and returns an error if
71// any occurred when performing the specified command.
72func (r FutureNodeResult) Receive() error {
73	_, err := receiveFuture(r)
74	return err
75}
76
77// NodeAsync returns an instance of a type that can be used to get the result
78// of the RPC at some future time by invoking the Receive function on the
79// returned instance.
80//
81// See Node for the blocking version and more details.
82func (c *Client) NodeAsync(command btcjson.NodeSubCmd, host string,
83	connectSubCmd *string) FutureNodeResult {
84	cmd := btcjson.NewNodeCmd(command, host, connectSubCmd)
85	return c.sendCmd(cmd)
86}
87
88// Node attempts to perform the passed node command on the host.
89// For example, it can be used to add or a remove a persistent peer, or to do
90// connect or diconnect a non-persistent one.
91//
92// The connectSubCmd should be set either "perm" or "temp", depending on
93// whether we are targetting a persistent or non-persistent peer. Passing nil
94// will cause the default value to be used, which currently is "temp".
95func (c *Client) Node(command btcjson.NodeSubCmd, host string,
96	connectSubCmd *string) error {
97	return c.NodeAsync(command, host, connectSubCmd).Receive()
98}
99
100// FutureGetAddedNodeInfoResult is a future promise to deliver the result of a
101// GetAddedNodeInfoAsync RPC invocation (or an applicable error).
102type FutureGetAddedNodeInfoResult chan *response
103
104// Receive waits for the response promised by the future and returns information
105// about manually added (persistent) peers.
106func (r FutureGetAddedNodeInfoResult) Receive() ([]btcjson.GetAddedNodeInfoResult, error) {
107	res, err := receiveFuture(r)
108	if err != nil {
109		return nil, err
110	}
111
112	// Unmarshal as an array of getaddednodeinfo result objects.
113	var nodeInfo []btcjson.GetAddedNodeInfoResult
114	err = json.Unmarshal(res, &nodeInfo)
115	if err != nil {
116		return nil, err
117	}
118
119	return nodeInfo, nil
120}
121
122// GetAddedNodeInfoAsync returns an instance of a type that can be used to get
123// the result of the RPC at some future time by invoking the Receive function on
124// the returned instance.
125//
126// See GetAddedNodeInfo for the blocking version and more details.
127func (c *Client) GetAddedNodeInfoAsync(peer string) FutureGetAddedNodeInfoResult {
128	cmd := btcjson.NewGetAddedNodeInfoCmd(true, &peer)
129	return c.sendCmd(cmd)
130}
131
132// GetAddedNodeInfo returns information about manually added (persistent) peers.
133//
134// See GetAddedNodeInfoNoDNS to retrieve only a list of the added (persistent)
135// peers.
136func (c *Client) GetAddedNodeInfo(peer string) ([]btcjson.GetAddedNodeInfoResult, error) {
137	return c.GetAddedNodeInfoAsync(peer).Receive()
138}
139
140// FutureGetAddedNodeInfoNoDNSResult is a future promise to deliver the result
141// of a GetAddedNodeInfoNoDNSAsync RPC invocation (or an applicable error).
142type FutureGetAddedNodeInfoNoDNSResult chan *response
143
144// Receive waits for the response promised by the future and returns a list of
145// manually added (persistent) peers.
146func (r FutureGetAddedNodeInfoNoDNSResult) Receive() ([]string, error) {
147	res, err := receiveFuture(r)
148	if err != nil {
149		return nil, err
150	}
151
152	// Unmarshal result as an array of strings.
153	var nodes []string
154	err = json.Unmarshal(res, &nodes)
155	if err != nil {
156		return nil, err
157	}
158
159	return nodes, nil
160}
161
162// GetAddedNodeInfoNoDNSAsync returns an instance of a type that can be used to
163// get the result of the RPC at some future time by invoking the Receive
164// function on the returned instance.
165//
166// See GetAddedNodeInfoNoDNS for the blocking version and more details.
167func (c *Client) GetAddedNodeInfoNoDNSAsync(peer string) FutureGetAddedNodeInfoNoDNSResult {
168	cmd := btcjson.NewGetAddedNodeInfoCmd(false, &peer)
169	return c.sendCmd(cmd)
170}
171
172// GetAddedNodeInfoNoDNS returns a list of manually added (persistent) peers.
173// This works by setting the dns flag to false in the underlying RPC.
174//
175// See GetAddedNodeInfo to obtain more information about each added (persistent)
176// peer.
177func (c *Client) GetAddedNodeInfoNoDNS(peer string) ([]string, error) {
178	return c.GetAddedNodeInfoNoDNSAsync(peer).Receive()
179}
180
181// FutureGetConnectionCountResult is a future promise to deliver the result
182// of a GetConnectionCountAsync RPC invocation (or an applicable error).
183type FutureGetConnectionCountResult chan *response
184
185// Receive waits for the response promised by the future and returns the number
186// of active connections to other peers.
187func (r FutureGetConnectionCountResult) Receive() (int64, error) {
188	res, err := receiveFuture(r)
189	if err != nil {
190		return 0, err
191	}
192
193	// Unmarshal result as an int64.
194	var count int64
195	err = json.Unmarshal(res, &count)
196	if err != nil {
197		return 0, err
198	}
199
200	return count, nil
201}
202
203// GetConnectionCountAsync returns an instance of a type that can be used to get
204// the result of the RPC at some future time by invoking the Receive function on
205// the returned instance.
206//
207// See GetConnectionCount for the blocking version and more details.
208func (c *Client) GetConnectionCountAsync() FutureGetConnectionCountResult {
209	cmd := btcjson.NewGetConnectionCountCmd()
210	return c.sendCmd(cmd)
211}
212
213// GetConnectionCount returns the number of active connections to other peers.
214func (c *Client) GetConnectionCount() (int64, error) {
215	return c.GetConnectionCountAsync().Receive()
216}
217
218// FuturePingResult is a future promise to deliver the result of a PingAsync RPC
219// invocation (or an applicable error).
220type FuturePingResult chan *response
221
222// Receive waits for the response promised by the future and returns the result
223// of queueing a ping to be sent to each connected peer.
224func (r FuturePingResult) Receive() error {
225	_, err := receiveFuture(r)
226	return err
227}
228
229// PingAsync returns an instance of a type that can be used to get the result of
230// the RPC at some future time by invoking the Receive function on the returned
231// instance.
232//
233// See Ping for the blocking version and more details.
234func (c *Client) PingAsync() FuturePingResult {
235	cmd := btcjson.NewPingCmd()
236	return c.sendCmd(cmd)
237}
238
239// Ping queues a ping to be sent to each connected peer.
240//
241// Use the GetPeerInfo function and examine the PingTime and PingWait fields to
242// access the ping times.
243func (c *Client) Ping() error {
244	return c.PingAsync().Receive()
245}
246
247// FutureGetNetworkInfoResult is a future promise to deliver the result of a
248// GetNetworkInfoAsync RPC invocation (or an applicable error).
249type FutureGetNetworkInfoResult chan *response
250
251// Receive waits for the response promised by the future and returns data about
252// the current network.
253func (r FutureGetNetworkInfoResult) Receive() (*btcjson.GetNetworkInfoResult, error) {
254	res, err := receiveFuture(r)
255	if err != nil {
256		return nil, err
257	}
258
259	// Unmarshal result as an array of getpeerinfo result objects.
260	var networkInfo btcjson.GetNetworkInfoResult
261	err = json.Unmarshal(res, &networkInfo)
262	if err != nil {
263		return nil, err
264	}
265
266	return &networkInfo, nil
267}
268
269// GetNetworkInfoAsync returns an instance of a type that can be used to get the
270// result of the RPC at some future time by invoking the Receive function on the
271// returned instance.
272//
273// See GetNetworkInfo for the blocking version and more details.
274func (c *Client) GetNetworkInfoAsync() FutureGetNetworkInfoResult {
275	cmd := btcjson.NewGetNetworkInfoCmd()
276	return c.sendCmd(cmd)
277}
278
279// GetNetworkInfo returns data about the current network.
280func (c *Client) GetNetworkInfo() (*btcjson.GetNetworkInfoResult, error) {
281	return c.GetNetworkInfoAsync().Receive()
282}
283
284// FutureGetPeerInfoResult is a future promise to deliver the result of a
285// GetPeerInfoAsync RPC invocation (or an applicable error).
286type FutureGetPeerInfoResult chan *response
287
288// Receive waits for the response promised by the future and returns  data about
289// each connected network peer.
290func (r FutureGetPeerInfoResult) Receive() ([]btcjson.GetPeerInfoResult, error) {
291	res, err := receiveFuture(r)
292	if err != nil {
293		return nil, err
294	}
295
296	// Unmarshal result as an array of getpeerinfo result objects.
297	var peerInfo []btcjson.GetPeerInfoResult
298	err = json.Unmarshal(res, &peerInfo)
299	if err != nil {
300		return nil, err
301	}
302
303	return peerInfo, nil
304}
305
306// GetPeerInfoAsync returns an instance of a type that can be used to get the
307// result of the RPC at some future time by invoking the Receive function on the
308// returned instance.
309//
310// See GetPeerInfo for the blocking version and more details.
311func (c *Client) GetPeerInfoAsync() FutureGetPeerInfoResult {
312	cmd := btcjson.NewGetPeerInfoCmd()
313	return c.sendCmd(cmd)
314}
315
316// GetPeerInfo returns data about each connected network peer.
317func (c *Client) GetPeerInfo() ([]btcjson.GetPeerInfoResult, error) {
318	return c.GetPeerInfoAsync().Receive()
319}
320
321// FutureGetNetTotalsResult is a future promise to deliver the result of a
322// GetNetTotalsAsync RPC invocation (or an applicable error).
323type FutureGetNetTotalsResult chan *response
324
325// Receive waits for the response promised by the future and returns network
326// traffic statistics.
327func (r FutureGetNetTotalsResult) Receive() (*btcjson.GetNetTotalsResult, error) {
328	res, err := receiveFuture(r)
329	if err != nil {
330		return nil, err
331	}
332
333	// Unmarshal result as a getnettotals result object.
334	var totals btcjson.GetNetTotalsResult
335	err = json.Unmarshal(res, &totals)
336	if err != nil {
337		return nil, err
338	}
339
340	return &totals, nil
341}
342
343// GetNetTotalsAsync returns an instance of a type that can be used to get the
344// result of the RPC at some future time by invoking the Receive function on the
345// returned instance.
346//
347// See GetNetTotals for the blocking version and more details.
348func (c *Client) GetNetTotalsAsync() FutureGetNetTotalsResult {
349	cmd := btcjson.NewGetNetTotalsCmd()
350	return c.sendCmd(cmd)
351}
352
353// GetNetTotals returns network traffic statistics.
354func (c *Client) GetNetTotals() (*btcjson.GetNetTotalsResult, error) {
355	return c.GetNetTotalsAsync().Receive()
356}
357