internal static string GetSupportedVersion() { if (WebSocketDllHandle.IsInvalid) { WebSocketHelpers.ThrowPlatformNotSupportedException_WSPC(); } SafeWebSocketHandle webSocketHandle = null; try { int errorCode = WebSocketCreateClientHandle_Raw(null, 0, out webSocketHandle); ThrowOnError(errorCode); if (webSocketHandle == null || webSocketHandle.IsInvalid) { WebSocketHelpers.ThrowPlatformNotSupportedException_WSPC(); } IntPtr additionalHeadersPtr; uint additionalHeaderCount; errorCode = WebSocketBeginClientHandshake_Raw(webSocketHandle, IntPtr.Zero, 0, IntPtr.Zero, 0, InitialClientRequestHeaders, (uint)InitialClientRequestHeaders.Length, out additionalHeadersPtr, out additionalHeaderCount); ThrowOnError(errorCode); HttpHeader[] additionalHeaders = MarshalHttpHeaders(additionalHeadersPtr, (int)additionalHeaderCount); string version = null; foreach (HttpHeader header in additionalHeaders) { if (string.Compare(header.Name, HttpKnownHeaderNames.SecWebSocketVersion, StringComparison.OrdinalIgnoreCase) == 0) { version = header.Value; break; } } Contract.Assert(version != null, "'version' MUST NOT be NULL."); return(version); } finally { if (webSocketHandle != null) { webSocketHandle.Dispose(); } } }
internal static void WebSocketCreateServerHandle(Property[] properties, int propertyCount, out SafeWebSocketHandle webSocketHandle) { Contract.Assert(propertyCount >= 0, "'propertyCount' MUST NOT be negative."); Contract.Assert((properties == null && propertyCount == 0) || (properties != null && propertyCount == properties.Length), "'propertyCount' MUST MATCH 'properties.Length'."); if (WebSocketDllHandle.IsInvalid) { WebSocketHelpers.ThrowPlatformNotSupportedException_WSPC(); } int errorCode = WebSocketCreateServerHandle_Raw(properties, (uint)propertyCount, out webSocketHandle); ThrowOnError(errorCode); if (webSocketHandle == null || webSocketHandle.IsInvalid) { WebSocketHelpers.ThrowPlatformNotSupportedException_WSPC(); } IntPtr responseHeadersPtr; uint responseHeaderCount; // Currently the WSPC doesn't allow to initiate a data session // without also being involved in the http handshake // There is no information whatsoever, which is needed by the // WSPC for parsing WebSocket frames from the HTTP handshake // In the managed implementation the HTTP header handling // will be done using the managed HTTP stack and we will // just fake an HTTP handshake for the WSPC calling // WebSocketBeginServerHandshake and WebSocketEndServerHandshake // with statically defined dummy headers. errorCode = WebSocketBeginServerHandshake_Raw(webSocketHandle, IntPtr.Zero, IntPtr.Zero, 0, ServerFakeRequestHeaders, (uint)ServerFakeRequestHeaders.Length, out responseHeadersPtr, out responseHeaderCount); ThrowOnError(errorCode); HttpHeader[] responseHeaders = MarshalHttpHeaders(responseHeadersPtr, (int)responseHeaderCount); errorCode = WebSocketEndServerHandshake_Raw(webSocketHandle); ThrowOnError(errorCode); Contract.Assert(webSocketHandle != null, "'webSocketHandle' MUST NOT be NULL at this point."); }
public ServerWebSocket(Stream innerStream, string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval, ArraySegment <byte> internalBuffer) : base(innerStream, subProtocol, keepAliveInterval, WebSocketBuffer.CreateServerBuffer(internalBuffer, receiveBufferSize)) { _properties = this.InternalBuffer.CreateProperties(false); _sessionHandle = this.CreateWebSocketHandle(); if (_sessionHandle == null || _sessionHandle.IsInvalid) { WebSocketHelpers.ThrowPlatformNotSupportedException_WSPC(); } StartKeepAliveTimer(); }
// This method is not thread safe. It must only be called after enforcing at most 1 outstanding send operation internal void PinSendBuffer(ArraySegment <byte> payload, out bool bufferHasBeenPinned) { bufferHasBeenPinned = false; WebSocketHelpers.ValidateBuffer(payload.Array, payload.Offset, payload.Count); int previousState = Interlocked.Exchange(ref _SendBufferState, SendBufferState.SendPayloadSpecified); if (previousState != SendBufferState.None) { Contract.Assert(false, "'m_SendBufferState' MUST BE 'None' at this point."); // 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(); } _PinnedSendBuffer = payload; _PinnedSendBufferHandle = GCHandle.Alloc(_PinnedSendBuffer.Array, GCHandleType.Pinned); bufferHasBeenPinned = true; _PinnedSendBufferStartAddress = Marshal.UnsafeAddrOfPinnedArrayElement(_PinnedSendBuffer.Array, _PinnedSendBuffer.Offset).ToInt64(); _PinnedSendBufferEndAddress = _PinnedSendBufferStartAddress + _PinnedSendBuffer.Count; }
internal static void WebSocketCreateClientHandle(Property[] properties, out SafeWebSocketHandle webSocketHandle) { uint propertyCount = properties == null ? 0 : (uint)properties.Length; if (WebSocketDllHandle.IsInvalid) { WebSocketHelpers.ThrowPlatformNotSupportedException_WSPC(); } int errorCode = WebSocketCreateClientHandle_Raw(properties, propertyCount, out webSocketHandle); ThrowOnError(errorCode); if (webSocketHandle == null || webSocketHandle.IsInvalid) { WebSocketHelpers.ThrowPlatformNotSupportedException_WSPC(); } IntPtr additionalHeadersPtr; uint additionalHeaderCount; // Currently the WSPC doesn't allow to initiate a data session // without also being involved in the http handshake // There is no information whatsoever, which is needed by the // WSPC for parsing WebSocket frames from the HTTP handshake // In the managed implementation the HTTP header handling // will be done using the managed HTTP stack and we will // just fake an HTTP handshake for the WSPC calling // WebSocketBeginClientHandshake and WebSocketEndClientHandshake // with statically defined dummy headers. errorCode = WebSocketBeginClientHandshake_Raw(webSocketHandle, IntPtr.Zero, 0, IntPtr.Zero, 0, InitialClientRequestHeaders, (uint)InitialClientRequestHeaders.Length, out additionalHeadersPtr, out additionalHeaderCount); ThrowOnError(errorCode); HttpHeader[] additionalHeaders = MarshalHttpHeaders(additionalHeadersPtr, (int)additionalHeaderCount); string key = null; foreach (HttpHeader header in additionalHeaders) { if (string.Compare(header.Name, HttpKnownHeaderNames.SecWebSocketKey, StringComparison.OrdinalIgnoreCase) == 0) { key = header.Value; break; } } Contract.Assert(key != null, "'key' MUST NOT be NULL."); string acceptValue = WebSocketHelpers.GetSecWebSocketAcceptString(key); HttpHeader[] responseHeaders = new HttpHeader[] { new HttpHeader() { Name = HttpKnownHeaderNames.Connection, NameLength = (uint)HttpKnownHeaderNames.Connection.Length, Value = HttpKnownHeaderNames.Upgrade, ValueLength = (uint)HttpKnownHeaderNames.Upgrade.Length }, new HttpHeader() { Name = HttpKnownHeaderNames.Upgrade, NameLength = (uint)HttpKnownHeaderNames.Upgrade.Length, Value = WebSocketHelpers.WebSocketUpgradeToken, ValueLength = (uint)WebSocketHelpers.WebSocketUpgradeToken.Length }, new HttpHeader() { Name = HttpKnownHeaderNames.SecWebSocketAccept, NameLength = (uint)HttpKnownHeaderNames.SecWebSocketAccept.Length, Value = acceptValue, ValueLength = (uint)acceptValue.Length } }; errorCode = WebSocketEndClientHandshake_Raw(webSocketHandle, responseHeaders, (uint)responseHeaders.Length, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); ThrowOnError(errorCode); Contract.Assert(webSocketHandle != null, "'webSocketHandle' MUST NOT be NULL at this point."); }