Public/Receive-GuacInstruction.ps1
|
function Receive-GuacInstruction { <# .SYNOPSIS Receives the next Guacamole protocol instruction from an active session. .DESCRIPTION Receives WebSocket frames from the active session's tunnel, buffers them, and returns complete instructions as they become available (terminated by semicolons). Instructions are parsed into [N2C_GuacAdmin_GuacInstruction] objects. If -TimeoutSec is specified and no instruction arrives within that time, returns $null. If the session is closed or the WebSocket is closed, returns $null. Reference (Apache Guacamole 1.6.0): - guacamole-common/src/main/java/org/apache/guacamole/protocol/GuacamoleProtocolReader.java (readInstruction method) .EXAMPLE $instr = Receive-GuacInstruction -Session $active if ($instr -and $instr.Opcode -eq 'data') { # Process base64 image data } .EXAMPLE # Receive with timeout $instr = Receive-GuacInstruction -Session $active -TimeoutSec 5 #> [CmdletBinding()] [OutputType([N2C_GuacAdmin_GuacInstruction])] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [N2C_GuacAdmin_GuacActiveSession] $Session, [Parameter(Mandatory = $false)] [AllowEmptyString()] [int] $TimeoutSec = 0 ) process { if ($Session.Closed) { return $null } $buffer = New-Object byte[] 4096 $bufferSegment = New-Object System.ArraySegment[byte] -ArgumentList $buffer # Set up cancellation for timeout $cts = if ($TimeoutSec -gt 0) { New-Object System.Threading.CancellationTokenSource $cts.CancelAfter([TimeSpan]::FromSeconds($TimeoutSec)) $cts.Token } else { [System.Threading.CancellationToken]::None } try { # Try to receive data $result = $Session.WebSocket.ReceiveAsync($bufferSegment, $cts).GetAwaiter().GetResult() if ($result.MessageType -eq [System.Net.WebSockets.WebSocketMessageType]::Close) { $Session.Closed = $true return $null } $receivedText = [System.Text.Encoding]::UTF8.GetString($buffer, 0, $result.Count) # Find complete instructions (terminated by ';') $semiIdx = $receivedText.IndexOf(';') if ($semiIdx -ge 0) { $completeInstr = $receivedText.Substring(0, $semiIdx + 1) $parsed = ConvertFrom-GuacInstructionString -Raw $completeInstr return $parsed } # Partial instruction; return null (caller should try again) return $null } catch [System.OperationCanceledException] { # Timeout return $null } finally { if ($null -ne $cts) { $cts.Dispose() } } } } |