ruby_ami 1.0.1 → 1.1.1

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/.travis.yml CHANGED
@@ -3,10 +3,10 @@ rvm:
3
3
  - 1.9.2
4
4
  - 1.9.3
5
5
  - jruby-19mode
6
- - rbx-19mode
6
+ # - rbx-19mode
7
7
  - ruby-head
8
8
  before_install:
9
- - wget http://ftp.us.debian.org/debian/pool/main/r/ragel/ragel_6.7-1_i386.deb
10
- - sudo dpkg -i ragel_6.7-1_i386.deb
9
+ - wget http://ftp.us.debian.org/debian/pool/main/r/ragel/ragel_6.7-1.1_i386.deb
10
+ - sudo dpkg -i ragel_6.7-1.1_i386.deb
11
11
  notifications:
12
12
  irc: "irc.freenode.org#adhearsion"
data/CHANGELOG.md CHANGED
@@ -1,4 +1,10 @@
1
- # develop
1
+ # [develop](https://github.com/adhearsion/ruby_ami)
2
+
3
+ # [1.1.1](https://github.com/adhearsion/ruby_ami/compare/v1.1.0...v1.1.1) - [2012-06-25](https://rubygems.org/gems/ruby_ami/versions/1.1.1)
4
+ * v1.1.0 re-released with fixed celluloid-io dependency
5
+
6
+ # [1.1.0](https://github.com/adhearsion/ruby_ami/compare/v1.0.1...v1.1.0) - [2012-06-16](https://rubygems.org/gems/ruby_ami/versions/1.1.0)
7
+ * Change: Switch from EventMachine to Celluloid & CelluloidIO for better JRuby compatability and performance (action and events connections are now in separate threads)
2
8
 
3
9
  # 1.0.1 - 2012-04-25
4
10
  * Bugfix: Actions which do not receive a response within 10s will allow further actions to be executed. Synchronous originate has a 60s timeout.
data/lib/ruby_ami.rb CHANGED
@@ -1,18 +1,10 @@
1
1
  %w{
2
- active_support/dependencies/autoload
3
- active_support/core_ext/object/blank
4
- active_support/core_ext/numeric/time
5
- active_support/core_ext/numeric/bytes
6
- active_support/hash_with_indifferent_access
7
-
8
2
  uuidtools
9
- eventmachine
10
3
  future-resource
11
4
  logger
12
5
  girl_friday
13
6
  countdownlatch
14
-
15
- ruby_ami/metaprogramming
7
+ celluloid/io
16
8
  }.each { |f| require f }
17
9
 
18
10
  class Logger
@@ -20,14 +12,16 @@ class Logger
20
12
  end
21
13
 
22
14
  module RubyAMI
23
- extend ActiveSupport::Autoload
24
-
25
- autoload :Action
26
- autoload :Client
27
- autoload :Error
28
- autoload :Event
29
- autoload :Lexer
30
- autoload :Response
31
- autoload :Stream
32
- autoload :Version
33
15
  end
16
+
17
+ %w{
18
+ action
19
+ client
20
+ error
21
+ event
22
+ lexer
23
+ metaprogramming
24
+ response
25
+ stream
26
+ version
27
+ }.each { |f| require "ruby_ami/#{f}" }
@@ -9,7 +9,7 @@ module RubyAMI
9
9
 
10
10
  def initialize(name, headers = {}, &block)
11
11
  @name = name.to_s.downcase.freeze
12
- @headers = headers.stringify_keys.freeze
12
+ @headers = headers.freeze
13
13
  @action_id = UUIDTools::UUID.random_create.to_s
14
14
  @response = FutureResource.new
15
15
  @response_callback = block
@@ -121,7 +121,7 @@ module RubyAMI
121
121
  alias :== :eql?
122
122
 
123
123
  def sync_timeout
124
- name.downcase == 'originate' && !headers['async'] ? 60 : 10
124
+ name.downcase == 'originate' && !headers[:async] ? 60 : 10
125
125
  end
126
126
 
127
127
  ##
@@ -41,16 +41,20 @@ module RubyAMI
41
41
  end
42
42
 
43
43
  def start
