multicast

package
v0.0.0-...-bda8275 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 31, 2024 License: MIT Imports: 9 Imported by: 0

README

To test:

  • can you call JoinOn on two different interfaces?

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FilterIPv4

func FilterIPv4(addrs []netip.Addr) (ret []netip.Addr)

func FilterIPv6

func FilterIPv6(addrs []netip.Addr) (ret []netip.Addr)

func GetAddressesForInterface

func GetAddressesForInterface(name string) ([]netip.Addr, error)

Types

type IP

type IP string

type InterfaceName

type InterfaceName string

type SourceIP

type SourceIP string

type Stats

type Stats struct {
	// contains filtered or unexported fields
}

func (*Stats) AsyncImmediateReads

func (s *Stats) AsyncImmediateReads() int

func (*Stats) AsyncImmediateWrites

func (s *Stats) AsyncImmediateWrites() int

func (*Stats) AsyncReadPerf

func (s *Stats) AsyncReadPerf() float64

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 (s *Stats) AsyncScheduledReads() int

func (*Stats) AsyncScheduledWrites

func (s *Stats) AsyncScheduledWrites() int

func (*Stats) AsyncTotalReads

func (s *Stats) AsyncTotalReads() int

func (*Stats) AsyncTotalWrites

func (s *Stats) AsyncTotalWrites() int

func (*Stats) Reset

func (s *Stats) Reset()

type UDPPeer

type UDPPeer struct {
	// contains filtered or unexported fields
}

func NewUDPPeer

func NewUDPPeer(ioc *sonic.IO, network string, addr string) (*UDPPeer, error)

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) All

func (p *UDPPeer) All() bool

func (*UDPPeer) AsyncRead

func (p *UDPPeer) AsyncRead(b []byte, fn func(error, int, netip.AddrPort))

func (*UDPPeer) AsyncWrite

func (p *UDPPeer) AsyncWrite(
	b []byte,
	addr netip.AddrPort,
	fn func(error, int),
)

func (*UDPPeer) BlockSource

func (p *UDPPeer) BlockSource(multicastIP IP, sourceIP SourceIP) error

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) Close

func (p *UDPPeer) Close() error

func (*UDPPeer) Closed

func (p *UDPPeer) Closed() bool

func (*UDPPeer) Inbound

func (p *UDPPeer) Inbound() *net.Interface

Inbound returns the interface set with SetInbound(...). If none was set, it returns nil.

func (*UDPPeer) Join

func (p *UDPPeer) Join(multicastIP IP) error

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

func (p *UDPPeer) JoinSource(multicastIP IP, sourceIP SourceIP) error

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

func (p *UDPPeer) Leave(multicastIP IP) error

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

func (p *UDPPeer) LeaveSource(multicastIP IP, sourceIP SourceIP) error

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

func (p *UDPPeer) LocalAddr() *net.UDPAddr

LocalAddr of the peer. Note that the IP can be zero if addr is empty in NewUDPPeer.

func (*UDPPeer) Loop

func (p *UDPPeer) Loop() bool

func (*UDPPeer) NextLayer

func (p *UDPPeer) NextLayer() *sonic.Socket

func (*UDPPeer) Outbound

func (p *UDPPeer) Outbound() (*net.Interface, netip.Addr)

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) Read

func (p *UDPPeer) Read(b []byte) (int, netip.AddrPort, error)

func (*UDPPeer) SetAll

func (p *UDPPeer) SetAll(all bool) error

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 (p *UDPPeer) SetAsyncReadBuffer(to []byte)

func (*UDPPeer) SetInbound

func (p *UDPPeer) SetInbound(interfaceName string) (err error)

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

func (p *UDPPeer) SetLoop(loop bool) error

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

func (p *UDPPeer) SetOutboundIPv4(interfaceName string) error

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

func (p *UDPPeer) SetOutboundIPv6(interfaceName string) error

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

func (p *UDPPeer) SetTTL(ttl uint8) error

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) Stats

func (p *UDPPeer) Stats() *Stats

func (*UDPPeer) TTL

func (p *UDPPeer) TTL() uint8

func (*UDPPeer) UnblockSource

func (p *UDPPeer) UnblockSource(multicastIP IP, sourceIP SourceIP) error

UnblockSource undoes BlockSource.

func (*UDPPeer) Write

func (p *UDPPeer) Write(b []byte, addr netip.AddrPort) (int, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL