ionian 0.6.12 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -103,7 +103,7 @@
103
103
  </div>
104
104
 
105
105
  <div id="footer">
106
- Generated on Mon Jan 26 21:45:48 2015 by
106
+ Generated on Wed Jan 28 16:07:19 2015 by
107
107
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
108
108
  0.8.7.6 (ruby-2.1.5).
109
109
  </div>
@@ -1,6 +1,7 @@
1
1
  require 'ionian/extension/io'
2
2
  require 'ionian/extension/socket'
3
3
  require 'ionian/socket'
4
+ require 'ionian/managed_socket'
4
5
  require 'ionian/server'
5
6
 
6
7
  # A library to simplify interaction with IO streams.
@@ -39,7 +39,7 @@ module Ionian
39
39
  ::IO.select([self], nil, nil, timeout) ? true : false
40
40
  end
41
41
 
42
- # Returns the regular expression used for {#read_match}.
42
+ # @return [Regexp] Regular expression used for {#read_match}.
43
43
  def expression
44
44
  @ionian_expression
45
45
  end
@@ -84,8 +84,8 @@ module Ionian
84
84
  # @yieldparam match [MatchData] If there are multiple matches, the block
85
85
  # is called multiple times.
86
86
  #
87
- # @return [Array<MatchData>, nil] Returns an array of matches.
88
- # Returns nil if no data was received within the timeout period.
87
+ # @return [Array<MatchData>, nil] matches.
88
+ # Nil if no data was received within the timeout period.
89
89
  #
90
90
  #
91
91
  # @option kwargs [Numeric] :timeout (nil) Timeout in seconds IO::select
@@ -114,16 +114,23 @@ module Ionian
114
114
  exp = Regexp.new "(.*?)#{exp}" if exp.is_a? String
115
115
 
116
116
  unless skip_select
117
- return nil unless ::IO.select [self], nil, nil, timeout
117
+ return nil unless self.has_data? timeout: timeout
118
118
  end
119
119
 
120
- # Read data from the IO buffer until it's empty.
121
- @ionian_buf << read_all
122
-
123
120
  @matches = []
124
121
 
122
+ # TODO: Implement an option for number of bytes or timeout to throw away
123
+ # data if no match is found.
124
+ Timeout.timeout(timeout) do
125
+ loop do
126
+ # Read data from the IO buffer until it's empty.
127
+ @ionian_buf << read_all
128
+ break if @ionian_buf =~ exp
129
+ end
130
+ end
131
+
125
132
  while @ionian_buf =~ exp
126
- @matches << $~ # Match data.
133
+ @matches << $~ # Match data.
127
134
  @ionian_buf = $' # Leave post match data in the buffer.
128
135
  end
129
136
 
@@ -155,6 +162,7 @@ module Ionian
155
162
  # This method SHOULD NOT be used if {#read_match} is used.
156
163
  def run_match **kwargs
157
164
  @run_match_thread ||= Thread.new do
165
+ Thread.current.thread_variable_set :match_thread_running, true
158
166
  begin
159
167
  while not closed? do
160
168
  matches = read_match **kwargs
@@ -168,6 +176,14 @@ module Ionian
168
176
  end
169
177
  end
170
178
 
179
+ def run_match_is_running?
180
+ return true if \
181
+ @run_match_thread and
182
+ @run_match_thread.thread_variable_get(:match_thread_running)
183
+
184
+ false
185
+ end
186
+
171
187
  # Erase the data in the IO and Ionian buffers.
172
188
  # This is typically handled automatically.
173
189
  def purge
@@ -195,6 +211,7 @@ module Ionian
195
211
 
196
212
  # @deprecated Use {#register_match_handler} instead.
197
213
  def register_observer &block
214
+ STDOUT.puts "WARN: Call to deprecated method #{__method__}"
198
215
  register_match_handler &block
199
216
  end
200
217
 
@@ -206,6 +223,7 @@ module Ionian
206
223
 
207
224
  # @deprecated Use {#unregister_match_handler} instead.
208
225
  def unregister_observer &block
226
+ STDOUT.puts "WARN: Call to deprecated method #{__method__}"
209
227
  unregister_match_handler &block
210
228
  end
211
229
 
@@ -55,13 +55,11 @@ module Ionian
55
55
  # immediately and try to deliver any data in the send buffer if value
56
56
  # is true.
57
57
  #
58
- # Args:
59
- # Time: Time in seconds to remain open before discarding data and
60
- # sending a RST packet.
58
+ # @param time [Fixnum] Time in seconds to remain open before discarding
59
+ # data and sending a RST packet.
60
+ #
61
61
  # ( SO_LINGER )
62
62
  def linger= enable, time: 60
63
- # TODO: Passing a kwarg doesn't work here because of the
64
- # assignment operator. Causes parser error.
65
63
  param = (!!enable && enable != 0) ? 1 : 0
66
64
  self.setsockopt ::Socket::SOL_SOCKET, ::Socket::SO_LINGER, [param, time.to_i].pack('ii')
67
65
  end
@@ -231,49 +229,51 @@ module Ionian
231
229
 
232
230
  # Not yet implemented.
233
231
  def ipv6_add_membership
234
- # TODO: Implement
235
- false
232
+ # TODO: Implement IPv6
233
+ raise NotImplementedError
236
234
  end
237
235
 
238
236
  # Not yet implemented.
239
237
  def ipv6_drop_membership
240
- # TODO: Implement
241
- false
238
+ # TODO: Implement IPv6
239
+ raise NotImplementedError
242
240
  end
243
241
 
244
242
  # Not yet implemented.
245
243
  def ipv6_multicast_if
246
- # TODO: Implement
247
- false
244
+ # TODO: Implement IPv6
245
+ raise NotImplementedError
248
246
  end
249
247
 
250
248
  # Not yet implemented.
251
249
  def ipv6_multicast_if= value
252
- # TODO: Implement
250
+ # TODO: Implement IPv6
253
251
  end
254
252
 
255
253
  # Not yet implemented.
256
254
  def ipv6_multicast_hops
257
- # TODO: Implement
258
- false
255
+ # TODO: Implement IPv6
256
+ raise NotImplementedError
259
257
  end
260
258
 
261
259
  # Not yet implemented.
262
260
  def ipv6_multicast_hops= value
263
- # TODO: Implement
261
+ # TODO: Implement IPv6
262
+ raise NotImplementedError
264
263
  end
265
264
 
266
265
  # Not yet implemented.
267
266
  def ipv6_multicast_loop
268
- # TODO: Implement
269
- false
267
+ # TODO: Implement IPv6
268
+ raise NotImplementedError
270
269
  end
271
270
 
272
271
  alias_method :ipv6_multicast_loop?, :ipv6_multicast_loop
273
272
 
274
273
  # Not yet implemented.
275
274
  def ipv6_multicast_loop= value
276
- # TODO: Implement
275
+ # TODO: Implement IPv6
276
+ raise NotImplementedError
277
277
  end
278
278
 
279
279
 
