Browse Source

Use linked lists for parameters.

pull/2/head
Justine Alexandra Roberts Tunney 11 years ago
parent
commit
556208ab65
21 changed files with 700 additions and 807 deletions
  1. +4
    -4
      example/echo/echo_test.go
  2. +15
    -18
      example/options/options_test.go
  3. +5
    -5
      sip/addr.go
  4. +10
    -30
      sip/addr_test.go
  5. +4
    -4
      sip/dialog.go
  6. +1
    -1
      sip/msg.go
  7. +345
    -363
      sip/msg_parse.go
  8. +69
    -52
      sip/msg_test.go
  9. +39
    -0
      sip/param.go
  10. +0
    -63
      sip/params.go
  11. +3
    -3
      sip/receiver.go
  12. +8
    -10
      sip/route.go
  13. +2
    -8
      sip/sip.rl
  14. +1
    -1
      sip/transport.go
  15. +11
    -49
      sip/uri.go
  16. +83
    -163
      sip/uri_parse.go
  17. +2
    -8
      sip/uri_parse.rl
  18. +6
    -17
      sip/uri_test.go
  19. +44
    -0
      sip/uriheader.go
  20. +40
    -0
      sip/uriparam.go
  21. +8
    -8
      sip/via.go

+ 4
- 4
example/echo/echo_test.go View File

@ -177,9 +177,9 @@ func TestCallToEchoApp(t *testing.T) {
Port: uint16(raddr.Port), Port: uint16(raddr.Port),
}, },
Via: &sip.Via{ Via: &sip.Via{
Host: laddr.IP.String(),
Port: uint16(laddr.Port),
Params: sip.Params{"branch": util.GenerateBranch()},
Host: laddr.IP.String(),
Port: uint16(laddr.Port),
Param: &sip.Param{"branch", util.GenerateBranch(), nil},
}, },
From: &sip.Addr{ From: &sip.Addr{
Display: "Echo Test", Display: "Echo Test",
@ -188,7 +188,7 @@ func TestCallToEchoApp(t *testing.T) {
Host: laddr.IP.String(), Host: laddr.IP.String(),
Port: uint16(laddr.Port), Port: uint16(laddr.Port),
}, },
Params: sip.Params{"tag": util.GenerateTag()},
Param: &sip.Param{"tag", util.GenerateTag(), nil},
}, },
To: &sip.Addr{ To: &sip.Addr{
Uri: &sip.URI{ Uri: &sip.URI{


+ 15
- 18
example/options/options_test.go View File

@ -7,7 +7,6 @@ import (
"github.com/jart/gosip/sip" "github.com/jart/gosip/sip"
"github.com/jart/gosip/util" "github.com/jart/gosip/util"
"net" "net"
"reflect"
"testing" "testing"
"time" "time"
) )
@ -27,6 +26,8 @@ func TestOptions(t *testing.T) {
CallID: util.GenerateCallID(), CallID: util.GenerateCallID(),
Method: "OPTIONS", Method: "OPTIONS",
CSeqMethod: "OPTIONS", CSeqMethod: "OPTIONS",
Accept: "application/sdp",
UserAgent: "pokémon/1.o",
Request: &sip.URI{ Request: &sip.URI{
Scheme: "sip", Scheme: "sip",
User: "echo", User: "echo",
@ -34,11 +35,11 @@ func TestOptions(t *testing.T) {
Port: uint16(raddr.Port), Port: uint16(raddr.Port),
}, },
Via: &sip.Via{ Via: &sip.Via{
Version: "2.0",
Proto: "UDP",
Host: laddr.IP.String(),
Port: uint16(laddr.Port),
Params: sip.Params{"branch": util.GenerateBranch()},
Version: "2.0",
Protocol: "UDP",
Host: laddr.IP.String(),
Port: uint16(laddr.Port),
Param: &sip.Param{"branch", util.GenerateBranch(), nil},
}, },
Contact: &sip.Addr{ Contact: &sip.Addr{
Uri: &sip.URI{ Uri: &sip.URI{
@ -52,7 +53,7 @@ func TestOptions(t *testing.T) {
Host: "justinetunney.com", Host: "justinetunney.com",
Port: 5060, Port: 5060,
}, },
Params: sip.Params{"tag": util.GenerateTag()},
Param: &sip.Param{"tag", util.GenerateTag(), nil},
}, },
To: &sip.Addr{ To: &sip.Addr{
Uri: &sip.URI{ Uri: &sip.URI{
@ -60,10 +61,6 @@ func TestOptions(t *testing.T) {
Port: uint16(raddr.Port), Port: uint16(raddr.Port),
}, },
}, },
Headers: map[string]string{
"Accept": "application/sdp",
"User-Agent": "pokémon/1.o",
},
} }
var b bytes.Buffer var b bytes.Buffer
@ -95,14 +92,14 @@ func TestOptions(t *testing.T) {
if options.CSeq != msg.CSeq || options.CSeqMethod != msg.CSeqMethod { if options.CSeq != msg.CSeq || options.CSeqMethod != msg.CSeqMethod {
t.Error("CSeq didnt match") t.Error("CSeq didnt match")
} }
if !reflect.DeepEqual(options.From, msg.From) {
t.Error("From headers didn't match:\n%#v\n%#v", options.From, msg.From)
if options.From.String() != msg.From.String() {
t.Errorf("From headers didn't match:\n%s\n%s\n\n%s", options.From, msg.From, memory[0:amt])
} }
if _, ok := msg.To.Params["tag"]; !ok {
t.Error("Remote UA didnt tag To header")
if msg.To.Param.Get("tag") == nil {
t.Errorf("Remote UA didnt tag To header:\n%s\n\n%s", msg.To, memory[0:amt])
} }
msg.To.Params = nil
if !reflect.DeepEqual(options.To, msg.To) {
t.Error("To mismatch:\n%#v\n%#v", options.To, msg.To)
msg.To.Param = nil
if options.To.String() != msg.To.String() {
t.Errorf("To headers didn't match:\n%s\n%s\n\n%s", options.To, msg.To, memory[0:amt])
} }
} }

+ 5
- 5
sip/addr.go View File

@ -27,7 +27,7 @@ import (
type Addr struct { type Addr struct {
Uri *URI // never nil Uri *URI // never nil
Display string // blank if not specified Display string // blank if not specified
Params Params // these look like ;key=lol;rport;key=wut
Param *Param // these look like ;key=lol;rport;key=wut
Next *Addr // for comma separated lists of addresses Next *Addr // for comma separated lists of addresses
} }
@ -49,7 +49,7 @@ func ParseAddrBytes(s []byte) (addr *Addr, err error) {
func (addr *Addr) String() string { func (addr *Addr) String() string {
if addr == nil { if addr == nil {
return "<nil>"
return ""
} }
var b bytes.Buffer var b bytes.Buffer
addr.Append(&b) addr.Append(&b)
@ -66,7 +66,7 @@ func (addr *Addr) Or(other *Addr) *Addr {
// Sets newly generated tag ID and returns self. // Sets newly generated tag ID and returns self.
func (addr *Addr) Tag() *Addr { func (addr *Addr) Tag() *Addr {
addr.Params["tag"] = util.GenerateTag()
addr.Param = &Param{"tag", util.GenerateTag(), addr.Param}
return addr return addr
} }
@ -79,7 +79,7 @@ func (addr *Addr) Append(b *bytes.Buffer) error {
b.WriteByte('<') b.WriteByte('<')
addr.Uri.Append(b) addr.Uri.Append(b)
b.WriteByte('>') b.WriteByte('>')
addr.Params.AppendQuoted(b)
addr.Param.Append(b)
if addr.Next != nil { if addr.Next != nil {
b.WriteByte(',') b.WriteByte(',')
b.WriteByte(' ') b.WriteByte(' ')
@ -95,7 +95,7 @@ func (addr *Addr) Copy() *Addr {
} }
res := new(Addr) res := new(Addr)
res.Uri = addr.Uri.Copy() res.Uri = addr.Uri.Copy()
res.Params = addr.Params.Copy()
res.Param = addr.Param
res.Next = addr.Next.Copy() res.Next = addr.Next.Copy()
return res return res
} }


+ 10
- 30
sip/addr_test.go View File

@ -35,9 +35,7 @@ var addrTests = []addrTest{
Scheme: "sip", Scheme: "sip",
Host: "pokemon.net", Host: "pokemon.net",
}, },
Params: sip.Params{
"tag": "deadbeef",
},
Param: &sip.Param{"tag", "deadbeef", nil},
}, },
}, },
@ -50,9 +48,7 @@ var addrTests = []addrTest{
Scheme: "sip", Scheme: "sip",
Host: "pokemon.net", Host: "pokemon.net",
}, },
Params: sip.Params{
"tag": "deadbeef",
},
Param: &sip.Param{"tag", "deadbeef", nil},
}, },
}, },
@ -65,9 +61,7 @@ var addrTests = []addrTest{
Scheme: "sip", Scheme: "sip",
Host: "pokemon.net", Host: "pokemon.net",
}, },
Params: sip.Params{
"tag": "deadbeef",
},
Param: &sip.Param{"tag", "deadbeef", nil},
}, },
}, },
@ -80,9 +74,7 @@ var addrTests = []addrTest{
Scheme: "sip", Scheme: "sip",
Host: "pokemon.net", Host: "pokemon.net",
}, },
Params: sip.Params{
"tag": "deadbeef",
},
Param: &sip.Param{"tag", "deadbeef", nil},
}, },
}, },
@ -94,9 +86,7 @@ var addrTests = []addrTest{
Scheme: "sip", Scheme: "sip",
Host: "pokemon.net", Host: "pokemon.net",
}, },
Params: sip.Params{
"tag": "\"deadbeef\"",
},
Param: &sip.Param{"tag", "\"deadbeef\"", nil},
}, },
}, },
@ -108,9 +98,7 @@ var addrTests = []addrTest{
Scheme: "sip", Scheme: "sip",
User: "brave", User: "brave",
Host: "toaster.net", Host: "toaster.net",
Params: sip.Params{
"isup-oli": "29",
},
Param: &sip.URIParam{"isup-oli", "29", nil},
}, },
}, },
}, },
@ -123,13 +111,9 @@ var addrTests = []addrTest{
Scheme: "sip", Scheme: "sip",
User: "brave", User: "brave",
Host: "toaster.net", Host: "toaster.net",
Params: sip.Params{
"isup-oli": "29",
},
},
Params: sip.Params{
"tag": "deadbeef",
Param: &sip.URIParam{"isup-oli", "29", nil},
}, },
Param: &sip.Param{"tag", "deadbeef", nil},
}, },
}, },
@ -182,13 +166,9 @@ var addrTests = []addrTest{
Scheme: "sip", Scheme: "sip",
User: "jart", User: "jart",
Host: "google.com", Host: "google.com",
Params: sip.Params{
"isup-oli": "29",
},
},
Params: sip.Params{
"tag": "deadbeef",
Param: &sip.URIParam{"isup-oli", "29", nil},
}, },
Param: &sip.Param{"tag", "deadbeef", nil},
}, },
}, },
} }


+ 4
- 4
sip/dialog.go View File

@ -214,9 +214,9 @@ func (dls *dialogState) populate(msg *Msg) {
lhost := laddr.IP.String() lhost := laddr.IP.String()
lport := uint16(laddr.Port) lport := uint16(laddr.Port)
msg.Via = &Via{ msg.Via = &Via{
Host: lhost,
Port: lport,
Params: Params{"branch": util.GenerateBranch()},
Host: lhost,
Port: lport,
Param: &Param{"branch", util.GenerateBranch(), nil},
} }
if msg.Contact == nil { if msg.Contact == nil {
if dls.csock != nil { if dls.csock != nil {
@ -227,7 +227,7 @@ func (dls *dialogState) populate(msg *Msg) {
Scheme: "sip", Scheme: "sip",
Host: lhost, Host: lhost,
Port: lport, Port: lport,
Params: Params{"transport": "udp"},
Param: &URIParam{"transport", "udp", nil},
}, },
} }
} }


+ 1
- 1
sip/msg.go View File

@ -461,7 +461,7 @@ func (msg *Msg) Append(b *bytes.Buffer) error {
payload := msg.Payload.Data() payload := msg.Payload.Data()
b.WriteString("Content-Length: ") b.WriteString("Content-Length: ")
b.WriteString(strconv.Itoa(len(payload))) b.WriteString(strconv.Itoa(len(payload)))
b.WriteString("\r\n\n\n")
b.WriteString("\r\n\r\n")
b.Write(payload) b.Write(payload)
} else { } else {
b.WriteString("Content-Length: 0\r\n\r\n") b.WriteString("Content-Length: 0\r\n\r\n")


+ 345
- 363
sip/msg_parse.go
File diff suppressed because it is too large
View File


+ 69
- 52
sip/msg_test.go View File

@ -313,9 +313,7 @@ var msgTests = []msgTest{
Scheme: "sip", Scheme: "sip",
Host: "lol.com", Host: "lol.com",
}, },
Params: sip.Params{
"tag": "omfg",
},
Param: &sip.Param{"tag", "omfg", nil},
}, },
}, },
}, },
@ -335,9 +333,7 @@ var msgTests = []msgTest{
Scheme: "sip", Scheme: "sip",
Host: "lol.com", Host: "lol.com",
}, },
Params: sip.Params{
"tag": "◕◡◕",
},
Param: &sip.Param{"tag", "◕◡◕", nil},
}, },
}, },
}, },
@ -356,9 +352,7 @@ var msgTests = []msgTest{
Scheme: "sip", Scheme: "sip",
Host: "lol.com", Host: "lol.com",
}, },
Params: sip.Params{
"tag": "",
},
Param: &sip.Param{"tag", "", nil},
}, },
}, },
}, },
@ -377,9 +371,7 @@ var msgTests = []msgTest{
Scheme: "sip", Scheme: "sip",
Host: "lol.com", Host: "lol.com",
}, },
Params: sip.Params{
"tag": "omfg",
},
Param: &sip.Param{"tag", "omfg", nil},
}, },
}, },
}, },
@ -560,7 +552,7 @@ var msgTests = []msgTest{
Version: "2.0", Version: "2.0",
Transport: "TCP", Transport: "TCP",
Host: "spindle.example.com", Host: "spindle.example.com",
Params: sip.Params{"branch": "z9hG4bK9ikj8"},
Param: &sip.Param{"branch", "z9hG4bK9ikj8", nil},
}, },
}, },
}, },
@ -580,7 +572,7 @@ var msgTests = []msgTest{
Version: "2.0", Version: "2.0",
Transport: "TCP", Transport: "TCP",
Host: "spindle.example.com", Host: "spindle.example.com",
Params: sip.Params{"branch": "z9hG4bK9ikj8"},
Param: &sip.Param{"branch", "z9hG4bK9ikj8", nil},
}, },
}, },
}, },
@ -605,19 +597,19 @@ var msgTests = []msgTest{
Version: "2.0", Version: "2.0",
Transport: "UDP", Transport: "UDP",
Host: "192.0.2.2", Host: "192.0.2.2",
Params: sip.Params{"branch": "390skdjuw"},
Param: &sip.Param{"branch", "390skdjuw", nil},
Next: &sip.Via{ Next: &sip.Via{
Protocol: "SIP", Protocol: "SIP",
Version: "2.0", Version: "2.0",
Transport: "TCP", Transport: "TCP",
Host: "spindle.example.com", Host: "spindle.example.com",
Params: sip.Params{"branch": "z9hG4bK9ikj8"},
Param: &sip.Param{"branch", "z9hG4bK9ikj8", nil},
Next: &sip.Via{ Next: &sip.Via{
Protocol: "SIP", Protocol: "SIP",
Version: "2.0", Version: "2.0",
Transport: "UDP", Transport: "UDP",
Host: "192.168.255.111", Host: "192.168.255.111",
Params: sip.Params{"branch": "z9hG4bK30239"},
Param: &sip.Param{"branch", "z9hG4bK30239", nil},
}, },
}, },
}, },
@ -656,7 +648,7 @@ var msgTests = []msgTest{
Transport: "UDP", Transport: "UDP",
Host: "10.11.34.37", Host: "10.11.34.37",
Port: 42367, Port: 42367,
Params: sip.Params{"rport": "", "branch": "9dc39c3c3e84"},
Param: &sip.Param{"branch", "9dc39c3c3e84", &sip.Param{"rport", "", nil}},
}, },
To: &sip.Addr{ To: &sip.Addr{
Uri: &sip.URI{ Uri: &sip.URI{
@ -670,9 +662,9 @@ var msgTests = []msgTest{
Scheme: "sip", Scheme: "sip",
Host: "10.11.34.37", Host: "10.11.34.37",
Port: 42367, Port: 42367,
Params: sip.Params{"laffo": ""},
Param: &sip.URIParam{"laffo", "", nil},
}, },
Params: sip.Params{"tag": "11917cbc0513"},
Param: &sip.Param{"tag", "11917cbc0513", nil},
}, },
Contact: &sip.Addr{ Contact: &sip.Addr{
Uri: &sip.URI{ Uri: &sip.URI{
@ -728,10 +720,17 @@ var msgTests = []msgTest{
Transport: "UDP", Transport: "UDP",
Host: "127.0.0.1", Host: "127.0.0.1",
Port: 52711, Port: 52711,
Params: sip.Params{
"branch": "z9hG4bK-03d1d81e94a0",
"received": "127.0.0.1",
"rport": "52711",
Param: &sip.Param{
Name: "rport",
Value: "52711",
Next: &sip.Param{
Name: "received",
Value: "127.0.0.1",
Next: &sip.Param{
Name: "branch",
Value: "z9hG4bK-03d1d81e94a0",
},
},
}, },
}, },
From: &sip.Addr{ From: &sip.Addr{
@ -739,9 +738,9 @@ var msgTests = []msgTest{
Scheme: "sip", Scheme: "sip",
Host: "127.0.0.1", Host: "127.0.0.1",
Port: 52711, Port: 52711,
Params: sip.Params{"transport": "udp"},
Param: &sip.URIParam{"transport", "udp", nil},
}, },
Params: sip.Params{"tag": "4568e274dbd8"},
Param: &sip.Param{"tag", "4568e274dbd8", nil},
}, },
To: &sip.Addr{ To: &sip.Addr{
Uri: &sip.URI{ Uri: &sip.URI{
@ -750,7 +749,7 @@ var msgTests = []msgTest{
Host: "127.0.0.1", Host: "127.0.0.1",
Port: 5060, Port: 5060,
}, },
Params: sip.Params{"tag": "as71a0fa72"},
Param: &sip.Param{"tag", "as71a0fa72", nil},
}, },
Contact: &sip.Addr{ Contact: &sip.Addr{
Uri: &sip.URI{ Uri: &sip.URI{
@ -814,7 +813,7 @@ var msgTests = []msgTest{
Transport: "UDP", Transport: "UDP",
Host: "1.2.3.4", Host: "1.2.3.4",
Port: 55345, Port: 55345,
Params: sip.Params{"branch": "z9hG4bK-d1d81e94a099"},
Param: &sip.Param{"branch", "z9hG4bK-d1d81e94a099", nil},
}, },
From: &sip.Addr{ From: &sip.Addr{
Uri: &sip.URI{ Uri: &sip.URI{
@ -822,7 +821,7 @@ var msgTests = []msgTest{
User: "+12126660420", User: "+12126660420",
Host: "fl.gg", Host: "fl.gg",
}, },
Params: sip.Params{"tag": "68e274dbd83b"},
Param: &sip.Param{"tag", "68e274dbd83b", nil},
}, },
To: &sip.Addr{ To: &sip.Addr{
Uri: &sip.URI{ Uri: &sip.URI{
@ -830,7 +829,7 @@ var msgTests = []msgTest{
User: "+12125650666", User: "+12125650666",
Host: "fl.gg", Host: "fl.gg",
}, },
Params: sip.Params{"tag": "gK0cacc73a"},
Param: &sip.Param{"tag", "gK0cacc73a", nil},
}, },
Contact: &sip.Addr{ Contact: &sip.Addr{
Uri: &sip.URI{ Uri: &sip.URI{
@ -845,14 +844,14 @@ var msgTests = []msgTest{
Scheme: "sip", Scheme: "sip",
Host: "216.115.69.133", Host: "216.115.69.133",
Port: 5060, Port: 5060,
Params: sip.Params{"lr": ""},
Param: &sip.URIParam{"lr", "", nil},
}, },
Next: &sip.Addr{ Next: &sip.Addr{
Uri: &sip.URI{ Uri: &sip.URI{
Scheme: "sip", Scheme: "sip",
Host: "216.115.69.144", Host: "216.115.69.144",
Port: 5060, Port: 5060,
Params: sip.Params{"lr": ""},
Param: &sip.URIParam{"lr", "", nil},
}, },
}, },
}, },
@ -918,7 +917,7 @@ var msgTests = []msgTest{
Transport: "UDP", Transport: "UDP",
Host: "10.11.34.37", Host: "10.11.34.37",
Port: 59516, Port: 59516,
Params: sip.Params{"rport": "", "branch": "z9hG4bKS308QB9UUpNyD"},
Param: &sip.Param{"branch", "z9hG4bKS308QB9UUpNyD", &sip.Param{"rport", "", nil}},
}, },
To: &sip.Addr{ To: &sip.Addr{
Uri: &sip.URI{ Uri: &sip.URI{
@ -932,7 +931,7 @@ var msgTests = []msgTest{
Host: "10.11.34.37", Host: "10.11.34.37",
Port: 59516, Port: 59516,
}, },
Params: sip.Params{"tag": "S1jX7UtK5Zerg"},
Param: &sip.Param{"tag", "S1jX7UtK5Zerg", nil},
}, },
Contact: &sip.Addr{ Contact: &sip.Addr{
Uri: &sip.URI{ Uri: &sip.URI{
@ -1015,7 +1014,7 @@ var msgTests = []msgTest{
Scheme: "sip", Scheme: "sip",
User: "vivekg", User: "vivekg",
Host: "chair-dnrc.example.com", Host: "chair-dnrc.example.com",
Params: sip.Params{"unknownparam": ""},
Param: &sip.URIParam{"unknownparam", "", nil},
}, },
To: &sip.Addr{ To: &sip.Addr{
Uri: &sip.URI{ Uri: &sip.URI{
@ -1023,7 +1022,7 @@ var msgTests = []msgTest{
User: "vivekg", User: "vivekg",
Host: "chair-dnrc.example.com", Host: "chair-dnrc.example.com",
}, },
Params: sip.Params{"tag": "1918181833n"},
Param: &sip.Param{"tag", "1918181833n", nil},
}, },
From: &sip.Addr{ From: &sip.Addr{
Display: "J Rosenberg \\\"", Display: "J Rosenberg \\\"",
@ -1032,7 +1031,7 @@ var msgTests = []msgTest{
User: "jdrosen", User: "jdrosen",
Host: "example.com", Host: "example.com",
}, },
Params: sip.Params{"tag": "98asjd8"},
Param: &sip.Param{"tag", "98asjd8", nil},
}, },
MaxForwards: 68, MaxForwards: 68,
CallID: "wsinv.ndaksdj@192.0.2.1", CallID: "wsinv.ndaksdj@192.0.2.1",
@ -1043,19 +1042,19 @@ var msgTests = []msgTest{
Version: "2.0", Version: "2.0",
Transport: "UDP", Transport: "UDP",
Host: "192.0.2.2", Host: "192.0.2.2",
Params: sip.Params{"branch": "390skdjuw"},
Param: &sip.Param{"branch", "390skdjuw", nil},
Next: &sip.Via{ Next: &sip.Via{
Protocol: "SIP", Protocol: "SIP",
Version: "2.0", Version: "2.0",
Transport: "TCP", Transport: "TCP",
Host: "spindle.example.com", Host: "spindle.example.com",
Params: sip.Params{"branch": "z9hG4bK9ikj8"},
Param: &sip.Param{"branch", "z9hG4bK9ikj8", nil},
Next: &sip.Via{ Next: &sip.Via{
Protocol: "SIP", Protocol: "SIP",
Version: "2.0", Version: "2.0",
Transport: "UDP", Transport: "UDP",
Host: "192.168.255.111", Host: "192.168.255.111",
Params: sip.Params{"branch": "z9hG4bK30239"},
Param: &sip.Param{"branch", "z9hG4bK30239", nil},
}, },
}, },
}, },
@ -1069,10 +1068,17 @@ var msgTests = []msgTest{
Uri: &sip.URI{ Uri: &sip.URI{
Scheme: "sip", Scheme: "sip",
Host: "services.example.com", Host: "services.example.com",
Params: sip.Params{
"lr": "",
"unknownwith": "value",
"unknown-no-value": "",
Param: &sip.URIParam{
Name: "unknown-no-value",
Value: "",
Next: &sip.URIParam{
Name: "unknownwith",
Value: "value",
Next: &sip.URIParam{
Name: "lr",
Value: "",
},
},
}, },
}, },
}, },
@ -1083,10 +1089,17 @@ var msgTests = []msgTest{
User: "jdrosen", User: "jdrosen",
Host: "example.com", Host: "example.com",
}, },
Params: sip.Params{
"newparam": "newvalue",
"secondparam": "",
"q": "0.33",
Param: &sip.Param{
Name: "q",
Value: "0.33",
Next: &sip.Param{
Name: "secondparam",
Value: "",
Next: &sip.Param{
Name: "newparam",
Value: "newvalue",
},
},
}, },
}, },
Payload: &sip.MiscPayload{ Payload: &sip.MiscPayload{
@ -1133,7 +1146,7 @@ var msgTests = []msgTest{
Version: "2.0", Version: "2.0",
Transport: "TCP", Transport: "TCP",
Host: "host1.example.com", Host: "host1.example.com",
Params: sip.Params{"branch": "z9hG4bK-.!%66*_+`'~"},
Param: &sip.Param{"branch", "z9hG4bK-.!%66*_+`'~", nil},
}, },
To: &sip.Addr{ To: &sip.Addr{
Display: "BEL:\x07 NUL:\x00 DEL:\x7F", Display: "BEL:\x07 NUL:\x00 DEL:\x7F",
@ -1150,9 +1163,13 @@ var msgTests = []msgTest{
User: "mundane", User: "mundane",
Host: "example.com", Host: "example.com",
}, },
Params: sip.Params{
"fromParam''~+*_!.-%": "\xD1\x80\xD0\xB0\xD0\xB1\xD0\xBE\xD1\x82\xD0\xB0\xD1\x8E\xD1\x89\xD0\xB8\xD0\xB9",
"tag": "_token~1'+`*%!-.",
Param: &sip.Param{
Name: "tag",
Value: "_token~1'+`*%!-.",
Next: &sip.Param{
Name: "fromParam''~+*_!.-%",
Value: "\xD1\x80\xD0\xB0\xD0\xB1\xD0\xBE\xD1\x82\xD0\xB0\xD1\x8E\xD1\x89\xD0\xB8\xD0\xB9",
},
}, },
}, },
Headers: sip.Headers{ Headers: sip.Headers{


+ 39
- 0
sip/param.go View File

@ -0,0 +1,39 @@
// Addr / Via Parameter Library
package sip
import (
"bytes"
)
// Param is a linked list of ;key="values" for Addr/Via parameters.
type Param struct {
Name string
Value string
Next *Param
}
// Get returns an entry in O(n) time.
func (p *Param) Get(name string) *Param {
if p == nil {
return nil
}
if p.Name == name {
return p
}
return p.Next.Get(name)
}
// Append serializes parameters in insertion order.
func (p *Param) Append(b *bytes.Buffer) {
if p == nil {
return
}
p.Next.Append(b)
b.WriteByte(';')
appendSanitized(b, []byte(p.Name), tokenc)
if p.Value != "" {
b.WriteByte('=')
appendQuoted(b, []byte(p.Value))
}
}

+ 0
- 63
sip/params.go View File

@ -1,63 +0,0 @@
package sip
import (
"bytes"
"sort"
)
type Params map[string]string
func (params Params) Copy() Params {
res := make(Params, len(params))
for k, v := range params {
res[k] = v
}
return res
}
func (params Params) Append(b *bytes.Buffer) {
if params != nil && len(params) > 0 {
keys := make([]string, len(params))
i := 0
for k, _ := range params {
keys[i] = k
i++
}
sort.Strings(keys)
for _, k := range keys {
b.WriteByte(';')
appendEscaped(b, []byte(k), paramc)
v := params[k]
if v != "" {
b.WriteByte('=')
appendEscaped(b, []byte(v), paramc)
}
}
}
}
func (params Params) AppendQuoted(b *bytes.Buffer) {
if params != nil && len(params) > 0 {
keys := make([]string, len(params))
i := 0
for k, _ := range params {
keys[i] = k
i++
}
sort.Strings(keys)
for _, k := range keys {
b.WriteByte(';')
appendSanitized(b, []byte(k), tokenc)
v := params[k]
if v != "" {
b.WriteByte('=')
appendQuoted(b, []byte(v))
}
}
}
}
func (params Params) Has(k string) bool {
_, ok := params["lr"]
return ok
}

+ 3
- 3
sip/receiver.go View File

@ -42,13 +42,13 @@ func ReceiveMessages(sock *net.UDPConn, c chan<- *Msg, e chan<- error) {
func addReceived(msg *Msg, addr *net.UDPAddr) { func addReceived(msg *Msg, addr *net.UDPAddr) {
if msg.Via.Host != addr.IP.String() || int(msg.Via.Port) != addr.Port { if msg.Via.Host != addr.IP.String() || int(msg.Via.Port) != addr.Port {
msg.Via.Params["received"] = addr.String()
msg.Via.Param = &Param{"received", addr.String(), msg.Via.Param}
} }
} }
func addTimestamp(msg *Msg, ts time.Time) { func addTimestamp(msg *Msg, ts time.Time) {
if *timestampTagging { if *timestampTagging {
msg.Via.Params["µsi"] = strconv.FormatInt(ts.UnixNano()/int64(time.Microsecond), 10)
msg.Via.Param = &Param{"usi", strconv.FormatInt(ts.UnixNano()/int64(time.Microsecond), 10), msg.Via.Param}
} }
} }
@ -56,7 +56,7 @@ func addTimestamp(msg *Msg, ts time.Time) {
// RFC3261 16.12.1.2: Traversing a Strict-Routing Proxy // RFC3261 16.12.1.2: Traversing a Strict-Routing Proxy
func fixMessagesFromStrictRouters(lhost string, lport uint16, msg *Msg) { func fixMessagesFromStrictRouters(lhost string, lport uint16, msg *Msg) {
if msg.Request != nil && if msg.Request != nil &&
msg.Request.Params.Has("lr") &&
msg.Request.Param.Get("lr") != nil &&
msg.Route != nil && msg.Route != nil &&
msg.Request.Host == lhost && msg.Request.Host == lhost &&
or5060(msg.Request.Port) == lport { or5060(msg.Request.Port) == lport {


+ 8
- 10
sip/route.go View File

@ -25,7 +25,7 @@ func PopulateMessage(via *Via, contact *Addr, msg *Msg) {
} }
if msg.From == nil { if msg.From == nil {
msg.From = msg.Contact.Copy() msg.From = msg.Contact.Copy()
msg.From.Uri.Params = nil
msg.From.Uri.Param = nil
} }
if msg.CallID == "" { if msg.CallID == "" {
msg.CallID = util.GenerateCallID() msg.CallID = util.GenerateCallID()
@ -42,13 +42,11 @@ func PopulateMessage(via *Via, contact *Addr, msg *Msg) {
if msg.UserAgent == "" { if msg.UserAgent == "" {
msg.UserAgent = GosipUA msg.UserAgent = GosipUA
} }
if _, ok := msg.Via.Params["branch"]; !ok {
msg.Via = msg.Via.Copy()
msg.Via.Params["branch"] = util.GenerateBranch()
if msg.Via.Param.Get("branch") == nil {
msg.Via.Param = &Param{"branch", util.GenerateBranch(), msg.Via.Param}
} }
if _, ok := msg.From.Params["tag"]; !ok {
msg.From = msg.From.Copy()
msg.From.Params["tag"] = util.GenerateTag()
if msg.From.Param.Get("tag") == nil {
msg.From.Param = &Param{"tag", util.GenerateTag(), msg.From.Param}
} }
} }
} }
@ -59,8 +57,8 @@ func RouteMessage(via *Via, contact *Addr, msg *Msg) (host string, port uint16,
msg.Via = msg.Via.Next msg.Via = msg.Via.Next
} }
host, port = msg.Via.Host, msg.Via.Port host, port = msg.Via.Host, msg.Via.Port
if received, ok := msg.Via.Params["received"]; ok {
host = received
if received := msg.Via.Param.Get("received"); received != nil {
host = received.Value
} }
} else { } else {
if contact.CompareHostPort(msg.Route) { if contact.CompareHostPort(msg.Route) {
@ -70,7 +68,7 @@ func RouteMessage(via *Via, contact *Addr, msg *Msg) (host string, port uint16,
if msg.Method == "REGISTER" { if msg.Method == "REGISTER" {
return "", 0, errors.New("Don't route REGISTER requests") return "", 0, errors.New("Don't route REGISTER requests")
} }
if msg.Route.Uri.Params.Has("lr") {
if msg.Route.Uri.Param.Get("lr") != nil {
// RFC3261 16.12.1.1 Basic SIP Trapezoid // RFC3261 16.12.1.1 Basic SIP Trapezoid
host, port = msg.Route.Uri.Host, msg.Route.Uri.Port host, port = msg.Route.Uri.Host, msg.Route.Uri.Port
} else { } else {


+ 2
- 8
sip/sip.rl View File

@ -147,10 +147,7 @@ action ViaPort {
} }
action ViaParam { action ViaParam {
if via.Params == nil {
via.Params = Params{}
}
via.Params[name] = string(buf[0:amt])
via.Param = &Param{name, string(buf[0:amt]), via.Param}
} }
action gxh { action gxh {
@ -196,10 +193,7 @@ action AddrUri {
} }
action AddrParam { action AddrParam {
if addr.Params == nil {
addr.Params = Params{}
}
addr.Params[name] = string(buf[0:amt])
addr.Param = &Param{name, string(buf[0:amt]), addr.Param}
} }
action Addr { action Addr {


+ 1
- 1
sip/transport.go View File

@ -37,7 +37,7 @@ func NewTransport(contact *Addr) (tp *Transport, err error) {
contact = contact.Copy() contact = contact.Copy()
contact.Next = nil contact.Next = nil
contact.Uri.Port = uint16(addr.Port) contact.Uri.Port = uint16(addr.Port)
contact.Uri.Params["transport"] = "udp"
contact.Uri.Param = &URIParam{"transport", "udp", contact.Uri.Param}
c := make(chan *Msg) c := make(chan *Msg)
e := make(chan error) e := make(chan error)
tp = &Transport{ tp = &Transport{


+ 11
- 49
sip/uri.go View File

@ -24,7 +24,6 @@ import (
"bytes" "bytes"
"errors" "errors"
"github.com/jart/gosip/util" "github.com/jart/gosip/util"
"sort"
) )
const ( const (
@ -37,16 +36,14 @@ var (
URIBadPort = errors.New("invalid port number") URIBadPort = errors.New("invalid port number")
) )
type URIHeaders map[string]string
type URI struct { type URI struct {
Scheme string // e.g. sip, sips, tel, etc.
User string // e.g. sip:USER@host
Pass string // e.g. sip:user:PASS@host
Host string // e.g. example.com, 1.2.3.4, etc.
Port uint16 // e.g. 5060, 80, etc.
Params Params // e.g. ;isup-oli=00;day=tuesday
Headers URIHeaders // e.g. ?subject=project%20x&lol=cat
Scheme string // e.g. sip, sips, tel, etc.
User string // e.g. sip:USER@host
Pass string // e.g. sip:user:PASS@host
Host string // e.g. example.com, 1.2.3.4, etc.
Port uint16 // e.g. 5060, 80, etc.
Param *URIParam // e.g. ;isup-oli=00;day=tuesday
Header *URIHeader // e.g. ?subject=project%20x&lol=cat
} }
//go:generate ragel -Z -G2 -o uri_parse.go uri_parse.rl //go:generate ragel -Z -G2 -o uri_parse.go uri_parse.rl
@ -58,8 +55,8 @@ func (uri *URI) Copy() *URI {
} }
res := new(URI) res := new(URI)
*res = *uri *res = *uri
res.Params = uri.Params.Copy()
res.Headers = uri.Headers.Copy()
res.Param = uri.Param
res.Header = uri.Header
return res return res
} }
@ -102,8 +99,8 @@ func (uri *URI) Append(b *bytes.Buffer) {
b.WriteByte(':') b.WriteByte(':')
b.WriteString(portstr(uri.Port)) b.WriteString(portstr(uri.Port))
} }
uri.Params.Append(b)
uri.Headers.Append(b)
uri.Param.Append(b)
uri.Header.Append(b)
} }
func (uri *URI) CompareHostPort(other *URI) bool { func (uri *URI) CompareHostPort(other *URI) bool {
@ -126,38 +123,3 @@ func (uri *URI) GetPort() uint16 {
return uri.Port return uri.Port
} }
} }
func (headers URIHeaders) Copy() URIHeaders {
res := make(URIHeaders, len(headers))
for k, v := range headers {
res[k] = v
}
return res
}
func (headers URIHeaders) Append(b *bytes.Buffer) {
if headers != nil && len(headers) > 0 {
keys := make([]string, len(headers))
i := 0
for k, _ := range headers {
keys[i] = k
i++
}
sort.Strings(keys)
first := true
for _, k := range keys {
if first {
b.WriteByte('?')
first = false
} else {
b.WriteByte('&')
}
appendEscaped(b, []byte(k), headerc)
v := headers[k]
if v != "" {
b.WriteByte('=')
appendEscaped(b, []byte(v), headerc)
}
}
}
}

+ 83
- 163
sip/uri_parse.go View File

@ -49,7 +49,7 @@ func ParseURIBytes(data []byte) (uri *URI, err error) {
var hex byte var hex byte
//line uri_parse.rl:171
//line uri_parse.rl:165
@ -58,7 +58,7 @@ func ParseURIBytes(data []byte) (uri *URI, err error) {
cs = uri_start cs = uri_start
} }
//line uri_parse.rl:174
//line uri_parse.rl:168
if bytes.IndexByte(data, '@') == -1 { if bytes.IndexByte(data, '@') == -1 {
cs = uri_en_uriSansUser; cs = uri_en_uriSansUser;
} else { } else {
@ -723,10 +723,7 @@ tr74:
//line uri_parse.rl:113 //line uri_parse.rl:113
if uri.Params == nil {
uri.Params = Params{}
}
uri.Params[b1] = b2
uri.Param = &URIParam{b1, b2, uri.Param}
goto st13 goto st13
tr79: tr79:
@ -737,10 +734,7 @@ tr79:
//line uri_parse.rl:113 //line uri_parse.rl:113
if uri.Params == nil {
uri.Params = Params{}
}
uri.Params[b1] = b2
uri.Param = &URIParam{b1, b2, uri.Param}
goto st13 goto st13
st13: st13:
@ -748,7 +742,7 @@ tr79:
goto _test_eof13 goto _test_eof13
} }
st_case_13: st_case_13:
//line uri_parse.go:752
//line uri_parse.go:746
switch data[p] { switch data[p] {
case 33: case 33:
goto tr22 goto tr22
@ -780,13 +774,9 @@ tr79:
} }
goto st0 goto st0
tr72: tr72:
//line uri_parse.rl:104
//line uri_parse.rl:51
if 'A' <= data[p] && data[p] <= 'Z' {
buf[amt] = data[p] + 0x20
} else {
buf[amt] = data[p]
}
buf[amt] = data[p]
amt++ amt++
goto st47 goto st47
@ -808,13 +798,9 @@ tr22:
b2 = string(buf[0:amt]) b2 = string(buf[0:amt])
amt = 0 amt = 0
//line uri_parse.rl:104
//line uri_parse.rl:51
if 'A' <= data[p] && data[p] <= 'Z' {
buf[amt] = data[p] + 0x20
} else {
buf[amt] = data[p]
}
buf[amt] = data[p]
amt++ amt++
goto st47 goto st47
@ -823,7 +809,7 @@ tr22:
goto _test_eof47 goto _test_eof47
} }
st_case_47: st_case_47:
//line uri_parse.go:827
//line uri_parse.go:813
switch data[p] { switch data[p] {
case 33: case 33:
goto tr72 goto tr72
@ -876,7 +862,7 @@ tr23:
goto _test_eof14 goto _test_eof14
} }
st_case_14: st_case_14:
//line uri_parse.go:880
//line uri_parse.go:866
switch { switch {
case data[p] < 65: case data[p] < 65:
if 48 <= data[p] && data[p] <= 57 { if 48 <= data[p] && data[p] <= 57 {
@ -901,7 +887,7 @@ tr24:
goto _test_eof15 goto _test_eof15
} }
st_case_15: st_case_15:
//line uri_parse.go:905
//line uri_parse.go:891
switch { switch {
case data[p] < 65: case data[p] < 65:
if 48 <= data[p] && data[p] <= 57 { if 48 <= data[p] && data[p] <= 57 {
@ -927,7 +913,7 @@ tr75:
goto _test_eof16 goto _test_eof16
} }
st_case_16: st_case_16:
//line uri_parse.go:931
//line uri_parse.go:917
switch data[p] { switch data[p] {
case 33: case 33:
goto tr26 goto tr26
@ -963,24 +949,16 @@ tr26:
amt = 0 amt = 0
//line uri_parse.rl:104
//line uri_parse.rl:51
if 'A' <= data[p] && data[p] <= 'Z' {
buf[amt] = data[p] + 0x20
} else {
buf[amt] = data[p]
}
buf[amt] = data[p]
amt++ amt++
goto st48 goto st48
tr77: tr77:
//line uri_parse.rl:104
//line uri_parse.rl:51
if 'A' <= data[p] && data[p] <= 'Z' {
buf[amt] = data[p] + 0x20
} else {
buf[amt] = data[p]
}
buf[amt] = data[p]
amt++ amt++
goto st48 goto st48
@ -997,7 +975,7 @@ tr29:
goto _test_eof48 goto _test_eof48
} }
st_case_48: st_case_48:
//line uri_parse.go:1001
//line uri_parse.go:979
switch data[p] { switch data[p] {
case 33: case 33:
goto tr77 goto tr77
@ -1043,7 +1021,7 @@ tr27:
goto _test_eof17 goto _test_eof17
} }
st_case_17: st_case_17:
//line uri_parse.go:1047
//line uri_parse.go:1025
switch { switch {
case data[p] < 65: case data[p] < 65:
if 48 <= data[p] && data[p] <= 57 { if 48 <= data[p] && data[p] <= 57 {
@ -1068,7 +1046,7 @@ tr28:
goto _test_eof18 goto _test_eof18
} }
st_case_18: st_case_18:
//line uri_parse.go:1072
//line uri_parse.go:1050
switch { switch {
case data[p] < 65: case data[p] < 65:
if 48 <= data[p] && data[p] <= 57 { if 48 <= data[p] && data[p] <= 57 {
@ -1096,10 +1074,7 @@ tr76:
//line uri_parse.rl:113 //line uri_parse.rl:113
if uri.Params == nil {
uri.Params = Params{}
}
uri.Params[b1] = b2
uri.Param = &URIParam{b1, b2, uri.Param}
goto st19 goto st19
tr80: tr80:
@ -1110,10 +1085,7 @@ tr80:
//line uri_parse.rl:113 //line uri_parse.rl:113
if uri.Params == nil {
uri.Params = Params{}
}
uri.Params[b1] = b2
uri.Param = &URIParam{b1, b2, uri.Param}
goto st19 goto st19
tr83: tr83:
@ -1122,12 +1094,9 @@ tr83:
b1 = string(buf[0:amt]) b1 = string(buf[0:amt])
amt = 0 amt = 0
//line uri_parse.rl:120
//line uri_parse.rl:117
if uri.Headers == nil {
uri.Headers = URIHeaders{}
}
uri.Headers[b1] = b2
uri.Header = &URIHeader{b1, b2, uri.Header}
goto st19 goto st19
tr87: tr87:
@ -1136,12 +1105,9 @@ tr87:
b2 = string(buf[0:amt]) b2 = string(buf[0:amt])
amt = 0 amt = 0
//line uri_parse.rl:120
//line uri_parse.rl:117
if uri.Headers == nil {
uri.Headers = URIHeaders{}
}
uri.Headers[b1] = b2
uri.Header = &URIHeader{b1, b2, uri.Header}
goto st19 goto st19
st19: st19:
@ -1149,7 +1115,7 @@ tr87:
goto _test_eof19 goto _test_eof19
} }
st_case_19: st_case_19:
//line uri_parse.go:1153
//line uri_parse.go:1119
switch data[p] { switch data[p] {
case 33: case 33:
goto tr30 goto tr30
@ -1220,7 +1186,7 @@ tr30:
goto _test_eof49 goto _test_eof49
} }
st_case_49: st_case_49:
//line uri_parse.go:1224
//line uri_parse.go:1190
switch data[p] { switch data[p] {
case 33: case 33:
goto tr81 goto tr81
@ -1273,7 +1239,7 @@ tr31:
goto _test_eof20 goto _test_eof20
} }
st_case_20: st_case_20:
//line uri_parse.go:1277
//line uri_parse.go:1243
switch { switch {
case data[p] < 65: case data[p] < 65:
if 48 <= data[p] && data[p] <= 57 { if 48 <= data[p] && data[p] <= 57 {
@ -1298,7 +1264,7 @@ tr32:
goto _test_eof21 goto _test_eof21
} }
st_case_21: st_case_21:
//line uri_parse.go:1302
//line uri_parse.go:1268
switch { switch {
case data[p] < 65: case data[p] < 65:
if 48 <= data[p] && data[p] <= 57 { if 48 <= data[p] && data[p] <= 57 {
@ -1324,7 +1290,7 @@ tr84:
goto _test_eof22 goto _test_eof22
} }
st_case_22: st_case_22:
//line uri_parse.go:1328
//line uri_parse.go:1294
switch data[p] { switch data[p] {
case 33: case 33:
goto tr34 goto tr34
@ -1390,7 +1356,7 @@ tr37:
goto _test_eof50 goto _test_eof50
} }
st_case_50: st_case_50:
//line uri_parse.go:1394
//line uri_parse.go:1360
switch data[p] { switch data[p] {
case 33: case 33:
goto tr85 goto tr85
@ -1436,7 +1402,7 @@ tr35:
goto _test_eof23 goto _test_eof23
} }
st_case_23: st_case_23:
//line uri_parse.go:1440
//line uri_parse.go:1406
switch { switch {
case data[p] < 65: case data[p] < 65:
if 48 <= data[p] && data[p] <= 57 { if 48 <= data[p] && data[p] <= 57 {
@ -1461,7 +1427,7 @@ tr36:
goto _test_eof24 goto _test_eof24
} }
st_case_24: st_case_24:
//line uri_parse.go:1465
//line uri_parse.go:1431
switch { switch {
case data[p] < 65: case data[p] < 65:
if 48 <= data[p] && data[p] <= 57 { if 48 <= data[p] && data[p] <= 57 {
@ -1527,7 +1493,7 @@ tr39:
goto _test_eof26 goto _test_eof26
} }
st_case_26: st_case_26:
//line uri_parse.go:1531
//line uri_parse.go:1497
switch data[p] { switch data[p] {
case 46: case 46:
goto tr39 goto tr39
@ -1558,7 +1524,7 @@ tr40:
goto _test_eof51 goto _test_eof51
} }
st_case_51: st_case_51:
//line uri_parse.go:1562
//line uri_parse.go:1528
switch data[p] { switch data[p] {
case 58: case 58:
goto st12 goto st12
@ -1609,7 +1575,7 @@ tr42:
goto _test_eof28 goto _test_eof28
} }
st_case_28: st_case_28:
//line uri_parse.go:1613
//line uri_parse.go:1579
switch data[p] { switch data[p] {
case 43: case 43:
goto tr42 goto tr42
@ -1645,7 +1611,7 @@ tr43:
goto _test_eof29 goto _test_eof29
} }
st_case_29: st_case_29:
//line uri_parse.go:1649
//line uri_parse.go:1615
switch data[p] { switch data[p] {
case 43: case 43:
goto tr44 goto tr44
@ -1701,7 +1667,7 @@ tr89:
goto _test_eof52 goto _test_eof52
} }
st_case_52: st_case_52:
//line uri_parse.go:1705
//line uri_parse.go:1671
switch data[p] { switch data[p] {
case 43: case 43:
goto tr89 goto tr89
@ -1741,7 +1707,7 @@ tr90:
goto _test_eof30 goto _test_eof30
} }
st_case_30: st_case_30:
//line uri_parse.go:1745
//line uri_parse.go:1711
if 48 <= data[p] && data[p] <= 57 { if 48 <= data[p] && data[p] <= 57 {
goto tr46 goto tr46
} }
@ -1757,7 +1723,7 @@ tr46:
goto _test_eof53 goto _test_eof53
} }
st_case_53: st_case_53:
//line uri_parse.go:1761
//line uri_parse.go:1727
switch data[p] { switch data[p] {
case 59: case 59:
goto st31 goto st31
@ -1782,10 +1748,7 @@ tr97:
//line uri_parse.rl:113 //line uri_parse.rl:113
if uri.Params == nil {
uri.Params = Params{}
}
uri.Params[b1] = b2
uri.Param = &URIParam{b1, b2, uri.Param}
goto st31 goto st31
tr102: tr102:
@ -1796,10 +1759,7 @@ tr102:
//line uri_parse.rl:113 //line uri_parse.rl:113
if uri.Params == nil {
uri.Params = Params{}
}
uri.Params[b1] = b2
uri.Param = &URIParam{b1, b2, uri.Param}
goto st31 goto st31
st31: st31:
@ -1807,7 +1767,7 @@ tr102:
goto _test_eof31 goto _test_eof31
} }
st_case_31: st_case_31:
//line uri_parse.go:1811
//line uri_parse.go:1771
switch data[p] { switch data[p] {
case 33: case 33:
goto tr47 goto tr47
@ -1839,13 +1799,9 @@ tr102:
} }
goto st0 goto st0
tr95: tr95:
//line uri_parse.rl:104
//line uri_parse.rl:51
if 'A' <= data[p] && data[p] <= 'Z' {
buf[amt] = data[p] + 0x20
} else {
buf[amt] = data[p]
}
buf[amt] = data[p]
amt++ amt++
goto st54 goto st54
@ -1867,13 +1823,9 @@ tr47:
b2 = string(buf[0:amt]) b2 = string(buf[0:amt])
amt = 0 amt = 0
//line uri_parse.rl:104
//line uri_parse.rl:51
if 'A' <= data[p] && data[p] <= 'Z' {
buf[amt] = data[p] + 0x20
} else {
buf[amt] = data[p]
}
buf[amt] = data[p]
amt++ amt++
goto st54 goto st54
@ -1882,7 +1834,7 @@ tr47:
goto _test_eof54 goto _test_eof54
} }
st_case_54: st_case_54:
//line uri_parse.go:1886
//line uri_parse.go:1838
switch data[p] { switch data[p] {
case 33: case 33:
goto tr95 goto tr95
@ -1935,7 +1887,7 @@ tr48:
goto _test_eof32 goto _test_eof32
} }
st_case_32: st_case_32:
//line uri_parse.go:1939
//line uri_parse.go:1891
switch { switch {
case data[p] < 65: case data[p] < 65:
if 48 <= data[p] && data[p] <= 57 { if 48 <= data[p] && data[p] <= 57 {
@ -1960,7 +1912,7 @@ tr49:
goto _test_eof33 goto _test_eof33
} }
st_case_33: st_case_33:
//line uri_parse.go:1964
//line uri_parse.go:1916
switch { switch {
case data[p] < 65: case data[p] < 65:
if 48 <= data[p] && data[p] <= 57 { if 48 <= data[p] && data[p] <= 57 {
@ -1986,7 +1938,7 @@ tr98:
goto _test_eof34 goto _test_eof34
} }
st_case_34: st_case_34:
//line uri_parse.go:1990
//line uri_parse.go:1942
switch data[p] { switch data[p] {
case 33: case 33:
goto tr51 goto tr51
@ -2022,24 +1974,16 @@ tr51:
amt = 0 amt = 0
//line uri_parse.rl:104
//line uri_parse.rl:51
if 'A' <= data[p] && data[p] <= 'Z' {
buf[amt] = data[p] + 0x20
} else {
buf[amt] = data[p]
}
buf[amt] = data[p]
amt++ amt++
goto st55 goto st55
tr100: tr100:
//line uri_parse.rl:104
//line uri_parse.rl:51
if 'A' <= data[p] && data[p] <= 'Z' {
buf[amt] = data[p] + 0x20
} else {
buf[amt] = data[p]
}
buf[amt] = data[p]
amt++ amt++
goto st55 goto st55
@ -2056,7 +2000,7 @@ tr54:
goto _test_eof55 goto _test_eof55
} }
st_case_55: st_case_55:
//line uri_parse.go:2060
//line uri_parse.go:2004
switch data[p] { switch data[p] {
case 33: case 33:
goto tr100 goto tr100
@ -2102,7 +2046,7 @@ tr52:
goto _test_eof35 goto _test_eof35
} }
st_case_35: st_case_35:
//line uri_parse.go:2106
//line uri_parse.go:2050
switch { switch {
case data[p] < 65: case data[p] < 65:
if 48 <= data[p] && data[p] <= 57 { if 48 <= data[p] && data[p] <= 57 {
@ -2127,7 +2071,7 @@ tr53:
goto _test_eof36 goto _test_eof36
} }
st_case_36: st_case_36:
//line uri_parse.go:2131
//line uri_parse.go:2075
switch { switch {
case data[p] < 65: case data[p] < 65:
if 48 <= data[p] && data[p] <= 57 { if 48 <= data[p] && data[p] <= 57 {
@ -2155,10 +2099,7 @@ tr99:
//line uri_parse.rl:113 //line uri_parse.rl:113
if uri.Params == nil {
uri.Params = Params{}
}
uri.Params[b1] = b2
uri.Param = &URIParam{b1, b2, uri.Param}
goto st37 goto st37
tr103: tr103:
@ -2169,10 +2110,7 @@ tr103:
//line uri_parse.rl:113 //line uri_parse.rl:113
if uri.Params == nil {
uri.Params = Params{}
}
uri.Params[b1] = b2
uri.Param = &URIParam{b1, b2, uri.Param}
goto st37 goto st37
tr106: tr106:
@ -2181,12 +2119,9 @@ tr106:
b1 = string(buf[0:amt]) b1 = string(buf[0:amt])
amt = 0 amt = 0
//line uri_parse.rl:120
//line uri_parse.rl:117
if uri.Headers == nil {
uri.Headers = URIHeaders{}
}
uri.Headers[b1] = b2
uri.Header = &URIHeader{b1, b2, uri.Header}
goto st37 goto st37
tr110: tr110:
@ -2195,12 +2130,9 @@ tr110:
b2 = string(buf[0:amt]) b2 = string(buf[0:amt])
amt = 0 amt = 0
//line uri_parse.rl:120
//line uri_parse.rl:117
if uri.Headers == nil {
uri.Headers = URIHeaders{}
}
uri.Headers[b1] = b2
uri.Header = &URIHeader{b1, b2, uri.Header}
goto st37 goto st37
st37: st37:
@ -2208,7 +2140,7 @@ tr110:
goto _test_eof37 goto _test_eof37
} }
st_case_37: st_case_37:
//line uri_parse.go:2212
//line uri_parse.go:2144
switch data[p] { switch data[p] {
case 33: case 33:
goto tr55 goto tr55
@ -2279,7 +2211,7 @@ tr55:
goto _test_eof56 goto _test_eof56
} }
st_case_56: st_case_56:
//line uri_parse.go:2283
//line uri_parse.go:2215
switch data[p] { switch data[p] {
case 33: case 33:
goto tr104 goto tr104
@ -2332,7 +2264,7 @@ tr56:
goto _test_eof38 goto _test_eof38
} }
st_case_38: st_case_38:
//line uri_parse.go:2336
//line uri_parse.go:2268
switch { switch {
case data[p] < 65: case data[p] < 65:
if 48 <= data[p] && data[p] <= 57 { if 48 <= data[p] && data[p] <= 57 {
@ -2357,7 +2289,7 @@ tr57:
goto _test_eof39 goto _test_eof39
} }
st_case_39: st_case_39:
//line uri_parse.go:2361
//line uri_parse.go:2293
switch { switch {
case data[p] < 65: case data[p] < 65:
if 48 <= data[p] && data[p] <= 57 { if 48 <= data[p] && data[p] <= 57 {
@ -2383,7 +2315,7 @@ tr107:
goto _test_eof40 goto _test_eof40
} }
st_case_40: st_case_40:
//line uri_parse.go:2387
//line uri_parse.go:2319
switch data[p] { switch data[p] {
case 33: case 33:
goto tr59 goto tr59
@ -2449,7 +2381,7 @@ tr62:
goto _test_eof57 goto _test_eof57
} }
st_case_57: st_case_57:
//line uri_parse.go:2453
//line uri_parse.go:2385
switch data[p] { switch data[p] {
case 33: case 33:
goto tr108 goto tr108
@ -2495,7 +2427,7 @@ tr60:
goto _test_eof41 goto _test_eof41
} }
st_case_41: st_case_41:
//line uri_parse.go:2499
//line uri_parse.go:2431
switch { switch {
case data[p] < 65: case data[p] < 65:
if 48 <= data[p] && data[p] <= 57 { if 48 <= data[p] && data[p] <= 57 {
@ -2520,7 +2452,7 @@ tr61:
goto _test_eof42 goto _test_eof42
} }
st_case_42: st_case_42:
//line uri_parse.go:2524
//line uri_parse.go:2456
switch { switch {
case data[p] < 65: case data[p] < 65:
if 48 <= data[p] && data[p] <= 57 { if 48 <= data[p] && data[p] <= 57 {
@ -2586,7 +2518,7 @@ tr64:
goto _test_eof44 goto _test_eof44
} }
st_case_44: st_case_44:
//line uri_parse.go:2590
//line uri_parse.go:2522
switch data[p] { switch data[p] {
case 46: case 46:
goto tr64 goto tr64
@ -2617,7 +2549,7 @@ tr65:
goto _test_eof58 goto _test_eof58
} }
st_case_58: st_case_58:
//line uri_parse.go:2621
//line uri_parse.go:2553
switch data[p] { switch data[p] {
case 58: case 58:
goto st30 goto st30
@ -2701,10 +2633,7 @@ tr65:
//line uri_parse.rl:113 //line uri_parse.rl:113
if uri.Params == nil {
uri.Params = Params{}
}
uri.Params[b1] = b2
uri.Param = &URIParam{b1, b2, uri.Param}
case 49, 56: case 49, 56:
//line uri_parse.rl:94 //line uri_parse.rl:94
@ -2712,12 +2641,9 @@ tr65:
b1 = string(buf[0:amt]) b1 = string(buf[0:amt])
amt = 0 amt = 0
//line uri_parse.rl:120
//line uri_parse.rl:117
if uri.Headers == nil {
uri.Headers = URIHeaders{}
}
uri.Headers[b1] = b2
uri.Header = &URIHeader{b1, b2, uri.Header}
case 48, 55: case 48, 55:
//line uri_parse.rl:99 //line uri_parse.rl:99
@ -2727,10 +2653,7 @@ tr65:
//line uri_parse.rl:113 //line uri_parse.rl:113
if uri.Params == nil {
uri.Params = Params{}
}
uri.Params[b1] = b2
uri.Param = &URIParam{b1, b2, uri.Param}
case 50, 57: case 50, 57:
//line uri_parse.rl:99 //line uri_parse.rl:99
@ -2738,21 +2661,18 @@ tr65:
b2 = string(buf[0:amt]) b2 = string(buf[0:amt])
amt = 0 amt = 0
//line uri_parse.rl:120
//line uri_parse.rl:117
if uri.Headers == nil {
uri.Headers = URIHeaders{}
}
uri.Headers[b1] = b2
uri.Header = &URIHeader{b1, b2, uri.Header}
//line uri_parse.go:2749
//line uri_parse.go:2669
} }
} }
_out: {} _out: {}
} }
//line uri_parse.rl:180
//line uri_parse.rl:174
if cs < uri_first_final { if cs < uri_first_final {
if p == pe { if p == pe {


+ 2
- 8
sip/uri_parse.rl View File

@ -111,17 +111,11 @@ func ParseURIBytes(data []byte) (uri *URI, err error) {
} }
action param { action param {
if uri.Params == nil {
uri.Params = Params{}
}
uri.Params[b1] = b2
uri.Param = &URIParam{b1, b2, uri.Param}
} }
action header { action header {
if uri.Headers == nil {
uri.Headers = URIHeaders{}
}
uri.Headers[b1] = b2
uri.Header = &URIHeader{b1, b2, uri.Header}
} }
# Byte character definitions. # Byte character definitions.


+ 6
- 17
sip/uri_test.go View File

@ -127,9 +127,7 @@ var uriTests = []uriTest{
Pass: "priceisright", Pass: "priceisright",
Host: "dead:beef::666", Host: "dead:beef::666",
Port: 5060, Port: 5060,
Params: sip.Params{
"isup-oli": "00",
},
Param: &sip.URIParam{"isup-oli", "00", nil},
}, },
}, },
@ -153,10 +151,7 @@ var uriTests = []uriTest{
Scheme: "sips", Scheme: "sips",
User: "alice", User: "alice",
Host: "atlanta.com", Host: "atlanta.com",
Headers: sip.URIHeaders{
"subject": "project x",
"priority": "urgent",
},
Header: &sip.URIHeader{"subject", "project x", &sip.URIHeader{"priority", "urgent", nil}},
}, },
}, },
@ -167,9 +162,7 @@ var uriTests = []uriTest{
User: "+1-212-555-1212", User: "+1-212-555-1212",
Pass: "1234", Pass: "1234",
Host: "gateway.com", Host: "gateway.com",
Params: sip.Params{
"user": "phone",
},
Param: &sip.URIParam{"user", "phone", nil},
}, },
}, },
@ -178,12 +171,8 @@ var uriTests = []uriTest{
uri: &sip.URI{ uri: &sip.URI{
Scheme: "sip", Scheme: "sip",
Host: "atlanta.com", Host: "atlanta.com",
Params: sip.Params{
"method": "register",
},
Headers: sip.URIHeaders{
"to": "alice@atlanta.com",
},
Param: &sip.URIParam{"method", "register", nil},
Header: &sip.URIHeader{"to", "alice@atlanta.com", nil},
}, },
}, },
@ -220,7 +209,7 @@ func TestFormatURI(t *testing.T) {
} }
uri := test.uri.String() uri := test.uri.String()
if test.s != uri { if test.s != uri {
t.Error(test.s, "!=", uri)
t.Errorf("\n%s !=\n%s", test.s, uri)
} }
} }
} }

+ 44
- 0
sip/uriheader.go View File

@ -0,0 +1,44 @@
// URI Header Library
package sip
import (
"bytes"
"strings"
)
// URIHeader is a linked list of ?key=values for URI headers.
type URIHeader struct {
Name string
Value string
Next *URIHeader
}
// Get returns an entry in O(n) time.
func (p *URIHeader) Get(name string) *URIHeader {
if p == nil {
return nil
}
if strings.EqualFold(p.Name, name) {
return p
}
return p.Next.Get(name)
}
// Append serializes URI headers in insertion order.
func (p *URIHeader) Append(b *bytes.Buffer) {
if p == nil {
return
}
if p.Next != nil {
p.Next.Append(b)
b.WriteByte('&')
} else {
b.WriteByte('?')
}
appendEscaped(b, []byte(p.Name), paramc)
if p.Value != "" {
b.WriteByte('=')
appendEscaped(b, []byte(p.Value), paramc)
}
}

+ 40
- 0
sip/uriparam.go View File

@ -0,0 +1,40 @@
// URI Parameter Library
package sip
import (
"bytes"
"strings"
)
// URIParam is a linked list of ;key=values for URI parameters.
type URIParam struct {
Name string
Value string
Next *URIParam
}
// Get returns an entry in O(n) time.
func (p *URIParam) Get(name string) *URIParam {
if p == nil {
return nil
}
if strings.EqualFold(p.Name, name) {
return p
}
return p.Next.Get(name)
}
// Append serializes URI parameters in insertion order.
func (p *URIParam) Append(b *bytes.Buffer) {
if p == nil {
return
}
p.Next.Append(b)
b.WriteByte(';')
appendEscaped(b, []byte(p.Name), paramc)
if p.Value != "" {
b.WriteByte('=')
appendEscaped(b, []byte(p.Value), paramc)
}
}

+ 8
- 8
sip/via.go View File

@ -21,7 +21,7 @@ type Via struct {
Transport string // transport type "UDP" Transport string // transport type "UDP"
Host string // name or ip of egress interface Host string // name or ip of egress interface
Port uint16 // network port number Port uint16 // network port number
Params Params // params like branch, received, rport, etc.
Param *Param // param like branch, received, rport, etc.
Next *Via // pointer to next via header if any Next *Via // pointer to next via header if any
} }
@ -52,7 +52,7 @@ func (via *Via) Append(b *bytes.Buffer) error {
b.WriteString(":") b.WriteString(":")
b.WriteString(strconv.Itoa(int(via.Port))) b.WriteString(strconv.Itoa(int(via.Port)))
} }
via.Params.Append(b)
via.Param.Append(b)
return nil return nil
} }
@ -67,14 +67,14 @@ func (via *Via) Copy() *Via {
res.Transport = via.Transport res.Transport = via.Transport
res.Host = via.Host res.Host = via.Host
res.Port = via.Port res.Port = via.Port
res.Params = via.Params.Copy()
res.Param = via.Param
res.Next = via.Next.Copy() res.Next = via.Next.Copy()
return res return res
} }
// Branch mutates via with a newly generated branch ID.
// Branch adds a randomly generated branch ID.
func (via *Via) Branch() *Via { func (via *Via) Branch() *Via {
via.Params["branch"] = util.GenerateBranch()
via.Param = &Param{"branch", util.GenerateBranch(), via.Param}
return via return via
} }
@ -107,9 +107,9 @@ func (via *Via) CompareHostPort(other *Via) bool {
func (via *Via) CompareBranch(other *Via) bool { func (via *Via) CompareBranch(other *Via) bool {
if via != nil && other != nil { if via != nil && other != nil {
if b1, ok := via.Params["branch"]; ok {
if b2, ok := other.Params["branch"]; ok {
if b1 == b2 {
if b1 := via.Param.Get("branch"); b1 != nil {
if b2 := other.Param.Get("branch"); b2 != nil {
if b1.Value == b2.Value {
return true return true
} }
} }


Loading…
Cancel
Save