• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ghettovoice / gosip / 20275641102

16 Dec 2025 04:42PM UTC coverage: 40.889% (-33.6%) from 74.523%
20275641102

push

github

ghettovoice
Refactor SIP stack with transaction/transport layers and improved API

- Implement TransactionLayer with request/response routing and graceful shutdown
- Add TransportLayer for centralized transport management
- Client/server transaction implementation with persistence support
- Add transaction factories and automatic cleanup on termination
- Introduce InboundMessage/OutboundMessage wrappers with type-safe accessors
- Add StatsRecorder interface for transport statistics
- Consolidate Send/Render/NewResponse methods with optional options
- Add log package with context-based logger
- Support compact header rendering
- Message RTT calculation
- Optimization: upgrade abnf lib, fix race conditions, read timeouts
- Improve error handling and validation
- Add comprehensive test coverage

7324 of 19365 new or added lines in 110 files covered. (37.82%)

19 existing lines in 3 files now uncovered.

8439 of 20639 relevant lines covered (40.89%)

8.25 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.84
/header/accept_encoding.go
1
package header
2

3
import (
4
        "errors"
5
        "fmt"
6
        "io"
7
        "slices"
8
        "strconv"
9

10
        "braces.dev/errtrace"
11
        "github.com/ghettovoice/abnf"
12

13
        "github.com/ghettovoice/gosip/internal/errorutil"
14
        "github.com/ghettovoice/gosip/internal/grammar"
15
        "github.com/ghettovoice/gosip/internal/ioutil"
16
        "github.com/ghettovoice/gosip/internal/util"
17
)
18

19
type AcceptEncoding []EncodingRange
20

21
func (AcceptEncoding) CanonicName() Name { return "Accept-Encoding" }
10✔
22

NEW
23
func (AcceptEncoding) CompactName() Name { return "Accept-Encoding" }
×
24

25
func (hdr AcceptEncoding) RenderTo(w io.Writer, _ *RenderOptions) (num int, err error) {
11✔
26
        if hdr == nil {
12✔
27
                return 0, nil
1✔
28
        }
1✔
29

30
        cw := ioutil.GetCountingWriter(w)
10✔
31
        defer ioutil.FreeCountingWriter(cw)
10✔
32
        cw.Fprint(hdr.CanonicName(), ": ")
10✔
33
        cw.Call(hdr.renderValueTo)
10✔
34
        return errtrace.Wrap2(cw.Result())
10✔
35
}
36

37
func (hdr AcceptEncoding) renderValueTo(w io.Writer) (num int, err error) {
15✔
38
        return errtrace.Wrap2(renderHdrEntries(w, hdr))
15✔
39
}
15✔
40

41
func (hdr AcceptEncoding) Render(opts *RenderOptions) string {
8✔
42
        if hdr == nil {
9✔
43
                return ""
1✔
44
        }
1✔
45

46
        sb := util.GetStringBuilder()
7✔
47
        defer util.FreeStringBuilder(sb)
7✔
48
        hdr.RenderTo(sb, opts) //nolint:errcheck
7✔
49
        return sb.String()
7✔
50
}
51

52
func (hdr AcceptEncoding) RenderValue() string {
5✔
53
        sb := util.GetStringBuilder()
5✔
54
        defer util.FreeStringBuilder(sb)
5✔
55
        hdr.renderValueTo(sb) //nolint:errcheck
5✔
56
        return sb.String()
5✔
57
}
5✔
58

59
func (hdr AcceptEncoding) String() string { return hdr.RenderValue() }
5✔
60

61
func (hdr AcceptEncoding) Format(f fmt.State, verb rune) {
6✔
62
        switch verb {
6✔
63
        case 's':
2✔
64
                if f.Flag('+') {
3✔
65
                        hdr.RenderTo(f, nil) //nolint:errcheck
1✔
66
                        return
1✔
67
                }
1✔
68
                fmt.Fprint(f, hdr.String())
1✔
69
                return
1✔
70
        case 'q':
2✔
71
                if f.Flag('+') {
3✔
72
                        fmt.Fprint(f, strconv.Quote(hdr.Render(nil)))
1✔
73
                        return
1✔
74
                }
1✔
75
                fmt.Fprint(f, strconv.Quote(hdr.String()))
1✔
76
                return
1✔
77
        default:
2✔
78
                type hideMethods AcceptEncoding
2✔
79
                type AcceptEncoding hideMethods
2✔
80
                fmt.Fprintf(f, fmt.FormatString(f, verb), AcceptEncoding(hdr))
2✔
81
                return
2✔
82
        }
83
}
84

85
func (hdr AcceptEncoding) Clone() Header { return cloneHdrEntries(hdr) }
3✔
86

87
func (hdr AcceptEncoding) Equal(val any) bool {
24✔
88
        var other AcceptEncoding
24✔
89
        switch v := val.(type) {
24✔
90
        case AcceptEncoding:
21✔
91
                other = v
21✔
92
        case *AcceptEncoding:
2✔
93
                if v == nil {
3✔
94
                        return false
1✔
95
                }
1✔
96
                other = *v
1✔
97
        default:
1✔
98
                return false
1✔
99
        }
100
        return slices.EqualFunc(hdr, other, func(rng1, rng2 EncodingRange) bool { return rng1.Equal(rng2) })
40✔
101
}
102

