Beispiel #1
0
 public void FinishMSDU(OpenSatelliteProject.GRB.MSDU msdu)
 {
     if (running)
     {
         if (packets.Count >= MAX_QUEUE_LENGTH)
         {
             OpenSatelliteProject.GRB.MSDU lmsdu;
             UIConsole.Warn("MSDU Manager Queue is full!!!! Some MSDU might be discarded!");
             packets.TryDequeue(out lmsdu);
         }
         packets.Enqueue(msdu);
     }
 }
 public void NewFile(Tuple <string, object> file)
 {
     if (running)
     {
         if (packets.Count >= MAX_QUEUE_LENGTH)
         {
             Tuple <string, object> f;
             UIConsole.Warn("File Handler Queue is full!!!! Files might be discarded!");
             packets.TryDequeue(out f);
         }
         packets.Enqueue(file);
     }
 }
Beispiel #3
0
 public void NewPacket(byte[] packet)
 {
     if (running)
     {
         if (packets.Count >= MAX_QUEUE_LENGTH)
         {
             byte[] drop;
             UIConsole.Warn("Channel Manager Queue is full!!!! Samples might be dropped.");
             packets.TryDequeue(out drop);
         }
         packets.Enqueue(packet);
     }
 }
Beispiel #4
0
        public static byte[] ReadFileFromOSPAssembly(string filename)
        {
            byte[]   buffer       = null;
            Assembly xritAssembly = GetAssemblyByName("XRIT");

            try {
                using (Stream stream = xritAssembly.GetManifestResourceStream(string.Format("OpenSatelliteProject.LUT.{0}", filename))) {
                    int num2;
                    buffer = new byte[stream.Length];
                    for (int i = 0; i < stream.Length; i += num2)
                    {
                        num2 = ((stream.Length - i) > 0x1000L) ? 0x1000 : (((int)stream.Length) - i);
                        stream.Read(buffer, i, num2);
                    }
                }
            } catch (Exception) {
                UIConsole.Warn(string.Format("Cannot load {0} from library.", filename));
            }
            return(buffer);
        }
Beispiel #5
0
        void HandleCADU(byte[] data)
        {
            long caduNumber = -1;

            if (data.Length == 2052)
            {
                byte[] counter = data.Take(4).ToArray();
                data       = data.Skip(4).ToArray();
                caduNumber = BitConverter.ToUInt32(counter, 0);
            }

            if (lastCaduNumber != -1 && caduNumber != -1)
            {
                if (lastCaduNumber == caduNumber)
                {
                    UIConsole.Warn("CADU Packet arrived duplicated! Dropping.");
                    return;
                }
                if (lastCaduNumber > caduNumber)
                {
                    UIConsole.Warn("CADU Packet arrived out of order! Dropping.");
                    return;
                }
                if (lastCaduNumber + 1 != caduNumber)
                {
                    long missingPackets = caduNumber - lastPacketNumber + 1;
                    UIConsole.Warn($"Missing {missingPackets} CADU packets!");
                }
            }

            if (FindSyncMark(data) != 0)
            {
                UIConsole.Error("Corrupted CADU data!");
                return;
            }

            PostChannelData(data.Skip(4).ToArray());
        }
Beispiel #6
0
        void ThreadLoop()
        {
            UIConsole.Debug("MSDU Thread started");
            while (running)
            {
                OpenSatelliteProject.GRB.MSDU msdu;
                if (packets.TryDequeue(out msdu))
                {
                    ProcessMSDU(msdu);
                }

                List <int> keys = msduCache.Keys.ToList();
                keys.ForEach(k => {
                    var minfo = msduCache[k];
                    if (minfo.Expired)
                    {
                        UIConsole.Warn($"Product {k:X3} expired. Dumping...");
                        string msduFile = Path.Combine(FileHandler.TemporaryFileFolder, minfo.FileName);
                        string target   = Path.Combine(FileHandler.TemporaryFileFolder, $"{k:X3}-{LLTools.TimestampMS()}-{Tools.RandomString(8)}");
                        File.Move(msduFile, target);
                        if (EnumHelpers.APID2Type(k) == PayloadType.Generic)
                        {
                            fileHandleManager.NewFile(new Tuple <string, object>(target, minfo.GenericHeader));
                        }
                        else
                        {
                            fileHandleManager.NewFile(new Tuple <string, object>(target, minfo.ImageHeader));
                        }
                        msduCache.Remove(k);
                    }
                });

                // Thread.Yield(); // This might be better
                Thread.Sleep(2);
            }
            UIConsole.Debug("Channel Thread stopped");
        }
Beispiel #7
0
        void ChannelDataLoop()
        {
            try {
                UIConsole.Log("Channel Data Loop started");
                byte[] buffer = new byte[2042];

                IPHostEntry ipHostInfo = Dns.GetHostEntry(ChannelDataServerName);
                IPAddress   ipAddress  = new IPAddress(new byte[] { 127, 0, 0, 1 });
                foreach (IPAddress ip in ipHostInfo.AddressList)
                {
                    if (ip.AddressFamily != AddressFamily.InterNetworkV6)
                    {
                        ipAddress = ip;
                        break;
                    }
                }
                IPEndPoint remoteEP = new IPEndPoint(ipAddress, ChannelDataServerPort);
                Socket     sender   = null;

                while (channelDataThreadRunning)
                {
                    bool isConnected = true;
                    UIConsole.Log("Channel Data Thread connect");
                    try {
                        sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
                        {
                            ReceiveTimeout = 5000
                        };
                        sender.Connect(remoteEP);
                        isConnected = true;
                        UIConsole.Log($"Socket connected to {sender.RemoteEndPoint}");
                        int nullReceive = 0;
                        while (isConnected)
                        {
                            try {
                                var receivedBytes = sender.Receive(buffer);
                                if (receivedBytes < buffer.Length && receivedBytes != 0)
                                {
                                    UIConsole.Error("Received less bytes than channel data!");
                                    Thread.Sleep(200);
                                    nullReceive = 0;
                                }
                                else if (receivedBytes == 0)
                                {
                                    nullReceive++;
                                    if (nullReceive == 5)
                                    {
                                        UIConsole.Error("Cannot reach server. Dropping connection!");
                                        isConnected = false;
                                        sender.Shutdown(SocketShutdown.Both);
                                        sender.Disconnect(false);
                                        sender.Close();
                                    }
                                }
                                else
                                {
                                    nullReceive = 0;
                                    this.PostChannelData(buffer);
                                }
                            } catch (ArgumentNullException ane) {
                                UIConsole.Error($"ArgumentNullException : {ane}");
                                isConnected = false;
                            } catch (SocketException) {
                                isConnected = false;
                            } catch (Exception e) {
                                UIConsole.Error($"Unexpected exception : {e}");
                                isConnected = false;
                            }

                            DataConnected = isConnected;

                            if (!channelDataThreadRunning)
                            {
                                break;
                            }
                        }

                        sender.Shutdown(SocketShutdown.Both);
                        sender.Disconnect(false);
                        sender.Close();
                    } catch (ArgumentNullException ane) {
                        UIConsole.Error($"ArgumentNullException : {ane}");
                    } catch (SocketException se) {
                        UIConsole.Error($"SocketException : {se}");
                    } catch (Exception e) {
                        UIConsole.Error($"Unexpected exception : {e}");
                    }
                    if (channelDataThreadRunning)
                    {
                        UIConsole.Warn("Socket closed. Waiting 1s before trying again.");
                        Thread.Sleep(1000);
                    }
                }

                UIConsole.Debug("Requested to close Channel Data Thread!");
                try {
                    if (sender != null)
                    {
                        sender.Shutdown(SocketShutdown.Both);
                        sender.Disconnect(false);
                        sender.Close();
                    }
                } catch (Exception e) {
                    UIConsole.Debug($"Exception thrown when closing socket: {e} Ignoring.");
                }

                UIConsole.Log("Channel Data Thread closed.");
            } catch (Exception e) {
                CrashReport.Report(e);
            }
        }
Beispiel #8
0
        void ProcessMSDU(OpenSatelliteProject.GRB.MSDU msdu)
        {
            try {
                if (msdu.APID == 2047)
                {
                    // Skip fill packet
                    return;
                }

                bool firstOrSinglePacket = msdu.Sequence == SequenceType.FIRST_SEGMENT || msdu.Sequence == SequenceType.SINGLE_DATA;

                Packets++;

                if (!msdu.Valid || !msdu.Full)
                {
                    if (msdu.FrameLost)
                    {
                        UIConsole.Error($"Lost some frames on MSDU, the file will be corrupted. CRC Match: {msdu.Valid} - Size Match: {msdu.Full}");
                    }
                    else
                    {
                        UIConsole.Error($"Corrupted MSDU. CRC Match: {msdu.Valid} - Size Match: {msdu.Full}");
                    }
                }

                if (!msdu.Valid)
                {
                    CRCFails++;
                    return;
                }

                var payloadType = EnumHelpers.APID2Type(msdu.APID);

                if (msdu.Sequence == SequenceType.FIRST_SEGMENT || msdu.Sequence == SequenceType.SINGLE_DATA)
                {
                    if (msduCache.ContainsKey(msdu.APID))
                    {
                        var minfo = msduCache[msdu.APID];
                        UIConsole.Warn($"Received First Segment for {msdu.APID:X3} but last data wasn't saved to disk yet! Forcing dump.");
                        // This can only happen for multi-segment file.
                        string msduFile = Path.Combine(FileHandler.TemporaryFileFolder, minfo.FileName);
                        string target   = Path.Combine(FileHandler.TemporaryFileFolder, $"{msdu.APID:X3}-{LLTools.TimestampMS()}-{Tools.RandomString(8)}");
                        File.Move(msduFile, target);
                        if (payloadType == PayloadType.Generic)
                        {
                            fileHandleManager.NewFile(new Tuple <string, object>(target, minfo.GenericHeader));
                        }
                        else
                        {
                            fileHandleManager.NewFile(new Tuple <string, object>(target, minfo.ImageHeader));
                        }
                        msduCache.Remove(msdu.APID);
                    }

                    var msInfo = new MSDUInfo()
                    {
                        APID          = msdu.APID,
                        FileName      = msdu.TemporaryFilename,
                        GenericHeader = payloadType == PayloadType.Generic ? new GRBGenericHeader(msdu.APID, msdu.Data.Skip(8).Take(21).ToArray()) : null,
                        ImageHeader   = payloadType == PayloadType.ImageData ? new GRBImageHeader(msdu.APID, msdu.Data.Skip(8).Take(34).ToArray()) : null,
                    };

                    msduCache.Add(msdu.APID, msInfo);
                }
                else if (msdu.Sequence == SequenceType.LAST_SEGMENT || msdu.Sequence == SequenceType.CONTINUED_SEGMENT)
                {
                    if (!msduCache.ContainsKey(msdu.APID))
                    {
                        UIConsole.Warn("Orphan Packet!");
                        return;
                    }
                }

                var msduInfo = msduCache[msdu.APID];
                msduInfo.Refresh();

                string path = FileHandler.TemporaryFileFolder;
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                string filename = Path.Combine(FileHandler.TemporaryFileFolder, msduInfo.FileName);

                int totalOffset;

                if (firstOrSinglePacket)
                {
                    totalOffset = 8;
                    if (payloadType == PayloadType.Generic)
                    {
                        totalOffset += 21;
                    }
                    else
                    {
                        totalOffset += 34;
                    }
                }
                else
                {
                    totalOffset = 8;
                }

                byte[] dataToSave = msdu.Data.Skip(totalOffset).ToArray();
                dataToSave = dataToSave.Take(dataToSave.Length - 4).ToArray();                 // Remove CRC

                using (FileStream fs = new FileStream(filename, firstOrSinglePacket ? FileMode.Create : FileMode.Append, FileAccess.Write)) {
                    using (BinaryWriter sw = new BinaryWriter(fs)) {
                        sw.Write(dataToSave);
                        sw.Flush();
                    }
                }

                if (msdu.Sequence == SequenceType.LAST_SEGMENT || msdu.Sequence == SequenceType.SINGLE_DATA)
                {
                    string target = Path.Combine(FileHandler.TemporaryFileFolder, $"{msdu.APID:X3}-{LLTools.TimestampMS()}-{Tools.RandomString(8)}");
                    File.Move(filename, target);
                    if (payloadType == PayloadType.Generic)
                    {
                        fileHandleManager.NewFile(new Tuple <string, object>(target, msduInfo.GenericHeader));
                    }
                    else
                    {
                        fileHandleManager.NewFile(new Tuple <string, object>(target, msduInfo.ImageHeader));
                    }
                    msduCache.Remove(msdu.APID);
                }
            } catch (Exception e) {
                UIConsole.Error(String.Format("Exception on FinishMSDU: {0}", e));
            }
        }
Beispiel #9
0
        public static List <XRITBaseHeader> GetHeaderData(byte[] data)
        {
            List <XRITBaseHeader> headers = new List <XRITBaseHeader>();
            int maxLength = data.Length; // Initial Guess
            int c         = 0;

            // Parse Primary Header for size
            int type = data[0];

            if (type != (int)HeaderType.PrimaryHeader)
            {
                UIConsole.Error($"Expected PrimaryHeader({(int)HeaderType.PrimaryHeader} got {type}. File is corrupt.");
                return(headers);
            }

            byte[] tmp = data.Skip(1).Take(2).ToArray();

            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(tmp);
            }

            int size = BitConverter.ToUInt16(tmp, 0);

            tmp = data.Take(size).ToArray();

            PrimaryRecord fh = LLTools.ByteArrayToStruct <PrimaryRecord>(tmp);

            fh        = LLTools.StructToSystemEndian(fh);
            maxLength = (int)fh.HeaderLength; // Set the correct size

            byte[] headerData = data.Take(maxLength).ToArray();
            data = data.Skip(maxLength).ToArray();

            // Parse Secondary Headers
            while (c < maxLength)
            {
                type = headerData[0];
                tmp  = headerData.Skip(1).Take(2).ToArray();

                if (BitConverter.IsLittleEndian)
                {
                    Array.Reverse(tmp);
                }

                size = BitConverter.ToUInt16(tmp, 0);
                tmp  = headerData.Take(size).ToArray();

                if (tmp.Length < size)
                {
                    UIConsole.Warn($"Not enough data for unpack header: Expected {size} got {tmp.Length} - Header Type: {type} - File might be corrupted.");
                    if (c + size > maxLength)
                    {
                        UIConsole.Debug($"c + size > maxLength: {c} + {size} > {maxLength}");
                        size = maxLength - c - 1;
                        c    = maxLength;
                    }
                }
                else
                {
                    c += size;
                }

                headerData = headerData.Skip(size).ToArray();

                XRITBaseHeader h;
                switch (type)
                {
                case (int)HeaderType.PrimaryHeader:
                    fh        = LLTools.ByteArrayToStruct <PrimaryRecord>(tmp);
                    fh        = LLTools.StructToSystemEndian(fh);
                    h         = new PrimaryHeader(fh);
                    maxLength = (int)fh.HeaderLength;     // Set the correct size
                    break;

                case (int)HeaderType.ImageStructureRecord:
                    ImageStructureRecord isr = LLTools.ByteArrayToStruct <ImageStructureRecord>(tmp);
                    isr = LLTools.StructToSystemEndian(isr);
                    h   = new ImageStructureHeader(isr);
                    break;

                case (int)HeaderType.ImageNavigationRecord:
                    ImageNavigationRecord inr = LLTools.ByteArrayToStruct <ImageNavigationRecord>(tmp);
                    inr = LLTools.StructToSystemEndian(inr);
                    h   = new ImageNavigationHeader(inr);
                    break;

                case (int)HeaderType.ImageDataFunctionRecord:
                    // Cannot marshable due variable length
                    //ImageDataFunctionRecord idfr = LLTools.ByteArrayToStruct<ImageDataFunctionRecord>(tmp);
                    //idfr = LLTools.StructToSystemEndian(idfr);
                    ImageDataFunctionRecord idfr = new ImageDataFunctionRecord();
                    idfr.Data = System.Text.Encoding.UTF8.GetString(tmp.Skip(3).ToArray());
                    h         = new ImageDataFunctionHeader(idfr);
                    break;

                case (int)HeaderType.AnnotationRecord:
                    // Cannot be marshalled due variable length
                    //AnnotationRecord ar = LLTools.ByteArrayToStruct<AnnotationRecord>(tmp);
                    //ar = LLTools.StructToSystemEndian(ar);
                    AnnotationRecord ar = new AnnotationRecord();
                    ar.Filename = System.Text.Encoding.UTF8.GetString(tmp.Skip(3).ToArray());
                    h           = new AnnotationHeader(ar);
                    break;

                case (int)HeaderType.TimestampRecord:
                    TimestampRecord tr = LLTools.ByteArrayToStruct <TimestampRecord>(tmp);
                    tr = LLTools.StructToSystemEndian(tr);
                    h  = new TimestampHeader(tr);
                    break;

                case (int)HeaderType.AncillaryTextRecord:
                    // Cannot be marshalled due variable length.
                    // AncillaryText at = LLTools.ByteArrayToStruct<AncillaryText>(tmp);
                    //at = LLTools.StructToSystemEndian(at);
                    AncillaryText at = new AncillaryText();
                    at.Data = System.Text.Encoding.UTF8.GetString(tmp.Skip(3).ToArray());
                    h       = new AncillaryHeader(at);
                    break;

                case (int)HeaderType.KeyRecord:
                    h = new XRITBaseHeader(HeaderType.KeyRecord, tmp);
                    break;

                case (int)HeaderType.SegmentIdentificationRecord:
                    SegmentIdentificationRecord sir = LLTools.ByteArrayToStruct <SegmentIdentificationRecord>(tmp);
                    sir = LLTools.StructToSystemEndian(sir);
                    h   = new SegmentIdentificationHeader(sir);
                    break;

                case (int)HeaderType.NOAASpecificHeader:
                    NOAASpecificRecord nsr = LLTools.ByteArrayToStruct <NOAASpecificRecord>(tmp);
                    nsr = LLTools.StructToSystemEndian(nsr);
                    h   = new NOAASpecificHeader(nsr);
                    break;

                case (int)HeaderType.HeaderStructuredRecord:
                    // Cannot be marshalled due variable length
                    //HeaderStructuredRecord hsr = LLTools.ByteArrayToStruct<HeaderStructuredRecord>(tmp);
                    //hsr = LLTools.StructToSystemEndian(hsr); // Header Structured Record doesn't have endianess dependant fields
                    HeaderStructuredRecord hsr = new HeaderStructuredRecord();
                    hsr.Data = System.Text.Encoding.UTF8.GetString(tmp.Skip(3).ToArray());
                    h        = new HeaderStructuredHeader(hsr);
                    break;

                case (int)HeaderType.RiceCompressionRecord:
                    RiceCompressionRecord rcr = LLTools.ByteArrayToStruct <RiceCompressionRecord>(tmp);
                    rcr = LLTools.StructToSystemEndian(rcr);
                    h   = new RiceCompressionHeader(rcr);
                    break;

                case (int)HeaderType.DCSFileNameRecord:
                    // Cannot be marshalled due variable length
                    //DCSFilenameRecord dfr = LLTools.ByteArrayToStruct<DCSFilenameRecord>(tmp);
                    //dfr = LLTools.StructToSystemEndian(dfr); // DCS Filename Record doesn't have endianess dependant fields
                    DCSFilenameRecord dfr = new DCSFilenameRecord();
                    dfr.Filename = System.Text.Encoding.UTF8.GetString(tmp.Skip(3).ToArray());
                    h            = new DCSFilenameHeader(dfr);
                    break;

                case (int)HeaderType.Head9:
                    Head9 h9 = new Head9();
                    h9.Data = tmp.Skip(3).ToArray();
                    h       = new Head9Header(h9);
                    ((Head9Header)h).FileName = $"buggy_file_{LLTools.TimestampMS()}.lrit";
                    tmp.Skip(3).ToArray().Separate(new byte[] { 0x00 }).ToList().ForEach((barr) => {
                        if (barr.Length > 0 && barr[0] == 0x1F)
                        {
                            ((Head9Header)h).FileName = System.Text.Encoding.UTF8.GetString(barr.Skip(1).ToArray());
                            ((Head9Header)h).FileName = LLTools.StripNonPrintable(((Head9Header)h).FileName);
                        }
                    });
                    UIConsole.Debug($"Got Head9 which may be a bug. Filename: {((Head9Header)h).FileName}");
                    break;

                default:
                    h      = new XRITBaseHeader();
                    h.Type = HeaderType.Unknown;
                    break;
                }

                h.RawData = tmp;
                headers.Add(h);
            }

            return(headers);
        }
Beispiel #10
0
        void HandleBBFrame(byte[] data)
        {
            long counter = -1;

            if (data.Length == 5384 || data.Length == 7278)
            {
                // Ayecka Packet Count is broken
                byte[] countData = data.Take(4).ToArray();
                data = data.Skip(4).ToArray();

                if (countData[0] == 0xB8)   // DVB-S2 Layer 3 Adaptation Header
                {
                    counter = countData[3];
                }
                else
                {
                    UIConsole.Warn("Looks like not a ayecka output");
                }
            }
            bool QPSK = data.Length == 7274;

            if (lastPacketNumber != -1 && counter != -1 && lastPacketNumber != 255)
            {
                if (lastPacketNumber == counter)
                {
                    UIConsole.Warn("Packet arrived duplicated! Dropping.");
                    return;
                }
                if (lastPacketNumber > counter)
                {
                    UIConsole.Warn($"Packet arrived out of order! - Last: {lastPacketNumber}, Current: {counter}");
                    // return;
                }
                if (lastPacketNumber + 1 != counter)
                {
                    long missingPackets = counter - lastPacketNumber + 1;
                    UIConsole.Warn($"Missing {missingPackets} packets! - Last: {lastPacketNumber}, Current: {counter}");
                }
            }

            lastPacketNumber = counter;

            byte[] bbHeader = data.Take(10).ToArray();
            data = data.Skip(10).ToArray();
            // TODO: Maybe parse BB Header?
            lastData = lastData.Concat(data).ToArray();
            if (!lastFrame.Any())
            {
                while (lastData.Length > 0)
                {
                    int pos = FindSyncMark(lastData);
                    if (pos == -1)
                    {
                        return;
                    }
                    lastData = lastData.Skip(pos).ToArray();
                    byte[] frameData = lastData.Length > 2048 ? lastData.Take(2048).ToArray() : lastData;
                    lastData = lastData.Skip(frameData.Length).ToArray();
                    lastFrame.AddRange(frameData);
                    if (lastFrame.Count() == 2048)
                    {
                        HandleCADU(lastFrame.ToArray());
                        lastFrame.Clear();
                    }
                }
            }
            else
            {
                int    remainingBytes = 2048 - lastFrame.Count();
                byte[] frameData      = lastData.Length > remainingBytes?lastData.Take(remainingBytes).ToArray() : lastData;

                lastData = lastData.Length > remainingBytes?lastData.Skip(remainingBytes).ToArray() : new byte[0];

                lastFrame.AddRange(frameData);
                if (lastFrame.Count() == 2048)
                {
                    HandleCADU(lastFrame.ToArray());
                    lastFrame.Clear();
                }
            }
        }
Beispiel #11
0
        public void ParseBytes(byte[] data)
        {
            uint counter;
            bool replayFlag;
            bool ovfVcnt;
            bool ovfVcntProblem;
            bool frameJump;

            if (data.Length < FRAMESIZE)
            {
                throw new Exception(String.Format("Not enough data. Expected {0} and got {1}", FRAMESIZE, data.Length));
            }

            channelId = (data[1] & 0x3F);

            byte[] cb = data.Skip(2).Take(4).ToArray();

            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(cb);
            }

            cb[0] = 0x00;


            counter = BitConverter.ToUInt32(cb, 0);
            //counter &= 0xFFFFFF00;
            counter  >>= 8;
            replayFlag = (data[5] & 0x80) > 0;

            if (replayFlag)
            {
                UIConsole.Debug("Replay Flag set. Skipping packet.");
                return;
            }

            if (counter - lastFrame - 1 == -1)
            {
                UIConsole.Warn("Last packet same ID as the current one but no replay bit set! Skipping packet.");
                return;
            }

            frameJump      = lastFrame > counter;
            ovfVcnt        = frameJump && counter == 0;
            ovfVcntProblem = ovfVcnt && (0xFFFFFF - lastFrame) + counter - 1 > 0;

            if (frameJump && !ovfVcnt)
            {
                UIConsole.Warn($"Frame Jump occured. Current Frame: {counter} Last Frame: {lastFrame}");
                if (lastAPID != -1)
                {
                    temporaryStorage[lastAPID].FrameLost = true;
                }
            }
            else if (lastFrame != -1 && lastFrame + 1 != counter && !ovfVcnt)
            {
                UIConsole.Error(String.Format("Lost {0} frames. Last Frame #{1} - Current Frame #{2} on VCID {3}", counter - lastFrame - 1, lastFrame, counter, channelId));
                if (lastAPID != -1)
                {
                    temporaryStorage[lastAPID].FrameLost = true;
                }
            }
            else if (!IgnoreCounterJump && lastFrame != -1 && ovfVcntProblem)
            {
                UIConsole.Error(String.Format("Lost {0} frames. Last Frame #{1} - Current Frame #{2} on VCID {3}", (0xFFFFFF - lastFrame) + counter - 1, lastFrame, counter, channelId));
                if (lastAPID != -1)
                {
                    temporaryStorage[lastAPID].FrameLost = true;
                }
            }

            if (ovfVcntProblem && IgnoreCounterJump || frameJump && IgnoreCounterJump)
            {
                UIConsole.Warn($"Frame Jump detected from {lastFrame} to {counter} on VCID {channelId} but IgnoreCounterJump is set to true. Ignoring...");
            }

            if (lastFrame != -1)
            {
                if (frameJump && !ovfVcnt)
                {
                    // manager.FrameLoss++;
                }
                else if (!IgnoreCounterJump && ovfVcnt)
                {
                    int losses = (int)Math.Abs((0xFFFFFF - lastFrame) + counter - 1);
                    if (losses < MAX_ACCOUTABLE_LOSSES)
                    {
                        FrameLoss += losses;
                    }
                    else
                    {
                        UIConsole.Warn($"Frame Lost ({losses}) in this section is higher than max accountable losses. Not accounting for it (probably corrupt frame).");
                    }
                }
                else if (!ovfVcnt)
                {
                    int losses = (int)Math.Abs(counter - lastFrame - 1);
                    if (losses < MAX_ACCOUTABLE_LOSSES)
                    {
                        FrameLoss += losses;
                    }
                    else
                    {
                        UIConsole.Warn($"Frame Lost ({losses}) in this section is higher than max accountable losses. Not accounting for it (probably corrupt frame).");
                    }
                }
            }

            if (frameJump && !ovfVcnt)
            {
                FrameJumps++;
            }

            if (lastFrame < counter || ovfVcnt || frameJump)
            {
                lastFrame = (int)counter;
            }
            else
            {
                UIConsole.Warn($"LastFrame is bigger than currentFrame ({lastFrame} > {counter}). Not changing current number...");
            }

            cb = data.Skip(6).Take(2).ToArray();
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(cb);
            }

            int fhp = BitConverter.ToUInt16(cb, 0) & 0x7FF;

            data = data.Skip(8).ToArray();

            // Data is now TP_PDU
            var p = Tuple.Create(0, new byte[0]);

            if (fhp != 2047)   // Has a packet start
            {
                if (lastAPID == -1 && buffer.Length > 0)
                {
                    //  There was not enough data to packetize last time. So lets fill the buffer until the fhp and create packet.
                    if (fhp > 0)
                    {
                        buffer = buffer.Concat(data.Take(fhp)).ToArray();
                        data   = data.Skip(fhp).ToArray();
                        fhp    = 0;
                    }

                    p        = CreatePacket(buffer);
                    lastAPID = p.Item1;
                    buffer   = p.Item2;
                }

                if (lastAPID != -1)
                {
                    if (fhp > 0)
                    {
                        temporaryStorage[lastAPID].AddDataBytes(buffer.Concat(data.Take(fhp)).ToArray());
                        data = data.Skip(fhp).ToArray();
                        fhp  = 0;
                    }

                    if (!temporaryStorage[lastAPID].Full && !temporaryStorage[lastAPID].FrameLost && lastAPID != 2047)
                    {
                        Bugs++;
                        StackFrame callStack = new StackFrame(0, true);
                        UIConsole.Debug(String.Format("Problem at line {0} in file {1}! Not full! Check code for bugs!", callStack.GetFileLineNumber(), callStack.GetFileName()));
                    }
                    msduManager.FinishMSDU(temporaryStorage[lastAPID]);
                    temporaryStorage.Remove(lastAPID);
                    lastAPID = -1;
                }

                buffer   = buffer.Concat(data.Skip(fhp)).ToArray();
                p        = CreatePacket(buffer);
                lastAPID = p.Item1;
                buffer   = p.Item2;
            }
            else
            {
                if (buffer.Length > 0 && lastAPID != -1)
                {
                    buffer   = buffer.Concat(data).ToArray();
                    p        = CreatePacket(buffer);
                    lastAPID = p.Item1;
                    buffer   = p.Item2;
                }
                else if (lastAPID == -1)
                {
                    buffer   = buffer.Concat(data).ToArray();
                    p        = CreatePacket(buffer);
                    lastAPID = p.Item1;
                    buffer   = p.Item2;
                }
                else if (buffer.Length > 0)
                {
                    UIConsole.Error("EDGE CASE! PLEASE REPORT THIS MESSAGE");
                }
                else
                {
                    temporaryStorage[lastAPID].AddDataBytes(data);
                }
            }
        }