44
- EventMachine.run do
45
- yield if block_given?
46
- @events_stream = start_stream lambda { |event| @event_processor << event }
47
- @actions_stream = start_stream lambda { |message| @message_processor << message }
48
- @state = :started
49
- end
44
+ @events_stream = start_stream lambda { |event| @event_processor << event }
45
+ @actions_stream = start_stream lambda { |message| @message_processor << message }
46
+ @state = :started
47
+ streams.each(&:join)
50
48
  end
51
49
 
52
50
  def stop
53
- streams.each { |s| s.close_connection_after_writing }
51
+ streams.each do |stream|
52
+ begin
53
+ stream.terminate
54
+ rescue => e
55
+ logger.error e if logger
56
+ end
57
+ end
54
58
  end
55
59
 
56
60
  def send_action(action, headers = {}, &block)
@@ -68,7 +72,7 @@ module RubyAMI
68
72
  login_actions
69
73
  when Stream::Disconnected
70
74
  stop_writing_actions
71
- unbind
75
+ stop
72
76
  when Event
73
77
  action = @current_action_with_causal_events
74
78
  if action
@@ -103,7 +107,7 @@ module RubyAMI
103
107
  when Stream::Connected
104
108
  login_events
105
109
  when Stream::Disconnected
106
- unbind
110
+ stop
107
111
  else
108
112
  pass_event event
109
113
  end
@@ -117,10 +121,6 @@ module RubyAMI
117
121
  action
118
122
  end
119
123
 
120
- def unbind
121
- EM.reactor_running? && EM.stop
122
- end
123
-
124
124
  private
125
125
 
126
126
  def pass_event(event)
@@ -179,7 +179,7 @@ module RubyAMI
179
179
  end
180
180
 
181
181
  def start_stream(callback)
182
- Stream.start @options[:host], @options[:port], callback
182
+ Stream.new @options[:host], @options[:port], callback
183
183
  end
184
184
 
185
185
  def logger
@@ -3,7 +3,7 @@ module RubyAMI
3
3
  attr_accessor :message, :action
4
4
 
5
5
  def initialize
6
- @headers = HashWithIndifferentAccess.new
6
+ @headers = Hash.new
7
7
  end
8
8
 
9
9
  def [](key)
@@ -1,3 +1,5 @@
1
+ require 'ruby_ami/response'
2
+
1
3
  module RubyAMI
2
4
  class Event < Response
3
5
  attr_reader :name
@@ -6,5 +8,9 @@ module RubyAMI
6
8
  super()
7
9
  @name = name
8
10
  end
11
+
12
+ def inspect_attributes
13
+ [:name] + super
14
+ end
9
15
  end
10
16
  end # RubyAMI
@@ -1,7 +1,8 @@
1
1
  module RubyAMI
2
2
  class Lexer
3
3
 
4
- BUFFER_SIZE = 128.kilobytes unless defined? BUFFER_SIZE
4
+ KILOBYTE = 1024
5
+ BUFFER_SIZE = 128 * KILOBYTE unless defined? BUFFER_SIZE
5
6
 
6
7
  ##
7
8
  # IMPORTANT! See method documentation for adjust_pointers!
@@ -18,7 +18,7 @@ module RubyAMI
18
18
  attr_reader :events
19
19
 
20
20
  def initialize
21
- @headers = HashWithIndifferentAccess.new
21
+ @headers = Hash.new
22
22
  end
23
23
 
24
24
  def has_text_body?
@@ -30,15 +30,28 @@ module RubyAMI
30
30
  end
31
31
 
32
32
  def [](arg)
33
- @headers[arg]
33
+ @headers[arg.to_s]
34
34
  end
35
35
 
36
36
  def []=(key,value)
37
- @headers[key] = value
37
+ @headers[key.to_s] = value
38
38
  end
39
39
 
40
40
  def action_id
41
41
  @headers['ActionID']
42
42
  end
43
+
44
+ def inspect
45
+ "#<#{self.class} #{inspect_attributes.map { |c| "#{c}=#{self.__send__(c).inspect rescue nil}" }.compact * ', '}>"
46
+ end
47
+
48
+ def inspect_attributes
49
+ [:headers, :text_body, :events, :action]
50
+ end
51
+
52
+ def eql?(o, *fields)
53
+ o.is_a?(self.class) && (fields + inspect_attributes).all? { |f| self.__send__(f) == o.__send__(f) }
54
+ end
55
+ alias :== :eql?
43
56
  end
44
57
  end # RubyAMI
