-
Notifications
You must be signed in to change notification settings - Fork 26
make multiaddr-net more pluggable #15
Changes from 1 commit
347065f
1263064
48f060e
79cf06b
b730d26
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,112 +4,198 @@ import ( | |
"fmt" | ||
"net" | ||
"strings" | ||
"sync" | ||
|
||
ma "github.com/jbenet/go-multiaddr" | ||
utp "github.com/jbenet/go-multiaddr-net/utp" | ||
) | ||
|
||
var errIncorrectNetAddr = fmt.Errorf("incorrect network addr conversion") | ||
|
||
type AddrParser func(a net.Addr) (ma.Multiaddr, error) | ||
type MaddrParser func(ma ma.Multiaddr) (net.Addr, error) | ||
|
||
var maddrParsers map[string]MaddrParser | ||
var addrParsers map[string]AddrParser | ||
var addrParsersLock sync.Mutex | ||
|
||
func init() { | ||
addrParsers = make(map[string]AddrParser) | ||
maddrParsers = make(map[string]MaddrParser) | ||
|
||
registerDefaultAddrParsers() | ||
registerDefaultMaddrParsers() | ||
} | ||
|
||
func registerDefaultAddrParsers() { | ||
funcs := map[string]AddrParser{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you think about adding the default addr/maddr parsers using the public My thinking is that if it's awkward or undesirable to do so, then that may be a signal that the public API needs some massaging to be likeable enough to use for registering them internally too. Does that make sense? |
||
"tcp": ParseTcpNetAddr, | ||
"udp": ParseUdpNetAddr, | ||
"utp": ParseUtpNetAddr, | ||
"ip": ParseIpNetAddr, | ||
} | ||
|
||
for k, v := range funcs { | ||
addrParsers[k] = v | ||
addrParsers[k+"4"] = v | ||
addrParsers[k+"6"] = v | ||
} | ||
|
||
addrParsers["ip+net"] = ParseIpPlusNetAddr | ||
} | ||
|
||
func RegisterAddressType(netname, maname string, ap AddrParser, mp MaddrParser) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Having a test for this would be nice to have. |
||
addrParsersLock.Lock() | ||
defer addrParsersLock.Unlock() | ||
addrParsers[netname] = ap | ||
maddrParsers[maname] = mp | ||
} | ||
|
||
func ParseTcpNetAddr(a net.Addr) (ma.Multiaddr, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do the |
||
ac, ok := a.(*net.TCPAddr) | ||
if !ok { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Get IP Addr | ||
ipm, err := FromIP(ac.IP) | ||
if err != nil { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Get TCP Addr | ||
tcpm, err := ma.NewMultiaddr(fmt.Sprintf("/tcp/%d", ac.Port)) | ||
if err != nil { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Encapsulate | ||
return ipm.Encapsulate(tcpm), nil | ||
} | ||
|
||
func ParseUdpNetAddr(a net.Addr) (ma.Multiaddr, error) { | ||
ac, ok := a.(*net.UDPAddr) | ||
if !ok { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Get IP Addr | ||
ipm, err := FromIP(ac.IP) | ||
if err != nil { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Get UDP Addr | ||
udpm, err := ma.NewMultiaddr(fmt.Sprintf("/udp/%d", ac.Port)) | ||
if err != nil { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Encapsulate | ||
return ipm.Encapsulate(udpm), nil | ||
} | ||
|
||
func ParseUtpNetAddr(a net.Addr) (ma.Multiaddr, error) { | ||
acc, ok := a.(*utp.Addr) | ||
if !ok { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Get UDP Addr | ||
ac, ok := acc.Child().(*net.UDPAddr) | ||
if !ok { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Get IP Addr | ||
ipm, err := FromIP(ac.IP) | ||
if err != nil { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Get UDP Addr | ||
utpm, err := ma.NewMultiaddr(fmt.Sprintf("/udp/%d/utp", ac.Port)) | ||
if err != nil { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Encapsulate | ||
return ipm.Encapsulate(utpm), nil | ||
} | ||
|
||
func ParseIpNetAddr(a net.Addr) (ma.Multiaddr, error) { | ||
ac, ok := a.(*net.IPAddr) | ||
if !ok { | ||
return nil, errIncorrectNetAddr | ||
} | ||
return FromIP(ac.IP) | ||
} | ||
|
||
func ParseIpPlusNetAddr(a net.Addr) (ma.Multiaddr, error) { | ||
ac, ok := a.(*net.IPNet) | ||
if !ok { | ||
return nil, errIncorrectNetAddr | ||
} | ||
return FromIP(ac.IP) | ||
} | ||
|
||
func getAddrParser(net string) (AddrParser, error) { | ||
addrParsersLock.Lock() | ||
defer addrParsersLock.Unlock() | ||
|
||
parser, ok := addrParsers[net] | ||
if !ok { | ||
return nil, fmt.Errorf("unknown network %v", net) | ||
} | ||
return parser, nil | ||
} | ||
|
||
// FromNetAddr converts a net.Addr type to a Multiaddr. | ||
func FromNetAddr(a net.Addr) (ma.Multiaddr, error) { | ||
if a == nil { | ||
return nil, fmt.Errorf("nil multiaddr") | ||
} | ||
p, err := getAddrParser(a.Network()) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
switch a.Network() { | ||
case "tcp", "tcp4", "tcp6": | ||
ac, ok := a.(*net.TCPAddr) | ||
if !ok { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Get IP Addr | ||
ipm, err := FromIP(ac.IP) | ||
if err != nil { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Get TCP Addr | ||
tcpm, err := ma.NewMultiaddr(fmt.Sprintf("/tcp/%d", ac.Port)) | ||
if err != nil { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Encapsulate | ||
return ipm.Encapsulate(tcpm), nil | ||
|
||
case "udp", "upd4", "udp6": | ||
ac, ok := a.(*net.UDPAddr) | ||
if !ok { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Get IP Addr | ||
ipm, err := FromIP(ac.IP) | ||
if err != nil { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Get UDP Addr | ||
udpm, err := ma.NewMultiaddr(fmt.Sprintf("/udp/%d", ac.Port)) | ||
if err != nil { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Encapsulate | ||
return ipm.Encapsulate(udpm), nil | ||
|
||
case "utp", "utp4", "utp6": | ||
acc, ok := a.(*utp.Addr) | ||
if !ok { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Get UDP Addr | ||
ac, ok := acc.Child().(*net.UDPAddr) | ||
if !ok { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Get IP Addr | ||
ipm, err := FromIP(ac.IP) | ||
if err != nil { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Get UDP Addr | ||
utpm, err := ma.NewMultiaddr(fmt.Sprintf("/udp/%d/utp", ac.Port)) | ||
if err != nil { | ||
return nil, errIncorrectNetAddr | ||
} | ||
|
||
// Encapsulate | ||
return ipm.Encapsulate(utpm), nil | ||
|
||
case "ip", "ip4", "ip6": | ||
ac, ok := a.(*net.IPAddr) | ||
if !ok { | ||
return nil, errIncorrectNetAddr | ||
} | ||
return FromIP(ac.IP) | ||
|
||
case "ip+net": | ||
ac, ok := a.(*net.IPNet) | ||
if !ok { | ||
return nil, errIncorrectNetAddr | ||
} | ||
return FromIP(ac.IP) | ||
return p(a) | ||
} | ||
|
||
default: | ||
return nil, fmt.Errorf("unknown network %v", a.Network()) | ||
func getMaddrParser(name string) (MaddrParser, error) { | ||
addrParsersLock.Lock() | ||
defer addrParsersLock.Unlock() | ||
p, ok := maddrParsers[name] | ||
if !ok { | ||
return nil, fmt.Errorf("network not supported: %s", name) | ||
} | ||
|
||
return p, nil | ||
} | ||
|
||
// ToNetAddr converts a Multiaddr to a net.Addr | ||
// Must be ThinWaist. acceptable protocol stacks are: | ||
// /ip{4,6}/{tcp, udp} | ||
func ToNetAddr(maddr ma.Multiaddr) (net.Addr, error) { | ||
protos := maddr.Protocols() | ||
final := protos[len(protos)-1] | ||
|
||
p, err := getMaddrParser(final.Name) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return p(maddr) | ||
} | ||
|
||
func registerDefaultMaddrParsers() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we're keeping this (i.e. not using the public API for registering), could we move it up to live with the |
||
for _, net := range []string{"tcp", "udp", "utp", "ip", "ip4", "ip6"} { | ||
maddrParsers[net] = parseBasicNetAddr | ||
} | ||
} | ||
|
||
func parseBasicNetAddr(maddr ma.Multiaddr) (net.Addr, error) { | ||
network, host, err := DialArgs(maddr) | ||
if err != nil { | ||
return nil, err | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A concurrency test or two would be nice to have.