예제 #1
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);
        }
예제 #2
0
        /// <summary>Creates a new instance of GMC.  
        /// Typically GMC will function as a singleton for each client, 
        /// however, there are cases where the designer may wish to have a variety of GMCS.</summary>
        /// <param name="subMrshlr">the submarshaller to use for marshalling objects to bytes.</param>
        public GMCMarshaller(IMarshaller subMrshlr)
        {
            log = LogManager.GetLogger(GetType());

            subMarshaller = subMrshlr;
            compressor = new GeneralMessageCompressor();
            decompressors = new Dictionary<int, GeneralMessageCompressor>();
        }