-
Notifications
You must be signed in to change notification settings - Fork 21
/
sipRequestLine.go
173 lines (156 loc) · 3.41 KB
/
sipRequestLine.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package siprocket
/*
RFC 3261 - https://www.ietf.org/rfc/rfc3261.txt
INVITE sip:[email protected];user=phone SIP/2.0
SIP/2.0 200 OK
*/
type sipReq struct {
Method []byte // Sip Method eg INVITE etc
UriType string // Type of URI sip, sips, tel etc
StatusCode []byte // Status Code eg 100
StatusDesc []byte // Status Code Description eg trying
User []byte // User part
Host []byte // Host part
Port []byte // Port number
UserType []byte // User Type
Src []byte // Full source if needed
}
func parseSipReq(v []byte, out *sipReq) {
pos := 0
state := 0
// Init the output area
out.UriType = ""
out.Method = nil
out.StatusCode = nil
out.User = nil
out.Host = nil
out.Port = nil
out.UserType = nil
out.Src = nil
// Keep the source line if needed
if keep_src {
out.Src = v
}
// Loop through the bytes making up the line
for pos < len(v) {
// FSM
switch state {
case FIELD_NULL:
if v[pos] >= 'A' && v[pos] <= 'S' && pos == 0 {
state = FIELD_METHOD
continue
}
case FIELD_METHOD:
if v[pos] == ' ' || pos > 9 {
if string(out.Method) == "SIP/2.0" {
state = FIELD_STATUS
out.Method = []byte{}
} else {
state = FIELD_BASE
}
pos++
continue
}
out.Method = append(out.Method, v[pos])
case FIELD_BASE:
if v[pos] != ' ' {
// Not a space so check for uri types
if getString(v, pos, pos+4) == "sip:" {
state = FIELD_USER
pos = pos + 4
out.UriType = "sip"
continue
}
if getString(v, pos, pos+5) == "sips:" {
state = FIELD_USER
pos = pos + 5
out.UriType = "sips"
continue
}
if getString(v, pos, pos+4) == "tel:" {
state = FIELD_USER
pos = pos + 4
out.UriType = "tel"
continue
}
if getString(v, pos, pos+5) == "user=" {
state = FIELD_USERTYPE
pos = pos + 5
continue
}
if v[pos] == '@' {
state = FIELD_HOST
out.User = out.Host // Move host to user
out.Host = nil // Clear the host
pos++
continue
}
}
case FIELD_USER:
if v[pos] == ':' {
state = FIELD_PORT
pos++
continue
}
if v[pos] == ';' || v[pos] == '>' {
state = FIELD_BASE
pos++
continue
}
if v[pos] == '@' {
state = FIELD_HOST
out.User = out.Host // Move host to user
out.Host = nil // Clear the host
pos++
continue
}
out.Host = append(out.Host, v[pos]) // Append to host for now
case FIELD_HOST:
if v[pos] == ':' {
state = FIELD_PORT
pos++
continue
}
if v[pos] == ';' || v[pos] == '>' || v[pos] == ' ' {
state = FIELD_BASE
pos++
continue
}
out.Host = append(out.Host, v[pos])
case FIELD_PORT:
if v[pos] == ';' || v[pos] == '>' || v[pos] == ' ' {
state = FIELD_BASE
pos++
continue
}
out.Port = append(out.Port, v[pos])
case FIELD_USERTYPE:
if v[pos] == ';' || v[pos] == '>' || v[pos] == ' ' {
state = FIELD_BASE
pos++
continue
}
out.UserType = append(out.UserType, v[pos])
case FIELD_STATUS:
if v[pos] == ';' || v[pos] == '>' {
state = FIELD_BASE
pos++
continue
}
if v[pos] == ' ' {
state = FIELD_STATUSDESC
pos++
continue
}
out.StatusCode = append(out.StatusCode, v[pos])
case FIELD_STATUSDESC:
if v[pos] == ';' || v[pos] == '>' {
state = FIELD_BASE
pos++
continue
}
out.StatusDesc = append(out.StatusDesc, v[pos])
}
pos++
}
}