Beispiel #1
0
        private void DumpMessage()
        {
            if (Address != 0)
            {
                string message = "A: " + Address.ToString("0000000") + " M: " + Mode;

                if (MessageBits.Count > 0)
                {
                    bool[] reorderedNumBits = ReorderBits((bool[])MessageBits.ToArray(typeof(bool)), 4);
                    bool[] reorderedMsgBits = ReorderBits((bool[])MessageBits.ToArray(typeof(bool)), 7);
                    byte[] NumBytes         = ByteUtil.BitsToBytes(reorderedNumBits, 4);
                    byte[] msgBytes         = ByteUtil.BitsToBytes(reorderedMsgBits, 7);
                    byte[] rawBytes         = ByteUtil.BitsToBytes((bool[])MessageBits.ToArray(typeof(bool)));
                    string textMessage      = new ASCIIEncoding().GetString(msgBytes);
                    string numMessage       = GetNumeric(NumBytes);

                    if (IsPrintable(textMessage))
                    {
                        message += " (TEXT) " + textMessage;
                    }
                    else
                    {
                        message += " (NUM) " + numMessage;
                        message += " (DATA) ";
                        foreach (byte msgByte in rawBytes)
                        {
                            message += msgByte.ToString("x2") + " ";
                        }
                    }
                }
                else
                {
                    message += " (BEEP)";
                }

                Log.AddMessage(message);

                Address = 0;
            }
            MessageBits.Clear();
        }
Beispiel #2
0
        public void WriteRawBurst(bool[] burstBits)
        {
            bool dummyBurst = false;
            bool skippable  = true;

            BurstCount++;

            lock (this)
            {
                /* if there is no file opened, return */
                if (DumpFile == null || Parameters.State != eGSMState.Lock)
                {
                    return;
                }

                long deltaSlots = (Parameters.FN - FN) * 8 + (Parameters.TN - TN);
                if (deltaSlots != 1)
                {
                    /* hmm maybe demodulator resynchronized. force an entry. */
                    FN        = -1;
                    TN        = -1;
                    ARFCN     = -1;
                    skippable = false;
                }

                OutputBuilder.Length = 0;
                OutputBuilder.Append("<b d=\"");

                /* convert bits to bytes for writing into output */
                ByteUtil.BitsToBytes(burstBits, BurstBufferD, 8, 0, 148);
                dummyBurst = BurstBufferD.SequenceEqual(DummyData);

                /* dummy bursts are skipped */
                if (!dummyBurst)
                {
                    skippable = false;
                    for (int pos = 0; pos < BurstBufferD.Length; pos++)
                    {
                        OutputBuilder.AppendFormat("{0:X02}", BurstBufferD[pos]);
                    }
                }

                OutputBuilder.Append("\"");

                /* output ARFCN if it has changed */
                if (!StripOutput || (ARFCN != Parameters.ARFCN))
                {
                    skippable = false;
                    OutputBuilder.AppendFormat(" a=\"{0}\"", Parameters.ARFCN);
                }

                /*
                 * output FN if a) it has changed and b) it is not an obvious FN change due to TN overflow.
                 * c) also output FN every 10 frames for better debug-ability.
                 */
                bool updatedFN       = (FN != Parameters.FN);
                bool obviousFNchange = ((FN + 1) == Parameters.FN) && (TN > Parameters.TN);
                bool cyclicFNOutput  = (((Parameters.FN % 10) == 0) && Parameters.TN == 0);

                if (!StripOutput || (updatedFN && (!obviousFNchange || cyclicFNOutput)))
                {
                    skippable = false;
                    OutputBuilder.AppendFormat(" f=\"{0}\"", Parameters.FN);
                }
                else if (SkippedBursts > 7)
                {
                    /* in case there were skipped more than 7 bursts, append FN on the next bursts. (will not happen due to TN=0 check below) */
                    OutputBuilder.AppendFormat(" f=\"{0}\"", Parameters.FN);
                }

                /* output TN if is not a simple increase. we will output TN=0 always */
                if (!StripOutput || ((TN + 1) != Parameters.TN))
                {
                    skippable = false;
                    OutputBuilder.AppendFormat(" t=\"{0}\"", Parameters.TN);
                }
                else if (SkippedBursts > 0)
                {
                    /* if there were bursts skipped previously, append TN */
                    OutputBuilder.AppendFormat(" t=\"{0}\"", Parameters.TN);
                }

                /* remember the last burst parameters */
                ARFCN = Parameters.ARFCN;
                FN    = Parameters.FN;
                TN    = Parameters.TN;

                if (!StripOutput || !skippable)
                {
                    /* only write time tag if the burst isnt skipped */
                    DateTime now         = DateTime.Now;
                    bool     updatedTime = ((now - LastTaggedTime).TotalSeconds > TimeTagEvery);

                    if (updatedTime)
                    {
                        LastTaggedTime = now;
                        OutputBuilder.AppendFormat(" time=\"{0}\"", LastTaggedTime.ToString());
                    }

                    OutputBuilder.Append("/>");

                    BurstEntries++;
                    SkippedBursts = 0;
                    DumpFile.WriteLine(OutputBuilder);
                }
                else
                {
                    SkippedBursts++;
                }
            }
        }
