public void OnDataReceived(IAsyncResult asyn)
 {
     // Logger.Log(0, "Begin OnDataReceived");
     IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
     byte[] buf = null;
     try {
         buf = udpConn.EndReceive(asyn, ref remoteIpEndPoint);
     } catch (SocketException e) {
         if (e.SocketErrorCode == SocketError.Interrupted)
             // ignore
             return;
         log_status.WarnFormat("Caught socket exception: {0}", e);
         WaitForData();
         return;
     } catch (ObjectDisposedException) {
         // just ignore this one
         return;
     }
     RdpConnection conn = GetConnection(remoteIpEndPoint);
     if (conn == null) {
         log_status.Info("Handling new connection");
         conn = HandleNewConnection(remoteIpEndPoint);
     }
     if (conn != null) {
         RdpPacket packet = new RdpPacket(buf);
         // Logger.Log(0, "Got data in OnDataReceived");
         conn.OnSegmentArrival(packet, remoteIpEndPoint);
         // Logger.Log(0, "Done with OnDataReceived");
     }
     try {
         WaitForData();
     } catch (SocketException e) {
         if (e.SocketErrorCode != SocketError.Interrupted)
             throw;
     } catch (ObjectDisposedException) {
         // Just ignore this
     }
 }
Ejemplo n.º 2
0
        // TODO: Should I pass in remote endpoint?
        public void OnSegmentArrival(RdpPacket packet)
        {
            switch (state) {
                case ConnectionState.Closed:
                    if (packet.Rst)
                        return;
                    else if (packet.Ack || packet.Nul) {
                        /// Send <SEQ=SEG.ACK + 1><RST>
                        ;
                    } else {
                        /// Send <SEQ=0><RST><ACK=SEG.SEQ><ACK>
                        ;
                    }
                    break;
                case ConnectionState.CloseWait:
                    break;
                case ConnectionState.Listen:
                    if (packet.Rst)
                        return;
                    if (packet.Ack || packet.Nul) {
                        /// Send <SEQ=SEG.ACK + 1><RST>
                        return;
                    }
                    if (packet.Syn) {
                        rcvCur = segSeq;
                        rcvIrs = segSeq;
                        sndMax = segMax;
                        sbufMax = segBmax;
                        /// Send <SEQ=SND.ISS><ACK=RCV.CUR><MAX=RCV.MAX><BUFMAX=RBUF.MAX>
                        ///      <ACK><SYN>
                        state = ConnectionState.SynRcvd;
                        return;
                    }
                    Trace.TraceWarning("Shouldn't have gotten here");
                    break;
                case ConnectionState.SynSent:
                    if (packet.Rst) {
                        if (packet.Ack) {
                            state = ConnectionState.Closed;
                            throw new Exception("Connection Refused");
                            // TODO: deallocate connection
                        }
                        return;
                    }
                    if (packet.Syn) {
                        rcvCur = segSeq;
                        rcvIrs = segSeq;
                        sndMax = segMax;
                        rbufMax = segBmax;
                        if (packet.Ack) {
                            sndUna = segAck + 1; // per rfc 1151
                            state = ConnectionState.Open;
                            /// Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK>
                        } else {
                            state = ConnectionState.SynRcvd;
                            /// Send <SEQ=SND.ISS><ACK=RCV.CUR><MAX=RCV.MAX><BUFMAX=RBUF.MAX>
                            //       <SYN><ACK>
                        }
                        return;
                    }
                    if (packet.Ack) {
                        if (!packet.Rst && segAck != sndIss) {
                            /// Send <SEQ=SEG.ACK + 1><RST>
                            state = ConnectionState.Closed;
                            throw new Exception("Connection Reset");
                            // TODO: deallocate connection
                            return;
                        }
                    }

                    Trace.TraceWarning("Shouldn't have gotten here");
                    break;
                case ConnectionState.SynRcvd:
                    if (rcvIrs >= segSeq || segSeq > (rcvCur + rcvMax * 2))
                        /// Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK>
                        return;
                    if (packet.Rst) {
                        if (passiveOpen)
                            state = ConnectionState.Listen;
                        else {
                            state = ConnectionState.Closed;
                            throw new Exception("Connection Refused");
                            // TODO: deallocate connection
                        }
                        return;
                    }
                    if (packet.Syn) {
                        /// Send <SEQ=SEG.ACK + 1><RST>
                        state = ConnectionState.Closed;
                        throw new Exception("Connection Reset");
                        // TODO: deallocate connection
                        return;
                    }
                    if (packet.Eak) {
                        /// Send <SEQ=SEG.ACK + 1><RST>
                        return;
                    }
                    if (packet.Ack) {
                        if (segAck == sndIss)
                            state = ConnectionState.Open;
                        else
                            /// Send <SEQ=SEG.ACK + 1><RST>
                            return;
                    } else
                        return;
                    if (packet.HasData || packet.Nul) {
                        bool inSequence = true;
                        // If the received segment is in sequence
                        if (inSequence) {
                            ///  TODO: Copy the data (if any) to user buffers
                            rcvCur = segSeq;
                            /// Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK>
                        } else {
                            if (outOfOrderAllowed)
                                // TODO: Copy the data (if any) to user buffers
                                ;
                            /// Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK><EACK><RCVDSEQNO1>
                            ///   ...<RCVDSEQNOn>
                        }
                    }
                    break;
                case ConnectionState.Open:
                    if (rcvCur >= segSeq || segSeq > (rcvCur + rcvMax * 2)) {
                        /// Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK>
                        return;
                    }
                    if (packet.Rst) {
                        state = ConnectionState.CloseWait;
                        throw new Exception("Connection Reset");
                        return;
                    }
                    if (packet.Nul) {
                        rcvCur = segSeq;
                        /// Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK>
                        return;
                    }
                    if (packet.Syn) {
                        /// Send <SEQ=SEG.ACK + 1><RST>
                        state = ConnectionState.Closed;
                        throw new Exception("Connection Reset");
                        // TODO: deallocate connection
                        return;
                    }
                    if (packet.Ack) {
                        if (sndUna <= segAck && segAck < sndNxt) {
                            sndUna = segAck + 1; // per rfc 1151
                            // TODO: Flush acknowledged segments
                        }
                    }
                    if (packet.Eak) {
                        // TODO: Flush acknowledged segments
                    }
                    if (packet.HasData) {
                        bool inSequence = true;
                        // If the received segment is in sequence
                        if (inSequence) {
                            ///  TODO: Copy the data (if any) to user buffers
                            rcvCur = segSeq;
                            // This can have EACKS too, if you want
                            /// Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK>
                        } else {
                            if (outOfOrderAllowed)
                                // TODO: Copy the data (if any) to user buffers
                                ;
                            /// Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK><EACK><RCVDSEQNO1>
                            ///   ...<RCVDSEQNOn>
                        }
                    }
                    break;
            }
        }
