private void HandleRetransmittedHandshakeRecord(int epoch, byte[] buf, int off, int len)
        {
            /*
             * TODO Need to handle the case where the previous inbound flight contains
             * messages from two epochs.
             */
            if (len < 12)
            {
                return;
            }
            int fragment_length = TlsUtilities.ReadUint24(buf, off + 9);

            if (len != (fragment_length + 12))
            {
                return;
            }
            int seq = TlsUtilities.ReadUint16(buf, off + 4);

            if (seq >= mNextReceiveSeq)
            {
                return;
            }

            byte msg_type = TlsUtilities.ReadUint8(buf, off);

            // TODO This is a hack that only works until we try to support renegotiation
            int expectedEpoch = msg_type == HandshakeType.finished ? 1 : 0;

            if (epoch != expectedEpoch)
            {
                return;
            }

            int length          = TlsUtilities.ReadUint24(buf, off + 1);
            int fragment_offset = TlsUtilities.ReadUint24(buf, off + 6);

            if (fragment_offset + fragment_length > length)
            {
                return;
            }

            DtlsReassembler reassembler = (DtlsReassembler)mCurrentInboundFlight[seq];

            if (reassembler != null)
            {
                reassembler.ContributeFragment(msg_type, length, buf, off + 12, fragment_offset,
                                               fragment_length);
                if (CheckAll(mCurrentInboundFlight))
                {
                    ResendOutboundFlight();
                    ResetAll(mCurrentInboundFlight);
                }
            }
        }
        internal Message ReceiveMessage()
        {
            if (mSending)
            {
                mSending = false;
                PrepareInboundFlight();
            }

            // Check if we already have the next message waiting
            {
                DtlsReassembler next = (DtlsReassembler)mCurrentInboundFlight[mNextReceiveSeq];
                if (next != null)
                {
                    byte[] body = next.GetBodyIfComplete();
                    if (body != null)
                    {
                        mPreviousInboundFlight = null;
                        return(UpdateHandshakeMessagesDigest(new Message(mNextReceiveSeq++, next.MsgType, body)));
                    }
                }
            }

            byte[] buf = null;

            // TODO Check the conditions under which we should reset this
            int readTimeoutMillis = 1000;

            for (;;)
            {
                int receiveLimit = mRecordLayer.GetReceiveLimit();
                if (buf == null || buf.Length < receiveLimit)
                {
                    buf = new byte[receiveLimit];
                }

                // TODO Handle records containing multiple handshake messages

                try
                {
                    for (; ;)
                    {
                        int received = mRecordLayer.Receive(buf, 0, receiveLimit, readTimeoutMillis);
                        if (received < 0)
                        {
                            break;
                        }
                        if (received < 12)
                        {
                            continue;
                        }
                        int fragment_length = TlsUtilities.ReadUint24(buf, 9);
                        if (received != (fragment_length + 12))
                        {
                            continue;
                        }
                        int seq = TlsUtilities.ReadUint16(buf, 4);
                        if (seq > (mNextReceiveSeq + MAX_RECEIVE_AHEAD))
                        {
                            continue;
                        }
                        byte msg_type        = TlsUtilities.ReadUint8(buf, 0);
                        int  length          = TlsUtilities.ReadUint24(buf, 1);
                        int  fragment_offset = TlsUtilities.ReadUint24(buf, 6);
                        if (fragment_offset + fragment_length > length)
                        {
                            continue;
                        }

                        if (seq < mNextReceiveSeq)
                        {
                            /*
                             * NOTE: If we Receive the previous flight of incoming messages in full
                             * again, retransmit our last flight
                             */
                            if (mPreviousInboundFlight != null)
                            {
                                DtlsReassembler reassembler = (DtlsReassembler)mPreviousInboundFlight[seq];
                                if (reassembler != null)
                                {
                                    reassembler.ContributeFragment(msg_type, length, buf, 12, fragment_offset,
                                                                   fragment_length);

                                    if (CheckAll(mPreviousInboundFlight))
                                    {
                                        ResendOutboundFlight();

                                        /*
                                         * TODO[DTLS] implementations SHOULD back off handshake packet
                                         * size during the retransmit backoff.
                                         */
                                        readTimeoutMillis = System.Math.Min(readTimeoutMillis * 2, 60000);

                                        ResetAll(mPreviousInboundFlight);
                                    }
                                }
                            }
                        }
                        else
                        {
                            DtlsReassembler reassembler = (DtlsReassembler)mCurrentInboundFlight[seq];
                            if (reassembler == null)
                            {
                                reassembler = new DtlsReassembler(msg_type, length);
                                mCurrentInboundFlight[seq] = reassembler;
                            }

                            reassembler.ContributeFragment(msg_type, length, buf, 12, fragment_offset, fragment_length);

                            if (seq == mNextReceiveSeq)
                            {
                                byte[] body = reassembler.GetBodyIfComplete();
                                if (body != null)
                                {
                                    mPreviousInboundFlight = null;
                                    return(UpdateHandshakeMessagesDigest(new Message(mNextReceiveSeq++,
                                                                                     reassembler.MsgType, body)));
                                }
                            }
                        }
                    }
                }
                catch (IOException)
                {
                    // NOTE: Assume this is a timeout for the moment
                }

                ResendOutboundFlight();

                /*
                 * TODO[DTLS] implementations SHOULD back off handshake packet size during the
                 * retransmit backoff.
                 */
                readTimeoutMillis = System.Math.Min(readTimeoutMillis * 2, 60000);
            }
        }