public TPDUConnection(byte[] packet)
        {
            int pos;
            int li = packet[0];

            TPDU.TPDU_TYPES type = (TPDU.TPDU_TYPES)(packet[1] >> 4);

            if ((type != TPDU.TPDU_TYPES.CR) && (type != TPDU.TPDU_TYPES.CC))
            {
                throw new ApplicationException("TPDU: This can only handle CC/CR TDPUs");
            }

            if (BitConverter.IsLittleEndian)
            {
                DstRef = ByteConvert.DoReverseEndian(BitConverter.ToUInt16(packet, 2));
                SrcRef = ByteConvert.DoReverseEndian(BitConverter.ToUInt16(packet, 4));
            }
            else
            {
                DstRef = BitConverter.ToUInt16(packet, 2);
                SrcRef = BitConverter.ToUInt16(packet, 4);
            }

            ClassOption = ((packet[6] & 0xf0) >> 4);
            if (ClassOption > 4)
            {
                throw new Exception("TPDU: Class option number not allowed.");
            }

            pos = 7;
            // read variable part
            Varpart = new ArrayList();
            try
            {
                while (pos < li)
                {
                    VarParam vp = new VarParam();
                    vp.code   = packet[pos];
                    pos      += 1;
                    vp.length = packet[pos];
                    pos      += 1;
                    vp.value  = new byte[vp.length];
                    Array.Copy(packet, pos, vp.value, 0, vp.length);
                    pos += vp.length;
                    Varpart.Add(vp);
                }
            }
            catch (Exception)
            {
                throw new Exception("TPDU: Error parsing variable part of CR/CC PDU.");
            }
        }
        // Handle connect request and build a connect confirm packet
        public TPDUConnection HandleConnectRequest(List <byte[]> LocalTsaps, int maxTPDUSize, bool enableTsapCheck)
        {
            ArrayList      varpart = new ArrayList();
            TPDUConnection ccpdu   = new TPDUConnection();
            Random         random  = new Random();

            this.MaxTPDUSize = maxTPDUSize;

            ccpdu.DstRef      = SrcRef;
            ccpdu.SrcRef      = Convert.ToUInt16(random.Next(1, 32766));
            ccpdu.ClassOption = 0;

            // Compare Destination TSAP
            int indDstTsap = Varpart.IndexOf((byte)VP.DST_TSAP);

            if (indDstTsap < 0)
            {
                throw new Exception("TPDU: Missing destination tsap in connect request.");
            }
            if (enableTsapCheck)
            {
                bool validTsapFound = false;
                foreach (byte[] tsap in LocalTsaps)
                {
                    // Check length
                    if (((VarParam)Varpart[indDstTsap]).length == tsap.Length)
                    {
                        for (int i = 0; i < tsap.Length; i++)
                        {
                            if (((VarParam)Varpart[indDstTsap]).value[i] == tsap[i])
                            {
                                if (i == tsap.Length - 1)
                                {
                                    validTsapFound = true;
                                    break;
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                    if (validTsapFound)
                    {
                        break;
                    }
                }
                if (validTsapFound == false)
                {
                    throw new Exception("TPDU: Destination tsap mismatch.");
                }
            }

            int indSrcTsap = Varpart.IndexOf((byte)VP.SRC_TSAP);

            if (indSrcTsap < 0)
            {
                throw new Exception("TPDU: Missing source tsap in connect request.");
            }

            // Add parameters
            VarParam vp = new VarParam();

            ccpdu.Varpart = new ArrayList();

            vp.code   = (byte)VP.SRC_TSAP;
            vp.length = ((VarParam)Varpart[indSrcTsap]).length;
            vp.value  = new byte[vp.length];
            Array.Copy(((VarParam)Varpart[indSrcTsap]).value, vp.value, vp.length);
            ccpdu.Varpart.Add(vp);

            vp.code   = (byte)VP.DST_TSAP;
            vp.length = ((VarParam)Varpart[indDstTsap]).length;
            vp.value  = new byte[vp.length];
            Array.Copy(((VarParam)Varpart[indDstTsap]).value, vp.value, vp.length);
            ccpdu.Varpart.Add(vp);

            int indPduSize = Varpart.IndexOf((byte)VP.TPDU_SIZE);
            int TPDUSizeId = GetTPDUSizeIdFromOctetCount(MaxTPDUSize);

            if (indPduSize >= 0)
            {
                if (((VarParam)Varpart[indPduSize]).value[0] < TPDUSizeId)
                {
                    TPDUSizeId = ((VarParam)Varpart[indPduSize]).value[0];
                }
            }
            ccpdu.MaxTPDUSize = GetTPDUOctetCountFromSizeId(TPDUSizeId);
            vp.code           = (byte)VP.TPDU_SIZE;
            vp.length         = 1;
            vp.value          = new byte[1];
            vp.value[0]       = Convert.ToByte(TPDUSizeId);
            ccpdu.Varpart.Add(vp);

            return(ccpdu);
        }