// 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; } }
private SafeHandle CreateWebSocketHandle() { Debug.Assert(_properties != null, "'_properties' MUST NOT be NULL."); return(WebSocketProtocolComponent.WebSocketCreateServerHandle( _properties, _properties.Length)); }
protected override bool ReleaseHandle() { if (!IsInvalid) { WebSocketProtocolComponent.WebSocketDeleteHandle(handle); } return(true); }
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); }
/// <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; } }
/// <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); }
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)); } }
internal void ValidateNativeBuffers(WebSocketProtocolComponent.Action action, WebSocketProtocolComponent.BufferType bufferType, Interop.WebSocket.Buffer[] dataBuffers, uint dataBufferCount) { _internalBuffer.ValidateNativeBuffers(action, bufferType, dataBuffers, dataBufferCount); }
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; }
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(); }