Beispiel #1
0
func (_ IP) Apply(m ma.Multiaddr, side int, ctx match.Context) error {
	p := m.Protocols()[0]
	name := p.Name
	s, _ := m.ValueForProtocol(p.Code)

	mctx := ctx.Misc()
	ip := net.ParseIP(s)
	if ip == nil {
		return fmt.Errorf("incorrect ip %s", m)
	}

	switch name {
	case "ip4":
		if ip = ip.To4(); ip == nil {
			return fmt.Errorf("incorrect ip4 %s", m)
		}
	case "ip6":
		if ip = ip.To16(); ip == nil {
			return fmt.Errorf("incorrent ip6 %s", m)
		}
	}

	mctx.IPs = append(mctx.IPs, ip)
	return nil
}
Beispiel #2
0
// AddrMatch returns the Multiaddrs that match the protocol stack on addr
func AddrMatch(match ma.Multiaddr, addrs []ma.Multiaddr) []ma.Multiaddr {

	// we should match transports entirely.
	p1s := match.Protocols()

	out := make([]ma.Multiaddr, 0, len(addrs))
	for _, a := range addrs {
		p2s := a.Protocols()
		if len(p1s) != len(p2s) {
			continue
		}

		match := true
		for i, p2 := range p2s {
			if p1s[i].Code != p2.Code {
				match = false
				break
			}
		}
		if match {
			out = append(out, a)
		}
	}
	return out
}
Beispiel #3
0
// ResolveUnspecifiedAddress expands an unspecified ip addresses (/ip4/0.0.0.0, /ip6/::) to
// use the known local interfaces. If ifaceAddr is nil, we request interface addresses
// from the network stack. (this is so you can provide a cached value if resolving many addrs)
func ResolveUnspecifiedAddress(resolve ma.Multiaddr, ifaceAddrs []ma.Multiaddr) ([]ma.Multiaddr, error) {
	// split address into its components
	split := ma.Split(resolve)

	// if first component (ip) is not unspecified, use it as is.
	if !manet.IsIPUnspecified(split[0]) {
		return []ma.Multiaddr{resolve}, nil
	}

	out := make([]ma.Multiaddr, 0, len(ifaceAddrs))
	for _, ia := range ifaceAddrs {
		// must match the first protocol to be resolve.
		if ia.Protocols()[0].Code != resolve.Protocols()[0].Code {
			continue
		}

		split[0] = ia
		joined := ma.Join(split...)
		out = append(out, joined)
		log.Debug("adding resolved addr:", resolve, joined, out)
	}
	if len(out) < 1 {
		return nil, fmt.Errorf("failed to resolve: %s", resolve)
	}
	return out, nil
}
Beispiel #4
0
func (w WS) Apply(m ma.Multiaddr, side int, ctx Context) error {
	var path string
	// ws client matches /http/ws too, so /ws might not be the first protocol
	for _, p := range m.Protocols() {
		if p.Name == "ws" {
			pth, err := m.ValueForProtocol(p.Code)
			if err != nil {
				return err
			}
			path = pth
			break
		}
	}
	sctx := ctx.Special()
	mctx := ctx.Misc()

	switch side {

	case S_Client:
		// resolve url
		var url string
		if mctx.Host != "" {
			// this will make mctx.Host appear in http request headers,
			// cloud servers often require that
			url = fmt.Sprintf("ws://%s/%s", mctx.Host, path)
		} else {
			switch t := sctx.NetConn.(type) {
			case *net.TCPConn:
				url = fmt.Sprintf("ws://%s/%s", t.RemoteAddr().String(), path)
			default:
				url = fmt.Sprintf("ws://foo.bar/%s", path)
			}
		}

		wcon, err := w.Select(sctx.NetConn, url)
		if err != nil {
			return err
		}
		sctx.NetConn = wcon
		return nil

	case S_Server:
		if mctx.HTTPMux == nil {
			// help the user out if /http is missing before /ws
			HTTP{}.Apply(m, S_Server, ctx)
		}
		ln, err := w.Handle(mctx.HTTPMux, "/"+path)
		if err != nil {
			return err
		}
		sctx.NetListener = ln
		sctx.CloseFn = ConcatClose(ln.Close, sctx.CloseFn)
		return nil

	}

	return fmt.Errorf("incorrect side constant")
}
Beispiel #5
0
func (_ DNS) Match(m ma.Multiaddr, side int) (int, bool) {
	ps := m.Protocols()

	if len(ps) > 0 && ps[0].Name == "dns" {
		return 1, true
	}

	return 0, false
}
Beispiel #6
0
func (p HTTP) Match(m ma.Multiaddr, side int) (int, bool) {
	if side != S_Server {
		return 0, false
	}

	ms := m.Protocols()
	if len(ms) >= 1 && ms[0].Name == "http" {
		return 1, true
	}

	return 0, false
}
Beispiel #7
0
func (t TCP) Match(m ma.Multiaddr, side int) (int, bool) {
	ps := m.Protocols()

	if len(ps) < 1 {
		return 0, false
	}

	if ps[0].Name == "tcp" {
		return 1, true
	}

	return 0, false
}
Beispiel #8
0
func (_ IP) Match(m ma.Multiaddr, side int) (int, bool) {
	ps := m.Protocols()

	if len(ps) < 1 {
		return 0, false
	}

	name := ps[0].Name
	if name == "ip" || name == "ip4" || name == "ip6" {
		return 1, true
	}

	return 0, false
}
Beispiel #9
0
func (w WS) Match(m ma.Multiaddr, side int) (int, bool) {
	ps := m.Protocols()

	if len(ps) >= 1 && ps[0].Name == "ws" {
		return 1, true
	}

	// If we're a client, also match "/http/ws".
	if side == S_Client && len(ps) >= 2 &&
		ps[0].Name == "http" && ps[1].Name == "ws" {

		return 2, true
	}

	return 0, false
}
Beispiel #10
0
// MultiaddrProtocolsMatch returns whether two multiaddrs match in protocol stacks.
func MultiaddrProtocolsMatch(a, b ma.Multiaddr) bool {
	ap := a.Protocols()
	bp := b.Protocols()

	if len(ap) != len(bp) {
		return false
	}

	for i, api := range ap {
		if api.Code != bp[i].Code {
			return false
		}
	}

	return true
}
Beispiel #11
0
func (t TCP) Apply(m ma.Multiaddr, side int, ctx match.Context) error {
	p := m.Protocols()[0]
	portstr, _ := m.ValueForProtocol(p.Code)

	port, err := strconv.Atoi(portstr)
	if err != nil {
		return err
	}

	mctx := ctx.Misc()
	sctx := ctx.Special()

	if len(mctx.IPs) == 0 {
		return fmt.Errorf("no ips in context")
	}

	switch side {

	case match.S_Client:
		var con net.Conn
		var err error
		if len(mctx.IPs) == 1 {
			con, err = t.Dial(mctx.IPs[0], port)
		} else {
			con, err = t.DialMany(mctx.IPs, port)
		}
		if err != nil {
			return err
		}

		sctx.NetConn = con
		sctx.CloseFn = con.Close
		return nil

	case match.S_Server:
		netln, err := t.Listen(mctx.IPs[0], port)
		if err != nil {
			return err
		}
		sctx.NetListener = netln
		sctx.CloseFn = netln.Close
		return nil

	}

	return fmt.Errorf("incorrect side constant")
}
Beispiel #12
0
func (_ DNS) Apply(m ma.Multiaddr, side int, ctx match.Context) error {
	p := m.Protocols()[0]
	host, _ := m.ValueForProtocol(p.Code)

	ips, err := net.LookupIP(host)
	if err != nil {
		return err
	}

	if len(ips) == 0 {
		return fmt.Errorf("failed to resolve domain")
	}

	mctx := ctx.Misc()
	mctx.Host = host
	mctx.IPs = ips

	return nil
}
Beispiel #13
0
// AddrUsable returns whether our network can use this addr.
// We only use the transports in SupportedTransportStrings,
// and we do not link local addresses. Loopback is ok
// as we need to be able to connect to multiple ipfs nodes
// in the same machine.
func AddrUsable(a ma.Multiaddr, partial bool) bool {
	if a == nil {
		return false
	}

	if !AddrOverNonLocalIP(a) {
		return false
	}

	// test the address protocol list is in SupportedTransportProtocols
	matches := func(supported, test []ma.Protocol) bool {
		if len(test) > len(supported) {
			return false
		}

		// when partial, it's ok if test < supported.
		if !partial && len(supported) != len(test) {
			return false
		}

		for i := range test {
			if supported[i].Code != test[i].Code {
				return false
			}
		}
		return true
	}

	transport := a.Protocols()
	for _, supported := range SupportedTransportProtocols {
		if matches(supported, transport) {
			return true
		}
	}

	return false
}
Beispiel #14
0
// IsThinWaist returns whether a Multiaddr starts with "Thin Waist" Protocols.
// This means: /{IP4, IP6}[/{TCP, UDP}]
func IsThinWaist(m ma.Multiaddr) bool {
	p := m.Protocols()

	// nothing? not even a waist.
	if len(p) == 0 {
		return false
	}

	if p[0].Code != ma.P_IP4 && p[0].Code != ma.P_IP6 {
		return false
	}

	// only IP? still counts.
	if len(p) == 1 {
		return true
	}

	switch p[1].Code {
	case ma.P_TCP, ma.P_UDP, ma.P_IP4, ma.P_IP6:
		return true
	default:
		return false
	}
}
Beispiel #15
0
func IsUtpMultiaddr(a ma.Multiaddr) bool {
	p := a.Protocols()
	return len(p) == 3 && p[2].Name == "utp"
}
Beispiel #16
0
func IsTcpMultiaddr(a ma.Multiaddr) bool {
	p := a.Protocols()
	return len(p) == 2 && (p[0].Name == "ip4" || p[0].Name == "ip6") && p[1].Name == "tcp"
}