From c1861bc8fa03d0b1a93de177887e99faa74619a6 Mon Sep 17 00:00:00 2001 From: David Hill Date: Wed, 6 Apr 2016 14:50:27 -0400 Subject: [PATCH] peer: declare QueueMessage()'s doneChan as send only. This ensures the channel passed to QueueMessage is writable and that QueueMessage will not read from the channel (write-only). This change is merely a safety change. If a user of the API passes a read-only channel to QueueMessage, it will now be caught at compile time instead of panicking during runtime. Also update internal functions. --- peer/peer.go | 4 ++-- server.go | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/peer/peer.go b/peer/peer.go index e914e0b5..968f0fb3 100644 --- a/peer/peer.go +++ b/peer/peer.go @@ -298,7 +298,7 @@ func newNetAddress(addr net.Addr, services wire.ServiceFlag) (*wire.NetAddress, // shutdown) type outMsg struct { msg wire.Message - doneChan chan struct{} + doneChan chan<- struct{} } // stallControlCmd represents the command of a stall control message. @@ -1897,7 +1897,7 @@ cleanup: // QueueMessage adds the passed bitcoin message to the peer send queue. // // This function is safe for concurrent access. -func (p *Peer) QueueMessage(msg wire.Message, doneChan chan struct{}) { +func (p *Peer) QueueMessage(msg wire.Message, doneChan chan<- struct{}) { // Avoid risk of deadlock if goroutine already exited. The goroutine // we will be sending to hangs around until it knows for a fact that // it is marked as disconnected and *then* it drains the channels. diff --git a/server.go b/server.go index 0156ff59..611b8cf7 100644 --- a/server.go +++ b/server.go @@ -921,7 +921,7 @@ func (s *server) RemoveRebroadcastInventory(iv *wire.InvVect) { // pushTxMsg sends a tx message for the provided transaction hash to the // connected peer. An error is returned if the transaction hash is not known. -func (s *server) pushTxMsg(sp *serverPeer, sha *wire.ShaHash, doneChan, waitChan chan struct{}) error { +func (s *server) pushTxMsg(sp *serverPeer, sha *wire.ShaHash, doneChan chan<- struct{}, waitChan <-chan struct{}) error { // Attempt to fetch the requested transaction from the pool. A // call could be made to check for existence first, but simply trying // to fetch a missing transaction results in the same behavior. @@ -948,7 +948,7 @@ func (s *server) pushTxMsg(sp *serverPeer, sha *wire.ShaHash, doneChan, waitChan // pushBlockMsg sends a block message for the provided block hash to the // connected peer. An error is returned if the block hash is not known. -func (s *server) pushBlockMsg(sp *serverPeer, sha *wire.ShaHash, doneChan, waitChan chan struct{}) error { +func (s *server) pushBlockMsg(sp *serverPeer, sha *wire.ShaHash, doneChan chan<- struct{}, waitChan <-chan struct{}) error { blk, err := s.db.FetchBlockBySha(sha) if err != nil { peerLog.Tracef("Unable to fetch requested block sha %v: %v", @@ -967,7 +967,7 @@ func (s *server) pushBlockMsg(sp *serverPeer, sha *wire.ShaHash, doneChan, waitC // We only send the channel for this message if we aren't sending // an inv straight after. - var dc chan struct{} + var dc chan<- struct{} continueHash := sp.continueHash sendInv := continueHash != nil && continueHash.IsEqual(sha) if !sendInv { @@ -999,7 +999,7 @@ func (s *server) pushBlockMsg(sp *serverPeer, sha *wire.ShaHash, doneChan, waitC // the connected peer. Since a merkle block requires the peer to have a filter // loaded, this call will simply be ignored if there is no filter loaded. An // error is returned if the block hash is not known. -func (s *server) pushMerkleBlockMsg(sp *serverPeer, sha *wire.ShaHash, doneChan, waitChan chan struct{}) error { +func (s *server) pushMerkleBlockMsg(sp *serverPeer, sha *wire.ShaHash, doneChan chan<- struct{}, waitChan <-chan struct{}) error { // Do not send a response if the peer doesn't have a filter loaded. if !sp.filter.IsLoaded() { if doneChan != nil { @@ -1030,7 +1030,7 @@ func (s *server) pushMerkleBlockMsg(sp *serverPeer, sha *wire.ShaHash, doneChan, // Send the merkleblock. Only send the done channel with this message // if no transactions will be sent afterwards. - var dc chan struct{} + var dc chan<- struct{} if len(matchedTxIndices) == 0 { dc = doneChan } @@ -1040,7 +1040,7 @@ func (s *server) pushMerkleBlockMsg(sp *serverPeer, sha *wire.ShaHash, doneChan, blkTransactions := blk.MsgBlock().Transactions for i, txIndex := range matchedTxIndices { // Only send the done channel on the final transaction. - var dc chan struct{} + var dc chan<- struct{} if i == len(matchedTxIndices)-1 { dc = doneChan }