Add a websocket session RPC.
This commit is contained in:
parent
6ac46f9e5f
commit
3c9d18d641
5 changed files with 68 additions and 4 deletions
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2014 The btcsuite developers
|
// Copyright (c) 2014-2015 The btcsuite developers
|
||||||
// Use of this source code is governed by an ISC
|
// Use of this source code is governed by an ISC
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
@ -56,6 +56,15 @@ func NewNotifyNewTransactionsCmd(verbose *bool) *NotifyNewTransactionsCmd {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SessionCmd defines the session JSON-RPC command.
|
||||||
|
type SessionCmd struct{}
|
||||||
|
|
||||||
|
// NewSessionCmd returns a new instance which can be used to issue a session
|
||||||
|
// JSON-RPC command.
|
||||||
|
func NewSessionCmd() *SessionCmd {
|
||||||
|
return &SessionCmd{}
|
||||||
|
}
|
||||||
|
|
||||||
// StopNotifyNewTransactionsCmd defines the stopnotifynewtransactions JSON-RPC command.
|
// StopNotifyNewTransactionsCmd defines the stopnotifynewtransactions JSON-RPC command.
|
||||||
type StopNotifyNewTransactionsCmd struct{}
|
type StopNotifyNewTransactionsCmd struct{}
|
||||||
|
|
||||||
|
@ -158,6 +167,7 @@ func init() {
|
||||||
MustRegisterCmd("notifynewtransactions", (*NotifyNewTransactionsCmd)(nil), flags)
|
MustRegisterCmd("notifynewtransactions", (*NotifyNewTransactionsCmd)(nil), flags)
|
||||||
MustRegisterCmd("notifyreceived", (*NotifyReceivedCmd)(nil), flags)
|
MustRegisterCmd("notifyreceived", (*NotifyReceivedCmd)(nil), flags)
|
||||||
MustRegisterCmd("notifyspent", (*NotifySpentCmd)(nil), flags)
|
MustRegisterCmd("notifyspent", (*NotifySpentCmd)(nil), flags)
|
||||||
|
MustRegisterCmd("session", (*SessionCmd)(nil), flags)
|
||||||
MustRegisterCmd("stopnotifyblocks", (*StopNotifyBlocksCmd)(nil), flags)
|
MustRegisterCmd("stopnotifyblocks", (*StopNotifyBlocksCmd)(nil), flags)
|
||||||
MustRegisterCmd("stopnotifynewtransactions", (*StopNotifyNewTransactionsCmd)(nil), flags)
|
MustRegisterCmd("stopnotifynewtransactions", (*StopNotifyNewTransactionsCmd)(nil), flags)
|
||||||
MustRegisterCmd("stopnotifyspent", (*StopNotifySpentCmd)(nil), flags)
|
MustRegisterCmd("stopnotifyspent", (*StopNotifySpentCmd)(nil), flags)
|
||||||
|
|
10
btcjson/chainsvrwsresults.go
Normal file
10
btcjson/chainsvrwsresults.go
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// Copyright (c) 2015 The btcsuite developers
|
||||||
|
// Use of this source code is governed by an ISC
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package btcjson
|
||||||
|
|
||||||
|
// SessionResult models the data from the session command.
|
||||||
|
type SessionResult struct {
|
||||||
|
SessionID uint64 `json:"sessionid"`
|
||||||
|
}
|
|
@ -685,6 +685,7 @@ user. Click the method name for further details such as parameter and return in
|
||||||
|8|[rescan](#rescan)|Rescan block chain for transactions to addresses and spent transaction outpoints.|[recvtx](#recvtx), [redeemingtx](#redeemingtx), [rescanprogress](#rescanprogress), and [rescanfinished](#rescanfinished) |
|
|8|[rescan](#rescan)|Rescan block chain for transactions to addresses and spent transaction outpoints.|[recvtx](#recvtx), [redeemingtx](#redeemingtx), [rescanprogress](#rescanprogress), and [rescanfinished](#rescanfinished) |
|
||||||
|9|[notifynewtransactions](#notifynewtransactions)|Send notifications for all new transactions as they are accepted into the mempool.|[txaccepted](#txaccepted) or [txacceptedverbose](#txacceptedverbose)|
|
|9|[notifynewtransactions](#notifynewtransactions)|Send notifications for all new transactions as they are accepted into the mempool.|[txaccepted](#txaccepted) or [txacceptedverbose](#txacceptedverbose)|
|
||||||
|10|[stopnotifynewtransactions](#stopnotifynewtransactions)|Stop sending either a txaccepted or a txacceptedverbose notification when a new transaction is accepted into the mempool.|None|
|
|10|[stopnotifynewtransactions](#stopnotifynewtransactions)|Stop sending either a txaccepted or a txacceptedverbose notification when a new transaction is accepted into the mempool.|None|
|
||||||
|
|11|[session](#session)|Return details regarding a websocket client's current connection.|None|
|
||||||
|
|
||||||
<a name="WSExtMethodDetails" />
|
<a name="WSExtMethodDetails" />
|
||||||
**7.2 Method Details**<br />
|
**7.2 Method Details**<br />
|
||||||
|
@ -815,6 +816,20 @@ user. Click the method name for further details such as parameter and return in
|
||||||
|Returns|Nothing|
|
|Returns|Nothing|
|
||||||
[Return to Overview](#WSExtMethodOverview)<br />
|
[Return to Overview](#WSExtMethodOverview)<br />
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
<a name="session"/>
|
||||||
|
|
||||||
|
| | |
|
||||||
|
|---|---|
|
||||||
|
|Method|session|
|
||||||
|
|Notifications|None|
|
||||||
|
|Parameters|None|
|
||||||
|
|Description|Return a JSON object with details regarding a websocket client's current connection to the RPC server. This currently only includes the session ID, a random unsigned 64-bit integer that is created for each newly connected client. Session IDs may be used to verify that the current connection was not lost and subsequently reestablished.|
|
||||||
|
|Returns|`{ (json object)`<br /> `"sessionid": n (numeric) the session ID`<br />`}`|
|
||||||
|
|Example Return|`{`<br /> `"sessionid": 67089679842`<br />`}`|
|
||||||
|
[Return to Overview](#WSExtMethodOverview)<br />
|
||||||
|
|
||||||
|
|
||||||
<a name="Notifications" />
|
<a name="Notifications" />
|
||||||
### 8. Notifications (Websocket-specific)
|
### 8. Notifications (Websocket-specific)
|
||||||
|
|
|
@ -525,6 +525,10 @@ var helpDescsEnUS = map[string]string{
|
||||||
|
|
||||||
// -------- Websocket-specific help --------
|
// -------- Websocket-specific help --------
|
||||||
|
|
||||||
|
// Session help.
|
||||||
|
"session--synopsis": "Return details regarding a websocket client's current connection session.",
|
||||||
|
"sessionresult-sessionid": "The unique session ID for a client's websocket connection.",
|
||||||
|
|
||||||
// NotifyBlocksCmd help.
|
// NotifyBlocksCmd help.
|
||||||
"notifyblocks--synopsis": "Request notifications for whenever a block is connected or disconnected from the main (best) chain.",
|
"notifyblocks--synopsis": "Request notifications for whenever a block is connected or disconnected from the main (best) chain.",
|
||||||
|
|
||||||
|
@ -616,6 +620,7 @@ var rpcResultTypes = map[string][]interface{}{
|
||||||
"verifymessage": []interface{}{(*bool)(nil)},
|
"verifymessage": []interface{}{(*bool)(nil)},
|
||||||
|
|
||||||
// Websocket commands.
|
// Websocket commands.
|
||||||
|
"session": []interface{}{(*btcjson.SessionResult)(nil)},
|
||||||
"notifyblocks": nil,
|
"notifyblocks": nil,
|
||||||
"stopnotifyblocks": nil,
|
"stopnotifyblocks": nil,
|
||||||
"notifynewtransactions": nil,
|
"notifynewtransactions": nil,
|
||||||
|
|
|
@ -54,6 +54,7 @@ var wsHandlersBeforeInit = map[string]wsCommandHandler{
|
||||||
"notifynewtransactions": handleNotifyNewTransactions,
|
"notifynewtransactions": handleNotifyNewTransactions,
|
||||||
"notifyreceived": handleNotifyReceived,
|
"notifyreceived": handleNotifyReceived,
|
||||||
"notifyspent": handleNotifySpent,
|
"notifyspent": handleNotifySpent,
|
||||||
|
"session": handleSession,
|
||||||
"stopnotifyblocks": handleStopNotifyBlocks,
|
"stopnotifyblocks": handleStopNotifyBlocks,
|
||||||
"stopnotifynewtransactions": handleStopNotifyNewTransactions,
|
"stopnotifynewtransactions": handleStopNotifyNewTransactions,
|
||||||
"stopnotifyspent": handleStopNotifySpent,
|
"stopnotifyspent": handleStopNotifySpent,
|
||||||
|
@ -94,7 +95,12 @@ func (s *rpcServer) WebsocketHandler(conn *websocket.Conn, remoteAddr string,
|
||||||
// Create a new websocket client to handle the new websocket connection
|
// Create a new websocket client to handle the new websocket connection
|
||||||
// and wait for it to shutdown. Once it has shutdown (and hence
|
// and wait for it to shutdown. Once it has shutdown (and hence
|
||||||
// disconnected), remove it and any notifications it registered for.
|
// disconnected), remove it and any notifications it registered for.
|
||||||
client := newWebsocketClient(s, conn, remoteAddr, authenticated, isAdmin)
|
client, err := newWebsocketClient(s, conn, remoteAddr, authenticated, isAdmin)
|
||||||
|
if err != nil {
|
||||||
|
rpcsLog.Errorf("Failed to serve client %s: %v", remoteAddr, err)
|
||||||
|
conn.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
s.ntfnMgr.AddClient(client)
|
s.ntfnMgr.AddClient(client)
|
||||||
client.Start()
|
client.Start()
|
||||||
client.WaitForShutdown()
|
client.WaitForShutdown()
|
||||||
|
@ -869,6 +875,11 @@ type wsClient struct {
|
||||||
// false means its access is only to the limited set of RPC calls.
|
// false means its access is only to the limited set of RPC calls.
|
||||||
isAdmin bool
|
isAdmin bool
|
||||||
|
|
||||||
|
// sessionID is a random ID generated for each client when connected.
|
||||||
|
// These IDs may be queried by a client using the session RPC. A change
|
||||||
|
// to the session ID indicates that the client reconnected.
|
||||||
|
sessionID uint64
|
||||||
|
|
||||||
// verboseTxUpdates specifies whether a client has requested verbose
|
// verboseTxUpdates specifies whether a client has requested verbose
|
||||||
// information about all new transactions.
|
// information about all new transactions.
|
||||||
verboseTxUpdates bool
|
verboseTxUpdates bool
|
||||||
|
@ -1383,13 +1394,19 @@ func (c *wsClient) WaitForShutdown() {
|
||||||
// incoming and outgoing messages in separate goroutines complete with queueing
|
// incoming and outgoing messages in separate goroutines complete with queueing
|
||||||
// and asynchrous handling for long-running operations.
|
// and asynchrous handling for long-running operations.
|
||||||
func newWebsocketClient(server *rpcServer, conn *websocket.Conn,
|
func newWebsocketClient(server *rpcServer, conn *websocket.Conn,
|
||||||
remoteAddr string, authenticated bool, isAdmin bool) *wsClient {
|
remoteAddr string, authenticated bool, isAdmin bool) (*wsClient, error) {
|
||||||
|
|
||||||
return &wsClient{
|
sessionID, err := wire.RandomUint64()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &wsClient{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
addr: remoteAddr,
|
addr: remoteAddr,
|
||||||
authenticated: authenticated,
|
authenticated: authenticated,
|
||||||
isAdmin: isAdmin,
|
isAdmin: isAdmin,
|
||||||
|
sessionID: sessionID,
|
||||||
server: server,
|
server: server,
|
||||||
addrRequests: make(map[string]struct{}),
|
addrRequests: make(map[string]struct{}),
|
||||||
spentRequests: make(map[wire.OutPoint]struct{}),
|
spentRequests: make(map[wire.OutPoint]struct{}),
|
||||||
|
@ -1398,6 +1415,7 @@ func newWebsocketClient(server *rpcServer, conn *websocket.Conn,
|
||||||
sendChan: make(chan wsResponse, websocketSendBufferSize),
|
sendChan: make(chan wsResponse, websocketSendBufferSize),
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleWebsocketHelp implements the help command for websocket connections.
|
// handleWebsocketHelp implements the help command for websocket connections.
|
||||||
|
@ -1454,6 +1472,12 @@ func handleNotifyBlocks(wsc *wsClient, icmd interface{}) (interface{}, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleSession implements the session command extension for websocket
|
||||||
|
// connections.
|
||||||
|
func handleSession(wsc *wsClient, icmd interface{}) (interface{}, error) {
|
||||||
|
return &btcjson.SessionResult{SessionID: wsc.sessionID}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// handleStopNotifyBlocks implements the stopnotifyblocks command extension for
|
// handleStopNotifyBlocks implements the stopnotifyblocks command extension for
|
||||||
// websocket connections.
|
// websocket connections.
|
||||||
func handleStopNotifyBlocks(wsc *wsClient, icmd interface{}) (interface{}, error) {
|
func handleStopNotifyBlocks(wsc *wsClient, icmd interface{}) (interface{}, error) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue