private static void MarshalAndVerifyHttpHeader(IntPtr httpHeaderPtr,
ref Interop.WebSocket.HttpHeader httpHeader)
{
Debug.Assert(httpHeaderPtr != IntPtr.Zero, "'currentHttpHeaderPtr' MUST NOT be IntPtr.Zero.");
IntPtr httpHeaderNamePtr = Marshal.ReadIntPtr(httpHeaderPtr);
IntPtr lengthPtr = IntPtr.Add(httpHeaderPtr, IntPtr.Size);
int length = Marshal.ReadInt32(lengthPtr);
Debug.Assert(length >= 0, "'length' MUST NOT be negative.");
if (httpHeaderNamePtr != IntPtr.Zero)
{
httpHeader.Name = Marshal.PtrToStringAnsi(httpHeaderNamePtr, length);
}
if ((httpHeader.Name == null && length != 0) ||
(httpHeader.Name != null && length != httpHeader.Name.Length))
{
Debug.Assert(false, "The length of 'httpHeader.Name' MUST MATCH 'length'.");
throw new AccessViolationException();
}
// structure of Interop.WebSocket.HttpHeader:
// Name = string*
// NameLength = uint*
// Value = string*
// ValueLength = uint*
// NOTE - All fields in the object are pointers to the actual value, hence the use of
// n * IntPtr.Size to get to the correct place in the object.
int valueOffset = 2 * IntPtr.Size;
int lengthOffset = 3 * IntPtr.Size;
IntPtr httpHeaderValuePtr =
Marshal.ReadIntPtr(IntPtr.Add(httpHeaderPtr, valueOffset));
lengthPtr = IntPtr.Add(httpHeaderPtr, lengthOffset);
length = Marshal.ReadInt32(lengthPtr);
httpHeader.Value = Marshal.PtrToStringAnsi(httpHeaderValuePtr, (int)length);
if ((httpHeader.Value == null && length != 0) ||
(httpHeader.Value != null && length != httpHeader.Value.Length))
{
Debug.Assert(false, "The length of 'httpHeader.Value' MUST MATCH 'length'.");
throw new AccessViolationException();
}
}