ionian 0.4.1 → 0.5.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/doc/Ionian/Extension/IO.html +1 -1
- data/doc/Ionian/Extension/Socket.html +1143 -20
- data/doc/Ionian/Socket.html +43 -14
- data/doc/created.rid +4 -4
- data/doc/js/search_index.js +1 -1
- data/doc/table_of_contents.html +155 -0
- data/lib/ionian/extension/io.rb +1 -1
- data/lib/ionian/extension/socket.rb +212 -8
- data/lib/ionian/socket.rb +43 -7
- metadata +2 -2
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'ionian/extension/io'
|
2
2
|
require 'socket'
|
3
|
+
require 'ipaddr'
|
3
4
|
|
4
5
|
module Ionian
|
5
6
|
module Extension
|
@@ -23,20 +24,223 @@ module Ionian
|
|
23
24
|
def initialize_ionian_socket
|
24
25
|
end
|
25
26
|
|
26
|
-
# Returns true if
|
27
|
-
#
|
27
|
+
# Returns true if local address reuse is allowed.
|
28
|
+
# ( SO_REUSEADDR )
|
29
|
+
def reuse_addr
|
30
|
+
param = self.getsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR)
|
31
|
+
.data.unpack('i').first
|
32
|
+
param > 0 ? true : false
|
33
|
+
end
|
34
|
+
|
35
|
+
alias_method :reuse_addr?, :reuse_addr
|
36
|
+
|
37
|
+
# Allows local address reuse if true.
|
38
|
+
# ( SO_REUSEADDR )
|
39
|
+
def reuse_addr=(value)
|
40
|
+
param = value ? 1 : 0
|
41
|
+
self.setsockopt ::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, [param].pack('i')
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns the time to live (hop limit).
|
45
|
+
# ( IP_TTL )
|
46
|
+
def ttl
|
47
|
+
self.getsockopt(::Socket::IPPROTO_IP, ::Socket::IP_TTL)
|
48
|
+
.data.unpack('i').first
|
49
|
+
end
|
50
|
+
|
51
|
+
alias_method :ttl?, :ttl
|
52
|
+
|
53
|
+
# Sets the time to live (hop limit).
|
54
|
+
# ( IP_TTL )
|
55
|
+
def ttl=(value)
|
56
|
+
self.setsockopt ::Socket::IPPROTO_IP, ::Socket::IP_TTL, [value].pack('i')
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns true if the Nagle algorithm is disabled.
|
60
|
+
# ( TCP_NODELAY )
|
28
61
|
def no_delay
|
29
|
-
|
30
|
-
|
62
|
+
param = self.getsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY)
|
63
|
+
.data.unpack('i').first
|
64
|
+
param > 0 ? true : false
|
31
65
|
end
|
32
66
|
|
33
|
-
|
34
|
-
|
67
|
+
alias_method :no_delay?, :no_delay
|
68
|
+
|
69
|
+
# Disables the Nagle algorithm if true.
|
70
|
+
# ( TCP_NODELAY )
|
35
71
|
def no_delay=(value)
|
36
|
-
|
37
|
-
self.setsockopt ::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY,
|
72
|
+
param = value ? 1 : 0
|
73
|
+
self.setsockopt ::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, [param].pack('i')
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns true if multiple writes are buffered into a single segment.
|
77
|
+
# See #recork.
|
78
|
+
# Linux only.
|
79
|
+
# ( TCP_CORK )
|
80
|
+
def cork
|
81
|
+
param = self.getsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_CORK)
|
82
|
+
.data.unpack('i').first
|
83
|
+
param > 0 ? true : false
|
84
|
+
end
|
85
|
+
|
86
|
+
alias_method :cork?, :cork
|
87
|
+
|
88
|
+
# Buffers multiple writes into a single segment if true.
|
89
|
+
# The segment is sent once the cork flag is disabled,
|
90
|
+
# the upper limit on the size of a segment is reached,
|
91
|
+
# the socket is closed, or 200ms elapses from the time
|
92
|
+
# the first corked byte is written.
|
93
|
+
# See #recork.
|
94
|
+
# Linux only.
|
95
|
+
# ( TCP_CORK )
|
96
|
+
def cork=(value)
|
97
|
+
param = value ? 1 : 0
|
98
|
+
self.setsockopt ::Socket::IPPROTO_TCP, ::Socket::TCP_CORK, [param].pack('i')
|
99
|
+
end
|
100
|
+
|
101
|
+
# Unsets cork to transmit data, then reapplies cork.
|
102
|
+
# ( TCP_CORK )
|
103
|
+
def recork
|
104
|
+
self.setsockopt ::Socket::IPPROTO_TCP, ::Socket::TCP_CORK, [0].pack('i')
|
105
|
+
self.setsockopt ::Socket::IPPROTO_TCP, ::Socket::TCP_CORK, [1].pack('i')
|
106
|
+
end
|
107
|
+
|
108
|
+
# Join a multicast group.
|
109
|
+
# Address is the class D multicast address (uses remote
|
110
|
+
# address if not specified).
|
111
|
+
# Interface is the local network interface to receive the
|
112
|
+
# multicast traffic on (all interfaces if not specified).
|
113
|
+
# ( IP_ADD_MEMBERSHIP )
|
114
|
+
def ip_add_membership(address = nil, interface = nil)
|
115
|
+
address ||= self.remote_address.ip_address
|
116
|
+
interface ||= '0.0.0.0'
|
117
|
+
|
118
|
+
self.setsockopt \
|
119
|
+
::Socket::IPPROTO_IP,
|
120
|
+
::Socket::IP_ADD_MEMBERSHIP,
|
121
|
+
IPAddr.new(address).hton + IPAddr.new(interface).hton
|
122
|
+
end
|
123
|
+
|
124
|
+
# Leave a multicast group.
|
125
|
+
# Address is the class D multicast address (uses remote
|
126
|
+
# address if not specified).
|
127
|
+
# Interface is the local network interface the multicast
|
128
|
+
# traffic is received on (all interfaces if not specified).
|
129
|
+
# ( IP_DROP_MEMBERSHIP )
|
130
|
+
def ip_drop_membership(address = nil, interface = nil)
|
131
|
+
address ||= self.remote_address.ip_address
|
132
|
+
interface ||= '0.0.0.0'
|
133
|
+
|
134
|
+
self.setsockopt \
|
135
|
+
::Socket::IPPROTO_IP,
|
136
|
+
::Socket::IP_DROP_MEMBERSHIP,
|
137
|
+
IPAddr.new(address).hton + IPAddr.new(interface).hton
|
138
|
+
end
|
139
|
+
|
140
|
+
# Returns the default interface for outgoing multicasts.
|
141
|
+
# ( IP_MULTICAST_IF )
|
142
|
+
def ip_multicast_if
|
143
|
+
self.getsockopt(::Socket::IPPROTO_IP, ::Socket::IP_MULTICAST_IF)
|
144
|
+
.data.unpack('CCCC').join('.')
|
145
|
+
end
|
146
|
+
|
147
|
+
# Specify default interface for outgoing multicasts.
|
148
|
+
# ( IP_MULTICAST_IF )
|
149
|
+
def ip_multicast_if=(interface = nil)
|
150
|
+
interface ||= '0.0.0.0'
|
151
|
+
|
152
|
+
self.setsockopt \
|
153
|
+
::Socket::IPPROTO_IP,
|
154
|
+
::Socket::IP_MULTICAST_IF,
|
155
|
+
IPAddr.new(interface).hton
|
156
|
+
end
|
157
|
+
|
158
|
+
# Returns the time to live (hop limit) for outgoing multicasts.
|
159
|
+
# ( IP_MULTICAST_TTL )
|
160
|
+
def ip_multicast_ttl
|
161
|
+
self.getsockopt(::Socket::IPPROTO_IP, ::Socket::IP_MULTICAST_TTL)
|
162
|
+
.data.unpack('C').first
|
163
|
+
end
|
164
|
+
|
165
|
+
# Set the time to live (hop limit) for outgoing multicasts.
|
166
|
+
# ( IP_MULTICAST_TTL )
|
167
|
+
def ip_multicast_ttl=(value)
|
168
|
+
self.setsockopt ::Socket::IPPROTO_IP, ::Socket::IP_MULTICAST_TTL, [value].pack('C')
|
169
|
+
end
|
170
|
+
|
171
|
+
# Returns true if loopback of outgoing multicasts is enabled.
|
172
|
+
# ( IP_MULTICAST_LOOP )
|
173
|
+
def ip_multicast_loop
|
174
|
+
param = self.getsockopt(::Socket::IPPROTO_IP, ::Socket::IP_MULTICAST_LOOP)
|
175
|
+
.data.unpack('C').first
|
176
|
+
param > 0 ? true : false
|
177
|
+
end
|
178
|
+
|
179
|
+
alias_method :ip_multicast_loop?, :ip_multicast_loop
|
180
|
+
|
181
|
+
# Enables loopback of outgoing multicasts if true.
|
182
|
+
# ( IP_MULTICAST_LOOP )
|
183
|
+
def ip_multicast_loop=(value)
|
184
|
+
param = value ? 1 : 0
|
185
|
+
self.setsockopt ::Socket::IPPROTO_IP, ::Socket::IP_MULTICAST_LOOP, [param].pack('C')
|
186
|
+
end
|
187
|
+
|
188
|
+
def ipv6_add_membership
|
189
|
+
# TODO: Implement
|
190
|
+
false
|
38
191
|
end
|
39
192
|
|
193
|
+
def ipv6_drop_membership
|
194
|
+
# TODO: Implement
|
195
|
+
false
|
196
|
+
end
|
197
|
+
|
198
|
+
def ipv6_multicast_if
|
199
|
+
# TODO: Implement
|
200
|
+
false
|
201
|
+
end
|
202
|
+
|
203
|
+
def ipv6_multicast_if=(value)
|
204
|
+
# TODO: Implement
|
205
|
+
end
|
206
|
+
|
207
|
+
def ipv6_multicast_hops
|
208
|
+
# TODO: Implement
|
209
|
+
false
|
210
|
+
end
|
211
|
+
|
212
|
+
def ipv6_multicast_hops=(value)
|
213
|
+
# TODO: Implement
|
214
|
+
end
|
215
|
+
|
216
|
+
def ipv6_multicast_loop
|
217
|
+
# TODO: Implement
|
218
|
+
false
|
219
|
+
end
|
220
|
+
|
221
|
+
alias_method :ipv6_multicast_loop?, :ipv6_multicast_loop
|
222
|
+
|
223
|
+
def ipv6_multicast_loop=(value)
|
224
|
+
# TODO: Implement
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
class << self
|
229
|
+
# Returns true if the given address is within the multicast range.
|
230
|
+
def multicast(address)
|
231
|
+
address >= '224.0.0.0' and address <= '239.255.255.255' ? true : false
|
232
|
+
end
|
233
|
+
|
234
|
+
alias_method :multicast?, :multicast
|
235
|
+
end
|
236
|
+
|
237
|
+
# Returns true if the socket's address is in the multicast range.
|
238
|
+
def multicast
|
239
|
+
Ionian::Extension::Socket.multicast self.remote_address.ip_address
|
240
|
+
end
|
241
|
+
|
242
|
+
alias_method :multicast?, :multicast
|
243
|
+
|
40
244
|
end
|
41
245
|
end
|
42
246
|
end
|
data/lib/ionian/socket.rb
CHANGED
@@ -6,22 +6,43 @@ module Ionian
|
|
6
6
|
class Socket
|
7
7
|
|
8
8
|
# Args:
|
9
|
-
# host:
|
10
|
-
# port:
|
11
|
-
# protocol:
|
9
|
+
# host: IP or hostname to connect to.
|
10
|
+
# port: Connection's port number. Default is 23. Unused by :unix protocol.
|
11
|
+
# protocol: Type of socket to create. :tcp, :udp, :unix. Default is :tcp.
|
12
|
+
# :udp will be automatically selected for addresses in the multicast range.
|
12
13
|
# persistent: The socket remains open after data is sent if this is true.
|
13
14
|
# The socket closes after data is sent and a packet is received
|
14
15
|
# if this is false. Default is true.
|
16
|
+
# bind_port: Local UDP port to bind to for receiving data, if different than
|
17
|
+
# the remote port being connected to.
|
18
|
+
# reuse_addr: Set true to enable the SO_REUSEADDR flag. Allows local address reuse.
|
19
|
+
# no_delay: Set true to enable the TCP_NODELAY flag. Disables Nagle algorithm.
|
20
|
+
# cork: Set true to enable the TCP_CORK flag. Buffers multiple writes
|
21
|
+
# into one segment.
|
15
22
|
# expression: Overrides the #read_match regular expression for received data.
|
16
23
|
def initialize(**kwargs)
|
17
24
|
@socket = nil
|
18
25
|
|
26
|
+
# TODO: Should be able to parse the port out of host.
|
27
|
+
# :port should override this parsed value.
|
28
|
+
|
19
29
|
@host = kwargs.fetch :host
|
20
|
-
@port = kwargs.fetch :port,
|
21
|
-
@
|
30
|
+
@port = kwargs.fetch :port, 23
|
31
|
+
@bind_port = kwargs.fetch :bind_port, @port
|
32
|
+
|
33
|
+
# Automatically select UDP for the multicast range. Otherwise default to TCP.
|
34
|
+
default_protocol = :tcp
|
35
|
+
default_protocol = :udp if Ionian::Extension::Socket.multicast? @host
|
36
|
+
default_protocol = :unix if @host.start_with? '/'
|
37
|
+
|
38
|
+
@protocol = kwargs.fetch :protocol, default_protocol
|
22
39
|
@persistent = kwargs.fetch :persistent, true
|
23
40
|
@expression = kwargs.fetch :expression, nil
|
24
41
|
|
42
|
+
@reuse_addr = kwargs.fetch :reuse_addr, false
|
43
|
+
@no_delay = kwargs.fetch :no_delay, false
|
44
|
+
@cork = kwargs.fetch :cork, false
|
45
|
+
|
25
46
|
create_socket if @persistent
|
26
47
|
end
|
27
48
|
|
@@ -123,15 +144,30 @@ module Ionian
|
|
123
144
|
case @protocol
|
124
145
|
when :tcp
|
125
146
|
@socket = ::TCPSocket.new @host, @port
|
147
|
+
@socket.extend Ionian::Extension::Socket
|
148
|
+
@socket.no_delay = true if @no_delay
|
149
|
+
@socket.cork = true if @cork
|
150
|
+
|
126
151
|
when :udp
|
127
152
|
@socket = ::UDPSocket.new
|
128
|
-
@socket.
|
153
|
+
@socket.extend Ionian::Extension::Socket
|
154
|
+
|
155
|
+
@socket.reuse_addr = true if
|
156
|
+
@reuse_addr or Ionian::Extension::Socket.multicast? @host
|
157
|
+
|
158
|
+
@socket.bind ::Socket::INADDR_ANY, @bind_port
|
129
159
|
@socket.connect @host, @port
|
160
|
+
|
161
|
+
@socket.ip_add_membership if Ionian::Extension::Socket.multicast? @host
|
162
|
+
|
130
163
|
when :unix
|
131
164
|
@socket = ::UNIXSocket.new @host
|
165
|
+
@socket.extend Ionian::Extension::Socket
|
132
166
|
end
|
133
167
|
|
134
|
-
|
168
|
+
# TODO: Implement SO_LINGER flag for non-persistent sockets;
|
169
|
+
# especially send-and-forget.
|
170
|
+
|
135
171
|
@socket.expression = @expression if @expression
|
136
172
|
|
137
173
|
initialize_socket_methods
|
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.5.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: 2013-12-
|
11
|
+
date: 2013-12-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|