Documentation
¶
Index ¶
- func FilterIPv4(addrs []netip.Addr) (ret []netip.Addr)
- func FilterIPv6(addrs []netip.Addr) (ret []netip.Addr)
- func GetAddressesForInterface(name string) ([]netip.Addr, error)
- type IP
- type InterfaceName
- type SourceIP
- type Stats
- func (s *Stats) AsyncImmediateReads() int
- func (s *Stats) AsyncImmediateWrites() int
- func (s *Stats) AsyncReadPerf() float64
- func (s *Stats) AsyncScheduledReads() int
- func (s *Stats) AsyncScheduledWrites() int
- func (s *Stats) AsyncTotalReads() int
- func (s *Stats) AsyncTotalWrites() int
- func (s *Stats) Reset()
- type UDPPeer
- func (p *UDPPeer) All() bool
- func (p *UDPPeer) AsyncRead(b []byte, fn func(error, int, netip.AddrPort))
- func (p *UDPPeer) AsyncWrite(b []byte, addr netip.AddrPort, fn func(error, int))
- func (p *UDPPeer) BlockSource(multicastIP IP, sourceIP SourceIP) error
- func (p *UDPPeer) Close() error
- func (p *UDPPeer) Closed() bool
- func (p *UDPPeer) Inbound() *net.Interface
- func (p *UDPPeer) Join(multicastIP IP) error
- func (p *UDPPeer) JoinOn(multicastIP IP, interfaceName InterfaceName) error
- func (p *UDPPeer) JoinSource(multicastIP IP, sourceIP SourceIP) error
- func (p *UDPPeer) JoinSourceOn(multicastIP IP, sourceIP SourceIP, interfaceName InterfaceName) error
- func (p *UDPPeer) Leave(multicastIP IP) error
- func (p *UDPPeer) LeaveSource(multicastIP IP, sourceIP SourceIP) error
- func (p *UDPPeer) LocalAddr() *net.UDPAddr
- func (p *UDPPeer) Loop() bool
- func (p *UDPPeer) NextLayer() *sonic.Socket
- func (p *UDPPeer) Outbound() (*net.Interface, netip.Addr)
- func (p *UDPPeer) Read(b []byte) (int, netip.AddrPort, error)
- func (p *UDPPeer) SetAll(all bool) error
- func (p *UDPPeer) SetAsyncReadBuffer(to []byte)
- func (p *UDPPeer) SetInbound(interfaceName string) (err error)
- func (p *UDPPeer) SetLoop(loop bool) error
- func (p *UDPPeer) SetOutboundIPv4(interfaceName string) error
- func (p *UDPPeer) SetOutboundIPv6(interfaceName string) error
- func (p *UDPPeer) SetTTL(ttl uint8) error
- func (p *UDPPeer) Stats() *Stats
- func (p *UDPPeer) TTL() uint8
- func (p *UDPPeer) UnblockSource(multicastIP IP, sourceIP SourceIP) error
- func (p *UDPPeer) Write(b []byte, addr netip.AddrPort) (int, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type InterfaceName ¶
type InterfaceName string
type Stats ¶
type Stats struct {
// contains filtered or unexported fields
}
func (*Stats) AsyncImmediateReads ¶
func (*Stats) AsyncImmediateWrites ¶
func (*Stats) AsyncReadPerf ¶
AsyncReadPerf gives an indication of the async read performance of the peer. Higher is better, and indicates that less syscalls have been made.
In the limit: - 0.0 means that all reads have passed through the reactor, hence none were done immediately. - 1.0 means that none of the reads have passed through the reactor and were hence done immediately.
func (*Stats) AsyncScheduledReads ¶
func (*Stats) AsyncScheduledWrites ¶
func (*Stats) AsyncTotalReads ¶
func (*Stats) AsyncTotalWrites ¶
type UDPPeer ¶
type UDPPeer struct {
// contains filtered or unexported fields
}
func NewUDPPeer ¶
NewUDPPeer creates a new UDPPeer capable of reading/writing multicast packets on a network interface.
`network` must be one of: "udp", "udp4", "udp6". "udp" resolves to "udp4". 4 means IPv4. 6 means IPv6.
`addr` must be `"<ip>:<port>"`. `<ip>` can be one of:
"": in this case the peer will be bound to all local interfaces i.e. `INADDR_ANY`. This means the underlying socket will receive datagrams from any groups that have been joined with `Join`, `JoinOn`, `JoinSource` and `JoinSourceOn` and that deliver to `<port>`. This is the most permissive IP address.
"<some_multicast_ip>": only traffic originating from <some_multicast_ip>:<port> will be received by this peer. Any other traffic originating from another <multicast_ip>:<port> will be ignored, even if you `Join` that other <multicast_ip>.
"<interface_ip_address>": this binds the underlying socket to the IP address owned by one of the host's network interfaces. Reads and writer will only be done from that interface.
A few examples: - If you want to only receive data from 224.0.1.0:1234, then: - NewUDPPeer(ioc, "udp", "224:0.1.0:1234") and then Join("224.0.1.0"). Without the Join, you will get no data.
- If you want to only receive data from a specific interface from 224.0.1.0:1234 then: NewUDPPeer(ioc, "udp", "224:0.1.0:1234") and then JoinOn("224.0.1.0", "eth0") where "eth0" is the interface name.
- If there are multiple hosts publishing to multicast group 224.0.1.0:1234, and you only want to receive data from the host with IP 192.168.1.1 then: NewUDPPeer(ioc, "udp", "224:0.1.0:1234"), then JoinSource("224.0.1.0", "192.168.1.1").
- If there are multiple hosts publishing to multicast group 224.0.1.0:1234, and you want to receive data from all but not the one with IP 192.168.1.1, then: NewUDPPeer(ioc, "udp", "224:0.1.0:1234"), then Join("224.0.1.0"), BlockSource("192.168.1.1").
The above examples should cover everything you need to write a decent multicast app.
Note that multiple UDPPeers can share the same addr. We set ReusePort on the socket before binding it.
Note that a peer's port must match the multicast group ports that it wants to join. In other words, if an exchange tells you it publishes to 224.0.25.108:14326, you must call either NewUDPPeer(ioc, "udp", ":14326") or NewUDPPeer(ioc, "udp", "224.0.25.108:14326"). Putting anything other than "14326" as a port will make it such that your Peer won't receive any data, even though it joined "224.0.25.108".
General note: binding to 0.0.0.0 means telling the TCP/IP layer to use all available interfaces for listening and choose the best interface for sending.
Multicast addresses map directly to MAC addresses. Hence, multicast needs direct hardware support. A network interface usually only listens to ethernet frames destined for its own MAC address. Telling a network interface to join a group means telling it to also listen to frames destined to the unique MAC mapping of that multicast IP.
Joining a multicast group means that all multicast traffic for all ports on that multicast IP will be received by your network interface. However, only the traffic destined to your binded listening port will get passed up the TCP/IP stack and into your process. Remember, multicast is an IP thing, ports is a transport (TCP/UDP) thing.
When sending multicast traffic, you should either bind the peer to 0.0.0.0 or to an interface's address. Find those with `ip addr`.
Note that there are certain semantics tied to certain multicast address ranges (https://www.rfc-editor.org/rfc/rfc5771). For example: - 224.0.0.0 to 224.0.0.255 are not routable, so packets sent to these groups will only reach hosts at most 1 link away. So packets won't be forwarded by routers. - 224.0.1.0 to 224.0.1.255 are fully routable That means that your choice of multicast IP matters, expecially if you're going to write to it. For example, let's assume you make both a writer and a reader in the same process and SetLoop(true) is set (it is by default): - if the multicast IP is in 224.0.0/24 (first case above), the reader will receive the packets once. SetLoop(true) ensures the reader gets the packets. - if the multicast IP is in 224.0.1/24 (second case above), the reader will receive each packet twice. Once from SetLoop(true) and once from the router. Your network router sees the packets sent by the writer and destined to a routable multicast IP coming in and it routes them back to your machine.
func (*UDPPeer) AsyncWrite ¶
func (*UDPPeer) BlockSource ¶
BlockSource Makes it such that any data originating from unicast IP sourceIP is not going to be received anymore after joining the multicastIP with Join, JoinOn, JoinSource or JoinSourceOn.
func (*UDPPeer) Inbound ¶
Inbound returns the interface set with SetInbound(...). If none was set, it returns nil.
func (*UDPPeer) Join ¶
Join a multicast group IP in order to receive data. Since no interface is specified, the system uses a default. To receive multicast packets from a group on a specific interface, use JoinOn.
The argument multicastIP must be an IP address. It must not have a port in it. See the Note above NewUDPPeer for more information.
Joining an already joined IP will return EADDRINUSE.
func (*UDPPeer) JoinOn ¶
func (p *UDPPeer) JoinOn(multicastIP IP, interfaceName InterfaceName) error
JoinOn a specific interface.
func (*UDPPeer) JoinSource ¶
JoinSource on any interface. This makes it such that you only receive data from the unicast IP sourceIP, even though multiple sourceIPs can send that to the same group.
func (*UDPPeer) JoinSourceOn ¶
func (p *UDPPeer) JoinSourceOn( multicastIP IP, sourceIP SourceIP, interfaceName InterfaceName, ) error
JoinSourceOn combines JoinSource with JoinOn.
func (*UDPPeer) Leave ¶
Leave Leaves the multicast group Join or JoinOn.
Note that this operation might take some time, potentially minutes, to be fulfilled. This is all NIC/switch/router dependent, there is nothing you can do about it on the application layer.
func (*UDPPeer) LeaveSource ¶
LeaveSource Leaves the multicast group joined with JoinSource or JoinSourceOn.
Note that this operation might take some time, potentially minutes, to be fulfilled. This is all NIC/switch/router dependent, there is nothing you can do about it on the application layer.
func (*UDPPeer) LocalAddr ¶
LocalAddr of the peer. Note that the IP can be zero if addr is empty in NewUDPPeer.
func (*UDPPeer) Outbound ¶
Outbound returns the interface with which packets are sent to a multicast group in calls to Write(...) or AsyncWrite(...).
If SetOutboundIPv4 or SetOuboundIPv6 have not been called before Outbound(), the returned interface will be nil and the IP will be 0.0.0.0.
func (*UDPPeer) SetAll ¶
SetAll is Linux only. If true, all UDPPeer's bound to IP 0.0.0.0 i.e. INADDR_ANY will receive all multicast packets from a group that was joined by another UDPPeer. Even though this is true in Linux by default, we set it to false in NewUDPPeer. Multicast should be opt-in, not opt-out. This flag does not exist on BSD systems.
Example: two readers, both on 0.0.0.0:1234 (Note that binding two sockets on the same addr+port is allowed since we mark sockets with ReusePort in NewUDPPeer). Reader 1 joins 224.0.1.0. Now you would expect only reader 1 to get datagrams, but reader 2 gets datagrams as well. This is only on Linux. On BSD, only reader 1 gets datagrams.
func (*UDPPeer) SetAsyncReadBuffer ¶
func (*UDPPeer) SetInbound ¶
SetInbound Specify that you only want to receive data from the specified interface.
Warning: this might not work on all hosts and interfaces. Instead, you should use JoinOn(multicastGroup, interfaceName).
func (*UDPPeer) SetLoop ¶
SetLoop If true, multicast packets sent on one host are looped back to readers on the same host. This should be the default.
Use `sysctl net.inet.ip.mcast.loop` to see what is the default on BSD/Linux.
Having this set to true, which is the default, makes it easy to write multicast tests on a single host. Anything you write to a multicast group will be made available to receivers that joined that multicast group.
func (*UDPPeer) SetOutboundIPv4 ¶
SetOutboundIPv4 sets the interface on which packets are sent by this peer to an IPv4 multicast group.
This means Write(...) and AsyncWrite(...) will use the specified interface to send packets to the multicast group.
func (*UDPPeer) SetOutboundIPv6 ¶
SetOutboundIPv6 sets the interface on which packets are sent by this peer to an IPv6 multicast group.
This means Write(...) and AsyncWrite(...) will use the specified interface to send packets to the multicast group.
func (*UDPPeer) SetTTL ¶
SetTTL Sets the time-to-live of udp multicast datagrams. The TTL is 1 by default.
A TTL of 1 prevents datagrams from being forwarded beyond the local network. Acceptable values are in the range [0, 255]. It is up to the caller to make sure the uint8 arg does not overflow.
func (*UDPPeer) UnblockSource ¶
UnblockSource undoes BlockSource.