sparoid 2.1.2 → 2.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b9b409fe26f6c1e4e114ef772a721c55fe5c33c41ad1e45319cdf391074d084b
4
- data.tar.gz: 4eaf23fb8ed1afb254bfce4956d68618eb5c31581cd5e36174ef950eaec87320
3
+ metadata.gz: 71eaf9ec6bae245550f5134ddd360754aa3b360342551676bea056083a56ee8b
4
+ data.tar.gz: d97abd87405cd9c65bc96583648f6f2075867b08bab919e8871ed95de5e2e4f0
5
5
  SHA512:
6
- metadata.gz: 8cda0c092e0fcea01748df2a4b5d26f480f6162135aea3b9863e39c8a224f7ed7ca4e105b982f032605b49dd0a7fa467ea92a3776b16592c858f7b38bb1ce2b4
7
- data.tar.gz: ddb2ac64f0db2115b49712c6d7aebac1e29bed8dbf52354ee806282be72955f6a08a35794965f727221152de360796c82ceb4a79554f2c95283fce4ffc12cb9c
6
+ metadata.gz: 4a4426c422d8c973596758cdfeed9e23a256aa697605e9beaa9c1aa6b06f14d2fbcf5712a8fd44e25d830ed97f47912e0b707e5006d52139f686efdcf288cec9
7
+ data.tar.gz: b7df47069061130c91155b86fa8385f8ca2c77919baf1189c7513db3f2aca7fc1bff06f8b8e8911184ef8c2014bf8092e9b1933af6692a4137a5155c1923a7d1
@@ -11,7 +11,7 @@ jobs:
11
11
  strategy:
12
12
  fail-fast: false
13
13
  matrix:
14
- ruby: [ 3.2, 3.3, 3.4, 4.0, ruby-head ]
14
+ ruby: [ "3.2", "3.3", "3.4", "4.0", ruby-head ]
15
15
  runs-on: ubuntu-latest
16
16
  steps:
17
17
  - uses: actions/checkout@v6
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## [2.2.1] - 2026-06-30
2
+
3
+ - Make Sparoid::Instance public-IP resolution thread-safe and empty-aware; raise Sparoid::PublicIPError when no public IP resolves (#25)
4
+
5
+ ## [2.2.0] - 2026-05-06
6
+
7
+ - Raise when sendmsg fails for every resolved address (#23)
8
+
1
9
  ## [2.1.2] - 2026-04-30
2
10
 
3
11
  - Skip addresses that fail synchronous connect in fdpass (#20)
data/Gemfile CHANGED
@@ -11,3 +11,4 @@ gem "rake", "~> 13.0"
11
11
  gem "rubocop", "~> 1.7"
12
12
  gem "rubocop-minitest", require: false
13
13
  gem "rubocop-rake", require: false
14
+ gem "webmock"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sparoid
4
- VERSION = "2.1.2"
4
+ VERSION = "2.2.1"
5
5
  end
data/lib/sparoid.rb CHANGED
@@ -22,20 +22,27 @@ module Sparoid # rubocop:disable Metrics/ModuleLength
22
22
  # Send an authorization packet
23
23
  def auth(key, hmac_key, host, port, open_for_ip: nil)
24
24
  addrs = resolve_ip_addresses(host, port)
25
- addrs.each do |addr|
25
+ errors = []
26
+ successful_addrs = addrs.filter_map do |addr|
26
27
  messages = generate_messages(open_for_ip)
27
28
  data = messages.map do |message|
28
29
  prefix_hmac(hmac_key, encrypt(key, message))
29
30
  end
30
31
  sendmsg(addr, data)
32
+ addr
33
+ rescue SystemCallError => e
34
+ errors << "#{addr.ip_address}: #{e.message}"
35
+ nil
31
36
  end
32
37
 
38
+ raise Error, "Sparoid failed to send to any address for #{host}: #{errors.join("; ")}" if successful_addrs.empty?
39
+
33
40
  # wait some time for the server to actually open the port
34
41
  # if we don't wait the next SYN package will be dropped
35
42
  # and it have to be redelivered, adding 1 second delay
36
43
  sleep 0.02
37
44
 
38
- addrs
45
+ successful_addrs
39
46
  end
40
47
 
41
48
  # Generate new aes and hmac keys, print to stdout
@@ -96,6 +103,8 @@ module Sparoid # rubocop:disable Metrics/ModuleLength
96
103
  ips = ips.grep_v(Resolv::IPv6)
97
104
  ips << Resolv::IPv6.create(native_ipv6)
98
105
  end
106
+ raise PublicIPError, "Sparoid could not resolve a public IP to knock from" if ips.empty?
107
+
99
108
  ips.map { |i| message(i) }
100
109
  end
101
110
  end
@@ -105,11 +114,9 @@ module Sparoid # rubocop:disable Metrics/ModuleLength
105
114
  socket.nonblock = false
106
115
  data.each do |packet|
107
116
  socket.sendmsg packet, 0, addr
108
- rescue StandardError => e
109
- warn "Sparoid error: #{e.message}"
110
117
  end
111
118
  ensure
112
- socket.close
119
+ socket&.close
113
120
  end
114
121
 
115
122
  def encrypt(key, data)
@@ -248,16 +255,31 @@ module Sparoid # rubocop:disable Metrics/ModuleLength
248
255
 
249
256
  class ResolvError < Error; end
250
257
 
251
- # Instance of SPAroid that only resolved public_ips once
258
+ class PublicIPError < Error; end
259
+
260
+ # Instance of SPAroid that resolves its public IP once and reuses it
252
261
  class Instance
253
262
  include Sparoid
254
263
 
255
- def public_ips(*args)
256
- @public_ips ||= super
264
+ def initialize
265
+ @resolve_mutex = Mutex.new
266
+ @public_ips = []
257
267
  end
258
268
 
259
269
  def cached_public_ips
260
- public_ips
270
+ return @public_ips if @public_ips.any?
271
+
272
+ @resolve_mutex.synchronize do
273
+ return @public_ips if @public_ips.any?
274
+
275
+ ips = public_ips
276
+ if ips.empty?
277
+ warn "Sparoid: Failed to retrieve public IPs"
278
+ else
279
+ @public_ips = ips
280
+ end
281
+ ips
282
+ end
261
283
  end
262
284
  end
263
285
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sparoid
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.2
4
+ version: 2.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carl Hörberg