Skip to content

Commit ccc1bc9

Browse files
committed
feat: allow compact headers usage in client
1 parent 0a8ea0c commit ccc1bc9

File tree

2 files changed

+132
-26
lines changed

2 files changed

+132
-26
lines changed

sip/headers.go

Lines changed: 110 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ type Header interface {
2121

2222
// Next() Header
2323
headerClone() Header
24+
valueStringWrite(w io.StringWriter)
2425
}
2526

2627
// CopyHeader is internal interface for cloning headers.
@@ -50,6 +51,9 @@ type headers struct {
5051
route *RouteHeader
5152
recordRoute *RecordRouteHeader
5253
maxForwards *MaxForwardsHeader
54+
55+
// CompactHeaders
56+
CompactHeaders bool
5357
}
5458

5559
func (hs *headers) String() string {
@@ -59,11 +63,29 @@ func (hs *headers) String() string {
5963
}
6064

6165
func (hs *headers) StringWrite(buffer io.StringWriter) {
66+
if hs.CompactHeaders {
67+
for typeIdx, header := range hs.headerOrder {
68+
if typeIdx > 0 {
69+
buffer.WriteString("\r\n")
70+
}
71+
72+
// https://www.cs.columbia.edu/sip/compact.html
73+
name := header.Name()
74+
buffer.WriteString(compactHeaderName(name))
75+
buffer.WriteString(": ")
76+
header.valueStringWrite(buffer)
77+
}
78+
buffer.WriteString("\r\n")
79+
return
80+
}
81+
6282
for typeIdx, header := range hs.headerOrder {
6383
if typeIdx > 0 {
6484
buffer.WriteString("\r\n")
6585
}
66-
header.StringWrite(buffer)
86+
buffer.WriteString(header.Name())
87+
buffer.WriteString(": ")
88+
header.valueStringWrite(buffer)
6789
}
6890
buffer.WriteString("\r\n")
6991
}
@@ -454,6 +476,10 @@ func (h *genericHeader) StringWrite(buffer io.StringWriter) {
454476
buffer.WriteString(h.Value())
455477
}
456478

479+
func (h *genericHeader) valueStringWrite(buffer io.StringWriter) {
480+
buffer.WriteString(h.Value())
481+
}
482+
457483
func (h *genericHeader) Name() string {
458484
return h.HeaderName
459485
}
@@ -492,18 +518,18 @@ func (h *ToHeader) String() string {
492518
func (h *ToHeader) StringWrite(buffer io.StringWriter) {
493519
buffer.WriteString(h.Name())
494520
buffer.WriteString(": ")
495-
h.ValueStringWrite(buffer)
521+
h.valueStringWrite(buffer)
496522
}
497523

498524
func (h *ToHeader) Name() string { return "To" }
499525

500526
func (h *ToHeader) Value() string {
501527
var buffer strings.Builder
502-
h.ValueStringWrite(&buffer)
528+
h.valueStringWrite(&buffer)
503529
return buffer.String()
504530
}
505531

506-
func (h *ToHeader) ValueStringWrite(buffer io.StringWriter) {
532+
func (h *ToHeader) valueStringWrite(buffer io.StringWriter) {
507533
if h.DisplayName != "" {
508534
buffer.WriteString("\"")
509535
buffer.WriteString(h.DisplayName)
@@ -570,18 +596,18 @@ func (h *FromHeader) String() string {
570596
func (h *FromHeader) StringWrite(buffer io.StringWriter) {
571597
buffer.WriteString(h.Name())
572598
buffer.WriteString(": ")
573-
h.ValueStringWrite(buffer)
599+
h.valueStringWrite(buffer)
574600
}
575601

576602
func (h *FromHeader) Name() string { return "From" }
577603

578604
func (h *FromHeader) Value() string {
579605
var buffer strings.Builder
580-
h.ValueStringWrite(&buffer)
606+
h.valueStringWrite(&buffer)
581607
return buffer.String()
582608
}
583609

584-
func (h *FromHeader) ValueStringWrite(buffer io.StringWriter) {
610+
func (h *FromHeader) valueStringWrite(buffer io.StringWriter) {
585611
if h.DisplayName != "" {
586612
buffer.WriteString("\"")
587613
buffer.WriteString(h.DisplayName)
@@ -645,18 +671,18 @@ func (h *ContactHeader) String() string {
645671
func (h *ContactHeader) StringWrite(buffer io.StringWriter) {
646672
buffer.WriteString(h.Name())
647673
buffer.WriteString(": ")
648-
h.valueWrite(buffer)
674+
h.valueStringWrite(buffer)
649675
}
650676

651677
func (h *ContactHeader) Name() string { return "Contact" }
652678

653679
func (h *ContactHeader) Value() string {
654680
var buffer strings.Builder
655-
h.valueWrite(&buffer)
681+
h.valueStringWrite(&buffer)
656682
return buffer.String()
657683
}
658684

659-
func (h *ContactHeader) valueWrite(buffer io.StringWriter) {
685+
func (h *ContactHeader) valueStringWrite(buffer io.StringWriter) {
660686

661687
switch h.Address.Wildcard {
662688
case true:
@@ -722,6 +748,10 @@ func (h *CallIDHeader) StringWrite(buffer io.StringWriter) {
722748
buffer.WriteString(h.Value())
723749
}
724750

751+
func (h *CallIDHeader) valueStringWrite(buffer io.StringWriter) {
752+
buffer.WriteString(h.Value())
753+
}
754+
725755
func (h *CallIDHeader) Name() string { return "Call-ID" }
726756

727757
func (h *CallIDHeader) Value() string { return string(*h) }
@@ -745,7 +775,7 @@ func (h *CSeqHeader) String() string {
745775
func (h *CSeqHeader) StringWrite(buffer io.StringWriter) {
746776
buffer.WriteString(h.Name())
747777
buffer.WriteString(": ")
748-
h.ValueStringWrite(buffer)
778+
h.valueStringWrite(buffer)
749779
}
750780

751781
func (h *CSeqHeader) Name() string { return "CSeq" }
@@ -754,7 +784,7 @@ func (h *CSeqHeader) Value() string {
754784
return fmt.Sprintf("%d %s", h.SeqNo, h.MethodName)
755785
}
756786

757-
func (h *CSeqHeader) ValueStringWrite(buffer io.StringWriter) {
787+
func (h *CSeqHeader) valueStringWrite(buffer io.StringWriter) {
758788
buffer.WriteString(strconv.Itoa(int(h.SeqNo)))
759789
buffer.WriteString(" ")
760790
buffer.WriteString(string(h.MethodName))
@@ -787,6 +817,10 @@ func (h *MaxForwardsHeader) StringWrite(buffer io.StringWriter) {
787817
buffer.WriteString(h.Value())
788818
}
789819

820+
func (h *MaxForwardsHeader) valueStringWrite(buffer io.StringWriter) {
821+
buffer.WriteString(h.Value())
822+
}
823+
790824
func (h *MaxForwardsHeader) Name() string { return "Max-Forwards" }
791825

792826
func (h *MaxForwardsHeader) Value() string { return strconv.Itoa(int(*h)) }
@@ -814,6 +848,10 @@ func (h *ExpiresHeader) StringWrite(buffer io.StringWriter) {
814848
buffer.WriteString(h.Value())
815849
}
816850

851+
func (h *ExpiresHeader) valueStringWrite(buffer io.StringWriter) {
852+
buffer.WriteString(h.Value())
853+
}
854+
817855
func (h *ExpiresHeader) Name() string { return "Expires" }
818856

819857
func (h ExpiresHeader) Value() string { return strconv.Itoa(int(h)) }
@@ -835,6 +873,10 @@ func (h ContentLengthHeader) StringWrite(buffer io.StringWriter) {
835873
buffer.WriteString(h.Value())
836874
}
837875

876+
func (h *ContentLengthHeader) valueStringWrite(buffer io.StringWriter) {
877+
buffer.WriteString(h.Value())
878+
}
879+
838880
func (h *ContentLengthHeader) Name() string { return "Content-Length" }
839881

840882
func (h ContentLengthHeader) Value() string { return strconv.Itoa(int(h)) }
@@ -881,11 +923,11 @@ func (h *ViaHeader) Name() string { return "Via" }
881923

882924
func (h *ViaHeader) Value() string {
883925
var buffer strings.Builder
884-
h.ValueStringWrite(&buffer)
926+
h.valueStringWrite(&buffer)
885927
return buffer.String()
886928
}
887929

888-
func (h *ViaHeader) ValueStringWrite(buffer io.StringWriter) {
930+
func (h *ViaHeader) valueStringWrite(buffer io.StringWriter) {
889931
buffer.WriteString(h.ProtocolName)
890932
buffer.WriteString("/")
891933
buffer.WriteString(h.ProtocolVersion)
@@ -942,6 +984,10 @@ func (h *ContentTypeHeader) StringWrite(buffer io.StringWriter) {
942984
buffer.WriteString(h.Value())
943985
}
944986

987+
func (h *ContentTypeHeader) valueStringWrite(buffer io.StringWriter) {
988+
buffer.WriteString(h.Value())
989+
}
990+
945991
// func (h **ContentTypeHeader) Name() string { return "Content-Type" }
946992
func (h *ContentTypeHeader) Name() string { return "Content-Type" }
947993

@@ -958,11 +1004,11 @@ func (h *RouteHeader) Name() string { return "Route" }
9581004

9591005
func (h *RouteHeader) Value() string {
9601006
var buffer strings.Builder
961-
h.ValueStringWrite(&buffer)
1007+
h.valueStringWrite(&buffer)
9621008
return buffer.String()
9631009
}
9641010

965-
func (h *RouteHeader) ValueStringWrite(buffer io.StringWriter) {
1011+
func (h *RouteHeader) valueStringWrite(buffer io.StringWriter) {
9661012
buffer.WriteString("<")
9671013
h.Address.StringWrite(buffer)
9681014
buffer.WriteString(">")
@@ -977,7 +1023,7 @@ func (h *RouteHeader) String() string {
9771023
func (h *RouteHeader) StringWrite(buffer io.StringWriter) {
9781024
buffer.WriteString(h.Name())
9791025
buffer.WriteString(": ")
980-
h.ValueStringWrite(buffer)
1026+
h.valueStringWrite(buffer)
9811027
}
9821028

9831029
func (h *RouteHeader) headerClone() Header {
@@ -1000,11 +1046,11 @@ func (h *RecordRouteHeader) Name() string { return "Record-Route" }
10001046

10011047
func (h *RecordRouteHeader) Value() string {
10021048
var buffer strings.Builder
1003-
h.ValueStringWrite(&buffer)
1049+
h.valueStringWrite(&buffer)
10041050
return buffer.String()
10051051
}
10061052

1007-
func (h *RecordRouteHeader) ValueStringWrite(buffer io.StringWriter) {
1053+
func (h *RecordRouteHeader) valueStringWrite(buffer io.StringWriter) {
10081054
buffer.WriteString("<")
10091055
h.Address.StringWrite(buffer)
10101056
buffer.WriteString(">")
@@ -1019,7 +1065,7 @@ func (h *RecordRouteHeader) String() string {
10191065
func (h *RecordRouteHeader) StringWrite(buffer io.StringWriter) {
10201066
buffer.WriteString(h.Name())
10211067
buffer.WriteString(": ")
1022-
h.ValueStringWrite(buffer)
1068+
h.valueStringWrite(buffer)
10231069
}
10241070

10251071
func (h *RecordRouteHeader) headerClone() Header {
@@ -1042,11 +1088,11 @@ func (h *ReferToHeader) Name() string { return "Refer-To" }
10421088

10431089
func (h *ReferToHeader) Value() string {
10441090
var buffer strings.Builder
1045-
h.ValueStringWrite(&buffer)
1091+
h.valueStringWrite(&buffer)
10461092
return buffer.String()
10471093
}
10481094

1049-
func (h *ReferToHeader) ValueStringWrite(buffer io.StringWriter) {
1095+
func (h *ReferToHeader) valueStringWrite(buffer io.StringWriter) {
10501096
buffer.WriteString("<")
10511097
h.Address.StringWrite(buffer)
10521098
buffer.WriteString(">")
@@ -1061,7 +1107,7 @@ func (h *ReferToHeader) String() string {
10611107
func (h *ReferToHeader) StringWrite(buffer io.StringWriter) {
10621108
buffer.WriteString(h.Name())
10631109
buffer.WriteString(": ")
1064-
h.ValueStringWrite(buffer)
1110+
h.valueStringWrite(buffer)
10651111
}
10661112

10671113
func (h *ReferToHeader) headerClone() Header {
@@ -1086,11 +1132,11 @@ func (h *ReferredByHeader) Name() string { return "Referred-By" }
10861132

10871133
func (h *ReferredByHeader) Value() string {
10881134
var buffer strings.Builder
1089-
h.ValueStringWrite(&buffer)
1135+
h.valueStringWrite(&buffer)
10901136
return buffer.String()
10911137
}
10921138

1093-
func (h *ReferredByHeader) ValueStringWrite(buffer io.StringWriter) {
1139+
func (h *ReferredByHeader) valueStringWrite(buffer io.StringWriter) {
10941140
if h.DisplayName != "" {
10951141
buffer.WriteString("\"")
10961142
buffer.WriteString(h.DisplayName)
@@ -1116,7 +1162,7 @@ func (h *ReferredByHeader) String() string {
11161162
func (h *ReferredByHeader) StringWrite(buffer io.StringWriter) {
11171163
buffer.WriteString(h.Name())
11181164
buffer.WriteString(": ")
1119-
h.ValueStringWrite(buffer)
1165+
h.valueStringWrite(buffer)
11201166
}
11211167

11221168
func (h *ReferredByHeader) headerClone() Header {
@@ -1162,3 +1208,41 @@ func parseHeaderLazy[T any, HP headerPointerReceiver[T]](hs *headers, f func(hea
11621208
}
11631209
return false
11641210
}
1211+
1212+
func compactHeaderName(full string) string {
1213+
switch full {
1214+
case "Via":
1215+
return "v"
1216+
case "From":
1217+
return "f"
1218+
case "To":
1219+
return "t"
1220+
case "Call-ID":
1221+
return "i"
1222+
case "Content-Type":
1223+
return "c"
1224+
case "Content-Length":
1225+
return "l"
1226+
case "Contact":
1227+
return "m"
1228+
case "Refer-To":
1229+
return "r"
1230+
case "Content-Encoding":
1231+
return "e"
1232+
case "Accept-Contact":
1233+
return "a"
1234+
case "Referred-By":
1235+
return "b"
1236+
case "Supported":
1237+
return "k"
1238+
case "Event":
1239+
return "o"
1240+
case "Subject":
1241+
return "s"
1242+
case "Allow-Events":
1243+
return "u"
1244+
1245+
default:
1246+
return full
1247+
}
1248+
}

sip/headers_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package sip
22

33
import (
4+
"bytes"
5+
"strings"
46
"testing"
57

68
"github.com/stretchr/testify/assert"
@@ -105,3 +107,23 @@ func TestCopyHeaders(t *testing.T) {
105107
require.Equal(t, "Record-Route: <sip:p1:5060;lr;transport=udp>", hdrs[0].String())
106108
require.Equal(t, "Record-Route: <sip:p2:5060;lr>", hdrs[1].String())
107109
}
110+
111+
func TestHeaderSCompact(t *testing.T) {
112+
invite := testCreateMessage(t, []string{
113+
"INVITE sip:[email protected] SIP/2.0",
114+
"Via: SIP/2.0/udp test.com;branch=z9hG4bK.3h9TE5VD6tjax5YW",
115+
"From: \"Alice\" <sip:[email protected]>;tag=1754166595691377466",
116+
"",
117+
"",
118+
}).(*Request)
119+
invite.CompactHeaders = true
120+
buf := bytes.NewBuffer(make([]byte, 0))
121+
invite.StringWrite(buf)
122+
123+
byteBuf := buf.String()
124+
rows := strings.Split(byteBuf, "\r\n")
125+
t.Log(rows)
126+
assert.Equal(t, "INVITE sip:[email protected] SIP/2.0", rows[0])
127+
assert.Equal(t, "v: SIP/2.0/udp test.com;branch=z9hG4bK.3h9TE5VD6tjax5YW", rows[1])
128+
assert.Equal(t, "f: \"Alice\" <sip:[email protected]>;tag=1754166595691377466", rows[2])
129+
}

0 commit comments

Comments
 (0)