public static MSDU ParseMSDU(byte[] data) { MSDU msdu = new MSDU { PrimaryHeader = data.Take(6).ToArray() }; byte[] ob = data.Take(2).ToArray(); if (BitConverter.IsLittleEndian) { Array.Reverse(ob); } UInt16 o = BitConverter.ToUInt16(ob, 0); msdu.Version = (o & 0xE000) >> 13; msdu.Type = (o & 0x1000) >> 12; msdu.HasSecondHeader = ((o & 0x800) >> 11) > 0; msdu.APID = o & 0x7FF; ob = data.Skip(2).Take(2).ToArray(); if (BitConverter.IsLittleEndian) { Array.Reverse(ob); } o = BitConverter.ToUInt16(ob, 0); msdu.Sequence = (SequenceType)((o & 0xC000) >> 14); msdu.PacketNumber = (o & 0x3FFF); msdu.TemporaryFilename = $"{msdu.APID}.grbtmp"; ob = data.Skip(4).Take(2).ToArray(); if (BitConverter.IsLittleEndian) { Array.Reverse(ob); } msdu.PacketLength = BitConverter.ToUInt16(ob, 0) + 1; data = data.Skip(6).ToArray(); if (data.Length > msdu.PacketLength) { msdu.RemainingData = data.Skip(msdu.PacketLength).ToArray(); data = data.Take(msdu.PacketLength).ToArray(); } else { msdu.RemainingData = new byte[0]; } msdu.Data = data.ToArray(); msdu.FrameLost = false; return(msdu); }
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); } }
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)); } }