config.go 2.1 KB
Newer Older
1 2 3 4
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

5
package multiresolver
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

import (
	"fmt"
	"strings"
	"unicode"

	"github.com/ethereum/go-ethereum/common"
)

// Defined as per RFC 1034. For reference, see:
// https://en.wikipedia.org/wiki/Domain_Name_System#cite_note-rfc1034-1
const maxTLDLength = 63

// ConnectionConfig contains the TLD, endpoint and contract address used to
// establish to a resolver.
type ConnectionConfig struct {
	TLD      string
	Address  string
	Endpoint string
}

// ParseConnectionString will try to parse a connection string used to connect
// the Resolver to a name resolution service. The resulting config can be
// used to initialize a resovler Service.
30
func parseConnectionString(cs string) (ConnectionConfig, error) {
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
	isAllUnicodeLetters := func(s string) bool {
		for _, r := range s {
			if !unicode.IsLetter(r) {
				return false
			}
		}
		return true
	}

	endpoint := cs
	var tld string
	var addr string

	// Split TLD and Endpoint strings.
	if i := strings.Index(endpoint, ":"); i > 0 {
		// Make sure not to grab the protocol, as it contains "://"!
		// Eg. in http://... the "http" is NOT a tld.
		if isAllUnicodeLetters(endpoint[:i]) && len(endpoint) > i+2 && endpoint[i+1:i+3] != "//" {
			tld = endpoint[:i]
			if len(tld) > maxTLDLength {
51
				return ConnectionConfig{}, fmt.Errorf("tld %s: %w", tld, ErrTLDTooLong)
52 53 54 55 56 57 58 59 60 61 62

			}
			endpoint = endpoint[i+1:]
		}
	}
	// Split the address string.
	if i := strings.Index(endpoint, "@"); i > 0 {
		addr = common.HexToAddress(endpoint[:i]).String()
		endpoint = endpoint[i+1:]
	}

63
	return ConnectionConfig{
64 65 66 67 68 69 70 71
		Endpoint: endpoint,
		Address:  addr,
		TLD:      tld,
	}, nil
}

// ParseConnectionStrings will apply ParseConnectionString to each connection
// string. Returns first error found.
72 73
func ParseConnectionStrings(cstrs []string) ([]ConnectionConfig, error) {
	var res []ConnectionConfig
74 75 76 77 78 79 80 81 82 83 84

	for _, cs := range cstrs {
		cfg, err := parseConnectionString(cs)
		if err != nil {
			return nil, err
		}
		res = append(res, cfg)
	}

	return res, nil
}