diff --git a/convert.go b/convert.go index 944c788..faea3ed 100644 --- a/convert.go +++ b/convert.go @@ -3,8 +3,10 @@ package manet import ( "fmt" "net" + "strconv" "strings" + tor "github.com/david415/oniondialer" utp "github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/h2so5/utp" ma "github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" ) @@ -97,6 +99,23 @@ func FromNetAddr(a net.Addr) (ma.Multiaddr, error) { } return FromIP(ac.IP) + case "onion": + onionAddr, ok := a.(*tor.OnionAddr) + if !ok { + return nil, errIncorrectNetAddr + } + + fields := strings.Split(onionAddr.String(), ":") + if len(fields) != 2 { + return nil, fmt.Errorf("invalid onion addr doesn't contain a port %v", onionAddr) + } + // Get Tor Onion Addr + onionm, err := ma.NewMultiaddr(fmt.Sprintf("/onion/%s:%s", fields[0], fields[1])) + if err != nil { + return nil, errIncorrectNetAddr + } + return onionm, nil + default: return nil, fmt.Errorf("unknown network %v", a.Network()) } @@ -139,13 +158,23 @@ func FromIP(ip net.IP) (ma.Multiaddr, error) { // DialArgs is a convenience function returning arguments for use in net.Dial func DialArgs(m ma.Multiaddr) (string, string, error) { - if !IsThinWaist(m) { - return "", "", fmt.Errorf("%s is not a 'thin waist' address", m) - } - str := m.String() parts := strings.Split(str, "/")[1:] + switch parts[0] { + case "onion": + addr := strings.Split(parts[1], ":") + if len(addr) != 2 { + return "", "", fmt.Errorf("failed to parse addr %s: does not contain a port number.", str) + } + onionHost := addr[0] + ".onion" + onionPort, err := strconv.Atoi(addr[1]) + if err != nil { + return "", "", fmt.Errorf("failed to parse addr %s: invalid port number", str) + } + return "onion", fmt.Sprintf("%s:%s", onionHost, onionPort), nil + } + if len(parts) == 2 { // only IP return parts[0], parts[1], nil } diff --git a/net.go b/net.go index 828a318..de0246d 100644 --- a/net.go +++ b/net.go @@ -5,6 +5,7 @@ import ( "net" // utp "github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/h2so5/utp" + tor "github.com/david415/oniondialer" ma "github.com/jbenet/go-multiaddr-net/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" ) @@ -88,18 +89,18 @@ type Dialer struct { // remote Multiaddrs). func (d *Dialer) Dial(remote ma.Multiaddr) (Conn, error) { - // if a LocalAddr is specified, use it on the embedded dialer. - if d.LocalAddr != nil { - // convert our multiaddr to net.Addr friendly - naddr, err := ToNetAddr(d.LocalAddr) - if err != nil { - return nil, err + if IsThinWaist(remote) { + // if a LocalAddr is specified, use it on the embedded dialer. + if d.LocalAddr != nil { + // convert our multiaddr to net.Addr friendly + naddr, err := ToNetAddr(d.LocalAddr) + if err != nil { + return nil, err + } + // set the dialer's LocalAddr as naddr + d.Dialer.LocalAddr = naddr } - - // set the dialer's LocalAddr as naddr - d.Dialer.LocalAddr = naddr } - // get the net.Dial friendly arguments from the remote addr rnet, rnaddr, err := DialArgs(remote) if err != nil { @@ -127,6 +128,21 @@ func (d *Dialer) Dial(remote ma.Multiaddr) (Conn, error) { // if err != nil { // return nil, err // } + case "onion": + // XXX fix me. do not want hard coded values. needs user specified parameters. + torDialer, err := tor.NewTorDialer("tcp", "127.0.0.1:9050", nil) + if err != nil { + return nil, err + } + nconn, err = torDialer.Dial(rnet, rnaddr) + if err != nil { + return nil, err + } + return &maConn{ + Conn: nconn, + laddr: d.LocalAddr, + raddr: remote, + }, nil } // get local address (pre-specified or assigned within net.Conn)