Send btcdconnected ntfns to connected clients.

If a websocket client was already connected and the wallet and/or
chain server is loaded into the rpc server (enabling the handlers
specific to those components), the btcdconnected notifications were
not being sent, and this could break clients that expected the
notification.  I'm not happy with this change, but since this is how
notifications are currently done (unsolicited), and to not break
compatibility yet, I'm adding these back in for now.

Eventually, this notification will require explicit registration
before it is received by a client.  See issue #84.

Closes #115.
This commit is contained in:
Josh Rickmar 2014-07-28 09:33:00 -05:00
parent cd1aebb68e
commit 8771664af7
3 changed files with 24 additions and 3 deletions

View file

@ -54,9 +54,7 @@ func NewClient(net *btcnet.Params, connect, user, pass string, certs []byte) (*C
}
initializedClient := make(chan struct{})
ntfnCallbacks := btcrpcclient.NotificationHandlers{
OnClientConnected: func() {
log.Info("Established connection to btcd")
},
OnClientConnected: client.onClientConnect,
OnBlockConnected: client.onBlockConnected,
OnBlockDisconnected: client.onBlockDisconnected,
OnRecvTx: client.onRecvTx,
@ -146,6 +144,7 @@ func (c *Client) BlockStamp() (*keystore.BlockStamp, error) {
// btcrpcclient callbacks, which isn't very Go-like and doesn't allow
// blocking client calls.
type (
ClientConnected struct{}
BlockConnected keystore.BlockStamp
BlockDisconnected keystore.BlockStamp
RecvTx struct {
@ -187,6 +186,11 @@ func parseBlock(block *btcws.BlockDetails) (blk *txstore.Block, idx int, err err
return blk, block.Index, nil
}
func (c *Client) onClientConnect() {
log.Info("Established websocket RPC connection to btcd")
c.enqueueNotification <- ClientConnected{}
}
func (c *Client) onBlockConnected(hash *btcwire.ShaHash, height int32) {
c.enqueueNotification <- BlockConnected{Hash: hash, Height: height}
}

View file

@ -28,6 +28,8 @@ func (w *Wallet) handleChainNotifications() {
for n := range w.chainSvr.Notifications() {
var err error
switch n := n.(type) {
case chain.ClientConnected:
w.notifyChainServerConnected(true)
case chain.BlockConnected:
w.connectBlock(keystore.BlockStamp(n))
case chain.BlockDisconnected:

View file

@ -514,6 +514,7 @@ func (s *rpcServer) SetWallet(wallet *Wallet) {
s.wallet = wallet
s.registerWalletNtfns <- struct{}{}
chainSvrConnected := false
if s.chainSvr != nil {
// If the chain server rpc client is also set, there's no reason
// to keep the mutex around. Make the locker simply execute
@ -523,7 +524,15 @@ func (s *rpcServer) SetWallet(wallet *Wallet) {
// With both the wallet and chain server set, all handlers are
// ok to run.
s.handlerLookup = lookupAnyHandler
chainSvrConnected = !s.chainSvr.Disconnected()
}
// Make sure already connected websocket clients get a notification
// if the chain RPC client connection is set and connected. This is
// run as a goroutine since it must aquire the handlerLock, which is
// locked here.
go s.notifyChainServerConnected(chainSvrConnected)
}
// SetChainServer sets the chain server client component needed to run a fully
@ -546,6 +555,12 @@ func (s *rpcServer) SetChainServer(chainSvr *chain.Client) {
// ok to run.
s.handlerLookup = lookupAnyHandler
}
// Make sure already connected websocket clients get a notification
// if the chain RPC client connection is set and connected. This is
// run as a goroutine since it must aquire the handlerLock, which is
// locked here.
go s.notifyChainServerConnected(!chainSvr.Disconnected())
}
// HandlerClosure creates a closure function for handling requests of the given