-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathsipTo.go
162 lines (148 loc) · 3.26 KB
/
sipTo.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
package siprocket
// Parses a single line that is in the format of a to line, v
// Also requires a pointer to a struct of type sipTo to write output to
// RFC 3261 - https://www.ietf.org/rfc/rfc3261.txt - 8.1.1.2 To
type sipTo struct {
UriType string // Type of URI sip, sips, tel etc
Name []byte // Named portion of URI
User []byte // User part
Host []byte // Host part
Port []byte // Port number
Tag []byte // Tag
UserType []byte // User Type
Src []byte // Full source if needed
}
func parseSipTo(v []byte, out *sipTo) {
pos := 0
state := FIELD_BASE
// Init the output area
out.UriType = ""
out.Name = nil
out.User = nil
out.Host = nil
out.Port = nil
out.Tag = 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_BASE:
if v[pos] == '"' && out.UriType == "" {
state = FIELD_NAMEQ
pos++
continue
}
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
}
// Look for a Tag identifier
if getString(v, pos, pos+4) == "tag=" {
state = FIELD_TAG
pos = pos + 4
continue
}
// Look for a User Type identifier
if getString(v, pos, pos+5) == "user=" {
state = FIELD_USERTYPE
pos = pos + 5
continue
}
// Look for other identifiers and ignore
if v[pos] == '=' {
state = FIELD_IGNORE
pos = pos + 1
continue
}
// Check for other chrs
if v[pos] != '<' && v[pos] != '>' && v[pos] != ';' && out.UriType == "" {
state = FIELD_NAME
continue
}
}
case FIELD_NAMEQ:
if v[pos] == '"' {
state = FIELD_BASE
pos++
continue
}
out.Name = append(out.Name, v[pos])
case FIELD_NAME:
if v[pos] == '<' || v[pos] == ' ' {
state = FIELD_BASE
pos++
continue
}
out.Name = append(out.Name, v[pos])
case FIELD_USER:
if v[pos] == '@' {
state = FIELD_HOST
pos++
continue
}
out.User = append(out.User, v[pos])
case FIELD_HOST:
if v[pos] == ':' {
state = FIELD_PORT
pos++
continue
}
if 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_TAG:
if v[pos] == ';' || v[pos] == '>' || v[pos] == ' ' {
state = FIELD_BASE
pos++
continue
}
out.Tag = append(out.Tag, v[pos])
case FIELD_IGNORE:
if v[pos] == ';' || v[pos] == '>' {
state = FIELD_BASE
pos++
continue
}
}
pos++
}
}