Example #1
0
        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);
                }
            }
        }
Example #2
0
        private Message GetPendingMessage()
        {
            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)));
                }
            }
            return(null);
        }
        private void HandleRetransmittedHandshakeRecord(int epoch, byte[] buf, int off, int len)
        {
            if (len < 12)
            {
                return;
            }
            int num = TlsUtilities.ReadUint24(buf, off + 9);

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

            if (num2 >= this.mNextReceiveSeq)
            {
                return;
            }
            byte b    = TlsUtilities.ReadUint8(buf, off);
            int  num3 = (b == 20) ? 1 : 0;

            if (epoch != num3)
            {
                return;
            }
            int num4 = TlsUtilities.ReadUint24(buf, off + 1);
            int num5 = TlsUtilities.ReadUint24(buf, off + 6);

            if (num5 + num > num4)
            {
                return;
            }
            DtlsReassembler dtlsReassembler = (DtlsReassembler)this.mCurrentInboundFlight[num2];

            if (dtlsReassembler != null)
            {
                dtlsReassembler.ContributeFragment(b, num4, buf, off + 12, num5, num);
                if (DtlsReliableHandshake.CheckAll(this.mCurrentInboundFlight))
                {
                    this.ResendOutboundFlight();
                    DtlsReliableHandshake.ResetAll(this.mCurrentInboundFlight);
                }
            }
        }
 private static void ResetAll(IDictionary inboundFlight)
 {
     global::System.Collections.IEnumerator enumerator = ((global::System.Collections.IEnumerable)inboundFlight.get_Values()).GetEnumerator();
     try
     {
         while (enumerator.MoveNext())
         {
             DtlsReassembler dtlsReassembler = (DtlsReassembler)enumerator.get_Current();
             dtlsReassembler.Reset();
         }
     }
     finally
     {
         global::System.IDisposable disposable = enumerator as global::System.IDisposable;
         if (disposable != null)
         {
             disposable.Dispose();
         }
     }
 }
 private static bool CheckAll(IDictionary inboundFlight)
 {
     global::System.Collections.IEnumerator enumerator = ((global::System.Collections.IEnumerable)inboundFlight.get_Values()).GetEnumerator();
     try
     {
         while (enumerator.MoveNext())
         {
             DtlsReassembler dtlsReassembler = (DtlsReassembler)enumerator.get_Current();
             if (dtlsReassembler.GetBodyIfComplete() == null)
             {
                 return(false);
             }
         }
     }
     finally
     {
         global::System.IDisposable disposable = enumerator as global::System.IDisposable;
         if (disposable != null)
         {
             disposable.Dispose();
         }
     }
     return(true);
 }
        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);
            }
        }
Example #7
0
        private bool ProcessRecord(int windowSize, int epoch, byte[] buf, int off, int len)
        {
            bool checkPreviousFlight = false;

            while (len >= MessageHeaderLength)
            {
                int fragment_length = TlsUtilities.ReadUint24(buf, off + 9);
                int message_length  = fragment_length + MessageHeaderLength;
                if (len < message_length)
                {
                    // NOTE: Truncated message - ignore it
                    break;
                }

                int length          = TlsUtilities.ReadUint24(buf, off + 1);
                int fragment_offset = TlsUtilities.ReadUint24(buf, off + 6);
                if (fragment_offset + fragment_length > length)
                {
                    // NOTE: Malformed fragment - ignore it and the rest of the record
                    break;
                }

                /*
                 * NOTE: This very simple epoch check will only work until we want to support
                 * renegotiation (and we're not likely to do that anyway).
                 */
                byte msg_type      = TlsUtilities.ReadUint8(buf, off + 0);
                int  expectedEpoch = msg_type == HandshakeType.finished ? 1 : 0;
                if (epoch != expectedEpoch)
                {
                    break;
                }

                int message_seq = TlsUtilities.ReadUint16(buf, off + 4);
                if (message_seq >= (mNextReceiveSeq + windowSize))
                {
                    // NOTE: Too far ahead - ignore
                }
                else if (message_seq >= mNextReceiveSeq)
                {
                    DtlsReassembler reassembler = (DtlsReassembler)mCurrentInboundFlight[message_seq];
                    if (reassembler == null)
                    {
                        reassembler = new DtlsReassembler(msg_type, length);
                        mCurrentInboundFlight[message_seq] = reassembler;
                    }

                    reassembler.ContributeFragment(msg_type, length, buf, off + MessageHeaderLength, fragment_offset,
                                                   fragment_length);
                }
                else if (mPreviousInboundFlight != null)
                {
                    /*
                     * NOTE: If we receive the previous flight of incoming messages in full again,
                     * retransmit our last flight
                     */

                    DtlsReassembler reassembler = (DtlsReassembler)mPreviousInboundFlight[message_seq];
                    if (reassembler != null)
                    {
                        reassembler.ContributeFragment(msg_type, length, buf, off + MessageHeaderLength, fragment_offset,
                                                       fragment_length);
                        checkPreviousFlight = true;
                    }
                }

                off += message_length;
                len -= message_length;
            }

            bool result = checkPreviousFlight && CheckAll(mPreviousInboundFlight);

            if (result)
            {
                ResendOutboundFlight();
                ResetAll(mPreviousInboundFlight);
            }
            return(result);
        }
