registry.go 4.26 KB
Newer Older
Jeromy's avatar
Jeromy committed
1 2 3 4 5 6 7
package manet

import (
	"fmt"
	"net"
	"sync"

8
	ma "github.com/multiformats/go-multiaddr"
Jeromy's avatar
Jeromy committed
9 10
)

11
// FromNetAddrFunc is a generic function which converts a net.Addr to Multiaddress
Jeromy's avatar
Jeromy committed
12
type FromNetAddrFunc func(a net.Addr) (ma.Multiaddr, error)
13 14

// ToNetAddrFunc is a generic function which converts a Multiaddress to net.Addr
Jeromy's avatar
Jeromy committed
15
type ToNetAddrFunc func(ma ma.Multiaddr) (net.Addr, error)
Jeromy's avatar
Jeromy committed
16

17
var defaultCodecs = NewCodecMap()
Jeromy's avatar
Jeromy committed
18

Jeromy's avatar
Jeromy committed
19
func init() {
20 21 22 23 24
	RegisterFromNetAddr(parseTCPNetAddr, "tcp", "tcp4", "tcp6")
	RegisterFromNetAddr(parseUDPNetAddr, "udp", "udp4", "udp6")
	RegisterFromNetAddr(parseIPNetAddr, "ip", "ip4", "ip6")
	RegisterFromNetAddr(parseIPPlusNetAddr, "ip+net")
	RegisterFromNetAddr(parseUnixNetAddr, "unix")
25

26
	RegisterToNetAddr(parseBasicNetMaddr, "tcp", "udp", "ip6", "ip4", "unix")
Jeromy's avatar
Jeromy committed
27 28
}

29 30 31 32
// CodecMap holds a map of NetCodecs indexed by their Protocol ID
// along with parsers for the addresses they use.
// It is used to keep a list of supported network address codecs (protocols
// which addresses can be converted to and from multiaddresses).
Jeromy's avatar
Jeromy committed
33 34 35 36 37 38
type CodecMap struct {
	addrParsers  map[string]FromNetAddrFunc
	maddrParsers map[string]ToNetAddrFunc
	lk           sync.Mutex
}

39
// NewCodecMap initializes and returns a CodecMap object.
Jeromy's avatar
Jeromy committed
40 41 42 43 44 45 46
func NewCodecMap() *CodecMap {
	return &CodecMap{
		addrParsers:  make(map[string]FromNetAddrFunc),
		maddrParsers: make(map[string]ToNetAddrFunc),
	}
}

47 48 49
// NetCodec is used to identify a network codec, that is, a network type for
// which we are able to translate multiaddresses into standard Go net.Addr
// and back.
50 51 52 53 54 55 56
//
// Deprecated: Unfortunately, these mappings aren't one to one. This abstraction
// assumes that multiple "networks" can map to a single multiaddr protocol but
// not the reverse. For example, this abstraction supports `tcp6, tcp4, tcp ->
// /tcp/` really well but doesn't support `ip -> {/ip4/, /ip6/}`.
//
// Please use `RegisterFromNetAddr` and `RegisterToNetAddr` directly.
Jeromy's avatar
Jeromy committed
57 58
type NetCodec struct {
	// NetAddrNetworks is an array of strings that may be returned
Jeromy's avatar
Jeromy committed
59
	// by net.Addr.Network() calls on addresses belonging to this type
Jeromy's avatar
Jeromy committed
60
	NetAddrNetworks []string
Jeromy's avatar
Jeromy committed
61

Jeromy's avatar
Jeromy committed
62 63
	// ProtocolName is the string value for Multiaddr address keys
	ProtocolName string
Jeromy's avatar
Jeromy committed
64 65

	// ParseNetAddr parses a net.Addr belonging to this type into a multiaddr
Jeromy's avatar
Jeromy committed
66
	ParseNetAddr FromNetAddrFunc
Jeromy's avatar
Jeromy committed
67 68

	// ConvertMultiaddr converts a multiaddr of this type back into a net.Addr
Jeromy's avatar
Jeromy committed
69
	ConvertMultiaddr ToNetAddrFunc
Jeromy's avatar
Jeromy committed
70 71 72 73 74

	// Protocol returns the multiaddr protocol struct for this type
	Protocol ma.Protocol
}

75
// RegisterNetCodec adds a new NetCodec to the default codecs.
Jeromy's avatar
Jeromy committed
76 77
func RegisterNetCodec(a *NetCodec) {
	defaultCodecs.RegisterNetCodec(a)
Jeromy's avatar
Jeromy committed
78 79
}

80 81 82 83 84 85 86 87 88 89
// RegisterFromNetAddr registers a conversion from net.Addr instances to multiaddrs.
func RegisterFromNetAddr(from FromNetAddrFunc, networks ...string) {
	defaultCodecs.RegisterFromNetAddr(from, networks...)
}

// RegisterToNetAddr registers a conversion from multiaddrs to net.Addr instances.
func RegisterToNetAddr(to ToNetAddrFunc, protocols ...string) {
	defaultCodecs.RegisterToNetAddr(to, protocols...)
}

90 91
// RegisterNetCodec adds a new NetCodec to the CodecMap. This function is
// thread safe.
Jeromy's avatar
Jeromy committed
92 93 94 95 96 97
func (cm *CodecMap) RegisterNetCodec(a *NetCodec) {
	cm.lk.Lock()
	defer cm.lk.Unlock()
	for _, n := range a.NetAddrNetworks {
		cm.addrParsers[n] = a.ParseNetAddr
	}
Jeromy's avatar
Jeromy committed
98

Jeromy's avatar
Jeromy committed
99
	cm.maddrParsers[a.ProtocolName] = a.ConvertMultiaddr
Jeromy's avatar
Jeromy committed
100 101
}

102 103 104 105
// RegisterFromNetAddr registers a conversion from net.Addr instances to multiaddrs
func (cm *CodecMap) RegisterFromNetAddr(from FromNetAddrFunc, networks ...string) {
	cm.lk.Lock()
	defer cm.lk.Unlock()
106

107 108 109
	for _, n := range networks {
		cm.addrParsers[n] = from
	}
110 111
}

112 113 114 115
// RegisterToNetAddr registers a conversion from multiaddrs to net.Addr instances
func (cm *CodecMap) RegisterToNetAddr(to ToNetAddrFunc, protocols ...string) {
	cm.lk.Lock()
	defer cm.lk.Unlock()
116

117 118 119
	for _, p := range protocols {
		cm.maddrParsers[p] = to
	}
Jeromy's avatar
Jeromy committed
120 121
}

Jeromy's avatar
Jeromy committed
122 123 124
func (cm *CodecMap) getAddrParser(net string) (FromNetAddrFunc, error) {
	cm.lk.Lock()
	defer cm.lk.Unlock()
Jeromy's avatar
Jeromy committed
125

Jeromy's avatar
Jeromy committed
126
	parser, ok := cm.addrParsers[net]
Jeromy's avatar
Jeromy committed
127 128 129 130 131 132
	if !ok {
		return nil, fmt.Errorf("unknown network %v", net)
	}
	return parser, nil
}

Jeromy's avatar
Jeromy committed
133 134 135 136
func (cm *CodecMap) getMaddrParser(name string) (ToNetAddrFunc, error) {
	cm.lk.Lock()
	defer cm.lk.Unlock()
	p, ok := cm.maddrParsers[name]
Jeromy's avatar
Jeromy committed
137 138 139 140 141 142
	if !ok {
		return nil, fmt.Errorf("network not supported: %s", name)
	}

	return p, nil
}