"net"
"time"
+ log "github.com/sirupsen/logrus"
"golang.org/x/crypto/nacl/box"
"golang.org/x/crypto/nacl/secretbox"
"golang.org/x/crypto/ripemd160"
var err error
ephPub, ephPriv, err = box.GenerateKey(crand.Reader)
if err != nil {
- cmn.PanicCrisis("Could not generate ephemeral keypairs")
+ log.Panic("Could not generate ephemeral keypairs")
}
return
}
--- /dev/null
+package p2p
+
+import (
+ "net"
+)
+
+// ExternalIPv4 returns the first IPv4 available.
+func ExternalIPv4() (string, error) {
+ ifaces, err := net.Interfaces()
+ if err != nil {
+ return "", err
+ }
+
+ for _, iface := range ifaces {
+ // interface down
+ if iface.Flags&net.FlagUp == 0 {
+ continue
+ }
+ // loopback interface
+ if iface.Flags&net.FlagLoopback != 0 {
+ continue
+ }
+ addrs, err := iface.Addrs()
+ if err != nil {
+ return "", err
+ }
+
+ for _, addr := range addrs {
+ var ip net.IP
+ switch v := addr.(type) {
+ case *net.IPNet:
+ ip = v.IP
+ case *net.IPAddr:
+ ip = v.IP
+ }
+ if ip == nil || ip.IsLoopback() {
+ continue
+ }
+ ip = ip.To4()
+ if ip == nil {
+ continue // not an ipv4 address
+ }
+ return ip.String(), nil
+ }
+ }
+ return "127.0.0.1", nil
+}
--- /dev/null
+package p2p
+
+import (
+ "regexp"
+ "testing"
+)
+
+func TestExternalIPv4(t *testing.T) {
+ // Regular expression format for IPv4
+ IPv4Format := `\.\d{1,3}\.\d{1,3}\b`
+ test, err := ExternalIPv4()
+
+ if err != nil {
+ t.Errorf("Test check external ipv4 failed with %v", err)
+ }
+
+ valid := regexp.MustCompile(IPv4Format)
+
+ if !valid.MatchString(test) {
+ t.Errorf("Wanted: %v, got: %v", IPv4Format, test)
+ }
+}
return NewNetAddressIPPort(ext, uint16(externalPort)), nil
}
-func getNaiveExternalAddress(port int, settleForLocal bool) *NetAddress {
- addrs, err := net.InterfaceAddrs()
- if err != nil {
- cmn.PanicCrisis(cmn.Fmt("Could not fetch interface addresses: %v", err))
- }
-
- for _, a := range addrs {
- ipnet, ok := a.(*net.IPNet)
- if !ok {
- continue
- }
- if v4 := ipnet.IP.To4(); v4 == nil || (!settleForLocal && v4[0] == 127) {
- continue
- }
- return NewNetAddressIPPort(ipnet.IP, uint16(port))
- }
-
- log.Info("Node may not be connected to internet. Settling for local address")
- return getNaiveExternalAddress(port, true)
-}
-
func splitHostPort(addr string) (host string, port int) {
host, portStr, err := net.SplitHostPort(addr)
if err != nil {
listener, err = net.Listen(protocol, lAddr)
}
if err != nil {
- cmn.PanicCrisis(err)
+ log.Panic(err)
}
intAddr, err := NewNetAddressString(lAddr)
if err != nil {
- cmn.PanicCrisis(err)
+ log.Panic(err)
}
// Actual listener local IP & port
log.WithFields(log.Fields{"module": logModule, "err": err}).Info("get UPNP external address")
}
+ // Get the IPv4 available
if extAddr == nil {
- if address := GetIP(); address.Success == true {
- extAddr = NewNetAddressIPPort(net.ParseIP(address.IP), uint16(lAddrPort))
+ if ip, err := ExternalIPv4(); err != nil {
+ log.WithFields(log.Fields{"module": logModule, "err": err}).Warning("get ipv4 external address")
+ log.Panic("get ipv4 external address fail!")
+ } else {
+ extAddr = NewNetAddressIPPort(net.ParseIP(ip), uint16(lAddrPort))
+ log.WithFields(log.Fields{"module": logModule, "addr": extAddr}).Info("get ipv4 external address success")
}
}
- if extAddr == nil {
- extAddr = getNaiveExternalAddress(listenerPort, false)
- }
- if extAddr == nil {
- cmn.PanicCrisis("could not determine external address!")
- }
dl := &DefaultListener{
listener: listener,
// listener wasn't stopped,
// yet we encountered an error.
if err != nil {
- cmn.PanicCrisis(err)
+ log.Panic(err)
}
l.connections <- conn
}
func() {
var n int
wire.ReadBinary(peerNodeInfo, pc.conn, maxNodeInfoSize, &n, &err2)
- log.WithFields(log.Fields{"module": logModule, "address": peerNodeInfo.ListenAddr}).Info("Peer handshake")
+ log.WithFields(log.Fields{"module": logModule, "address": pc.conn.RemoteAddr().String()}).Info("Peer handshake")
})
if err1 != nil {
return peerNodeInfo, errors.Wrap(err1, "Error during handshake/write")
+++ /dev/null
-package p2p
-
-import (
- "io/ioutil"
- "net"
- "net/http"
- "strings"
- "time"
-)
-
-var ipCheckServices = []string{
- "http://members.3322.org/dyndns/getip",
- "http://ifconfig.me/",
- "http://icanhazip.com/",
- "http://ifconfig.io/ip",
- "http://ident.me/",
- "http://whatismyip.akamai.com/",
- "http://myip.dnsomatic.com/",
- "http://diagnostic.opendns.com/myip",
- "http://myexternalip.com/raw",
-}
-
-// IPResult is the ip check response
-type IPResult struct {
- Success bool
- IP string
-}
-
-var timeout = time.Duration(5)
-
-// GetIP return the ip of the current host
-func GetIP() *IPResult {
- resultCh := make(chan *IPResult, 1)
- for _, s := range ipCheckServices {
- go ipAddress(s, resultCh)
- }
-
- for {
- select {
- case result := <-resultCh:
- return result
- case <-time.After(time.Second * timeout):
- return &IPResult{false, ""}
- }
- }
-}
-
-func ipAddress(service string, done chan<- *IPResult) {
- client := http.Client{Timeout: time.Duration(timeout * time.Second)}
- resp, err := client.Get(service)
- if err != nil {
- return
- }
-
- defer resp.Body.Close()
- data, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return
- }
-
- address := strings.TrimSpace(string(data))
- if ip := net.ParseIP(address); ip != nil && ip.To4() != nil {
- select {
- case done <- &IPResult{true, address}:
- return
- default:
- return
- }
- }
-}