@@ -1,5 +1,5 @@
1
1
  module RubyAMI
2
- class Stream < EventMachine::Connection
2
+ class Stream
3
3
  class ConnectionStatus
4
4
  def eql?(other)
5
5
  other.is_a? self.class
@@ -11,50 +11,64 @@ module RubyAMI
11
11
  Connected = Class.new ConnectionStatus
12
12
  Disconnected = Class.new ConnectionStatus
13
13
 
14
- def self.start(host, port, event_callback)
15
- EM.connect host, port, self, event_callback
16
- end
14
+ include Celluloid::IO
17
15
 
18
- def initialize(event_callback)
16
+ def initialize(host, port, event_callback)
19
17
  super()
20
18
  @event_callback = event_callback
21
- @logger = Logger.new($stdout)
22
- @logger.level = Logger::FATAL
23
- @logger.debug "Starting up..."
19
+ logger.debug "Starting up..."
24
20
  @lexer = Lexer.new self
21
+ @socket = TCPSocket.from_ruby_socket ::TCPSocket.new(host, port)
22
+ post_init
23
+ run!
25
24
  end
26
25
 
27
26
  [:started, :stopped, :ready].each do |state|
28
27
  define_method("#{state}?") { @state == state }
29
28
  end
30
29
 
30
+ def run
31
+ loop { receive_data @socket.readpartial(4096) }
32
+ rescue EOFError
33
+ logger.info "Client socket closed!"
34
+ current_actor.terminate!
35
+ end
36
+
31
37
  def post_init
32
38
  @state = :started
33
39
  @event_callback.call Connected.new
34
40
  end
35
41
 
42
+ def send_data(data)
43
+ @socket.write data
44
+ end
45
+
36
46
  def send_action(action)
37
- @logger.debug "[SEND] #{action.to_s}"
47
+ logger.debug "[SEND] #{action.to_s}"
38
48
  send_data action.to_s
39
49
  end
40
50
 
41
51
  def receive_data(data)
42
- @logger.debug "[RECV] #{data}"
52
+ logger.debug "[RECV] #{data}"
43
53
  @lexer << data
44
54
  end
45
55
 
46
56
  def message_received(message)
47
- @logger.debug "[RECV] #{message.inspect}"
57
+ logger.debug "[RECV] #{message.inspect}"
48
58
  @event_callback.call message
49
59
  end
50
60
 
51
61
  alias :error_received :message_received
52
62
 
53
- # Called by EM when the connection is closed
54
- # @private
55
- def unbind
63
+ def finalize
64
+ logger.debug "Finalizing stream"
65
+ @socket.close if @socket
56
66
  @state = :stopped
57
67
  @event_callback.call Disconnected.new
58
68
  end
69
+
70
+ def logger
71
+ Logger
72
+ end
59
73
  end
60
74
  end
@@ -1,3 +1,3 @@
1
1
  module RubyAMI
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.1"
3
3
  end
data/ruby_ami.gemspec CHANGED
@@ -18,13 +18,11 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
20
 
21
- s.add_runtime_dependency %q<activesupport>, ["~> 3.0"]
22
21
  s.add_runtime_dependency %q<uuidtools>, [">= 0"]
23
- s.add_runtime_dependency %q<eventmachine>, [">= 0"]
22
+ s.add_runtime_dependency %q<celluloid-io>, ["~> 0.11.0"]
24
23
  s.add_runtime_dependency %q<future-resource>, [">= 0"]
25
24
  s.add_runtime_dependency %q<girl_friday>, [">= 0"]
26
25
  s.add_runtime_dependency %q<countdownlatch>, ["~> 1.0"]
27
- s.add_runtime_dependency %q<i18n>, [">= 0"]
28
26
 
29
27
  s.add_development_dependency %q<bundler>, ["~> 1.0"]
30
28
  s.add_development_dependency %q<rspec>, [">= 2.5.0"]
@@ -26,11 +26,11 @@ module RubyAMI
26
26
 
27
27
  describe 'starting up' do
28
28
  before do
29
- MockServer.any_instance.stubs :receive_data
30
- subject.start do
31
- EM.start_server options[:host], options[:port], ServerMock
32
- EM.add_timer(0.5) { EM.stop if EM.reactor_running? }
33
- end
29
+ ms = MockServer.new
30
+ ms.expects(:receive_data).at_least_once
31
+ s = ServerMock.new options[:host], options[:port], ms
32
+ Thread.new { subject.start }
33
+ sleep 0.2
34
34
  end
