From e1101990b004dce8ffb27faf018a508a76283f37 Mon Sep 17 00:00:00 2001 From: David Hall Date: Sun, 30 Oct 2022 09:35:13 -0600 Subject: [PATCH] Updates to WebSocket --- PInvoke/WebSocket/WebSocket.cs | 122 ++++++++++++++++++++- .../Properties/Resources.Designer.cs | 2 +- 2 files changed, 119 insertions(+), 5 deletions(-) diff --git a/PInvoke/WebSocket/WebSocket.cs b/PInvoke/WebSocket/WebSocket.cs index ccddda4f..0594317a 100644 --- a/PInvoke/WebSocket/WebSocket.cs +++ b/PInvoke/WebSocket/WebSocket.cs @@ -463,8 +463,8 @@ public static partial class WebSocket [PInvokeData("websocket.h", MSDNShortId = "NF:websocket.WebSocketBeginClientHandshake")] [DllImport(Lib_Websocket, SetLastError = false, ExactSpelling = true)] public static extern HRESULT WebSocketBeginClientHandshake([In] WEB_SOCKET_HANDLE hWebSocket, [In, Optional, MarshalAs(UnmanagedType.LPStr)] string pszSubprotocols, - uint ulSubprotocolCount, [In, Optional, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] string pszExtensions, uint ulExtensionCount, - [In, Optional, MarshalAs(UnmanagedType.LPArray)] WEB_SOCKET_HTTP_HEADER[] pInitialHeaders, uint ulInitialHeaderCount, + [Optional] uint ulSubprotocolCount, [In, Optional, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] string pszExtensions, [Optional] uint ulExtensionCount, + [In, Optional, MarshalAs(UnmanagedType.LPArray)] WEB_SOCKET_HTTP_HEADER[] pInitialHeaders, [Optional] uint ulInitialHeaderCount, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 8)] out WEB_SOCKET_HTTP_HEADER[] pAdditionalHeaders, out uint pulAdditionalHeaderCount); /// The WebSocketBeginServerHandshake function begins the server-side handshake. @@ -529,7 +529,7 @@ public static partial class WebSocket [DllImport(Lib_Websocket, SetLastError = false, ExactSpelling = true)] public static extern HRESULT WebSocketBeginServerHandshake([In] WEB_SOCKET_HANDLE hWebSocket, [In, Optional, MarshalAs(UnmanagedType.LPStr)] string pszSubprotocolSelected, - [In, Optional, MarshalAs(UnmanagedType.LPStr)] string pszExtensionSelected, uint ulExtensionSelectedCount, + [In, Optional, MarshalAs(UnmanagedType.LPStr)] string pszExtensionSelected, [Optional] uint ulExtensionSelectedCount, [In, MarshalAs(UnmanagedType.LPArray)] WEB_SOCKET_HTTP_HEADER[] pRequestHeaders, uint ulRequestHeaderCount, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 7)] out WEB_SOCKET_HTTP_HEADER[] pResponseHeaders, out uint pulResponseHeaderCount); @@ -731,9 +731,82 @@ public static partial class WebSocket [DllImport(Lib_Websocket, SetLastError = false, ExactSpelling = true)] public static extern HRESULT WebSocketEndClientHandshake([In] WEB_SOCKET_HANDLE hWebSocket, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] WEB_SOCKET_HTTP_HEADER[] pResponseHeaders, - uint ulReponseHeaderCount, [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] pulSelectedExtensions, + uint ulReponseHeaderCount, [In, Optional, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] pulSelectedExtensions, ref uint pulSelectedExtensionCount, out uint pulSelectedSubprotocol); + /// The WebSocketEndClientHandshake function completes the client-side handshake. + /// + /// Type: WEB_SOCKET_HANDLE + /// WebSocket session handle returned by a previous call to WebSocketCreateClientHandle. + /// + /// + /// Type: const PWEB_SOCKET_HTTP_HEADER + /// Pointer to an array of WEB_SOCKET_HTTP_HEADER structures that contain the response headers received by the application. + /// + /// + /// Type: ULONG + /// Number of response headers in pResponseHeaders. + /// + /// + /// Type: ULONG* + /// + /// On input, pointer to an array allocated by the application. On successful output, pointer to an array of numbers that represent the + /// extensions chosen by the server during the client-server handshake. These number are the zero-based indices into the extensions array + /// passed to pszExtensions in WebSocketBeginClientHandshake. + /// + /// + /// + /// Type: ULONG* + /// + /// On input, number of extensions allocated in pulSelectedExtensions. This must be at least equal to the number passed to + /// ulExtensionCount in WebSocketEndClientHandshake. On successful output, number of extensions returned in pulSelectedExtensions. + /// + /// + /// + /// Type: ULONG* + /// + /// On successful output, pointer to a number that represents the sub-protocol chosen by the server during the client-server handshake. + /// This number is the zero-based index into the sub-protocols array passed to pszSubprotocols in WebSocketBeginClientHandshake. + /// + /// + /// + /// Type: HRESULT + /// If the function succeeds, it returns S_OK. + /// If the function fails, it returns one of the following or a system error code defined in WinError.h. + /// + /// + /// Return code + /// Description + /// + /// + /// E_INVALID_PROTOCOL_FORMAT + /// Protocol data had an invalid format. + /// + /// + /// E_UNSUPPORTED_SUBPROTOCOL + /// Server does not accept any of the sub-protocols specified by the application. + /// + /// + /// E_UNSUPPORTED_EXTENSION + /// Server does not accept extensions specified by the application. + /// + /// + /// + /// + /// This function must be called to complete the client-side handshake after a previous call to WebSocketBeginClientHandshake. Once the + /// client-server handshake is complete, the application may use the session functions. + /// + // https://learn.microsoft.com/en-us/windows/win32/api/websocket/nf-websocket-websocketendclienthandshake HRESULT + // WebSocketEndClientHandshake( [in] WEB_SOCKET_HANDLE hWebSocket, [in] const PWEB_SOCKET_HTTP_HEADER pResponseHeaders, [in] ULONG + // ulReponseHeaderCount, [in, out, optional] ULONG *pulSelectedExtensions, [in, out, optional] ULONG *pulSelectedExtensionCount, [in, + // out, optional] ULONG *pulSelectedSubprotocol ); + [PInvokeData("websocket.h", MSDNShortId = "NF:websocket.WebSocketEndClientHandshake")] + [DllImport(Lib_Websocket, SetLastError = false, ExactSpelling = true)] + public static extern HRESULT WebSocketEndClientHandshake([In] WEB_SOCKET_HANDLE hWebSocket, + [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] WEB_SOCKET_HTTP_HEADER[] pResponseHeaders, + uint ulReponseHeaderCount, [In, Optional, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] uint[] pulSelectedExtensions, + [In, Optional] IntPtr pulSelectedExtensionCount, [In, Optional] IntPtr pulSelectedSubprotocol); + /// The WebSocketEndServerHandshake function completes the server-side handshake. /// /// Type: WEB_SOCKET_HANDLE @@ -1053,6 +1126,26 @@ public static partial class WebSocket /// WEB_SOCKET_CLOSE_STATUS enumeration that specifies the WebSocket status. public WEB_SOCKET_CLOSE_STATUS usStatus; } + + /// Initializes a new instance of the struct. + /// The WebSocket buffer data. + public WEB_SOCKET_BUFFER(SafeAllocatedMemoryHandle mem) + { + CloseStatus = default; + Data.pbBuffer = mem; + Data.ulBufferLength = mem.Size; + } + + /// Initializes a new instance of the struct. + /// A UTF-8 string that represents the reason the connection is closed. + /// The WebSocket status. + public WEB_SOCKET_BUFFER(SafeAllocatedMemoryHandle reason, WEB_SOCKET_CLOSE_STATUS closeStatus) + { + Data = default; + CloseStatus.pbReason = reason ?? IntPtr.Zero; + CloseStatus.ulReasonLength = reason?.Size ?? 0; + CloseStatus.usStatus = closeStatus; + } } /// Provides a handle to a WebSocket. @@ -1140,6 +1233,17 @@ public static partial class WebSocket /// Length, in characters, of the HTTP value pointed to by pcValue. /// public uint ulValueLength; + + /// Initializes a new instance of the struct. + /// The HTTP header name. + /// The header value. + public WEB_SOCKET_HTTP_HEADER(string name, string value) + { + pcName = name; + ulNameLength = (uint)name.Length; + pcValue = value; + ulValueLength = (uint)value.Length; + } } /// The WEB_SOCKET_PROPERTY structure contains a single WebSocket property. @@ -1166,6 +1270,16 @@ public static partial class WebSocket /// The size, in bytes, of the property pointed to by pvValue. /// public uint ulValueSize; + + /// Initializes a new instance of the struct. + /// The WebSocket property type. + /// The value to set. + public WEB_SOCKET_PROPERTY(WEB_SOCKET_PROPERTY_TYPE type, SafeAllocatedMemoryHandle value) + { + Type = type; + pvValue = value; + ulValueSize = value.Size; + } } /// Provides a for that is disposed using . diff --git a/UnitTests/Windows.Forms.App/Properties/Resources.Designer.cs b/UnitTests/Windows.Forms.App/Properties/Resources.Designer.cs index 7a311ca9..4831a249 100644 --- a/UnitTests/Windows.Forms.App/Properties/Resources.Designer.cs +++ b/UnitTests/Windows.Forms.App/Properties/Resources.Designer.cs @@ -19,7 +19,7 @@ namespace Windows.Forms.App.Properties { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources {