// event handler for link status changes
        static void nic_OnLinkChangedEvent(ENC28J60Driver sender, DateTime time, bool isUp)
        {
            Debug.WriteLine("Link is now " + (isUp ? "up :)" : "down :("));

            if (isUp && (Adapter.IPAddress == null || !DhcpDisabled))
            {
                PollingTimer.Change(500, 10000);  // Get DHCP addresses now that link is up
            }
            else if (isUp && Adapter.IPAddress != null && DhcpDisabled && Adapter.Gateway != null)
            {
                PollingTimer.Change(500, 10000);  // Get Gateway when setup for static ip and link comes up
            }
            else if (!isUp && !DhcpDisabled)
            {
                // Link is down, so when it comes back up, if we were using DHCP, we want to renew the address.  
                AreRenewing = true;
                PollingTimer.Change(500, 7000);
            }
        }
        // event handler for new ethernet frame arrivals
        static void nic_OnFrameArrived(ENC28J60Driver sender, byte[] frame, DateTime timeReceived)
        {
            //if (buf[0] == 0x01)
            //{
            //    Debug.WriteLine("Probable Multicast Message Detected - " + buf.Length.ToString());
            //    if (buf[29] == 0x65) Debug.WriteLine("IP ending in 101");
            //}

            //if (buf[29] == 0x65)
            //{
            //    Debug.WriteLine("IP ending in 101 - size: " + buf.Length.ToString());

            //    if (buf.Length == 541)
            //        Debug.WriteLine("What is this? ");
            //}

            //var packetID = Guid.NewGuid().ToString();

            if (frame == null) return;

            //Debug.WriteLine("Memory: " + Microsoft.SPOT.Debug.GC(false).ToString() + ", packetID = " + packetID + ", age = " + timeReceived.Subtract(DateTime.Now).Seconds + "s, size = " + frame.Length + ", addys = " + Utility.ExtractRangeFromArray(frame, 0, 14).ToAddress());



            if (frame[13] == 0x06 && frame[12] == 0x08)  // ARP Packet Type
            {
                if (IPAddress != null)
                {
                    // If message request, and IP matches ours, we need to respond!
                    if (frame[41] == IPAddress[3] && frame[40] == IPAddress[2] && frame[39] == IPAddress[1] && frame[38] == IPAddress[0])
                    {
                        ARP.HandlePacket(frame);
                    }
                    else if (frame[21] == 0x02 && frame[31] == IPAddress[3] && frame[30] == IPAddress[2] && frame[29] == IPAddress[1] && frame[28] == IPAddress[0])
                    {
                        Debug.WriteLine("Possible IP Address Conflict Detected");
                        Adapter.Stop();  // IP Address Conflict!
                                         //TODO: if DHCP is enabled, don't stop the networking!  Just reset and get a new IP!!!!
                    }
                }
            }
            else if (frame[13] == 0x00 && frame[12] == 0x08)  // Handle IP packets
            {
                if (frame[23] == 0x01)  // Protocol 1 -- PING
                {
                    // Debug.WriteLine("Received ICMP (Ping) Packet -- " + frame.Length + " bytes");

                    ICMP.HandlePacket(frame);
                }
                else if (frame[23] == 0x11)  // Protocol 17 -- UDP
                {
                    if (frame[37] == 0x44 && !DhcpDisabled && frame[36] == 0x00)  // DHCP port 68  -- Order of conditions to short-circuit earlier!
                    {
                        //Debug.WriteLine("Received DHCP Packet -- " + frame.Length + " bytes");

                        DHCP.HandlePacket(frame);
                    }
                    else if (frame[37] == 0x89 && frame[36] == 0x00 && Name != null && Name != string.Empty && IPAddress != null)  // NetBIOS port 137 and name is set
                    {
                        //Debug.WriteLine("Received NBNS Packet -- " + frame.Length + " bytes");

                        // Uncomment the line below to enable Netbios over TCP Name resolution
                        NetBiosNaming.HandlePacket(frame);
                    }
                    else if (frame[35] == 0x35 && frame[34] == 0x00)  // DNS Source Port of 53 (0x35h)
                    {
                        //Debug.WriteLine("Received DNS Packet -- " + frame.Length + " bytes");

                        DNS.HandlePacket(frame);
                    }
                    else if (frame[37] == 0xe9 && frame[36] == 0x14 && frame[35] == 0xe9 && frame[34] == 0x14 && Name != null && Name != string.Empty && IPAddress != null) // mDNS Source and Destination Port of 5353 or LLMNR Destination Port of 5355
                    {
                        //Debug.WriteLine("Received MDNS Packet -- " + frame.Length + " bytes");

                        MDNS.HandlePacket(frame);
                    }
                    else if (frame[37] == 0xeb && frame[36] == 0x14 && Name != null && Name != string.Empty && IPAddress != null)
                    {
                        // Debug.WriteLine("Received LLMNR Packet -- " + frame.Length + " bytes");

                        LLMNR.HandlePacket(frame);
                    }
                    else if (OnUdpReceivedPacketEvent != null && IPAddress != null)  // Check Listening ports
                    {
                        //Debug.WriteLine("Received UDP Packet -- " + frame.Length + " bytes");

                        foreach (byte[] aPort in ListeningPorts.Values)
                            if (aPort[0] == frame[36] && aPort[1] == frame[37]) UDP.HandlePacket(frame);
                    }
                }
                else if (frame[23] == 0x06 && IPAddress != null)  // Protocol 6 -- TCP
                {
                    //Debug.WriteLine("Received TCP Packet -- " + frame.Length + " bytes");

                    foreach (byte[] aPort in ListeningPorts.Values)
                    {
                        if (aPort[0] == frame[36] && aPort[1] == frame[37])
                        {
                            TCP.HandlePacket(frame);
                            return;
                        }
                    }

                    // Handle a response from a currently open connection
                    ulong conID = TCP.GenerateConnectionID(frame);
                    if (TCP.Connections.Contains(conID))
                        TCP.HandlePacket(frame);
                    //else
                    //TODO: Send a RST as a response to a closed port.  

                    //var port = (new byte[2] { frame[36], frame[37] }).ToShort();

                    //foreach (Connection aCon in TCP.Connections)
                    //{
                    //    if (aCon.LocalPort == port) 
                    //        TCP.HandlePacket(frame); 
                    //    return;
                    //}

                }
            }

            // All other packets are ignored... like throwing back a fish :)

            //Debug.WriteLine("Memory: " + Microsoft.SPOT.Debug.GC(false).ToString() + ", packetID = " + packetID);


            //Microsoft.SPOT.Debug.EnableGCMessages(true);
        }
        private static void MainService()
        {
            if (nic != null && nic is ENC28J60Driver) return;

            nic = new ENC28J60Driver(Adapter.IntPin, Adapter.CSPin, Adapter.SpiPort);

            // event handler for link status changes (i.e. up/down)
            nic.OnLinkChangedEvent += new ENC28J60Driver.LinkChangedEventHandler(nic_OnLinkChangedEvent);

            // event handler for incoming packet arrival
            nic.OnFrameArrived += new ENC28J60Driver.FrameArrivedEventHandler(nic_OnFrameArrived);

            // NOTE: Don't call any other functions until started
            nic.Start(MacAddress);

            //PollingTimer.Change(10000, 10000);
        }