Example #1
0
        internal static void UnwrapWebSocketBuffer(Interop.WebSocket.Buffer buffer,
                                                   WebSocketProtocolComponent.BufferType bufferType,
                                                   out IntPtr bufferData,
                                                   out uint bufferLength)
        {
            bufferData   = IntPtr.Zero;
            bufferLength = 0;

            switch (bufferType)
            {
            case WebSocketProtocolComponent.BufferType.Close:
                bufferData   = buffer.CloseStatus.ReasonData;
                bufferLength = buffer.CloseStatus.ReasonLength;
                break;

            case WebSocketProtocolComponent.BufferType.None:
            case WebSocketProtocolComponent.BufferType.BinaryFragment:
            case WebSocketProtocolComponent.BufferType.BinaryMessage:
            case WebSocketProtocolComponent.BufferType.UTF8Fragment:
            case WebSocketProtocolComponent.BufferType.UTF8Message:
            case WebSocketProtocolComponent.BufferType.PingPong:
            case WebSocketProtocolComponent.BufferType.UnsolicitedPong:
                bufferData   = buffer.Data.BufferData;
                bufferLength = buffer.Data.BufferLength;
                break;

            default:
                Debug.Assert(false,
                             string.Format(CultureInfo.InvariantCulture,
                                           "BufferType '{0}' is invalid/unknown.",
                                           bufferType));
                break;
            }
        }
Example #2
0
        internal ArraySegment <byte> ConvertNativeBuffer(WebSocketProtocolComponent.Action action,
                                                         Interop.WebSocket.Buffer buffer,
                                                         WebSocketProtocolComponent.BufferType bufferType)
        {
            ThrowIfDisposed();

            IntPtr bufferData;
            uint   bufferLength;

            UnwrapWebSocketBuffer(buffer, bufferType, out bufferData, out bufferLength);

            if (bufferData == IntPtr.Zero)
            {
                return(ArraySegment <byte> .Empty);
            }

            if (this.IsNativeBuffer(bufferData, bufferLength))
            {
                return(new ArraySegment <byte>(_internalBuffer.Array,
                                               this.GetOffset(bufferData),
                                               (int)bufferLength));
            }

            Debug.Assert(false, "'buffer' MUST reference a memory segment within the pinned InternalBuffer.");
            // Indicates a violation in the contract with native Websocket.dll and could indicate
            // memory corruption because the internal buffer is shared between managed and native code
            throw new AccessViolationException();
        }
Example #3
0
        // This method is not thread safe. It must only be called after enforcing at most 1 outstanding send operation
        internal bool IsPinnedSendPayloadBuffer(Interop.WebSocket.Buffer buffer,
                                                WebSocketProtocolComponent.BufferType bufferType)
        {
            if (_sendBufferState != SendBufferState.SendPayloadSpecified)
            {
                return(false);
            }

            IntPtr bufferData;
            uint   bufferSize;

            UnwrapWebSocketBuffer(buffer, bufferType, out bufferData, out bufferSize);

            long nativeBufferStartAddress = bufferData.ToInt64();
            long nativeBufferEndAddress   = nativeBufferStartAddress + bufferSize;

            return(nativeBufferStartAddress >= _pinnedSendBufferStartAddress &&
                   nativeBufferEndAddress >= _pinnedSendBufferStartAddress &&
                   nativeBufferStartAddress <= _pinnedSendBufferEndAddress &&
                   nativeBufferEndAddress <= _pinnedSendBufferEndAddress);
        }
Example #4
0
        // This method is not thread safe. It must only be called after enforcing at most 1 outstanding send operation
        internal ArraySegment <byte> ConvertPinnedSendPayloadFromNative(Interop.WebSocket.Buffer buffer,
                                                                        WebSocketProtocolComponent.BufferType bufferType)
        {
            if (!IsPinnedSendPayloadBuffer(buffer, bufferType))
            {
                // Indicates a violation in the API contract that could indicate
                // memory corruption because the pinned sendbuffer is shared between managed and native code
                throw new AccessViolationException();
            }

            Debug.Assert(Marshal.UnsafeAddrOfPinnedArrayElement(_pinnedSendBuffer.Array,
                                                                _pinnedSendBuffer.Offset).ToInt64() == _pinnedSendBufferStartAddress,
                         "'m_PinnedSendBuffer.Array' MUST be pinned during the entire send operation.");

            IntPtr bufferData;
            uint   bufferSize;

            UnwrapWebSocketBuffer(buffer, bufferType, out bufferData, out bufferSize);

            int internalOffset = (int)(bufferData.ToInt64() - _pinnedSendBufferStartAddress);

            return(new ArraySegment <byte>(_pinnedSendBuffer.Array, _pinnedSendBuffer.Offset + internalOffset, (int)bufferSize));
        }
Example #5
0
        internal void ValidateNativeBuffers(WebSocketProtocolComponent.Action action,
                                            WebSocketProtocolComponent.BufferType bufferType,
                                            Interop.WebSocket.Buffer[] dataBuffers,
                                            uint dataBufferCount)
        {
            Debug.Assert(dataBufferCount <= (uint)int.MaxValue,
                         "'dataBufferCount' MUST NOT be bigger than Int32.MaxValue.");
            Debug.Assert(dataBuffers != null, "'dataBuffers' MUST NOT be NULL.");

            ThrowIfDisposed();
            if (dataBufferCount > dataBuffers.Length)
            {
                Debug.Assert(false, "'dataBufferCount' MUST NOT be bigger than 'dataBuffers.Length'.");
                // Indicates a violation in the contract with native Websocket.dll and could indicate
                // memory corruption because the internal buffer is shared between managed and native code
                throw new AccessViolationException();
            }

            int  count          = dataBuffers.Length;
            bool isSendActivity = action == WebSocketProtocolComponent.Action.IndicateSendComplete ||
                                  action == WebSocketProtocolComponent.Action.SendToNetwork;

            if (isSendActivity)
            {
                count = (int)dataBufferCount;
            }

            bool nonZeroBufferFound = false;

            for (int i = 0; i < count; i++)
            {
                Interop.WebSocket.Buffer dataBuffer = dataBuffers[i];

                IntPtr bufferData;
                uint   bufferLength;
                UnwrapWebSocketBuffer(dataBuffer, bufferType, out bufferData, out bufferLength);

                if (bufferData == IntPtr.Zero)
                {
                    continue;
                }

                nonZeroBufferFound = true;

                bool isPinnedSendPayloadBuffer = IsPinnedSendPayloadBuffer(dataBuffer, bufferType);

                if (bufferLength > GetMaxBufferSize())
                {
                    if (!isSendActivity || !isPinnedSendPayloadBuffer)
                    {
                        Debug.Assert(false,
                                     "'dataBuffer.BufferLength' MUST NOT be bigger than 'm_ReceiveBufferSize' and 'm_SendBufferSize'.");
                        // Indicates a violation in the contract with native Websocket.dll and could indicate
                        // memory corruption because the internal buffer is shared between managed and native code
                        throw new AccessViolationException();
                    }
                }

                if (!isPinnedSendPayloadBuffer && !IsNativeBuffer(bufferData, bufferLength))
                {
                    Debug.Assert(false,
                                 "WebSocketGetAction MUST return a pointer within the pinned internal buffer.");
                    // Indicates a violation in the contract with native Websocket.dll and could indicate
                    // memory corruption because the internal buffer is shared between managed and native code
                    throw new AccessViolationException();
                }
            }

            if (!nonZeroBufferFound &&
                action != WebSocketProtocolComponent.Action.NoAction &&
                action != WebSocketProtocolComponent.Action.IndicateReceiveComplete &&
                action != WebSocketProtocolComponent.Action.IndicateSendComplete)
            {
                Debug.Assert(false, "At least one 'dataBuffer.Buffer' MUST NOT be NULL.");
            }
        }