Example #1
0
        /// <summary>
        /// Extracts the field value from this packet.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="field">The field definition.</param>
        /// <param name="packet">The packet.</param>
        /// <param name="definitions">The definitions.</param>
        /// <returns>
        /// The value of the field.
        /// </returns>
        private string ExtractFieldValue(Span <byte> data, Field field, PacketDefinition packet, PacketDefinitions definitions)
        {
            var fieldSize = field.GetFieldSizeInBytes();

            if (field.Type == FieldType.String && field.Index < data.Length)
            {
                return(data.ExtractString(field.Index, fieldSize ?? int.MaxValue, Encoding.UTF8));
            }

            if (field.Type == FieldType.Binary && field.Index < data.Length)
            {
                return(fieldSize.HasValue
                    ? data.Slice(field.Index, fieldSize.Value).AsString()
                    : data.Slice(field.Index).AsString());
            }

            if (data.Length < field.Index + fieldSize)
            {
                return(string.Empty);
            }

            switch (field.Type)
            {
            case FieldType.Byte:
                return(data.Slice(field.Index).GetByteValue(field.LengthSpecified ? field.Length : 8, field.LeftShifted).ToString());

            case FieldType.Boolean:
                return(data.Slice(field.Index).GetBoolean(field.LeftShifted).ToString());

            case FieldType.IntegerLittleEndian:
                return(ReadUInt32LittleEndian(data.Slice(field.Index)).ToString());

            case FieldType.IntegerBigEndian:
                return(ReadUInt32BigEndian(data.Slice(field.Index)).ToString());

            case FieldType.ShortLittleEndian:
                return(ReadUInt16LittleEndian(data.Slice(field.Index)).ToString());

            case FieldType.ShortBigEndian:
                return(ReadUInt16BigEndian(data.Slice(field.Index)).ToString());

            case FieldType.LongLittleEndian:
                return(ReadUInt64LittleEndian(data.Slice(field.Index)).ToString());

            case FieldType.LongBigEndian:
                return(ReadUInt64BigEndian(data.Slice(field.Index)).ToString());

            case FieldType.Enum:
                return(this.ExtractEnumValue(data, field, packet, definitions));

            case FieldType.StructureArray:
                return(this.ExtractStructureArrayValues(data, field, packet, definitions));

            case FieldType.Float:
                return(BitConverter.ToSingle(data.Slice(field.Index)).ToString(CultureInfo.InvariantCulture));

            default:
                return(string.Empty);
            }
        }
Example #2
0
        private string ExtractEnumValue(Span <byte> data, Field field, PacketDefinition packet, PacketDefinitions definitions)
        {
            var byteValue      = data.Slice(field.Index).GetByteValue(field.LengthSpecified ? field.Length : 8, field.LeftShifted);
            var enumDefinition = packet.Enums?.FirstOrDefault(e => e.Name == field.TypeName)
                                 ?? definitions.Enums?.FirstOrDefault(e => e.Name == field.TypeName)
                                 ?? this.commonDefinitions?.Enums?.FirstOrDefault(e => e.Name == field.TypeName);
            var enumValue = enumDefinition?.Values.FirstOrDefault(v => v.Value == byteValue);

            return($"{data[field.Index]} ({enumValue?.Name ?? "unknown"})");
        }
Example #3
0
 /// <summary>
 /// Extracts the field value from this packet or returns an error message, if it couldn't be extracted.
 /// </summary>
 /// <param name="data">The data.</param>
 /// <param name="field">The field definition.</param>
 /// <param name="packet">The packet.</param>
 /// <param name="definitions">The definitions.</param>
 /// <returns>
 /// The value of the field or the error message.
 /// </returns>
 private string ExtractFieldValueOrGetError(Span <byte> data, Field field, PacketDefinition packet, PacketDefinitions definitions)
 {
     try
     {
         return(this.ExtractFieldValue(data, field, packet, definitions));
     }
     catch (Exception e)
     {
         return($"{e.GetType().Name}: {e.Message}");
     }
 }
Example #4
0
        private string ExtractStructureArrayValues(Span <byte> data, Field field, PacketDefinition packet, PacketDefinitions definitions)
        {
            var type = packet.Structures?.FirstOrDefault(s => s.Name == field.TypeName)
                       ?? definitions.Structures?.FirstOrDefault(s => s.Name == field.TypeName)
                       ?? this.commonDefinitions.Structures?.FirstOrDefault(s => s.Name == field.TypeName);

            if (type == null)
            {
                return(data.Slice(field.Index).AsString());
            }

            var countField = packet.Fields.FirstOrDefault(f => f.Name == field.ItemCountField)
                             ?? packet.Structures?.SelectMany(s => s.Fields).FirstOrDefault(f => f.Name == field.ItemCountField);
            int count = int.Parse(this.ExtractFieldValue(data, countField, packet, definitions));

            if (count == 0)
            {
                return(string.Empty);
            }

            var typeLength    = type.Length > 0 ? type.Length : this.DetermineFixedStructLength(data, field, type, count);
            var stringBuilder = new StringBuilder();
            var restData      = data.Slice(field.Index);

            for (int i = 0; i < count; i++)
            {
                var currentLength = typeLength ?? this.DetermineDynamicStructLength(restData, type, packet);
                var elementData   = restData.Slice(0, currentLength);
                restData = restData.Slice(currentLength);

                stringBuilder.Append(Environment.NewLine)
                .Append(field.Name + $"[{i}]:");
                stringBuilder.Append(Environment.NewLine)
                .Append("  Raw: ").Append(elementData.AsString());
                foreach (var structField in type.Fields)
                {
                    stringBuilder.Append(Environment.NewLine)
                    .Append("  ").Append(structField.Name).Append(": ").Append(this.ExtractFieldValue(elementData, structField, packet, definitions));
                }
            }

            return(stringBuilder.ToString());
        }
Example #5
0
        /// <summary>
        /// Determines the length of the dynamic structure.
        /// We assume that a nested struct type has a fixed length specified in <see cref="Structure.Length"/>.
        /// </summary>
        /// <param name="restData">The rest data.</param>
        /// <param name="type">The type.</param>
        /// <param name="packetType">Type of the packet.</param>
        /// <returns>The dynamic length of a struct with a nested structure array.</returns>
        private int DetermineDynamicStructLength(Span <byte> restData, Structure type, PacketDefinition packetType)
        {
            var nestedStructField = type.Fields.First(f => f.Type == FieldType.StructureArray);
            var countField        = type.Fields.First(f => f.Name == nestedStructField.ItemCountField);
            var count             = restData[countField.Index];
            var nestedStructType  = packetType.Structures.First(s => s.Name == nestedStructField.TypeName);

            return(nestedStructField.Index + (count * nestedStructType.Length));
        }