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 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 = RamiServer.new
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
- ## The username and secret used to login to the Asterisk manager interface
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
- client = RamiClient.new
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','SIP/test_extension')
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
- # A proxy server/client api for the Asterisk Manager Interface
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 library. To use the library make sure the server has been started and then call RamiClient.new and set the
40
- # host, port, and timeout attributes. All methods return an array of hashes, or an empty array if no data is available.
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. It contains sample code for calling every available method.
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 RamiClient for
57
- # the new command, and then add a section in the RamiClient::send_action loop to harvest the response.
58
- class RamiClient
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
- def initialize
68
- @host = 'localhost'
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
- DRb.start_service()
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 RamiServer for more information on the queue structure.
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 RamiServer for more information on the queue structure.
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
- # RamiServer maintains one open connection to asterisk. It uses one thread to constantly read responses and stick them into
273
- # the appropriate queue. Clients connect via DRb and are each serviced in their own thread.
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 RamiClient.get_events and RamiClient.find_events.
306
+ # queue can be queried via Client.get_events and Client.find_events.
278
307
  #
279
- # To run the server, call RamiServer.new, set the attributes, then call the run method.
280
- # For an example of how to run the server, see bin/server.rb.
281
- class RamiServer
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
- def initialize
300
- @console = 0
301
- @username = 'asterisk'
302
- @secret = 'secret'
303
- @host = 'localhost'
304
- @port = 5038
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
- if @console == 1
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 Exception => e
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
- if @console == 1
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
- if @console == 1
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
- if @console == 1
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
- print "#{Time.now} SEND #{@eventcount}: #{key}: #{value}\r\n"
464
+ logger('SEND',"#{key}: #{value}\r\n")
439
465
  end
440
466
  @sock.write("\r\n")
441
- print "#{Time.now} SEND #{@eventcount}: \r\n"
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 Drb by RamiClient
485
+ # Should only be called via Client
460
486
  def find_events(key=nil,value=nil)
461
- print "#{Time.now} find_events: #{key}: #{value}\r\n"
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 Drb by RamiClient
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 Drb by RamiClient
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.1"
7
- date: 2005-10-17 00:00:00 -07:00
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: []