1package net
2
3import (
4	"net"
5	"strings"
6)
7
8// Destination represents a network destination including address and protocol (tcp / udp).
9type Destination struct {
10	Address Address
11	Port    Port
12	Network Network
13}
14
15// DestinationFromAddr generates a Destination from a net address.
16func DestinationFromAddr(addr net.Addr) Destination {
17	switch addr := addr.(type) {
18	case *net.TCPAddr:
19		return TCPDestination(IPAddress(addr.IP), Port(addr.Port))
20	case *net.UDPAddr:
21		return UDPDestination(IPAddress(addr.IP), Port(addr.Port))
22	case *net.UnixAddr:
23		return UnixDestination(DomainAddress(addr.Name))
24	default:
25		panic("Net: Unknown address type.")
26	}
27}
28
29// ParseDestination converts a destination from its string presentation.
30func ParseDestination(dest string) (Destination, error) {
31	d := Destination{
32		Address: AnyIP,
33		Port:    Port(0),
34	}
35
36	switch {
37	case strings.HasPrefix(dest, "tcp:"):
38		d.Network = Network_TCP
39		dest = dest[4:]
40	case strings.HasPrefix(dest, "udp:"):
41		d.Network = Network_UDP
42		dest = dest[4:]
43	case strings.HasPrefix(dest, "unix:"):
44		d = UnixDestination(DomainAddress(dest[5:]))
45		return d, nil
46	}
47
48	hstr, pstr, err := SplitHostPort(dest)
49	if err != nil {
50		return d, err
51	}
52	if len(hstr) > 0 {
53		d.Address = ParseAddress(hstr)
54	}
55	if len(pstr) > 0 {
56		port, err := PortFromString(pstr)
57		if err != nil {
58			return d, err
59		}
60		d.Port = port
61	}
62	return d, nil
63}
64
65// TCPDestination creates a TCP destination with given address
66func TCPDestination(address Address, port Port) Destination {
67	return Destination{
68		Network: Network_TCP,
69		Address: address,
70		Port:    port,
71	}
72}
73
74// UDPDestination creates a UDP destination with given address
75func UDPDestination(address Address, port Port) Destination {
76	return Destination{
77		Network: Network_UDP,
78		Address: address,
79		Port:    port,
80	}
81}
82
83// UnixDestination creates a Unix destination with given address
84func UnixDestination(address Address) Destination {
85	return Destination{
86		Network: Network_UNIX,
87		Address: address,
88	}
89}
90
91// NetAddr returns the network address in this Destination in string form.
92func (d Destination) NetAddr() string {
93	addr := ""
94	if d.Network == Network_TCP || d.Network == Network_UDP {
95		addr = d.Address.String() + ":" + d.Port.String()
96	} else if d.Network == Network_UNIX {
97		addr = d.Address.String()
98	}
99	return addr
100}
101
102// String returns the strings form of this Destination.
103func (d Destination) String() string {
104	prefix := "unknown:"
105	switch d.Network {
106	case Network_TCP:
107		prefix = "tcp:"
108	case Network_UDP:
109		prefix = "udp:"
110	case Network_UNIX:
111		prefix = "unix:"
112	}
113	return prefix + d.NetAddr()
114}
115
116// IsValid returns true if this Destination is valid.
117func (d Destination) IsValid() bool {
118	return d.Network != Network_Unknown
119}
120
121// AsDestination converts current Endpoint into Destination.
122func (p *Endpoint) AsDestination() Destination {
123	return Destination{
124		Network: p.Network,
125		Address: p.Address.AsAddress(),
126		Port:    Port(p.Port),
127	}
128}
129