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

import (
	"fmt"
	"net"
	"sync"

	ma "github.com/jbenet/go-multiaddr"
)

Jeromy's avatar
Jeromy committed
11 12
type FromNetAddrFunc func(a net.Addr) (ma.Multiaddr, error)
type ToNetAddrFunc func(ma ma.Multiaddr) (net.Addr, error)
Jeromy's avatar
Jeromy committed
13

Jeromy's avatar
Jeromy committed
14
var defaultCodecs *CodecMap
Jeromy's avatar
Jeromy committed
15

Jeromy's avatar
Jeromy committed
16 17 18 19 20 21 22
func init() {
	defaultCodecs = NewCodecMap()
	defaultCodecs.RegisterNetCodec(tcpAddrSpec)
	defaultCodecs.RegisterNetCodec(udpAddrSpec)
	defaultCodecs.RegisterNetCodec(utpAddrSpec)
	defaultCodecs.RegisterNetCodec(ip4AddrSpec)
	defaultCodecs.RegisterNetCodec(ip6AddrSpec)
Jeromy's avatar
Jeromy committed
23
	defaultCodecs.RegisterNetCodec(ipnetAddrSpec)
Jeromy's avatar
Jeromy committed
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
}

type CodecMap struct {
	codecs       map[string]*NetCodec
	addrParsers  map[string]FromNetAddrFunc
	maddrParsers map[string]ToNetAddrFunc
	lk           sync.Mutex
}

func NewCodecMap() *CodecMap {
	return &CodecMap{
		codecs:       make(map[string]*NetCodec),
		addrParsers:  make(map[string]FromNetAddrFunc),
		maddrParsers: make(map[string]ToNetAddrFunc),
	}
}

type NetCodec struct {
	// NetAddrNetworks is an array of strings that may be returned
Jeromy's avatar
Jeromy committed
43
	// by net.Addr.Network() calls on addresses belonging to this type
Jeromy's avatar
Jeromy committed
44
	NetAddrNetworks []string
Jeromy's avatar
Jeromy committed
45

Jeromy's avatar
Jeromy committed
46 47
	// ProtocolName is the string value for Multiaddr address keys
	ProtocolName string
Jeromy's avatar
Jeromy committed
48 49

	// ParseNetAddr parses a net.Addr belonging to this type into a multiaddr
Jeromy's avatar
Jeromy committed
50
	ParseNetAddr FromNetAddrFunc
Jeromy's avatar
Jeromy committed
51 52

	// ConvertMultiaddr converts a multiaddr of this type back into a net.Addr
Jeromy's avatar
Jeromy committed
53
	ConvertMultiaddr ToNetAddrFunc
Jeromy's avatar
Jeromy committed
54 55 56 57 58

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

Jeromy's avatar
Jeromy committed
59 60
func RegisterNetCodec(a *NetCodec) {
	defaultCodecs.RegisterNetCodec(a)
Jeromy's avatar
Jeromy committed
61 62
}

Jeromy's avatar
Jeromy committed
63 64 65 66 67 68 69
func (cm *CodecMap) RegisterNetCodec(a *NetCodec) {
	cm.lk.Lock()
	defer cm.lk.Unlock()
	cm.codecs[a.ProtocolName] = a
	for _, n := range a.NetAddrNetworks {
		cm.addrParsers[n] = a.ParseNetAddr
	}
Jeromy's avatar
Jeromy committed
70

Jeromy's avatar
Jeromy committed
71
	cm.maddrParsers[a.ProtocolName] = a.ConvertMultiaddr
Jeromy's avatar
Jeromy committed
72 73
}

Jeromy's avatar
Jeromy committed
74 75 76
var tcpAddrSpec = &NetCodec{
	ProtocolName:     "tcp",
	NetAddrNetworks:  []string{"tcp", "tcp4", "tcp6"},
77 78 79 80
	ParseNetAddr:     parseTcpNetAddr,
	ConvertMultiaddr: parseBasicNetMaddr,
}

Jeromy's avatar
Jeromy committed
81 82 83
var udpAddrSpec = &NetCodec{
	ProtocolName:     "udp",
	NetAddrNetworks:  []string{"udp", "udp4", "udp6"},
84 85 86 87
	ParseNetAddr:     parseUdpNetAddr,
	ConvertMultiaddr: parseBasicNetMaddr,
}

Jeromy's avatar
Jeromy committed
88 89 90
var utpAddrSpec = &NetCodec{
	ProtocolName:     "utp",
	NetAddrNetworks:  []string{"utp", "utp4", "utp6"},
91 92 93 94
	ParseNetAddr:     parseUtpNetAddr,
	ConvertMultiaddr: parseBasicNetMaddr,
}

Jeromy's avatar
Jeromy committed
95 96 97
var ip4AddrSpec = &NetCodec{
	ProtocolName:     "ip4",
	NetAddrNetworks:  []string{"ip4"},
98 99 100 101
	ParseNetAddr:     parseIpNetAddr,
	ConvertMultiaddr: parseBasicNetMaddr,
}

Jeromy's avatar
Jeromy committed
102 103 104
var ip6AddrSpec = &NetCodec{
	ProtocolName:     "ip6",
	NetAddrNetworks:  []string{"ip6"},
105 106 107 108
	ParseNetAddr:     parseIpNetAddr,
	ConvertMultiaddr: parseBasicNetMaddr,
}

Jeromy's avatar
Jeromy committed
109 110 111 112 113 114 115 116 117
var ipnetAddrSpec = &NetCodec{
	ProtocolName:    "ip+net",
	NetAddrNetworks: []string{"ip+net"},
	ParseNetAddr:    parseIpPlusNetAddr,
	ConvertMultiaddr: func(ma.Multiaddr) (net.Addr, error) {
		return nil, fmt.Errorf("converting ip+net multiaddr not supported")
	},
}

Jeromy's avatar
Jeromy committed
118 119 120
func (cm *CodecMap) getAddrParser(net string) (FromNetAddrFunc, error) {
	cm.lk.Lock()
	defer cm.lk.Unlock()
Jeromy's avatar
Jeromy committed
121

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

Jeromy's avatar
Jeromy committed
129 130 131 132
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
133 134 135 136 137 138
	if !ok {
		return nil, fmt.Errorf("network not supported: %s", name)
	}

	return p, nil
}