//******************************************************************************************************
// Payload.cs - Gbtc
//
// Copyright © 2012, Grid Protection Alliance. All Rights Reserved.
//
// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
// the NOTICE file distributed with this work for additional information regarding copyright ownership.
// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may
// not use this file except in compliance with the License. You may obtain a copy of the License at:
//
// http://www.opensource.org/licenses/MIT
//
// Unless agreed to in writing, the subject software distributed under the License is distributed on an
// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
// License for the specific language governing permissions and limitations.
//
// Code Modification History:
// ----------------------------------------------------------------------------------------------------
// 07/06/2006 - Pinal C. Patel
// Original version of source code generated.
// 09/29/2008 - J. Ritchie Carroll
// Converted to C#.
// 09/14/2009 - Stephen C. Wills
// Added new header and license agreement.
// 09/21/2009 - Pinal C. Patel
// Fixed a bug in AddHeader() that was putting the length of the provided buffer in the header
// instead of the length specified in the method parameter.
// 01/30/2011 - Pinal C. Patel
// Fixed a bug in AddHeader() that created an insufficient return buffer when the specified offset
// was non-zero resulting in "out of bounds" exception.
// 08/18/2011 - J. Ritchie Carroll
// Added processing overloads to be able to use socket asynchronous event arguments and performed
// minor code clean up and code review.
// 12/13/2012 - Starlynn Danyelle Gilliam
// Modified Header.
//
//******************************************************************************************************
using System;
namespace GSF.Communication
{
///
/// A helper class containing methods for manipulation of payload.
///
public static class Payload
{
///
/// Specifies the length of the segment in a "Payload-Aware" transmission that contains the payload length.
///
public const int LengthSegment = 4;
///
/// Default byte sequence used to mark the beginning of the payload in a "Payload-Aware" transmissions.
///
public static byte[] DefaultMarker = { 0xAA, 0xBB, 0xCC, 0xDD };
///
/// Adds header containing the to the payload in the for "Payload-Aware" transmission.
///
/// The buffer containing the payload.
/// The offset in the at which the payload starts.
/// The length of the payload in the starting at the .
/// The byte sequence used to mark the beginning of the payload in a "Payload-Aware" transmissions.
/// The endian order to apply to payload size encoding.
public static void AddHeader(ref byte[] buffer, ref int offset, ref int length, byte[] marker, EndianOrder endianOrder)
{
// Note that the resulting buffer will be at least 4 bytes bigger than the payload
// Resulting buffer = x bytes for payload marker + 4 bytes for the payload size + The payload
byte[] result = new byte[length + marker.Length + LengthSegment];
// First, copy the payload marker to the buffer, if any
if (marker.Length > 0)
Buffer.BlockCopy(marker, 0, result, 0, marker.Length);
// Then, copy the payload's size to the buffer after the payload marker
Buffer.BlockCopy(endianOrder.GetBytes(length), 0, result, marker.Length, LengthSegment);
// At last, copy the payload after the payload marker and payload size
Buffer.BlockCopy(buffer, offset, result, marker.Length + LengthSegment, length);
buffer = result;
offset = 0;
length = buffer.Length;
}
///
/// Determines whether or not the contains the header information of a "Payload-Aware" transmission.
///
/// The buffer to be checked at index zero.
/// The byte sequence used to mark the beginning of the payload in a "Payload-Aware" transmissions.
/// true if the buffer contains "Payload-Aware" transmission header; otherwise false.
public static bool HasHeader(byte[] buffer, byte[] marker)
{
for (int i = 0; i < marker.Length; i++)
{
if (buffer[i] != marker[i])
return false;
}
return true;
}
///
/// Determines the length of a payload in a "Payload-Aware" transmission from the payload header information.
///
/// The buffer containing payload header information starting at index zero.
/// The length of valid data within in .
/// The byte sequence used to mark the beginning of the payload in a "Payload-Aware" transmissions.
/// The endian order to apply to payload size decoding.
/// Length of the payload.
public static int ExtractLength(byte[] buffer, int length, byte[] marker, EndianOrder endianOrder)
{
// Check to see if buffer is at least as big as the payload header
if (length < marker.Length + LengthSegment)
return -1;
// Check to see if buffer has the payload marker
return !HasHeader(buffer, marker) ? 0 : endianOrder.ToInt32(buffer, marker.Length);
}
}
}