Example #8
0
        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);
            }
        }
        internal DtlsReliableHandshake.Message ReceiveMessage()
        {
            if (this.mSending)
            {
                this.mSending = false;
                this.PrepareInboundFlight();
            }
            DtlsReassembler dtlsReassembler = (DtlsReassembler)this.mCurrentInboundFlight[this.mNextReceiveSeq];

            if (dtlsReassembler != null)
            {
                byte[] bodyIfComplete = dtlsReassembler.GetBodyIfComplete();
                if (bodyIfComplete != null)
                {
                    this.mPreviousInboundFlight = null;
                    return(this.UpdateHandshakeMessagesDigest(new DtlsReliableHandshake.Message(this.mNextReceiveSeq++, dtlsReassembler.MsgType, bodyIfComplete)));
                }
            }
            byte[] array = null;
            int    num   = 1000;

            DtlsReliableHandshake.Message result;
            while (true)
            {
                int receiveLimit = this.mRecordLayer.GetReceiveLimit();
                if (array != null && array.Length >= receiveLimit)
                {
                    goto IL_92;
                }
                array = new byte[receiveLimit];
                try
                {
                    DtlsReassembler dtlsReassembler3;
                    byte[]          bodyIfComplete2;
                    while (true)
                    {
IL_92:
                        int num2 = this.mRecordLayer.Receive(array, 0, receiveLimit, num);
                        if (num2 < 0)
                        {
                            goto IL_214;
                        }
                        if (num2 >= 12)
                        {
                            int num3 = TlsUtilities.ReadUint24(array, 9);
                            if (num2 == num3 + 12)
                            {
                                int num4 = TlsUtilities.ReadUint16(array, 4);
                                if (num4 <= this.mNextReceiveSeq + 10)
                                {
                                    byte msg_type = TlsUtilities.ReadUint8(array, 0);
                                    int  num5     = TlsUtilities.ReadUint24(array, 1);
                                    int  num6     = TlsUtilities.ReadUint24(array, 6);
                                    if (num6 + num3 <= num5)
                                    {
                                        if (num4 < this.mNextReceiveSeq)
                                        {
                                            if (this.mPreviousInboundFlight != null)
                                            {
                                                DtlsReassembler dtlsReassembler2 = (DtlsReassembler)this.mPreviousInboundFlight[num4];
                                                if (dtlsReassembler2 != null)
                                                {
                                                    dtlsReassembler2.ContributeFragment(msg_type, num5, array, 12, num6, num3);
                                                    if (DtlsReliableHandshake.CheckAll(this.mPreviousInboundFlight))
                                                    {
                                                        this.ResendOutboundFlight();
                                                        num = Math.Min(num * 2, 60000);
                                                        DtlsReliableHandshake.ResetAll(this.mPreviousInboundFlight);
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            dtlsReassembler3 = (DtlsReassembler)this.mCurrentInboundFlight[num4];
                                            if (dtlsReassembler3 == null)
                                            {
                                                dtlsReassembler3 = new DtlsReassembler(msg_type, num5);
                                                this.mCurrentInboundFlight[num4] = dtlsReassembler3;
                                            }
                                            dtlsReassembler3.ContributeFragment(msg_type, num5, array, 12, num6, num3);
                                            if (num4 == this.mNextReceiveSeq)
                                            {
                                                bodyIfComplete2 = dtlsReassembler3.GetBodyIfComplete();
                                                if (bodyIfComplete2 != null)
                                                {
                                                    break;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    this.mPreviousInboundFlight = null;
                    result = this.UpdateHandshakeMessagesDigest(new DtlsReliableHandshake.Message(this.mNextReceiveSeq++, dtlsReassembler3.MsgType, bodyIfComplete2));
                    break;
                    IL_214 :;
                }
                catch (IOException)
                {
                }
                this.ResendOutboundFlight();
                num = Math.Min(num * 2, 60000);
            }
            return(result);
        }
        internal Message ReceiveMessage()
        {
            if (mSending)
            {
                mSending = false;
                PrepareInboundFlight();
            }
            DtlsReassembler dtlsReassembler = (DtlsReassembler)mCurrentInboundFlight.get_Item((object)mNextReceiveSeq);

            if (dtlsReassembler != null)
            {
                byte[] bodyIfComplete = dtlsReassembler.GetBodyIfComplete();
                if (bodyIfComplete != null)
                {
                    mPreviousInboundFlight = null;
                    return(UpdateHandshakeMessagesDigest(new Message(mNextReceiveSeq++, dtlsReassembler.MsgType, bodyIfComplete)));
                }
            }
            byte[] array = null;
            int    num   = 1000;

            while (true)
            {
                int receiveLimit = mRecordLayer.GetReceiveLimit();
                if (array == null || array.Length < receiveLimit)
                {
                    array = new byte[receiveLimit];
                }
                try
                {
                    while (true)
                    {
                        int num2 = mRecordLayer.Receive(array, 0, receiveLimit, num);
                        if (num2 < 0)
                        {
                            break;
                        }
                        if (num2 < 12)
                        {
                            continue;
                        }
                        int num3 = TlsUtilities.ReadUint24(array, 9);
                        if (num2 != num3 + 12)
                        {
                            continue;
                        }
                        int num4 = TlsUtilities.ReadUint16(array, 4);
                        if (num4 > mNextReceiveSeq + 10)
                        {
                            continue;
                        }
                        byte msg_type = TlsUtilities.ReadUint8(array, 0);
                        int  num5     = TlsUtilities.ReadUint24(array, 1);
                        int  num6     = TlsUtilities.ReadUint24(array, 6);
                        if (num6 + num3 > num5)
                        {
                            continue;
                        }
                        if (num4 < mNextReceiveSeq)
                        {
                            if (mPreviousInboundFlight == null)
                            {
                                continue;
                            }
                            DtlsReassembler dtlsReassembler2 = (DtlsReassembler)mPreviousInboundFlight.get_Item((object)num4);
                            if (dtlsReassembler2 != null)
                            {
                                dtlsReassembler2.ContributeFragment(msg_type, num5, array, 12, num6, num3);
                                if (CheckAll(mPreviousInboundFlight))
                                {
                                    ResendOutboundFlight();
                                    num = Math.Min(num * 2, 60000);
                                    ResetAll(mPreviousInboundFlight);
                                }
                            }
                            continue;
                        }
                        DtlsReassembler dtlsReassembler3 = (DtlsReassembler)mCurrentInboundFlight.get_Item((object)num4);
                        if (dtlsReassembler3 == null)
                        {
                            dtlsReassembler3 = new DtlsReassembler(msg_type, num5);
                            mCurrentInboundFlight.set_Item((object)num4, (object)dtlsReassembler3);
                        }
                        dtlsReassembler3.ContributeFragment(msg_type, num5, array, 12, num6, num3);
                        if (num4 == mNextReceiveSeq)
                        {
                            byte[] bodyIfComplete2 = dtlsReassembler3.GetBodyIfComplete();
                            if (bodyIfComplete2 != null)
                            {
                                mPreviousInboundFlight = null;
                                return(UpdateHandshakeMessagesDigest(new Message(mNextReceiveSeq++, dtlsReassembler3.MsgType, bodyIfComplete2)));
                            }
                        }
                    }
                }
                catch (IOException)
                {
                }
                ResendOutboundFlight();
                num = Math.Min(num * 2, 60000);
            }
        }