forked from pion/transport
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
With initial implementations by 'net.StdNet' and 'vnet.Net'. This PR closes pion#34 and clearly separates the virtual network 'vnet.Net' from the code which is using in production. Furthermore this change allows users to provide their own 'net.Net' implementation for reasons like the one described in pion#34.
- Loading branch information
Showing
14 changed files
with
561 additions
and
448 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
package transport | ||
|
||
import ( | ||
"errors" | ||
"net" | ||
) | ||
|
||
var ( | ||
ErrNoAddressAssigned = errors.New("no address assigned") | ||
ErrNotSupported = errors.New("not supported yey") | ||
) | ||
|
||
// Net is an interface providing common networking functions which are | ||
// similar to the functions provided by standard net package. | ||
type Net interface { | ||
// ListenPacket announces on the local network address. | ||
// | ||
// The network must be "udp", "udp4", "udp6", "unixgram", or an IP | ||
// transport. The IP transports are "ip", "ip4", or "ip6" followed by | ||
// a colon and a literal protocol number or a protocol name, as in | ||
// "ip:1" or "ip:icmp". | ||
// | ||
// For UDP and IP networks, if the host in the address parameter is | ||
// empty or a literal unspecified IP address, ListenPacket listens on | ||
// all available IP addresses of the local system except multicast IP | ||
// addresses. | ||
// To only use IPv4, use network "udp4" or "ip4:proto". | ||
// The address can use a host name, but this is not recommended, | ||
// because it will create a listener for at most one of the host's IP | ||
// addresses. | ||
// If the port in the address parameter is empty or "0", as in | ||
// "127.0.0.1:" or "[::1]:0", a port number is automatically chosen. | ||
// The LocalAddr method of PacketConn can be used to discover the | ||
// chosen port. | ||
// | ||
// See func Dial for a description of the network and address | ||
// parameters. | ||
// | ||
// ListenPacket uses context.Background internally; to specify the context, use | ||
// ListenConfig.ListenPacket. | ||
ListenPacket(network string, address string) (net.PacketConn, error) | ||
|
||
// ListenUDP acts like ListenPacket for UDP networks. | ||
// | ||
// The network must be a UDP network name; see func Dial for details. | ||
// | ||
// If the IP field of laddr is nil or an unspecified IP address, | ||
// ListenUDP listens on all available IP addresses of the local system | ||
// except multicast IP addresses. | ||
// If the Port field of laddr is 0, a port number is automatically | ||
// chosen. | ||
ListenUDP(network string, locAddr *net.UDPAddr) (UDPConn, error) | ||
|
||
// | ||
// Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only), | ||
// "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4" | ||
// (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and | ||
// "unixpacket". | ||
// | ||
// For TCP and UDP networks, the address has the form "host:port". | ||
// The host must be a literal IP address, or a host name that can be | ||
// resolved to IP addresses. | ||
// The port must be a literal port number or a service name. | ||
// If the host is a literal IPv6 address it must be enclosed in square | ||
// brackets, as in "[2001:db8::1]:80" or "[fe80::1%zone]:80". | ||
// The zone specifies the scope of the literal IPv6 address as defined | ||
// in RFC 4007. | ||
// The functions JoinHostPort and SplitHostPort manipulate a pair of | ||
// host and port in this form. | ||
// When using TCP, and the host resolves to multiple IP addresses, | ||
// Dial will try each IP address in order until one succeeds. | ||
// | ||
// Examples: | ||
// | ||
// Dial("tcp", "golang.org:http") | ||
// Dial("tcp", "192.0.2.1:http") | ||
// Dial("tcp", "198.51.100.1:80") | ||
// Dial("udp", "[2001:db8::1]:domain") | ||
// Dial("udp", "[fe80::1%lo0]:53") | ||
// Dial("tcp", ":80") | ||
// | ||
// For IP networks, the network must be "ip", "ip4" or "ip6" followed | ||
// by a colon and a literal protocol number or a protocol name, and | ||
// the address has the form "host". The host must be a literal IP | ||
// address or a literal IPv6 address with zone. | ||
// It depends on each operating system how the operating system | ||
// behaves with a non-well known protocol number such as "0" or "255". | ||
// | ||
// Examples: | ||
// | ||
// Dial("ip4:1", "192.0.2.1") | ||
// Dial("ip6:ipv6-icmp", "2001:db8::1") | ||
// Dial("ip6:58", "fe80::1%lo0") | ||
// | ||
// For TCP, UDP and IP networks, if the host is empty or a literal | ||
// unspecified IP address, as in ":80", "0.0.0.0:80" or "[::]:80" for | ||
// TCP and UDP, "", "0.0.0.0" or "::" for IP, the local system is | ||
// assumed. | ||
// | ||
// For Unix networks, the address must be a file system path. | ||
Dial(network, address string) (net.Conn, error) | ||
|
||
// DialUDP acts like Dial for UDP networks. | ||
// | ||
// The network must be a UDP network name; see func Dial for details. | ||
// | ||
// If laddr is nil, a local address is automatically chosen. | ||
// If the IP field of raddr is nil or an unspecified IP address, the | ||
// local system is assumed. | ||
DialUDP(network string, laddr, raddr *net.UDPAddr) (UDPConn, error) | ||
|
||
// | ||
// The network must be a UDP network name. | ||
// | ||
// If the host in the address parameter is not a literal IP address or | ||
// the port is not a literal port number, ResolveUDPAddr resolves the | ||
// address to an address of UDP end point. | ||
// Otherwise, it parses the address as a pair of literal IP address | ||
// and port number. | ||
// The address parameter can use a host name, but this is not | ||
// recommended, because it will return at most one of the host name's | ||
// IP addresses. | ||
// | ||
// See func Dial for a description of the network and address | ||
// parameters. | ||
ResolveUDPAddr(network, address string) (*net.UDPAddr, error) | ||
|
||
// Interfaces returns a list of the system's network interfaces. | ||
Interfaces() ([]*Interface, error) | ||
|
||
// The following functions are extensions to Go's standard net package | ||
|
||
CreateDialer(dialer *net.Dialer) Dialer | ||
} | ||
|
||
// Dialer is identical to net.Dialer excepts that its methods | ||
// (Dial, DialContext) are overridden to use the Net interface. | ||
// Use vnet.CreateDialer() to create an instance of this Dialer. | ||
type Dialer interface { | ||
Dial(network, address string) (net.Conn, error) | ||
} | ||
|
||
// UDPConn is packet-oriented connection for UDP. | ||
type UDPConn interface { | ||
net.Conn | ||
net.PacketConn | ||
} | ||
|
||
type Interface struct { | ||
net.Interface | ||
addrs []net.Addr | ||
} | ||
|
||
// NewInterface creates a new interface based of a standard net.Interface | ||
func NewInterface(ifc net.Interface) *Interface { | ||
return &Interface{ | ||
Interface: ifc, | ||
addrs: nil, | ||
} | ||
} | ||
|
||
// AddAddress adds a new address to the interface | ||
func (ifc *Interface) AddAddress(addr net.Addr) { | ||
ifc.addrs = append(ifc.addrs, addr) | ||
} | ||
|
||
// Addresses returns a slice of configured addresses on the interface | ||
func (ifc *Interface) Addresses() ([]net.Addr, error) { | ||
if len(ifc.addrs) == 0 { | ||
return nil, ErrNoAddressAssigned | ||
} | ||
return ifc.addrs, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package stdnet | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
|
||
"github.com/pion/transport" | ||
) | ||
|
||
const ( | ||
lo0String = "lo0String" | ||
udpString = "udp" | ||
) | ||
|
||
// Net is an implementation of the net.Net interface | ||
// based on functions of the standard net package. | ||
type Net struct { | ||
interfaces []*transport.Interface | ||
} | ||
|
||
// NewStdNet creates a new StdNet instance. | ||
func NewNet() (*Net, error) { | ||
n := &Net{} | ||
|
||
return n, n.UpdateInterfaces() | ||
} | ||
|
||
// Compile-time assertion | ||
var _ transport.Net = &Net{} | ||
|
||
// UpdateInterfaces updates the internal list of network interfaces | ||
// and associated addresses. | ||
func (n *Net) UpdateInterfaces() error { | ||
ifs := []*transport.Interface{} | ||
|
||
oifs, err := net.Interfaces() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for _, oif := range oifs { | ||
ifc := transport.NewInterface(oif) | ||
|
||
addrs, err := oif.Addrs() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for _, addr := range addrs { | ||
ifc.AddAddress(addr) | ||
} | ||
|
||
ifs = append(ifs, ifc) | ||
} | ||
|
||
n.interfaces = ifs | ||
|
||
return nil | ||
} | ||
|
||
// Interfaces returns a slice of interfaces which are available on the | ||
// system | ||
func (n *Net) Interfaces() ([]*transport.Interface, error) { | ||
return n.interfaces, nil | ||
} | ||
|
||
// InterfaceByName returns the interface specified by name. | ||
func (n *Net) InterfaceByName(name string) (*transport.Interface, error) { | ||
for _, ifc := range n.interfaces { | ||
if ifc.Name == name { | ||
return ifc, nil | ||
} | ||
} | ||
|
||
return nil, fmt.Errorf("interface %s not found", name) | ||
} | ||
|
||
// ListenPacket announces on the local network address. | ||
func (n *Net) ListenPacket(network string, address string) (net.PacketConn, error) { | ||
return net.ListenPacket(network, address) | ||
} | ||
|
||
// ListenUDP acts like ListenPacket for UDP networks. | ||
func (n *Net) ListenUDP(network string, locAddr *net.UDPAddr) (transport.UDPConn, error) { | ||
return net.ListenUDP(network, locAddr) | ||
} | ||
|
||
// Dial connects to the address on the named network. | ||
func (n *Net) Dial(network, address string) (net.Conn, error) { | ||
return net.Dial(network, address) | ||
} | ||
|
||
// DialUDP acts like Dial for UDP networks. | ||
func (n *Net) DialUDP(network string, laddr, raddr *net.UDPAddr) (transport.UDPConn, error) { | ||
return net.DialUDP(network, laddr, raddr) | ||
} | ||
|
||
// ResolveIPAddr returns an address of IP end point. | ||
func (n *Net) ResolveIPAddr(network, address string) (*net.IPAddr, error) { | ||
return net.ResolveIPAddr(network, address) | ||
} | ||
|
||
// ResolveUDPAddr returns an address of UDP end point. | ||
func (n *Net) ResolveUDPAddr(network, address string) (*net.UDPAddr, error) { | ||
return net.ResolveUDPAddr(network, address) | ||
} | ||
|
||
*net.Dialer | ||
} | ||
|
||
func (d stdDialer) Dial(network, address string) (net.Conn, error) { | ||
return d.Dialer.Dial(network, address) | ||
} | ||
|
||
// CreateDialer creates an instance of vnet.Dialer | ||
func (n *Net) CreateDialer(d *net.Dialer) transport.Dialer { | ||
return stdDialer{d} | ||
} |
Oops, something went wrong.