socketry 0.5.1 → 0.6.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 +5 -5
- data/context/configuration.md +154 -0
- data/lib/socketry/version.rb +5 -1
- data/lib/socketry.rb +3 -22
- data/license.md +21 -0
- data/readme.md +47 -0
- data/releases.md +6 -0
- data/skills/socketry-github-repository/SKILL.md +95 -0
- data/skills/socketry-pull-request/SKILL.md +54 -0
- metadata +20 -69
- data/.gitignore +0 -9
- data/.rspec +0 -4
- data/.rubocop.yml +0 -59
- data/.ruby-version +0 -1
- data/.travis.yml +0 -16
- data/CHANGES.md +0 -35
- data/Gemfile +0 -20
- data/Guardfile +0 -10
- data/LICENSE.txt +0 -22
- data/README.md +0 -110
- data/Rakefile +0 -10
- data/lib/socketry/exceptions.rb +0 -40
- data/lib/socketry/resolver/resolv.rb +0 -67
- data/lib/socketry/resolver/system.rb +0 -48
- data/lib/socketry/ssl/server.rb +0 -53
- data/lib/socketry/ssl/socket.rb +0 -190
- data/lib/socketry/tcp/server.rb +0 -85
- data/lib/socketry/tcp/socket.rb +0 -345
- data/lib/socketry/timeout.rb +0 -76
- data/lib/socketry/udp/datagram.rb +0 -29
- data/lib/socketry/udp/socket.rb +0 -185
- data/logo.png +0 -0
- data/socketry.gemspec +0 -29
data/lib/socketry/udp/socket.rb
DELETED
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Socketry
|
|
4
|
-
# User Datagram Protocol: "fire-and-forget" packet protocol
|
|
5
|
-
module UDP
|
|
6
|
-
# User Datagram Protocol sockets
|
|
7
|
-
class Socket
|
|
8
|
-
include Socketry::Timeout
|
|
9
|
-
|
|
10
|
-
attr_reader :addr_family, :read_timeout, :write_timeout, :resolver, :socket_class
|
|
11
|
-
|
|
12
|
-
# Create a UDP socket matching the given socket's address family
|
|
13
|
-
#
|
|
14
|
-
# @param remote_addr [String] Address to connect/bind to
|
|
15
|
-
# @param resolver [Object] Resolver object to use for resolving DNS names
|
|
16
|
-
#
|
|
17
|
-
# @return [Socketry::UDP::Socket]
|
|
18
|
-
def self.from_addr(remote_addr, resolver: Socketry::Resolver::DEFAULT_RESOLVER)
|
|
19
|
-
addr = resolver.resolve(remote_addr)
|
|
20
|
-
if addr.ipv4? then new(addr_family: :ipv4)
|
|
21
|
-
elsif addr.ipv6? then new(addr_family: :ipv6)
|
|
22
|
-
else raise Socketry::AddressError, "unsupported IP address family: #{addr}"
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# Create a UDP server bound to the given address and port
|
|
27
|
-
#
|
|
28
|
-
# @param local_addr [String] Local DNS name or IP address to listen on
|
|
29
|
-
# @param local_port [Fixnum] Local UDP port to listen on
|
|
30
|
-
# @param resolver [Object] Resolver object to use for resolving DNS names
|
|
31
|
-
#
|
|
32
|
-
# @return [Socketry::UDP::Socket]
|
|
33
|
-
def self.bind(local_addr, local_port, resolver: Socketry::Resolver::DEFAULT_RESOLVER)
|
|
34
|
-
from_addr(local_addr, resolver: resolver).bind(local_addr, local_port)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# Connect to the given address and port
|
|
38
|
-
#
|
|
39
|
-
# @param remote_addr [String] DNS name or IP address of the host to connect to
|
|
40
|
-
# @param remote_port [Fixnum] UDP port to connect to
|
|
41
|
-
# @param resolver [Object] Resolver object to use for resolving DNS names
|
|
42
|
-
#
|
|
43
|
-
# @return [Socketry::UDP::Socket]
|
|
44
|
-
def self.connect(remote_addr, remote_port, resolver: Socketry::Resolver::DEFAULT_RESOLVER)
|
|
45
|
-
from_addr(remote_addr, resolver: resolver).connect(remote_addr, remote_port)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
# Create a new UDP socket
|
|
49
|
-
#
|
|
50
|
-
# @param addr_family [:ipv4, :ipv6] (default :ipv4) address family for this socket
|
|
51
|
-
# @param read_timeout [Numeric] Seconds to wait before an uncompleted read errors
|
|
52
|
-
# @param write_timeout [Numeric] Seconds to wait before an uncompleted write errors
|
|
53
|
-
# @param timer [Object] Time interval object to use for measuring timeouts
|
|
54
|
-
# @param resolver [Object] Resolver object to use for resolving DNS names
|
|
55
|
-
# @param socket_class [Object] Underlying socket class which implements I/O ops
|
|
56
|
-
#
|
|
57
|
-
# @raise [ArgumentError] an invalid argument was given
|
|
58
|
-
#
|
|
59
|
-
# @return [Socketry::UDP::Socket]
|
|
60
|
-
def initialize(
|
|
61
|
-
addr_family: :ipv4,
|
|
62
|
-
read_timeout: Socketry::Timeout::DEFAULT_TIMEOUTS[:read],
|
|
63
|
-
write_timeout: Socketry::Timeout::DEFAULT_TIMEOUTS[:write],
|
|
64
|
-
timer: Socketry::Timeout::DEFAULT_TIMER.new,
|
|
65
|
-
resolver: Socketry::Resolver::DEFAULT_RESOLVER,
|
|
66
|
-
socket_class: ::UDPSocket
|
|
67
|
-
)
|
|
68
|
-
@addr_family = case addr_family
|
|
69
|
-
when :ipv4 then ::Socket::AF_INET
|
|
70
|
-
when :ipv6 then ::Socket::AF_INET6
|
|
71
|
-
when ::Socket::AF_INET, ::Socket::AF_INET6 then addr_family
|
|
72
|
-
else raise ArgumentError, "invalid address family: #{addr_family.inspect}"
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
@socket = socket_class.new(@addr_family)
|
|
76
|
-
@read_timeout = read_timeout
|
|
77
|
-
@write_timeout = write_timeout
|
|
78
|
-
@resolver = resolver
|
|
79
|
-
|
|
80
|
-
start_timer(timer)
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
# Start a UDP server bound to a particular address and port
|
|
84
|
-
#
|
|
85
|
-
# @param local_addr [String] Local DNS name or IP address to listen on
|
|
86
|
-
# @param local_port [Fixnum] Local UDP port to listen on
|
|
87
|
-
#
|
|
88
|
-
# @return [self]
|
|
89
|
-
def bind(local_addr, local_port)
|
|
90
|
-
@socket.bind(@resolver.resolve(local_addr).to_s, local_port)
|
|
91
|
-
self
|
|
92
|
-
rescue Errno::EADDRINUSE => ex
|
|
93
|
-
raise AddressInUseError, ex.message, ex.backtrace
|
|
94
|
-
rescue => ex
|
|
95
|
-
raise Socketry::Error, ex.message, ex.backtrace
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
# Make a UDP client connection to the given address and port
|
|
99
|
-
#
|
|
100
|
-
# @param remote_addr [String] DNS name or IP address of the host to connect to
|
|
101
|
-
# @param remote_port [Fixnum] UDP port to connect to
|
|
102
|
-
#
|
|
103
|
-
# @return [self]
|
|
104
|
-
def connect(remote_addr, remote_port)
|
|
105
|
-
@socket.connect(@resolver.resolve(remote_addr).to_s, remote_port)
|
|
106
|
-
self
|
|
107
|
-
rescue => ex
|
|
108
|
-
# TODO: more specific exceptions
|
|
109
|
-
raise Socketry::Error, ex.message, ex.backtrace
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
# Perform a non-blocking receive
|
|
113
|
-
#
|
|
114
|
-
# @param maxlen [Fixnum] Maximum packet length to receive
|
|
115
|
-
#
|
|
116
|
-
# @return [Socketry::UDP::Datagram, :wait_readable] Received datagram or indication to wait
|
|
117
|
-
def recvfrom_nonblock(maxlen)
|
|
118
|
-
Socketry::UDP::Datagram.new(*@socket.recvfrom_nonblock(maxlen))
|
|
119
|
-
rescue ::IO::WaitReadable
|
|
120
|
-
:wait_readable
|
|
121
|
-
rescue => ex
|
|
122
|
-
# TODO: more specific exceptions
|
|
123
|
-
raise Socketry::Error, ex.message, ex.backtrace
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
# Perform a blocking receive
|
|
127
|
-
#
|
|
128
|
-
# @param maxlen [Fixnum] Maximum packet length to receive
|
|
129
|
-
# @param timeout [Numeric] Number of seconds to wait for recvfrom operation to complete
|
|
130
|
-
#
|
|
131
|
-
# @return [String] Received data
|
|
132
|
-
def recvfrom(maxlen, timeout: @read_timeout)
|
|
133
|
-
set_timeout(timeout)
|
|
134
|
-
|
|
135
|
-
begin
|
|
136
|
-
while (result = recvfrom_nonblock(maxlen)) == :wait_readable
|
|
137
|
-
next if @socket.wait_readable(time_remaining(timeout))
|
|
138
|
-
raise Socketry::TimeoutError, "recvfrom timed out after #{timeout} seconds"
|
|
139
|
-
end
|
|
140
|
-
ensure
|
|
141
|
-
clear_timeout(timeout)
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
result
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
# Send a UDP packet to a remote host
|
|
148
|
-
#
|
|
149
|
-
# @param msg [String] Data to write to the remote host/port
|
|
150
|
-
# @param host [String] Remote host to send data to. May be omitted if `connect` was called previously
|
|
151
|
-
# @param port [Fixnum] UDP port to send data to. May be omitted if `connect` was called previously
|
|
152
|
-
#
|
|
153
|
-
# @return [Fixum] Number of bytes sent
|
|
154
|
-
def send(msg, host: nil, port: nil)
|
|
155
|
-
host = @resolver.resolve(host).to_s if host
|
|
156
|
-
if host || port
|
|
157
|
-
@socket.send(msg, 0, host, port)
|
|
158
|
-
else
|
|
159
|
-
@socket.send(msg, 0)
|
|
160
|
-
end
|
|
161
|
-
rescue => ex
|
|
162
|
-
# TODO: more specific exceptions
|
|
163
|
-
raise Socketry::Error, ex.message, ex.backtrace
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
# Close the socket
|
|
167
|
-
#
|
|
168
|
-
# @return [true, false] true if the socket was open, false if closed
|
|
169
|
-
def close
|
|
170
|
-
return false if closed?
|
|
171
|
-
@socket.close
|
|
172
|
-
true
|
|
173
|
-
ensure
|
|
174
|
-
@socket = nil
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
# Is the socket closed?
|
|
178
|
-
#
|
|
179
|
-
# @return [true, false] do we locally think the socket is closed?
|
|
180
|
-
def closed?
|
|
181
|
-
@socket.nil?
|
|
182
|
-
end
|
|
183
|
-
end
|
|
184
|
-
end
|
|
185
|
-
end
|
data/logo.png
DELETED
|
Binary file
|
data/socketry.gemspec
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
lib = File.expand_path("../lib", __FILE__)
|
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
-
require "socketry/version"
|
|
5
|
-
|
|
6
|
-
Gem::Specification.new do |spec|
|
|
7
|
-
spec.name = "socketry"
|
|
8
|
-
spec.version = Socketry::VERSION
|
|
9
|
-
spec.authors = ["Tony Arcieri"]
|
|
10
|
-
spec.email = ["bascule@gmail.com"]
|
|
11
|
-
spec.licenses = ["MIT"]
|
|
12
|
-
spec.homepage = "https://github.com/socketry/socketry/"
|
|
13
|
-
spec.summary = "High-level wrappers for Ruby sockets with advanced thread-safe timeout support"
|
|
14
|
-
spec.description = <<-DESCRIPTION.strip.gsub(/\s+/, " ")
|
|
15
|
-
Socketry wraps Ruby's sockets with an advanced timeout engine which is able to provide multiple
|
|
16
|
-
simultaneous timeout behaviors in a thread-safe way.
|
|
17
|
-
DESCRIPTION
|
|
18
|
-
|
|
19
|
-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
20
|
-
spec.bindir = "exe"
|
|
21
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
22
|
-
spec.require_paths = ["lib"]
|
|
23
|
-
|
|
24
|
-
spec.required_ruby_version = ">= 2.2.6"
|
|
25
|
-
|
|
26
|
-
spec.add_runtime_dependency "hitimes", "~> 1.2"
|
|
27
|
-
|
|
28
|
-
spec.add_development_dependency "bundler", "~> 1.0"
|
|
29
|
-
end
|