103
func (hdr AcceptEncoding) IsValid() bool {
5✔
104
        return hdr != nil && !slices.ContainsFunc(hdr, func(rng EncodingRange) bool { return !rng.IsValid() })
9✔
105
}
106

NEW
107
func (hdr AcceptEncoding) MarshalJSON() ([]byte, error) {
×
NEW
108
        return errtrace.Wrap2(ToJSON(hdr))
×
NEW
109
}
×
110

NEW
111
func (hdr *AcceptEncoding) UnmarshalJSON(data []byte) error {
×
NEW
112
        gh, err := FromJSON(data)
×
NEW
113
        if err != nil {
×
NEW
114
                *hdr = nil
×
NEW
115
                if errors.Is(err, errNotHeaderJSON) {
×
NEW
116
                        return nil
×
NEW
117
                }
×
NEW
118
                return errtrace.Wrap(err)
×
119
        }
120

NEW
121
        h, ok := gh.(AcceptEncoding)
×
NEW
122
        if !ok {
×
NEW
123
                *hdr = nil
×
NEW
124
                return errtrace.Wrap(errorutil.Errorf("unexpected header: got %T, want %T", gh, *hdr))
×
NEW
125
        }
×
126

NEW
127
        *hdr = h
×
NEW
128
        return nil
×
129
}
130

131
func buildFromAcceptEncodingNode(node *abnf.Node) AcceptEncoding {
3✔
132
        rngNodes := node.GetNodes("encoding")
3✔
133
        hdr := make(AcceptEncoding, len(rngNodes))
3✔
134
        for i, rngNode := range rngNodes {
6✔
135
                hdr[i] = EncodingRange{
3✔
136
                        Encoding: Encoding(grammar.MustGetNode(rngNode, "codings").String()),
3✔
137
                        Params:   buildFromHeaderParamNodes(rngNode.GetNodes("accept-param"), nil),
3✔
138
                }
3✔
139
        }
3✔
140
        return hdr
3✔
141
}
142

143
type EncodingRange struct {
144
        Encoding Encoding
145
        Params   Values
146
}
147

148
func (rng EncodingRange) String() string {
23✔
149
        sb := util.GetStringBuilder()
23✔
150
        defer util.FreeStringBuilder(sb)
23✔
151
        sb.WriteString(string(rng.Encoding))
23✔
152
        renderHdrParams(sb, rng.Params, false) //nolint:errcheck
23✔
153
        return sb.String()
23✔
154
}
23✔
155

156
func (rng EncodingRange) Format(f fmt.State, verb rune) {
23✔
157
        switch verb {
23✔
NEW
158
        case 's':
×
NEW
159
                fmt.Fprint(f, rng.String())
×
NEW
160
                return
×
NEW
161
        case 'q':
×
NEW
162
                fmt.Fprint(f, strconv.Quote(rng.String()))
×
NEW
163
                return
×
164
        default:
23✔
165
                if !f.Flag('+') && !f.Flag('#') {
44✔
166
                        fmt.Fprint(f, rng.String())
21✔
167
                        return
21✔
168
                }
21✔
169

170
                type hideMethods EncodingRange
2✔
171
                type EncodingRange hideMethods
2✔
172
                fmt.Fprintf(f, fmt.FormatString(f, verb), EncodingRange(rng))
2✔
173
                return
2✔
174
        }
175
}
176

177
func (rng EncodingRange) Equal(val any) bool {
34✔
178
        var other EncodingRange
34✔
179
        switch v := val.(type) {
34✔
180
        case EncodingRange:
31✔
181
                other = v
31✔
182
        case *EncodingRange:
2✔
183
                if v == nil {
3✔
184
                        return false
1✔
185
                }
1✔
186
                other = *v
1✔
187
        default:
1✔
188
                return false
1✔
189
        }
190
        return rng.Encoding.Equal(other.Encoding) &&
32✔
191
                compareHdrParams(rng.Params, other.Params, map[string]bool{"q": true})
32✔
192
}
193

194
func (rng EncodingRange) IsValid() bool {
8✔
195
        return rng.Encoding.IsValid() &&
8✔
196
                validateHdrParams(rng.Params)
8✔
197
}
8✔
198

199
func (rng EncodingRange) IsZero() bool { return rng.Encoding == "" && len(rng.Params) == 0 }
2✔
200

201
func (rng EncodingRange) Clone() EncodingRange {
4✔
202
        rng.Params = rng.Params.Clone()
4✔
203
        return rng
4✔
204
}
4✔
205

NEW
206
func (rng EncodingRange) MarshalText() ([]byte, error) {
×
NEW
207
        return []byte(rng.String()), nil
×
NEW
208
}
×
209

NEW
210
func (rng *EncodingRange) UnmarshalText(data []byte) error {
×
NEW
211
        node, err := grammar.ParseEncoding(data)
×
NEW
212
        if err != nil {
×
NEW
213
                *rng = EncodingRange{}
×
NEW
214
                if errors.Is(err, grammar.ErrEmptyInput) {
×
NEW
215
                        return nil
×
NEW
216
                }
×
NEW
217
                return errtrace.Wrap(err)
×
218
        }
219

NEW
220
        rng.Encoding = Encoding(grammar.MustGetNode(node, "codings").String())
×
NEW
221
        rng.Params = buildFromHeaderParamNodes(node.GetNodes("accept-param"), nil)
×
NEW
222
        return nil
×
223
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc