opensips-mi 0.0.11 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CODE_OF_CONDUCT.md +128 -0
- data/CONTRIBUTING.md +7 -0
- data/Gemfile +9 -4
- data/README.md +133 -120
- data/Rakefile +8 -12
- data/lib/opensips/mi/command.rb +85 -92
- data/lib/opensips/mi/transport/abstract.rb +64 -0
- data/lib/opensips/mi/transport/datagram.rb +40 -26
- data/lib/opensips/mi/transport/http.rb +40 -0
- data/lib/opensips/mi/transport/xmlrpc.rb +36 -22
- data/lib/opensips/mi/transport.rb +4 -1
- data/lib/opensips/mi/version.rb +3 -1
- data/lib/opensips/mi.rb +17 -12
- data/lib/opensips.rb +4 -0
- data/sig/opensips/mi.rbs +6 -0
- metadata +20 -83
- data/.gitignore +0 -30
- data/.rspec +0 -1
- data/.travis.yml +0 -3
- data/lib/opensips/mi/response.rb +0 -176
- data/lib/opensips/mi/transport/fifo.rb +0 -90
- data/opensips-mi.gemspec +0 -26
- data/spec/command_spec.rb +0 -4
- data/spec/fixtures/dlg_list +0 -20
- data/spec/fixtures/ul_dump +0 -168
- data/spec/response_spec.rb +0 -117
- data/spec/spec_helper.rb +0 -112
- data/spec/transport_spec.rb +0 -119
data/lib/opensips/mi/command.rb
CHANGED
@@ -1,45 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Opensips
|
2
4
|
module MI
|
5
|
+
# core class to send command to MI
|
6
|
+
# and return responses
|
3
7
|
class Command
|
8
|
+
attr_reader :transp
|
9
|
+
|
4
10
|
EVENTNOTIFY = {
|
5
11
|
# Aastra
|
6
|
-
aastra_check_cfg:
|
7
|
-
aastra_xml:
|
12
|
+
aastra_check_cfg: "check-sync",
|
13
|
+
aastra_xml: "aastra-xml",
|
8
14
|
# Digium
|
9
|
-
digium_check_cfg:
|
15
|
+
digium_check_cfg: "check-sync",
|
10
16
|
# Linksys
|
11
|
-
linksys_cold_restart:
|
12
|
-
linksys_warm_restart:
|
17
|
+
linksys_cold_restart: "reboot_now",
|
18
|
+
linksys_warm_restart: "restart_now",
|
13
19
|
# Polycom
|
14
|
-
polycom_check_cfg:
|
20
|
+
polycom_check_cfg: "check-sync",
|
15
21
|
# Sipura
|
16
|
-
sipura_check_cfg:
|
17
|
-
sipura_get_report:
|
22
|
+
sipura_check_cfg: "resync",
|
23
|
+
sipura_get_report: "report",
|
18
24
|
# Snom
|
19
|
-
snom_check_cfg:
|
20
|
-
snom_reboot:
|
25
|
+
snom_check_cfg: "check-sync;reboot=false",
|
26
|
+
snom_reboot: "check-sync;reboot=true",
|
21
27
|
# Cisco
|
22
|
-
cisco_check_cfg:
|
28
|
+
cisco_check_cfg: "check-sync",
|
23
29
|
# Avaya
|
24
|
-
avaya_check_cfg:
|
25
|
-
}
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
30
|
+
avaya_check_cfg: "check-sync"
|
31
|
+
}.freeze
|
32
|
+
|
33
|
+
def initialize(transp)
|
34
|
+
@transp = transp
|
35
|
+
end
|
36
|
+
|
37
|
+
# prepare args, pipe them to send to MI using transport
|
38
|
+
# and finally format response
|
39
|
+
def command(*params)
|
40
|
+
raise ErrorParams, "command missing method name" if params.empty?
|
41
|
+
|
42
|
+
transp.adapter_request(*params)
|
43
|
+
.then { |args| transp.send(*args) }
|
44
|
+
.then { |resp| transp.adapter_response(resp) }
|
45
|
+
end
|
46
|
+
|
47
|
+
# meta methods call directly
|
48
|
+
def method_missing(cmd, *args)
|
49
|
+
command(cmd.to_s, *args)
|
37
50
|
end
|
38
51
|
|
52
|
+
def respond_to_missing?(_name, _include_private = false) = true
|
53
|
+
|
39
54
|
# = Interface to t_uac_dlg function of transaction (tm) module
|
40
55
|
# Very cool method from OpenSIPs. Can generate and send SIP request method to destination.
|
41
56
|
# Example of usage:
|
42
|
-
# - Send NOTIFY with special Event header to force restart SIP phone
|
57
|
+
# - Send NOTIFY with special Event header to force restart SIP phone
|
58
|
+
# (equivalent of ASterisk's "sip notify peer")
|
43
59
|
# - Send PUBLISH to trigger device state change notification
|
44
60
|
# - Send REFER to transfer call
|
45
61
|
# - etc., etc., etc.
|
@@ -50,10 +66,6 @@ module Opensips
|
|
50
66
|
# Example:
|
51
67
|
# hf["From"] => "Alice Liddell <sip:alice@wanderland.com>;tag=843887163"
|
52
68
|
#
|
53
|
-
# Special "nl" header with any value is used to input additional "\r\n". This is
|
54
|
-
# useful, for example, for message-summary event to separate application body. This is
|
55
|
-
# because t_uac_dlg expect body parameter as xml only.
|
56
|
-
#
|
57
69
|
# Thus, using multiple headers with same header-name is not possible with header hash.
|
58
70
|
# However, it is possible to use multiple header-values comma separated (rfc3261, section 7.3.1):
|
59
71
|
# hf["Route"] => "<sip:alice@atlanta.com>, <sip:bob@biloxi.com>"
|
@@ -67,60 +79,52 @@ module Opensips
|
|
67
79
|
# == Parameters
|
68
80
|
# method: SIP request method (NOTIFY, PUBLISH etc)
|
69
81
|
# ruri: Request URI, ex.: sip:555@10.0.0.55:5060
|
70
|
-
# hf: Headers array. Additional headers will be added to request.
|
82
|
+
# hf: Headers array. Additional headers will be added to request.
|
71
83
|
# At least "From" and "To" headers must be specify
|
72
84
|
# nhop: Next hop SIP URI (OBP); use "." if no value.
|
73
|
-
# socket: Local socket to be used for sending the request; use "." if no value.
|
74
|
-
#
|
75
|
-
#
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
"Missing mandatory header #{n.capitalize}" unless hf.keys.map{|h| h.downcase}.include?(n)
|
82
|
-
end
|
83
|
-
# compile headers to string
|
84
|
-
headers = hf.map{|name,val| name.eql?("nl") ? "" : "#{name}: #{val}"}.join "\r\n"
|
85
|
+
# socket: Local socket to be used for sending the request; use "." if no value.
|
86
|
+
# Ex.: udp:10.130.8.21:5060
|
87
|
+
# body: (optional, may not be present) request body (if present, requires the "Content-Type"
|
88
|
+
# and "Content-length" headers)
|
89
|
+
def uac_dlg(method, ruri, hdrs, next_hop = ".", socket = ".", body = nil)
|
90
|
+
validate_hf(hdrs)
|
91
|
+
|
92
|
+
headers = hdrs.map { |name, val| "#{name}: #{val}" }.join("\r\n")
|
85
93
|
headers << "\r\n\r\n"
|
86
94
|
|
87
|
-
|
88
|
-
params = [method, ruri, next_hop, socket, set_header(headers)]
|
95
|
+
params = [method, ruri, next_hop, socket, headers]
|
89
96
|
params << body unless body.nil?
|
90
|
-
|
91
|
-
command 't_uac_dlg', params
|
97
|
+
command "t_uac_dlg", params
|
92
98
|
end
|
93
99
|
|
94
100
|
# = NOTIFY check-sync like event
|
95
|
-
# NOTIFY Events to restart phone, force configuration reload or
|
96
|
-
# report for some SIP IP phone models.
|
101
|
+
# NOTIFY Events to restart phone, force configuration reload or
|
102
|
+
# report for some SIP IP phone models.
|
97
103
|
# The events list was taken from Asterisk configuration file (sip_notify.conf)
|
98
104
|
# Note that SIP IP phones usually should be configured to accept special notify
|
99
105
|
# event to reboot. For example, Polycom configuration option to enable special
|
100
106
|
# event would be:
|
101
107
|
# voIpProt.SIP.specialEvent.checkSync.alwaysReboot="1"
|
102
108
|
#
|
103
|
-
# This function will generate To/From/Event headers. Will use random tag for
|
104
|
-
# From header.
|
109
|
+
# This function will generate To/From/Event headers. Will use random tag for
|
110
|
+
# From header.
|
105
111
|
# *NOTE*: This function will not generate To header tag. This is not complying with
|
106
|
-
# SIP protocol specification (rfc3265). NOTIFY must be part of a subscription
|
112
|
+
# SIP protocol specification (rfc3265). NOTIFY must be part of a subscription
|
107
113
|
# dialog. However, it works for the most of the SIP IP phone models.
|
108
114
|
# == Parameters
|
109
|
-
# - uri: Valid client contact URI (sip:alice@10.0.0.100:5060).
|
115
|
+
# - uri: Valid client contact URI (sip:alice@10.0.0.100:5060).
|
110
116
|
# To get client URI use *ul_show_contact => contact* function
|
111
117
|
# - event: One of the events from EVENTNOTIFY constant hash
|
112
|
-
# - hf: Header fields. Add To/From header fields here if you do not want them
|
118
|
+
# - hf: Header fields. Add To/From header fields here if you do not want them
|
113
119
|
# to be auto-generated. Header field example:
|
114
120
|
# hf['To'] => '<sip:alice@wanderland.com>'
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
uac_dlg "NOTIFY", uri, hf
|
121
|
+
def event_notify(uri, event, hdrs = {})
|
122
|
+
hnames = hdrs.keys.map { |k| k.to_s.downcase } || []
|
123
|
+
hdrs["To"] = "<#{uri}>" unless hnames.include?("to")
|
124
|
+
hdrs["From"] = "<#{uri}>;tag=#{rand(1 << 32)}" unless hnames.include?("from")
|
125
|
+
hdrs["Event"] = EVENTNOTIFY[event] || event.to_s
|
126
|
+
|
127
|
+
uac_dlg "NOTIFY", uri, hdrs
|
124
128
|
end
|
125
129
|
|
126
130
|
# = Presence MWI
|
@@ -135,39 +139,28 @@ module Opensips
|
|
135
139
|
# - old: (optional) Old messages
|
136
140
|
# - urg_new: (optional) New urgent messages
|
137
141
|
# - urg_old: (optional) Old urgent messages
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
'Content-Type' => "application/simple-message-summary",
|
151
|
-
'nl' => "",
|
152
|
-
]
|
153
|
-
|
154
|
-
uac_dlg "NOTIFY", uri, hf.merge(mbody)
|
142
|
+
def mwi_update(uri, vmaccount, newmsgs, old = 0, urg_new = 0, urg_old = 0)
|
143
|
+
hbody = { "Messages-Waiting" => (newmsgs.positive? ? "yes" : "no"),
|
144
|
+
"Message-Account" => vmaccount,
|
145
|
+
"Voice-Message" => "#{newmsgs}/#{old} (#{urg_new}/#{urg_old})" }
|
146
|
+
hdrs = { "To" => "<#{uri}>",
|
147
|
+
"From" => "<#{uri}>;tag=#{rand(1 << 32)}",
|
148
|
+
"Event" => "message-summary",
|
149
|
+
"Subscription-State" => "active",
|
150
|
+
"Content-Type" => "application/simple-message-summary" }
|
151
|
+
|
152
|
+
body = hbody.map { |k, v| "#{k}: #{v}" }.join("\r\n") << "\r\n\r\n"
|
153
|
+
uac_dlg "NOTIFY", uri, hdrs, ".", ".", body
|
155
154
|
end
|
156
155
|
|
157
156
|
private
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
Socket.getaddrinfo(params[:host], nil) rescue
|
166
|
-
raise SocketError, "Invalid host #{params[:host]}"
|
167
|
-
raise SocketError,
|
168
|
-
"Invalid port #{params[:port]}" unless (1..(2**16-1)).include?(params[:port])
|
169
|
-
true
|
170
|
-
end
|
157
|
+
|
158
|
+
def validate_hf(headers)
|
159
|
+
names = headers&.keys&.map { |k| k.to_s.downcase } || []
|
160
|
+
return if names.include?("to") && names.include?("from")
|
161
|
+
|
162
|
+
raise ArgumentError, "invalid headers value. must be a hash and have 'To' and 'From' headers"
|
163
|
+
end
|
171
164
|
end
|
172
165
|
end
|
173
166
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
module Opensips
|
6
|
+
module MI
|
7
|
+
module Transport
|
8
|
+
# abstruct class for transport protocols
|
9
|
+
class Abstract
|
10
|
+
# send a command to connection and return response
|
11
|
+
def send(_command)
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
# request adapter method
|
16
|
+
# by default if does jsonrpc v2 as string
|
17
|
+
# xmlrpc overload this message
|
18
|
+
def adapter_request(cmd, *args)
|
19
|
+
rpc = {
|
20
|
+
jsonrpc: "2.0",
|
21
|
+
id: rand(1 << 16),
|
22
|
+
method: cmd
|
23
|
+
}
|
24
|
+
|
25
|
+
unless args.empty?
|
26
|
+
params = args.flatten
|
27
|
+
rpc[:params] = params[0].is_a?(Hash) ? params[0] : params
|
28
|
+
end
|
29
|
+
|
30
|
+
JSON.generate(rpc)
|
31
|
+
end
|
32
|
+
|
33
|
+
# response adapter by default parses jsonrpc response
|
34
|
+
# to an object. xmlrp overloads this method
|
35
|
+
def adapter_response(body)
|
36
|
+
resp = JSON.parse(body)
|
37
|
+
if resp["result"]
|
38
|
+
{ result: resp["result"] }
|
39
|
+
elsif resp["error"]
|
40
|
+
{ error: resp["error"] }
|
41
|
+
else
|
42
|
+
{ error: { "message" => "invalid response: #{body}" } }
|
43
|
+
end
|
44
|
+
rescue JSON::ParserError => e
|
45
|
+
{ error: { "message" => %(JSON::ParserError: #{e}) } }
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
def raise_invalid_params
|
51
|
+
raise Opensips::MI::ErrorParams,
|
52
|
+
"invalid params. Expecting a hash with :url and optional :timeout"
|
53
|
+
end
|
54
|
+
|
55
|
+
def seturi(url)
|
56
|
+
@uri = URI(url)
|
57
|
+
rescue URI::InvalidURIError
|
58
|
+
raise Opensips::MI::ErrorParams,
|
59
|
+
"invalid http host url: #{url}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -1,42 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "abstract"
|
4
|
+
require "socket"
|
5
|
+
require "timeout"
|
6
|
+
|
1
7
|
module Opensips
|
2
8
|
module MI
|
3
9
|
module Transport
|
4
|
-
|
5
|
-
|
6
|
-
|
10
|
+
# datagram UDP transport to communicate with MI
|
11
|
+
class Datagram < Abstract
|
12
|
+
def initialize(args)
|
13
|
+
super()
|
14
|
+
raise_invalid_params unless args.is_a?(Hash)
|
15
|
+
@host, @port, @timeout = args.values_at(:host, :port, :timeout)
|
16
|
+
raise_invalid_params if @host.nil? || @port.nil?
|
17
|
+
raise_invalid_port unless @port.to_i.between?(1, 1 << 16)
|
18
|
+
@timeout ||= 5
|
19
|
+
connect
|
20
|
+
end
|
7
21
|
|
8
|
-
|
9
|
-
|
10
|
-
|
22
|
+
def send(command)
|
23
|
+
Timeout.timeout(
|
24
|
+
@timeout,
|
25
|
+
Opensips::MI::ErrorSendTimeout,
|
26
|
+
"timeout send command to #{@host}:#{@port} within #{@timeout} sec"
|
27
|
+
) do
|
28
|
+
@sock.send command, 0
|
29
|
+
msg, = @sock.recvfrom(1500)
|
30
|
+
msg
|
11
31
|
end
|
12
32
|
end
|
13
33
|
|
14
|
-
|
15
|
-
host_valid? params
|
16
|
-
@sock = Socketry::UDP::Socket.connect(params[:host], params[:port])
|
17
|
-
@timeout = params[:timeout].to_i
|
18
|
-
end
|
34
|
+
protected
|
19
35
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
request << "#{c}\n"
|
24
|
-
end
|
25
|
-
response = send(request)
|
26
|
-
Opensips::MI::Response.new response.split(?\n)
|
36
|
+
def raise_invalid_params
|
37
|
+
raise Opensips::MI::ErrorParams,
|
38
|
+
"invalid params. Expecting a hash with :host, :port and optional :timeout"
|
27
39
|
end
|
28
40
|
|
29
|
-
def
|
30
|
-
|
41
|
+
def raise_invalid_port
|
42
|
+
raise Opensips::MI::ErrorParams, "invalid port '#{@port}'"
|
31
43
|
end
|
32
44
|
|
33
45
|
private
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
46
|
+
|
47
|
+
def connect
|
48
|
+
@sock = UDPSocket.new
|
49
|
+
Timeout.timeout(
|
50
|
+
@timeout,
|
51
|
+
Opensips::MI::ErrorResolveTimeout,
|
52
|
+
"failed to resolve address #{@host}:#{@port} within #{@timeout} sec"
|
53
|
+
) { @sock.connect(@host, @port) }
|
40
54
|
end
|
41
55
|
end
|
42
56
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "net/http"
|
4
|
+
require_relative "abstract"
|
5
|
+
|
6
|
+
module Opensips
|
7
|
+
module MI
|
8
|
+
module Transport
|
9
|
+
# HTTP transport to communicate with MI
|
10
|
+
class HTTP < Abstract
|
11
|
+
def initialize(args)
|
12
|
+
super()
|
13
|
+
raise_invalid_params unless args.is_a?(Hash)
|
14
|
+
url, @timeout = args.values_at(:url, :timeout)
|
15
|
+
raise_invalid_params if url.nil?
|
16
|
+
seturi(url)
|
17
|
+
@timeout ||= 5
|
18
|
+
connect
|
19
|
+
end
|
20
|
+
|
21
|
+
def send(cmd)
|
22
|
+
resp = @client.post(@uri.path, cmd, { "Content-Type" => "application/json" })
|
23
|
+
unless resp.code.eql? "200"
|
24
|
+
raise Opensips::MI::ErrorHTTPReq,
|
25
|
+
"invalid MI HTTP response: #{resp.message}"
|
26
|
+
end
|
27
|
+
resp.body
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def connect
|
33
|
+
@client = Net::HTTP.new(@uri.host, @uri.port)
|
34
|
+
@client.read_timeout = @timeout
|
35
|
+
@client.write_timeout = @timeout
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,35 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "abstract"
|
4
|
+
require "xmlrpc/client"
|
5
|
+
|
1
6
|
module Opensips
|
2
7
|
module MI
|
3
8
|
module Transport
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
9
|
+
# XML-RPC protocol for MI
|
10
|
+
class Xmlrpc < Abstract
|
11
|
+
def initialize(args)
|
12
|
+
super()
|
13
|
+
raise_invalid_params unless args.is_a?(Hash)
|
14
|
+
url, @timeout = args.values_at(:url, :timeout)
|
15
|
+
raise_invalid_params if url.nil?
|
16
|
+
seturi(url)
|
17
|
+
@client = XMLRPC::Client.new2(@uri.to_s, nil, @timeout)
|
10
18
|
end
|
11
19
|
|
12
|
-
def
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
rescue => e
|
17
|
-
raise e
|
18
|
-
"Can not connect OpenSIPs server.\n#{e.message}"
|
20
|
+
def send(*cmd)
|
21
|
+
@client.call(*cmd)
|
22
|
+
rescue XMLRPC::FaultException => e
|
23
|
+
{ error: { "message" => e.message } }
|
24
|
+
rescue StandardError => e
|
25
|
+
raise Opensips::MI::ErrorHTTPReq, e
|
19
26
|
end
|
20
27
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
return Opensips::MI::Response.new response
|
28
|
+
# overload resonse adapter for xmlrpc
|
29
|
+
def adapter_response(resp)
|
30
|
+
if resp[:error]
|
31
|
+
resp
|
32
|
+
else
|
33
|
+
{ result: resp }
|
34
|
+
end
|
29
35
|
end
|
30
36
|
|
31
|
-
|
37
|
+
# overload request adapter for xmlrpc
|
38
|
+
def adapter_request(*args)
|
39
|
+
args.flatten => [cmd, *rest]
|
40
|
+
return [cmd] if rest.empty?
|
41
|
+
|
42
|
+
rest = rest.flatten
|
43
|
+
return [cmd, rest.first.map { |_, v| v }].flatten if rest.first.is_a?(Hash)
|
32
44
|
|
45
|
+
[cmd, rest].flatten
|
46
|
+
end
|
33
47
|
end
|
34
48
|
end
|
35
49
|
end
|
@@ -1,9 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require_relative "transport/datagram"
|
4
|
+
require_relative "transport/http"
|
3
5
|
require_relative "transport/xmlrpc"
|
4
6
|
|
5
7
|
module Opensips
|
6
8
|
module MI
|
9
|
+
# module transport protocols implementation
|
7
10
|
module Transport
|
8
11
|
end
|
9
12
|
end
|
data/lib/opensips/mi/version.rb
CHANGED
data/lib/opensips/mi.rb
CHANGED
@@ -1,22 +1,27 @@
|
|
1
|
-
|
2
|
-
require 'fcntl'
|
3
|
-
require 'securerandom'
|
4
|
-
require 'socketry'
|
5
|
-
require 'xmlrpc/client'
|
1
|
+
# frozen_string_literal: true
|
6
2
|
|
7
3
|
require "opensips/mi/version"
|
8
|
-
require "opensips/mi/response"
|
9
4
|
require "opensips/mi/command"
|
10
5
|
require "opensips/mi/transport"
|
11
6
|
|
12
7
|
module Opensips
|
8
|
+
# OpenSIPS Managemen Interface core module
|
13
9
|
module MI
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
class Error < StandardError; end
|
11
|
+
class ErrorParams < Error; end
|
12
|
+
class ErrorResolveTimeout < Error; end
|
13
|
+
class ErrorSendTimeout < Error; end
|
14
|
+
class ErrorHTTPReq < Error; end
|
15
|
+
|
16
|
+
def self.connect(transport_proto, params = {})
|
17
|
+
transp = case transport_proto
|
18
|
+
when :datagram then Transport::Datagram.new(params)
|
19
|
+
when :http then Transport::HTTP.new(params)
|
20
|
+
when :xmlrpc then Transport::Xmlrpc.new(params)
|
21
|
+
else
|
22
|
+
raise Error, "Unknown transport method: #{transport_proto}"
|
23
|
+
end
|
24
|
+
Command.new(transp)
|
19
25
|
end
|
20
26
|
end
|
21
27
|
end
|
22
|
-
|
data/lib/opensips.rb
CHANGED