@@ -0,0 +1,109 @@
1
+ require 'ionian/socket'
2
+
3
+ module Ionian
4
+
5
+ # A socket manager that wraps an {Ionian::Socket} and can perform functions
6
+ # like heartbeating and auto-reconnect.
7
+ class ManagedSocket
8
+
9
+ # When true, automatically reconnect if the socket closes.
10
+ attr_reader :auto_reconnect
11
+
12
+ # @option kwargs [Boolean] :auto_reconnect (false) Automatically reconnect
13
+ # if the socket closes. Must call {#close} to break the auto-reconnect
14
+ # loop.
15
+ #
16
+ # @see Ionian::Socket#initialize More optional parameters.
17
+ def initialize **kwargs
18
+ @auto_reconnect = kwargs.delete(:auto_reconnect) || false
19
+ @kwargs = kwargs
20
+
21
+ @match_handlers = []
22
+ @error_handlers = []
23
+
24
+ create_socket
25
+ end
26
+
27
+ # Close the socket.
28
+ # Disables :auto_reconnect.
29
+ def close
30
+ @auto_reconnect = false
31
+ @socket.close unless @socket.closed?
32
+ end
33
+
34
+ # Register a block to be called when {Ionian::Extension::IO#run_match}
35
+ # receives matched data.
36
+ # Method callbacks can be registered with &object.method(:method).
37
+ # @return [Block] The given block.
38
+ # @yield [MatchData, self]
39
+ def register_match_handler &block
40
+ @match_handlers << block unless @match_handlers.include? block
41
+ @socket.register_match_handler &block if @socket
42
+ block
43
+ end
44
+
45
+ alias_method :on_match, :register_match_handler
46
+
47
+ # Unregister a block from being called when matched data is received.
48
+ def unregister_match_handler &block
49
+ @match_handlers.delete_if { |o| o == block }
50
+ @socket.unregister_match_handler &block if @socket
51
+ block
52
+ end
53
+
54
+ # Register a block to be called when {Ionian::Extension::IO#run_match}
55
+ # raises an error.
56
+ # Method callbacks can be registered with &object.method(:method).
57
+ # @return [Block] a reference to the given block.
58
+ # @yield [Exception, self]
59
+ def register_error_handler &block
60
+ @error_handlers << block unless @error_handlers.include? block
61
+ @socket.register_error_handler &block if @socket
62
+ block
63
+ end
64
+
65
+ alias_method :on_error, :register_error_handler
66
+
67
+ # Unregister a block from being called when a {Ionian::IO#run_match} error
68
+ # is raised.
69
+ def unregister_error_handler &block
70
+ @error_handlers.delete_if { |o| o == block }
71
+ @socket.unregister_error_handler &block if @socket
72
+ block
73
+ end
74
+
75
+ # Pass unhandled methods to @socket.
76
+ # @see Ionian::Socket
77
+ def method_missing meth, *args, &block
78
+ @socket.__send__ meth, *args, &block
79
+ end
80
+
81
+ def respond_to_missing? meth, *args
82
+ @socket.respond_to? meth, *args
83
+ end
84
+
85
+
86
+ private
87
+
88
+ # Initialize or reinitialize @socket.
89
+ def create_socket
90
+ @socket = Ionian::Socket.new **@kwargs
91
+ @socket.on_error &method(:socket_error_handler)
92
+ @match_handlers.each { |h| @socket.register_match_handler &h }
93
+ @error_handlers.each { |h| @socket.register_error_handler &h }
94
+
95
+ @socket.run_match
96
+ end
97
+
98
+ # {Ionian::Socket#on_error} handler for @socket.
99
+ def socket_error_handler e, socket
100
+ if auto_reconnect
101
+ @socket.close unless @socket.closed?
102
+ create_socket
103
+ else
104
+ raise e unless e.is_a? EOFError or e.is_a? IOError
105
+ end
106
+ end
107
+
108
+ end
109
+ end
@@ -1,3 +1,4 @@
1
+ require 'timeout'
1
2
  require 'ionian/extension/socket'
2
3
 
3
4
  module Ionian
@@ -19,6 +20,17 @@ module Ionian
19
20
  attr_reader :protocol
20
21
  alias_method :protocol?, :protocol
21
22
 
23
+ # @return [Ionian::Socket] a broadcast socket.
24
+ #
25
+ # @option kwargs [Fixnum] :port Port to broadcast on.
26
+ # @option kwargs [String] :address ('255.255.255.255') Address to broadcast on.
27
+ #
28
+ # @see #initialize Full list of socket options.
29
+ def self.create_broadcast_socket **kwargs
30
+ kwargs[:host] = kwargs.delete(:address) || '255.255.255.255'
31
+ kwargs[:broadcast] = true
32
+ new **kwargs
33
+ end
22
34
 
23
35
  # Creates a new socket or wraps an existing socket.
24
36
  #
@@ -76,7 +88,8 @@ module Ionian
76
88
  def initialize existing_socket = nil, **kwargs, &block
77
89
  @socket = existing_socket
78
90
 
79
- @ionian_listeners = []
91
+ @ionian_match_handlers = []
92
+ @ionian_error_handlers = []
80
93
 
81
94
  @expression = kwargs.fetch :expression, nil
82
95
 
@@ -192,31 +205,64 @@ module Ionian
192
205
  matches
193
206
  end
194
207
 
195
- # Register a block to be called when #run_match receives matched data.
208
+ # Register a block to be called when {Ionian::Extension::IO#run_match}
209
+ # receives matched data.
196
210
  # Method callbacks can be registered with &object.method(:method).
197
- # Returns a reference to the given block.
198
- # block = ionian_socket.register_observer { ... }
199
- def register_observer &block
200
- @ionian_listeners << block unless @ionian_listeners.include? block
201
- @socket.register_observer &block if @socket
211
+ # @return [Block] The given block.
212
+ # @yield [MatchData, self]
213
+ def register_match_handler &block
214
+ @ionian_match_handlers << block unless @ionian_match_handlers.include? block
215
+ @socket.register_match_handler &block if @socket
202
216
  block
203
217
  end
204
218
 
