rami 0.1 → 0.2
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.
- data/CHANGELOG +20 -0
- data/bin/example1.rb +33 -0
- data/bin/example2.rb +29 -0
- data/bin/server.rb +2 -9
- data/bin/test.rb +4 -7
- data/lib/rami.rb +90 -64
- metadata +5 -2
data/CHANGELOG
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
* 0.2 (Oct 20, 2005)
|
|
2
|
+
|
|
3
|
+
* Change RamiServer and RamiClient classes to just Server and Client. Client now takes one paramater for new(), which is an instance
|
|
4
|
+
of Server. Server.new now takes it's argumetns via a single hash, instead of setting the options via attributes after the instance
|
|
5
|
+
is created.
|
|
6
|
+
|
|
7
|
+
* Separated Drb from Rami per the suggestion of Jonathan Paisley. You can now create a server and client without having to use Drb
|
|
8
|
+
|
|
9
|
+
* Added some more examples to /bin
|
|
10
|
+
|
|
11
|
+
* Fixed couple of minor bugs
|
|
12
|
+
|
|
13
|
+
* Cleaned up the logging a bit. I know I should use the ruby logging module, maybe later..
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
* 0.1 (Oct 16, 2005)
|
|
18
|
+
|
|
19
|
+
* First release of Rami
|
|
20
|
+
|
data/bin/example1.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/local/bin/ruby
|
|
2
|
+
|
|
3
|
+
require 'rubygems'
|
|
4
|
+
require 'rami'
|
|
5
|
+
include Rami
|
|
6
|
+
|
|
7
|
+
def print_results(t)
|
|
8
|
+
if t.size > 0
|
|
9
|
+
t.each do |array|
|
|
10
|
+
array.each {|key,value| puts "#{key}: #{value}"}
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
puts "\n\n"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
server = Server.new({'host' => 'localhost', 'username' => 'asterisk', 'secret' => 'secret'})
|
|
17
|
+
server.console =1
|
|
18
|
+
server.event_cache = 100
|
|
19
|
+
server.run
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
client = Client.new(server)
|
|
23
|
+
|
|
24
|
+
client.timeout = 10
|
|
25
|
+
t = client.ping
|
|
26
|
+
print_results(t)
|
|
27
|
+
|
|
28
|
+
t = client.mailbox_count(1002)
|
|
29
|
+
print_results(t)
|
|
30
|
+
|
|
31
|
+
t = client.get_events
|
|
32
|
+
print_results(t)
|
|
33
|
+
|
data/bin/example2.rb
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/local/bin/ruby
|
|
2
|
+
|
|
3
|
+
require 'rubygems'
|
|
4
|
+
require 'rami'
|
|
5
|
+
include Rami
|
|
6
|
+
|
|
7
|
+
def print_results(t)
|
|
8
|
+
if t.size > 0
|
|
9
|
+
t.each do |array|
|
|
10
|
+
array.each {|key,value| puts "#{key}: #{value}"}
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
puts "\n\n"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
c = DRbObject.new(nil,"druby://localhost:9000")
|
|
17
|
+
client = Client.new(c)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
client.timeout = 10
|
|
21
|
+
t = client.ping
|
|
22
|
+
print_results(t)
|
|
23
|
+
|
|
24
|
+
t = client.mailbox_count(1002)
|
|
25
|
+
print_results(t)
|
|
26
|
+
|
|
27
|
+
t = client.get_events
|
|
28
|
+
print_results(t)
|
|
29
|
+
|
data/bin/server.rb
CHANGED
|
@@ -4,18 +4,11 @@ require 'rubygems'
|
|
|
4
4
|
require 'rami'
|
|
5
5
|
include Rami
|
|
6
6
|
|
|
7
|
-
server =
|
|
7
|
+
server = Server.new({'host' => 'localhost', 'username' => 'asterisk', 'secret' => 'secret', 'console' => 0, 'event_cache' => 100})
|
|
8
8
|
|
|
9
|
-
## if you want all events printed to the console set this to 1
|
|
10
9
|
server.console =1
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
server.username = 'asterisk'
|
|
14
|
-
server.secret = 'secret'
|
|
15
|
-
|
|
16
|
-
## The host and port that the manager interface is running on.
|
|
17
|
-
server.host = 'localhost'
|
|
18
|
-
server.port = 5038
|
|
11
|
+
server.event_cache = 100
|
|
19
12
|
|
|
20
13
|
## DRb URI
|
|
21
14
|
drburi = "druby://localhost:9000"
|
data/bin/test.rb
CHANGED
|
@@ -13,7 +13,9 @@ def print_results(t)
|
|
|
13
13
|
puts "\n\n"
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
c = DRbObject.new(nil,"druby://localhost:9000")
|
|
17
|
+
client = Client.new(c)
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
## Redirect
|
|
19
21
|
client.timeout = 10
|
|
@@ -35,11 +37,6 @@ client.timeout = 10
|
|
|
35
37
|
t = client.sip_peers
|
|
36
38
|
print_results(t)
|
|
37
39
|
|
|
38
|
-
## SIPshowpeer
|
|
39
|
-
client.timeout = 10
|
|
40
|
-
t = client.sip_show_peer('test_peer')
|
|
41
|
-
print_results(t)
|
|
42
|
-
|
|
43
40
|
## ParkedCalls
|
|
44
41
|
client.timeout = 10
|
|
45
42
|
t = client.parked_calls
|
|
@@ -135,7 +132,7 @@ print_results(t)
|
|
|
135
132
|
t = client.find_events('Event','NewCallerID')
|
|
136
133
|
print_results(t)
|
|
137
134
|
# OR
|
|
138
|
-
t = client.find_events('any'
|
|
135
|
+
t = client.find_events('any' => 'SIP/test_extension')
|
|
139
136
|
print_results(t)
|
|
140
137
|
|
|
141
138
|
## Get all events in the state queue
|
data/lib/rami.rb
CHANGED
|
@@ -33,11 +33,46 @@ require 'monitor'
|
|
|
33
33
|
require 'socket'
|
|
34
34
|
require 'timeout'
|
|
35
35
|
|
|
36
|
-
#
|
|
36
|
+
# Rami can be used to write standalone scripts to send commands to the Asterisk manager interface, or you can
|
|
37
|
+
# use Drb and Rami::Server to run a Rami proxy server. You can then connect to the proxy server using Rami::Client and Drb.
|
|
38
|
+
# This module was written against Asterisk 1.2-beta1. There are a few minor changes to some AMI commands
|
|
39
|
+
# in Asterisk CVS HEAD. When 1.2 is released I will update the module accordingly.
|
|
37
40
|
module Rami
|
|
38
41
|
|
|
39
|
-
# The Rami client
|
|
40
|
-
#
|
|
42
|
+
# The Rami client.
|
|
43
|
+
#
|
|
44
|
+
# One possible point of confusion about the client is that it takes a server instance as the sole argument to it's new()
|
|
45
|
+
# method. This is because Rami was designed to be used with Drb. You don't have to use Drb though.
|
|
46
|
+
# You can create and start a Server instance via it's run method, then in the same code create your Client instance
|
|
47
|
+
# and submit requests to the server. A simple example..
|
|
48
|
+
#
|
|
49
|
+
# require 'rubygems'
|
|
50
|
+
#
|
|
51
|
+
# require 'rami'
|
|
52
|
+
#
|
|
53
|
+
# include Rami
|
|
54
|
+
#
|
|
55
|
+
# server = Server.new({'host' => 'localhost', 'username' => 'asterisk', 'secret' => 'secret'})
|
|
56
|
+
#
|
|
57
|
+
# server.run
|
|
58
|
+
#
|
|
59
|
+
# client = Client.new(server)
|
|
60
|
+
#
|
|
61
|
+
# client.timeout = 10
|
|
62
|
+
#
|
|
63
|
+
# puts client.ping
|
|
64
|
+
#
|
|
65
|
+
# The above code will start the server and login, then execute the ping command and print the results, then exit, disconnecting
|
|
66
|
+
# from asterisk.
|
|
67
|
+
#
|
|
68
|
+
# To connect to a running server using Drb you can create a client instance like this.:
|
|
69
|
+
#
|
|
70
|
+
# c = DRbObject.new(nil,"druby://localhost:9000")
|
|
71
|
+
#
|
|
72
|
+
# client = Client.new(c)
|
|
73
|
+
#
|
|
74
|
+
#
|
|
75
|
+
# All Client methods return an array of hashes, or an empty array if no data is available.
|
|
41
76
|
#
|
|
42
77
|
# Each hash will contain an asterisk response packet. Note that not all response packets are always returned. If a response
|
|
43
78
|
# packet is necessary for the actual communication with asterisk, but does not in itself have any meaningful content, then
|
|
@@ -48,29 +83,23 @@ module Rami
|
|
|
48
83
|
# I tried to document the things that need it the most. Some things should be fairly evident, such as methods for simple
|
|
49
84
|
# commands like Monitor or Ping.
|
|
50
85
|
#
|
|
51
|
-
# For examples, see test.rb in the bin directory.
|
|
86
|
+
# For examples, see example1.rb, example2.rb, and test.rb in the bin directory.
|
|
52
87
|
#
|
|
53
88
|
# Not all manager commands are currently supported. This is only because I have not yet had the time to add them.
|
|
54
89
|
# I tried to add the most complicated commands first, so adding the remaining commands is fairly simple.
|
|
55
90
|
# If there is a command you need let me know and I will make sure it gets included.
|
|
56
|
-
# If you want to add your own action command it's fairly simple. Add a method in
|
|
57
|
-
# the new command, and then add a section in the
|
|
58
|
-
class
|
|
59
|
-
|
|
60
|
-
# Server hostname. Default localhost
|
|
61
|
-
attr_writer :host
|
|
62
|
-
# Server port. Default 9000
|
|
63
|
-
attr_writer :port
|
|
91
|
+
# If you want to add your own action command it's fairly simple. Add a method in Client for
|
|
92
|
+
# the new command, and then add a section in the Client::send_action loop to harvest the response.
|
|
93
|
+
class Client
|
|
94
|
+
|
|
64
95
|
# Number of seconds before a method call will timeout. Default 10.
|
|
65
96
|
attr_writer :timeout
|
|
66
97
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
@port = 9000
|
|
98
|
+
# Takes one argument, an instance of Server OR a DrbObject pointed at a running Rami server.
|
|
99
|
+
def initialize(client)
|
|
70
100
|
@timeout = 10
|
|
71
101
|
@action_id = Time.now().to_f
|
|
72
|
-
|
|
73
|
-
@client = DRbObject.new(nil,"druby://#{@host}:#{@port}")
|
|
102
|
+
@client = client
|
|
74
103
|
end
|
|
75
104
|
|
|
76
105
|
def absolute_timeout(channel=nil,tout=nil)
|
|
@@ -112,13 +141,13 @@ class RamiClient
|
|
|
112
141
|
# The key is an exact match, the value is a regex. You can also call find_events with key=any, which will match
|
|
113
142
|
# any entry with the given value
|
|
114
143
|
#
|
|
115
|
-
# The returned results are deleted from the queue. See
|
|
144
|
+
# The returned results are deleted from the queue. See Server for more information on the queue structure.
|
|
116
145
|
def find_events(key=nil,value=nil)
|
|
117
146
|
return @client.find_events(key,value)
|
|
118
147
|
end
|
|
119
148
|
|
|
120
149
|
# Get all events from the state queue. The returned results are deleted from the queue.
|
|
121
|
-
# See
|
|
150
|
+
# See Server for more information on the queue structure.
|
|
122
151
|
def get_events
|
|
123
152
|
return @client.get_events
|
|
124
153
|
end
|
|
@@ -268,27 +297,19 @@ private
|
|
|
268
297
|
|
|
269
298
|
end
|
|
270
299
|
|
|
271
|
-
|
|
272
|
-
#
|
|
273
|
-
# the appropriate queue.
|
|
300
|
+
# To run a standalone Rami server create a Server instance and then call it's run() method.
|
|
301
|
+
# The server will maintain one open connection to asterisk. It uses one thread to constantly read responses and stick them into
|
|
302
|
+
# the appropriate queue.
|
|
274
303
|
#
|
|
275
304
|
# The server uses two queues to hold responses from asterisk. The action queue holds all responses that contain an ActionID.
|
|
276
305
|
# The state queue holds all responses that do not have an ActionID. The action queue is only used internally, while the state
|
|
277
|
-
# queue can be queried via
|
|
306
|
+
# queue can be queried via Client.get_events and Client.find_events.
|
|
278
307
|
#
|
|
279
|
-
#
|
|
280
|
-
#
|
|
281
|
-
class
|
|
308
|
+
# For an example of how to run a standalone server, see bin/server.rb. For using the Server and Client classes together without
|
|
309
|
+
# starting a standalone server see the Client documentation.
|
|
310
|
+
class Server
|
|
282
311
|
# If set to 1, console logging is turned on. Default 0
|
|
283
312
|
attr_writer :console
|
|
284
|
-
# Asterisk manager username. Default asterisk.
|
|
285
|
-
attr_writer :username
|
|
286
|
-
# Asterisk manager secret. Default secret.
|
|
287
|
-
attr_writer :secret
|
|
288
|
-
# Asterisk manager hostname. Default localhost
|
|
289
|
-
attr_writer :host
|
|
290
|
-
# Asterisk manager port. Default 5038
|
|
291
|
-
attr_writer :port
|
|
292
313
|
# The number of responses to hold in the state queue. The state queue is a FIFO list. Default is 100.
|
|
293
314
|
attr_writer :event_cache
|
|
294
315
|
|
|
@@ -296,14 +317,24 @@ Thread.current.abort_on_exception=true
|
|
|
296
317
|
|
|
297
318
|
include DRbUndumped
|
|
298
319
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
320
|
+
# Takes a hash with the following keys:
|
|
321
|
+
# * host - hostname the AMI is running on
|
|
322
|
+
# * port - port number the AMI is running on
|
|
323
|
+
# * username - AMI username
|
|
324
|
+
# * secret - AMI secret
|
|
325
|
+
# * console - Set to 1 for console logging. Default is 0 (off)
|
|
326
|
+
# * event_cache - Number of responses to hold in the event queue. Default 100
|
|
327
|
+
#
|
|
328
|
+
# console and event_cache are also attributes, so they can be changed after calling Server.new
|
|
329
|
+
def initialize(options = {})
|
|
330
|
+
@console = options['console'] || 0
|
|
331
|
+
@username = options['username'] || 'asterisk'
|
|
332
|
+
@secret = options['secret'] || 'secret'
|
|
333
|
+
@host = options['host'] || 'localhost'
|
|
334
|
+
@port = options['port'] || 5038
|
|
335
|
+
@event_cache = options['event_cache'] || 100
|
|
336
|
+
|
|
305
337
|
@eventcount = 1
|
|
306
|
-
@event_cache = 100
|
|
307
338
|
|
|
308
339
|
@sock = nil
|
|
309
340
|
@socklock = nil
|
|
@@ -324,6 +355,12 @@ end
|
|
|
324
355
|
|
|
325
356
|
private
|
|
326
357
|
|
|
358
|
+
def logger(type,msg)
|
|
359
|
+
if @console == 1
|
|
360
|
+
print "#{Time.now} #{type} #{@eventcount}: #{msg}"
|
|
361
|
+
end
|
|
362
|
+
end
|
|
363
|
+
|
|
327
364
|
def connect
|
|
328
365
|
@sock = TCPSocket.new(@host,@port)
|
|
329
366
|
login = {'Action' => 'login', 'Username' => @username, 'Secret' => @secret, 'Events' => 'On'}
|
|
@@ -337,9 +374,7 @@ def connect
|
|
|
337
374
|
key,value = parseline(line) if line.include?(':')
|
|
338
375
|
accum[key] = value
|
|
339
376
|
end
|
|
340
|
-
|
|
341
|
-
print "#{Time.now} RECV #{@eventcount}: #{line}"
|
|
342
|
-
end
|
|
377
|
+
logger('RECV',"#{line}")
|
|
343
378
|
if line == "\r\n" and accum['Message'] == 'Authentication accepted' and accum['Response'] == 'Success'
|
|
344
379
|
login =1
|
|
345
380
|
@eventcount += 1
|
|
@@ -349,7 +384,7 @@ def connect
|
|
|
349
384
|
end
|
|
350
385
|
return true
|
|
351
386
|
end
|
|
352
|
-
rescue
|
|
387
|
+
rescue Timeout::Error => e
|
|
353
388
|
puts "LOGIN TIMEOUT"
|
|
354
389
|
return false
|
|
355
390
|
end
|
|
@@ -365,23 +400,17 @@ def mainloop
|
|
|
365
400
|
@sock.each("\r\n") do |line|
|
|
366
401
|
linecount += 1
|
|
367
402
|
type = 'state'
|
|
368
|
-
|
|
369
|
-
print "#{Time.now} RECV #{@eventcount}: #{line}"
|
|
370
|
-
end
|
|
403
|
+
logger('RECV', "#{line}")
|
|
371
404
|
if line == "\r\n"
|
|
372
405
|
if event.size == 0
|
|
373
|
-
|
|
374
|
-
print "#{Time.now} MSG: #{@eventcount} RECEIVED EXTRA CR/LF #{line}"
|
|
375
|
-
end
|
|
406
|
+
logger('MSG',"RECEIVED EXTRA CR/LF #{line}")
|
|
376
407
|
next
|
|
377
408
|
end
|
|
378
409
|
if event['ActionID']
|
|
379
410
|
type = 'action'
|
|
380
411
|
end
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
print "#{Time.now} MSG: #{@eventcount} finished (type=#{type}) #{line}"
|
|
384
|
-
end
|
|
412
|
+
|
|
413
|
+
logger('MSG',"finished (type=#{type}) #{line}")
|
|
385
414
|
|
|
386
415
|
if type == 'action'
|
|
387
416
|
@action_events.synchronize do
|
|
@@ -427,18 +456,15 @@ def parseline(line)
|
|
|
427
456
|
|
|
428
457
|
end
|
|
429
458
|
|
|
430
|
-
def writelog(msg)
|
|
431
|
-
print "#{Time.now} #{msg}\r\n"
|
|
432
|
-
end
|
|
433
459
|
|
|
434
460
|
def writesock(action)
|
|
435
461
|
@socklock.synchronize do
|
|
436
462
|
action.each do |key,value|
|
|
437
463
|
@sock.write("#{key}: #{value}\r\n")
|
|
438
|
-
|
|
464
|
+
logger('SEND',"#{key}: #{value}\r\n")
|
|
439
465
|
end
|
|
440
466
|
@sock.write("\r\n")
|
|
441
|
-
|
|
467
|
+
logger('SEND',"\r\n")
|
|
442
468
|
end
|
|
443
469
|
end
|
|
444
470
|
|
|
@@ -456,9 +482,9 @@ def run
|
|
|
456
482
|
mainloop
|
|
457
483
|
end
|
|
458
484
|
|
|
459
|
-
# Should only be called via
|
|
485
|
+
# Should only be called via Client
|
|
460
486
|
def find_events(key=nil,value=nil)
|
|
461
|
-
|
|
487
|
+
logger('find_events',"#{key}: #{value}")
|
|
462
488
|
found = []
|
|
463
489
|
@state_events.synchronize do
|
|
464
490
|
if @state_events.empty?
|
|
@@ -479,7 +505,7 @@ def find_events(key=nil,value=nil)
|
|
|
479
505
|
end
|
|
480
506
|
end
|
|
481
507
|
|
|
482
|
-
# Should only be called via
|
|
508
|
+
# Should only be called via Client
|
|
483
509
|
def get_events
|
|
484
510
|
found = []
|
|
485
511
|
@state_events.synchronize do
|
|
@@ -496,7 +522,7 @@ def get_events
|
|
|
496
522
|
end
|
|
497
523
|
end
|
|
498
524
|
|
|
499
|
-
# Should only be called via
|
|
525
|
+
# Should only be called via Client
|
|
500
526
|
def send_action(action=nil,t=10)
|
|
501
527
|
sent_id = action['ActionID'].to_s
|
|
502
528
|
result = []
|
metadata
CHANGED
|
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
|
|
|
3
3
|
specification_version: 1
|
|
4
4
|
name: rami
|
|
5
5
|
version: !ruby/object:Gem::Version
|
|
6
|
-
version: "0.
|
|
7
|
-
date: 2005-10-
|
|
6
|
+
version: "0.2"
|
|
7
|
+
date: 2005-10-20 00:00:00 -07:00
|
|
8
8
|
summary: A proxy server/client api for the Asterisk Manager Interface
|
|
9
9
|
require_paths:
|
|
10
10
|
- lib
|
|
@@ -31,10 +31,13 @@ authors:
|
|
|
31
31
|
files:
|
|
32
32
|
- README
|
|
33
33
|
- LICENSE
|
|
34
|
+
- CHANGELOG
|
|
34
35
|
- manager.txt
|
|
35
36
|
- lib/rami.rb
|
|
36
37
|
- bin/server.rb
|
|
37
38
|
- bin/test.rb
|
|
39
|
+
- bin/example1.rb
|
|
40
|
+
- bin/example2.rb
|
|
38
41
|
test_files: []
|
|
39
42
|
rdoc_options: []
|
|
40
43
|
extra_rdoc_files: []
|