Ejemplo n.º 3
0
 public void Send(RdpPacket packet)
 {
     switch (state) {
         case ConnectionState.Open:
             if (sndNxt >= sndUna + sndMax)
                 throw new Exception("Error - insufficient resources to send data");
             /// Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK><Data>
             sndNxt = sndNxt + 1;
             break;
         case ConnectionState.Listen:
         case ConnectionState.SynRcvd:
         case ConnectionState.SynSent:
         case ConnectionState.Closed:
         case ConnectionState.CloseWait:
             throw new Exception("Error - connection not open");
             break;
     }
 }
        /// <summary>
        ///   Method to handle segment arrival
        /// </summary>
        /// <param name="inPacket"></param>
        /// <param name="remote"></param>
        public void OnSegmentArrival(RdpPacket inPacket, IPEndPoint remoteEP) {
            try {
				Monitor.Enter(this);
				InternalOnSegmentArrival(inPacket, remoteEP);
            } finally {
                Monitor.Exit(this);
            }
        }
        /// <summary>
        ///   Internal method to handle segment arrival.  For this version, we already hold the lock.
        /// </summary>
        /// <param name="inPacket"></param>
        /// <param name="remoteEP"></param>
        private void InternalOnSegmentArrival(RdpPacket inPacket, IPEndPoint remoteEP) {
            DateTime now = DateTime.Now;
			log.DebugFormat("OnSegmentArrival: {0} - packet {1}", now, inPacket);

            // count received bytes
            bytesReceivedCount += inPacket.PacketLength;
            totalBytesReceivedCount += inPacket.PacketLength;
			packetsReceivedCount++;

			switch (state) {
                case ConnectionState.Closed:
				case ConnectionState.CloseWait:
					if (inPacket.Rst)
						return;
                    else if (inPacket.Ack || inPacket.Nul) {
                        /// Send <SEQ=SEG.ACK + 1><RST>
                        RdpPacket packet = new RdpPacket(0);
                        packet.SeqNumber = inPacket.AckNumber + 1;
                        packet.Rst = true;
                        SendPacket(packet);
                    } else {
                        /// Send <SEQ=0><RST><ACK=SEG.SEQ><ACK>
                        RdpPacket packet = new RdpPacket(0);
                        packet.SeqNumber = 0;
                        packet.AckNumber = inPacket.SeqNumber;
                        packet.Rst = true;
                        packet.Ack = true;
                        SendPacket(packet);
                    }
                    break;
                case ConnectionState.Listen:
                    if (inPacket.Rst)
                        return;
                    if (inPacket.Ack || inPacket.Nul) {
                        /// Send <SEQ=SEG.ACK + 1><RST>
                        RdpPacket packet = new RdpPacket(0);
                        packet.SeqNumber = inPacket.AckNumber + 1;
                        packet.Rst = true;
                        SendPacket(packet);
                        return;
                    }
                    if (inPacket.Syn) {
                        rcvCur = inPacket.SeqNumber;
                        rcvIrs = inPacket.SeqNumber;
                        sndMax = inPacket.MaxSegments;
                        sbufMax = inPacket.MaxSegmentSize;
                        /// Send <SEQ=SND.ISS><ACK=RCV.CUR><MAX=RCV.MAX><BUFMAX=RBUF.MAX>
                        ///      <ACK><SYN>
                        RdpPacket packet = new RdpPacket(0, RdpPacket.OpenLength);
                        packet.SeqNumber = sndIss;
                        packet.AckNumber = rcvCur;
                        packet.Ack = true;
                        packet.Syn = true;
                        packet.MaxSegments = (short)rcvMax;
                        packet.MaxSegmentSize = (short)rbufMax;
                        packet.Sequenced = inPacket.Sequenced;
                        SendPacket(packet);
                        State = ConnectionState.SynRcvd;
                        return;
                    }
                    log.Warn("Shouldn't have gotten here");
                    break;
                case ConnectionState.SynSent:
                    if (inPacket.Rst) {
                        if (inPacket.Ack) {
                            State = ConnectionState.Closed;
                            log.Warn("Connection Refused");
                            // TODO: deallocate connection
                        }
                        return;
                    }
                    if (inPacket.Syn) {
                        rcvCur = inPacket.SeqNumber;
                        rcvIrs = inPacket.SeqNumber;
                        sndMax = inPacket.MaxSegments;
                        sbufMax = inPacket.MaxSegmentSize;
                        if (inPacket.Ack) {
                            sndUna = inPacket.AckNumber + 1; // per rfc 1151
                            State = ConnectionState.Open;
                            /// Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK>
                            RdpPacket packet = new RdpPacket(0);
                            packet.SeqNumber = sndNxt;
                            packet.AckNumber = rcvCur;
                            packet.Ack = true;
                            SendPacket(packet);
                        } else {
                            State = ConnectionState.SynRcvd;
                            /// Send <SEQ=SND.ISS><ACK=RCV.CUR><MAX=RCV.MAX><BUFMAX=RBUF.MAX>
                            ///      <SYN><ACK>
                            RdpPacket packet = new RdpPacket(0, RdpPacket.OpenLength);
                            packet.SeqNumber = sndIss;
                            packet.AckNumber = rcvCur;
                            packet.Ack = true;
                            packet.Syn = true;
                            packet.MaxSegments = (short)rcvMax;
                            packet.MaxSegmentSize = (short)rbufMax;
                            packet.Sequenced = inPacket.Sequenced;
                            SendPacket(packet);
                        }
                        return;
                    }
                    if (inPacket.Ack) {
                        if (!inPacket.Rst && inPacket.AckNumber != sndIss) {
                            /// Send <SEQ=SEG.ACK + 1><RST>
                            RdpPacket packet = new RdpPacket(0);
                            packet.SeqNumber = inPacket.AckNumber + 1;
                            packet.Rst = true;
                            SendPacket(packet);
                            State = ConnectionState.Closed;
                            log.Warn("Connection Reset (by invalid ACK)");
                            // TODO: deallocate connection
                            return;
                        }
                    }
					if (inPacket.Nul) {
                        log.Warn("Shouldn't have gotten here");
						break;
					}
                    log.Error("Shouldn't have gotten here");
					break;
                case ConnectionState.SynRcvd:
                    if (rcvIrs >= inPacket.SeqNumber || inPacket.SeqNumber > (rcvCur + rcvMax * 2)) {
                        /// Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK>
                        RdpPacket packet = new RdpPacket(0);
                        packet.SeqNumber = sndNxt;
                        packet.AckNumber = rcvCur;
                        packet.Ack = true;
                        SendPacket(packet);
                        return;
                    }
                    if (inPacket.Rst) {
                        if (passiveOpen)
                            State = ConnectionState.Listen;
                        else {
                            State = ConnectionState.Closed;
                            throw new Exception("Connection Refused");
                        }
                        return;
                    }
                    if (inPacket.Syn) {
                        /// Send <SEQ=SEG.ACK + 1><RST>
                        RdpPacket packet = new RdpPacket(0);
                        packet.SeqNumber = inPacket.AckNumber + 1;
                        packet.Rst = true;
                        SendPacket(packet);
                        State = ConnectionState.Closed;
                        log.Warn("Connection Reset (by SYN)");
                        return;
                    }
                    if (inPacket.Eak) {
                        /// Send <SEQ=SEG.ACK + 1><RST>
                        RdpPacket packet = new RdpPacket(0);
                        packet.SeqNumber = inPacket.AckNumber + 1;
                        packet.Rst = true;
                        SendPacket(packet);
                        return;
                    }
                    if (inPacket.Ack) {
                        if (inPacket.AckNumber == sndIss)
                            State = ConnectionState.Open;
                        else {
                            /// Send <SEQ=SEG.ACK + 1><RST>
                            RdpPacket packet = new RdpPacket(0);
                            packet.SeqNumber = inPacket.AckNumber + 1;
                            packet.Rst = true;
                            SendPacket(packet);
                            return;
                        }
                    } else 
                        return;
                    if (inPacket.HasData || inPacket.Nul) {
                        HandleDataPacket(inPacket);
                        /// Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK><EACK><RCVDSEQNO1>
                        ///   ...<RCVDSEQNOn>
                        int[] eakArray = AbridgedEakArray;
                        RdpPacket packet = new RdpPacket(0, eakArray.Length * 4);
                        packet.SeqNumber = sndNxt;
                        packet.AckNumber = rcvCur;
                        packet.Ack = true;
                        if (eakArray.Length > 0) {
                            packet.Eak = true;
                            packet.EakEntries = eakArray;
                        }
                        SendPacket(packet);
                    }
                    break;
                case ConnectionState.Open:
                    if (inPacket.Rst) {
                        State = ConnectionState.CloseWait;
                        log.Warn("Connection Reset");
                        return;
                    }
                    if (rcvCur >= inPacket.SeqNumber || inPacket.SeqNumber > (rcvCur + rcvMax * 2)) {
                        /// Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK>
                        RdpPacket packet = new RdpPacket(0);
                        packet.SeqNumber = sndNxt;
                        packet.AckNumber = rcvCur;
                        packet.Ack = true;
                        SendPacket(packet);
						log.Debug("Acking packet that was already received");
						return;
                    }
#if STRICT_SPEC
                    if (inPacket.Nul) {
                        rcvCur = inPacket.SeqNumber;
                        /// Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK>
                        RdpPacket packet = new RdpPacket(0);
                        packet.SeqNumber = sndNxt;
                        packet.AckNumber = rcvCur;
                        packet.Ack = true;
                        SendPacket(packet);
						Logger.Log(1, "Got Nul packet");
						return;
					}
#endif
                    if (inPacket.Syn) {
                        /// Send <SEQ=SEG.ACK + 1><RST>
                        RdpPacket packet = new RdpPacket(0);
                        packet.SeqNumber = inPacket.AckNumber + 1;
                        packet.Rst = true;
                        SendPacket(packet);
                        State = ConnectionState.Closed;
                        log.Warn("Connection Reset (by SYN)");
                        // TODO: deallocate connection
                        return;
                    }
                    if (inPacket.Ack) {
                        if (sndUna <= inPacket.AckNumber && inPacket.AckNumber < sndNxt) {
                            sndUna = inPacket.AckNumber + 1; // per rfc 1151
                            List<int> removeList = new List<int>();
                            int segAck = inPacket.AckNumber;
                            foreach (int segSeq in unacknowledgedPackets.Keys)
                                if (segSeq <= segAck)
                                    removeList.Add(segSeq);
                            foreach (int segSeq in removeList)
                                unacknowledgedPackets.Remove(segSeq);
                        }
                    }
                    if (inPacket.Eak) {
                        int[] eakEntries = inPacket.EakEntries;
						log.DebugFormat("Received eack packet: {0}", inPacket);
						foreach (int segSeq in eakEntries)
                             unacknowledgedPackets.Remove(segSeq);
                    }
#if STRICT_SPEC
                    if (inPacket.HasData) {
#else
                    if (inPacket.HasData || inPacket.Nul) {
#endif
                        HandleDataPacket(inPacket);
                        /// Send <SEQ=SND.NXT><ACK=RCV.CUR><ACK><EACK><RCVDSEQNO1>
                        ///   ...<RCVDSEQNOn>
                        int[] eakArray = AbridgedEakArray;
                        RdpPacket packet = new RdpPacket(0, eakArray.Length * 4);
                        packet.SeqNumber = sndNxt;
                        packet.AckNumber = rcvCur;
                        packet.Ack = true;
                        if (eakArray.Length > 0) {
                            packet.Eak = true;
                            packet.EakEntries = eakArray;
                        }
                        SendPacket(packet);
                    }
                    break;
            }
        }
 /// <summary>
 ///   Internal version of the send method.  For this version, we already hold the lock.
 /// </summary>
 /// <param name="packet"></param>
 private void InternalSend(RdpPacket packet) {
     switch (state) {
         case ConnectionState.Open:
             if (sndNxt >= sndUna + sndMax)
                 throw new Exception("Error - insufficient resources to send data");
             /// Send <ACK=RCV.CUR><SEQ=SND.NXT><ACK><Data>;
             packet.AckNumber = rcvCur;
             packet.SeqNumber = sndNxt;
             packet.Ack = true;
             SendPacket(packet);
             sndNxt = sndNxt + 1;
             break;
         case ConnectionState.Listen:
         case ConnectionState.SynRcvd:
         case ConnectionState.SynSent:
         case ConnectionState.Closed:
         case ConnectionState.CloseWait:
             throw new Exception("Error - connection not open");
     }
 }
 /// <summary>
 ///   Internal version of close.  For this version, we already hold the lock.
 /// </summary>
 private void InternalClose() {
     int ticks = Environment.TickCount - startTick;
     log.InfoFormat("Sent {0} bytes, Received {1} bytes in {2} seconds", 
                    bytesSentCount, bytesReceivedCount, ticks / 1000);
     switch (state) {
         case ConnectionState.Open: {
                 /// Send <SEQ=SND.NXT><RST>;
                 RdpPacket packet = new RdpPacket(0);
                 packet.SeqNumber = sndNxt;
                 packet.Rst = true;
                 SendPacket(packet);
             }
             State = ConnectionState.CloseWait;
             // TODO: Start TIMWAIT Timer
             break;
         case ConnectionState.Listen:
             State = ConnectionState.Closed;
             break;
         case ConnectionState.SynRcvd:
         case ConnectionState.SynSent: {
                 /// Send <SEQ=SND.NXT><RST>
                 RdpPacket packet = new RdpPacket(0);
                 packet.SeqNumber = sndNxt;
                 packet.Rst = true;
                 SendPacket(packet);
             }
             State = ConnectionState.Closed;
             break;
         case ConnectionState.CloseWait:
             throw new Exception("Error - Connection closing");
         case ConnectionState.Closed:
             throw new Exception("Error - Connection not open");
     }
 }
 /// <summary>
 ///   Takes a packet with nothing but the data portion filled, 
 ///   and does what is needed to send it out.
 /// </summary>
 /// <param name="packet"></param>
 public void Send(RdpPacket packet) {
     if (!valid)
         throw new Exception("Called Send on closed connection");
     try {
         Monitor.Enter(this);
         InternalSend(packet);
     } finally {
         Monitor.Exit(this);
     }
 }
 public void Send(byte[] data) {
     if (!valid)
         throw new Exception("Called Send on closed connection");
     RdpPacket packet = new RdpPacket(data.Length);
     Array.Copy(data, 0, packet.PacketData, packet.DataOffset, data.Length);
     Send(packet);
 }
        /// <summary>
        ///   Method to send the packet.  If this is a client, we will pass in 
        ///   null as the remoteEP, since the UdpClient object will have
        ///   called connect.  We should already hold the lock on the connection.
        /// </summary>
        /// <param name="packet"></param>
        private void SendPacket(RdpPacket packet) {
            // count the bytes of outgoing packet
            bytesSentCount += packet.PacketLength;
			totalBytesSentCount += packet.PacketLength;
            packetsSentCount++;

            if (packet.HasData) {
				const int IpHeaderLength = 20;
				const int UdpHeaderLength = 8;
                // If the packet is too large, throw
				if (packet.PacketLength + IpHeaderLength + UdpHeaderLength > sbufMax)
					throw new RdpFragmentationException("packet size {0} is too large for connection with max of {1}", packet.DataLength, sbufMax);
                // If we have already sent as many packets as we can, throw
                if (unacknowledgedPackets.Count > rcvMax)
                    throw new Exception("maximum unacknowledged packets exceeds limit");
                DateTime now = DateTime.Now;
                unacknowledgedPackets[packet.SeqNumber] = packet;
                retransmissionTimer[packet.SeqNumber] = now.AddMilliseconds(RetransmissionTimeout);
                log.DebugFormat("SendPacket: {0} - packet {1}", now, packet);
            }
			if (packet.Eak)
				log.DebugFormat("sending packet with eak set: {0}", packet);
            udpConn.Send(packet.PacketData, packet.PacketData.Length, remoteEP);
         }
        /// <summary>
        ///   Version of Open that bypasses the lock (used internally)
        ///   Generally with these methods, we already hold the lock, but
        ///   in this case, we don't need to hold the lock, since we are
        ///   still in the constructor.
        /// </summary>
        /// <param name="passiveOpen"></param>
        /// <param name="rcvMax"></param>
        /// <param name="rmaxBuf"></param>
        /// <param name="isSequenced"></param>
        private void InternalOpen(bool passiveOpen) {
            if (state != ConnectionState.Closed)
                throw new Exception("Error - connection already open");

            this.passiveOpen = passiveOpen;

            State = ConnectionState.Listen;

            // Create a connection record
            if (!passiveOpen) {
                /// Send <SEQ=SND.ISS><MAX=SND.MAX><MAXBUF=RMAX.BUF><SYN>
                RdpPacket packet = new RdpPacket(0, RdpPacket.OpenLength);
                packet.SeqNumber = sndIss;
                packet.Syn = true;
                packet.MaxSegments = (short)rcvMax;
                packet.MaxSegmentSize = (short)rbufMax;
                packet.Sequenced = !outOfOrderAllowed;
                SendPacket(packet);
                State = ConnectionState.SynSent;
            }
        }
        /// <summary>
        ///   Process the packet, adding it to either the out of order list 
        ///   or the available list as appropriate.  We already have the lock.
        ///   This will also update rcvCur to be appropriate.
        /// </summary>
        /// <param name="packet"></param>
        private void HandleDataPacket(RdpPacket packet) {
            outOfOrderPackets[packet.SeqNumber] = packet;
            if (outOfOrderAllowed)
                availableOutOfOrderPackets[packet.SeqNumber] = packet;
            int[] sortedSequence = new int[outOfOrderPackets.Keys.Count];
            outOfOrderPackets.Keys.CopyTo(sortedSequence, 0);
			foreach (int segSeq in sortedSequence) {
				if (segSeq == rcvCur + 1) {
					RdpPacket currentPacket = outOfOrderPackets[segSeq];
					log.DebugFormat("Queued packet {0} : {1}", currentPacket.SeqNumber, segSeq);
					availablePackets.Add(currentPacket);
					if (outOfOrderAllowed)
						availableOutOfOrderPackets.Remove(segSeq);
					rcvCur = segSeq;
					outOfOrderPackets.Remove(segSeq);
				}
			}
			Monitor.PulseAll(this);
        }