-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathfreeswitch.go
108 lines (101 loc) · 4.3 KB
/
freeswitch.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
package main
import (
"bytes"
"encoding/xml"
"errors"
"fmt"
"log"
"strings"
"github.com/0x19/goesl"
"github.com/paulrosania/go-charset/charset"
_ "github.com/paulrosania/go-charset/data"
)
func subscribeToFreeswitchRegEvents(esl_client *goesl.Client) error {
// Ensure that we are listening to the required FreeSWITCH events, before we start watching the connection.
esl_client.Send("events json CUSTOM sofia::register sofia::unregister sofia::expire")
result, err := esl_client.ReadMessage()
if err != nil {
return err
}
for _, v := range []string{"Content-Type", "Reply-Text"} {
if _, ok := result.Headers[v]; ok == false {
return fmt.Errorf("subscribeToFreeswitchRegEvents() : Response header '%s' header is missing, cannot proceed.", v)
}
}
if result.Headers["Content-Type"] != "command/reply" {
return errors.New("subscribeToFreeswitchRegEvents() : Response header 'Content-Type' != 'command/reply', cannot proceed.")
}
if result.Headers["Reply-Text"] != "+OK event listener enabled json" {
return errors.New("subscribeToFreeswitchRegEvents() : Response header 'Reply-Text' != '+OK event listener enabled json', cannot proceed.")
}
return nil
}
// These events don't have the full <user> like we get showing registrations, build it from username and from-host.
// event_type string, user string, err error
func parseFreeswitchRegEvent(event *goesl.Message) (string, string, error) {
for _, v := range []string{"Event-Subclass", "username", "from-host"} {
if _, ok := event.Headers[v]; ok == false {
return "", "", fmt.Errorf("getFreeswitchRegEvent() : '%s' field does not exist in FreeSWITCH Event, must be present.", v)
}
if len(event.Headers[v]) == 0 {
return "", "", fmt.Errorf("getFreeswitchRegEvent() : '%s' field cannot be empty in FreeSWITCH Event.", v)
}
}
valid_event_subclasses := []string{"sofia::register", "sofia::expire", "sofia::unregister"}
if stringInSlice(event.Headers["Event-Subclass"], valid_event_subclasses) == false {
return "", "", fmt.Errorf("getFreeswitchRegEvent() : 'Event-Subclass' field must be one of: %s", strings.Join(valid_event_subclasses, ", "))
}
return strings.Replace(event.Headers["Event-Subclass"], "sofia::", "", 1), fmt.Sprintf("%s@%s", event.Headers["username"], event.Headers["from-host"]), nil
}
type FsRegProfile struct {
Profile xml.Name `xml:"profile"`
Registrations []FsRegProfileRegistration `xml:"registrations>registration"`
}
type FsRegProfileRegistration struct {
CallId string `xml:"call-id"`
User string `xml:"user"`
Contact string `xml:"contact"`
Agent string `xml:"agent"`
Status string `xml:"status"`
PingStatus string `xml:"ping-status"`
PingTime float64 `xml:"ping-time"`
Host string `xml:"host"`
NetworkIp string `xml:"network-ip"`
NetworkPort string `xml:"network-port"`
SipAuthUser string `xml:"sip-auth-user"`
SipAuthRealm string `xml:"sip-auth-realm"`
MwiAccount string `xml:"mwi-account"`
}
func getFreeswitchRegistrations(esl_client *goesl.Client, sofia_profiles []string) (*[]string, error) {
var results []string
for _, sofia_profile := range sofia_profiles {
log.Printf("getFreeswitchRegistrations(): Fetching Registrations for Sofia Profile '%s'.\n", sofia_profile)
esl_client.Send(fmt.Sprintf("api sofia xmlstatus profile %s reg", sofia_profile))
msg, err := esl_client.ReadMessage()
if err != nil {
// TODO: decide on the right course of action here...
// If it contains EOF, we really dont care...
if !strings.Contains(err.Error(), "EOF") && err.Error() != "unexpected end of JSON input" {
log.Printf("Error while reading Freeswitch message: %s", err.Error())
continue
}
return new([]string), err
}
// TODOLATER: do we want to check the msg.Headers at all?
var parsed_msg FsRegProfile
// The XML is ISO-8859-1 as received from FreeSWITCH, convert to UTF-8.
decoder := xml.NewDecoder(bytes.NewBuffer(msg.Body))
decoder.CharsetReader = charset.NewReader
err = decoder.Decode(&parsed_msg)
if err != nil {
return new([]string), err
}
//log.Printf("Sofia Profile '%s' Registrations: %+v\n", sofia_profile, parsed_msg)
for _, v := range parsed_msg.Registrations {
if len(v.User) > 0 && stringInSlice(v.User, results) == false {
results = append(results, v.User)
}
}
}
return &results, nil
}