-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathvia.go
115 lines (104 loc) · 2.65 KB
/
via.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// Copyright 2011, Shelby Ramsey. All rights reserved.
// Use of this code is governed by a BSD license that can be
// found in the LICENSE.txt file.
package sipparser
// Imports from the go standard library
import (
"errors"
"strings"
)
type viaStateFn func(v *Via) viaStateFn
// Via is an important part of the *SipMsg. It is a fundamental
// basis on which to build route-sets and do call matching. It
// has the following structs:
type Via struct {
State string // State is the parser state
Error error // Error is an error
Via string // Via is the raw value
Proto string // Proto is the protocol (i.e. "SIP")
Version string // Version is the version (i.e. "2.0")
Transport string // Transport is the transport method (i.e. "UDP")
SentBy string // SentBy is a host:port combination
Branch string // Branch is the branch parameter
Received string
RPort string
Params []*Param
protoEnd int
paramStart int
}
func (v *Via) parse() {
for state := parseViaState; state != nil; {
state = state(v)
}
}
func (v *Via) addParam(s string) {
if v.Params == nil {
v.Params = make([]*Param, 0)
}
p := getParam(s)
switch {
case p.Param == "branch":
v.Branch = p.Val
case p.Param == "rport":
v.RPort = p.Val
case p.Param == "received":
v.Received = p.Val
default:
v.Params = append(v.Params, p)
}
}
func (v *Via) AddReceived(s string) {
v.Received = s
}
func parseViaState(v *Via) viaStateFn {
if v.Error != nil {
return nil
}
return parseViaGetProto
}
func parseViaGetProto(v *Via) viaStateFn {
v.protoEnd = strings.Index(v.Via, " ")
if v.protoEnd == -1 {
v.Error = errors.New("parseViaGetProto err: could not get LWS char.")
return nil
}
protoParts := strings.SplitN(v.Via[0:v.protoEnd], "/", 3)
if len(protoParts) != 3 {
v.Error = errors.New("parseViaGetProto err: split err on proto char.")
return nil
}
v.Proto = protoParts[0]
v.Version = protoParts[1]
v.Transport = protoParts[2]
return parseViaGetParams
}
func parseViaGetParams(v *Via) viaStateFn {
pChar := strings.IndexRune(v.Via, ';')
if pChar == -1 {
return parseViaGetHostPort
}
if v.paramStart == 0 {
v.paramStart = pChar
}
if len(v.Via)-1 > pChar+1 {
parts := strings.Split(v.Via[pChar+1:], ";")
if len(parts) == 1 {
v.addParam(parts[0])
return parseViaGetHostPort
}
for i := 0; i < len(parts); i++ {
v.addParam(parts[i])
}
}
return parseViaGetHostPort
}
func parseViaGetHostPort(v *Via) viaStateFn {
if v.protoEnd == 0 {
v.Error = errors.New("parseViaGetHostPort err: protoEnd is 0.")
return nil
}
if v.protoEnd < v.paramStart {
v.SentBy = v.Via[v.protoEnd+1 : v.paramStart]
}
return nil
}