35
35
 
36
36
  it { should be_started }
@@ -89,8 +89,8 @@ module RubyAMI
89
89
  end
90
90
 
91
91
  describe 'when the events stream disconnects' do
92
- it 'should unbind' do
93
- subject.expects(:unbind).once
92
+ it 'should stop' do
93
+ subject.expects(:stop).once
94
94
  subject.handle_event Stream::Disconnected.new
95
95
  event_handler.should be_empty
96
96
  end
@@ -117,8 +117,8 @@ module RubyAMI
117
117
  action.should be_new
118
118
  end
119
119
 
120
- it 'should unbind' do
121
- subject.expects(:unbind).once
120
+ it 'should stop' do
121
+ subject.expects(:stop).once
122
122
  subject.handle_message Stream::Disconnected.new
123
123
  end
124
124
  end
@@ -340,27 +340,9 @@ module RubyAMI
340
340
  end
341
341
 
342
342
  it 'should close both streams' do
343
- streams.each { |s| s.expects :close_connection_after_writing }
343
+ streams.each { |s| s.expects :terminate }
344
344
  subject.stop
345
345
  end
346
346
  end
347
-
348
- describe '#unbind' do
349
- context 'if EM is running' do
350
- it 'shuts down EM' do
351
- EM.expects(:reactor_running?).returns true
352
- EM.expects(:stop)
353
- subject.unbind
354
- end
355
- end
356
-
357
- context 'if EM is not running' do
358
- it 'does nothing' do
359
- EM.expects(:reactor_running?).returns false
360
- EM.expects(:stop).never
361
- subject.unbind
362
- end
363
- end
364
- end
365
347
  end
366
348
  end
@@ -2,6 +2,72 @@ require 'spec_helper'
2
2
 
3
3
  module RubyAMI
4
4
  describe Event do
5
- pending
5
+ describe "equality" do
6
+ context "with the same name and the same headers" do
7
+ let :event1 do
8
+ Event.new('Hangup').tap do |e|
9
+ e['Channel'] = 'SIP/101-3f3f'
10
+ e['Uniqueid'] = '1094154427.10'
11
+ e['Cause'] = '0'
12
+ end
13
+ end
14
+
15
+ let :event2 do
16
+ Event.new('Hangup').tap do |e|
17
+ e['Channel'] = 'SIP/101-3f3f'
18
+ e['Uniqueid'] = '1094154427.10'
19
+ e['Cause'] = '0'
20
+ end
21
+ end
22
+
23
+ it "should be equal" do
24
+ event1.should be == event2
25
+ end
26
+ end
27
+
28
+ context "with a different name and the same headers" do
29
+ let :event1 do
30
+ Event.new('Hangup').tap do |e|
31
+ e['Channel'] = 'SIP/101-3f3f'
32
+ e['Uniqueid'] = '1094154427.10'
33
+ e['Cause'] = '0'
34
+ end
35
+ end
36
+
37
+ let :event2 do
38
+ Event.new('Foo').tap do |e|
39
+ e['Channel'] = 'SIP/101-3f3f'
40
+ e['Uniqueid'] = '1094154427.10'
41
+ e['Cause'] = '0'
42
+ end
43
+ end
44
+
45
+ it "should not be equal" do
46
+ event1.should_not be == event2
47
+ end
48
+ end
49
+
50
+ context "with the same name and different headers" do
51
+ let :event1 do
52
+ Event.new('Hangup').tap do |e|
53
+ e['Channel'] = 'SIP/101-3f3f'
54
+ e['Uniqueid'] = '1094154427.10'
55
+ e['Cause'] = '0'
56
+ end
57
+ end
58
+
59
+ let :event2 do
60
+ Event.new('Hangup').tap do |e|
61
+ e['Channel'] = 'SIP/101-3f3f'
62
+ e['Uniqueid'] = '1094154427.10'
63
+ e['Cause'] = '1'
64
+ end
65
+ end
66
+
67
+ it "should not be equal" do
68
+ event1.should_not be == event2
69
+ end
70
+ end
71
+ end
6
72
  end # Event
7
73
  end # RubyAMI
@@ -2,6 +2,50 @@ require 'spec_helper'
2
2
 
3
3
  module RubyAMI
4
4
  describe Response do
5
- pending
5
+ describe "equality" do
6
+ context "with the same headers" do
7
+ let :event1 do
8
+ Response.new.tap do |e|
9
+ e['Channel'] = 'SIP/101-3f3f'
10
+ e['Uniqueid'] = '1094154427.10'
11
+ e['Cause'] = '0'
12
+ end
13
+ end
14
+
15
+ let :event2 do
16
+ Response.new.tap do |e|
17
+ e['Channel'] = 'SIP/101-3f3f'
18
+ e['Uniqueid'] = '1094154427.10'
19
+ e['Cause'] = '0'
20
+ end
21
+ end
22
+
23
+ it "should be equal" do
24
+ event1.should be == event2
25
+ end
26
+ end
27
+
28
+ context "with different headers" do
29
+ let :event1 do
30
+ Response.new.tap do |e|
31
+ e['Channel'] = 'SIP/101-3f3f'
32
+ e['Uniqueid'] = '1094154427.10'
33
+ e['Cause'] = '0'
34
+ end
35
+ end
36
+
37
+ let :event2 do
38
+ Response.new.tap do |e|
39
+ e['Channel'] = 'SIP/101-3f3f'
40
+ e['Uniqueid'] = '1094154427.10'
41
+ e['Cause'] = '1'
42
+ end
43
+ end
44
+
45
+ it "should not be equal" do
46
+ event1.should_not be == event2
47
+ end
48
+ end
49
+ end
6
50
  end # Response
7
51
  end # RubyAMI
@@ -2,21 +2,33 @@ require 'spec_helper'
2
2
 
3
3
  module RubyAMI
4
4
  describe Stream do
5
- def mocked_server(times = nil, fake_client = nil, &block)
6
- MockServer.any_instance.expects(:receive_data).send(*(times ? [:times, times] : [:at_least, 1])).with &block
7
- EventMachine::run {
8
- EM.add_timer(0.5) { EM.stop if EM.reactor_running? }
5
+ let(:server_port) { 50000 - rand(1000) }
9
6
 
10
- port = 50000 - rand(1000)
7
+ before do
8
+ def client.message_received(message)
9
+ @messages ||= Queue.new
10
+ @messages << message
11
+ end
11
12
 
12
- # Mocked server
13
- EventMachine::start_server '127.0.0.1', port, ServerMock
13
+ def client.messages
14
+ @messages
15
+ end
16
+ end
14
17
 
15
- # Stream connection
16
- EM.connect('127.0.0.1', port, Stream, lambda { |m| client.message_received m }) {|c| @stream = c}
18
+ let :client_messages do
19
+ messages = []
20
+ messages << client.messages.pop until client.messages.empty?
21
+ messages
22
+ end
17
23
 
18
- fake_client.call if fake_client.respond_to? :call
19
- }
24
+ def mocked_server(times = nil, fake_client = nil, &block)
25
+ mock_target = MockServer.new
26
+ mock_target.expects(:receive_data).send(*(times ? [:times, times] : [:at_least, 1])).with &block
27
+ s = ServerMock.new '127.0.0.1', server_port, mock_target
28
+ @stream = Stream.new '127.0.0.1', server_port, lambda { |m| client.message_received m }
29
+ fake_client.call if fake_client.respond_to? :call
30
+ s.join
31
+ @stream.join
20
32
  end
21
33
 
22
34
  def expect_connected_event
@@ -29,22 +41,11 @@ module RubyAMI
29
41
 
30
42
  before { @sequence = 1 }
31
43
 
32
- it 'can be started' do
33
- EM.expects(:connect).with do |*params|
34
- params[0].should == 'example.com'
35
- params[1].should == 1234
36
- params[2].should == Stream
37
- params[3].should be_a Proc
38
- end
39
-
40
- Stream.start 'example.com', 1234, lambda {}
41
- end
42
-
43
44
  describe "after connection" do
44
45
  it "should be started" do
45
46
  expect_connected_event
46
47
  expect_disconnected_event
47
- mocked_server(1, lambda { @stream.send_data 'Foo' }) do |val, server|
48
+ mocked_server(0) do |val, server|
48
49
  @stream.started?.should be_true
49
50
  end
50
51
  end
@@ -60,23 +61,6 @@ module RubyAMI
60
61
  end
61
62
 
62
63
  it 'sends events to the client when the stream is ready' do
63
- client.expects(:message_received).times(3).with do |e|
64
- case @sequence
65
- when 1
66
- e.should be_a Stream::Connected
67
- when 2
68
- EM.stop
69
- e.should be_a Event
70
- e.name.should == 'Hangup'
71
- e['Channel'].should == 'SIP/101-3f3f'
72
- e['Uniqueid'].should == '1094154427.10'
73
- e['Cause'].should == '0'
74
- when 3
75
- e.should be_a Stream::Disconnected
76
- end
77
- @sequence += 1
78
- end
79
-
80
64
  mocked_server(1, lambda { @stream.send_data 'Foo' }) do |val, server|
81
65
  server.send_data <<-EVENT
82
66
  Event: Hangup
@@ -86,24 +70,19 @@ Cause: 0
86
70
 
87
71
  EVENT
88
72
  end
73
+
74
+ client_messages.should be == [
75
+ Stream::Connected.new,
76
+ Event.new('Hangup').tap do |e|
77
+ e['Channel'] = 'SIP/101-3f3f'
78
+ e['Uniqueid'] = '1094154427.10'
79
+ e['Cause'] = '0'
80
+ end,
81
+ Stream::Disconnected.new
82
+ ]
89
83
  end
90
84
 
91
85
  it 'sends responses to the client when the stream is ready' do
92
- client.expects(:message_received).times(3).with do |r|
93
- case @sequence
94
- when 1
95
- r.should be_a Stream::Connected
96
- when 2
97
- EM.stop
98
- r.should be_a Response
99
- r['ActionID'].should == 'ee33eru2398fjj290'
100
- r['Message'].should == 'Authentication accepted'
101
- when 3
102
- r.should be_a Stream::Disconnected
103
- end
104
- @sequence += 1
105
- end
106
-
107
86
  mocked_server(1, lambda { @stream.send_data 'Foo' }) do |val, server|
108
87
  server.send_data <<-EVENT
109
88
  Response: Success
@@ -112,6 +91,15 @@ Message: Authentication accepted
112
91
 
113
92
  EVENT
114
93
  end
94
+
95
+ client_messages.should be == [
96
+ Stream::Connected.new,
97
+ Response.new.tap do |r|
98
+ r['ActionID'] = 'ee33eru2398fjj290'
99
+ r['Message'] = 'Authentication accepted'
100
+ end,
101
+ Stream::Disconnected.new
102
+ ]
115
103
  end
116
104
 
117
105
  it 'sends error to the client when the stream is ready and a bad command was send' do
@@ -120,7 +108,6 @@ Message: Authentication accepted
120
108
  when 1
121
109
  r.should be_a Stream::Connected
122
110
  when 2
123
- EM.stop
124
111
  r.should be_a Error
125
112
  r['ActionID'].should == 'ee33eru2398fjj290'
126
113
  r['Message'].should == 'You stupid git'
@@ -144,10 +131,9 @@ Message: You stupid git
144
131
  expect_connected_event
145
132
  expect_disconnected_event
146
133
  mocked_server(1, lambda { @stream.send_data 'Foo' }) do |val, server|
147
- EM.stop
148
134
  @stream.stopped?.should be false
149
135
  end
150
- @stream.stopped?.should be true
136
+ @stream.alive?.should be false
151
137
  end
152
138
  end
153
139
  end
@@ -1,13 +1,41 @@
1
1
  MockServer = Class.new
2
2
 
3
- module ServerMock
3
+ class ServerMock
4
+ include Celluloid::IO
5
+
6
+ def initialize(host, port, mock_target = MockServer.new)
7
+ puts "*** Starting echo server on #{host}:#{port}"
8
+ @server = TCPServer.new host, port
9
+ @mock_target = mock_target
10
+ @clients = []
11
+ run!
12
+ end
13
+
14
+ def finalize
15
+ Logger.debug "ServerMock finalizing"
16
+ @server.close if @server
17
+ @clients.each(&:close)
18
+ end
19
+
20
+ def run
21
+ after(0.5) { terminate }
22
+ loop { handle_connection! @server.accept }
23
+ end
24
+
25
+ def handle_connection(socket)
26
+ @clients << socket
27
+ _, port, host = socket.peeraddr
28
+ puts "*** Received connection from #{host}:#{port}"
29
+ loop { receive_data socket.readpartial(4096) }
30
+ end
31
+
4
32
  def receive_data(data)
