|
|
|
@ -7,6 +7,7 @@ import ( |
|
|
|
|
"log" |
|
|
|
|
"net" |
|
|
|
|
"strconv" |
|
|
|
|
"strings" |
|
|
|
|
"sync/atomic" |
|
|
|
|
"time" |
|
|
|
|
) |
|
|
|
@ -16,6 +17,36 @@ const ( |
|
|
|
|
outputBufferSize = 50 |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// Peer capabillities
|
|
|
|
|
type Caps byte |
|
|
|
|
|
|
|
|
|
const ( |
|
|
|
|
CapDiscoveryTy = 0x01 |
|
|
|
|
CapTxTy = 0x02 |
|
|
|
|
CapChainTy = 0x04 |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
var capsToString = map[Caps]string{ |
|
|
|
|
CapDiscoveryTy: "Peer discovery", |
|
|
|
|
CapTxTy: "Transaction relaying", |
|
|
|
|
CapChainTy: "Block chain relaying", |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (c Caps) String() string { |
|
|
|
|
var caps []string |
|
|
|
|
if c&CapDiscoveryTy > 0 { |
|
|
|
|
caps = append(caps, capsToString[CapDiscoveryTy]) |
|
|
|
|
} |
|
|
|
|
if c&CapChainTy > 0 { |
|
|
|
|
caps = append(caps, capsToString[CapChainTy]) |
|
|
|
|
} |
|
|
|
|
if c&CapTxTy > 0 { |
|
|
|
|
caps = append(caps, capsToString[CapTxTy]) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return strings.Join(caps, " | ") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type Peer struct { |
|
|
|
|
// Ethereum interface
|
|
|
|
|
ethereum *Ethereum |
|
|
|
@ -45,6 +76,10 @@ type Peer struct { |
|
|
|
|
|
|
|
|
|
// Determines whether this is a seed peer
|
|
|
|
|
seed bool |
|
|
|
|
|
|
|
|
|
host []byte |
|
|
|
|
port uint16 |
|
|
|
|
caps Caps |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func NewPeer(conn net.Conn, ethereum *Ethereum, inbound bool) *Peer { |
|
|
|
@ -56,6 +91,7 @@ func NewPeer(conn net.Conn, ethereum *Ethereum, inbound bool) *Peer { |
|
|
|
|
inbound: inbound, |
|
|
|
|
disconnect: 0, |
|
|
|
|
connected: 1, |
|
|
|
|
port: 30303, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -223,7 +259,8 @@ out: |
|
|
|
|
peers := make([]string, data.Length()) |
|
|
|
|
// Parse each possible peer
|
|
|
|
|
for i := 0; i < data.Length(); i++ { |
|
|
|
|
peers[i] = data.Get(i).Get(0).AsString() + ":" + strconv.Itoa(int(data.Get(i).Get(1).AsUint())) |
|
|
|
|
peers[i] = unpackAddr(data.Get(i).Get(0).AsBytes(), data.Get(i).Get(1).AsUint()) |
|
|
|
|
log.Println(peers[i]) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Connect to the list of peers
|
|
|
|
@ -277,20 +314,52 @@ out: |
|
|
|
|
p.Stop() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func packAddr(address, port string) ([]byte, uint16) { |
|
|
|
|
addr := strings.Split(address, ".") |
|
|
|
|
a, _ := strconv.Atoi(addr[0]) |
|
|
|
|
b, _ := strconv.Atoi(addr[1]) |
|
|
|
|
c, _ := strconv.Atoi(addr[2]) |
|
|
|
|
d, _ := strconv.Atoi(addr[3]) |
|
|
|
|
host := []byte{byte(a), byte(b), byte(c), byte(d)} |
|
|
|
|
prt, _ := strconv.Atoi(port) |
|
|
|
|
|
|
|
|
|
return host, uint16(prt) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func unpackAddr(h []byte, p uint64) string { |
|
|
|
|
if len(h) != 4 { |
|
|
|
|
return "" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
a := strconv.Itoa(int(h[0])) |
|
|
|
|
b := strconv.Itoa(int(h[1])) |
|
|
|
|
c := strconv.Itoa(int(h[2])) |
|
|
|
|
d := strconv.Itoa(int(h[3])) |
|
|
|
|
host := strings.Join([]string{a, b, c, d}, ".") |
|
|
|
|
port := strconv.Itoa(int(p)) |
|
|
|
|
|
|
|
|
|
return net.JoinHostPort(host, port) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (p *Peer) Start(seed bool) { |
|
|
|
|
p.seed = seed |
|
|
|
|
|
|
|
|
|
peerHost, _, _ := net.SplitHostPort(p.conn.LocalAddr().String()) |
|
|
|
|
servHost, _, _ := net.SplitHostPort(p.conn.RemoteAddr().String()) |
|
|
|
|
peerHost, peerPort, _ := net.SplitHostPort(p.conn.LocalAddr().String()) |
|
|
|
|
servHost, servPort, _ := net.SplitHostPort(p.conn.RemoteAddr().String()) |
|
|
|
|
if peerHost == servHost { |
|
|
|
|
log.Println("Connected to self") |
|
|
|
|
|
|
|
|
|
p.Stop() |
|
|
|
|
//p.Stop()
|
|
|
|
|
|
|
|
|
|
return |
|
|
|
|
//return
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if p.inbound { |
|
|
|
|
p.host, p.port = packAddr(peerHost, peerPort) |
|
|
|
|
} else { |
|
|
|
|
p.host, p.port = packAddr(servHost, servPort) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//if !p.inbound {
|
|
|
|
|
err := p.pushHandshake() |
|
|
|
|
if err != nil { |
|
|
|
|
log.Printf("Peer can't send outbound version ack", err) |
|
|
|
@ -299,7 +368,6 @@ func (p *Peer) Start(seed bool) { |
|
|
|
|
|
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
// Run the outbound handler in a new goroutine
|
|
|
|
|
go p.HandleOutbound() |
|
|
|
@ -324,7 +392,7 @@ func (p *Peer) Stop() { |
|
|
|
|
|
|
|
|
|
func (p *Peer) pushHandshake() error { |
|
|
|
|
msg := ethwire.NewMessage(ethwire.MsgHandshakeTy, []interface{}{ |
|
|
|
|
uint32(0), uint32(0), "/Ethereum(G) v0.0.1/", |
|
|
|
|
uint32(0), uint32(0), "/Ethereum(G) v0.0.1/", CapChainTy | CapTxTy | CapDiscoveryTy, p.port, |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
p.QueueMessage(msg) |
|
|
|
@ -354,41 +422,27 @@ func (p *Peer) handleHandshake(msg *ethwire.Msg) { |
|
|
|
|
var istr string |
|
|
|
|
// If this is an inbound connection send an ack back
|
|
|
|
|
if p.inbound { |
|
|
|
|
/* |
|
|
|
|
err := p.pushHandshake() |
|
|
|
|
if err != nil { |
|
|
|
|
log.Println("Peer can't send ack back") |
|
|
|
|
if port := c.Get(4).AsUint(); port != 0 { |
|
|
|
|
p.port = uint16(port) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
p.Stop() |
|
|
|
|
} |
|
|
|
|
*/ |
|
|
|
|
istr = "inbound" |
|
|
|
|
} else { |
|
|
|
|
//msg := ethwire.NewMessage(ethwire.MsgGetChainTy, []interface{}{p.ethereum.BlockManager.BlockChain().CurrentBlock.Hash(), uint64(100)})
|
|
|
|
|
//p.QueueMessage(msg)
|
|
|
|
|
msg := ethwire.NewMessage(ethwire.MsgGetChainTy, []interface{}{p.ethereum.BlockManager.BlockChain().CurrentBlock.Hash(), uint64(100)}) |
|
|
|
|
p.QueueMessage(msg) |
|
|
|
|
|
|
|
|
|
istr = "outbound" |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
log.Printf("peer connect (%s) %v %s\n", istr, p.conn.RemoteAddr(), c.Get(2).AsString()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (p *Peer) RlpData() []interface{} { |
|
|
|
|
host, _, err := net.SplitHostPort(p.conn.RemoteAddr().String()) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* FIXME |
|
|
|
|
port, err := strconv.Atoi(prt) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil |
|
|
|
|
if caps := Caps(c.Get(3).AsByte()); caps != 0 { |
|
|
|
|
p.caps = caps |
|
|
|
|
} |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
//port := ethutil.NumberToBytes(uint16(i), 16)
|
|
|
|
|
log.Printf("peer connect (%s) %v %s [%s]\n", istr, p.conn.RemoteAddr(), c.Get(2).AsString(), p.caps) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return []interface{}{host, uint16(30303) /*port*/} |
|
|
|
|
func (p *Peer) RlpData() []interface{} { |
|
|
|
|
return []interface{}{p.host, p.port /*port*/} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (p *Peer) RlpEncode() []byte { |
|
|
|
|