7 #include <satcat5/ip_dispatch.h>
13 using satcat5::ip::ADDR_NONE;
20 TYPE_IGMP(satcat5::ip::PROTO_IGMP);
23 static constexpr u32 TIMER_INTERVAL_MSEC = 10;
29 const unsigned wcount, u16* data)
34 if (!SATCAT5_IGMP_ENABLE)
return false;
41 data[1] = satcat5::ip::checksum(wcount, data);
45 satcat5::eth::MACADDR_BROADCAST, satcat5::eth::ETYPE_IPV4);
46 if (!wr)
return false;
50 satcat5::ip::PROTO_IGMP, dst, 2*wcount, 1);
55 for (
unsigned a = 0 ; a < wcount ; ++a)
56 wr->write_u16(data[a]);
62 if (!hdr)
return 10000;
63 if (hdr < 128 || !v3)
return 100*hdr;
64 u16 mant = (hdr & 0x0F) + 16;
65 u16 expn = (hdr & 0x70) >> 4;
66 return u32(100 * mant) << (expn + 3);
69 #if SATCAT5_IGMP_ENABLE
82 #if SATCAT5_ALLOW_DELETION
93 obj.m_igmp_group = addr;
98 obj.m_igmp_timer = prng.
next(1, 1000);
104 if (obj.m_igmp_group == ADDR_NONE)
return;
106 if (m_version > 1) send_leave(obj.m_igmp_group);
109 obj.m_igmp_group = ADDR_NONE;
121 rcvd[wcount++] = src.read_u16();
122 u16 chk = satcat5::ip::checksum(wcount, rcvd);
128 Addr addr(rcvd[2], rcvd[3]);
136 }
else if (wcount == 4) {
143 if (addr != ADDR_NONE) {
145 auto match = find_match(addr);
146 if (match) set_timer(match->m_igmp_timer, max_dly);
147 }
else if (m_version == 3) {
149 set_timer(m_reply_timer, max_dly);
152 Address* item = m_groups.head();
154 set_timer(item->m_igmp_timer, max_dly);
155 item = m_groups.
next(item);
161 auto match = find_match(addr);
162 if (match) match->m_igmp_timer = 0;
168 if (countdown(m_reply_timer, TIMER_INTERVAL_MSEC)) {
169 send_report(ADDR_NONE);
172 Address* item = m_groups.head();
174 if (countdown(item->m_igmp_timer, TIMER_INTERVAL_MSEC)) {
175 send_report(item->m_igmp_group);
177 item = m_groups.
next(item);
181 Address* Client::find_match(
const Addr& group)
const {
182 Address* item = m_groups.head();
183 while (item && item->m_igmp_group != group) {
184 item = m_groups.
next(item);
189 void Client::send_leave(
const Addr& group) {
190 u16 msg[MIN_LEN_SHORTS];
192 msg[wcount++] = TYPE_LEAVE_V2;
194 msg[wcount++] = u16(group.
value >> 16);
195 msg[wcount++] = u16(group.
value >> 0);
196 igmp_send(m_iface, DST_ALL_ROUTERS, wcount, msg);
199 void Client::send_report(
const Addr& group) {
202 if (m_version == 1) {
206 msg[wcount++] = u16(group.
value >> 16);
207 msg[wcount++] = u16(group.
value >> 0);
209 }
else if (m_version == 2) {
213 msg[wcount++] = u16(group.
value >> 16);
214 msg[wcount++] = u16(group.
value >> 0);
222 msg[wcount++] = u16(len);
224 Address* item = m_groups.head();
225 for (
unsigned a = 0 ; item && a < len ; ++a) {
228 msg[wcount++] = u16(item->m_igmp_group.
value >> 16);
229 msg[wcount++] = u16(item->m_igmp_group.
value >> 0);
230 item = m_groups.
next(item);
232 igmp_send(m_iface, DST_IGMPV3_REPORT, wcount, msg);
236 void Client::set_timer(u32& timer, u32 max_msec) {
238 u32 new_dly =
prng.
next(1, max_msec);
239 if (new_dly < timer || !timer) timer = new_dly;
satcat5::io::Writeable * open_write(const satcat5::eth::MacAddr &dst, const satcat5::eth::MacType &type, satcat5::eth::VlanTag vtag=satcat5::eth::VTAG_NONE)
Send a frame to the designated Ethernet address/VLAN.
Host/Client for the Internet Group Management Protocol (IGMP).
Client(satcat5::ip::Dispatch *iface)
Link this handler to an IPv4 network interface.
void join(satcat5::igmp::Address &obj, const satcat5::ip::Addr &addr)
Join a multicast group.
void timer_event() override
Child class MUST override this method.
void frame_rcvd(satcat5::io::LimitedRead &src) override
Dispatch calls frame_rcvd(...) for each incoming frame with with a matching net::Type value.
void leave(satcat5::igmp::Address &obj)
Leave a multicast group.
Limited read of next N bytes.
unsigned get_read_ready() const override
How many bytes can be read without blocking?
Abstract API for writing byte-streams and packets.
virtual bool write_finalize()
Mark end of frame and release temporary working data.
Protocol handler and dispatch unit for Internet Protocol v4 (IPv4).
satcat5::ip::Header next_header(u8 protocol, const satcat5::ip::Addr &dst, unsigned inner_bytes, u8 ttl=SATCAT5_IP_TTL)
Create a basic IPv4 header with the specified information.
void add(satcat5::net::Protocol *proto)
Register a Protocol object.
void remove(satcat5::net::Protocol *proto)
Unregister a Protocol object.
void timer_every(unsigned msec)
Configure a repeating notification every X milliseconds.
unsigned len() const
Traverse the linked list to count its length.
T * next(const T *item) const
Fetch pointer to the next item.
void add_safe(T *item)
Check if list already contains item before adding.
bool is_empty() const
Is this list empty?
void remove(T *item)
Remove the designated item from the list.
u32 next()
Range [0..2^32)
Client-side implementation of the Internet Group Management Protocol (IGMP)
constexpr unsigned MIN_LEN_SHORTS
Set upper and lower bounds for the length of an IGMP message.
constexpr unsigned MAX_LEN_SHORTS
Set upper and lower bounds for the length of an IGMP message.
constexpr u16 TYPE_REPORT_V3
Reply to IGMPv3 query.
constexpr unsigned MIN_LEN_BYTES
Set upper and lower bounds for the length of an IGMP message.
constexpr unsigned MAX_LEN_BYTES
Set upper and lower bounds for the length of an IGMP message.
constexpr u16 TYPE_REPORT_V1
Reply to IGMPv1 query.
constexpr u16 MASK_MAXLEN
Bit-mask "length" from first header word.
constexpr u16 RECORD_MODE_EXCL
Record type: Exclude mode.
u32 decode_maxdly(u16 hdr, bool v3)
Given the first word of the IGMP query header, decode max delay.
constexpr u16 TYPE_REPORT_V2
Reply to IGMPv2 query.
bool igmp_send(satcat5::ip::Dispatch *iface, const satcat5::ip::Addr &dst, const unsigned wcount, u16 *data)
Given IGMP message contents, write Eth/IP headers and send packet.
constexpr u16 TYPE_QUERY
IGMP query (all versions)
constexpr u16 MASK_TYPE
Bit-mask "type" from first header word.
Client state for an IGMP multicast subscription.
IPv4 address is a 32-bit unsigned integer.
u32 value
Raw access to the underlying representation.
bool is_multicast() const
IP multicast (224.*.*.*)
bool is_broadcast() const
Limited broadcast (255.255.255.255)
Multipurpose filter for matching fields in network packets.
Miscellaneous mathematical utility functions.
constexpr unsigned min_unsigned(unsigned a, unsigned b)
Min and max functions.
bool countdown(T &timer, const T &decr)
Decrement a countdown timer, returning true if it reaches zero.
satcat5::util::Prng prng
Global instance of the Prng class.