Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions sip/header_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ func (hp HeaderParams) Clone() HeaderParams {
}

func (hp HeaderParams) clone() HeaderParams {
if hp == nil {
return nil
}
dup := make(HeaderParams, len(hp))

for k, v := range hp {
Expand Down
14 changes: 7 additions & 7 deletions sip/parse_address.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ func addressStateHeaderParams(a *nameAddress, s string) (addressFSM, string, err
}

// headerParserTo generates ToHeader
func headerParserTo(headerName string, headerText string) (header Header, err error) {
func headerParserTo(headerName []byte, headerText string) (header Header, err error) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could understand this comes from line buffer, but value is mostly not used, so not sure do we need this change anyway?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally it would be great to switch values to byte slices - that should give even better performance. But that would be a very large change. So I only did header names for now.

Answering your question, tbh I'm not sure why it helps here specifically. As you mentioned, the string here is unused and is mostly generated from static strings in the lower case header names switch. So it should not matter if we do bytes here. But it does affect performance in the end.

h := &ToHeader{}
return h, parseToHeader(headerText, h)
}
Expand All @@ -214,7 +214,7 @@ func parseToHeader(headerText string, h *ToHeader) error {
}

// headerParserFrom generates FromHeader
func headerParserFrom(headerName string, headerText string) (header Header, err error) {
func headerParserFrom(headerName []byte, headerText string) (header Header, err error) {
h := &FromHeader{}
return h, parseFromHeader(headerText, h)
}
Expand All @@ -240,7 +240,7 @@ func parseFromHeader(headerText string, h *FromHeader) error {
return nil
}

func headerParserContact(headerName string, headerText string) (header Header, err error) {
func headerParserContact(headerName []byte, headerText string) (header Header, err error) {
h := ContactHeader{}
return &h, parseContactHeader(headerText, &h)
}
Expand Down Expand Up @@ -285,7 +285,7 @@ func parseContactHeader(headerText string, h *ContactHeader) error {
return err
}

func headerParserRoute(headerName string, headerText string) (header Header, err error) {
func headerParserRoute(headerName []byte, headerText string) (header Header, err error) {
// Append a comma to simplify the parsing code; we split address sections
// on commas, so use a comma to signify the end of the final address section.
h := RouteHeader{}
Expand All @@ -298,7 +298,7 @@ func parseRouteHeader(headerText string, h *RouteHeader) error {
}

// parseRouteHeader generates RecordRouteHeader
func headerParserRecordRoute(headerName string, headerText string) (header Header, err error) {
func headerParserRecordRoute(headerName []byte, headerText string) (header Header, err error) {
// Append a comma to simplify the parsing code; we split address sections
// on commas, so use a comma to signify the end of the final address section.
h := RecordRouteHeader{}
Expand All @@ -309,7 +309,7 @@ func parseRecordRouteHeader(headerText string, h *RecordRouteHeader) error {
return parseRouteAddress(headerText, &h.Address)
}

func headerParserReferTo(headerName string, headerText string) (header Header, err error) {
func headerParserReferTo(headerName []byte, headerText string) (header Header, err error) {
h := ReferToHeader{}
return &h, parseReferToHeader(headerText, &h)
}
Expand All @@ -318,7 +318,7 @@ 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) {
func headerParserReferredBy(headerName []byte, headerText string) (header Header, err error) {
h := &ReferredByHeader{}
return h, parseReferredByHeader(headerText, h)
}
Expand Down
60 changes: 27 additions & 33 deletions sip/parse_header.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package sip

import (
"bytes"
"fmt"
"strconv"
"strings"
Expand All @@ -10,9 +11,9 @@ import (
// Some of headers parsing are moved to different files for better maintance

// A HeaderParser is any function that turns raw header data into one or more Header objects.
type HeaderParser func(headerName string, headerData string) (Header, error)
type HeaderParser func(headerName []byte, headerData string) (Header, error)

type mapHeadersParser map[string]HeaderParser
type HeadersParser map[string]HeaderParser

type errComaDetected int

Expand All @@ -37,7 +38,7 @@ func (e errComaDetected) Error() string {
// t To RFC 3261
// u Allow-Events -events- "understand"
// v Via RFC 3261
var headersParsers = mapHeadersParser{
var headersParsers = HeadersParser{
"c": headerParserContentType,
"content-type": headerParserContentType,
"f": headerParserFrom,
Expand Down Expand Up @@ -66,56 +67,49 @@ func DefaultHeadersParser() map[string]HeaderParser {
return headersParsers
}

// parseMsgHeader will append any parsed header
// In case comma seperated values it will add them as new in case comma is detected
func (headersParser mapHeadersParser) parseMsgHeader(msg Message, headerText string) (err error) {
// p.log.Tracef("parsing header \"%s\"", headerText)

colonIdx := strings.Index(headerText, ":")
// ParseHeader parses a SIP header from the line and appends it to out.
func (headersParser HeadersParser) ParseHeader(out []Header, line []byte) ([]Header, error) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was avoiding to expose this, but I guess there is use case?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm quite happy with the current API having the ParseHeader which avoids the body, so we could unexport it back. The reason I still exposed it is just in case we'll need something more exotic for parsing, while still keeping compatibility with sipgo data structures. We'll need to call this directly then. Maybe the answer is similar to the one for NextLine - move it to another package like parser. Would that work?

colonIdx := bytes.IndexByte(line, ':')
if colonIdx == -1 {
err = fmt.Errorf("field name with no value in header: %s", headerText)
return
return out, fmt.Errorf("field name with no value in header: %q", line)
}

fieldName := strings.TrimSpace(headerText[:colonIdx])
lowerFieldName := HeaderToLower(fieldName)
fieldText := strings.TrimSpace(headerText[colonIdx+1:])
fieldName := bytes.TrimSpace(line[:colonIdx])
lowerFieldName := headerToLower(fieldName)
fieldValue := bytes.TrimSpace(line[colonIdx+1:])

headerParser, ok := headersParser[lowerFieldName]
headerParser, ok := headersParser[string(lowerFieldName)]
if !ok {
// We have no registered parser for this header type,
// so we encapsulate the header data in a GenericHeader struct.
// We do only forwarding on this with trimmed space. Validation and parsing is required by user

header := NewHeader(fieldName, fieldText)
msg.AppendHeader(header)
return nil
h := NewHeader(string(fieldName), string(fieldValue))
out = append(out, h)
return out, nil
}

// Support comma seperated value
fieldText := string(fieldValue)
// Support comma separated values
for {
// We have a registered parser for this header type - use it.
// headerParser should detect comma (,) and return as error
header, err := headerParser(lowerFieldName, fieldText)

// Mostly we will run with no error
h, err := headerParser(lowerFieldName, fieldText)
if err == nil {
msg.AppendHeader(header)
return nil
out = append(out, h)
return out, nil
}

commaErr, ok := err.(errComaDetected)
if !ok {
return err
return out, err
}

// Ok we detected we have comma in header value
msg.AppendHeader(header)
out = append(out, h)
fieldText = fieldText[commaErr+1:]
}
}

func headerParserCallId(headerName string, headerText string) (header Header, err error) {
func headerParserCallId(headerName []byte, headerText string) (header Header, err error) {
var callId CallIDHeader
return &callId, parseCallIdHeader(headerText, &callId)
}
Expand All @@ -131,7 +125,7 @@ func parseCallIdHeader(headerText string, callId *CallIDHeader) error {
return nil
}

func headerParserMaxForwards(headerName string, headerText string) (header Header, err error) {
func headerParserMaxForwards(headerName []byte, headerText string) (header Header, err error) {
var maxfwd MaxForwardsHeader
return &maxfwd, parseMaxForwardsHeader(headerText, &maxfwd)
}
Expand All @@ -143,7 +137,7 @@ func parseMaxForwardsHeader(headerText string, maxfwd *MaxForwardsHeader) error
return err
}

func headerParserCSeq(headerName string, headerText string) (headers Header, err error) {
func headerParserCSeq(headerName []byte, headerText string) (headers Header, err error) {
var cseq CSeqHeader
return &cseq, parseCSeqHeader(headerText, &cseq)
}
Expand All @@ -169,7 +163,7 @@ func parseCSeqHeader(headerText string, cseq *CSeqHeader) error {
return nil
}

func headerParserContentLength(headerName string, headerText string) (header Header, err error) {
func headerParserContentLength(headerName []byte, headerText string) (header Header, err error) {
var contentLength ContentLengthHeader
return &contentLength, parseContentLengthHeader(headerText, &contentLength)
}
Expand All @@ -182,7 +176,7 @@ func parseContentLengthHeader(headerText string, contentLength *ContentLengthHea
}

// headerParserContentType parses ContentType header
func headerParserContentType(headerName string, headerText string) (headers Header, err error) {
func headerParserContentType(headerName []byte, headerText string) (headers Header, err error) {
var contentType ContentTypeHeader
return &contentType, parseContentTypeHeader(headerText, &contentType)
}
Expand Down
2 changes: 1 addition & 1 deletion sip/parse_via.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"strings"
)

func headerParserVia(headerName string, headerText string) (
func headerParserVia(headerName []byte, headerText string) (
header Header, err error) {
// sections := strings.Split(headerText, ",")
h := ViaHeader{
Expand Down
Loading
Loading