PwshWebSocketClient.psm1

<#
  Understanding standing the websocket protocol: https://stackoverflow.com/questions/26791107/ws-on-http-vs-wss-on-https
  In order to become a true engineer don't avoid reading rfc's: https://www.rfc-editor.org/rfc/rfc6455
#>


#Get public and private function definition files.
$Public  = @( Get-ChildItem -Path $PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue )
$Private = @( Get-ChildItem -Path $PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue )

#Dot source the files
Foreach($import in @($Public + $Private))
{
  Try
  {
    . $import.fullname
  }
  Catch
  {
    Write-Error -Message "Failed to import function $($import.fullname): $_"
  }
}
# Typically we would: Export-ModuleMember -Function $Public.Basename
# But since there is a shared state: create instance of websocket client
$WebSocketClient = New-WebSocketClient
# Other


<#
.SYNOPSIS
  Initiate a managed websocket connection.
.DESCRIPTION
  Initiate a managed websocket connection.
.PARAMETER Uri
  Open a Websocket Connection to the Uri specified in the parameter.
.PARAMETER Certificate
  The Filepath to a X.509 in pfx format. If this argument is present then the password must be supplied CertificatePass
.PARAMETER CertificatePass
  The password to the X.509 certificate supplied in the Certificate argument, wrapped as a secure string.
.PARAMETER Cookies
  A collection of cookies to send along with the initial upgrade into a websocket. The datatype to supply to this parameter is [System.Net.CookieContainer]
.PARAMETER NetworkCredentials
  Parameters to be used in network level authentication schemes including basic, digest, NTLM, and Kerberos authentication. See Documentation for System.Net.NetworkCredential.
.PARAMETER KeepAliveInterval
  Sets the frequency at which to send Ping/Pong keep-alive control frames.
  Dotnet sets the default is two minutes, the default behavior of this module is keep the websocket connect alive no matter what.
  This is accomplished by setting the default value of this parameter to [System.TimeSpan]::zero
.PARAMETER Proxy
  A Uri to a proxy websocket server.
.EXAMPLE
  Connect-WebSocket -Uri 'ws://uri here'
.EXAMPLE
  Connect-WebSocket -Uri 'wss://uri here'
.EXAMPLE
  Connect-WebSocket -Uri 'wss://uri here' -KeepAliveInterval [System.TimeSpan]::zero
.EXAMPLE
  Connect-WebSocket -Uri 'ws://uri here' -Proxy 'ws://proxy_uri'
.EXAMPLE
  Connect-WebSocket -Uri 'wss://uri here' -Proxy 'wss://proxy_uri'
.EXAMPLE
  Connect-WebSocket -Uri 'wss://uri here' --Certificate path-to-pfx-format-certificate --CertificatePass pfx-cert-pass
.Example
  $Cookie = [System.Net.Cookie]::new("donkey", "Important value: heee haw")
  $Cookie.Domain='localhost'
  $Cookie.HttpOnly = $true
  $CookieJar = New-Object System.Net.CookieContainer
  $CookieJar.add($Cookie)
  Connect-WebSocket -Uri 'ws://uri here' -Cookies $CookieJar
#>

Function Connect-Websocket {
 [CmdletBinding(DefaultParameterSetName='Default')]
  Param (
    [Parameter(Mandatory=$true)]
    [string]$Uri,
    [Parameter(Mandatory=$true, ParameterSetName="TLS Auth")]
    [string]$Certificate, #https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x509certificate?view=netcore-3.1
    [Parameter(Mandatory=$true, ParameterSetName="TLS Auth")]
    [System.Security.SecureString]$CertificatePass,
    # The Parameters below are taken from .net core 3 https://learn.microsoft.com/en-us/dotnet/api/system.net.websockets.clientwebsocketoptions?view=netcore-3.1
    [Parameter(Mandatory=$false)]
    [System.Net.CookieContainer]$Cookies,
    [Parameter(Mandatory=$false)]
    [System.Net.NetworkCredential]$NetworkCredential,
    [Parameter(Mandatory=$false)]
    [System.TimeSpan]$KeepAliveInterval=[System.TimeSpan]::zero, #https://stackoverflow.com/questions/40502921/net-websockets-forcibly-closed-despite-keep-alive-and-activity-on-the-connectio
    [Parameter(Mandatory=$false)]
    [string]$Proxy
  )
  return $WebSocketClient.ConnectWebsocket($Uri, $Certificate, $CertificatePass, $Cookies, $NetworkCredential, $KeepAliveInterval, $Proxy )
}
<#
.SYNOPSIS
  Send a message over a websocket.
.DESCRIPTION
  Send a message over a websocket.
.PARAMETER Message
  The message to be send over the websocket.
.PARAMETER SocketId
  The websocket that the message is to be sent on. This parameter defaults to 0, thus if no SocketId is specified all messages will be sent over the first websocket created.
.EXAMPLE
  Send-Message -Message datatobesent
.EXAMPLE
  Send-Message -Message 'Message_Here'
.EXAMPLE
  Send-Message -Message 'Message_Here' -SocketId 0
#>

Function Send-Message {
  param(
    [Parameter(Mandatory=$true)]
    [string]$Message,
    [Parameter(Mandatory=$false)]
    [int]$SocketId = 0
  )
  return $WebSocketClient.SendMessage($Message, $SocketId)
}
<#
.SYNOPSIS
  Receive a message over a websocket.
.DESCRIPTION
  Receive a message over a websocket.
.PARAMETER BufferSize
  The maximum amount of data the websocket receive at once. The buffer size defaults to 1kb (1024 bytes).
.PARAMETER SocketId
  The socket that the message is to be received on. This parameter defaults to 0, thus if no SocketId is specified all messages will be received on the first websocket created.
.EXAMPLE
  Receive-Message
.EXAMPLE
  Receive-Message -SocketId 0
.EXAMPLE
  Receive-Message -SocketId 0 -BufferSize 4096
#>

Function Receive-Message {
  param(
    [Parameter(Mandatory=$false)]
    [int]$BufferSize = 1024,
    [Parameter(Mandatory=$false)]
    [int]$SocketId = 0
  )
  return $WebSocketClient.ReceiveMessage($SocketId, $BufferSize)
}

<#
.SYNOPSIS
  Disconnect a websocket connection.
.DESCRIPTION
  Disconnect a websocket connection.
.PARAMETER SocketId
  The websocket to disconnect. This parameter defaults to 0, thus if no SocketId is specified the first websocket created will be disconnected.
.EXAMPLE
  Disconnect-WebSocket
.EXAMPLE
  Disconnect-WebSocket -SocketId 0
#>

Function Disconnect-Websocket {
  param(
    [Parameter(Mandatory=$false)]
    [int]$SocketId = 0
  )
  return $WebSocketClient.DisconnectWebsocket($SocketId)
}

<#
.SYNOPSIS
  Get information about a websocket.
.DESCRIPTION
  Get information about a websocket.
.PARAMETER SocketId
  The websocket to disconnect. This parameter defaults to 0, thus if no SocketId is specified this commandlet will return the state of the first websocket created.
.EXAMPLE
  Get-WebSocketState
.EXAMPLE
  Get-WebSocketState -SocketId 0
#>

Function Get-WebsocketState {
  param(
    [Parameter(Mandatory=$false)]
    [int]$SocketId = 0
  )
  return $WebSocketClient.GetWebsocketState($SocketId)
}

Export-ModuleMember Connect-Websocket,Disconnect-Websocket,Send-Message,Receive-Message, Get-WebsocketState