Example #1
0
 // Set the error code only if there is an error (i.e. nativeError >= 0). Otherwise the code ----s up on deserialization
 // as the Exception..ctor() throws on setting HResult to 0. The default for HResult is -2147467259.
 private void SetErrorCodeOnError(int nativeError)
 {
     if (!WebSocketProtocolComponent.Succeeded(nativeError))
     {
         this.HResult = nativeError;
     }
 }
Example #2
0
 private SafeHandle CreateWebSocketHandle()
 {
     Debug.Assert(_properties != null, "'_properties' MUST NOT be NULL.");
     return(WebSocketProtocolComponent.WebSocketCreateServerHandle(
                _properties,
                _properties.Length));
 }
Example #3
0
 protected override bool ReleaseHandle()
 {
     if (!IsInvalid)
     {
         WebSocketProtocolComponent.WebSocketDeleteHandle(handle);
     }
     return(true);
 }
Example #4
0
        private SafeHandle CreateWebSocketHandle()
        {
            Contract.Assert(m_Properties != null, "'m_Properties' MUST NOT be NULL.");
            SafeWebSocketHandle sessionHandle;

            WebSocketProtocolComponent.WebSocketCreateClientHandle(m_Properties, out sessionHandle);
            Contract.Assert(sessionHandle != null, "'sessionHandle MUST NOT be NULL.");

            return(sessionHandle);
        }
        private SafeHandle CreateWebSocketHandle()
        {
            Debug.Assert(_properties != null, "'_properties' MUST NOT be NULL.");
            SafeWebSocketHandle sessionHandle;

            WebSocketProtocolComponent.WebSocketCreateServerHandle(
                _properties,
                _properties.Length,
                out sessionHandle);
            Debug.Assert(sessionHandle != null, "'sessionHandle MUST NOT be NULL.");

            return(sessionHandle);
        }
Example #6
0
 /// <summary>Creates an instance of the <see cref="T:System.Net.WebSockets.WebSocketException" /> class.</summary>
 /// <param name="nativeError">The native error code for the exception.</param>
 /// <param name="innerException">Indicates the previous exception that led to the current exception.</param>
 public WebSocketException(int nativeError, Exception innerException)
     : base(SR.GetString("net_WebSockets_Generic"), innerException)
 {
     this.m_WebSocketErrorCode = !WebSocketProtocolComponent.Succeeded(nativeError) ? WebSocketError.NativeError : WebSocketError.Success;
     this.SetErrorCodeOnError(nativeError);
 }
        internal static void UnwrapWebSocketBuffer(WebSocketProtocolComponent.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:
                    Contract.Assert(false,
                        string.Format(CultureInfo.InvariantCulture,
                            "BufferType '{0}' is invalid/unknown.",
                            bufferType));
                    break;
            }
        }
Example #8
0
 /// <summary>Creates an instance of the <see cref="T:System.Net.WebSockets.WebSocketException" /> class.</summary>
 /// <param name="nativeError">The native error code for the exception.</param>
 /// <param name="message">The description of the error.</param>
 public WebSocketException(int nativeError, string message)
     : base(nativeError, message)
 {
     this.m_WebSocketErrorCode = !WebSocketProtocolComponent.Succeeded(nativeError) ? WebSocketError.NativeError : WebSocketError.Success;
     this.SetErrorCodeOnError(nativeError);
 }
        internal void ConvertCloseBuffer(WebSocketProtocolComponent.Action action,
            WebSocketProtocolComponent.Buffer buffer,
            out WebSocketCloseStatus closeStatus,
            out string reason)
        {
            ThrowIfDisposed();
            IntPtr bufferData;
            uint bufferLength;
            closeStatus = (WebSocketCloseStatus)buffer.CloseStatus.CloseStatus;

            UnwrapWebSocketBuffer(buffer, WebSocketProtocolComponent.BufferType.Close, out bufferData, out bufferLength);

            if (bufferData == IntPtr.Zero)
            {
                reason = null;
            }
            else
            {
                ArraySegment<byte> reasonBlob;
                if (this.IsNativeBuffer(bufferData, bufferLength))
                {
                    reasonBlob = new ArraySegment<byte>(m_InternalBuffer.Array,
                        this.GetOffset(bufferData),
                        (int)bufferLength);
                }
                else
                {
                    Contract.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();
                }

                // No need to wrap DecoderFallbackException for invalid UTF8 chacters, because
                // Encoding.UTF8 will not throw but replace invalid characters instead.
                reason = Encoding.UTF8.GetString(reasonBlob.Array, reasonBlob.Offset, reasonBlob.Count);
            }
        }
        internal void ValidateNativeBuffers(WebSocketProtocolComponent.Action action,
            WebSocketProtocolComponent.BufferType bufferType,
            WebSocketProtocolComponent.Buffer[] dataBuffers,
            uint dataBufferCount)
        {
            Contract.Assert(dataBufferCount <= (uint)int.MaxValue, 
                "'dataBufferCount' MUST NOT be bigger than Int32.MaxValue.");
            Contract.Assert(dataBuffers != null, "'dataBuffers' MUST NOT be NULL.");

            ThrowIfDisposed();
            if (dataBufferCount > dataBuffers.Length)
            {
                Contract.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++)
            {
                WebSocketProtocolComponent.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)
                    {
                        Contract.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))
                {
                    Contract.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)
            {
                Contract.Assert(false, "At least one 'dataBuffer.Buffer' MUST NOT be NULL.");
            }
        }
        // This method is not thread safe. It must only be called after enforcing at most 1 outstanding send operation
        private bool IsPinnedSendPayloadBuffer(WebSocketProtocolComponent.Buffer buffer,
            WebSocketProtocolComponent.BufferType bufferType)
        {
            if (m_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 >= m_PinnedSendBufferStartAddress &&
                nativeBufferEndAddress >= m_PinnedSendBufferStartAddress &&
                nativeBufferStartAddress <= m_PinnedSendBufferEndAddress &&
                nativeBufferEndAddress <= m_PinnedSendBufferEndAddress;
        }
        internal ArraySegment<byte> ConvertNativeBuffer(WebSocketProtocolComponent.Action action,
            WebSocketProtocolComponent.Buffer buffer,
            WebSocketProtocolComponent.BufferType bufferType)
        {
            ThrowIfDisposed();

            IntPtr bufferData;
            uint bufferLength;

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

            if (bufferData == IntPtr.Zero)
            {
                return WebSocketHelpers.EmptyPayload;
            }

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

            Contract.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();
        }
        // This method is not thread safe. It must only be called after enforcing at most 1 outstanding send operation
        internal ArraySegment<byte> ConvertPinnedSendPayloadFromNative(WebSocketProtocolComponent.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();
            }

            Contract.Assert(Marshal.UnsafeAddrOfPinnedArrayElement(m_PinnedSendBuffer.Array,
                m_PinnedSendBuffer.Offset).ToInt64() == m_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() - m_PinnedSendBufferStartAddress);

            return new ArraySegment<byte>(m_PinnedSendBuffer.Array, m_PinnedSendBuffer.Offset + internalOffset, (int)bufferSize);
        }
Example #14
0
        private static WebSocketMessageType GetMessageType(WebSocketProtocolComponent.BufferType bufferType)
        {
            switch (bufferType)
            {
                case WebSocketProtocolComponent.BufferType.Close:
                    return WebSocketMessageType.Close;
                case WebSocketProtocolComponent.BufferType.BinaryFragment:
                case WebSocketProtocolComponent.BufferType.BinaryMessage:
                    return WebSocketMessageType.Binary;
                case WebSocketProtocolComponent.BufferType.UTF8Fragment:
                case WebSocketProtocolComponent.BufferType.UTF8Message:
                    return WebSocketMessageType.Text;
                default:
                    // This indicates a contract violation of the websocket protocol component,
                    // because we currently don't support any WebSocket extensions and would
                    // not accept a Websocket handshake requesting extensions
                    Debug.Assert(false,
                    string.Format(CultureInfo.InvariantCulture,
                        "The value of 'bufferType' ({0}) is invalid. Valid buffer types: {1}, {2}, {3}, {4}, {5}.",
                        bufferType,
                        WebSocketProtocolComponent.BufferType.Close,
                        WebSocketProtocolComponent.BufferType.BinaryFragment,
                        WebSocketProtocolComponent.BufferType.BinaryMessage,
                        WebSocketProtocolComponent.BufferType.UTF8Fragment,
                        WebSocketProtocolComponent.BufferType.UTF8Message));

                    throw new WebSocketException(WebSocketError.NativeError,
                        SR.Format(SR.net_WebSockets_InvalidBufferType,
                            bufferType,
                            WebSocketProtocolComponent.BufferType.Close,
                            WebSocketProtocolComponent.BufferType.BinaryFragment,
                            WebSocketProtocolComponent.BufferType.BinaryMessage,
                            WebSocketProtocolComponent.BufferType.UTF8Fragment,
                            WebSocketProtocolComponent.BufferType.UTF8Message));
            }
        }
Example #15
0
 internal void ValidateNativeBuffers(WebSocketProtocolComponent.Action action,
     WebSocketProtocolComponent.BufferType bufferType,
     Interop.WebSocket.Buffer[] dataBuffers,
     uint dataBufferCount)
 {
     _internalBuffer.ValidateNativeBuffers(action, bufferType, dataBuffers, dataBufferCount);
 }
Example #16
0
                protected override void ProcessAction_IndicateReceiveComplete(
                    Nullable<ArraySegment<byte>> buffer,
                    WebSocketProtocolComponent.BufferType bufferType,
                    WebSocketProtocolComponent.Action action,
                    Interop.WebSocket.Buffer[] dataBuffers,
                    uint dataBufferCount,
                    IntPtr actionContext)
                {
                    Debug.Assert(buffer != null, "'buffer MUST NOT be NULL.");

                    int bytesTransferred = 0;
                    _pongReceived = false;

                    if (bufferType == WebSocketProtocolComponent.BufferType.PingPong)
                    {
                        // ignoring received pong frame 
                        _pongReceived = true;
                        WebSocketProtocolComponent.WebSocketCompleteAction(_webSocket,
                            actionContext,
                            bytesTransferred);
                        return;
                    }

                    WebSocketReceiveResult receiveResult;
                    try
                    {
                        ArraySegment<byte> payload;
                        WebSocketMessageType messageType = GetMessageType(bufferType);
                        int newReceiveState = ReceiveState.Idle;

                        if (bufferType == WebSocketProtocolComponent.BufferType.Close)
                        {
                            payload = WebSocketValidate.EmptyPayload;
                            string reason;
                            WebSocketCloseStatus closeStatus;
                            _webSocket._internalBuffer.ConvertCloseBuffer(action, dataBuffers[0], out closeStatus, out reason);

                            receiveResult = new WebSocketReceiveResult(bytesTransferred,
                                messageType, true, closeStatus, reason);
                        }
                        else
                        {
                            payload = _webSocket._internalBuffer.ConvertNativeBuffer(action, dataBuffers[0], bufferType);

                            bool endOfMessage = bufferType ==
                                WebSocketProtocolComponent.BufferType.BinaryMessage ||
                                bufferType == WebSocketProtocolComponent.BufferType.UTF8Message ||
                                bufferType == WebSocketProtocolComponent.BufferType.Close;

                            if (payload.Count > buffer.Value.Count)
                            {
                                _webSocket._internalBuffer.BufferPayload(payload, buffer.Value.Count, messageType, endOfMessage);
                                newReceiveState = ReceiveState.PayloadAvailable;
                                endOfMessage = false;
                            }

                            bytesTransferred = Math.Min(payload.Count, (int)buffer.Value.Count);
                            if (bytesTransferred > 0)
                            {
                                Buffer.BlockCopy(payload.Array,
                                    payload.Offset,
                                    buffer.Value.Array,
                                    buffer.Value.Offset,
                                    bytesTransferred);
                            }

                            receiveResult = new WebSocketReceiveResult(bytesTransferred, messageType, endOfMessage);
                        }

                        _webSocket.UpdateReceiveState(newReceiveState, _receiveState);
                    }
                    finally
                    {
                        WebSocketProtocolComponent.WebSocketCompleteAction(_webSocket,
                            actionContext,
                            bytesTransferred);
                    }

                    ReceiveResult = receiveResult;
                }
Example #17
0
 protected virtual void ProcessAction_IndicateReceiveComplete(
     Nullable<ArraySegment<byte>> buffer,
     WebSocketProtocolComponent.BufferType bufferType,
     WebSocketProtocolComponent.Action action,
     Interop.WebSocket.Buffer[] dataBuffers,
     uint dataBufferCount,
     IntPtr actionContext)
 {
     throw new NotImplementedException();
 }