Esempio n. 1
0
// The first thing to do after a connection is established is to exchange version.
// For kaiju it goes as follows:
// 1. Send out my version message, if outgoing == true
// 2. Expect the remote peer send it's version message
// 3. Once the message from remote peer is received, send verack
// 4. Send out my version message, if outgoing == false
// 5. Done, knet.Peer starts to work
func (p *Peer) versionHankshake() error {
	// Step 1
	if p.outgoing {
		err := p.sendVersionMsg()
		if err != nil {
			return err
		}
	}
	// Step 2
	msg, err := btcmsg.ReadMsg(p.conn)
	if err != nil {
		return err
	} else {
		if ver, ok := msg.(*btcmsg.Message_version); ok {
			// TODO: more check
			p.info = ver.Addr_from
		} else {
			return errors.New("Wrong message type when doing versionHankshake")
		}
	}
	// Step 3
	vamsg := btcmsg.NewVerAckMsg()
	err = btcmsg.WriteMsg(p.conn, vamsg)
	if err != nil {
		return err
	}
	// Step 4
	if !p.outgoing {
		err := p.sendVersionMsg()
		if err != nil {
			return err
		}
	}
	return nil
}
Esempio n. 2
0
func (p *Peer) loopMain() {
	// This "running" is used to fix a bug about "break",
	// so if you break in "select", you cannot get out of "for".
	running := true
	for running {
		select {
		case m := <-p.sendChan:
			ch := make(chan error, 1)
			go func() { ch <- btcmsg.WriteMsg(p.conn, m.msg) }()
			select {
			case err := <-ch:
				if m.errChan != nil {
					m.errChan <- err
				}
				if err != nil {
					running = false
				}
			case <-time.After(m.timeout):
				if m.errChan != nil {
					m.errChan <- errors.New("Peer send message timeout.")
				}
				if m.timeout >= defaultSendMsgTimeout {
					running = false
				}
			case <-p.done:
				running = false
			}
		case <-p.keepAliveTimer.C:
			ping := btcmsg.NewPingMsg().(*btcmsg.Message_ping)
			ping.Nonce = uint64(p.handle)
			p.sendMsg(ping, 0, nil)
		case <-p.kickTimer.C:
			p.kick()
		case <-p.done:
			running = false
		}
	}
	p.cleanUp()
}
Esempio n. 3
0
func (p *Peer) sendVersionMsg() error {
	vmsg := btcmsg.NewLocalVersionMsg(p.info)
	return btcmsg.WriteMsg(p.conn, vmsg)
}