ionian 0.6.12 → 0.7.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/README.md +13 -0
- data/doc/Ionian.html +3 -3
- data/doc/Ionian/Extension.html +1 -1
- data/doc/Ionian/Extension/IO.html +175 -56
- data/doc/Ionian/Extension/Socket.html +229 -122
- data/doc/Ionian/ManagedSocket.html +946 -0
- data/doc/Ionian/Server.html +1 -1
- data/doc/Ionian/Socket.html +720 -138
- data/doc/_index.html +16 -1
- data/doc/class_list.html +1 -1
- data/doc/file.README.html +14 -1
- data/doc/file.license.html +1 -1
- data/doc/index.html +14 -1
- data/doc/method_list.html +137 -47
- data/doc/top-level-namespace.html +1 -1
- data/lib/ionian.rb +1 -0
- data/lib/ionian/extension/io.rb +26 -8
- data/lib/ionian/extension/socket.rb +18 -18
- data/lib/ionian/managed_socket.rb +109 -0
- data/lib/ionian/socket.rb +65 -18
- metadata +5 -3
@@ -103,7 +103,7 @@
|
|
103
103
|
</div>
|
104
104
|
|
105
105
|
<div id="footer">
|
106
|
-
Generated on
|
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>
|
data/lib/ionian.rb
CHANGED
data/lib/ionian/extension/io.rb
CHANGED
@@ -39,7 +39,7 @@ module Ionian
|
|
39
39
|
::IO.select([self], nil, nil, timeout) ? true : false
|
40
40
|
end
|
41
41
|
|
42
|
-
#
|
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]
|
88
|
-
#
|
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
|
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 << $~
|
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
|
-
#
|
59
|
-
#
|
60
|
-
#
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/ionian/socket.rb
CHANGED
@@ -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
|
-
@
|
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
|
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
|
-
#
|
198
|
-
#
|
199
|
-
def
|
200
|
-
@
|
201
|
-
@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, :
|
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
|
-
|
210
|
-
|
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
|
-
#
|
217
|
-
#
|
218
|
-
#
|
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.
|
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
|
321
|
-
@
|
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.
|
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-
|
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.
|
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.
|