/// <summary>
        /// Handle a discovery request
        /// </summary>
        internal void HandleRequest(IncomingNetMessage message, NetworkEndPoint senderEndpoint)
        {
            ushort number;

            if (!VerifyIdentifiers(message, senderEndpoint, out number))
            {
                return;                 // bad app ident or self discovery
            }
            NetBuffer buf = m_netBase.CreateBuffer(2);

            buf.Write(number);

            m_netBase.LogWrite("Sending discovery response to " + senderEndpoint + " request " + number);

            // send discovery response
            m_netBase.SendSingleUnreliableSystemMessage(
                NetSystemType.DiscoveryResponse,
                buf,
                senderEndpoint,
                null
                );

            m_netBase.RecycleBuffer(buf);
        }
        // TODO: Use this with TRUE isLibraryThread for internal sendings (acks etc)

        internal void SendMessage(NetBuffer data, NetChannel channel, NetBuffer receiptData, bool isLibraryThread)
        {
            if (m_status != NetConnectionStatus.Connected)
            {
                throw new NetException("Status must be Connected to send messages");
            }

            if (data.LengthBytes > m_owner.m_config.m_maximumTransmissionUnit)
            {
                //
                // Fragmented message
                //

                int dataLen      = data.LengthBytes;
                int chunkSize    = m_owner.m_config.m_maximumTransmissionUnit - 10;              // header
                int numFragments = dataLen / chunkSize;
                if (chunkSize * numFragments < dataLen)
                {
                    numFragments++;
                }

                ushort fragId = m_nextSendFragmentId++;

                for (int i = 0; i < numFragments; i++)
                {
                    OutgoingNetMessage fmsg = m_owner.CreateOutgoingMessage();
                    fmsg.m_type    = NetMessageLibraryType.UserFragmented;
                    fmsg.m_msgType = NetMessageType.Data;

                    NetBuffer fragBuf = m_owner.CreateBuffer();
                    fragBuf.Write(fragId);
                    fragBuf.WriteVariableUInt32((uint)i);
                    fragBuf.WriteVariableUInt32((uint)numFragments);

                    if (i < numFragments - 1)
                    {
                        // normal fragment
                        fragBuf.Write(data.Data, i * chunkSize, chunkSize);
                    }
                    else
                    {
                        // last fragment
                        int bitsInLast  = data.LengthBits - (chunkSize * (numFragments - 1) * 8);
                        int bytesInLast = dataLen - (chunkSize * (numFragments - 1));
                        fragBuf.Write(data.Data, i * chunkSize, bytesInLast);

                        // add receipt only to last message
                        fmsg.m_receiptData = receiptData;
                    }
                    fmsg.m_data            = fragBuf;
                    fmsg.m_data.m_refCount = 1;                     // since it's just been created

                    fmsg.m_numSent         = 0;
                    fmsg.m_nextResend      = double.MaxValue;
                    fmsg.m_sequenceChannel = channel;
                    fmsg.m_sequenceNumber  = -1;

                    if (isLibraryThread)
                    {
                        m_unsentMessages.Enqueue(fmsg);
                    }
                    else
                    {
                        lock (m_lockedUnsentMessages)
                            m_lockedUnsentMessages.Enqueue(fmsg);
                    }
                }

                // TODO: recycle the original, unfragmented data

                return;
            }

            //
            // Normal, unfragmented, message
            //

            OutgoingNetMessage msg = m_owner.CreateOutgoingMessage();

            msg.m_msgType = NetMessageType.Data;
            msg.m_type    = NetMessageLibraryType.User;
            msg.m_data    = data;
            msg.m_data.m_refCount++;             // it could have been sent earlier also
            msg.m_numSent         = 0;
            msg.m_nextResend      = double.MaxValue;
            msg.m_sequenceChannel = channel;
            msg.m_sequenceNumber  = -1;
            msg.m_receiptData     = receiptData;

            if (isLibraryThread)
            {
                m_unsentMessages.Enqueue(msg);
            }
            else
            {
                lock (m_lockedUnsentMessages)
                    m_lockedUnsentMessages.Enqueue(msg);
            }
        }