// $Id: IGMPPacket.cs,v 1.1.1.1 2007/07/03 10:15:17 tamirgal Exp $

/// <summary>************************************************************************
/// Copyright (C) 2001, Patrick Charles and Jonas Lehmann                   *
/// Distributed under the Mozilla Public License                            *
/// http://www.mozilla.org/NPL/MPL-1.1.txt                                *
/// *************************************************************************
/// </summary>
using System;
//UPGRADE_TODO: The type 'Tamir.IPLib.Packets.Util.AnsiEscapeSequences_Fields' could not be found. If it was not included in the conversion, there may be compiler issues. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1262'"
using AnsiEscapeSequences_Fields = Tamir.IPLib.Packets.Util.AnsiEscapeSequences_Fields;
//UPGRADE_TODO: The type 'Tamir.IPLib.Packets.Util.ArrayHelper' could not be found. If it was not included in the conversion, there may be compiler issues. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1262'"
using ArrayHelper = Tamir.IPLib.Packets.Util.ArrayHelper;
//UPGRADE_TODO: The type 'Tamir.IPLib.Packets.Util.Timeval' could not be found. If it was not included in the conversion, there may be compiler issues. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1262'"
using Timeval = Tamir.IPLib.Packets.Util.Timeval;
using Tamir.IPLib.Packets.Util;

namespace Tamir.IPLib.Packets
{


	/// <summary> An IGMP packet.
	/// <p>
	/// Extends an IP packet, adding an IGMP header and IGMP data payload.
	/// 
	/// </summary>
	/// <author>  Patrick Charles and Jonas Lehmann
	/// </author>
	/// <version>  $Revision: 1.1.1.1 $
	/// </version>
	/// <lastModifiedBy>  $Author: tamirgal $ </lastModifiedBy>
	/// <lastModifiedAt>  $Date: 2007/07/03 10:15:17 $ </lastModifiedAt>
	[Serializable]
	public class IGMPPacket : IPPacket, IGMPFields
	{
		/// <summary> Fetch the IGMP header a byte array.</summary>
		virtual public byte[] IGMPHeader
		{
			get
			{
				if (_igmpHeaderBytes == null)
				{
					_igmpHeaderBytes = PacketEncoding.extractHeader(_ethOffset, IGMPFields_Fields.IGMP_HEADER_LEN, _bytes);
				}
				return _igmpHeaderBytes;
			}

		}
		/// <summary> Fetch the IGMP header as a byte array.</summary>
		override public byte[] Header
		{
			get
			{
				return IGMPHeader;
			}

		}
		/// <summary> Fetch the IGMP data as a byte array.</summary>
		virtual public byte[] IGMPData
		{
			get
			{
				if (_igmpDataBytes == null)
				{
					// set data length based on info in headers (note: tcpdump
					//  can return extra junk bytes which bubble up to here
					int dataLen = _bytes.Length - _ethOffset - IGMPFields_Fields.IGMP_HEADER_LEN;

					_igmpDataBytes = PacketEncoding.extractData(_ethOffset, IGMPFields_Fields.IGMP_HEADER_LEN, _bytes, dataLen);
				}
				return _igmpDataBytes;
			}

		}
		/// <summary> Fetch the IGMP message type, including subcode. Return value can be 
		/// used with IGMPMessage.getDescription().
		/// </summary>
		/// <returns> a 2-byte value containing the message type in the high byte
		/// and the message type subcode in the low byte.
		/// </returns>
		virtual public int MessageType
		{
			get
			{
				return ArrayHelper.extractInteger(_bytes, _ipOffset + IGMPFields_Fields.IGMP_CODE_POS, IGMPFields_Fields.IGMP_CODE_LEN);
			}

		}
		/// <summary> Fetch the IGMP max response time.</summary>
		virtual public int MaxResponseTime
		{
			get
			{
				return ArrayHelper.extractInteger(_bytes, _ipOffset + IGMPFields_Fields.IGMP_MRSP_POS, IGMPFields_Fields.IGMP_MRSP_LEN);
			}

		}
		/// <summary> Fetch the IGMP header checksum.</summary>
		virtual public int IGMPChecksum
		{
			get
			{
				return ArrayHelper.extractInteger(_bytes, _ipOffset + IGMPFields_Fields.IGMP_CSUM_POS, IGMPFields_Fields.IGMP_CSUM_LEN);
			}

		}
		/// <summary> Fetch the IGMP group address.</summary>
		virtual public System.String GroupAddress
		{
			get
			{
				return IPAddress.extract(_ipOffset + IGMPFields_Fields.IGMP_GADDR_POS, _bytes);
			}

		}
		/// <summary> Fetch ascii escape sequence of the color associated with this packet type.</summary>
		override public System.String Color
		{
			get
			{
				return AnsiEscapeSequences_Fields.BROWN;
			}

		}
		public IGMPPacket(int lLen, byte[] bytes)
			: base(lLen, bytes)
		{
		}

		public IGMPPacket(int lLen, byte[] bytes, Timeval tv)
			: this(lLen, bytes)
		{
			this._timeval = tv;
		}

		private byte[] _igmpHeaderBytes = null;

		private byte[] _igmpDataBytes = null;

		/// <summary> Fetch the IGMP data as a byte array.</summary>
		public override byte[] Data
		{
			get
			{
				return IGMPData;
			}
		}

		/// <summary> Fetch the IGMP header checksum.</summary>
		public override int Checksum
		{
			get
			{
				return IGMPChecksum;
			}
		}


		/// <summary> Convert this IGMP packet to a readable string.</summary>
		public override System.String ToString()
		{
			return ToColoredString(false);
		}

		/// <summary> Generate string with contents describing this IGMP packet.</summary>
		/// <param name="colored">whether or not the string should contain ansi
		/// color escape sequences.
		/// </param>
		public override System.String ToColoredString(bool colored)
		{
			System.Text.StringBuilder buffer = new System.Text.StringBuilder();
			buffer.Append('[');
			if (colored)
				buffer.Append(Color);
			buffer.Append("IGMPPacket");
			if (colored)
				buffer.Append(AnsiEscapeSequences_Fields.RESET);
			buffer.Append(": ");
			buffer.Append(IGMPMessage.getDescription(MessageType));
			buffer.Append(", ");
			buffer.Append(GroupAddress + ": ");
			buffer.Append(SourceAddress + " -> " + DestinationAddress);
			buffer.Append(" l=" + IGMPFields_Fields.IGMP_HEADER_LEN + "," + (_bytes.Length - _ipOffset - IGMPFields_Fields.IGMP_HEADER_LEN));
			buffer.Append(']');

			return buffer.ToString();
		}
	}
}