IGMPv2 (RFC 2236) message encoding and decoding.

An IGMPv2 message is a fixed 8-byte structure — there is no variable-length trailer:

 0      7 8     15 16    23 24    31
+--------+--------+--------+--------+
|  Type  | MaxResp|    Checksum     |
+--------+--------+--------+--------+
|            Group Address          |
+-----------------------------------+

maxResponseTime is only meaningful on Membership Query messages (type === IGMP_TYPE.MEMBERSHIP_QUERY); other message types set it to 0. groupAddress is 0.0.0.0 for a General Query and the multicast group being queried/reported/left otherwise.

IPv4 addresses are surfaced as raw 32-bit unsigned integers, mirroring how @binstruct/ipv4 and @binstruct/arp expose the same field. Use @hertzg/ip's parseAddressv4 / stringifyAddressv4 for human-readable conversion.

Per the binstruct philosophy, encoding does not auto-compute the checksum. Use internetChecksum from @binstruct/inet after encoding (with the checksum field zeroed) to fill it in.

This coder covers header-level IGMPv2 messages only — IGMPv1/v3 framing and the variable-length group-record trailer of IGMPv3 are out of scope.

Examples

Round-trip a v2 Membership Report

import { assertEquals } from "@std/assert";
import { IGMP_TYPE, igmpMessage } from "@binstruct/igmp";

const coder = igmpMessage();
const message = {
  type: IGMP_TYPE.V2_MEMBERSHIP_REPORT,
  maxResponseTime: 0,
  checksum: 0,
  groupAddress: 0xe0000001,
};

const buffer = new Uint8Array(8);
const written = coder.encode(message, buffer);
const [decoded, read] = coder.decode(buffer);

assertEquals(written, 8);
assertEquals(read, 8);
assertEquals(decoded, message);