// Copyright 2020 Justine Alexandra Roberts Tunney
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// SIP Via Address Library
|
|
|
|
package sip
|
|
|
|
import (
|
|
"bytes"
|
|
"strconv"
|
|
|
|
"github.com/jart/gosip/util"
|
|
)
|
|
|
|
// Example: SIP/2.0/UDP 1.2.3.4:5060;branch=z9hG4bK556f77e6.
|
|
type Via struct {
|
|
Protocol string // should be "SIP"
|
|
Version string // protocol version e.g. "2.0"
|
|
Transport string // transport type "UDP"
|
|
Host string // name or ip of egress interface
|
|
Port uint16 // network port number
|
|
Param *Param // param like branch, received, rport, etc.
|
|
Next *Via // pointer to next via header if any
|
|
}
|
|
|
|
func (via *Via) Append(b *bytes.Buffer) {
|
|
if via.Protocol == "" {
|
|
b.WriteString("SIP/")
|
|
} else {
|
|
b.WriteString(via.Protocol)
|
|
b.WriteString("/")
|
|
}
|
|
if via.Version == "" {
|
|
b.WriteString("2.0/")
|
|
} else {
|
|
b.WriteString(via.Version)
|
|
b.WriteString("/")
|
|
}
|
|
if via.Transport == "" {
|
|
b.WriteString("UDP ")
|
|
} else {
|
|
b.WriteString(via.Transport)
|
|
b.WriteString(" ")
|
|
}
|
|
b.WriteString(via.Host)
|
|
if via.Port != 5060 {
|
|
b.WriteString(":")
|
|
b.WriteString(strconv.Itoa(int(via.Port)))
|
|
}
|
|
via.Param.Append(b)
|
|
}
|
|
|
|
// Copy returns a deep copy of via.
|
|
func (via *Via) Copy() *Via {
|
|
if via == nil {
|
|
return nil
|
|
}
|
|
res := new(Via)
|
|
res.Protocol = via.Protocol
|
|
res.Version = via.Version
|
|
res.Transport = via.Transport
|
|
res.Host = via.Host
|
|
res.Port = via.Port
|
|
res.Param = via.Param
|
|
res.Next = via.Next.Copy()
|
|
return res
|
|
}
|
|
|
|
// Branch adds a randomly generated branch ID.
|
|
func (via *Via) Branch() *Via {
|
|
via.Param = &Param{"branch", util.GenerateBranch(), via.Param}
|
|
return via
|
|
}
|
|
|
|
// Detach returns a shallow copy of via with Next set to nil.
|
|
func (via *Via) Detach() *Via {
|
|
res := new(Via)
|
|
*res = *via
|
|
res.Next = nil
|
|
return res
|
|
}
|
|
|
|
// Last returns pointer to last via in linked list.
|
|
func (via *Via) Last() *Via {
|
|
if via != nil {
|
|
for ; via.Next != nil; via = via.Next {
|
|
}
|
|
}
|
|
return via
|
|
}
|
|
|
|
func (via *Via) CompareHostPort(other *Via) bool {
|
|
if via != nil && other != nil {
|
|
if via.Host == other.Host &&
|
|
via.Port == other.Port {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (via *Via) CompareBranch(other *Via) bool {
|
|
if via != nil && other != nil {
|
|
if b1 := via.Param.Get("branch"); b1 != nil {
|
|
if b2 := other.Param.Get("branch"); b2 != nil {
|
|
if b1.Value == b2.Value {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|