/** * Deserialize an IGMP message. * * @param data bytes to deserialize * @param offset offset to start deserializing from * @param length length of the data to deserialize * @return populated IGMP object */ @Override public IPacket deserialize(final byte[] data, final int offset, final int length) { final IGMP igmp; try { igmp = IGMP.deserializer().deserialize(data, offset, length); } catch (DeserializationException e) { log.error("Deserialization exception", e); return this; } this.igmpType = igmp.igmpType; this.resField = igmp.resField; this.checksum = igmp.checksum; this.groups = igmp.groups; return this; }
/** * Deserializer function for IPv4 packets. * * @return deserializer function */ public static Deserializer<IGMP> deserializer() { return (data, offset, length) -> { checkInput(data, offset, length, IGMPv2.HEADER_LENGTH); // we will assume that this is IGMPv2 if the length is 8 boolean isV2 = length == IGMPv2.HEADER_LENGTH; IGMP igmp = isV2 ? new IGMPv2() : new IGMPv3(); final ByteBuffer bb = ByteBuffer.wrap(data, offset, length); igmp.igmpType = bb.get(); igmp.resField = bb.get(); igmp.checksum = bb.getShort(); if (isV2) { igmp.addGroup(new IGMPQuery(IpAddress.valueOf(bb.getInt()), 0)); if (igmp.validChecksum()) { return igmp; } throw new DeserializationException("invalid checksum"); } // second check for IGMPv3 checkInput(data, offset, length, IGMPv3.MINIMUM_HEADER_LEN); String msg; switch (igmp.igmpType) { case TYPE_IGMPV3_MEMBERSHIP_QUERY: IGMPQuery qgroup = new IGMPQuery(); qgroup.deserialize(bb); igmp.groups.add(qgroup); break; case TYPE_IGMPV3_MEMBERSHIP_REPORT: bb.getShort(); // Ignore resvd int ngrps = bb.getShort(); for (; ngrps > 0; ngrps--) { IGMPMembership mgroup = new IGMPMembership(); mgroup.deserialize(bb); igmp.groups.add(mgroup); } break; /* * NOTE: according to the IGMPv3 spec. These previous IGMP type fields * must be supported. At this time we are going to <b>assume</b> we run * in a modern network where all devices are IGMPv3 capable. */ case TYPE_IGMPV1_MEMBERSHIP_REPORT: case TYPE_IGMPV2_MEMBERSHIP_REPORT: case TYPE_IGMPV2_LEAVE_GROUP: igmp.unsupportTypeData = bb.array(); // Is this the entire array? msg = "IGMP message type: " + igmp.igmpType + " is not supported"; igmp.log.debug(msg); break; default: msg = "IGMP message type: " + igmp.igmpType + " is not recognized"; igmp.unsupportTypeData = bb.array(); igmp.log.debug(msg); break; } return igmp; }; }