예제 #1
0
        /// <summary>
        /// Decode a trie-based encoded message.
        /// </summary>
        /// <param name="encoded">the encoded bytes</param>
        /// <returns>the decoded bytes</returns>
        public byte[] Decode(byte[] encoded)
        {
            MemoryStream input = new MemoryStream(encoded);
            MemoryStream result = new MemoryStream(encoded.Length);
            IList<byte> missingAnnouncements = new List<byte>();
            int b;
            while ((b = input.ReadByte()) >= 0)
            {
                switch(b) {
                case EscapeSingleCharacter:
                    result.WriteByte((byte)input.ReadByte());
                    break;

                case EscapeMultipleCharacterSequence:
                    uint length = ByteUtils.DecodeLength(input);
                    while (length-- > 0 && input.Position < input.Length)
                    {
                        result.WriteByte((byte)input.ReadByte());
                    }
                    break;

                //case EscapeDictionaryAnnouncement:
                //    byte shortForm = (byte)input.ReadByte();
                //    int longForm = ByteUtils.DecodeLength(input);
                //    HandleAnnouncement(longForm, shortForm);

                //    if (inverseShortcuts[shortForm] != 0)
                //    {
                //        byte[] decoded = decodingTable[inverseShortcuts[shortForm]];
                //        result.Write(decoded, 0, decoded.Length);
                //    }
                //    else
                //    {
                //        missingAnnouncements.Add((byte)shortForm);
                //    }
                //    break;

                default:
                    if(inverseShortcuts[b] != 0)
                    {
                        byte[] decoded = decodingTable[(int)inverseShortcuts[b]];
                        result.Write(decoded, 0, decoded.Length);
                    }
                    else
                    {
                        missingAnnouncements.Add((byte)b);
                    }
                    break;
                }
            }
            if (missingAnnouncements.Count > 0)
            {
                MissingInformationException mcce = new MissingInformationException();
                mcce.Template = templateId;
                //mcce.UserID = userId;
                mcce.IDs = missingAnnouncements;
                mcce.ExceptionType = EnumExceptionType.MissingAnnouncement;
                throw mcce;
            }
            return result.ToArray();
        }
예제 #2
0
        /// <summary>
        /// Decode the provided byte array received from the user with unique
        /// identity <c>userId</c>.
        /// </summary>
        /// <param name="userId">the unique identity for the user</param>
        /// <param name="encodedBytes">the encoded message received</param>
        /// <returns></returns>
        public byte[] Decode(int userId, byte[] encodedBytes)
        {
            log.Trace("\n>>>> DECODING <<<<<");
            Stream input = TryInflating(encodedBytes);
            CompressedMessagePackage cmp = new CompressedMessagePackage();
            cmp.TemplateId = (short)ByteUtils.DecodeLength(input);
            log.Trace(String.Format("==> Decoding with template {0}", cmp.TemplateId));
            int inputValue;
            while((inputValue = input.ReadByte()) != -1) {
                switch ((GMCMessageKey)inputValue)
                {
                case GMCMessageKey.Huffed: cmp.Huffed = true; break;
                case GMCMessageKey.NotHuffed: cmp.Huffed = false; break;
                case GMCMessageKey.Template:
                    cmp.Template = DecodeTemplate(input);
                    if (log.IsTraceEnabled)
                    {
                        log.Trace(String.Format("TID={0}: Decoded template: {1}",
                            cmp.TemplateId, ByteUtils.DumpBytes(cmp.Template)));
                    }
                    break;
                case GMCMessageKey.HuffmanFrequencyTable:
                    cmp.FrequencyTable = DecodeFrequencies(input);
                    log.Trace(String.Format("TID={0}: Decoded huffman frequencies", cmp.TemplateId));
                    break;
                case GMCMessageKey.Announcements:
                    cmp.Announcements = DecodeAnnouncements(input);
                    if (log.IsTraceEnabled)
                    {
                        StringBuilder message = new StringBuilder();
                        message.Append(String.Format("TID={0}: Decoded {1} dictionary announcements:",
                                cmp.TemplateId, cmp.Announcements.Count));
                        foreach(KeyValuePair<uint, byte> kvp in cmp.Announcements)
                        {
                            message.Append(' ');
                            message.Append(kvp.Key);
                            message.Append("->");
                            message.Append(kvp.Value);
                        }
                        log.Trace(message);
                    }
                    break;
                case GMCMessageKey.Message:
                    uint len = ByteUtils.DecodeLength(input);
                    cmp.Message = new byte[len];
                    input.Read(cmp.Message, 0, (int)len);
                    if (log.IsTraceEnabled)
                    {
                        log.Trace(String.Format("Decoded message: {0}",
                            ByteUtils.DumpBytes(cmp.Message)));
                    }
                    break;
                default:
                    log.Trace("Invalid GMC message");
                    throw new MarshallingException("invalid GMC message");
                }
            }

            GeneralMessageCompressor handler;
            if (!decompressors.TryGetValue(userId, out handler))
            {
                if (cmp.Template == null)
                {
                    //we haven't received any templates whatsoever from this person.
                    MissingInformationException mte = new MissingInformationException();
                    mte.Template = 0;
                    mte.UserID = userId;
                    mte.ExceptionType = EnumExceptionType.MissingTemplate;
                    throw mte;
                }
                handler = decompressors[userId] = new GeneralMessageCompressor();
            }
            return handler.Decode(cmp, userId);
        }
예제 #3
0
        /// <summary>
        /// Decode the provided message using the specified template
        /// </summary>
        /// <param name="cmp">the message package to be decompressed</param>
        /// <param name="userId">the user from which the encoded message was received</param>
        /// <returns>The decoded (uncompressed) message</returns>
        public byte[] Decode(CompressedMessagePackage cmp, int userId)
        {
            if (cmp.Template != null)
            {
                AddTemplate(cmp.Template, cmp.TemplateId);
            }
            if (cmp.TemplateId < 0 || cmp.TemplateId > compressors.Count)
            {
                MissingInformationException mte = new MissingInformationException();
                mte.Template = cmp.TemplateId;
                mte.UserID = userId;
                mte.ExceptionType = EnumExceptionType.MissingTemplate;
                throw mte;
            }

            return compressors[cmp.TemplateId].Decode(cmp);
        }