1package ice
2
3import (
4	"net"
5	"strings"
6)
7
8// CandidateHost is a candidate of type host
9type CandidateHost struct {
10	candidateBase
11
12	network string
13}
14
15// CandidateHostConfig is the config required to create a new CandidateHost
16type CandidateHostConfig struct {
17	CandidateID string
18	Network     string
19	Address     string
20	Port        int
21	Component   uint16
22	Priority    uint32
23	Foundation  string
24	TCPType     TCPType
25}
26
27// NewCandidateHost creates a new host candidate
28func NewCandidateHost(config *CandidateHostConfig) (*CandidateHost, error) {
29	candidateID := config.CandidateID
30
31	if candidateID == "" {
32		candidateID = globalCandidateIDGenerator.Generate()
33	}
34
35	c := &CandidateHost{
36		candidateBase: candidateBase{
37			id:                 candidateID,
38			address:            config.Address,
39			candidateType:      CandidateTypeHost,
40			component:          config.Component,
41			port:               config.Port,
42			tcpType:            config.TCPType,
43			foundationOverride: config.Foundation,
44			priorityOverride:   config.Priority,
45		},
46		network: config.Network,
47	}
48
49	if !strings.HasSuffix(config.Address, ".local") {
50		ip := net.ParseIP(config.Address)
51		if ip == nil {
52			return nil, ErrAddressParseFailed
53		}
54
55		if err := c.setIP(ip); err != nil {
56			return nil, err
57		}
58	} else {
59		// Until mDNS candidate is resolved assume it is UDPv4
60		c.candidateBase.networkType = NetworkTypeUDP4
61	}
62
63	return c, nil
64}
65
66func (c *CandidateHost) setIP(ip net.IP) error {
67	networkType, err := determineNetworkType(c.network, ip)
68	if err != nil {
69		return err
70	}
71
72	c.candidateBase.networkType = networkType
73	c.candidateBase.resolvedAddr = createAddr(networkType, ip, c.port)
74
75	return nil
76}
77