Browse Source

Use linked list for extended headers.

pull/2/head
Justine Alexandra Roberts Tunney 11 years ago
parent
commit
1c5167641a
5 changed files with 321 additions and 272 deletions
  1. +3
    -15
      sip/msg.go
  2. +218
    -221
      sip/msg_parse.go
  3. +54
    -32
      sip/msg_test.go
  4. +1
    -4
      sip/sip.rl
  5. +45
    -0
      sip/xheader.go

+ 3
- 15
sip/msg.go View File

@ -8,8 +8,6 @@ import (
"strconv"
)
type Headers map[string]string
// Msg represents a SIP message. This can either be a request or a response.
// These fields are never nil unless otherwise specified.
type Msg struct {
@ -84,7 +82,7 @@ type Msg struct {
Warning []byte
// Extension headers.
Headers Headers
XHeader *XHeader
}
//go:generate ragel -Z -G2 -o msg_parse.go msg_parse.rl
@ -114,10 +112,7 @@ func (msg *Msg) Copy() *Msg {
res.Route = msg.Route.Copy()
res.Contact = msg.Contact.Copy()
res.RecordRoute = msg.RecordRoute.Copy()
res.Headers = make(Headers, len(msg.Headers))
for k, v := range msg.Headers {
res.Headers[k] = v
}
res.XHeader = msg.XHeader
return res
}
@ -442,14 +437,7 @@ func (msg *Msg) Append(b *bytes.Buffer) {
b.WriteString("\r\n")
}
if msg.Headers != nil {
for k, v := range msg.Headers {
b.WriteString(k)
b.WriteString(": ")
b.WriteString(v)
b.WriteString("\r\n")
}
}
msg.XHeader.Append(b)
if msg.Payload != nil {
b.WriteString("Content-Type: ")


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


+ 54
- 32
sip/msg_test.go View File

@ -48,9 +48,7 @@ var msgTests = []msgTest{
VersionMajor: 2,
Status: 200,
Phrase: "OK",
Headers: sip.Headers{
"X-LOL": "omfg",
},
XHeader: &sip.XHeader{"X-LOL", []byte("omfg"), nil},
},
},
@ -122,9 +120,7 @@ var msgTests = []msgTest{
" Come buy, come buy:\r\n" +
" Apples and quinces,\r\n" +
" Lemons and oranges"),
Headers: sip.Headers{
"X-LOL": "omfg",
},
XHeader: &sip.XHeader{"X-LOL", []byte("omfg"), nil},
},
},
@ -139,10 +135,14 @@ var msgTests = []msgTest{
VersionMajor: 2,
Status: 200,
Phrase: "OK",
Headers: sip.Headers{
"X-Warning": "Come buy our orchard fruits,\r\n" +
" Come buy, come buy",
"X-LOL": "omfg",
XHeader: &sip.XHeader{
Name: "X-LOL",
Value: []byte("omfg"),
Next: &sip.XHeader{
Name: "X-Warning",
Value: []byte("Come buy our orchard fruits,\r\n" +
" Come buy, come buy"),
},
},
},
},
@ -158,10 +158,14 @@ var msgTests = []msgTest{
VersionMajor: 2,
Status: 200,
Phrase: "OK",
Headers: sip.Headers{
"NewFangledHeader": "newfangled value\r\n" +
" continued newfangled value",
"UnknownHeaderWithUnusualValue": ";;,,;;,;",
XHeader: &sip.XHeader{
Name: "UnknownHeaderWithUnusualValue",
Value: []byte(";;,,;;,;"),
Next: &sip.XHeader{
Name: "NewFangledHeader",
Value: []byte("newfangled value\r\n" +
" continued newfangled value"),
},
},
},
},
@ -195,22 +199,35 @@ var msgTests = []msgTest{
msgTest{
name: "Extended header looks like standard headers",
s: "SIP/2.0 200 OK\r\n" +
"Proxy-LOL: take\r\n" +
"CSeq2: back\r\n" +
"Contazt: the\r\n" +
"P-Asserted-LOL: dance\r\n" +
"viaz: floor\r\n" +
"P-Asserted-LOL: dance\r\n" +
"Contazt: the\r\n" +
"CSeq2: back\r\n" +
"Proxy-LOL: take\r\n" +
"\r\n",
msg: sip.Msg{
VersionMajor: 2,
Status: 200,
Phrase: "OK",
Headers: sip.Headers{
"Proxy-LOL": "take",
"CSeq2": "back",
"Contazt": "the",
"P-Asserted-LOL": "dance",
"viaz": "floor",
XHeader: &sip.XHeader{
Name: "Proxy-LOL",
Value: []byte("take"),
Next: &sip.XHeader{
Name: "CSeq2",
Value: []byte("back"),
Next: &sip.XHeader{
Name: "Contazt",
Value: []byte("the"),
Next: &sip.XHeader{
Name: "P-Asserted-LOL",
Value: []byte("dance"),
Next: &sip.XHeader{
Name: "viaz",
Value: []byte("floor"),
},
},
},
},
},
},
},
@ -1059,10 +1076,14 @@ var msgTests = []msgTest{
},
},
},
Headers: sip.Headers{
"NewFangledHeader": "newfangled value\r\n" +
" continued newfangled value",
"UnknownHeaderWithUnusualValue": ";;,,;;,;",
XHeader: &sip.XHeader{
Name: "UnknownHeaderWithUnusualValue",
Value: []byte(";;,,;;,;"),
Next: &sip.XHeader{
Name: "NewFangledHeader",
Value: []byte("newfangled value\r\n" +
" continued newfangled value"),
},
},
Route: &sip.Addr{
Uri: &sip.URI{
@ -1172,8 +1193,9 @@ var msgTests = []msgTest{
},
},
},
Headers: sip.Headers{
"extensionHeader-!.%*+_`'~": "\xEF\xBB\xBF\xE5\xA4\xA7\xE5\x81\x9C\xE9\x9B\xBB",
XHeader: &sip.XHeader{
Name: "extensionHeader-!.%*+_`'~",
Value: []byte("\xEF\xBB\xBF\xE5\xA4\xA7\xE5\x81\x9C\xE9\x9B\xBB"),
},
},
},
@ -1195,8 +1217,8 @@ func TestParseMsg(t *testing.T) {
if !reflect.DeepEqual(test.msg.Payload, msg.Payload) {
t.Errorf("Payload:\n%#v !=\n%#v", test.msg.Payload, msg.Payload)
}
if !reflect.DeepEqual(test.msg.Headers, msg.Headers) {
t.Errorf("Headers:\n%#v !=\n%#v", test.msg.Headers, msg.Headers)
if test.msg.XHeader.String() != msg.XHeader.String() {
t.Errorf("Headers:\n%s !=\n%s", test.msg.XHeader, msg.XHeader)
}
if !reflect.DeepEqual(test.msg.Via, msg.Via) {
t.Errorf("Via:\n%#v !=\n%#v", test.msg.Via, msg.Via)


+ 1
- 4
sip/sip.rl View File

@ -164,10 +164,7 @@ action value {{
if value != nil {
*value = b
} else {
if msg.Headers == nil {
msg.Headers = Headers{}
}
msg.Headers[name] = string(b)
msg.XHeader = &XHeader{name, b, msg.XHeader}
}
}}


+ 45
- 0
sip/xheader.go View File

@ -0,0 +1,45 @@
// Addr / Via Parameter Library
package sip
import (
"bytes"
"strings"
)
// XHeader is a linked list storing an unrecognized SIP headers.
type XHeader struct {
Name string // tokenc
Value []byte // UTF8, never nil
Next *XHeader
}
// Get returns an entry in O(n) time.
func (h *XHeader) Get(name string) *XHeader {
if h == nil {
return nil
}
if strings.EqualFold(h.Name, name) {
return h
}
return h.Next.Get(name)
}
// String turns XHeader into a string.
func (h *XHeader) String() string {
var b bytes.Buffer
h.Append(&b)
return b.String()
}
// Append serializes headers in insertion order.
func (h *XHeader) Append(b *bytes.Buffer) {
if h == nil {
return
}
h.Next.Append(b)
appendSanitized(b, []byte(h.Name), tokenc)
b.WriteString(": ")
b.Write(h.Value)
b.WriteString("\r\n")
}

Loading…
Cancel
Save