private void ParseHeader(RawDGram p, int len)
        {
            Console.WriteLine("Parsing Header");
            IPHeader header = new IPHeader(p.rawBytes, len);

            switch (header.ProtocolType)
            {
            case Protocol.ICMP:
                ICMPHeader icmpHeader = new ICMPHeader(header.Data, header.MessageLength);
                //Console.WriteLine(String.Format("ICMP type: {0} code: {1}", icmpHeader.Type, icmpHeader.Code));
                if (icmpHeader.Type == ICMPHeader.ICMPTypes.DestinationUnreachable && icmpHeader.Code == 3)
                {
                    //Binary search the MTU (this is used during the probe phase of some congestion control
                    //algorithms. Also, the initial congestion window should be calculated in terms of bytes i.e. (mtu/windowsize = packets)
                }
                break;

            case Protocol.TCP:
                //Console.WriteLine("TCP packet received");
                break;

            case Protocol.UDP:
                UDPHeader udpHeader = new UDPHeader(header.Data, header.MessageLength);
                HandleUDP(header, udpHeader);
                break;

            case Protocol.Unknown:
                //Console.WriteLine("Unknown packet received");
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
        private void OnPacketRecieved(IAsyncResult ar)
        {
            Console.WriteLine("Data received");
            RawDGram p   = (RawDGram)ar.AsyncState;
            int      len = socket.EndReceiveFrom(ar, ref p.sender);

            readerEvent.Set();
            //this can be pushed off to a task or threadpool
            ParseHeader(p, len);
        }
        private void StartRecievingPackets()
        {
            byte[] byTrue = new byte[4] {
                1, 0, 0, 0
            };
            byte[] byOut = new byte[4];
            this.socket.IOControl(IOControlCode.ReceiveAll, byTrue, byOut);

            while (this.isOn)
            {
                Console.WriteLine("Entering receive loop");
                readerEvent.Reset();
                RawDGram p = new RawDGram(this.mtu, ep);
                socket.BeginReceiveFrom(p.rawBytes,
                                        0,
                                        p.rawBytes.Length,
                                        SocketFlags.None,
                                        ref p.sender,
                                        new AsyncCallback(OnPacketRecieved),
                                        p);
                readerEvent.WaitOne();
            }
        }