5
- @server ||= MockServer.new
6
- @server.receive_data data, self
33
+ Logger.debug "ServerMock receiving data: #{data}"
34
+ @mock_target.receive_data data, self
7
35
  end
8
36
 
9
37
  def send_data(data)
10
- super data.gsub("\n", "\r\n")
38
+ @clients.each { |client| client.write data.gsub("\n", "\r\n") }
11
39
  end
12
40
  end
13
41
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_ami
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,24 +9,8 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-25 00:00:00.000000000 Z
12
+ date: 2012-06-25 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: activesupport
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ~>
20
- - !ruby/object:Gem::Version
21
- version: '3.0'
22
- type: :runtime
23
- prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ~>
28
- - !ruby/object:Gem::Version
29
- version: '3.0'
30
14
  - !ruby/object:Gem::Dependency
31
15
  name: uuidtools
32
16
  requirement: !ruby/object:Gem::Requirement
@@ -44,21 +28,21 @@ dependencies:
44
28
  - !ruby/object:Gem::Version
45
29
  version: '0'
46
30
  - !ruby/object:Gem::Dependency
47
- name: eventmachine
31
+ name: celluloid-io
48
32
  requirement: !ruby/object:Gem::Requirement
49
33
  none: false
50
34
  requirements:
51
- - - ! '>='
35
+ - - ~>
52
36
  - !ruby/object:Gem::Version
53
- version: '0'
37
+ version: 0.11.0
54
38
  type: :runtime
55
39
  prerelease: false
56
40
  version_requirements: !ruby/object:Gem::Requirement
57
41
  none: false
58
42
  requirements:
59
- - - ! '>='
43
+ - - ~>
60
44
  - !ruby/object:Gem::Version
61
- version: '0'
45
+ version: 0.11.0
62
46
  - !ruby/object:Gem::Dependency
63
47
  name: future-resource
64
48
  requirement: !ruby/object:Gem::Requirement
@@ -107,22 +91,6 @@ dependencies:
107
91
  - - ~>
108
92
  - !ruby/object:Gem::Version
109
93
  version: '1.0'
110
- - !ruby/object:Gem::Dependency
111
- name: i18n
112
- requirement: !ruby/object:Gem::Requirement
113
- none: false
114
- requirements:
115
- - - ! '>='
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :runtime
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
- requirements:
123
- - - ! '>='
124
- - !ruby/object:Gem::Version
125
- version: '0'
126
94
  - !ruby/object:Gem::Dependency
127
95
  name: bundler
128
96
  requirement: !ruby/object:Gem::Requirement
@@ -324,7 +292,6 @@ files:
324
292
  - features/support/introspective_lexer.rb
325
293
  - features/support/lexer_helper.rb
326
294
  - lib/ruby_ami.rb
327
- - lib/ruby_ami/Guardfile
328
295
  - lib/ruby_ami/action.rb
329
296
  - lib/ruby_ami/client.rb
330
297
  - lib/ruby_ami/error.rb
@@ -359,7 +326,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
359
326
  version: '0'
360
327
  segments:
361
328
  - 0
362
- hash: -2979332282969643621
329
+ hash: 3703213424052847614
363
330
  required_rubygems_version: !ruby/object:Gem::Requirement
364
331
  none: false
365
332
  requirements:
@@ -368,10 +335,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
368
335
  version: '0'
369
336
  segments:
370
337
  - 0
371
- hash: -2979332282969643621
338
+ hash: 3703213424052847614
372
339
  requirements: []
373
340
  rubyforge_project: ruby_ami
374
- rubygems_version: 1.8.21
341
+ rubygems_version: 1.8.24
375
342
  signing_key:
376
343
  specification_version: 3
377
344
  summary: Futzing with AMI so you don't have to
@@ -1,6 +0,0 @@
1
- ENV['SKIP_RCOV'] = 'true'
2
- guard 'rspec', :version => 2, :cli => '--format documentation' do
3
- watch(%r{^spec/.+_spec\.rb$})
4
- watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
5
- watch('spec/spec_helper.rb') { "spec/" }
6
- end