Beispiel #3
0
        public override eSuccessState ParseData(GSMParameters param, bool[] decodedBurst, int sequence)
        {
            eSuccessState success = eSuccessState.Unknown;

            if (IsDummy(decodedBurst))
            {
                State = eBurstState.Idle;
                DummyBursts++;

                //CloseFiles();

                /* don't treat TCHs as a reliable source for end-of-connection detection */
                //DummyBurstReceived(param);

                if (DumpRawData)
                {
                    StatusMessage = "Dummy Burst";
                }
                return(eSuccessState.Succeeded);
            }

            EncryptionType   = AssociatedSACCH.EncryptionType;
            ChannelEncrypted = AssociatedSACCH.ChannelEncrypted;

            StoreBurstContext(param, decodedBurst, TCHSeq);

            /* GSM 05.03 Ch 2.1 */
            /* when we got 8 TCH bursts */
            if (++TCHSeq == 8)
            {
                TCHSeq = 0;

                /* try to decrypt buffer if this is enabled, but do not try to crack the key */
                if (!HandleEncryption(param, false))
                {
                    State = eBurstState.CryptedTraffic;

                    /* encrypted but no decryptor available, silently return */
                    return(eSuccessState.Unknown);
                }

                /* deinterleave the 8 TCH bursts. the result is a 456 bit block. i[] to c[] */
                Deinterleave();

                /*
                 * GSM-05.03 4.2.5
                 * was this burst stolen for a FACCH? hl(B) (in e[]) is set for the last 4 bursts */
                if (IsHL(decodedBurst))
                {
                    /* pass encryption information to FACCH */
                    FACCH.A5Algorithm      = A5Algorithm;
                    FACCH.A5CipherKey      = A5CipherKey;
                    FACCH.ChannelEncrypted = ChannelEncrypted;

                    /* pass c[] to FACCH handler */
                    success = FACCH.ParseFACCHData(param, BurstBufferC);

                    StatusMessage = FACCH.StatusMessage;
                    ErrorMessage  = FACCH.ErrorMessage;

                    FACCH.StatusMessage = null;
                    FACCH.ErrorMessage  = null;
                }
                else
                {
                    /* TCH speech/data (data not supported yet) */

                    /* split up the class 1... */
                    Array.Copy(BurstBufferC, Class1DataConv, Class1DataConv.Length);
                    /* ... and class 2 bits */
                    Array.Copy(BurstBufferC, 378, GSMFrameBufferD, 182, 78);

                    /* use an own convolutional coder buffer for these 188 bits */
                    if (ConvolutionalCoder.Decode(Class1DataConv, ref Class1Data) == 0)
                    {
                        bool[] parityBits = new bool[53];

                        for (int pos = 0; pos < 91; pos++)
                        {
                            GSMFrameBufferD[2 * pos]     = Class1Data[pos];
                            GSMFrameBufferD[2 * pos + 1] = Class1Data[184 - pos];
                        }

                        /* calculate parity */
                        Array.Copy(GSMFrameBufferD, 0, parityBits, 0, 50);
                        Array.Copy(Class1Data, 91, parityBits, 50, 3);

                        bool[] crc = CRC.Calc(parityBits, 0, 53, CRC.PolynomialTCHFR);
                        if (CRC.Matches(crc))
                        {
                            DataBursts++;
                            success = eSuccessState.Succeeded;

                            if (ChannelEncrypted)
                            {
                                State = eBurstState.DecryptedTraffic;
                            }
                            else
                            {
                                State = eBurstState.PlainTraffic;
                            }
#if false
                            #region Microsoft WAV49 GSM Format
                            if (WAV49First)
                            {
                                BitMapping.Unmap(GSMFrameBufferD, 0, WAV49FrameBool, 0, BitMapping.g610BitOrder);
                            }
                            else
                            {
                                /* directly unmap into boolean WAV49 frame buffer */
                                BitMapping.Unmap(GSMFrameBufferD, 0, WAV49FrameBool, 260, BitMapping.g610BitOrder);

                                /* convert that WAV49 frame to byte[] */
                                ByteUtil.BitsToBytes(WAV49FrameBool, WAV49FrameByte);

                                try
                                {
                                    if (OutFile == null)
                                    {
                                        string name = ("GSM_" + Name + "_" + param.FN + ".wav").Replace("/", "_");
                                        OutFile = new FileStream(name, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
                                        WriteHeader(OutFile);
                                    }

                                    /* and write it */
                                    WriteBuffer(OutFile, WAV49FrameByte);
                                    WriteHeader(OutFile);
                                    StatusMessage = "GSM 06.10 Voice data (" + OutFile.Name + ")";
                                }
                                catch (Exception e)
                                {
                                    StatusMessage = "GSM 06.10 Voice data (Writing file failed, " + e.GetType() + ")";
                                }
                            }
                            WAV49First = !WAV49First;
                            #endregion
#endif
                            if (ChannelMode != 33)
                            {
                                #region write audio dump in RTP A/V Format
                                /* GSM frame magic */
                                RTPFrameBool[0] = true;
                                RTPFrameBool[1] = true;
                                RTPFrameBool[2] = false;
                                RTPFrameBool[3] = true;

                                /* directly unmap into boolean RTP frame buffer */
                                BitMapping.Unmap(GSMFrameBufferD, 0, RTPFrameBool, 4, BitMapping.g610BitOrder);

                                /* convert that RTP frame to byte[] */
                                ByteUtil.BitsToBytes(RTPFrameBool, RTPFrameByte);

                                StatusMessage = "";

                                if (ChannelEncrypted)
                                {
                                    StatusMessage += "======= encrypted =======" + Environment.NewLine;
                                }

                                try
                                {
                                    if (OutFile == null)
                                    {
                                        string name = ("GSM_" + Name + "_" + param.FN).Replace("/", "_");
                                        OutFile = new FileStream(name + ".gsm", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
                                        //OutFileRaw = new FileStream(name + ".raw", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
                                        StatusMessage += "Created file: '" + name + "'" + Environment.NewLine;
                                    }

                                    /* and write it */
                                    OutFile.Write(RTPFrameByte, 0, RTPFrameByte.Length);
                                    OutFile.Flush();

                                    /*
                                     * Array.Copy(GSMFrameBufferD, 0, RTPFrameBool, 4, GSMFrameBufferD.Length);
                                     * RTPFrameBool[0] = false;
                                     * RTPFrameBool[1] = false;
                                     * RTPFrameBool[2] = false;
                                     * RTPFrameBool[3] = false;
                                     * ByteUtil.BitsToBytes(RTPFrameBool, RTPFrameByte);
                                     * OutFileRaw.Write(RTPFrameByte, 0, RTPFrameByte.Length);
                                     */

                                    StatusMessage += "GSM 06.10 Voice data (" + OutFile.Name + ")";
                                }
                                catch (Exception e)
                                {
                                    StatusMessage += "GSM 06.10 Voice data (Writing file failed, " + e.GetType() + ")";
                                }
                                #endregion
                            }
                            else
                            {
                                #region write audio dump in AMR Format (assume 12.2kbit/s)

                                UnmapDToW();
                                UnmapWToS();

                                /* convert that AMR frame to byte[] */
                                ByteUtil.BitsToBytes(BurstBufferSpeechBits, RTPFrameByte);

                                StatusMessage = "";

                                if (ChannelEncrypted)
                                {
                                    StatusMessage += "======= encrypted =======" + Environment.NewLine;
                                }

                                try
                                {
                                    if (OutFile == null)
                                    {
                                        byte[] fileHeader = new byte[] { 0x23, 0x21, 0x41, 0x4D, 0x52, 0x0A };
                                        string name       = ("GSM_" + Name + "_" + param.FN).Replace("/", "_");
                                        OutFile = new FileStream(name + ".amr", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
                                        OutFile.Write(fileHeader, 0, fileHeader.Length);
                                    }

                                    /* and write it */
                                    OutFile.WriteByte(0x3C);
                                    OutFile.Write(RTPFrameByte, 0, 31);
                                    OutFile.Flush();

                                    StatusMessage += "GSM 06.90 Voice data (" + OutFile.Name + ")";
                                }
                                catch (Exception e)
                                {
                                    StatusMessage += "GSM 06.90 Voice data (Writing file failed, " + e.GetType() + ")";
                                }

                                #endregion
                            }
                        }
                        else
                        {
                            State = eBurstState.Failed;
                            CryptedFrames++;
                            ErrorMessage = "(TCH/F Class Ia: CRC Error)";
                        }
                    }
                    else
                    {
                        State = eBurstState.Failed;
                        CryptedFrames++;
                        ErrorMessage = "(TCH/F Class I: Error in ConvolutionalCoder)";
                    }
                }


                /* trick:
                 * first use the last 8 bursts until one block was successfully decoded.
                 * then use the last 4 bursts as we normally would do.
                 * this will help in finding the correct alignment within the 4 frames.
                 */

                if (success == eSuccessState.Succeeded)
                {
                    BurstShiftCount = 4;
                }
                else
                {
                    BurstShiftCount = 7;
                }

                /* save the last n bursts for the next block */
                for (int pos = 0; pos < BurstShiftCount; pos++)
                {
                    BurstData src = BurstBlock[(8 - BurstShiftCount) + pos];
                    BurstData dst = BurstBlock[pos];

                    dst.FN    = src.FN;
                    dst.Count = src.Count;
                    Array.Copy(src.BurstBufferI, 0, dst.BurstBufferI, 0, dst.BurstBufferI.Length);
                    Array.Copy(src.BurstBufferE, 0, dst.BurstBufferE, 0, dst.BurstBufferE.Length);
                }

                /* and continue at position n (so we will read another 8-n bursts) */
                TCHSeq = BurstShiftCount;

                /* only when in sync, return error flag */
                if (BurstShiftCount == 4)
                {
                    return(success);
                }
            }

            return(eSuccessState.Unknown);
        }