Skip to content

Commit

Permalink
Changing sip parser interface to use ParseSIP as more exact func #18
Browse files Browse the repository at this point in the history
  • Loading branch information
emiago committed Mar 20, 2023
1 parent 25db1cc commit b324967
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 89 deletions.
12 changes: 6 additions & 6 deletions example/proxysip/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func inviteScenario(t testing.TB, client1, client2 fakes.TestConnection, p *pars
//RECEIVE INVITE
{
res := client2.TestReadConn(t)
inviteReqRec, err := p.Parse(res)
inviteReqRec, err := p.ParseSIP(res)
require.Nil(t, err)
assert.Equal(t, inviteReqRec.(*sip.Request).StartLine(), inviteReq.(*sip.Request).StartLine())

Expand All @@ -110,7 +110,7 @@ func inviteScenario(t testing.TB, client1, client2 fakes.TestConnection, p *pars
for {
res := client2.TestReadConn(t)

resReceived, err := p.Parse(res)
resReceived, err := p.ParseSIP(res)
if req, ok := resReceived.(*sip.Request); ok && req.IsInvite() {
continue
}
Expand Down Expand Up @@ -143,12 +143,12 @@ func inviteScenario(t testing.TB, client1, client2 fakes.TestConnection, p *pars
t.Log("CLIENT1: Send INVITE")
res := client1.TestRequest(t, []byte(inviteReq.String()))
t.Log("CLIENT1 INVITE: Got response")
trying, err := p.Parse(res)
trying, err := p.ParseSIP(res)
require.Nil(t, err)
assert.Equal(t, "SIP/2.0 100 Trying", trying.(*sip.Response).StartLine())

res = client1.TestReadConn(t)
inviteOK, err := p.Parse(res)
inviteOK, err := p.ParseSIP(res)
require.Nil(t, err)
assert.Equal(t, "SIP/2.0 200 OK", inviteOK.(*sip.Response).StartLine())
}
Expand All @@ -165,7 +165,7 @@ func inviteScenario(t testing.TB, client1, client2 fakes.TestConnection, p *pars
t.Log("CLIENT1: Send BYE")
res := client1.TestRequest(t, []byte(byeReq.String()))
t.Log("CLIENT1 BYE: Got response")
byeOK, err := p.Parse(res)
byeOK, err := p.ParseSIP(res)
require.Nil(t, err)
assert.Equal(t, "SIP/2.0 200 OK", byeOK.(*sip.Response).StartLine())
}
Expand Down Expand Up @@ -362,7 +362,7 @@ func TestRegisterTCP(t *testing.T) {
})

res := client1.TestRequest(t, []byte(reg.String()))
res200, err := p.Parse(res)
res200, err := p.ParseSIP(res)
require.Nil(t, err)
t.Log(res200.String())
assert.Equal(t, "SIP/2.0 200 OK", res200.(*sip.Response).StartLine())
Expand Down
76 changes: 32 additions & 44 deletions parser/parser.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// Originaly forked from github.com/StefanKopieczek/gossip by @StefanKopieczek
package parser

import (
Expand Down Expand Up @@ -37,24 +36,13 @@ var bufReader = sync.Pool{
},
}

// The buffer size of the parser input channel.
// SipParser is interface for decoding full message into sip message
type SIPParser interface {
Parse(data []byte) (sip.Message, error)
}

// SIPParserStreamed is parser that allows streamed data for parsing
type SIPParserStreamed interface {
Write(data []byte) (int, error)
Output() chan sip.Message
}

// Parse a SIP message by creating a parser on the fly.
func ParseMessage(msgData []byte) (sip.Message, error) {
parser := NewParser()
return parser.Parse(msgData)
return parser.ParseSIP(msgData)
}

// Parser is implementation of sip.SIPParser
// It is optimized with faster header parsing
type Parser struct {
log zerolog.Logger
// HeadersParsers uses default list of headers to be parsed. Smaller list parser will be faster
Expand Down Expand Up @@ -96,8 +84,8 @@ func WithHeadersParsers(m map[string]HeaderParser) ParserOption {
}
}

// Parse converts data to sip message. Buffer must contain full sip message
func (p *Parser) Parse(data []byte) (msg sip.Message, err error) {
// ParseSIP converts data to sip message. Buffer must contain full sip message
func (p *Parser) ParseSIP(data []byte) (msg sip.Message, err error) {
reader := bufReader.Get().(*bytes.Buffer)
defer bufReader.Put(reader)
reader.Reset()
Expand Down Expand Up @@ -125,7 +113,7 @@ func (p *Parser) Parse(data []byte) (msg sip.Message, err error) {
break
}

header, err := p.ParseHeader(line)
header, err := p.parseHeader(line)
if err == nil {
msg.AppendHeader(header)
} else {
Expand Down Expand Up @@ -160,6 +148,32 @@ func (p *Parser) Parse(data []byte) (msg sip.Message, err error) {
return msg, nil
}

func (p *Parser) parseHeader(headerText string) (header sip.Header, err error) {
// p.log.Tracef("parsing header \"%s\"", headerText)

colonIdx := strings.Index(headerText, ":")
if colonIdx == -1 {
err = fmt.Errorf("field name with no value in header: %s", headerText)
return
}

fieldName := strings.TrimSpace(headerText[:colonIdx])
lowerFieldName := sip.HeaderToLower(fieldName)
fieldText := strings.TrimSpace(headerText[colonIdx+1:])
if headerParser, ok := p.headersParsers[lowerFieldName]; ok {
// We have a registered parser for this header type - use it.
// header, err = headerParser(lowerFieldName, fieldText)
header, err = headerParser(lowerFieldName, fieldText)
} else {
// We have no registered parser for this header type,
// so we encapsulate the header data in a GenericHeader struct.
// p.log.Tracef("no parser for header type %s", fieldName)
header = sip.NewHeader(fieldName, fieldText)
}

return
}

func ParseLine(startLine string) (msg sip.Message, err error) {
if isRequest(startLine) {
recipient := sip.Uri{}
Expand Down Expand Up @@ -330,29 +344,3 @@ func ParseStatusLine(statusLine string) (

return
}

func (p *Parser) ParseHeader(headerText string) (header sip.Header, err error) {
// p.log.Tracef("parsing header \"%s\"", headerText)

colonIdx := strings.Index(headerText, ":")
if colonIdx == -1 {
err = fmt.Errorf("field name with no value in header: %s", headerText)
return
}

fieldName := strings.TrimSpace(headerText[:colonIdx])
lowerFieldName := sip.HeaderToLower(fieldName)
fieldText := strings.TrimSpace(headerText[colonIdx+1:])
if headerParser, ok := p.headersParsers[lowerFieldName]; ok {
// We have a registered parser for this header type - use it.
// header, err = headerParser(lowerFieldName, fieldText)
header, err = headerParser(lowerFieldName, fieldText)
} else {
// We have no registered parser for this header type,
// so we encapsulate the header data in a GenericHeader struct.
// p.log.Tracef("no parser for header type %s", fieldName)
header = sip.NewHeader(fieldName, fieldText)
}

return
}
26 changes: 13 additions & 13 deletions parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func TestParseHeaders(t *testing.T) {
t.Run("ViaHeader", func(t *testing.T) {
branch := sip.GenerateBranch()
header := "Via: SIP/2.0/UDP 127.0.0.2:5060;rport;branch=" + branch
h, err := parser.ParseHeader(header)
h, err := parser.parseHeader(header)
require.Nil(t, err)

hstr := h.String()
Expand All @@ -102,7 +102,7 @@ func TestParseHeaders(t *testing.T) {

t.Run("ToHeader", func(t *testing.T) {
header := "To: \"Bob\" <sip:[email protected]:5060>;xxx=xxx;yyyy=yyyy"
h, err := parser.ParseHeader(header)
h, err := parser.parseHeader(header)
require.Nil(t, err)

hstr := h.String()
Expand All @@ -112,7 +112,7 @@ func TestParseHeaders(t *testing.T) {

t.Run("FromHeader", func(t *testing.T) {
header := "From: \"Bob\" <sip:[email protected]:5060>"
h, err := parser.ParseHeader(header)
h, err := parser.parseHeader(header)
require.Nil(t, err)

hstr := h.String()
Expand All @@ -126,7 +126,7 @@ func TestParseHeaders(t *testing.T) {
"Contact: <sip:127.0.0.2:5060;transport=UDP>": "Contact: <sip:127.0.0.2:5060;transport=UDP>",
// "m: <sip:[email protected]:50267;transport=TCP;ob>;reg-id=1;+sip.instance=\"<urn:uuid:00000000-0000-0000-0000-0000eb83488d>\"": "Contact: <sip:[email protected]:50267;transport=TCP;ob>;reg-id=1;+sip.instance=\"<urn:uuid:00000000-0000-0000-0000-0000eb83488d>\"",
} {
h, err := parser.ParseHeader(header)
h, err := parser.parseHeader(header)
require.Nil(t, err)
assert.IsType(t, &sip.ContactHeader{}, h)

Expand All @@ -137,7 +137,7 @@ func TestParseHeaders(t *testing.T) {

t.Run("RouteHeader", func(t *testing.T) {
header := "Route: <sip:[email protected]:5061;transport=tls;lr>"
h, err := parser.ParseHeader(header)
h, err := parser.parseHeader(header)
require.Nil(t, err, err)

hstr := h.String()
Expand All @@ -147,7 +147,7 @@ func TestParseHeaders(t *testing.T) {

t.Run("RecordRouteHeader", func(t *testing.T) {
header := "Record-Route: <sip:[email protected]:5061;transport=tls;lr>"
h, err := parser.ParseHeader(header)
h, err := parser.parseHeader(header)
require.Nil(t, err, err)

hstr := h.String()
Expand All @@ -157,7 +157,7 @@ func TestParseHeaders(t *testing.T) {

t.Run("MaxForwards", func(t *testing.T) {
header := "Max-Forwards: 70"
h, err := parser.ParseHeader(header)
h, err := parser.parseHeader(header)
require.Nil(t, err, err)

exp := sip.MaxForwardsHeader(70)
Expand Down Expand Up @@ -256,7 +256,7 @@ func TestParseRequest(t *testing.T) {
"INVITE sip:10.5.0.10:5060;transport=udp SIP/2.0\r\nContent-Length: 0\r\n\n",
"INVITE sip:10.5.0.10:5060;transport=udp SIP/2.0\r\nContent-Length: 10\r\nabcd\nefgh",
} {
_, err := parser.Parse([]byte(msgstr))
_, err := parser.ParseSIP([]byte(msgstr))
assert.Equal(t, ErrLineNoCRLF, err)
}
})
Expand Down Expand Up @@ -301,7 +301,7 @@ func TestParseRequest(t *testing.T) {

msgstr := strings.Join(rawMsg, "\r\n")

msg, err := parser.Parse([]byte(msgstr))
msg, err := parser.ParseSIP([]byte(msgstr))
require.Nil(t, err)

from, exists := msg.From()
Expand Down Expand Up @@ -343,7 +343,7 @@ func TestRegisterRequestFail(t *testing.T) {
data := []byte(strings.Join(rawMsg, "\r\n"))

parser := NewParser()
msg, err := parser.Parse(data)
msg, err := parser.ParseSIP(data)
require.Nil(t, err, err)
req := msg.(*sip.Request)

Expand Down Expand Up @@ -378,7 +378,7 @@ func BenchmarkParser(b *testing.B) {
b.ResetTimer()
testcase := func(b *testing.B) {
for i := 0; i < b.N; i++ {
msg, err := parser.Parse(data)
msg, err := parser.ParseSIP(data)
if err != nil {
b.Fatal(err)
}
Expand All @@ -393,7 +393,7 @@ func BenchmarkParser(b *testing.B) {
b.RunParallel(func(p *testing.PB) {
i := 0
for p.Next() {
msg, err := parser.Parse(data)
msg, err := parser.ParseSIP(data)
if err != nil {
b.Fatal(err)
}
Expand Down Expand Up @@ -466,7 +466,7 @@ func BenchmarkParserNoData(b *testing.B) {
b.Run("New", func(b *testing.B) {
parser := NewParser()
for i := 0; i < b.N; i++ {
parser.Parse(data)
parser.ParseSIP(data)
}
})
}
Expand Down
8 changes: 4 additions & 4 deletions server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ func TestUDPUAS(t *testing.T) {
rstr := req.String()

data := client1.TestRequest(t, []byte(rstr))
res, err := p.Parse(data)
res, err := p.ParseSIP(data)
assert.Nil(t, err)

assert.Equal(t, "SIP/2.0 200 OK", res.(*sip.Response).StartLine())
Expand All @@ -199,7 +199,7 @@ func TestUDPUAS(t *testing.T) {

req := createSimpleRequest("NONALLOWED", sender, recipment, "UDP")
data := client1.TestRequest(t, []byte(req.String()))
res, err := p.Parse(data)
res, err := p.ParseSIP(data)
assert.Nil(t, err)
assert.Equal(t, "SIP/2.0 405 Method Not Allowed", res.(*sip.Response).StartLine())

Expand Down Expand Up @@ -284,7 +284,7 @@ func TestTCPUAS(t *testing.T) {
rstr := req.String()

data := client1.TestRequest(t, []byte(rstr))
res, err := p.Parse(data)
res, err := p.ParseSIP(data)
assert.Nil(t, err)
assert.Equal(t, "SIP/2.0 200 OK", res.(*sip.Response).StartLine())
}
Expand All @@ -297,7 +297,7 @@ func TestTCPUAS(t *testing.T) {

req := createSimpleRequest("NONALLOWED", sender, recipment, "TCP")
data := client1.TestRequest(t, []byte(req.String()))
res, err := p.Parse(data)
res, err := p.ParseSIP(data)
assert.Nil(t, err)
assert.Equal(t, "SIP/2.0 405 Method Not Allowed", res.(*sip.Response).StartLine())

Expand Down
6 changes: 6 additions & 0 deletions sip/sip.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ const (
RFC3261BranchMagicCookie = "z9hG4bK"
)

// The buffer size of the parser input channel.
// Parser is interface for decoding full message into sip message
type Parser interface {
ParseSIP(data []byte) (Message, error)
}

// GenerateBranch returns random unique branch ID.
func GenerateBranch() string {
return GenerateBranchN(16)
Expand Down
Loading

0 comments on commit b324967

Please sign in to comment.