Public/Messaging.ps1
|
<#
.SYNOPSIS Public functions for sending and receiving messages .DESCRIPTION Cmdlets for encrypted messaging within active sessions. Messages are ephemeral - never persisted to disk. #> function Send-ChatMessage { <# .SYNOPSIS Send an encrypted message to connected peer .PARAMETER Message The message to send .PARAMETER SessionId Session to send on (defaults to most recent) .EXAMPLE Send-ChatMessage "Hello, world!" .EXAMPLE "Hello" | Send-ChatMessage #> [CmdletBinding()] param( [Parameter(Mandatory, Position = 0, ValueFromPipeline)] [string]$Message, [string]$SessionId ) process { if (-not $SessionId) { $SessionId = @($script:ActiveSessions.Keys)[-1] } if (-not $SessionId) { throw "No active session. Use Start-ChatSession first." } $sessionData = $script:ActiveSessions[$SessionId] if ($null -eq $sessionData) { throw "Session not found: $SessionId" } $session = $sessionData.Session $transport = $sessionData.Transport if ($session.State -ne [SessionState]::Established) { throw "Session not established (current state: $($session.State))" } # Encrypt message $encrypted = $session.Encrypt($Message) # Create protocol message $protocolMsg = [MessageProtocol]::CreateMessage($encrypted) # Send $transport.SendString($protocolMsg) Write-Verbose "Sent encrypted message ($($Message.Length) chars)" } } function Receive-ChatMessage { <# .SYNOPSIS Receive messages from connected peer .PARAMETER SessionId Session to receive from (defaults to most recent) .PARAMETER Timeout Receive timeout in milliseconds (default: 5000) .PARAMETER Continuous Keep receiving until cancelled .EXAMPLE Receive-ChatMessage .EXAMPLE Receive-ChatMessage -Continuous #> [CmdletBinding()] param( [string]$SessionId, [int]$Timeout = 5000, [switch]$Continuous ) if (-not $SessionId) { $SessionId = @($script:ActiveSessions.Keys)[-1] } if (-not $SessionId) { throw "No active session. Use Start-ChatSession first." } $sessionData = $script:ActiveSessions[$SessionId] if ($null -eq $sessionData) { throw "Session not found: $SessionId" } $session = $sessionData.Session $transport = $sessionData.Transport do { try { $rawMessage = $transport.ReceiveString($Timeout) if ($null -eq $rawMessage) { if (-not $Continuous) { Write-Verbose "No message received (timeout)" } continue } # Parse protocol message $parsed = [MessageProtocol]::Parse($rawMessage) if ($null -eq $parsed -or $parsed.type -eq "unknown") { Write-Warning "Received invalid message" continue } switch ($parsed.type) { "message" { # Decrypt and output $decrypted = $session.Decrypt($parsed.content) # Output as object with metadata [PSCustomObject]@{ Timestamp = [DateTime]::Parse($parsed.timestamp) From = "Peer" Message = $decrypted } } "handshake" { Write-Verbose "Received handshake from $($parsed.sessionId)" if ($session.State -ne [SessionState]::Established) { $session.CompleteHandshake($parsed.publicKey) Write-Host "Peer connected!" -ForegroundColor Green } } "disconnect" { Write-Host "Peer disconnected: $($parsed.reason)" -ForegroundColor Yellow Stop-ChatSession -SessionId $SessionId return } default { Write-Verbose "Unknown message type: $($parsed.type)" } } } catch { if ($Continuous) { Write-Warning "Error receiving: $_" } else { throw } } } while ($Continuous) } |