本文整理汇总了Golang中github.com/conformal/btcwire.NewMsgInv函数的典型用法代码示例。如果您正苦于以下问题:Golang NewMsgInv函数的具体用法?Golang NewMsgInv怎么用?Golang NewMsgInv使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了NewMsgInv函数的11个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: outHandler
// outHandler handles all outgoing messages for the peer. It must be run as a
// goroutine. It uses a buffered channel to serialize output messages while
// allowing the sender to continue running asynchronously.
func (p *peer) outHandler() {
trickleTicker := time.NewTicker(time.Second * 10)
out:
for {
select {
case msg := <-p.outputQueue:
p.writeMessage(msg)
case iv := <-p.outputInvChan:
p.invSendQueue.PushBack(iv)
case <-trickleTicker.C:
// Don't send anything if we're disconnecting or there
// is no queued inventory.
if atomic.LoadInt32(&p.disconnect) != 0 ||
p.invSendQueue.Len() == 0 {
continue
}
// Create and send as many inv messages as needed to
// drain the inventory send queue.
invMsg := btcwire.NewMsgInv()
for e := p.invSendQueue.Front(); e != nil; e = p.invSendQueue.Front() {
iv := p.invSendQueue.Remove(e).(*btcwire.InvVect)
// Don't send inventory that became known after
// the initial check.
if p.isKnownInventory(iv) {
continue
}
invMsg.AddInvVect(iv)
if len(invMsg.InvList) >= maxInvTrickleSize {
p.writeMessage(invMsg)
invMsg = btcwire.NewMsgInv()
}
// Add the inventory that is being relayed to
// the known inventory for the peer.
p.addKnownInventory(iv)
}
if len(invMsg.InvList) > 0 {
p.writeMessage(invMsg)
}
case <-p.quit:
break out
}
}
log.Tracef("[PEER] Peer output handler done for %s", p.addr)
}
示例2: TestInv
// TestInv tests the MsgInv API.
func TestInv(t *testing.T) {
pver := btcwire.ProtocolVersion
// Ensure the command is expected value.
wantCmd := "inv"
msg := btcwire.NewMsgInv()
if cmd := msg.Command(); cmd != wantCmd {
t.Errorf("NewMsgInv: wrong command - got %v want %v",
cmd, wantCmd)
}
// Ensure max payload is expected value for latest protocol version.
// Num inventory vectors (varInt) + max allowed inventory vectors.
wantPayload := uint32(1800009)
maxPayload := msg.MaxPayloadLength(pver)
if maxPayload != wantPayload {
t.Errorf("MaxPayloadLength: wrong max payload length for "+
"protocol version %d - got %v, want %v", pver,
maxPayload, wantPayload)
}
// Ensure inventory vectors are added properly.
hash := btcwire.ShaHash{}
iv := btcwire.NewInvVect(btcwire.InvTypeBlock, &hash)
err := msg.AddInvVect(iv)
if err != nil {
t.Errorf("AddInvVect: %v", err)
}
if msg.InvList[0] != iv {
t.Errorf("AddInvVect: wrong invvect added - got %v, want %v",
spew.Sprint(msg.InvList[0]), spew.Sprint(iv))
}
// Ensure adding more than the max allowed inventory vectors per
// message returns an error.
for i := 0; i < btcwire.MaxInvPerMsg; i++ {
err = msg.AddInvVect(iv)
}
if err == nil {
t.Errorf("AddInvVect: expected error on too many inventory " +
"vectors not received")
}
// Ensure creating the message with a size hint larger than the max
// works as expected.
msg = btcwire.NewMsgInvSizeHint(btcwire.MaxInvPerMsg + 1)
wantCap := btcwire.MaxInvPerMsg
if cap(msg.InvList) != wantCap {
t.Errorf("NewMsgInvSizeHint: wrong cap for size hint - "+
"got %v, want %v", cap(msg.InvList), wantCap)
}
return
}
示例3: pushBlockMsg
// 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 (p *peer) pushBlockMsg(sha *btcwire.ShaHash, doneChan chan bool) error {
// What should this function do about the rate limiting the
// number of blocks queued for this peer?
// Current thought is have a counting mutex in the peer
// such that if > N Tx/Block requests are currently in
// the tx queue, wait until the mutex clears allowing more to be
// sent. This prevents 500 1+MB blocks from being loaded into
// memory and sit around until the output queue drains.
// Actually the outputQueue has a limit of 50 in its queue
// but still 50MB to 1.6GB(50 32MB blocks) just setting
// in memory waiting to be sent is pointless.
// I would recommend a getdata request limit of about 5
// outstanding objects.
// Should the tx complete api be a mutex or channel?
blk, err := p.server.db.FetchBlockBySha(sha)
if err != nil {
log.Tracef("PEER: Unable to fetch requested block sha %v: %v",
sha, err)
return err
}
// We only send the channel for this message if we aren't sending
// an inv straight after.
var dc chan bool
sendInv := p.continueHash != nil && p.continueHash.IsEqual(sha)
if !sendInv {
dc = doneChan
}
p.QueueMessage(blk.MsgBlock(), dc)
// When the peer requests the final block that was advertised in
// response to a getblocks message which requested more blocks than
// would fit into a single message, send it a new inventory message
// to trigger it to issue another getblocks message for the next
// batch of inventory.
if p.continueHash != nil && p.continueHash.IsEqual(sha) {
hash, _, err := p.server.db.NewestSha()
if err == nil {
invMsg := btcwire.NewMsgInv()
iv := btcwire.NewInvVect(btcwire.InvTypeBlock, hash)
invMsg.AddInvVect(iv)
p.QueueMessage(invMsg, doneChan)
p.continueHash = nil
} else if doneChan != nil {
// Avoid deadlock when caller waits on channel.
go func() {
doneChan <- false
}()
}
}
return nil
}
示例4: pushBlockMsg
// 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 (p *peer) pushBlockMsg(sha *btcwire.ShaHash, doneChan, waitChan chan bool) error {
blk, err := p.server.db.FetchBlockBySha(sha)
if err != nil {
peerLog.Tracef("Unable to fetch requested block sha %v: %v",
sha, err)
return err
}
// Once we have fetched data wait for any previous operation to finish.
if waitChan != nil {
<-waitChan
}
// We only send the channel for this message if we aren't sending
// an inv straight after.
var dc chan bool
sendInv := p.continueHash != nil && p.continueHash.IsEqual(sha)
if !sendInv {
dc = doneChan
}
p.QueueMessage(blk.MsgBlock(), dc)
// When the peer requests the final block that was advertised in
// response to a getblocks message which requested more blocks than
// would fit into a single message, send it a new inventory message
// to trigger it to issue another getblocks message for the next
// batch of inventory.
if p.continueHash != nil && p.continueHash.IsEqual(sha) {
hash, _, err := p.server.db.NewestSha()
if err == nil {
invMsg := btcwire.NewMsgInv()
iv := btcwire.NewInvVect(btcwire.InvTypeBlock, hash)
invMsg.AddInvVect(iv)
p.QueueMessage(invMsg, doneChan)
p.continueHash = nil
} else if doneChan != nil {
// Avoid deadlock when caller waits on channel.
go func() {
doneChan <- false
}()
}
}
return nil
}
示例5: handleMemPoolMsg
// handleMemPoolMsg is invoked when a peer receives a mempool bitcoin message.
// It creates and sends an inventory message with the contents of the memory
// pool up to the maximum inventory allowed per message.
func (p *peer) handleMemPoolMsg(msg *btcwire.MsgMemPool) {
// Generate inventory message with the available transactions in the
// transaction memory pool. Limit it to the max allowed inventory
// per message.
invMsg := btcwire.NewMsgInv()
hashes := p.server.txMemPool.TxShas()
for i, hash := range hashes {
iv := btcwire.NewInvVect(btcwire.InvTypeTx, hash)
invMsg.AddInvVect(iv)
if i+1 >= btcwire.MaxInvPerMsg {
break
}
}
// Send the inventory message if there is anything to send.
if len(invMsg.InvList) > 0 {
p.QueueMessage(invMsg, nil)
}
}
示例6: TestInvWire
// TestInvWire tests the MsgInv wire encode and decode for various numbers
// of inventory vectors and protocol versions.
func TestInvWire(t *testing.T) {
// Block 203707 hash.
hashStr := "3264bc2ac36a60840790ba1d475d01367e7c723da941069e9dc"
blockHash, err := btcwire.NewShaHashFromStr(hashStr)
if err != nil {
t.Errorf("NewShaHashFromStr: %v", err)
}
// Transation 1 of Block 203707 hash.
hashStr = "d28a3dc7392bf00a9855ee93dd9a81eff82a2c4fe57fbd42cfe71b487accfaf0"
txHash, err := btcwire.NewShaHashFromStr(hashStr)
if err != nil {
t.Errorf("NewShaHashFromStr: %v", err)
}
iv := btcwire.NewInvVect(btcwire.InvVect_Block, blockHash)
iv2 := btcwire.NewInvVect(btcwire.InvVect_Tx, txHash)
// Empty inv message.
NoInv := btcwire.NewMsgInv()
NoInvEncoded := []byte{
0x00, // Varint for number of inventory vectors
}
// Inv message with multiple inventory vectors.
MultiInv := btcwire.NewMsgInv()
MultiInv.AddInvVect(iv)
MultiInv.AddInvVect(iv2)
MultiInvEncoded := []byte{
0x02, // Varint for number of inv vectors
0x02, 0x00, 0x00, 0x00, // InvVect_Block
0xdc, 0xe9, 0x69, 0x10, 0x94, 0xda, 0x23, 0xc7,
0xe7, 0x67, 0x13, 0xd0, 0x75, 0xd4, 0xa1, 0x0b,
0x79, 0x40, 0x08, 0xa6, 0x36, 0xac, 0xc2, 0x4b,
0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 203707 hash
0x01, 0x00, 0x00, 0x00, // InvVect_Tx
0xf0, 0xfa, 0xcc, 0x7a, 0x48, 0x1b, 0xe7, 0xcf,
0x42, 0xbd, 0x7f, 0xe5, 0x4f, 0x2c, 0x2a, 0xf8,
0xef, 0x81, 0x9a, 0xdd, 0x93, 0xee, 0x55, 0x98,
0x0a, 0xf0, 0x2b, 0x39, 0xc7, 0x3d, 0x8a, 0xd2, // Tx 1 of block 203707 hash
}
tests := []struct {
in *btcwire.MsgInv // Message to encode
out *btcwire.MsgInv // Expected decoded message
buf []byte // Wire encoding
pver uint32 // Protocol version for wire encoding
}{
// Latest protocol version with no inv vectors.
{
NoInv,
NoInv,
NoInvEncoded,
btcwire.ProtocolVersion,
},
// Latest protocol version with multiple inv vectors.
{
MultiInv,
MultiInv,
MultiInvEncoded,
btcwire.ProtocolVersion,
},
// Protocol version BIP0035Version no inv vectors.
{
NoInv,
NoInv,
NoInvEncoded,
btcwire.BIP0035Version,
},
// Protocol version BIP0035Version with multiple inv vectors.
{
MultiInv,
MultiInv,
MultiInvEncoded,
btcwire.BIP0035Version,
},
// Protocol version BIP0031Version no inv vectors.
{
NoInv,
NoInv,
NoInvEncoded,
btcwire.BIP0031Version,
},
// Protocol version BIP0031Version with multiple inv vectors.
{
MultiInv,
MultiInv,
MultiInvEncoded,
btcwire.BIP0031Version,
},
// Protocol version NetAddressTimeVersion no inv vectors.
{
//.........这里部分代码省略.........
示例7: handleGetBlocksMsg
// handleGetBlocksMsg is invoked when a peer receives a getdata bitcoin message.
func (p *peer) handleGetBlocksMsg(msg *btcwire.MsgGetBlocks) {
// Return all block hashes to the latest one (up to max per message) if
// no stop hash was specified.
// Attempt to find the ending index of the stop hash if specified.
endIdx := btcdb.AllShas
if !msg.HashStop.IsEqual(&zeroHash) {
block, err := p.server.db.FetchBlockBySha(&msg.HashStop)
if err == nil {
endIdx = block.Height() + 1
}
}
// Find the most recent known block based on the block locator.
// Use the block after the genesis block if no other blocks in the
// provided locator are known. This does mean the client will start
// over with the genesis block if unknown block locators are provided.
// This mirrors the behavior in the reference implementation.
startIdx := int64(1)
for _, hash := range msg.BlockLocatorHashes {
block, err := p.server.db.FetchBlockBySha(hash)
if err == nil {
// Start with the next hash since we know this one.
startIdx = block.Height() + 1
break
}
}
// Don't attempt to fetch more than we can put into a single message.
autoContinue := false
if endIdx-startIdx > btcwire.MaxBlocksPerMsg {
endIdx = startIdx + btcwire.MaxBlocksPerMsg
autoContinue = true
}
// Generate inventory message.
//
// The FetchBlockBySha call is limited to a maximum number of hashes
// per invocation. Since the maximum number of inventory per message
// might be larger, call it multiple times with the appropriate indices
// as needed.
invMsg := btcwire.NewMsgInv()
for start := startIdx; start < endIdx; {
// Fetch the inventory from the block database.
hashList, err := p.server.db.FetchHeightRange(start, endIdx)
if err != nil {
log.Warnf("PEER: Block lookup failed: %v", err)
return
}
// The database did not return any further hashes. Break out of
// the loop now.
if len(hashList) == 0 {
break
}
// Add block inventory to the message.
for _, hash := range hashList {
hashCopy := hash
iv := btcwire.NewInvVect(btcwire.InvTypeBlock, &hashCopy)
invMsg.AddInvVect(iv)
}
start += int64(len(hashList))
}
// Send the inventory message if there is anything to send.
if len(invMsg.InvList) > 0 {
invListLen := len(invMsg.InvList)
if autoContinue && invListLen == btcwire.MaxBlocksPerMsg {
// Intentionally use a copy of the final hash so there
// is not a reference into the inventory slice which
// would prevent the entire slice from being eligible
// for GC as soon as it's sent.
continueHash := invMsg.InvList[invListLen-1].Hash
p.continueHash = &continueHash
}
p.QueueMessage(invMsg, nil)
}
}
示例8: outHandler
// outHandler handles all outgoing messages for the peer. It must be run as a
// goroutine. It uses a buffered channel to serialize output messages while
// allowing the sender to continue running asynchronously.
func (p *peer) outHandler() {
trickleTicker := time.NewTicker(time.Second * 10)
pingTimer := time.AfterFunc(pingTimeoutMinutes*time.Minute, func() {
nonce, err := btcwire.RandomUint64()
if err != nil {
log.Errorf("Not sending ping on timeout to %s: %v",
p, err)
return
}
p.QueueMessage(btcwire.NewMsgPing(nonce), nil)
})
out:
for {
select {
case msg := <-p.outputQueue:
// If the message is one we should get a reply for
// then reset the timer, we only want to send pings
// when otherwise we would not recieve a reply from
// the peer. We specifically do not count block or inv
// messages here since they are not sure of a reply if
// the inv is of no interest explicitly solicited invs
// should elicit a reply but we don't track them
// specially.
reset := true
switch msg.msg.(type) {
case *btcwire.MsgVersion:
// should get an ack
case *btcwire.MsgGetAddr:
// should get addresses
case *btcwire.MsgPing:
// expects pong
case *btcwire.MsgMemPool:
// Should return an inv.
case *btcwire.MsgGetData:
// Should get us block, tx, or not found.
case *btcwire.MsgGetHeaders:
// Should get us headers back.
default:
// Not one of the above, no sure reply.
// We want to ping if nothing else
// interesting happens.
reset = false
}
if reset {
pingTimer.Reset(pingTimeoutMinutes * time.Minute)
}
p.writeMessage(msg.msg)
p.lastSend = time.Now()
if msg.doneChan != nil {
msg.doneChan <- true
}
case iv := <-p.outputInvChan:
// No handshake? They'll find out soon enough.
if p.versionKnown {
p.invSendQueue.PushBack(iv)
}
case <-trickleTicker.C:
// Don't send anything if we're disconnecting or there
// is no queued inventory.
if atomic.LoadInt32(&p.disconnect) != 0 ||
p.invSendQueue.Len() == 0 ||
!p.versionKnown {
continue
}
// Create and send as many inv messages as needed to
// drain the inventory send queue.
invMsg := btcwire.NewMsgInv()
for e := p.invSendQueue.Front(); e != nil; e = p.invSendQueue.Front() {
iv := p.invSendQueue.Remove(e).(*btcwire.InvVect)
// Don't send inventory that became known after
// the initial check.
if p.isKnownInventory(iv) {
continue
}
invMsg.AddInvVect(iv)
if len(invMsg.InvList) >= maxInvTrickleSize {
p.writeMessage(invMsg)
invMsg = btcwire.NewMsgInv()
}
// Add the inventory that is being relayed to
// the known inventory for the peer.
p.addKnownInventory(iv)
}
if len(invMsg.InvList) > 0 {
p.writeMessage(invMsg)
}
case <-p.quit:
break out
}
//.........这里部分代码省略.........
示例9: TestInvWireErrors
// TestInvWireErrors performs negative tests against wire encode and decode
// of MsgInv to confirm error paths work correctly.
func TestInvWireErrors(t *testing.T) {
pver := btcwire.ProtocolVersion
btcwireErr := &btcwire.MessageError{}
// Block 203707 hash.
hashStr := "3264bc2ac36a60840790ba1d475d01367e7c723da941069e9dc"
blockHash, err := btcwire.NewShaHashFromStr(hashStr)
if err != nil {
t.Errorf("NewShaHashFromStr: %v", err)
}
iv := btcwire.NewInvVect(btcwire.InvVect_Block, blockHash)
// Base inv message used to induce errors.
baseInv := btcwire.NewMsgInv()
baseInv.AddInvVect(iv)
baseInvEncoded := []byte{
0x02, // Varint for number of inv vectors
0x02, 0x00, 0x00, 0x00, // InvVect_Block
0xdc, 0xe9, 0x69, 0x10, 0x94, 0xda, 0x23, 0xc7,
0xe7, 0x67, 0x13, 0xd0, 0x75, 0xd4, 0xa1, 0x0b,
0x79, 0x40, 0x08, 0xa6, 0x36, 0xac, 0xc2, 0x4b,
0x26, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Block 203707 hash
}
// Inv message that forces an error by having more than the max allowed
// inv vectors.
maxInv := btcwire.NewMsgInv()
for i := 0; i < btcwire.MaxInvPerMsg; i++ {
maxInv.AddInvVect(iv)
}
maxInv.InvList = append(maxInv.InvList, iv)
maxInvEncoded := []byte{
0xfd, 0x51, 0xc3, // Varint for number of inv vectors (50001)
}
tests := []struct {
in *btcwire.MsgInv // Value to encode
buf []byte // Wire encoding
pver uint32 // Protocol version for wire encoding
max int // Max size of fixed buffer to induce errors
writeErr error // Expected write error
readErr error // Expected read error
}{
// Latest protocol version with intentional read/write errors.
// Force error in inventory vector count
{baseInv, baseInvEncoded, pver, 0, io.ErrShortWrite, io.EOF},
// Force error in inventory list.
{baseInv, baseInvEncoded, pver, 1, io.ErrShortWrite, io.EOF},
// Force error with greater than max inventory vectors.
{maxInv, maxInvEncoded, pver, 3, btcwireErr, btcwireErr},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
// Encode to wire format.
w := newFixedWriter(test.max)
err := test.in.BtcEncode(w, test.pver)
if reflect.TypeOf(err) != reflect.TypeOf(test.writeErr) {
t.Errorf("BtcEncode #%d wrong error got: %v, want: %v",
i, err, test.writeErr)
continue
}
// For errors which are not of type btcwire.MessageError, check
// them for equality.
if _, ok := err.(*btcwire.MessageError); !ok {
if err != test.writeErr {
t.Errorf("BtcEncode #%d wrong error got: %v, "+
"want: %v", i, err, test.writeErr)
continue
}
}
// Decode from wire format.
var msg btcwire.MsgInv
r := newFixedReader(test.max, test.buf)
err = msg.BtcDecode(r, test.pver)
if reflect.TypeOf(err) != reflect.TypeOf(test.readErr) {
t.Errorf("BtcDecode #%d wrong error got: %v, want: %v",
i, err, test.readErr)
continue
}
// For errors which are not of type btcwire.MessageError, check
// them for equality.
if _, ok := err.(*btcwire.MessageError); !ok {
if err != test.readErr {
t.Errorf("BtcDecode #%d wrong error got: %v, "+
"want: %v", i, err, test.readErr)
continue
}
}
}
}
示例10: TestMessage
// TestMessage tests the Read/WriteMessage API.
func TestMessage(t *testing.T) {
pver := btcwire.ProtocolVersion
// Create the various types of messages to test.
// MsgVersion.
addrYou := &net.TCPAddr{IP: net.ParseIP("192.168.0.1"), Port: 8333}
you, err := btcwire.NewNetAddress(addrYou, btcwire.SFNodeNetwork)
if err != nil {
t.Errorf("NewNetAddress: %v", err)
}
you.Timestamp = time.Time{} // Version message has zero value timestamp.
addrMe := &net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: 8333}
me, err := btcwire.NewNetAddress(addrMe, btcwire.SFNodeNetwork)
if err != nil {
t.Errorf("NewNetAddress: %v", err)
}
me.Timestamp = time.Time{} // Version message has zero value timestamp.
msgVersion := btcwire.NewMsgVersion(me, you, 123123, "/test:0.0.1/", 0)
msgVerack := btcwire.NewMsgVerAck()
msgGetAddr := btcwire.NewMsgGetAddr()
msgAddr := btcwire.NewMsgAddr()
msgGetBlocks := btcwire.NewMsgGetBlocks(&btcwire.ShaHash{})
msgBlock := &blockOne
msgInv := btcwire.NewMsgInv()
msgGetData := btcwire.NewMsgGetData()
msgNotFound := btcwire.NewMsgNotFound()
msgTx := btcwire.NewMsgTx()
msgPing := btcwire.NewMsgPing(123123)
msgPong := btcwire.NewMsgPong(123123)
msgGetHeaders := btcwire.NewMsgGetHeaders()
msgHeaders := btcwire.NewMsgHeaders()
msgAlert := btcwire.NewMsgAlert("payload", "signature")
msgMemPool := btcwire.NewMsgMemPool()
tests := []struct {
in btcwire.Message // Value to encode
out btcwire.Message // Expected decoded value
pver uint32 // Protocol version for wire encoding
btcnet btcwire.BitcoinNet // Network to use for wire encoding
}{
{msgVersion, msgVersion, pver, btcwire.MainNet},
{msgVerack, msgVerack, pver, btcwire.MainNet},
{msgGetAddr, msgGetAddr, pver, btcwire.MainNet},
{msgAddr, msgAddr, pver, btcwire.MainNet},
{msgGetBlocks, msgGetBlocks, pver, btcwire.MainNet},
{msgBlock, msgBlock, pver, btcwire.MainNet},
{msgInv, msgInv, pver, btcwire.MainNet},
{msgGetData, msgGetData, pver, btcwire.MainNet},
{msgNotFound, msgNotFound, pver, btcwire.MainNet},
{msgTx, msgTx, pver, btcwire.MainNet},
{msgPing, msgPing, pver, btcwire.MainNet},
{msgPong, msgPong, pver, btcwire.MainNet},
{msgGetHeaders, msgGetHeaders, pver, btcwire.MainNet},
{msgHeaders, msgHeaders, pver, btcwire.MainNet},
{msgAlert, msgAlert, pver, btcwire.MainNet},
{msgMemPool, msgMemPool, pver, btcwire.MainNet},
}
t.Logf("Running %d tests", len(tests))
for i, test := range tests {
// Encode to wire format.
var buf bytes.Buffer
err := btcwire.WriteMessage(&buf, test.in, test.pver, test.btcnet)
if err != nil {
t.Errorf("WriteMessage #%d error %v", i, err)
continue
}
// Decode from wire format.
rbuf := bytes.NewBuffer(buf.Bytes())
msg, _, err := btcwire.ReadMessage(rbuf, test.pver, test.btcnet)
if err != nil {
t.Errorf("ReadMessage #%d error %v, msg %v", i, err,
spew.Sdump(msg))
continue
}
if !reflect.DeepEqual(msg, test.out) {
t.Errorf("ReadMessage #%d\n got: %v want: %v", i,
spew.Sdump(msg), spew.Sdump(test.out))
continue
}
}
}
示例11: queueHandler
// queueHandler handles the queueing of outgoing data for the peer. This runs
// as a muxer for various sources of input so we can ensure that blockmanager
// and the server goroutine both will not block on us sending a message.
// We then pass the data on to outHandler to be actually written.
func (p *peer) queueHandler() {
pendingMsgs := list.New()
invSendQueue := list.New()
trickleTicker := time.NewTicker(time.Second * 10)
// We keep the waiting flag so that we know if we have a message queued
// to the outHandler or not. We could use the presence of a head of
// the list for this but then we have rather racy concerns about whether
// it has gotten it at cleanup time - and thus who sends on the
// message's done channel. To avoid such confusion we keep a different
// flag and pendingMsgs only contains messages that we have not yet
// passed to outHandler.
waiting := false
// To avoid duplication below.
queuePacket := func(msg outMsg, list *list.List, waiting bool) bool {
if !waiting {
peerLog.Tracef("%s: sending to outHandler", p)
p.sendQueue <- msg
peerLog.Tracef("%s: sent to outHandler", p)
} else {
list.PushBack(msg)
}
// we are always waiting now.
return true
}
out:
for {
select {
case msg := <-p.outputQueue:
waiting = queuePacket(msg, pendingMsgs, waiting)
// This channel is notified when a message has been sent across
// the network socket.
case <-p.sendDoneQueue:
peerLog.Tracef("%s: acked by outhandler", p)
// No longer waiting if there are no more messages
// in the pending messages queue.
next := pendingMsgs.Front()
if next == nil {
waiting = false
continue
}
// Notify the outHandler about the next item to
// asynchronously send.
val := pendingMsgs.Remove(next)
peerLog.Tracef("%s: sending to outHandler", p)
p.sendQueue <- val.(outMsg)
peerLog.Tracef("%s: sent to outHandler", p)
case iv := <-p.outputInvChan:
// No handshake? They'll find out soon enough.
if p.versionKnown {
invSendQueue.PushBack(iv)
}
case <-trickleTicker.C:
// Don't send anything if we're disconnecting or there
// is no queued inventory.
// version is known if send queue has any entries.
if atomic.LoadInt32(&p.disconnect) != 0 ||
invSendQueue.Len() == 0 {
continue
}
// Create and send as many inv messages as needed to
// drain the inventory send queue.
invMsg := btcwire.NewMsgInv()
for e := invSendQueue.Front(); e != nil; e = invSendQueue.Front() {
iv := invSendQueue.Remove(e).(*btcwire.InvVect)
// Don't send inventory that became known after
// the initial check.
if p.isKnownInventory(iv) {
continue
}
invMsg.AddInvVect(iv)
if len(invMsg.InvList) >= maxInvTrickleSize {
waiting = queuePacket(
outMsg{msg: invMsg},
pendingMsgs, waiting)
invMsg = btcwire.NewMsgInv()
}
// Add the inventory that is being relayed to
// the known inventory for the peer.
p.AddKnownInventory(iv)
}
if len(invMsg.InvList) > 0 {
waiting = queuePacket(outMsg{msg: invMsg},
pendingMsgs, waiting)
}
//.........这里部分代码省略.........