/// <summary> /// This method is used to deserialize the items of the cell knowledge from the byte array. /// </summary> /// <param name="byteArray">Specify the byte array.</param> /// <param name="currentIndex">Specify the start index from the byte array.</param> /// <param name="lengthOfItems">Specify the current length of items in the cell knowledge.</param> protected override void DeserializeItemsFromByteArray(byte[] byteArray, ref int currentIndex, int lengthOfItems) { if (lengthOfItems != 0) { throw new KnowledgeParseErrorException(currentIndex, "CellKnowledge object over-parse error", null); } int index = currentIndex; StreamObjectHeaderStart header; int length = 0; this.CellKnowledgeEntryList = new List <CellKnowledgeEntry>(); this.CellKnowledgeRangeList = new List <CellKnowledgeRange>(); while ((length = StreamObjectHeaderStart.TryParse(byteArray, index, out header)) != 0) { index += length; if (header.Type == StreamObjectTypeHeaderStart.CellKnowledgeEntry) { this.CellKnowledgeEntryList.Add(StreamObject.ParseStreamObject(header, byteArray, ref index) as CellKnowledgeEntry); } else if (header.Type == StreamObjectTypeHeaderStart.CellKnowledgeRange) { this.CellKnowledgeRangeList.Add(StreamObject.ParseStreamObject(header, byteArray, ref index) as CellKnowledgeRange); } else { throw new KnowledgeParseErrorException(currentIndex, "Failed to parse CellKnowledge, expect the inner object type is either CellKnowledgeEntry or CellKnowledgeRange but actual type value is " + header.Type, null); } } currentIndex = index; }
/// <summary> /// Used to de-serialize the element. /// </summary> /// <param name="byteArray">A Byte array</param> /// <param name="currentIndex">Start position</param> /// <param name="lengthOfItems">The length of the items</param> protected override void DeserializeItemsFromByteArray(byte[] byteArray, ref int currentIndex, int lengthOfItems) { int index = currentIndex; if (lengthOfItems != 0) { throw new StreamObjectParseErrorException(currentIndex, "LeafNodeObjectData", "Stream Object over-parse error", null); } this.Signature = StreamObject.GetCurrent <SignatureObject>(byteArray, ref index); this.DataSize = StreamObject.GetCurrent <DataSizeObject>(byteArray, ref index); // Try to read StreamObjectHeaderStart to see there is data hash object or not StreamObjectHeaderStart streamObjectHeader; if ((StreamObjectHeaderStart.TryParse(byteArray, index, out streamObjectHeader)) != 0) { if (streamObjectHeader.Type == StreamObjectTypeHeaderStart.DataHashObject) { this.DataHash = StreamObject.GetCurrent <DataHashObject>(byteArray, ref index); } } currentIndex = index; }
/// <summary> /// This method is used to parse the actual 16bit or 32bit stream header. /// </summary> /// <param name="byteArray">Specify the Byte array.</param> /// <param name="startIndex">Specify the start position.</param> /// <param name="streamObjectHeader">Specify the out value for the parse result.</param> /// <returns>Return true if success, otherwise returns false. </returns> public static int TryParse(byte[] byteArray, int startIndex, out StreamObjectHeaderStart streamObjectHeader) { uint headerType = (uint)(byteArray[startIndex] & 0x3); if (headerType == StreamObjectHeaderStart.StreamObjectHeaderStart16bit) { streamObjectHeader = new StreamObjectHeaderStart16bit(); } else { if (headerType == StreamObjectHeaderStart.StreamObjectHeaderStart32bit) { streamObjectHeader = new StreamObjectHeaderStart32bit(); } else { streamObjectHeader = null; return 0; } } try { return streamObjectHeader.DeserializeFromByteArray(byteArray, startIndex); } catch (InvalidOperationException) { streamObjectHeader = null; return 0; } }
/// <summary> /// This method is used to parse the actual 16bit or 32bit stream header. /// </summary> /// <param name="byteArray">Specify the Byte array.</param> /// <param name="startIndex">Specify the start position.</param> /// <param name="streamObjectHeader">Specify the out value for the parse result.</param> /// <returns>Return true if success, otherwise returns false. </returns> public static int TryParse(byte[] byteArray, int startIndex, out StreamObjectHeaderStart streamObjectHeader) { uint headerType = (uint)(byteArray[startIndex] & 0x3); if (headerType == StreamObjectHeaderStart.StreamObjectHeaderStart16bit) { streamObjectHeader = new StreamObjectHeaderStart16bit(); } else { if (headerType == StreamObjectHeaderStart.StreamObjectHeaderStart32bit) { streamObjectHeader = new StreamObjectHeaderStart32bit(); } else { streamObjectHeader = null; return(0); } } try { return(streamObjectHeader.DeserializeFromByteArray(byteArray, startIndex)); } catch (InvalidOperationException) { streamObjectHeader = null; return(0); } }
/// <summary> /// Deserialize sub response data from byte array. /// </summary> /// <param name="byteArray">The byte array which contains sub response data.</param> /// <param name="currentIndex">The index special where to start.</param> protected override void DeserializeSubResponseDataFromByteArray(byte[] byteArray, ref int currentIndex) { int index = currentIndex; int headerLength = 0; StreamObjectHeaderStart header; if ((headerLength = StreamObjectHeaderStart.TryParse(byteArray, index, out header)) == 0) { throw new ResponseParseErrorException(index, "Failed to parse the AllocateExtendedGuidRangeData stream object header", null); } if (header.Type != StreamObjectTypeHeaderStart.AllocateExtendedGUIDRangeResponse) { throw new ResponseParseErrorException(index, "Failed to extract the AllocateExtendedGuidRangeData stream object header type, unexpected value " + header.Type, null); } this.AllocateExtendedGUIDRangeResponse = new StreamObjectHeaderStart32bit(header.Type, header.Length); index += headerLength; int currentTmpIndex = index; byte[] guidarray = new byte[16]; Array.Copy(byteArray, index, guidarray, 0, 16); this.GUIDComponent = new Guid(guidarray); index += 16; this.IntegerRangeMin = BasicObject.Parse <Compact64bitInt>(byteArray, ref index); this.IntegerRangeMax = BasicObject.Parse <Compact64bitInt>(byteArray, ref index); if (index - currentTmpIndex != header.Length) { throw new ResponseParseErrorException(-1, "AllocateExtendedGuidRangeData object over-parse error", null); } currentIndex = index; }
/// <summary> /// Try to get current object, true will returned if success. /// </summary> /// <typeparam name="T">The type of target object.</typeparam> /// <param name="byteArray">The byte array.</param> /// <param name="index">The position where to start.</param> /// <param name="streamObject">The instance that want to get.</param> /// <returns>The result of whether get success.</returns> public static bool TryGetCurrent <T>(byte[] byteArray, ref int index, out T streamObject) where T : StreamObject { int tmpIndex = index; streamObject = null; int length = 0; StreamObjectHeaderStart streamObjectHeader; if ((length = StreamObjectHeaderStart.TryParse(byteArray, tmpIndex, out streamObjectHeader)) == 0) { return(false); } tmpIndex += length; if (StreamObjectTypeMapping.Keys.Contains(streamObjectHeader.Type) && StreamObjectTypeMapping[streamObjectHeader.Type] == typeof(T)) { streamObject = ParseStreamObject(streamObjectHeader, byteArray, ref tmpIndex) as T; } else { return(false); } index = tmpIndex; return(true); }
/// <summary> /// Get current stream object. /// </summary> /// <typeparam name="T">The type of target object.</typeparam> /// <param name="byteArray">The byte array which contains message.</param> /// <param name="index">The position where to start.</param> /// <returns>The current object instance.</returns> public static T GetCurrent <T>(byte[] byteArray, ref int index) where T : StreamObject { int tmpIndex = index; int length = 0; StreamObjectHeaderStart streamObjectHeader; if ((length = StreamObjectHeaderStart.TryParse(byteArray, tmpIndex, out streamObjectHeader)) == 0) { throw new StreamObjectParseErrorException(tmpIndex, typeof(T).Name, "Failed to extract either 16bit or 32bit stream object header in the current index.", null); } tmpIndex += length; StreamObject streamObject = ParseStreamObject(streamObjectHeader, byteArray, ref tmpIndex); if (!(streamObject is T)) { throw new StreamObjectParseErrorException(tmpIndex, typeof(T).Name, string.Format("Failed to get stream object as expect type {0}, actual type is {1}", typeof(T).Name, StreamObjectTypeMapping[streamObjectHeader.Type].Name), null); } // Store the current index to the ref parameter index. index = tmpIndex; return(streamObject as T); }
/// <summary> /// Used to de-serialize data element. /// </summary> /// <param name="byteArray">Byte array</param> /// <param name="startIndex">Start position</param> /// <returns>The length of the array</returns> public override int DeserializeDataElementDataFromByteArray(byte[] byteArray, int startIndex) { int index = startIndex; this.StorageManifestSchemaGUID = StreamObject.GetCurrent <StorageManifestSchemaGUID>(byteArray, ref index); this.StorageManifestRootDeclareList = new List <StorageManifestRootDeclare>(); StreamObjectHeaderStart header; int headerLength = 0; while ((headerLength = StreamObjectHeaderStart.TryParse(byteArray, index, out header)) != 0) { if (header.Type == StreamObjectTypeHeaderStart.StorageManifestRootDeclare) { index += headerLength; this.StorageManifestRootDeclareList.Add(StreamObject.ParseStreamObject(header, byteArray, ref index) as StorageManifestRootDeclare); } else { throw new DataElementParseErrorException(index, "Failed to parse StorageManifestDataElement, expect the inner object type StorageManifestRootDeclare, but actual type value is " + header.Type, null); } } return(index - startIndex); }
/// <summary> /// Used to de-serialize the element. /// </summary> /// <param name="byteArray">A Byte array</param> /// <param name="currentIndex">Start position</param> /// <param name="lengthOfItems">The length of the items</param> protected override void DeserializeItemsFromByteArray(byte[] byteArray, ref int currentIndex, int lengthOfItems) { if (lengthOfItems != 0) { throw new StreamObjectParseErrorException(currentIndex, "ObjectGroupMetadataDeclarations", "Stream object over-parse error", null); } int index = currentIndex; int headerLength = 0; StreamObjectHeaderStart header; this.ObjectGroupMetadataList = new List <ObjectGroupMetadata>(); while ((headerLength = StreamObjectHeaderStart.TryParse(byteArray, index, out header)) != 0) { index += headerLength; if (header.Type == StreamObjectTypeHeaderStart.ObjectGroupMetadata) { this.ObjectGroupMetadataList.Add(StreamObject.ParseStreamObject(header, byteArray, ref index) as ObjectGroupMetadata); } else { throw new StreamObjectParseErrorException(index, "ObjectGroupDeclarations", "Failed to parse ObjectGroupMetadataDeclarations, expect the inner object type ObjectGroupMetadata, but actual type value is " + header.Type, null); } } currentIndex = index; }
/// <summary> /// This method is used to deserialize the items of the specialized knowledge from the byte array. /// </summary> /// <param name="byteArray">Specify the byte array.</param> /// <param name="currentIndex">Specify the start index from the byte array.</param> /// <param name="lengthOfItems">Specify the current length of items in the specialized knowledge.</param> protected override void DeserializeItemsFromByteArray(byte[] byteArray, ref int currentIndex, int lengthOfItems) { if (lengthOfItems != 16) { throw new KnowledgeParseErrorException(currentIndex, "Failed to check the stream object header length in the DeserializeSpecializedKnowledgeFromByteArray", null); } int index = currentIndex; byte[] temp = new byte[16]; Array.Copy(byteArray, index, temp, 0, 16); this.GUID = new Guid(temp); if (!KnowledgeTypeGuidMapping.Keys.Contains(this.GUID)) { throw new KnowledgeParseErrorException(index, string.Format("Failed to check the special knowledge guid value in the DeserializeSpecializedKnowledgeFromByteArray, the value {0 }is not defined", this.GUID), null); } index += 16; this.specializedKnowledgeData = Activator.CreateInstance(KnowledgeTypeGuidMapping[this.GUID]) as SpecializedKnowledgeData; StreamObjectHeaderStart specializedKnowledgeDataHeader; int headerLength = 0; if ((headerLength = StreamObjectHeaderStart.TryParse(byteArray, index, out specializedKnowledgeDataHeader)) == 0) { throw new KnowledgeParseErrorException(index, "Failed to parse the specialized knowledge data stream object header", null); } if (!KnowledgeEnumGuidMapping.Keys.Contains(specializedKnowledgeDataHeader.Type)) { throw new KnowledgeParseErrorException(index, "Unexpected specialized knowledge data stream object header type " + specializedKnowledgeDataHeader.Type, null); } if (KnowledgeEnumGuidMapping[specializedKnowledgeDataHeader.Type] != this.GUID) { throw new KnowledgeParseErrorException(index, "Unmatched specialized knowledge data stream object header type and the specified guid value", null); } index += headerLength; try { index += this.specializedKnowledgeData.DeserializeFromByteArray(specializedKnowledgeDataHeader, byteArray, index); } catch (StreamObjectParseErrorException streamObjectException) { throw new KnowledgeParseErrorException(index, streamObjectException); } catch (BasicObjectParseErrorException basicObjectException) { throw new KnowledgeParseErrorException(index, basicObjectException); } currentIndex = index; }
/// <summary> /// Used to return the length of this element. /// </summary> /// <param name="header">Then instance of StreamObjectHeaderStart.</param> /// <param name="byteArray">The byte list</param> /// <param name="startIndex">The position where to start.</param> /// <returns>The element length</returns> public int DeserializeFromByteArray(StreamObjectHeaderStart header, byte[] byteArray, int startIndex) { this.StreamObjectType = header.Type; this.LengthOfItems = header.Length; if (header is StreamObjectHeaderStart32bit) { if (header.Length == 32767) { this.LengthOfItems = (int)(header as StreamObjectHeaderStart32bit).LargeLength.DecodedValue; } } int index = startIndex; this.StreamObjectHeaderStart = header; this.DeserializeItemsFromByteArray(byteArray, ref index, this.LengthOfItems); if (CompoundTypes.Contains(this.StreamObjectType)) { StreamObjectHeaderEnd end = null; BitReader bitReader = new BitReader(byteArray, index); int aField = bitReader.ReadInt32(2); if (aField == 0x1) { end = BasicObject.Parse <StreamObjectHeaderEnd8bit>(byteArray, ref index); } if (aField == 0x3) { end = BasicObject.Parse <StreamObjectHeaderEnd16bit>(byteArray, ref index); } if ((int)end.Type != (int)this.StreamObjectType) { throw new StreamObjectParseErrorException(index, null, "Unexpected the stream header end value " + (int)this.StreamObjectType, null); } this.StreamObjectHeaderEnd = end; } // Capture all the type related requirements if (SharedContext.Current.IsMsFsshttpRequirementsCaptured) { new MsfsshttpbAdapterCapture().InvokeCaptureMethod(this.GetType(), this, SharedContext.Current.Site); } return(index - startIndex); }
/// <summary> /// Parse stream object from byte array. /// </summary> /// <param name="header">The instance of StreamObjectHeaderStart.</param> /// <param name="byteArray">The byte array.</param> /// <param name="index">The position where to start.</param> /// <returns>The instance of StreamObject.</returns> public static StreamObject ParseStreamObject(StreamObjectHeaderStart header, byte[] byteArray, ref int index) { if (StreamObjectTypeMapping.Keys.Contains(header.Type)) { StreamObject streamObject = Activator.CreateInstance(StreamObjectTypeMapping[header.Type]) as StreamObject; try { index += streamObject.DeserializeFromByteArray(header, byteArray, index); } catch (BasicObjectParseErrorException e) { throw new StreamObjectParseErrorException(index, StreamObjectTypeMapping[header.Type].Name, e); } return(streamObject); } int tmpIndex = index; tmpIndex -= header.HeaderType == StreamObjectHeaderStart.StreamObjectHeaderStart16bit ? 2 : 4; throw new StreamObjectParseErrorException(tmpIndex, "Unknown", string.Format("Failed to create the specified stream object instance, the type {0} of stream object header in the current index is not defined", (int)header.Type), null); }
/// <summary> /// Used to de-serialize the data element. /// </summary> /// <param name="byteArray">Byte array</param> /// <param name="startIndex">Start position</param> /// <returns>The length of the element</returns> public override int DeserializeDataElementDataFromByteArray(byte[] byteArray, int startIndex) { int index = startIndex; int headerLength = 0; StreamObjectHeaderStart header; bool isStorageIndexManifestMappingExist = false; while ((headerLength = StreamObjectHeaderStart.TryParse(byteArray, index, out header)) != 0) { index += headerLength; if (header.Type == StreamObjectTypeHeaderStart.StorageIndexManifestMapping) { if (isStorageIndexManifestMappingExist) { throw new DataElementParseErrorException(index - headerLength, "Failed to parse StorageIndexDataElement, only can contain zero or one StorageIndexManifestMapping", null); } this.StorageIndexManifestMapping = StreamObject.ParseStreamObject(header, byteArray, ref index) as StorageIndexManifestMapping; isStorageIndexManifestMappingExist = true; } else if (header.Type == StreamObjectTypeHeaderStart.StorageIndexCellMapping) { this.StorageIndexCellMappingList.Add(StreamObject.ParseStreamObject(header, byteArray, ref index) as StorageIndexCellMapping); } else if (header.Type == StreamObjectTypeHeaderStart.StorageIndexRevisionMapping) { this.StorageIndexRevisionMappingList.Add(StreamObject.ParseStreamObject(header, byteArray, ref index) as StorageIndexRevisionMapping); } else { throw new DataElementParseErrorException(index - headerLength, "Failed to parse StorageIndexDataElement, expect the inner object type StorageIndexCellMapping or StorageIndexRevisionMapping, but actual type value is " + header.Type, null); } } return(index - startIndex); }
/// <summary> /// This method is used to convert the element into a byte List /// </summary> /// <returns>Return the Byte List</returns> public List <byte> SerializeToByteList() { this.RequestStart = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.Request, 0); this.UserAgentStart = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.UserAgent, 0); this.UserAgentGUID = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.UserAgentGUID, 16); this.UserAgentVersion = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.UserAgentversion, 4); this.UserAgentEnd = new StreamObjectHeaderEnd16bit((int)StreamObjectTypeHeaderEnd.UserAgent); this.CellRequestEnd = new StreamObjectHeaderEnd16bit((int)StreamObjectTypeHeaderEnd.Request); List <byte> byteList = new List <byte>(); // Protocol Version byteList.AddRange(LittleEndianBitConverter.GetBytes(this.ProtocolVersion)); // Minimum Version byteList.AddRange(LittleEndianBitConverter.GetBytes(this.MinimumVersion)); // Signature byteList.AddRange(LittleEndianBitConverter.GetBytes(this.Signature)); // Request Start byteList.AddRange(this.RequestStart.SerializeToByteList()); // User Agent Start byteList.AddRange(this.UserAgentStart.SerializeToByteList()); // User Agent GUID byteList.AddRange(this.UserAgentGUID.SerializeToByteList()); // GUID byteList.AddRange(this.GUID.ToByteArray()); // User Agent Version byteList.AddRange(this.UserAgentVersion.SerializeToByteList()); // Version byteList.AddRange(LittleEndianBitConverter.GetBytes(this.Version)); // User Agent End byteList.AddRange(this.UserAgentEnd.SerializeToByteList()); if (this.IsRequestHashingOptionsUsed) { List <byte> hashSchemaList = this.RequestHashingSchema.SerializeToByteList(); this.RequestHashingOptionsDeclaration = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.RequestHashOptions, hashSchemaList.Count + 1); // Request Hashing Options Declaration byteList.AddRange(this.RequestHashingOptionsDeclaration.SerializeToByteList()); // Request Hashing Schema byteList.AddRange(hashSchemaList); // Reserve BitWriter bw = new BitWriter(1); bw.AppendInit32(this.Reserve1, 1); bw.AppendInit32(this.Reserve2, 1); bw.AppendInit32(this.RequestDataElementHashesInsteadofData, 1); bw.AppendInit32(this.RequestDataElementHashes, 1); bw.AppendInit32(this.Reserve3, 4); byteList.AddRange(bw.Bytes); } // Sub-requests if (this.SubRequests != null && this.SubRequests.Count != 0) { foreach (FsshttpbCellSubRequest subRequest in this.SubRequests) { byteList.AddRange(subRequest.SerializeToByteList()); } } else { throw new InvalidOperationException("MUST contain sub request in request structure which is defined in the MS-FSSHTTPB."); } // Data Element Package if (this.DataElementPackage != null) { byteList.AddRange(this.DataElementPackage.SerializeToByteList()); } // Cell Request End byteList.AddRange(this.CellRequestEnd.SerializeToByteList()); return(byteList); }
/// <summary> /// Deserialize response from byte array. /// </summary> /// <param name="byteArray">Server returned message.</param> /// <param name="startIndex">The index special where start.</param> /// <returns>The instance of CellResponse.</returns> public static FsshttpbResponse DeserializeResponseFromByteArray(byte[] byteArray, int startIndex) { int index = startIndex; FsshttpbResponse response = new FsshttpbResponse(); response.ProtocolVersion = LittleEndianBitConverter.ToUInt16(byteArray, index); index += 2; response.MinimumVersion = LittleEndianBitConverter.ToUInt16(byteArray, index); index += 2; response.Signature = LittleEndianBitConverter.ToUInt64(byteArray, index); index += 8; int length = 0; StreamObjectHeaderStart streamObjectHeader; if ((length = StreamObjectHeaderStart.TryParse(byteArray, index, out streamObjectHeader)) == 0) { throw new ResponseParseErrorException(index, "Failed to parse the response header", null); } if (!(streamObjectHeader is StreamObjectHeaderStart32bit)) { throw new ResponseParseErrorException(index, "Unexpected 16-bit response stream object header, expect 32-bit stream object header for Response", null); } if (streamObjectHeader.Type != StreamObjectTypeHeaderStart.FsshttpbResponse) { throw new ResponseParseErrorException(index, "Failed to extract the response header type, unexpected value " + streamObjectHeader.Type, null); } if (streamObjectHeader.Length != 1) { throw new ResponseParseErrorException(index, "Response object over-parse error", null); } index += length; response.ResponseStart = streamObjectHeader as StreamObjectHeaderStart32bit; response.Status = (byteArray[index] & 0x1) == 0x1 ? true : false; response.Reserved = (byte)(byteArray[index] >> 1); index += 1; try { if (response.Status) { response.ResponseError = StreamObject.GetCurrent <ResponseError>(byteArray, ref index); response.DataElementPackage = null; response.CellSubResponses = null; } else { DataElementPackage package; if (StreamObject.TryGetCurrent <DataElementPackage>(byteArray, ref index, out package)) { response.DataElementPackage = package; } response.CellSubResponses = new List <FsshttpbSubResponse>(); FsshttpbSubResponse subResponse; while (StreamObject.TryGetCurrent <FsshttpbSubResponse>(byteArray, ref index, out subResponse)) { response.CellSubResponses.Add(subResponse); } } response.ResponseEnd = BasicObject.Parse <StreamObjectHeaderEnd16bit>(byteArray, ref index); } catch (StreamObjectParseErrorException streamObjectException) { throw new ResponseParseErrorException(index, streamObjectException); } catch (DataElementParseErrorException dataElementException) { throw new ResponseParseErrorException(index, dataElementException); } catch (KnowledgeParseErrorException knowledgeException) { throw new ResponseParseErrorException(index, knowledgeException); } if (index != byteArray.Length) { throw new ResponseParseErrorException(index, "Failed to pass the whole response, not reach the end of the byte array", null); } return(response); }
/// <summary> /// This method is used to convert the element into a byte List /// </summary> /// <returns>Return the Byte List</returns> public List<byte> SerializeToByteList() { this.RequestStart = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.Request, 0); this.UserAgentStart = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.UserAgent, 0); this.UserAgentGUID = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.UserAgentGUID, 16); this.UserAgentVersion = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.UserAgentversion, 4); this.UserAgentEnd = new StreamObjectHeaderEnd16bit((int)StreamObjectTypeHeaderEnd.UserAgent); this.CellRequestEnd = new StreamObjectHeaderEnd16bit((int)StreamObjectTypeHeaderEnd.Request); List<byte> byteList = new List<byte>(); // Protocol Version byteList.AddRange(LittleEndianBitConverter.GetBytes(this.ProtocolVersion)); // Minimum Version byteList.AddRange(LittleEndianBitConverter.GetBytes(this.MinimumVersion)); // Signature byteList.AddRange(LittleEndianBitConverter.GetBytes(this.Signature)); // Request Start byteList.AddRange(this.RequestStart.SerializeToByteList()); // User Agent Start byteList.AddRange(this.UserAgentStart.SerializeToByteList()); // User Agent GUID byteList.AddRange(this.UserAgentGUID.SerializeToByteList()); // GUID byteList.AddRange(this.GUID.ToByteArray()); // User Agent Version byteList.AddRange(this.UserAgentVersion.SerializeToByteList()); // Version byteList.AddRange(LittleEndianBitConverter.GetBytes(this.Version)); // User Agent End byteList.AddRange(this.UserAgentEnd.SerializeToByteList()); if (this.IsRequestHashingOptionsUsed) { List<byte> hashSchemaList = this.RequestHashingSchema.SerializeToByteList(); this.RequestHashingOptionsDeclaration = new StreamObjectHeaderStart32bit(StreamObjectTypeHeaderStart.RequestHashOptions, hashSchemaList.Count + 1); // Request Hashing Options Declaration byteList.AddRange(this.RequestHashingOptionsDeclaration.SerializeToByteList()); // Request Hashing Schema byteList.AddRange(hashSchemaList); // Reserve BitWriter bw = new BitWriter(1); bw.AppendInit32(this.Reserve1, 1); bw.AppendInit32(this.Reserve2, 1); bw.AppendInit32(this.RequestDataElementHashesInsteadofData, 1); bw.AppendInit32(this.RequestDataElementHashes, 1); bw.AppendInit32(this.Reserve3, 4); byteList.AddRange(bw.Bytes); } // Sub-requests if (this.SubRequests != null && this.SubRequests.Count != 0) { foreach (FsshttpbCellSubRequest subRequest in this.SubRequests) { byteList.AddRange(subRequest.SerializeToByteList()); } } else { throw new InvalidOperationException("MUST contain sub request in request structure which is defined in the MS-FSSHTTPB."); } // Data Element Package if (this.DataElementPackage != null) { byteList.AddRange(this.DataElementPackage.SerializeToByteList()); } // Cell Request End byteList.AddRange(this.CellRequestEnd.SerializeToByteList()); return byteList; }