UcsSipUtil.psm1
Function Invoke-UcsSipRequest { Param( [Parameter(Mandatory,HelpMessage = '127.0.0.1')][String]$IPv4Address, [Int][ValidateRange(1,9999)]$CSeq = 1, [String][ValidateSet('OPTIONS','NOTIFY','INFO')]$Method = 'NOTIFY', [String]$Event = '', [Timespan]$Timeout = (Get-UcsConfig -API SIP).Timeout, [int][ValidateRange(1,100)]$Retries = (Get-UcsConfig -API SIP).Retries, [int][ValidateRange(1,65535)]$Port = (Get-UcsConfig -API SIP).Port, [switch]$SkipParse ) if($null -eq (Get-Module -Name nettcpip)) { Try { Write-Debug "Attempting to load NetTCPIP..." if($PSVersionTable.PSEdition -eq "Core") { Import-Module -Name NetTCPIP -SkipEditionCheck-ErrorAction Stop } else { Import-Module -Name NetTCPIP -ErrorAction Stop } } Catch { Throw "Couldn't load NetTCPIP library. Error was: $_" } } $ThisIPv4Address = $IPv4Address $RandomRangeHigh = 99999999 $RandomRangeLow = 10000000 Write-Debug "Performing initial setup for $ThisIpv4Address." $PhoneId = 'UCS' $SourceAddress = Find-NetRoute -RemoteIPAddress $ThisIPv4Address | Select-Object -First 1 | Select-Object -ExpandProperty IPAddress $SourcePort = Get-Random -Minimum 50000 -Maximum 50999 $CallID = ('{0}-{1}' -f (Get-Random -Minimum $RandomRangeLow -Maximum $RandomRangeHigh), (Get-Random -Minimum $RandomRangeLow -Maximum $RandomRangeHigh)) $CSeqString = ('{0} {1}' -f $CSeq, $Method) $SipTag = ('{0}-{1}' -f (Get-Random -Minimum $RandomRangeLow -Maximum $RandomRangeHigh), (Get-Random -Minimum $RandomRangeLow -Maximum $RandomRangeHigh)) $SipMessage = @" ${Method} sip:${PhoneId}:${Port} SIP/2.0 Via: SIP/2.0/UDP ${SourceAddress}:${SourcePort} From: <sip:${PhoneId}>;tag=${SipTag} To: <sip:${ThisIPv4Address}:5060> Call-ID: ${CallID} CSeq: ${CSeqString} Contact: <sip:${PhoneId}> Content-Length: 0 "@ if($Event.Length -gt 0) { $SipMessage += "`nEvent: $Event" } $RemainingRetries = $Retries While($RemainingRetries -gt 0) { Write-Debug "Starting connection attempt for $ThisIPv4Address with $RemainingRetries retries remaining." $RemainingRetries-- Try { $Parsed = $null $AsciiEncoded = New-Object -TypeName System.Text.ASCIIEncoding $Bytes = $AsciiEncoded.GetBytes($SipMessage) $Socket = New-Object -TypeName Net.Sockets.Socket -ArgumentList ([Net.Sockets.AddressFamily]::InterNetwork, [Net.Sockets.SocketType]::Dgram, [Net.Sockets.ProtocolType]::Udp) $ThisEndpoint = New-Object -TypeName System.Net.IPEndPoint -ArgumentList ([ipaddress]::Parse($SourceAddress), $SourcePort) $Socket.Bind($ThisEndpoint) $Socket.Connect($ThisIPv4Address,$Port) [Void]$Socket.Send($Bytes) [Byte[]]$buffer = New-Object -TypeName Byte[] -ArgumentList ($Socket.ReceiveBufferSize) Write-Debug ('{0}: Initiating timeout of {1} seconds.' -f $IPv4Address,$Timeout.TotalSeconds) $IntegerTimeout = ($Timeout.TotalMilliseconds) * 1000 if($Socket.Poll($IntegerTimeout,[Net.Sockets.SelectMode]::SelectRead)) { $receivebytes = $Socket.Receive($buffer) } else { Write-Error ('{0}: Timeout of {1} seconds expired.' -f $IPv4Address,$Timeout.TotalSeconds) -ErrorAction Stop } [string]$PhoneResponse = $AsciiEncoded.GetString($buffer, 0, $receivebytes) if($SkipParse -eq $true) { $Parsed = $PhoneResponse } else { $Parsed = Convert-UcsSipResponse -SipMessage $PhoneResponse -ErrorAction Stop } } Catch { if($RemainingRetries -le 0) { Write-Error "An error occured while processing $ThisIPv4Address." Write-Debug "$_" } else { Write-Debug "Processing $ThisIPv4Address failed, $RemainingRetries remain." } } Finally { $Socket.Close() } if($null -ne $Parsed) { Break #Get out of the loop. } } Return $Parsed } Function Convert-UcsSipResponse { Param([Parameter(Mandatory)][String]$SipMessage) $PhoneResponse = $SipMessage.Split("`n") $ParameterList = New-Object -TypeName System.Collections.ArrayList $SipOK = $false $ObjectBuilder = New-Object -TypeName PSObject Foreach($Line in $PhoneResponse) { if($Line -like '*SIP/2.0 200 OK*') { $SipOK = $true Continue } elseif($SipOK -eq $false) { Write-Error $Line } if($Line.Length -lt 3) { Write-Debug -Message "Skipped Line `"$Line`"" Continue } $ColonIndex = $Line.IndexOf(':') $ParameterName = $Line.Substring(0,$ColonIndex) $ParameterValue = ($Line.Substring($ColonIndex + 1)).Trim(' ') if($ParameterName -in $ParameterList) { Write-Debug ('{0} is already in the parameter set. Overriding original value "{1}" with new value "{2}".' -f $ParameterName,$ObjectBuilder.$ParameterName,$ParameterValue) } $null = $ParameterList.Add($ParameterName) $ObjectBuilder | Add-Member -MemberType NoteProperty -Name $ParameterName -Value $ParameterValue -Force } $ParsedSipMessage = $ObjectBuilder #Now we have an object with all the parameters that SIP gave back to us. We can further chop known ones up. Return $ParsedSipMessage } <# Examples of SIP Messages: NOTIFY (for info): $message = @" NOTIFY sip:${phoneid}:5060 SIP/2.0 Via: SIP/2.0/UDP ${serverip} From: <sip:discover>;tag=1530231855-106746376154 To: <sip:${ClientIP}:5060> Call-ID: ${call_id} CSeq: 1500 NOTIFY Contact: <sip:${phoneid}> Content-Length: 0 NOTIFY (check-sync reboot) $message = @" NOTIFY sip:${phoneid}:5060 SIP/2.0 Via: SIP/2.0/UDP ${serverip} From: <sip:${sip_from}> To: <sip:${phoneid}> Event: check-sync Call-ID: ${call_id}@${serverip} CSeq: 1300 NOTIFY Contact: <sip:${sip_from}> Content-Length: 0 #> <# Example SIP Response: SIP/2.0 200 OK Via: SIP/2.0/UDP 192.168.10.50:51234 From: <sip:discover>;tag=1530231855-106746376154 To: "John Smith" <sip:192.168.92.51:5060>;tag=2628867A-55AB4B1F CSeq: 1500 NOTIFY Call-ID: 07/10/201714:47:46msgtodiscover Contact: <sip:jsmith@example.com;opaque=user:epid:1234;gruu> User-Agent: Polycom/5.5.2.8571 PolycomVVX-VVX_310-UA/5.5.2.8571 Accept-Language: en P-Preferred-Identity: "John Smith" <sip:jsmith@example.com>,<tel:+1234;ext=1234> Authorization: TLS-DSK qop="auth", realm="SIP Communications Service", opaque="1234", crand="12134", cnum="4", targetname="lyncserver.example.com", response="1234" Content-Length: 0 #> |