205
- alias_method :on_match, :register_observer
219
+ alias_method :on_match, :register_match_handler
220
+
221
+ # @deprecated Use {#register_match_handler} instead.
222
+ def register_observer &block
223
+ STDOUT.puts "WARN: Call to deprecated method #{__method__}"
224
+ register_match_handler &block
225
+ end
206
226
 
207
227
  # Unregister a block from being called when matched data is received.
228
+ def unregister_match_handler &block
229
+ @ionian_match_handlers.delete_if { |o| o == block }
230
+ @socket.unregister_match_handler &block if @socket
231
+ block
232
+ end
233
+
234
+ # @deprecated Use {#unregister_match_handler} instead.
208
235
  def unregister_observer &block
209
- @ionian_listeners.delete_if { |o| o == block }
210
- @socket.unregister_observer &block if @socket
236
+ STDOUT.puts "WARN: Call to deprecated method #{__method__}"
237
+ unregister_match_handler &block
238
+ end
239
+
240
+ # Register a block to be called when {Ionian::Extension::IO#run_match}
241
+ # raises an error.
242
+ # Method callbacks can be registered with &object.method(:method).
243
+ # @return [Block] a reference to the given block.
244
+ # @yield [Exception, self]
245
+ def register_error_handler &block
246
+ @ionian_error_handlers << block unless @ionian_error_handlers.include? block
247
+ @socket.register_error_handler &block if @socket
248
+ block
249
+ end
250
+
251
+ alias_method :on_error, :register_error_handler
252
+
253
+ # Unregister a block from being called when a {Ionian::IO#run_match} error
254
+ # is raised.
255
+ def unregister_error_handler &block
256
+ @ionian_error_handlers.delete_if { |o| o == block }
257
+ @socket.unregister_error_handler &block if @socket
211
258
  block
212
259
  end
213
260
 
214
261
  ### Methods Forwarded To @socket ###
215
262
 
216
- # Returns true if there is data in the receive buffer.
217
- # Args:
218
- # Timeout: Number of seconds to wait for data until
219
- # giving up. Set to nil for blocking.
263
+ # @return [Boolean] True if there is data in the receive buffer.
264
+ # @option kwargs [Fixnum, nil] :timeout (0) Number of seconds to wait for
265
+ # data until giving up. Set to nil for blocking.
220
266
  def has_data? **kwargs
221
267
  return false unless @socket
222
268
  @socket.has_data? kwargs
@@ -240,8 +286,8 @@ module Ionian
240
286
  self.write string.map{ |s| s.chomp }.join("\n") + "\n"
241
287
  end
242
288
 
243
- # Writes the given string to the socket. Returns the number of
244
- # bytes written.
289
+ # Writes the given string to the socket.
290
+ # @return [Fixnum] Number of bytes written.
245
291
  def write string
246
292
  create_socket unless @persistent
247
293
 
@@ -317,8 +363,9 @@ module Ionian
317
363
 
318
364
  @socket.expression = @expression if @expression
319
365
 
320
- # Register listeners.
321
- @ionian_listeners.each { |proc| @socket.on_match &proc }
366
+ # Register handlers.
367
+ @ionian_match_handlers.each { |proc| @socket.on_match &proc }
368
+ @ionian_error_handlers.each { |proc| @socket.on_error &proc }
322
369
 
323
370
  initialize_socket_methods
324
371
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ionian
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.12
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex McLain
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-26 00:00:00.000000000 Z
11
+ date: 2015-01-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -121,6 +121,7 @@ files:
121
121
  - doc/Ionian/Extension.html
122
122
  - doc/Ionian/Extension/IO.html
123
123
  - doc/Ionian/Extension/Socket.html
124
+ - doc/Ionian/ManagedSocket.html
124
125
  - doc/Ionian/Server.html
125
126
  - doc/Ionian/Socket.html
126
127
  - doc/_index.html
@@ -141,6 +142,7 @@ files:
141
142
  - lib/ionian.rb
142
143
  - lib/ionian/extension/io.rb
143
144
  - lib/ionian/extension/socket.rb
145
+ - lib/ionian/managed_socket.rb
144
146
  - lib/ionian/server.rb
145
147
  - lib/ionian/socket.rb
146
148
  - license.txt
@@ -164,7 +166,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
166
  version: '0'
165
167
  requirements: []
166
168
  rubyforge_project:
167
- rubygems_version: 2.4.5
169
+ rubygems_version: 2.4.4
168
170
  signing_key:
169
171
  specification_version: 4
170
172
  summary: Regular expression matching and notification for IO streams.