Skip to content

Commit

Permalink
feat: add refer-to header and referred-by
Browse files Browse the repository at this point in the history
  • Loading branch information
kota-yata authored and emiago committed Dec 3, 2024
1 parent 30197cc commit 8710278
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 0 deletions.
121 changes: 121 additions & 0 deletions sip/headers.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ type headers struct {
route *RouteHeader
recordRoute *RecordRouteHeader
maxForwards *MaxForwardsHeader
referTo *ReferToHeader
referredBy *ReferredByHeader
}

func (hs *headers) String() string {
Expand Down Expand Up @@ -407,6 +409,24 @@ func (hs *headers) RecordRoute() *RecordRouteHeader {
return hs.recordRoute
}

// ReferTo returns underlying Refer-To parsed header or nil if not exists
func (hs *headers) ParseReferTo() *ReferToHeader {
h := &ReferToHeader{}
if parseHeaderLazy(hs, parseReferToHeader, []string{"refer-to"}, h) {
return h
}
return nil
}

// ReferredBy returns underlying Referred-By parsed header or nil if not exists
func (hs *headers) ParseReferredBy() *ReferredByHeader {
h := &ReferredByHeader{}
if parseHeaderLazy(hs, parseReferredByHeader, []string{"referred-by"}, h) {
return h
}
return nil
}

// NewHeader creates generic type of header
func NewHeader(name, value string) Header {
return &genericHeader{
Expand Down Expand Up @@ -1014,6 +1034,107 @@ func (h *RecordRouteHeader) Clone() *RecordRouteHeader {
return newRoute
}

// ReferToHeader is Refer-To header representation.
type ReferToHeader struct {
Address Uri
}

func (h *ReferToHeader) Name() string { return "Refer-To" }

func (h *ReferToHeader) Value() string {
var buffer strings.Builder
h.ValueStringWrite(&buffer)
return buffer.String()
}

func (h *ReferToHeader) ValueStringWrite(buffer io.StringWriter) {
buffer.WriteString("<")
h.Address.StringWrite(buffer)
buffer.WriteString(">")
}

func (h *ReferToHeader) String() string {
var buffer strings.Builder
h.StringWrite(&buffer)
return buffer.String()
}

func (h *ReferToHeader) StringWrite(buffer io.StringWriter) {
buffer.WriteString(h.Name())
buffer.WriteString(": ")
h.ValueStringWrite(buffer)
}

func (h *ReferToHeader) headerClone() Header {
return h.Clone()
}

func (h *ReferToHeader) Clone() *ReferToHeader {
newTarget := &ReferToHeader{
Address: *h.Address.Clone(),
}
return newTarget
}

// ReferredByHeader is Referred-By header representation.
type ReferredByHeader struct {
DisplayName string
Address Uri
Params HeaderParams
}

func (h *ReferredByHeader) Name() string { return "Referred-By" }

func (h *ReferredByHeader) Value() string {
var buffer strings.Builder
h.ValueStringWrite(&buffer)
return buffer.String()
}

func (h *ReferredByHeader) ValueStringWrite(buffer io.StringWriter) {
if h.DisplayName != "" {
buffer.WriteString("\"")
buffer.WriteString(h.DisplayName)
buffer.WriteString("\" ")
}

buffer.WriteString("<")
h.Address.StringWrite(buffer)
buffer.WriteString(">")

if h.Params != nil && h.Params.Length() > 0 {
buffer.WriteString(";")
h.Params.ToStringWrite(';', buffer)
}
}

func (h *ReferredByHeader) String() string {
var buffer strings.Builder
h.StringWrite(&buffer)
return buffer.String()
}

func (h *ReferredByHeader) StringWrite(buffer io.StringWriter) {
buffer.WriteString(h.Name())
buffer.WriteString(": ")
h.ValueStringWrite(buffer)
}

func (h *ReferredByHeader) headerClone() Header {
return h.Clone()
}

func (h *ReferredByHeader) Clone() *ReferredByHeader {
newTarget := &ReferredByHeader{
DisplayName: h.DisplayName,
Address: *h.Address.Clone(),
}
if h.Params != nil {
newTarget.Params = h.Params.Clone()
}
return newTarget
}

// Copy all headers of one type from one message to another.
// Appending to any headers that were already there.
func CopyHeaders(name string, from, to Message) {
Expand Down
34 changes: 34 additions & 0 deletions sip/parse_address.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,40 @@ func parseRecordRouteHeader(headerText string, h *RecordRouteHeader) error {
return parseRouteAddress(headerText, &h.Address)
}

func headerParserReferTo(headerName string, headerText string) (header Header, err error) {
h := ReferToHeader{}
return &h, parseReferToHeader(headerText, &h)
}

func parseReferToHeader(headerText string, h *ReferToHeader) error {
return parseRouteAddress(headerText, &h.Address) // calling parseRouteAddress because the structure is same
}

func headerParserReferredBy(headerName string, headerText string) (header Header, err error) {
h := &ReferredByHeader{}
return h, parseReferredByHeader(headerText, h)
}

func parseReferredByHeader(headerText string, h *ReferredByHeader) error {
var err error

h.Params = NewParams()
h.DisplayName, err = ParseAddressValue(headerText, &h.Address, h.Params)
if err != nil {
return err
}

if h.Address.Wildcard {
// The Wildcard '*' URI is only permitted in Contact headers.
err = fmt.Errorf(
"wildcard uri not permitted in to: header: %s",
headerText,
)
return err
}
return nil
}

func parseRouteAddress(headerText string, address *Uri) (err error) {
inBrackets := false
inQuotes := false
Expand Down
2 changes: 2 additions & 0 deletions sip/parse_header.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ var headersParsers = mapHeadersParser{
"l": headerParserContentLength,
"route": headerParserRoute,
"record-route": headerParserRecordRoute,
"refer-to": headerParserReferTo,
"referred-by": headerParserReferredBy,
}

// DefaultHeadersParser returns minimal version header parser.
Expand Down

0 comments on commit 8710278

Please sign in to comment.